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