1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * Redistribution of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Neither the name of Sun Microsystems, Inc. or the names of 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * This software is provided "AS IS," without a warranty of any kind. 20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 #define _XOPEN_SOURCE 700 33 34 #include <stdlib.h> 35 #include <stdio.h> 36 #include <inttypes.h> 37 #include <signal.h> 38 #include <string.h> 39 #include <strings.h> 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <unistd.h> 43 #include <fcntl.h> 44 #include <errno.h> 45 #include <ctype.h> 46 47 #include <ipmitool/helper.h> 48 #include <ipmitool/log.h> 49 #include <ipmitool/ipmi.h> 50 #include <ipmitool/ipmi_intf.h> 51 #include <ipmitool/ipmi_session.h> 52 #include <ipmitool/ipmi_sdr.h> 53 #include <ipmitool/ipmi_gendev.h> 54 #include <ipmitool/ipmi_sel.h> 55 #include <ipmitool/ipmi_fru.h> 56 #include <ipmitool/ipmi_sol.h> 57 #include <ipmitool/ipmi_isol.h> 58 #include <ipmitool/ipmi_lanp.h> 59 #include <ipmitool/ipmi_chassis.h> 60 #include <ipmitool/ipmi_mc.h> 61 #include <ipmitool/ipmi_firewall.h> 62 #include <ipmitool/ipmi_sensor.h> 63 #include <ipmitool/ipmi_channel.h> 64 #include <ipmitool/ipmi_session.h> 65 #include <ipmitool/ipmi_event.h> 66 #include <ipmitool/ipmi_user.h> 67 #include <ipmitool/ipmi_raw.h> 68 #include <ipmitool/ipmi_pef.h> 69 #include <ipmitool/ipmi_oem.h> 70 #include <ipmitool/ipmi_ekanalyzer.h> 71 #include <ipmitool/ipmi_picmg.h> 72 73 #ifdef HAVE_CONFIG_H 74 # include <config.h> 75 #endif 76 77 #ifdef ENABLE_ALL_OPTIONS 78 # define OPTION_STRING "I:hVvcgsEKYao:H:d:P:f:U:p:C:L:A:t:T:m:z:S:l:b:B:e:k:y:O:R:N:D:" 79 #else 80 # define OPTION_STRING "I:hVvcH:f:U:p:d:S:D:" 81 #endif 82 83 extern int verbose; 84 extern int csv_output; 85 extern const struct valstr ipmi_privlvl_vals[]; 86 extern const struct valstr ipmi_authtype_session_vals[]; 87 88 static struct ipmi_intf * ipmi_main_intf = NULL; 89 90 /* ipmi_password_file_read - Open file and read password from it 91 * 92 * @filename: file name to read from 93 * 94 * returns pointer to allocated buffer containing password 95 * (caller is expected to free when finished) 96 * returns NULL on error 97 */ 98 static char * 99 ipmi_password_file_read(char * filename) 100 { 101 FILE * fp; 102 char * pass = NULL; 103 int l; 104 105 pass = malloc(21); 106 if (pass == NULL) { 107 lprintf(LOG_ERR, "ipmitool: malloc failure"); 108 return NULL; 109 } 110 111 memset(pass, 0, 21); 112 fp = ipmi_open_file_read((const char *)filename); 113 if (fp == NULL) { 114 lprintf(LOG_ERR, "Unable to open password file %s", 115 filename); 116 free(pass); 117 return NULL; 118 } 119 120 /* read in id */ 121 if (fgets(pass, 21, fp) == NULL) { 122 lprintf(LOG_ERR, "Unable to read password from file %s", 123 filename); 124 free(pass); 125 fclose(fp); 126 return NULL; 127 } 128 129 /* remove traling <cr><nl><tab> */ 130 l = strcspn(pass, "\r\n\t"); 131 if (l > 0) { 132 pass[l] = '\0'; 133 } 134 135 fclose(fp); 136 return pass; 137 } 138 139 140 /* 141 * Print all the commands in the above table to stderr 142 * used for help text on command line and shell 143 */ 144 void 145 ipmi_cmd_print(struct ipmi_cmd * cmdlist) 146 { 147 struct ipmi_cmd * cmd; 148 int hdr = 0; 149 150 if (cmdlist == NULL) 151 return; 152 for (cmd=cmdlist; cmd->func != NULL; cmd++) { 153 if (cmd->desc == NULL) 154 continue; 155 if (hdr == 0) { 156 lprintf(LOG_NOTICE, "Commands:"); 157 hdr = 1; 158 } 159 lprintf(LOG_NOTICE, "\t%-12s %s", cmd->name, cmd->desc); 160 } 161 lprintf(LOG_NOTICE, ""); 162 } 163 164 /* ipmi_cmd_run - run a command from list based on parameters 165 * called from main() 166 * 167 * 1. iterate through ipmi_cmd_list matching on name 168 * 2. call func() for that command 169 * 170 * @intf: ipmi interface 171 * @name: command name 172 * @argc: command argument count 173 * @argv: command argument list 174 * 175 * returns value from func() of that commnad if found 176 * returns -1 if command is not found 177 */ 178 int 179 ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv) 180 { 181 struct ipmi_cmd * cmd = intf->cmdlist; 182 183 /* hook to run a default command if nothing specified */ 184 if (name == NULL) { 185 if (cmd->func == NULL || cmd->name == NULL) 186 return -1; 187 else if (strncmp(cmd->name, "default", 7) == 0) 188 return cmd->func(intf, 0, NULL); 189 else { 190 lprintf(LOG_ERR, "No command provided!"); 191 ipmi_cmd_print(intf->cmdlist); 192 return -1; 193 } 194 } 195 196 for (cmd=intf->cmdlist; cmd->func != NULL; cmd++) { 197 if (strncmp(name, cmd->name, __maxlen(cmd->name, name)) == 0) 198 break; 199 } 200 if (cmd->func == NULL) { 201 cmd = intf->cmdlist; 202 if (strncmp(cmd->name, "default", 7) == 0) 203 return cmd->func(intf, argc+1, argv-1); 204 205 lprintf(LOG_ERR, "Invalid command: %s", name); 206 ipmi_cmd_print(intf->cmdlist); 207 return -1; 208 } 209 return cmd->func(intf, argc, argv); 210 } 211 212 static void 213 ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_intf_support * intflist) 214 { 215 lprintf(LOG_NOTICE, "%s version %s\n", progname, VERSION); 216 lprintf(LOG_NOTICE, "usage: %s [options...] <command>\n", progname); 217 lprintf(LOG_NOTICE, " -h This help"); 218 lprintf(LOG_NOTICE, " -V Show version information"); 219 lprintf(LOG_NOTICE, " -v Verbose (can use multiple times)"); 220 lprintf(LOG_NOTICE, " -c Display output in comma separated format"); 221 lprintf(LOG_NOTICE, " -d N Specify a /dev/ipmiN device to use (default=0)"); 222 lprintf(LOG_NOTICE, " -I intf Interface to use"); 223 lprintf(LOG_NOTICE, " -H hostname Remote host name for LAN interface"); 224 lprintf(LOG_NOTICE, " -p port Remote RMCP port [default=623]"); 225 lprintf(LOG_NOTICE, " -U username Remote session username"); 226 lprintf(LOG_NOTICE, " -f file Read remote session password from file"); 227 lprintf(LOG_NOTICE, " -z size Change Size of Communication Channel (OEM)"); 228 lprintf(LOG_NOTICE, " -S sdr Use local file for remote SDR cache"); 229 lprintf(LOG_NOTICE, " -D tty:b[:s] Specify the serial device, baud rate to use"); 230 lprintf(LOG_NOTICE, " and, optionally, specify that interface is the system one"); 231 #ifdef ENABLE_ALL_OPTIONS 232 lprintf(LOG_NOTICE, " -a Prompt for remote password"); 233 lprintf(LOG_NOTICE, " -Y Prompt for the Kg key for IPMIv2 authentication"); 234 lprintf(LOG_NOTICE, " -e char Set SOL escape character"); 235 lprintf(LOG_NOTICE, " -C ciphersuite Cipher suite to be used by lanplus interface"); 236 lprintf(LOG_NOTICE, " -k key Use Kg key for IPMIv2 authentication"); 237 lprintf(LOG_NOTICE, " -y hex_key Use hexadecimal-encoded Kg key for IPMIv2 authentication"); 238 lprintf(LOG_NOTICE, " -L level Remote session privilege level [default=ADMINISTRATOR]"); 239 lprintf(LOG_NOTICE, " Append a '+' to use name/privilege lookup in RAKP1"); 240 lprintf(LOG_NOTICE, " -A authtype Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM"); 241 lprintf(LOG_NOTICE, " -P password Remote session password"); 242 lprintf(LOG_NOTICE, " -E Read password from IPMI_PASSWORD environment variable"); 243 lprintf(LOG_NOTICE, " -K Read kgkey from IPMI_KGKEY environment variable"); 244 lprintf(LOG_NOTICE, " -m address Set local IPMB address"); 245 lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request"); 246 lprintf(LOG_NOTICE, " -t address Bridge request to remote target address"); 247 lprintf(LOG_NOTICE, " -B channel Set transit channel for bridged request (dual bridge)"); 248 lprintf(LOG_NOTICE, " -T address Set transit address for bridge request (dual bridge)"); 249 lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands"); 250 lprintf(LOG_NOTICE, " -o oemtype Setup for OEM (use 'list' to see available OEM types)"); 251 lprintf(LOG_NOTICE, " -O seloem Use file for OEM SEL event descriptions"); 252 lprintf(LOG_NOTICE, " -N seconds Specify timeout for lan [default=2] / lanplus [default=1] interface"); 253 lprintf(LOG_NOTICE, " -R retry Set the number of retries for lan/lanplus interface [default=4]"); 254 #endif 255 lprintf(LOG_NOTICE, ""); 256 257 ipmi_intf_print(intflist); 258 259 if (cmdlist != NULL) 260 ipmi_cmd_print(cmdlist); 261 } 262 /* ipmi_catch_sigint - Handle the interrupt signal (Ctrl-C), close the 263 * interface, and exit ipmitool with error (-1) 264 * 265 * This insures that the IOL session gets freed 266 * for other callers. 267 * 268 * returns -1 269 */ 270 void ipmi_catch_sigint() 271 { 272 if (ipmi_main_intf != NULL) { 273 printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc); 274 /* reduce retry count to a single retry */ 275 if (ipmi_main_intf->session) { 276 ipmi_main_intf->session->retry = 1; 277 } 278 /* close interface */ 279 ipmi_main_intf->close(ipmi_main_intf); 280 } 281 exit(-1); 282 } 283 284 /* ipmi_parse_hex - convert hexadecimal numbers to ascii string 285 * Input string must be composed of two-characer hexadecimal numbers. 286 * There is no separator between the numbers. Each number results in one character 287 * of the converted string. 288 * 289 * Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD' 290 * 291 * @param str: input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters. 292 * @returns converted ascii string 293 * @returns NULL on error 294 */ 295 static unsigned char * 296 ipmi_parse_hex(const char *str) 297 { 298 const char * p; 299 unsigned char * out, *q; 300 unsigned char b = 0; 301 int shift = 4; 302 303 if (strlen(str) == 0) 304 return NULL; 305 306 if (strlen(str) % 2 != 0) { 307 lprintf(LOG_ERR, "Number of hex_kg characters is not even"); 308 return NULL; 309 } 310 311 if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) { 312 lprintf(LOG_ERR, "Kg key is too long"); 313 return NULL; 314 } 315 316 out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char)); 317 if (out == NULL) { 318 lprintf(LOG_ERR, "malloc failure"); 319 return NULL; 320 } 321 322 for (p = str, q = out; *p; p++) { 323 if (!isxdigit(*p)) { 324 lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); 325 free(out); 326 out = NULL; 327 return NULL; 328 } 329 330 if (*p < 'A') /* it must be 0-9 */ 331 b = *p - '0'; 332 else /* it's A-F or a-f */ 333 b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */ 334 335 *q = *q + b << shift; 336 if (shift) 337 shift = 0; 338 else { 339 shift = 4; 340 q++; 341 } 342 } 343 344 return out; 345 } 346 347 /* ipmi_parse_options - helper function to handle parsing command line options 348 * 349 * @argc: count of options 350 * @argv: list of options 351 * @cmdlist: list of supported commands 352 * @intflist: list of supported interfaces 353 * 354 * returns 0 on success 355 * returns -1 on error 356 */ 357 int 358 ipmi_main(int argc, char ** argv, 359 struct ipmi_cmd * cmdlist, 360 struct ipmi_intf_support * intflist) 361 { 362 struct ipmi_intf_support * sup; 363 int privlvl = 0; 364 uint8_t target_addr = 0; 365 uint8_t target_channel = 0; 366 367 uint8_t transit_addr = 0; 368 uint8_t transit_channel = 0; 369 uint8_t target_lun = 0; 370 uint8_t arg_addr = 0; 371 uint8_t addr = 0; 372 uint16_t my_long_packet_size=0; 373 uint8_t my_long_packet_set=0; 374 uint8_t lookupbit = 0x10; /* use name-only lookup by default */ 375 int retry = 0; 376 uint32_t timeout = 0; 377 int authtype = -1; 378 char * tmp_pass = NULL; 379 char * tmp_env = NULL; 380 char * hostname = NULL; 381 char * username = NULL; 382 char * password = NULL; 383 char * intfname = NULL; 384 char * progname = NULL; 385 char * oemtype = NULL; 386 char * sdrcache = NULL; 387 unsigned char * kgkey = NULL; 388 char * seloem = NULL; 389 int port = 0; 390 int devnum = 0; 391 int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */ 392 int argflag, i, found; 393 int rc = -1; 394 char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT; 395 char * devfile = NULL; 396 397 /* save program name */ 398 progname = strrchr(argv[0], '/'); 399 progname = ((progname == NULL) ? argv[0] : progname+1); 400 signal(SIGINT, ipmi_catch_sigint); 401 402 while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1) 403 { 404 switch (argflag) { 405 case 'I': 406 if (intfname) { 407 free(intfname); 408 intfname = NULL; 409 } 410 intfname = strdup(optarg); 411 if (intfname == NULL) { 412 lprintf(LOG_ERR, "%s: malloc failure", progname); 413 goto out_free; 414 } 415 if (intflist != NULL) { 416 found = 0; 417 for (sup=intflist; sup->name != NULL; sup++) { 418 if (strncmp(sup->name, intfname, strlen(intfname)) == 0 && 419 strncmp(sup->name, intfname, strlen(sup->name)) == 0 && 420 sup->supported == 1) 421 found = 1; 422 } 423 if (!found) { 424 lprintf(LOG_ERR, "Interface %s not supported", intfname); 425 goto out_free; 426 } 427 } 428 break; 429 case 'h': 430 ipmi_option_usage(progname, cmdlist, intflist); 431 rc = 0; 432 goto out_free; 433 break; 434 case 'V': 435 printf("%s version %s\n", progname, VERSION); 436 rc = 0; 437 goto out_free; 438 break; 439 case 'd': 440 if (str2int(optarg, &devnum) != 0) { 441 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-d'."); 442 rc = -1; 443 goto out_free; 444 } 445 /* Check if device number is -gt 0; I couldn't find limit for 446 * kernels > 2.6, thus right side is unlimited. 447 */ 448 if (devnum < 0) { 449 lprintf(LOG_ERR, "Device number %i is out of range.", devnum); 450 rc = -1; 451 goto out_free; 452 } 453 break; 454 case 'p': 455 if (str2int(optarg, &port) != 0) { 456 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-p'."); 457 rc = -1; 458 goto out_free; 459 } 460 /* Check if port is -gt 0 && port is -lt 65535 */ 461 if (port < 0 || port > 65535) { 462 lprintf(LOG_ERR, "Port number %i is out of range.", port); 463 rc = -1; 464 goto out_free; 465 } 466 break; 467 case 'C': 468 if (str2int(optarg, &cipher_suite_id) != 0) { 469 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'."); 470 rc = -1; 471 goto out_free; 472 } 473 /* add check Cipher is -gt 0 */ 474 if (cipher_suite_id < 0) { 475 lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id); 476 rc = -1; 477 goto out_free; 478 } 479 break; 480 case 'v': 481 verbose++; 482 break; 483 case 'c': 484 csv_output = 1; 485 break; 486 case 'H': 487 if (hostname) { 488 free(hostname); 489 hostname = NULL; 490 } 491 hostname = strdup(optarg); 492 if (hostname == NULL) { 493 lprintf(LOG_ERR, "%s: malloc failure", progname); 494 goto out_free; 495 } 496 break; 497 case 'f': 498 if (password) { 499 free(password); 500 password = NULL; 501 } 502 password = ipmi_password_file_read(optarg); 503 if (password == NULL) 504 lprintf(LOG_ERR, "Unable to read password " 505 "from file %s", optarg); 506 break; 507 case 'a': 508 #ifdef HAVE_GETPASSPHRASE 509 tmp_pass = getpassphrase("Password: "); 510 #else 511 tmp_pass = getpass("Password: "); 512 #endif 513 if (tmp_pass != NULL) { 514 if (password) { 515 free(password); 516 password = NULL; 517 } 518 password = strdup(tmp_pass); 519 tmp_pass = NULL; 520 if (password == NULL) { 521 lprintf(LOG_ERR, "%s: malloc failure", progname); 522 goto out_free; 523 } 524 } 525 break; 526 case 'k': 527 if (kgkey) { 528 free(kgkey); 529 kgkey = NULL; 530 } 531 kgkey = strdup(optarg); 532 if (kgkey == NULL) { 533 lprintf(LOG_ERR, "%s: malloc failure", progname); 534 goto out_free; 535 } 536 break; 537 case 'K': 538 if ((tmp_env = getenv("IPMI_KGKEY"))) { 539 if (kgkey) { 540 free(kgkey); 541 kgkey = NULL; 542 } 543 kgkey = strdup(tmp_env); 544 if (kgkey == NULL) { 545 lprintf(LOG_ERR, "%s: malloc failure", progname); 546 goto out_free; 547 } 548 } else { 549 lprintf(LOG_WARN, "Unable to read kgkey from environment"); 550 } 551 break; 552 case 'y': 553 if (kgkey) { 554 free(kgkey); 555 kgkey = NULL; 556 } 557 kgkey = ipmi_parse_hex(optarg); 558 if (kgkey == NULL) { 559 goto out_free; 560 } 561 break; 562 case 'Y': 563 #ifdef HAVE_GETPASSPHRASE 564 tmp_pass = getpassphrase("Key: "); 565 #else 566 tmp_pass = getpass("Key: "); 567 #endif 568 if (tmp_pass != NULL) { 569 if (kgkey) { 570 free(kgkey); 571 kgkey = NULL; 572 } 573 kgkey = strdup(tmp_pass); 574 tmp_pass = NULL; 575 if (kgkey == NULL) { 576 lprintf(LOG_ERR, "%s: malloc failure", progname); 577 goto out_free; 578 } 579 } 580 break; 581 case 'U': 582 if (username) { 583 free(username); 584 username = NULL; 585 } 586 if (strlen(optarg) > 16) { 587 lprintf(LOG_ERR, "Username is too long (> 16 bytes)"); 588 goto out_free; 589 } 590 username = strdup(optarg); 591 if (username == NULL) { 592 lprintf(LOG_ERR, "%s: malloc failure", progname); 593 goto out_free; 594 } 595 break; 596 case 'S': 597 if (sdrcache) { 598 free(sdrcache); 599 sdrcache = NULL; 600 } 601 sdrcache = strdup(optarg); 602 if (sdrcache == NULL) { 603 lprintf(LOG_ERR, "%s: malloc failure", progname); 604 goto out_free; 605 } 606 break; 607 case 'D': 608 /* check for subsequent instance of -D */ 609 if (devfile) { 610 /* free memory for previous string */ 611 free(devfile); 612 } 613 devfile = strdup(optarg); 614 if (devfile == NULL) { 615 lprintf(LOG_ERR, "%s: malloc failure", progname); 616 goto out_free; 617 } 618 break; 619 #ifdef ENABLE_ALL_OPTIONS 620 case 'o': 621 if (oemtype) { 622 free(oemtype); 623 oemtype = NULL; 624 } 625 oemtype = strdup(optarg); 626 if (oemtype == NULL) { 627 lprintf(LOG_ERR, "%s: malloc failure", progname); 628 goto out_free; 629 } 630 if (strncmp(oemtype, "list", 4) == 0 || 631 strncmp(oemtype, "help", 4) == 0) { 632 ipmi_oem_print(); 633 rc = 0; 634 goto out_free; 635 } 636 break; 637 case 'g': 638 /* backwards compatible oem hack */ 639 if (oemtype) { 640 free(oemtype); 641 oemtype = NULL; 642 } 643 oemtype = strdup("intelwv2"); 644 break; 645 case 's': 646 /* backwards compatible oem hack */ 647 if (oemtype) { 648 free(oemtype); 649 oemtype = NULL; 650 } 651 oemtype = strdup("supermicro"); 652 break; 653 case 'P': 654 if (password) { 655 free(password); 656 password = NULL; 657 } 658 password = strdup(optarg); 659 if (password == NULL) { 660 lprintf(LOG_ERR, "%s: malloc failure", progname); 661 goto out_free; 662 } 663 664 /* Prevent password snooping with ps */ 665 i = strlen(optarg); 666 memset(optarg, 'X', i); 667 break; 668 case 'E': 669 if ((tmp_env = getenv("IPMITOOL_PASSWORD"))) { 670 if (password) { 671 free(password); 672 password = NULL; 673 } 674 password = strdup(tmp_env); 675 if (password == NULL) { 676 lprintf(LOG_ERR, "%s: malloc failure", progname); 677 goto out_free; 678 } 679 } 680 else if ((tmp_env = getenv("IPMI_PASSWORD"))) { 681 if (password) { 682 free(password); 683 password = NULL; 684 } 685 password = strdup(tmp_env); 686 if (password == NULL) { 687 lprintf(LOG_ERR, "%s: malloc failure", progname); 688 goto out_free; 689 } 690 } 691 else { 692 lprintf(LOG_WARN, "Unable to read password from environment"); 693 } 694 break; 695 case 'L': 696 i = strlen(optarg); 697 if ((i > 0) && (optarg[i-1] == '+')) { 698 lookupbit = 0; 699 optarg[i-1] = 0; 700 } 701 privlvl = str2val(optarg, ipmi_privlvl_vals); 702 if (privlvl == 0xFF) { 703 lprintf(LOG_WARN, "Invalid privilege level %s", optarg); 704 } 705 break; 706 case 'A': 707 authtype = str2val(optarg, ipmi_authtype_session_vals); 708 break; 709 case 't': 710 if (str2uchar(optarg, &target_addr) != 0) { 711 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-t'."); 712 rc = -1; 713 goto out_free; 714 } 715 break; 716 case 'b': 717 if (str2uchar(optarg, &target_channel) != 0) { 718 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-b'."); 719 rc = -1; 720 goto out_free; 721 } 722 break; 723 case 'T': 724 if (str2uchar(optarg, &transit_addr) != 0) { 725 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-T'."); 726 rc = -1; 727 goto out_free; 728 } 729 break; 730 case 'B': 731 if (str2uchar(optarg, &transit_channel) != 0) { 732 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-B'."); 733 rc = -1; 734 goto out_free; 735 } 736 break; 737 case 'l': 738 if (str2uchar(optarg, &target_lun) != 0) { 739 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-l'."); 740 rc = 1; 741 goto out_free; 742 } 743 break; 744 case 'm': 745 if (str2uchar(optarg, &arg_addr) != 0) { 746 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'."); 747 rc = -1; 748 goto out_free; 749 } 750 break; 751 case 'e': 752 sol_escape_char = optarg[0]; 753 break; 754 case 'O': 755 if (seloem) { 756 free(seloem); 757 seloem = NULL; 758 } 759 seloem = strdup(optarg); 760 if (seloem == NULL) { 761 lprintf(LOG_ERR, "%s: malloc failure", progname); 762 goto out_free; 763 } 764 break; 765 case 'z': 766 if (str2ushort(optarg, &my_long_packet_size) != 0) { 767 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-z'."); 768 rc = -1; 769 goto out_free; 770 } 771 break; 772 /* Retry and Timeout */ 773 case 'R': 774 if (str2int(optarg, &retry) != 0 || retry < 0) { 775 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-R'."); 776 rc = -1; 777 goto out_free; 778 } 779 break; 780 case 'N': 781 if (str2uint(optarg, &timeout) != 0) { 782 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-N'."); 783 rc = -1; 784 goto out_free; 785 } 786 break; 787 #endif 788 default: 789 ipmi_option_usage(progname, cmdlist, intflist); 790 goto out_free; 791 } 792 } 793 794 /* check for command before doing anything */ 795 if (argc-optind > 0 && 796 strncmp(argv[optind], "help", 4) == 0) { 797 ipmi_cmd_print(cmdlist); 798 rc = 0; 799 goto out_free; 800 } 801 802 /* 803 * If the user has specified a hostname (-H option) 804 * then this is a remote access session. 805 * 806 * If no password was specified by any other method 807 * and the authtype was not explicitly set to NONE 808 * then prompt the user. 809 */ 810 if (hostname != NULL && password == NULL && 811 (authtype != IPMI_SESSION_AUTHTYPE_NONE || authtype < 0)) { 812 #ifdef HAVE_GETPASSPHRASE 813 tmp_pass = getpassphrase("Password: "); 814 #else 815 tmp_pass = getpass("Password: "); 816 #endif 817 if (tmp_pass != NULL) { 818 password = strdup(tmp_pass); 819 tmp_pass = NULL; 820 if (password == NULL) { 821 lprintf(LOG_ERR, "%s: malloc failure", progname); 822 goto out_free; 823 } 824 } 825 } 826 827 /* if no interface was specified but a 828 * hostname was then use LAN by default 829 * otherwise the default is hardcoded 830 * to use the first entry in the list 831 */ 832 if (intfname == NULL && hostname != NULL) { 833 intfname = strdup("lan"); 834 if (intfname == NULL) { 835 lprintf(LOG_ERR, "%s: malloc failure", progname); 836 goto out_free; 837 } 838 } 839 840 if (password != NULL && intfname != NULL) { 841 if (strcmp(intfname, "lan") == 0 && strlen(password) > 16) { 842 lprintf(LOG_ERR, "%s: password is longer than 16 bytes.", intfname); 843 rc = -1; 844 goto out_free; 845 } else if (strcmp(intfname, "lanplus") == 0 && strlen(password) > 20) { 846 lprintf(LOG_ERR, "%s: password is longer than 20 bytes.", intfname); 847 rc = -1; 848 goto out_free; 849 } 850 } /* if (password != NULL && intfname != NULL) */ 851 852 /* load interface */ 853 ipmi_main_intf = ipmi_intf_load(intfname); 854 if (ipmi_main_intf == NULL) { 855 lprintf(LOG_ERR, "Error loading interface %s", intfname); 856 goto out_free; 857 } 858 859 /* setup log */ 860 log_init(progname, 0, verbose); 861 862 /* run OEM setup if found */ 863 if (oemtype != NULL && 864 ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) { 865 lprintf(LOG_ERR, "OEM setup for \"%s\" failed", oemtype); 866 goto out_free; 867 } 868 869 /* set session variables */ 870 if (hostname != NULL) 871 ipmi_intf_session_set_hostname(ipmi_main_intf, hostname); 872 if (username != NULL) 873 ipmi_intf_session_set_username(ipmi_main_intf, username); 874 if (password != NULL) 875 ipmi_intf_session_set_password(ipmi_main_intf, password); 876 if (kgkey != NULL) 877 ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); 878 if (port > 0) 879 ipmi_intf_session_set_port(ipmi_main_intf, port); 880 if (authtype >= 0) 881 ipmi_intf_session_set_authtype(ipmi_main_intf, (uint8_t)authtype); 882 if (privlvl > 0) 883 ipmi_intf_session_set_privlvl(ipmi_main_intf, (uint8_t)privlvl); 884 else 885 ipmi_intf_session_set_privlvl(ipmi_main_intf, 886 IPMI_SESSION_PRIV_ADMIN); /* default */ 887 /* Adding retry and timeout for interface that support it */ 888 if (retry > 0) 889 ipmi_intf_session_set_retry(ipmi_main_intf, retry); 890 if (timeout > 0) 891 ipmi_intf_session_set_timeout(ipmi_main_intf, timeout); 892 893 ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit); 894 ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char); 895 ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id); 896 897 ipmi_main_intf->devnum = devnum; 898 899 /* setup device file if given */ 900 ipmi_main_intf->devfile = devfile; 901 902 /* Open the interface with the specified or default IPMB address */ 903 ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR; 904 if (ipmi_main_intf->open != NULL) { 905 if (ipmi_main_intf->open(ipmi_main_intf) < 0) { 906 goto out_free; 907 } 908 } 909 /* 910 * Attempt picmg discovery of the actual interface address unless 911 * the users specified an address. 912 * Address specification always overrides discovery 913 */ 914 if (picmg_discover(ipmi_main_intf) && !arg_addr) { 915 lprintf(LOG_DEBUG, "Running PICMG Get Address Info"); 916 addr = ipmi_picmg_ipmb_address(ipmi_main_intf); 917 lprintf(LOG_INFO, "Discovered IPMB-0 address 0x%x", addr); 918 } 919 920 /* 921 * If we discovered the ipmb address and it is not the same as what we 922 * used for open, Set the discovered IPMB address as my address if the 923 * interface supports it. 924 */ 925 if (addr != 0 && addr != ipmi_main_intf->my_addr && 926 ipmi_main_intf->set_my_addr) { 927 /* 928 * Only set the interface address on interfaces which support 929 * it 930 */ 931 (void) ipmi_main_intf->set_my_addr(ipmi_main_intf, addr); 932 } 933 934 /* If bridging addresses are specified, handle them */ 935 if (target_addr > 0) { 936 ipmi_main_intf->target_addr = target_addr; 937 ipmi_main_intf->target_lun = target_lun ; 938 ipmi_main_intf->target_channel = target_channel ; 939 } 940 if (transit_addr > 0) { 941 /* sanity check, transit makes no sense without a target */ 942 if ((transit_addr != 0 || transit_channel != 0) && 943 ipmi_main_intf->target_addr == 0) { 944 lprintf(LOG_ERR, 945 "Transit address/channel %#x/%#x ignored. " 946 "Target address must be specified!", 947 transit_addr, transit_channel); 948 goto out_free; 949 } 950 951 ipmi_main_intf->transit_addr = transit_addr; 952 ipmi_main_intf->transit_channel = transit_channel; 953 } 954 if (ipmi_main_intf->target_addr > 0) { 955 /* must be admin level to do this over lan */ 956 ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN); 957 /* Get the ipmb address of the targeted entity */ 958 ipmi_main_intf->target_ipmb_addr = 959 ipmi_picmg_ipmb_address(ipmi_main_intf); 960 lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x", 961 ipmi_main_intf->target_addr, 962 ipmi_main_intf->target_channel, 963 ipmi_main_intf->transit_addr, 964 ipmi_main_intf->transit_channel); 965 if (ipmi_main_intf->target_ipmb_addr) { 966 lprintf(LOG_INFO, "Discovered Target IPMB-0 address %#x", 967 ipmi_main_intf->target_ipmb_addr); 968 } 969 } 970 971 lprintf(LOG_DEBUG, "Interface address: my_addr %#x " 972 "transit %#x:%#x target %#x:%#x " 973 "ipmb_target %#x\n", 974 ipmi_main_intf->my_addr, 975 ipmi_main_intf->transit_addr, 976 ipmi_main_intf->transit_channel, 977 ipmi_main_intf->target_addr, 978 ipmi_main_intf->target_channel, 979 ipmi_main_intf->target_ipmb_addr); 980 981 /* parse local SDR cache if given */ 982 if (sdrcache != NULL) { 983 ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache); 984 } 985 /* Parse SEL OEM file if given */ 986 if (seloem != NULL) { 987 ipmi_sel_oem_init(seloem); 988 } 989 990 /* Enable Big Buffer when requested */ 991 if ( my_long_packet_size != 0 ) { 992 /* Enable Big Buffer when requested */ 993 if (!ipmi_oem_active(ipmi_main_intf, "kontron") || 994 ipmi_kontronoem_set_large_buffer(ipmi_main_intf, 995 my_long_packet_size ) == 0) { 996 printf("Setting large buffer to %i\n", my_long_packet_size); 997 my_long_packet_set = 1; 998 ipmi_intf_set_max_request_data_size(ipmi_main_intf, 999 my_long_packet_size); 1000 } 1001 } 1002 1003 ipmi_main_intf->cmdlist = cmdlist; 1004 1005 /* now we finally run the command */ 1006 if (argc-optind > 0) 1007 rc = ipmi_cmd_run(ipmi_main_intf, argv[optind], argc-optind-1, 1008 &(argv[optind+1])); 1009 else 1010 rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL); 1011 1012 if (my_long_packet_set == 1) { 1013 if (ipmi_oem_active(ipmi_main_intf, "kontron")) { 1014 /* Restore defaults */ 1015 ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 ); 1016 } 1017 } 1018 1019 /* clean repository caches */ 1020 ipmi_cleanup(ipmi_main_intf); 1021 1022 /* call interface close function if available */ 1023 if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close != NULL) 1024 ipmi_main_intf->close(ipmi_main_intf); 1025 1026 out_free: 1027 log_halt(); 1028 1029 if (intfname != NULL) { 1030 free(intfname); 1031 intfname = NULL; 1032 } 1033 if (hostname != NULL) { 1034 free(hostname); 1035 hostname = NULL; 1036 } 1037 if (username != NULL) { 1038 free(username); 1039 username = NULL; 1040 } 1041 if (password != NULL) { 1042 free(password); 1043 password = NULL; 1044 } 1045 if (oemtype != NULL) { 1046 free(oemtype); 1047 oemtype = NULL; 1048 } 1049 if (seloem != NULL) { 1050 free(seloem); 1051 seloem = NULL; 1052 } 1053 if (kgkey != NULL) { 1054 free(kgkey); 1055 kgkey = NULL; 1056 } 1057 if (sdrcache != NULL) { 1058 free(sdrcache); 1059 sdrcache = NULL; 1060 } 1061 if (devfile) { 1062 free(devfile); 1063 devfile = NULL; 1064 } 1065 1066 return rc; 1067 } 1068 1069 1070