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 static uint8_t 348 ipmi_acquire_ipmb_address(struct ipmi_intf * intf) 349 { 350 if (intf->picmg_avail) { 351 return ipmi_picmg_ipmb_address(intf); 352 } else if (intf->vita_avail) { 353 return ipmi_vita_ipmb_address(intf); 354 } else { 355 return 0; 356 } 357 } 358 359 /* ipmi_parse_options - helper function to handle parsing command line options 360 * 361 * @argc: count of options 362 * @argv: list of options 363 * @cmdlist: list of supported commands 364 * @intflist: list of supported interfaces 365 * 366 * returns 0 on success 367 * returns -1 on error 368 */ 369 int 370 ipmi_main(int argc, char ** argv, 371 struct ipmi_cmd * cmdlist, 372 struct ipmi_intf_support * intflist) 373 { 374 struct ipmi_intf_support * sup; 375 int privlvl = 0; 376 uint8_t target_addr = 0; 377 uint8_t target_channel = 0; 378 379 uint8_t transit_addr = 0; 380 uint8_t transit_channel = 0; 381 uint8_t target_lun = 0; 382 uint8_t arg_addr = 0; 383 uint8_t addr = 0; 384 uint16_t my_long_packet_size=0; 385 uint8_t my_long_packet_set=0; 386 uint8_t lookupbit = 0x10; /* use name-only lookup by default */ 387 int retry = 0; 388 uint32_t timeout = 0; 389 int authtype = -1; 390 char * tmp_pass = NULL; 391 char * tmp_env = NULL; 392 char * hostname = NULL; 393 char * username = NULL; 394 char * password = NULL; 395 char * intfname = NULL; 396 char * progname = NULL; 397 char * oemtype = NULL; 398 char * sdrcache = NULL; 399 unsigned char * kgkey = NULL; 400 char * seloem = NULL; 401 int port = 0; 402 int devnum = 0; 403 int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */ 404 int argflag, i, found; 405 int rc = -1; 406 char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT; 407 char * devfile = NULL; 408 409 /* save program name */ 410 progname = strrchr(argv[0], '/'); 411 progname = ((progname == NULL) ? argv[0] : progname+1); 412 signal(SIGINT, ipmi_catch_sigint); 413 414 while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1) 415 { 416 switch (argflag) { 417 case 'I': 418 if (intfname) { 419 free(intfname); 420 intfname = NULL; 421 } 422 intfname = strdup(optarg); 423 if (intfname == NULL) { 424 lprintf(LOG_ERR, "%s: malloc failure", progname); 425 goto out_free; 426 } 427 if (intflist != NULL) { 428 found = 0; 429 for (sup=intflist; sup->name != NULL; sup++) { 430 if (strncmp(sup->name, intfname, strlen(intfname)) == 0 && 431 strncmp(sup->name, intfname, strlen(sup->name)) == 0 && 432 sup->supported == 1) 433 found = 1; 434 } 435 if (!found) { 436 lprintf(LOG_ERR, "Interface %s not supported", intfname); 437 goto out_free; 438 } 439 } 440 break; 441 case 'h': 442 ipmi_option_usage(progname, cmdlist, intflist); 443 rc = 0; 444 goto out_free; 445 break; 446 case 'V': 447 printf("%s version %s\n", progname, VERSION); 448 rc = 0; 449 goto out_free; 450 break; 451 case 'd': 452 if (str2int(optarg, &devnum) != 0) { 453 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-d'."); 454 rc = -1; 455 goto out_free; 456 } 457 /* Check if device number is -gt 0; I couldn't find limit for 458 * kernels > 2.6, thus right side is unlimited. 459 */ 460 if (devnum < 0) { 461 lprintf(LOG_ERR, "Device number %i is out of range.", devnum); 462 rc = -1; 463 goto out_free; 464 } 465 break; 466 case 'p': 467 if (str2int(optarg, &port) != 0) { 468 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-p'."); 469 rc = -1; 470 goto out_free; 471 } 472 /* Check if port is -gt 0 && port is -lt 65535 */ 473 if (port < 0 || port > 65535) { 474 lprintf(LOG_ERR, "Port number %i is out of range.", port); 475 rc = -1; 476 goto out_free; 477 } 478 break; 479 case 'C': 480 if (str2int(optarg, &cipher_suite_id) != 0) { 481 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'."); 482 rc = -1; 483 goto out_free; 484 } 485 /* add check Cipher is -gt 0 */ 486 if (cipher_suite_id < 0) { 487 lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id); 488 rc = -1; 489 goto out_free; 490 } 491 break; 492 case 'v': 493 verbose++; 494 break; 495 case 'c': 496 csv_output = 1; 497 break; 498 case 'H': 499 if (hostname) { 500 free(hostname); 501 hostname = NULL; 502 } 503 hostname = strdup(optarg); 504 if (hostname == NULL) { 505 lprintf(LOG_ERR, "%s: malloc failure", progname); 506 goto out_free; 507 } 508 break; 509 case 'f': 510 if (password) { 511 free(password); 512 password = NULL; 513 } 514 password = ipmi_password_file_read(optarg); 515 if (password == NULL) 516 lprintf(LOG_ERR, "Unable to read password " 517 "from file %s", optarg); 518 break; 519 case 'a': 520 #ifdef HAVE_GETPASSPHRASE 521 tmp_pass = getpassphrase("Password: "); 522 #else 523 tmp_pass = getpass("Password: "); 524 #endif 525 if (tmp_pass != NULL) { 526 if (password) { 527 free(password); 528 password = NULL; 529 } 530 password = strdup(tmp_pass); 531 tmp_pass = NULL; 532 if (password == NULL) { 533 lprintf(LOG_ERR, "%s: malloc failure", progname); 534 goto out_free; 535 } 536 } 537 break; 538 case 'k': 539 if (kgkey) { 540 free(kgkey); 541 kgkey = NULL; 542 } 543 kgkey = strdup(optarg); 544 if (kgkey == NULL) { 545 lprintf(LOG_ERR, "%s: malloc failure", progname); 546 goto out_free; 547 } 548 break; 549 case 'K': 550 if ((tmp_env = getenv("IPMI_KGKEY"))) { 551 if (kgkey) { 552 free(kgkey); 553 kgkey = NULL; 554 } 555 kgkey = strdup(tmp_env); 556 if (kgkey == NULL) { 557 lprintf(LOG_ERR, "%s: malloc failure", progname); 558 goto out_free; 559 } 560 } else { 561 lprintf(LOG_WARN, "Unable to read kgkey from environment"); 562 } 563 break; 564 case 'y': 565 if (kgkey) { 566 free(kgkey); 567 kgkey = NULL; 568 } 569 kgkey = ipmi_parse_hex(optarg); 570 if (kgkey == NULL) { 571 goto out_free; 572 } 573 break; 574 case 'Y': 575 #ifdef HAVE_GETPASSPHRASE 576 tmp_pass = getpassphrase("Key: "); 577 #else 578 tmp_pass = getpass("Key: "); 579 #endif 580 if (tmp_pass != NULL) { 581 if (kgkey) { 582 free(kgkey); 583 kgkey = NULL; 584 } 585 kgkey = strdup(tmp_pass); 586 tmp_pass = NULL; 587 if (kgkey == NULL) { 588 lprintf(LOG_ERR, "%s: malloc failure", progname); 589 goto out_free; 590 } 591 } 592 break; 593 case 'U': 594 if (username) { 595 free(username); 596 username = NULL; 597 } 598 if (strlen(optarg) > 16) { 599 lprintf(LOG_ERR, "Username is too long (> 16 bytes)"); 600 goto out_free; 601 } 602 username = strdup(optarg); 603 if (username == NULL) { 604 lprintf(LOG_ERR, "%s: malloc failure", progname); 605 goto out_free; 606 } 607 break; 608 case 'S': 609 if (sdrcache) { 610 free(sdrcache); 611 sdrcache = NULL; 612 } 613 sdrcache = strdup(optarg); 614 if (sdrcache == NULL) { 615 lprintf(LOG_ERR, "%s: malloc failure", progname); 616 goto out_free; 617 } 618 break; 619 case 'D': 620 /* check for subsequent instance of -D */ 621 if (devfile) { 622 /* free memory for previous string */ 623 free(devfile); 624 } 625 devfile = strdup(optarg); 626 if (devfile == NULL) { 627 lprintf(LOG_ERR, "%s: malloc failure", progname); 628 goto out_free; 629 } 630 break; 631 #ifdef ENABLE_ALL_OPTIONS 632 case 'o': 633 if (oemtype) { 634 free(oemtype); 635 oemtype = NULL; 636 } 637 oemtype = strdup(optarg); 638 if (oemtype == NULL) { 639 lprintf(LOG_ERR, "%s: malloc failure", progname); 640 goto out_free; 641 } 642 if (strncmp(oemtype, "list", 4) == 0 || 643 strncmp(oemtype, "help", 4) == 0) { 644 ipmi_oem_print(); 645 rc = 0; 646 goto out_free; 647 } 648 break; 649 case 'g': 650 /* backwards compatible oem hack */ 651 if (oemtype) { 652 free(oemtype); 653 oemtype = NULL; 654 } 655 oemtype = strdup("intelwv2"); 656 break; 657 case 's': 658 /* backwards compatible oem hack */ 659 if (oemtype) { 660 free(oemtype); 661 oemtype = NULL; 662 } 663 oemtype = strdup("supermicro"); 664 break; 665 case 'P': 666 if (password) { 667 free(password); 668 password = NULL; 669 } 670 password = strdup(optarg); 671 if (password == NULL) { 672 lprintf(LOG_ERR, "%s: malloc failure", progname); 673 goto out_free; 674 } 675 676 /* Prevent password snooping with ps */ 677 i = strlen(optarg); 678 memset(optarg, 'X', i); 679 break; 680 case 'E': 681 if ((tmp_env = getenv("IPMITOOL_PASSWORD"))) { 682 if (password) { 683 free(password); 684 password = NULL; 685 } 686 password = strdup(tmp_env); 687 if (password == NULL) { 688 lprintf(LOG_ERR, "%s: malloc failure", progname); 689 goto out_free; 690 } 691 } 692 else if ((tmp_env = getenv("IPMI_PASSWORD"))) { 693 if (password) { 694 free(password); 695 password = NULL; 696 } 697 password = strdup(tmp_env); 698 if (password == NULL) { 699 lprintf(LOG_ERR, "%s: malloc failure", progname); 700 goto out_free; 701 } 702 } 703 else { 704 lprintf(LOG_WARN, "Unable to read password from environment"); 705 } 706 break; 707 case 'L': 708 i = strlen(optarg); 709 if ((i > 0) && (optarg[i-1] == '+')) { 710 lookupbit = 0; 711 optarg[i-1] = 0; 712 } 713 privlvl = str2val(optarg, ipmi_privlvl_vals); 714 if (privlvl == 0xFF) { 715 lprintf(LOG_WARN, "Invalid privilege level %s", optarg); 716 } 717 break; 718 case 'A': 719 authtype = str2val(optarg, ipmi_authtype_session_vals); 720 break; 721 case 't': 722 if (str2uchar(optarg, &target_addr) != 0) { 723 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-t'."); 724 rc = -1; 725 goto out_free; 726 } 727 break; 728 case 'b': 729 if (str2uchar(optarg, &target_channel) != 0) { 730 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-b'."); 731 rc = -1; 732 goto out_free; 733 } 734 break; 735 case 'T': 736 if (str2uchar(optarg, &transit_addr) != 0) { 737 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-T'."); 738 rc = -1; 739 goto out_free; 740 } 741 break; 742 case 'B': 743 if (str2uchar(optarg, &transit_channel) != 0) { 744 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-B'."); 745 rc = -1; 746 goto out_free; 747 } 748 break; 749 case 'l': 750 if (str2uchar(optarg, &target_lun) != 0) { 751 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-l'."); 752 rc = 1; 753 goto out_free; 754 } 755 break; 756 case 'm': 757 if (str2uchar(optarg, &arg_addr) != 0) { 758 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'."); 759 rc = -1; 760 goto out_free; 761 } 762 break; 763 case 'e': 764 sol_escape_char = optarg[0]; 765 break; 766 case 'O': 767 if (seloem) { 768 free(seloem); 769 seloem = NULL; 770 } 771 seloem = strdup(optarg); 772 if (seloem == NULL) { 773 lprintf(LOG_ERR, "%s: malloc failure", progname); 774 goto out_free; 775 } 776 break; 777 case 'z': 778 if (str2ushort(optarg, &my_long_packet_size) != 0) { 779 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-z'."); 780 rc = -1; 781 goto out_free; 782 } 783 break; 784 /* Retry and Timeout */ 785 case 'R': 786 if (str2int(optarg, &retry) != 0 || retry < 0) { 787 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-R'."); 788 rc = -1; 789 goto out_free; 790 } 791 break; 792 case 'N': 793 if (str2uint(optarg, &timeout) != 0) { 794 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-N'."); 795 rc = -1; 796 goto out_free; 797 } 798 break; 799 #endif 800 default: 801 ipmi_option_usage(progname, cmdlist, intflist); 802 goto out_free; 803 } 804 } 805 806 /* check for command before doing anything */ 807 if (argc-optind > 0 && 808 strncmp(argv[optind], "help", 4) == 0) { 809 ipmi_cmd_print(cmdlist); 810 rc = 0; 811 goto out_free; 812 } 813 814 /* 815 * If the user has specified a hostname (-H option) 816 * then this is a remote access session. 817 * 818 * If no password was specified by any other method 819 * and the authtype was not explicitly set to NONE 820 * then prompt the user. 821 */ 822 if (hostname != NULL && password == NULL && 823 (authtype != IPMI_SESSION_AUTHTYPE_NONE || authtype < 0)) { 824 #ifdef HAVE_GETPASSPHRASE 825 tmp_pass = getpassphrase("Password: "); 826 #else 827 tmp_pass = getpass("Password: "); 828 #endif 829 if (tmp_pass != NULL) { 830 password = strdup(tmp_pass); 831 tmp_pass = NULL; 832 if (password == NULL) { 833 lprintf(LOG_ERR, "%s: malloc failure", progname); 834 goto out_free; 835 } 836 } 837 } 838 839 /* if no interface was specified but a 840 * hostname was then use LAN by default 841 * otherwise the default is hardcoded 842 * to use the first entry in the list 843 */ 844 if (intfname == NULL && hostname != NULL) { 845 intfname = strdup("lan"); 846 if (intfname == NULL) { 847 lprintf(LOG_ERR, "%s: malloc failure", progname); 848 goto out_free; 849 } 850 } 851 852 if (password != NULL && intfname != NULL) { 853 if (strcmp(intfname, "lan") == 0 && strlen(password) > 16) { 854 lprintf(LOG_ERR, "%s: password is longer than 16 bytes.", intfname); 855 rc = -1; 856 goto out_free; 857 } else if (strcmp(intfname, "lanplus") == 0 && strlen(password) > 20) { 858 lprintf(LOG_ERR, "%s: password is longer than 20 bytes.", intfname); 859 rc = -1; 860 goto out_free; 861 } 862 } /* if (password != NULL && intfname != NULL) */ 863 864 /* load interface */ 865 ipmi_main_intf = ipmi_intf_load(intfname); 866 if (ipmi_main_intf == NULL) { 867 lprintf(LOG_ERR, "Error loading interface %s", intfname); 868 goto out_free; 869 } 870 871 /* setup log */ 872 log_init(progname, 0, verbose); 873 874 /* run OEM setup if found */ 875 if (oemtype != NULL && 876 ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) { 877 lprintf(LOG_ERR, "OEM setup for \"%s\" failed", oemtype); 878 goto out_free; 879 } 880 881 /* set session variables */ 882 if (hostname != NULL) 883 ipmi_intf_session_set_hostname(ipmi_main_intf, hostname); 884 if (username != NULL) 885 ipmi_intf_session_set_username(ipmi_main_intf, username); 886 if (password != NULL) 887 ipmi_intf_session_set_password(ipmi_main_intf, password); 888 if (kgkey != NULL) 889 ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); 890 if (port > 0) 891 ipmi_intf_session_set_port(ipmi_main_intf, port); 892 if (authtype >= 0) 893 ipmi_intf_session_set_authtype(ipmi_main_intf, (uint8_t)authtype); 894 if (privlvl > 0) 895 ipmi_intf_session_set_privlvl(ipmi_main_intf, (uint8_t)privlvl); 896 else 897 ipmi_intf_session_set_privlvl(ipmi_main_intf, 898 IPMI_SESSION_PRIV_ADMIN); /* default */ 899 /* Adding retry and timeout for interface that support it */ 900 if (retry > 0) 901 ipmi_intf_session_set_retry(ipmi_main_intf, retry); 902 if (timeout > 0) 903 ipmi_intf_session_set_timeout(ipmi_main_intf, timeout); 904 905 ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit); 906 ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char); 907 ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id); 908 909 ipmi_main_intf->devnum = devnum; 910 911 /* setup device file if given */ 912 ipmi_main_intf->devfile = devfile; 913 914 /* Open the interface with the specified or default IPMB address */ 915 ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR; 916 if (ipmi_main_intf->open != NULL) { 917 if (ipmi_main_intf->open(ipmi_main_intf) < 0) { 918 goto out_free; 919 } 920 } 921 /* 922 * Attempt picmg/vita discovery of the actual interface address unless 923 * the users specified an address. 924 * Address specification always overrides discovery 925 */ 926 if (picmg_discover(ipmi_main_intf)) { 927 ipmi_main_intf->picmg_avail = 1; 928 } else if (vita_discover(ipmi_main_intf)) { 929 ipmi_main_intf->vita_avail = 1; 930 } 931 932 if (arg_addr) { 933 addr = arg_addr; 934 } else { 935 lprintf(LOG_DEBUG, "Acquire IPMB address"); 936 addr = ipmi_acquire_ipmb_address(ipmi_main_intf); 937 lprintf(LOG_INFO, "Discovered IPMB address 0x%x", addr); 938 } 939 940 /* 941 * If we discovered the ipmb address and it is not the same as what we 942 * used for open, Set the discovered IPMB address as my address if the 943 * interface supports it. 944 */ 945 if (addr != 0 && addr != ipmi_main_intf->my_addr && 946 ipmi_main_intf->set_my_addr) { 947 /* 948 * Only set the interface address on interfaces which support 949 * it 950 */ 951 (void) ipmi_main_intf->set_my_addr(ipmi_main_intf, addr); 952 } 953 954 /* If bridging addresses are specified, handle them */ 955 if (target_addr > 0) { 956 ipmi_main_intf->target_addr = target_addr; 957 ipmi_main_intf->target_lun = target_lun ; 958 ipmi_main_intf->target_channel = target_channel ; 959 } 960 if (transit_addr > 0) { 961 /* sanity check, transit makes no sense without a target */ 962 if ((transit_addr != 0 || transit_channel != 0) && 963 ipmi_main_intf->target_addr == 0) { 964 lprintf(LOG_ERR, 965 "Transit address/channel %#x/%#x ignored. " 966 "Target address must be specified!", 967 transit_addr, transit_channel); 968 goto out_free; 969 } 970 971 ipmi_main_intf->transit_addr = transit_addr; 972 ipmi_main_intf->transit_channel = transit_channel; 973 } 974 if (ipmi_main_intf->target_addr > 0) { 975 /* must be admin level to do this over lan */ 976 ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN); 977 /* Get the ipmb address of the targeted entity */ 978 ipmi_main_intf->target_ipmb_addr = 979 ipmi_acquire_ipmb_address(ipmi_main_intf); 980 lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x", 981 ipmi_main_intf->target_addr, 982 ipmi_main_intf->target_channel, 983 ipmi_main_intf->transit_addr, 984 ipmi_main_intf->transit_channel); 985 if (ipmi_main_intf->target_ipmb_addr) { 986 lprintf(LOG_INFO, "Discovered Target IPMB-0 address %#x", 987 ipmi_main_intf->target_ipmb_addr); 988 } 989 } 990 991 lprintf(LOG_DEBUG, "Interface address: my_addr %#x " 992 "transit %#x:%#x target %#x:%#x " 993 "ipmb_target %#x\n", 994 ipmi_main_intf->my_addr, 995 ipmi_main_intf->transit_addr, 996 ipmi_main_intf->transit_channel, 997 ipmi_main_intf->target_addr, 998 ipmi_main_intf->target_channel, 999 ipmi_main_intf->target_ipmb_addr); 1000 1001 /* parse local SDR cache if given */ 1002 if (sdrcache != NULL) { 1003 ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache); 1004 } 1005 /* Parse SEL OEM file if given */ 1006 if (seloem != NULL) { 1007 ipmi_sel_oem_init(seloem); 1008 } 1009 1010 /* Enable Big Buffer when requested */ 1011 if ( my_long_packet_size != 0 ) { 1012 /* Enable Big Buffer when requested */ 1013 if (!ipmi_oem_active(ipmi_main_intf, "kontron") || 1014 ipmi_kontronoem_set_large_buffer(ipmi_main_intf, 1015 my_long_packet_size ) == 0) { 1016 printf("Setting large buffer to %i\n", my_long_packet_size); 1017 my_long_packet_set = 1; 1018 ipmi_intf_set_max_request_data_size(ipmi_main_intf, 1019 my_long_packet_size); 1020 } 1021 } 1022 1023 ipmi_main_intf->cmdlist = cmdlist; 1024 1025 /* now we finally run the command */ 1026 if (argc-optind > 0) 1027 rc = ipmi_cmd_run(ipmi_main_intf, argv[optind], argc-optind-1, 1028 &(argv[optind+1])); 1029 else 1030 rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL); 1031 1032 if (my_long_packet_set == 1) { 1033 if (ipmi_oem_active(ipmi_main_intf, "kontron")) { 1034 /* Restore defaults */ 1035 ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 ); 1036 } 1037 } 1038 1039 /* clean repository caches */ 1040 ipmi_cleanup(ipmi_main_intf); 1041 1042 /* call interface close function if available */ 1043 if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close != NULL) 1044 ipmi_main_intf->close(ipmi_main_intf); 1045 1046 out_free: 1047 log_halt(); 1048 1049 if (intfname != NULL) { 1050 free(intfname); 1051 intfname = NULL; 1052 } 1053 if (hostname != NULL) { 1054 free(hostname); 1055 hostname = NULL; 1056 } 1057 if (username != NULL) { 1058 free(username); 1059 username = NULL; 1060 } 1061 if (password != NULL) { 1062 free(password); 1063 password = NULL; 1064 } 1065 if (oemtype != NULL) { 1066 free(oemtype); 1067 oemtype = NULL; 1068 } 1069 if (seloem != NULL) { 1070 free(seloem); 1071 seloem = NULL; 1072 } 1073 if (kgkey != NULL) { 1074 free(kgkey); 1075 kgkey = NULL; 1076 } 1077 if (sdrcache != NULL) { 1078 free(sdrcache); 1079 sdrcache = NULL; 1080 } 1081 if (devfile) { 1082 free(devfile); 1083 devfile = NULL; 1084 } 1085 1086 return rc; 1087 } 1088 1089 1090