diff --git a/ipmitool/include/ipmitool/ipmi_intf.h b/ipmitool/include/ipmitool/ipmi_intf.h index b2aa95d..1a9ca40 100644 --- a/ipmitool/include/ipmitool/ipmi_intf.h +++ b/ipmitool/include/ipmitool/ipmi_intf.h @@ -68,7 +68,7 @@ enum LANPLUS_SESSION_STATE { struct ipmi_session { uint8_t hostname[64]; - uint8_t username[16]; + uint8_t username[17]; uint8_t authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1]; uint8_t challenge[16]; uint8_t authtype; @@ -82,6 +82,7 @@ struct ipmi_session { uint8_t authextra; uint8_t privlvl; uint8_t cipher_suite_id; + char sol_escape_char; int password; int port; int active; @@ -194,6 +195,8 @@ void ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username); void ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password); void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t privlvl); void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id); +void ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char); +void ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey); void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port); void ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype); void ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout); diff --git a/ipmitool/include/ipmitool/ipmi_sol.h b/ipmitool/include/ipmitool/ipmi_sol.h index 568d4c0..582ac69 100644 --- a/ipmitool/include/ipmitool/ipmi_sol.h +++ b/ipmitool/include/ipmitool/ipmi_sol.h @@ -39,6 +39,7 @@ #include +#define SOL_ESCAPE_CHARACTER_DEFAULT '~' #define IPMI_SOL_SERIAL_ALERT_MASK_SUCCEED 0x08 #define IPMI_SOL_SERIAL_ALERT_MASK_DEFERRED 0x04 diff --git a/ipmitool/lib/ipmi_fru.c b/ipmitool/lib/ipmi_fru.c index 758ff8c..63b5ac5 100644 --- a/ipmitool/lib/ipmi_fru.c +++ b/ipmitool/lib/ipmi_fru.c @@ -48,6 +48,17 @@ # include #endif +/* + * Apparently some systems have problems with FRU access greater than 16 bytes + * at a time, even when using byte (not word) access. In order to ensure we + * work with the widest variety of hardware request size is capped at 16 bytes. + * Since this may result in slowdowns on some systems with lots of FRU data you + * can undefine this to enable larger (up to 32 bytes at a time) access. + * + * TODO: make this a command line option + */ +#define LIMIT_ALL_REQUEST_SIZE 1 + extern int verbose; extern int ipmi_spd_print(struct ipmi_intf * intf, uint8_t id); static void ipmi_fru_read_to_bin(struct ipmi_intf * intf,unsigned char * pFileName, unsigned char fruId); @@ -216,9 +227,13 @@ write_fru_area(struct ipmi_intf * intf, struct fru_info *fru, unsigned char id, req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = SET_FRU_DATA; req.msg.data = msg_data; - + +#ifdef LIMIT_ALL_REQUEST_SIZE + if (fru_data_rqst_size > 16) +#else if (fru->access && fru_data_rqst_size > 16) - fru_data_rqst_size = 16; +#endif + fru_data_rqst_size = 16; do { /* real destination offset */ @@ -301,7 +316,11 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, req.msg.data = msg_data; req.msg.data_len = 4; +#ifdef LIMIT_ALL_REQUEST_SIZE + if (fru_data_rqst_size > 16) +#else if (fru->access && fru_data_rqst_size > 16) +#endif fru_data_rqst_size = 16; do { tmp = fru->access ? off >> 1 : off; @@ -320,8 +339,6 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, break; } if (rsp->ccode > 0) { - lprintf(LOG_NOTICE, "FRU Read failed: %s", - val2str(rsp->ccode, completion_code_vals)); /* if we get C7 or C8 or CA return code then we requested too * many bytes at once so try again with smaller size */ if ((rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) && @@ -330,6 +347,8 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, fru_data_rqst_size); continue; } + lprintf(LOG_NOTICE, "FRU Read failed: %s", + val2str(rsp->ccode, completion_code_vals)); break; } @@ -1159,15 +1178,15 @@ __ipmi_fru_print(struct ipmi_intf * intf, uint8_t id) lprintf(LOG_DEBUG, "fru.header.version: 0x%x", header.version); lprintf(LOG_DEBUG, "fru.header.offset.internal: 0x%x", - header.offset.internal); + header.offset.internal * 8); lprintf(LOG_DEBUG, "fru.header.offset.chassis: 0x%x", - header.offset.chassis); + header.offset.chassis * 8); lprintf(LOG_DEBUG, "fru.header.offset.board: 0x%x", - header.offset.board); + header.offset.board * 8); lprintf(LOG_DEBUG, "fru.header.offset.product: 0x%x", - header.offset.product); + header.offset.product * 8); lprintf(LOG_DEBUG, "fru.header.offset.multi: 0x%x", - header.offset.multi); + header.offset.multi * 8); /* * rather than reading the entire part diff --git a/ipmitool/lib/ipmi_main.c b/ipmitool/lib/ipmi_main.c index e328c30..380c26c 100644 --- a/ipmitool/lib/ipmi_main.c +++ b/ipmitool/lib/ipmi_main.c @@ -74,7 +74,7 @@ #endif #ifdef ENABLE_ALL_OPTIONS -# define OPTION_STRING "I:hVvcgsEao:H:P:f:U:p:C:L:A:t:m:S:l:b:" +# define OPTION_STRING "I:hVvcgsEao:H:P:f:U:p:C:L:A:t:m:S:l:b:e:k:" #else # define OPTION_STRING "I:hVvcH:f:U:p:S:" #endif @@ -227,7 +227,9 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_ lprintf(LOG_NOTICE, " -S sdr Use local file for remote SDR cache"); #ifdef ENABLE_ALL_OPTIONS lprintf(LOG_NOTICE, " -a Prompt for remote password"); + 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, " -L level Remote session privilege level [default=ADMINISTRATOR]"); lprintf(LOG_NOTICE, " -A authtype Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM"); lprintf(LOG_NOTICE, " -P password Remote session password"); @@ -235,7 +237,6 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_ lprintf(LOG_NOTICE, " -m address Set local IPMB address"); lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request"); lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands"); - lprintf(LOG_NOTICE, " -t address Bridge request to remote target address"); lprintf(LOG_NOTICE, " -o oemtype Setup for OEM (use 'list' to see available OEM types)"); #endif @@ -279,10 +280,12 @@ ipmi_main(int argc, char ** argv, char * progname = NULL; char * oemtype = NULL; char * sdrcache = NULL; + char * kgkey = NULL; int port = 0; int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */ int argflag, i, found; int rc = -1; + char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT; /* save program name */ progname = strrchr(argv[0], '/'); @@ -364,6 +367,13 @@ ipmi_main(int argc, char ** argv, } } break; + case 'k': + kgkey = strdup(optarg); + if (kgkey == NULL) { + lprintf(LOG_ERR, "%s: malloc failure", progname); + goto out_free; + } + break; case 'U': username = strdup(optarg); if (username == NULL) { @@ -457,6 +467,9 @@ ipmi_main(int argc, char ** argv, case 'm': my_addr = (uint8_t)strtol(optarg, NULL, 0); break; + case 'e': + sol_escape_char = optarg[0]; + break; #endif default: ipmi_option_usage(progname, cmdlist, intflist); @@ -533,6 +546,8 @@ ipmi_main(int argc, char ** argv, ipmi_intf_session_set_username(intf, username); if (password != NULL) ipmi_intf_session_set_password(intf, password); + if (kgkey != NULL) + ipmi_intf_session_set_kgkey(intf, kgkey); if (port > 0) ipmi_intf_session_set_port(intf, port); if (authtype >= 0) @@ -543,13 +558,14 @@ ipmi_main(int argc, char ** argv, ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN); /* default */ + ipmi_intf_session_set_sol_escape_char(intf, sol_escape_char); ipmi_intf_session_set_cipher_suite_id(intf, cipher_suite_id); - /* setup destination lun if given */ - intf->target_lun = target_lun ; + /* setup destination lun if given */ + intf->target_lun = target_lun ; - /* setup destination channel if given */ - intf->target_channel = target_channel ; + /* setup destination channel if given */ + intf->target_channel = target_channel ; /* setup IPMB local and target address if given */ intf->my_addr = my_addr ? : IPMI_BMC_SLAVE_ADDR; diff --git a/ipmitool/lib/ipmi_sol.c b/ipmitool/lib/ipmi_sol.c index 3bbe6e8..5aa09a8 100644 --- a/ipmitool/lib/ipmi_sol.c +++ b/ipmitool/lib/ipmi_sol.c @@ -67,8 +67,6 @@ #define SOL_PARAMETER_SOL_PAYLOAD_CHANNEL 0x07 #define SOL_PARAMETER_SOL_PAYLOAD_PORT 0x08 -#define SOL_ESCAPE_CHARACTER '~' - const struct valstr sol_parameter_vals[] = { { SOL_PARAMETER_SET_IN_PROGRESS, "Set In Progress (0)" }, { SOL_PARAMETER_SOL_ENABLE, "Enable (1)" }, @@ -1048,7 +1046,7 @@ suspendSelf(int bRestoreTty) * Send some useful documentation to the user */ static void -printSolEscapeSequences(void) +printSolEscapeSequences(struct ipmi_intf * intf) { printf( "%c?\r\n\ @@ -1060,14 +1058,14 @@ printSolEscapeSequences(void) %c? - this message\r\n\ %c%c - send the escape character by typing it twice\r\n\ (Note that escapes are only recognized immediately after newline.)\r\n", - SOL_ESCAPE_CHARACTER, - SOL_ESCAPE_CHARACTER, - SOL_ESCAPE_CHARACTER, - SOL_ESCAPE_CHARACTER, - SOL_ESCAPE_CHARACTER, - SOL_ESCAPE_CHARACTER, - SOL_ESCAPE_CHARACTER, - SOL_ESCAPE_CHARACTER); + intf->session->sol_escape_char, + intf->session->sol_escape_char, + intf->session->sol_escape_char, + intf->session->sol_escape_char, + intf->session->sol_escape_char, + intf->session->sol_escape_char, + intf->session->sol_escape_char, + intf->session->sol_escape_char); } @@ -1158,7 +1156,7 @@ static int processSolUserInput( struct ipmi_intf * intf, uint8_t * input, - uint16_t buffer_length) + uint16_t buffer_length) { static int escape_pending = 0; static int last_was_cr = 1; @@ -1186,38 +1184,44 @@ processSolUserInput( */ switch (ch) { case '.': - printf("%c. [terminated ipmitool]\r\n", SOL_ESCAPE_CHARACTER); + printf("%c. [terminated ipmitool]\r\n", + intf->session->sol_escape_char); retval = 1; break; + case 'Z' - 64: - printf("%c^Z [suspend ipmitool]\r\n", SOL_ESCAPE_CHARACTER); + printf("%c^Z [suspend ipmitool]\r\n", + intf->session->sol_escape_char); suspendSelf(1); /* Restore tty back to raw */ continue; case 'X' - 64: - printf("%c^Z [suspend ipmitool]\r\n", SOL_ESCAPE_CHARACTER); + printf("%c^Z [suspend ipmitool]\r\n", + intf->session->sol_escape_char); suspendSelf(0); /* Don't restore to raw mode */ continue; case 'B': - printf("%cb [send break]\r\n", SOL_ESCAPE_CHARACTER); + printf("%cb [send break]\r\n", + intf->session->sol_escape_char); sendBreak(intf); continue; case '?': - printSolEscapeSequences(); + printSolEscapeSequences(intf); continue; + default: - if (ch != SOL_ESCAPE_CHARACTER) + if (ch != intf->session->sol_escape_char) v2_payload.payload.sol_packet.data[length++] = - SOL_ESCAPE_CHARACTER; + intf->session->sol_escape_char; v2_payload.payload.sol_packet.data[length++] = ch; } } else { - if (last_was_cr && (ch == SOL_ESCAPE_CHARACTER)) { + if (last_was_cr && (ch == intf->session->sol_escape_char)) { escape_pending = 1; continue; } @@ -1413,7 +1417,7 @@ ipmi_sol_activate(struct ipmi_intf * intf) intf->session->sol_data.sol_input_handler = output; - memset(&req, 0, sizeof(req)); + memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = IPMI_ACTIVATE_PAYLOAD; req.msg.data_len = 6; @@ -1519,7 +1523,7 @@ ipmi_sol_activate(struct ipmi_intf * intf) printf("[SOL Session operational. Use %c? for help]\r\n", - SOL_ESCAPE_CHARACTER); + intf->session->sol_escape_char); /* diff --git a/ipmitool/src/plugins/ipmi_intf.c b/ipmitool/src/plugins/ipmi_intf.c index 7bb855a..b90eaac 100644 --- a/ipmitool/src/plugins/ipmi_intf.c +++ b/ipmitool/src/plugins/ipmi_intf.c @@ -180,7 +180,7 @@ ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username) if (intf->session == NULL) return; - memset(intf->session->username, 0, 16); + memset(intf->session->username, 0, 17); if (username == NULL) return; @@ -224,6 +224,30 @@ ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_su intf->session->cipher_suite_id = cipher_suite_id; } +void +ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char) +{ + if (intf->session == NULL) + return; + + intf->session->sol_escape_char = sol_escape_char; +} + +void +ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey) +{ + if (intf->session == NULL) + return; + + memset(intf->session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); + + if (kgkey == NULL) + return; + + memcpy(intf->session->v2_data.kg, kgkey, + __min(strlen(kgkey), IPMI_KG_BUFFER_SIZE)); +} + void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port) { diff --git a/ipmitool/src/plugins/lanplus/lanplus.c b/ipmitool/src/plugins/lanplus/lanplus.c index 9c090d8..da2f4cb 100644 --- a/ipmitool/src/plugins/lanplus/lanplus.c +++ b/ipmitool/src/plugins/lanplus/lanplus.c @@ -3238,7 +3238,9 @@ ipmi_lanplus_open(struct ipmi_intf * intf) //session->sol_data.last_received_sequence_number = 0; //session->sol_data.last_received_byte_count = 0; memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE); - memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); + + /* Kg is set in ipmi_intf */ + //memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); /* open port to BMC */ diff --git a/ipmitool/src/plugins/lanplus/lanplus_crypt.c b/ipmitool/src/plugins/lanplus/lanplus_crypt.c index ffc346d..7c4fd2e 100644 --- a/ipmitool/src/plugins/lanplus/lanplus_crypt.c +++ b/ipmitool/src/plugins/lanplus/lanplus_crypt.c @@ -528,13 +528,10 @@ int lanplus_generate_sik(struct ipmi_session * session) { /* We will be hashing with Kg */ /* - * TODO: Section 13.31 of the IPMI v2 spec describes the SIK creation - * using Kg. It specifies that Kg should not be truncated, but I - * do not know what is meant by that. + * Section 13.31 of the IPMI v2 spec describes the SIK creation + * using Kg. It specifies that Kg should not be truncated. + * Kg is set in ipmi_intf. */ - lprintf(LOG_ERR, "lanplus_generate_sik: We dont yet support hashing with Kg"); - assert(0); - input_key = session->v2_data.kg; } else