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