/* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #define _XOPEN_SOURCE 700 #define _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || \ _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H # include #endif #ifdef ENABLE_ALL_OPTIONS # define OPTION_STRING "I:46hVvcgsEKYao:H:d:P:f:U:p:C:L:A:t:T:m:z:S:l:b:B:e:k:y:O:R:N:D:" #else # define OPTION_STRING "I:46hVvcH:f:U:p:d:S:D:" #endif /* From src/plugins/ipmi_intf.c: */ void ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size); extern int verbose; extern int csv_output; extern const struct valstr ipmi_privlvl_vals[]; extern const struct valstr ipmi_authtype_session_vals[]; static struct ipmi_intf * ipmi_main_intf = NULL; /* ipmi_password_file_read - Open file and read password from it * * @filename: file name to read from * * returns pointer to allocated buffer containing password * (caller is expected to free when finished) * returns NULL on error */ static char * ipmi_password_file_read(char * filename) { FILE * fp; char * pass = NULL; int l; pass = malloc(21); if (pass == NULL) { lprintf(LOG_ERR, "ipmitool: malloc failure"); return NULL; } memset(pass, 0, 21); fp = ipmi_open_file_read((const char *)filename); if (fp == NULL) { lprintf(LOG_ERR, "Unable to open password file %s", filename); free(pass); return NULL; } /* read in id */ if (fgets(pass, 21, fp) == NULL) { lprintf(LOG_ERR, "Unable to read password from file %s", filename); free(pass); fclose(fp); return NULL; } /* remove traling */ l = strcspn(pass, "\r\n\t"); if (l > 0) { pass[l] = '\0'; } fclose(fp); return pass; } /* * Print all the commands in the above table to stderr * used for help text on command line and shell */ void ipmi_cmd_print(struct ipmi_cmd * cmdlist) { struct ipmi_cmd * cmd; int hdr = 0; if (cmdlist == NULL) return; for (cmd=cmdlist; cmd->func != NULL; cmd++) { if (cmd->desc == NULL) continue; if (hdr == 0) { lprintf(LOG_NOTICE, "Commands:"); hdr = 1; } lprintf(LOG_NOTICE, "\t%-12s %s", cmd->name, cmd->desc); } lprintf(LOG_NOTICE, ""); } /* ipmi_cmd_run - run a command from list based on parameters * called from main() * * 1. iterate through ipmi_cmd_list matching on name * 2. call func() for that command * * @intf: ipmi interface * @name: command name * @argc: command argument count * @argv: command argument list * * returns value from func() of that commnad if found * returns -1 if command is not found */ int ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv) { struct ipmi_cmd * cmd = intf->cmdlist; /* hook to run a default command if nothing specified */ if (name == NULL) { if (cmd->func == NULL || cmd->name == NULL) return -1; else if (strncmp(cmd->name, "default", 7) == 0) return cmd->func(intf, 0, NULL); else { lprintf(LOG_ERR, "No command provided!"); ipmi_cmd_print(intf->cmdlist); return -1; } } for (cmd=intf->cmdlist; cmd->func != NULL; cmd++) { if (strncmp(name, cmd->name, __maxlen(cmd->name, name)) == 0) break; } if (cmd->func == NULL) { cmd = intf->cmdlist; if (strncmp(cmd->name, "default", 7) == 0) return cmd->func(intf, argc+1, argv-1); lprintf(LOG_ERR, "Invalid command: %s", name); ipmi_cmd_print(intf->cmdlist); return -1; } return cmd->func(intf, argc, argv); } static void ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_intf_support * intflist) { lprintf(LOG_NOTICE, "%s version %s\n", progname, VERSION); lprintf(LOG_NOTICE, "usage: %s [options...] \n", progname); lprintf(LOG_NOTICE, " -h This help"); lprintf(LOG_NOTICE, " -V Show version information"); lprintf(LOG_NOTICE, " -v Verbose (can use multiple times)"); lprintf(LOG_NOTICE, " -c Display output in comma separated format"); lprintf(LOG_NOTICE, " -d N Specify a /dev/ipmiN device to use (default=0)"); lprintf(LOG_NOTICE, " -I intf Interface to use"); lprintf(LOG_NOTICE, " -H hostname Remote host name for LAN interface"); lprintf(LOG_NOTICE, " -p port Remote RMCP port [default=623]"); lprintf(LOG_NOTICE, " -U username Remote session username"); lprintf(LOG_NOTICE, " -f file Read remote session password from file"); lprintf(LOG_NOTICE, " -z size Change Size of Communication Channel (OEM)"); lprintf(LOG_NOTICE, " -S sdr Use local file for remote SDR cache"); lprintf(LOG_NOTICE, " -D tty:b[:s] Specify the serial device, baud rate to use"); lprintf(LOG_NOTICE, " and, optionally, specify that interface is the system one"); lprintf(LOG_NOTICE, " -4 Use only IPv4"); lprintf(LOG_NOTICE, " -6 Use only IPv6"); #ifdef ENABLE_ALL_OPTIONS lprintf(LOG_NOTICE, " -a Prompt for remote password"); lprintf(LOG_NOTICE, " -Y Prompt for the Kg key for IPMIv2 authentication"); lprintf(LOG_NOTICE, " -e char Set SOL escape character"); lprintf(LOG_NOTICE, " -C ciphersuite Cipher suite to be used by lanplus interface"); lprintf(LOG_NOTICE, " -k key Use Kg key for IPMIv2 authentication"); lprintf(LOG_NOTICE, " -y hex_key Use hexadecimal-encoded Kg key for IPMIv2 authentication"); lprintf(LOG_NOTICE, " -L level Remote session privilege level [default=ADMINISTRATOR]"); lprintf(LOG_NOTICE, " Append a '+' to use name/privilege lookup in RAKP1"); lprintf(LOG_NOTICE, " -A authtype Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM"); lprintf(LOG_NOTICE, " -P password Remote session password"); lprintf(LOG_NOTICE, " -E Read password from IPMI_PASSWORD environment variable"); lprintf(LOG_NOTICE, " -K Read kgkey from IPMI_KGKEY environment variable"); lprintf(LOG_NOTICE, " -m address Set local IPMB address"); lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request"); lprintf(LOG_NOTICE, " -t address Bridge request to remote target address"); lprintf(LOG_NOTICE, " -B channel Set transit channel for bridged request (dual bridge)"); lprintf(LOG_NOTICE, " -T address Set transit address for bridge request (dual bridge)"); lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands"); lprintf(LOG_NOTICE, " -o oemtype Setup for OEM (use 'list' to see available OEM types)"); lprintf(LOG_NOTICE, " -O seloem Use file for OEM SEL event descriptions"); lprintf(LOG_NOTICE, " -N seconds Specify timeout for lan [default=2] / lanplus [default=1] interface"); lprintf(LOG_NOTICE, " -R retry Set the number of retries for lan/lanplus interface [default=4]"); #endif lprintf(LOG_NOTICE, ""); ipmi_intf_print(intflist); if (cmdlist != NULL) ipmi_cmd_print(cmdlist); } /* ipmi_catch_sigint - Handle the interrupt signal (Ctrl-C), close the * interface, and exit ipmitool with error (-1) * * This insures that the IOL session gets freed * for other callers. * * returns -1 */ void ipmi_catch_sigint() { if (ipmi_main_intf != NULL) { printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc); /* reduce retry count to a single retry */ ipmi_main_intf->ssn_params.retry = 1; /* close interface */ ipmi_main_intf->close(ipmi_main_intf); } exit(-1); } /* ipmi_parse_hex - convert hexadecimal numbers to ascii string * Input string must be composed of two-characer hexadecimal numbers. * There is no separator between the numbers. Each number results in one character * of the converted string. * * Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD' * * @param str: input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters. * @returns converted ascii string * @returns NULL on error */ static unsigned char * ipmi_parse_hex(const char *str) { const char * p; unsigned char * out, *q; unsigned char b = 0; int shift = 4; if (strlen(str) == 0) return NULL; if (strlen(str) % 2 != 0) { lprintf(LOG_ERR, "Number of hex_kg characters is not even"); return NULL; } if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) { lprintf(LOG_ERR, "Kg key is too long"); return NULL; } out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char)); if (out == NULL) { lprintf(LOG_ERR, "malloc failure"); return NULL; } for (p = str, q = out; *p; p++) { if (!isxdigit(*p)) { lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); free(out); out = NULL; return NULL; } if (*p < 'A') /* it must be 0-9 */ b = *p - '0'; else /* it's A-F or a-f */ b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */ *q = *q + (b << shift); if (shift) shift = 0; else { shift = 4; q++; } } return out; } static uint8_t ipmi_acquire_ipmb_address(struct ipmi_intf * intf) { if (intf->picmg_avail) { return ipmi_picmg_ipmb_address(intf); } else if (intf->vita_avail) { return ipmi_vita_ipmb_address(intf); } else { return 0; } } /* ipmi_parse_options - helper function to handle parsing command line options * * @argc: count of options * @argv: list of options * @cmdlist: list of supported commands * @intflist: list of supported interfaces * * returns 0 on success * returns -1 on error */ int ipmi_main(int argc, char ** argv, struct ipmi_cmd * cmdlist, struct ipmi_intf_support * intflist) { struct ipmi_intf_support * sup; int privlvl = 0; uint8_t target_addr = 0; uint8_t target_channel = 0; uint8_t transit_addr = 0; uint8_t transit_channel = 0; uint8_t target_lun = 0; uint8_t arg_addr = 0; uint8_t addr = 0; uint16_t my_long_packet_size=0; uint8_t my_long_packet_set=0; uint8_t lookupbit = 0x10; /* use name-only lookup by default */ int retry = 0; uint32_t timeout = 0; int authtype = -1; char * tmp_pass = NULL; char * tmp_env = NULL; char * hostname = NULL; char * username = NULL; char * password = NULL; char * intfname = NULL; char * progname = NULL; char * oemtype = NULL; char * sdrcache = NULL; unsigned char * kgkey = NULL; char * seloem = NULL; int port = 0; int devnum = 0; int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */ int argflag, i, found; int rc = -1; int ai_family = AF_UNSPEC; char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT; char * devfile = NULL; /* save program name */ progname = strrchr(argv[0], '/'); progname = ((progname == NULL) ? argv[0] : progname+1); signal(SIGINT, ipmi_catch_sigint); while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1) { switch (argflag) { case 'I': if (intfname) { free(intfname); intfname = NULL; } intfname = strdup(optarg); if (intfname == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } if (intflist != NULL) { found = 0; for (sup=intflist; sup->name != NULL; sup++) { if (strncmp(sup->name, intfname, strlen(intfname)) == 0 && strncmp(sup->name, intfname, strlen(sup->name)) == 0 && sup->supported == 1) found = 1; } if (!found) { lprintf(LOG_ERR, "Interface %s not supported", intfname); goto out_free; } } break; case 'h': ipmi_option_usage(progname, cmdlist, intflist); rc = 0; goto out_free; break; case 'V': printf("%s version %s\n", progname, VERSION); rc = 0; goto out_free; break; case 'd': if (str2int(optarg, &devnum) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-d'."); rc = -1; goto out_free; } /* Check if device number is -gt 0; I couldn't find limit for * kernels > 2.6, thus right side is unlimited. */ if (devnum < 0) { lprintf(LOG_ERR, "Device number %i is out of range.", devnum); rc = -1; goto out_free; } break; case 'p': if (str2int(optarg, &port) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-p'."); rc = -1; goto out_free; } /* Check if port is -gt 0 && port is -lt 65535 */ if (port < 0 || port > 65535) { lprintf(LOG_ERR, "Port number %i is out of range.", port); rc = -1; goto out_free; } break; case 'C': if (str2int(optarg, &cipher_suite_id) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'."); rc = -1; goto out_free; } /* add check Cipher is -gt 0 */ if (cipher_suite_id < 0) { lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id); rc = -1; goto out_free; } break; case 'v': verbose++; break; case 'c': csv_output = 1; break; case 'H': if (hostname) { free(hostname); hostname = NULL; } hostname = strdup(optarg); if (hostname == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } break; case 'f': if (password) { free(password); password = NULL; } password = ipmi_password_file_read(optarg); if (password == NULL) lprintf(LOG_ERR, "Unable to read password " "from file %s", optarg); break; case 'a': #ifdef HAVE_GETPASSPHRASE tmp_pass = getpassphrase("Password: "); #else tmp_pass = getpass("Password: "); #endif if (tmp_pass != NULL) { if (password) { free(password); password = NULL; } password = strdup(tmp_pass); tmp_pass = NULL; if (password == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } } break; case 'k': if (kgkey) { free(kgkey); kgkey = NULL; } kgkey = strdup(optarg); if (kgkey == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } break; case 'K': if ((tmp_env = getenv("IPMI_KGKEY"))) { if (kgkey) { free(kgkey); kgkey = NULL; } kgkey = strdup(tmp_env); if (kgkey == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } } else { lprintf(LOG_WARN, "Unable to read kgkey from environment"); } break; case 'y': if (kgkey) { free(kgkey); kgkey = NULL; } kgkey = ipmi_parse_hex(optarg); if (kgkey == NULL) { goto out_free; } break; case 'Y': #ifdef HAVE_GETPASSPHRASE tmp_pass = getpassphrase("Key: "); #else tmp_pass = getpass("Key: "); #endif if (tmp_pass != NULL) { if (kgkey) { free(kgkey); kgkey = NULL; } kgkey = strdup(tmp_pass); tmp_pass = NULL; if (kgkey == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } } break; case 'U': if (username) { free(username); username = NULL; } if (strlen(optarg) > 16) { lprintf(LOG_ERR, "Username is too long (> 16 bytes)"); goto out_free; } username = strdup(optarg); if (username == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } break; case 'S': if (sdrcache) { free(sdrcache); sdrcache = NULL; } sdrcache = strdup(optarg); if (sdrcache == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } break; case 'D': /* check for subsequent instance of -D */ if (devfile) { /* free memory for previous string */ free(devfile); } devfile = strdup(optarg); if (devfile == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } break; case '4': /* IPv4 only */ if (ai_family == AF_UNSPEC) { ai_family = AF_INET; } else { if (ai_family == AF_INET6) { lprintf(LOG_ERR, "Parameter is mutually exclusive with -6."); } else { lprintf(LOG_ERR, "Multiple -4 parameters given."); } rc = (-1); goto out_free; } break; case '6': /* IPv6 only */ if (ai_family == AF_UNSPEC) { ai_family = AF_INET6; } else { if (ai_family == AF_INET) { lprintf(LOG_ERR, "Parameter is mutually exclusive with -4."); } else { lprintf(LOG_ERR, "Multiple -6 parameters given."); } rc = (-1); goto out_free; } break; #ifdef ENABLE_ALL_OPTIONS case 'o': if (oemtype) { free(oemtype); oemtype = NULL; } oemtype = strdup(optarg); if (oemtype == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } if (strncmp(oemtype, "list", 4) == 0 || strncmp(oemtype, "help", 4) == 0) { ipmi_oem_print(); rc = 0; goto out_free; } break; case 'g': /* backwards compatible oem hack */ if (oemtype) { free(oemtype); oemtype = NULL; } oemtype = strdup("intelwv2"); break; case 's': /* backwards compatible oem hack */ if (oemtype) { free(oemtype); oemtype = NULL; } oemtype = strdup("supermicro"); break; case 'P': if (password) { free(password); password = NULL; } password = strdup(optarg); if (password == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } /* Prevent password snooping with ps */ i = strlen(optarg); memset(optarg, 'X', i); break; case 'E': if ((tmp_env = getenv("IPMITOOL_PASSWORD"))) { if (password) { free(password); password = NULL; } password = strdup(tmp_env); if (password == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } } else if ((tmp_env = getenv("IPMI_PASSWORD"))) { if (password) { free(password); password = NULL; } password = strdup(tmp_env); if (password == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } } else { lprintf(LOG_WARN, "Unable to read password from environment"); } break; case 'L': i = strlen(optarg); if ((i > 0) && (optarg[i-1] == '+')) { lookupbit = 0; optarg[i-1] = 0; } privlvl = str2val(optarg, ipmi_privlvl_vals); if (privlvl == 0xFF) { lprintf(LOG_WARN, "Invalid privilege level %s", optarg); } break; case 'A': authtype = str2val(optarg, ipmi_authtype_session_vals); break; case 't': if (str2uchar(optarg, &target_addr) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-t'."); rc = -1; goto out_free; } break; case 'b': if (str2uchar(optarg, &target_channel) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-b'."); rc = -1; goto out_free; } break; case 'T': if (str2uchar(optarg, &transit_addr) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-T'."); rc = -1; goto out_free; } break; case 'B': if (str2uchar(optarg, &transit_channel) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-B'."); rc = -1; goto out_free; } break; case 'l': if (str2uchar(optarg, &target_lun) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-l'."); rc = 1; goto out_free; } break; case 'm': if (str2uchar(optarg, &arg_addr) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'."); rc = -1; goto out_free; } break; case 'e': sol_escape_char = optarg[0]; break; case 'O': if (seloem) { free(seloem); seloem = NULL; } seloem = strdup(optarg); if (seloem == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } break; case 'z': if (str2ushort(optarg, &my_long_packet_size) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-z'."); rc = -1; goto out_free; } break; /* Retry and Timeout */ case 'R': if (str2int(optarg, &retry) != 0 || retry < 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-R'."); rc = -1; goto out_free; } break; case 'N': if (str2uint(optarg, &timeout) != 0) { lprintf(LOG_ERR, "Invalid parameter given or out of range for '-N'."); rc = -1; goto out_free; } break; #endif default: ipmi_option_usage(progname, cmdlist, intflist); goto out_free; } } /* check for command before doing anything */ if (argc-optind > 0 && strncmp(argv[optind], "help", 4) == 0) { ipmi_cmd_print(cmdlist); rc = 0; goto out_free; } /* * If the user has specified a hostname (-H option) * then this is a remote access session. * * If no password was specified by any other method * and the authtype was not explicitly set to NONE * then prompt the user. */ if (hostname != NULL && password == NULL && (authtype != IPMI_SESSION_AUTHTYPE_NONE || authtype < 0)) { #ifdef HAVE_GETPASSPHRASE tmp_pass = getpassphrase("Password: "); #else tmp_pass = getpass("Password: "); #endif if (tmp_pass != NULL) { password = strdup(tmp_pass); tmp_pass = NULL; if (password == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } } } /* if no interface was specified but a * hostname was then use LAN by default * otherwise the default is hardcoded * to use the first entry in the list */ if (intfname == NULL && hostname != NULL) { intfname = strdup("lan"); if (intfname == NULL) { lprintf(LOG_ERR, "%s: malloc failure", progname); goto out_free; } } if (password != NULL && intfname != NULL) { if (strcmp(intfname, "lan") == 0 && strlen(password) > 16) { lprintf(LOG_ERR, "%s: password is longer than 16 bytes.", intfname); rc = -1; goto out_free; } else if (strcmp(intfname, "lanplus") == 0 && strlen(password) > 20) { lprintf(LOG_ERR, "%s: password is longer than 20 bytes.", intfname); rc = -1; goto out_free; } } /* if (password != NULL && intfname != NULL) */ /* load interface */ ipmi_main_intf = ipmi_intf_load(intfname); if (ipmi_main_intf == NULL) { lprintf(LOG_ERR, "Error loading interface %s", intfname); goto out_free; } /* setup log */ log_init(progname, 0, verbose); /* run OEM setup if found */ if (oemtype != NULL && ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) { lprintf(LOG_ERR, "OEM setup for \"%s\" failed", oemtype); goto out_free; } /* set session variables */ if (hostname != NULL) ipmi_intf_session_set_hostname(ipmi_main_intf, hostname); if (username != NULL) ipmi_intf_session_set_username(ipmi_main_intf, username); if (password != NULL) ipmi_intf_session_set_password(ipmi_main_intf, password); if (kgkey != NULL) ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); if (port > 0) ipmi_intf_session_set_port(ipmi_main_intf, port); if (authtype >= 0) ipmi_intf_session_set_authtype(ipmi_main_intf, (uint8_t)authtype); if (privlvl > 0) ipmi_intf_session_set_privlvl(ipmi_main_intf, (uint8_t)privlvl); else ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN); /* default */ /* Adding retry and timeout for interface that support it */ if (retry > 0) ipmi_intf_session_set_retry(ipmi_main_intf, retry); if (timeout > 0) ipmi_intf_session_set_timeout(ipmi_main_intf, timeout); ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit); ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char); ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id); ipmi_main_intf->devnum = devnum; /* setup device file if given */ ipmi_main_intf->devfile = devfile; ipmi_main_intf->ai_family = ai_family; /* Open the interface with the specified or default IPMB address */ ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR; if (ipmi_main_intf->open != NULL) { if (ipmi_main_intf->open(ipmi_main_intf) < 0) { goto out_free; } } if (!ipmi_oem_active(ipmi_main_intf, "i82571spt")) { /* * Attempt picmg/vita discovery of the actual interface * address, unless the users specified an address. * Address specification always overrides discovery */ if (picmg_discover(ipmi_main_intf)) { ipmi_main_intf->picmg_avail = 1; } else if (vita_discover(ipmi_main_intf)) { ipmi_main_intf->vita_avail = 1; } } if (arg_addr) { addr = arg_addr; } else if (!ipmi_oem_active(ipmi_main_intf, "i82571spt")) { lprintf(LOG_DEBUG, "Acquire IPMB address"); addr = ipmi_acquire_ipmb_address(ipmi_main_intf); lprintf(LOG_INFO, "Discovered IPMB address 0x%x", addr); } /* * If we discovered the ipmb address and it is not the same as what we * used for open, Set the discovered IPMB address as my address if the * interface supports it. */ if (addr != 0 && addr != ipmi_main_intf->my_addr) { if (ipmi_main_intf->set_my_addr) { /* * Some interfaces need special handling * when changing local address */ (void)ipmi_main_intf->set_my_addr(ipmi_main_intf, addr); } /* set local address */ ipmi_main_intf->my_addr = addr; } ipmi_main_intf->target_addr = ipmi_main_intf->my_addr; /* If bridging addresses are specified, handle them */ if (transit_addr > 0 || target_addr > 0) { /* sanity check, transit makes no sense without a target */ if ((transit_addr != 0 || transit_channel != 0) && target_addr == 0) { lprintf(LOG_ERR, "Transit address/channel %#x/%#x ignored. " "Target address must be specified!", transit_addr, transit_channel); goto out_free; } ipmi_main_intf->target_addr = target_addr; ipmi_main_intf->target_channel = target_channel ; ipmi_main_intf->transit_addr = transit_addr; ipmi_main_intf->transit_channel = transit_channel; /* must be admin level to do this over lan */ ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN); /* Get the ipmb address of the targeted entity */ ipmi_main_intf->target_ipmb_addr = ipmi_acquire_ipmb_address(ipmi_main_intf); lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x", ipmi_main_intf->target_addr, ipmi_main_intf->target_channel, ipmi_main_intf->transit_addr, ipmi_main_intf->transit_channel); if (ipmi_main_intf->target_ipmb_addr) { lprintf(LOG_INFO, "Discovered Target IPMB-0 address %#x", ipmi_main_intf->target_ipmb_addr); } } /* set target LUN (for RAW command) */ ipmi_main_intf->target_lun = target_lun ; lprintf(LOG_DEBUG, "Interface address: my_addr %#x " "transit %#x:%#x target %#x:%#x " "ipmb_target %#x\n", ipmi_main_intf->my_addr, ipmi_main_intf->transit_addr, ipmi_main_intf->transit_channel, ipmi_main_intf->target_addr, ipmi_main_intf->target_channel, ipmi_main_intf->target_ipmb_addr); /* parse local SDR cache if given */ if (sdrcache != NULL) { ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache); } /* Parse SEL OEM file if given */ if (seloem != NULL) { ipmi_sel_oem_init(seloem); } /* Enable Big Buffer when requested */ if ( my_long_packet_size != 0 ) { /* Enable Big Buffer when requested */ if (!ipmi_oem_active(ipmi_main_intf, "kontron") || ipmi_kontronoem_set_large_buffer(ipmi_main_intf, my_long_packet_size ) == 0) { printf("Setting large buffer to %i\n", my_long_packet_size); my_long_packet_set = 1; ipmi_intf_set_max_request_data_size(ipmi_main_intf, my_long_packet_size); } } ipmi_main_intf->cmdlist = cmdlist; /* now we finally run the command */ if (argc-optind > 0) rc = ipmi_cmd_run(ipmi_main_intf, argv[optind], argc-optind-1, &(argv[optind+1])); else rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL); if (my_long_packet_set == 1) { if (ipmi_oem_active(ipmi_main_intf, "kontron")) { /* Restore defaults */ ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 ); } } /* clean repository caches */ ipmi_cleanup(ipmi_main_intf); /* call interface close function if available */ if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close != NULL) ipmi_main_intf->close(ipmi_main_intf); out_free: log_halt(); if (intfname != NULL) { free(intfname); intfname = NULL; } if (hostname != NULL) { free(hostname); hostname = NULL; } if (username != NULL) { free(username); username = NULL; } if (password != NULL) { free(password); password = NULL; } if (oemtype != NULL) { free(oemtype); oemtype = NULL; } if (seloem != NULL) { free(seloem); seloem = NULL; } if (kgkey != NULL) { free(kgkey); kgkey = NULL; } if (sdrcache != NULL) { free(sdrcache); sdrcache = NULL; } if (devfile) { free(devfile); devfile = NULL; } return rc; }