diff options
Diffstat (limited to 'debian/patches/20_ipmi_isol')
-rw-r--r-- | debian/patches/20_ipmi_isol | 1185 |
1 files changed, 14 insertions, 1171 deletions
diff --git a/debian/patches/20_ipmi_isol b/debian/patches/20_ipmi_isol index ac70722..85e684f 100644 --- a/debian/patches/20_ipmi_isol +++ b/debian/patches/20_ipmi_isol @@ -1,37 +1,10 @@ ## 20_ipmi_isol.dpatch by <mjj29@debian.org> ## ## 20_ipmi_isol, closes #412816 -diff -urN ipmitool-1.8.9.orig/include/ipmitool/ipmi_isol.h ipmitool-1.8.9/include/ipmitool/ipmi_isol.h ---- ipmitool-1.8.9.orig/include/ipmitool/ipmi_isol.h 2007-02-22 08:38:55.000000000 +0000 -+++ ipmitool-1.8.9/include/ipmitool/ipmi_isol.h 2007-12-13 10:16:57.063986495 +0000 -@@ -41,15 +41,16 @@ - - #define ISOL_ENABLE_PARAM 0x01 - #define ISOL_AUTHENTICATION_PARAM 0x02 --#define ISOL_ENABLE_FLAG 0x01 --#define ISOL_PRIVILEGE_LEVEL_USER 0x02 -+ - #define ISOL_BAUD_RATE_PARAM 0x05 --#define ISOL_BAUD_RATE_9600 0x06 --#define ISOL_BAUD_RATE_19200 0x07 --#define ISOL_BAUD_RATE_38400 0x08 --#define ISOL_BAUD_RATE_57600 0x09 --#define ISOL_BAUD_RATE_115200 0x0A --#define ISOL_PREFERRED_BAUD_RATE 0x07 -+ -+#define ISOL_PREFERRED_BAUD_RATE 0x07 -+ -+struct isol_config_parameters { -+ uint8_t enabled; -+ uint8_t privilege_level; -+ uint8_t bit_rate; -+}; - - int ipmi_isol_main(struct ipmi_intf *, int, char **); - -diff -urN ipmitool-1.8.9.orig/include/ipmitool/ipmi_isol.h.orig ipmitool-1.8.9/include/ipmitool/ipmi_isol.h.orig ---- ipmitool-1.8.9.orig/include/ipmitool/ipmi_isol.h.orig 1970-01-01 01:00:00.000000000 +0100 -+++ ipmitool-1.8.9/include/ipmitool/ipmi_isol.h.orig 2007-02-22 08:38:55.000000000 +0000 +Index: ipmitool-1.8.11/include/ipmitool/ipmi_isol.h.orig +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ipmitool-1.8.11/include/ipmitool/ipmi_isol.h.orig 2009-03-22 16:48:34.633972562 +0000 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. @@ -89,874 +62,10 @@ diff -urN ipmitool-1.8.9.orig/include/ipmitool/ipmi_isol.h.orig ipmitool-1.8.9/i +int ipmi_isol_main(struct ipmi_intf *, int, char **); + +#endif /* IPMI_SOL_H */ -diff -urN ipmitool-1.8.9.orig/lib/ipmi_isol.c ipmitool-1.8.9/lib/ipmi_isol.c ---- ipmitool-1.8.9.orig/lib/ipmi_isol.c 2007-02-22 08:38:56.000000000 +0000 -+++ ipmitool-1.8.9/lib/ipmi_isol.c 2007-12-13 10:16:57.063986495 +0000 -@@ -32,7 +32,17 @@ - - #include <stdlib.h> - #include <string.h> -+#include <strings.h> - #include <stdio.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <sys/select.h> -+#include <sys/time.h> -+#include <signal.h> -+#include <unistd.h> -+ -+ -+#include <termios.h> - - #include <ipmitool/helper.h> - #include <ipmitool/log.h> -@@ -41,39 +51,40 @@ - #include <ipmitool/ipmi_intf.h> - #include <ipmitool/ipmi_isol.h> - --const struct valstr ipmi_isol_baud_vals[] = { -- { ISOL_BAUD_RATE_9600, "9600" }, -- { ISOL_BAUD_RATE_19200, "19200" }, -- { ISOL_BAUD_RATE_38400, "38400" }, -- { ISOL_BAUD_RATE_57600, "57600" }, -- { ISOL_BAUD_RATE_115200, "115200" }, -- { 0x00, NULL } --}; -+static struct termios _saved_tio; -+static int _in_raw_mode = 0; - - extern int verbose; - --static int ipmi_isol_setup(struct ipmi_intf * intf, char baudsetting) -+#define ISOL_ESCAPE_CHARACTER '~' -+ -+/* -+ * ipmi_get_isol_info -+ */ -+static int ipmi_get_isol_info(struct ipmi_intf * intf, -+ struct isol_config_parameters * params) - { - struct ipmi_rs * rsp; - struct ipmi_rq req; -- unsigned char data[6]; -+ unsigned char data[6]; - -- /* TEST FOR AVAILABILITY */ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_ISOL; -+ req.msg.cmd = GET_ISOL_CONFIG; -+ req.msg.data = data; -+ req.msg.data_len = 4; - -+ /* GET ISOL ENABLED CONFIG */ -+ - memset(data, 0, 6); - data[0] = 0x00; - data[1] = ISOL_ENABLE_PARAM; -- data[2] = ISOL_ENABLE_FLAG; -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_ISOL; -- req.msg.cmd = SET_ISOL_CONFIG; -- req.msg.data = data; -- req.msg.data_len = 3; -+ data[2] = 0x00; /* block */ -+ data[3] = 0x00; /* selector */ - - rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { -- lprintf(LOG_ERR, "Error in Set ISOL Config Command"); -+ lprintf(LOG_ERR, "Error in Get ISOL Config Command"); - return -1; - } - if (rsp->ccode == 0xc1) { -@@ -81,20 +92,19 @@ - return -1; - } - if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Error in Set ISOL Config Command: %s", -+ lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s", - val2str(rsp->ccode, completion_code_vals)); - return -1; - } -+ params->enabled = rsp->data[1]; - -- /* GET ISOL CONFIG */ -- -+ /* GET ISOL AUTHENTICATON CONFIG */ -+ - memset(data, 0, 6); - data[0] = 0x00; - data[1] = ISOL_AUTHENTICATION_PARAM; - data[2] = 0x00; /* block */ - data[3] = 0x00; /* selector */ -- req.msg.cmd = GET_ISOL_CONFIG; -- req.msg.data_len = 4; - - rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { -@@ -106,86 +116,713 @@ - val2str(rsp->ccode, completion_code_vals)); - return -1; - } -- -- if (verbose > 1) -- printbuf(rsp->data, rsp->data_len, "ISOL Config"); -- -- /* SET ISOL CONFIG - AUTHENTICATION */ -- -+ params->privilege_level = rsp->data[1]; -+ -+ /* GET ISOL BAUD RATE CONFIG */ -+ - memset(data, 0, 6); - data[0] = 0x00; -- data[1] = ISOL_AUTHENTICATION_PARAM; -- data[2] = ISOL_PRIVILEGE_LEVEL_USER | (rsp->data[1] & 0x80); -- req.msg.cmd = SET_ISOL_CONFIG; -- req.msg.data_len = 3; -+ data[1] = ISOL_BAUD_RATE_PARAM; -+ data[2] = 0x00; /* block */ -+ data[3] = 0x00; /* selector */ - - rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { -- lprintf(LOG_ERR, "Error in Set ISOL Config (Authentication) Command"); -+ lprintf(LOG_ERR, "Error in Get ISOL Config Command"); - return -1; - } - if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Error in Set ISOL Config (Authentication) Command: %s", -+ lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s", - val2str(rsp->ccode, completion_code_vals)); - return -1; - } -+ params->bit_rate = rsp->data[1]; - -- /* SET ISOL CONFIG - BAUD RATE */ -+ return 0; -+} - -- memset(data, 0, 6); -- data[0] = 0x00; -- data[1] = ISOL_BAUD_RATE_PARAM; -- data[2] = baudsetting; -+static int ipmi_print_isol_info(struct ipmi_intf * intf) -+{ -+ struct isol_config_parameters params = {0}; -+ if (ipmi_get_isol_info(intf, ¶ms)) -+ return -1; -+ -+ if (csv_output) -+ { -+ printf("%s,", (params.enabled & 0x1)?"true": "false"); -+ printf("%s,", -+ val2str((params.privilege_level & 0xf), ipmi_privlvl_vals)); -+ printf("%s,", -+ val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals)); -+ } -+ else -+ { -+ printf("Enabled : %s\n", -+ (params.enabled & 0x1)?"true": "false"); -+ printf("Privilege Level : %s\n", -+ val2str((params.privilege_level & 0xf), ipmi_privlvl_vals)); -+ printf("Bit Rate (kbps) : %s\n", -+ val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals)); -+ } -+ -+ return 0; -+} -+ -+static int ipmi_isol_set_param(struct ipmi_intf * intf, -+ const char *param, -+ const char *value) -+{ -+ struct ipmi_rs * rsp; -+ struct ipmi_rq req; -+ unsigned char data[6]; -+ struct isol_config_parameters params = {0}; -+ -+ /* We need other values to complete the request */ -+ if (ipmi_get_isol_info(intf, ¶ms)) -+ return -1; -+ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_ISOL; - req.msg.cmd = SET_ISOL_CONFIG; -+ req.msg.data = data; - req.msg.data_len = 3; - -+ memset(data, 0, 6); -+ -+ /* -+ * enabled -+ */ -+ if (strcmp(param, "enabled") == 0) -+ { -+ data[1] = ISOL_ENABLE_PARAM; -+ if (strcmp(value, "true") == 0) -+ data[2] = 0x01; -+ else if (strcmp(value, "false") == 0) -+ data[2] = 0x00; -+ else { -+ lprintf(LOG_ERR, "Invalid value %s for parameter %s", -+ value, param); -+ lprintf(LOG_ERR, "Valid values are true and false"); -+ return -1; -+ } -+ } -+ -+ /* -+ * privilege-level -+ */ -+ else if (strcmp(param, "privilege-level") == 0) -+ { -+ data[1] = ISOL_AUTHENTICATION_PARAM; -+ if (! strcmp(value, "user")) -+ data[2] = 0x02; -+ else if (! strcmp(value, "operator")) -+ data[2] = 0x03; -+ else if (! strcmp(value, "admin")) -+ data[2] = 0x04; -+ else if (! strcmp(value, "oem")) -+ data[2] = 0x05; -+ else -+ { -+ lprintf(LOG_ERR, "Invalid value %s for parameter %s", -+ value, param); -+ lprintf(LOG_ERR, "Valid values are user, operator, admin, and oem"); -+ return -1; -+ } -+ /* We need to mask bit7 from the fetched value */ -+ data[2] |= (params.privilege_level & 0x80) ? 0x80 : 0x00; -+ } -+ -+ /* -+ * bit-rate -+ */ -+ else if (strcmp(param, "bit-rate") == 0) -+ { -+ data[1] = ISOL_BAUD_RATE_PARAM; -+ if (strncmp(value, "9.6", 3) == 0) { -+ data[2] = 0x06; -+ } -+ else if (strncmp(value, "19.2", 4) == 0) { -+ data[2] = 0x07; -+ } -+ else if (strncmp(value, "38.4", 4) == 0) { -+ data[2] = 0x08; -+ } -+ else if (strncmp(value, "57.6", 4) == 0) { -+ data[2] = 0x09; -+ } -+ else if (strncmp(value, "115.2", 5) == 0) { -+ data[2] = 0x0A; -+ } -+ else { -+ lprintf(LOG_ERR, "ISOL - Unsupported baud rate: %s", value); -+ lprintf(LOG_ERR, "Valid values are 9.6, 19.2, 38.4, 57.6 and 115.2"); -+ return -1; -+ } -+ } -+ else -+ { -+ lprintf(LOG_ERR, "Error: invalid ISOL parameter %s", param); -+ return -1; -+ } -+ -+ -+ /* -+ * Execute the request -+ */ -+ - rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { -- lprintf(LOG_ERR, "Error in Set ISOL Config (Baud Rate) Command"); -+ lprintf(LOG_ERR, "Error setting ISOL parameter '%s'", param); - return -1; - } - if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Error in Set ISOL Config (Baud Rate) Command: %s", -- val2str(rsp->ccode, completion_code_vals)); -+ lprintf(LOG_ERR, "Error setting ISOL parameter '%s': %s", -+ param, val2str(rsp->ccode, completion_code_vals)); - return -1; - } - -- printf("Set ISOL Baud Rate to %s\n", -- val2str(baudsetting, ipmi_isol_baud_vals)); -+ return 0; -+} -+ -+static void -+leave_raw_mode(void) -+{ -+ if (!_in_raw_mode) -+ return; -+ if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) -+ perror("tcsetattr"); -+ else -+ _in_raw_mode = 0; -+} -+ -+ -+ -+static void -+enter_raw_mode(void) -+{ -+ struct termios tio; -+ if (tcgetattr(fileno(stdin), &tio) == -1) { -+ perror("tcgetattr"); -+ return; -+ } -+ _saved_tio = tio; -+ tio.c_iflag |= IGNPAR; -+ tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF)\ -+ ; -+ tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); -+ // #ifdef IEXTEN -+ tio.c_lflag &= ~IEXTEN; -+ // #endif -+ tio.c_oflag &= ~OPOST; -+ tio.c_cc[VMIN] = 1; -+ tio.c_cc[VTIME] = 0; -+ if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1) -+ perror("tcsetattr"); -+ else -+ _in_raw_mode = 1; -+} -+ -+ -+static void -+sendBreak(struct ipmi_intf * intf) -+{ -+ struct ipmi_v2_payload v2_payload; -+ -+ memset(&v2_payload, 0, sizeof(v2_payload)); -+ -+ v2_payload.payload.sol_packet.character_count = 0; -+ v2_payload.payload.sol_packet.generate_break = 1; -+ -+ intf->send_sol(intf, &v2_payload); -+} -+ -+/* -+ * suspendSelf -+ * -+ * Put ourself in the background -+ * -+ * param bRestoreTty specifies whether we will put our self back -+ * in raw mode when we resume -+ */ -+static void -+suspendSelf(int bRestoreTty) -+{ -+ leave_raw_mode(); -+ kill(getpid(), SIGTSTP); -+ -+ if (bRestoreTty) -+ enter_raw_mode(); -+} -+ -+ -+ -+/* -+ * printiSolEscapeSequences -+ * -+ * Send some useful documentation to the user -+ */ -+static void -+printiSolEscapeSequences(void) -+{ -+ printf( -+ "%c?\r\n\ -+ Supported escape sequences:\r\n\ -+ %c. - terminate connection\r\n\ -+ %c^Z - suspend ipmitool\r\n\ -+ %c^X - suspend ipmitool, but don't restore tty on restart\r\n\ -+ %cB - send break\r\n\ -+ %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", -+ ISOL_ESCAPE_CHARACTER, -+ ISOL_ESCAPE_CHARACTER, -+ ISOL_ESCAPE_CHARACTER, -+ ISOL_ESCAPE_CHARACTER, -+ ISOL_ESCAPE_CHARACTER, -+ ISOL_ESCAPE_CHARACTER, -+ ISOL_ESCAPE_CHARACTER, -+ ISOL_ESCAPE_CHARACTER); -+} -+ -+ -+ -+/* -+ * output -+ * -+ * Send the specified data to stdout -+ */ -+static void -+output(struct ipmi_rs * rsp) -+{ -+ if (rsp) -+ { -+ int i; -+ for (i = 0; i < rsp->data_len; ++i) -+ putc(rsp->data[i], stdout); -+ -+ fflush(stdout); -+ } -+} -+ -+/* -+ * ipmi_isol_deactivate -+ */ -+static int -+ipmi_isol_deactivate(struct ipmi_intf * intf) -+{ -+ struct ipmi_rs * rsp; -+ struct ipmi_rq req; -+ uint8_t data[6]; -+ struct isol_config_parameters params; -+ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_ISOL; -+ req.msg.cmd = ACTIVATE_ISOL; -+ req.msg.data = data; -+ req.msg.data_len = 5; - -+ memset(data, 0, 6); -+ data[0] = 0x00; /* Deactivate */ -+ data[1] = 0x00; -+ data[2] = 0x00; -+ data[3] = 0x00; -+ data[5] = 0x00; -+ -+ rsp = intf->sendrecv(intf, &req); -+ if (rsp == NULL) { -+ lprintf(LOG_ERR, "Error deactivating ISOL"); -+ return -1; -+ } -+ if (rsp->ccode > 0) { -+ lprintf(LOG_ERR, "Error deactivating ISOL: %s", -+ val2str(rsp->ccode, completion_code_vals)); -+ return -1; -+ } -+ /* response contain 4 additional bytes : 80 00 32 ff -+ Don't know what to use them for yet... */ - return 0; - } - --int ipmi_isol_main(struct ipmi_intf * intf, int argc, char ** argv) -+/* -+ * processiSolUserInput -+ * -+ * Act on user input into the ISOL session. The only reason this -+ * is complicated is that we have to process escape sequences. -+ * -+ * return 0 on success -+ * 1 if we should exit -+ * < 0 on error (BMC probably closed the session) -+ */ -+static int -+processiSolUserInput(struct ipmi_intf * intf, -+ uint8_t * input, -+ uint16_t buffer_length) - { -- int ret = 0; -+ static int escape_pending = 0; -+ static int last_was_cr = 1; -+ struct ipmi_v2_payload v2_payload; -+ int length = 0; -+ int retval = 0; -+ char ch; -+ int i; -+ -+ memset(&v2_payload, 0, sizeof(v2_payload)); -+ -+ /* -+ * Our first order of business is to check the input for escape -+ * sequences to act on. -+ */ -+ for (i = 0; i < buffer_length; ++i) -+ { -+ ch = input[i]; -+ -+ if (escape_pending){ -+ escape_pending = 0; -+ -+ /* -+ * Process a possible escape sequence. -+ */ -+ switch (ch) { -+ case '.': -+ printf("%c. [terminated ipmitool]\r\n", ISOL_ESCAPE_CHARACTER); -+ retval = 1; -+ break; -+ case 'Z' - 64: -+ printf("%c^Z [suspend ipmitool]\r\n", ISOL_ESCAPE_CHARACTER); -+ suspendSelf(1); /* Restore tty back to raw */ -+ continue; -+ -+ case 'X' - 64: -+ printf("%c^X [suspend ipmitool]\r\n", ISOL_ESCAPE_CHARACTER); -+ suspendSelf(0); /* Don't restore to raw mode */ -+ continue; -+ -+ case 'B': -+ printf("%cb [send break]\r\n", ISOL_ESCAPE_CHARACTER); -+ sendBreak(intf); -+ continue; -+ -+ case '?': -+ printiSolEscapeSequences(); -+ continue; -+ default: -+ if (ch != ISOL_ESCAPE_CHARACTER) -+ v2_payload.payload.sol_packet.data[length++] = -+ ISOL_ESCAPE_CHARACTER; -+ v2_payload.payload.sol_packet.data[length++] = ch; -+ } -+ } - -- if (argc < 2 || strncmp(argv[0], "help", 4) == 0) { -- lprintf(LOG_NOTICE, "ISOL Commands: setup <baud>"); -- lprintf(LOG_NOTICE, "ISOL Baud Rates: 9600, 19200, 38400, 57600, 115200"); -- return 0; -- } -- -- if (strncmp(argv[0], "setup", 5) == 0) { -- if (strncmp(argv[1], "9600", 4) == 0) { -- ret = ipmi_isol_setup(intf, ISOL_BAUD_RATE_9600); -- } -- else if (strncmp(argv[1], "19200", 5) == 0) { -- ret = ipmi_isol_setup(intf, ISOL_BAUD_RATE_19200); -+ else -+ { -+ if (last_was_cr && (ch == ISOL_ESCAPE_CHARACTER)) { -+ escape_pending = 1; -+ continue; -+ } -+ -+ v2_payload.payload.sol_packet.data[length++] = ch; - } -- else if (strncmp(argv[1], "38400", 5) == 0) { -- ret = ipmi_isol_setup(intf, ISOL_BAUD_RATE_38400); -+ -+ -+ /* -+ * Normal character. Record whether it was a newline. -+ */ -+ last_was_cr = (ch == '\r' || ch == '\n'); -+ } -+ -+ /* -+ * If there is anything left to process we dispatch it to the BMC, -+ * send intf->session->sol_data.max_outbound_payload_size bytes -+ * at a time. -+ */ -+ if (length) -+ { -+ struct ipmi_rs * rsp; -+ -+ v2_payload.payload.sol_packet.flush_outbound = 1; /* Not sure if necessary ? */ -+ v2_payload.payload.sol_packet.character_count = length; -+ rsp = intf->send_sol(intf, &v2_payload); -+ -+ if (! rsp) { -+ lprintf(LOG_ERR, "Error sending SOL data"); -+ retval = -1; - } -- else if (strncmp(argv[1], "57600", 5) == 0) { -- ret = ipmi_isol_setup(intf, ISOL_BAUD_RATE_57600); -+ -+ /* If the sequence number is set we know we have new data */ -+ else if ((rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) && -+ (rsp->payload.sol_packet.packet_sequence_number)) -+ output(rsp); -+ } -+ return retval; -+} -+ -+/* -+ * ipmi_isol_red_pill -+ */ -+static int -+ipmi_isol_red_pill(struct ipmi_intf * intf) -+{ -+ char * buffer; -+ int numRead; -+ int bShouldExit = 0; -+ int bBmcClosedSession = 0; -+ fd_set read_fds; -+ struct timeval tv; -+ int retval; -+ int buffer_size = 255; -+ int timedout = 0; -+ -+ buffer = (char*)malloc(buffer_size); -+ if (buffer == NULL) { -+ lprintf(LOG_ERR, "ipmitool: malloc failure"); -+ return -1; -+ } -+ -+ enter_raw_mode(); -+ -+ while (! bShouldExit) -+ { -+ FD_ZERO(&read_fds); -+ FD_SET(0, &read_fds); -+ FD_SET(intf->fd, &read_fds); -+ -+ /* Wait up to half a second */ -+ tv.tv_sec = 0; -+ tv.tv_usec = 500000; -+ -+ retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv); -+ -+ if (retval) -+ { -+ if (retval == -1) -+ { -+ /* ERROR */ -+ perror("select"); -+ return -1; -+ } -+ -+ timedout = 0; -+ -+ /* -+ * Process input from the user -+ */ -+ if (FD_ISSET(0, &read_fds)) -+ { -+ bzero(buffer, sizeof(buffer)); -+ numRead = read(fileno(stdin), -+ buffer, -+ buffer_size); -+ -+ if (numRead > 0) -+ { -+ int rc = processiSolUserInput(intf, buffer, numRead); -+ -+ if (rc) -+ { -+ if (rc < 0) -+ bShouldExit = bBmcClosedSession = 1; -+ else -+ bShouldExit = 1; -+ } -+ } -+ else -+ { -+ bShouldExit = 1; -+ } -+ } -+ -+ -+ /* -+ * Process input from the BMC -+ */ -+ else if (FD_ISSET(intf->fd, &read_fds)) -+ { -+ struct ipmi_rs * rs = intf->recv_sol(intf); -+ if (! rs) -+ { -+ bShouldExit = bBmcClosedSession = 1; -+ } -+ else -+ output(rs); -+ } -+ -+ -+ /* -+ * ERROR in select -+ */ -+ else -+ { -+ lprintf(LOG_ERR, "Error: Select returned with nothing to read"); -+ bShouldExit = 1; -+ } - } -- else if (strncmp(argv[1], "115200", 6) == 0) { -- ret = ipmi_isol_setup(intf, ISOL_BAUD_RATE_115200); -+ else -+ { -+ if ((++timedout) == 20) /* Every 10 seconds we send a keepalive */ -+ { -+ intf->keepalive(intf); -+ timedout = 0; -+ } - } -- else { -- lprintf(LOG_ERR, "ISOL - Unsupported baud rate: %s", argv[1]); -- ret = -1; -+ } -+ -+ leave_raw_mode(); -+ -+ if (bBmcClosedSession) -+ { -+ lprintf(LOG_ERR, "SOL session closed by BMC"); -+ } -+ else -+ ipmi_isol_deactivate(intf); -+ -+ return 0; -+} -+ -+/* -+ * ipmi_isol_activate -+ */ -+static int -+ipmi_isol_activate(struct ipmi_intf * intf) -+{ -+ struct ipmi_rs * rsp; -+ struct ipmi_rq req; -+ uint8_t data[6]; -+ struct isol_config_parameters params; -+ -+ if (ipmi_get_isol_info(intf, ¶ms)) -+ return -1; -+ -+ if (!(params.enabled & 0x1)) { -+ lprintf(LOG_ERR, "ISOL is not enabled!"); -+ return -1; -+ } -+ -+ /* -+ * Setup a callback so that the lanplus processing knows what -+ * to do with packets that come unexpectedly (while waiting for -+ * an ACK, perhaps. -+ */ -+ intf->session->sol_data.sol_input_handler = output; -+ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_ISOL; -+ req.msg.cmd = ACTIVATE_ISOL; -+ req.msg.data = data; -+ req.msg.data_len = 5; -+ -+ memset(data, 0, 6); -+ data[0] = 0x01; -+ data[1] = 0x00; -+ data[2] = 0x00; -+ data[3] = 0x00; -+ data[5] = 0x00; -+ -+ rsp = intf->sendrecv(intf, &req); -+ if (NULL != rsp) { -+ switch (rsp->ccode) { -+ case 0x00: -+ if (rsp->data_len == 4) { -+ break; -+ } else { -+ lprintf(LOG_ERR, "Error: Unexpected data length (%d) received " -+ "in ISOL activation response", -+ rsp->data_len); -+ return -1; -+ } -+ break; -+ case 0x80: -+ lprintf(LOG_ERR, "Info: ISOL already active on another session"); -+ return -1; -+ case 0x81: -+ lprintf(LOG_ERR, "Info: ISOL disabled"); -+ return -1; -+ case 0x82: -+ lprintf(LOG_ERR, "Info: ISOL activation limit reached"); -+ return -1; -+ default: -+ lprintf(LOG_ERR, "Error activating ISOL: %s", -+ val2str(rsp->ccode, completion_code_vals)); -+ return -1; -+ } -+ } else { -+ lprintf(LOG_ERR, "Error: No response activating ISOL"); -+ return -1; -+ } -+ -+ /* response contain 4 additional bytes : 80 01 32 ff -+ Don't know what to use them for yet... */ -+ -+ printf("[SOL Session operational. Use %c? for help]\r\n", -+ ISOL_ESCAPE_CHARACTER); -+ -+ /* -+ * At this point we are good to go with our SOL session. We -+ * need to listen to -+ * 1) STDIN for user input -+ * 2) The FD for incoming SOL packets -+ */ -+ if (ipmi_isol_red_pill(intf)) { -+ lprintf(LOG_ERR, "Error in SOL session"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static void print_isol_set_usage(void) { -+ lprintf(LOG_NOTICE, "\nISOL set parameters and values: \n"); -+ lprintf(LOG_NOTICE, " enabled true | false"); -+ lprintf(LOG_NOTICE, " privilege-level user | operator | admin | oem"); -+ lprintf(LOG_NOTICE, " bit-rate " -+ "9.6 | 19.2 | 38.4 | 57.6 | 115.2"); -+ lprintf(LOG_NOTICE, ""); -+} -+ -+static void print_isol_usage(void) { -+ lprintf(LOG_NOTICE, "ISOL Commands: info"); -+ lprintf(LOG_NOTICE, " set <parameter> <setting>"); -+ lprintf(LOG_NOTICE, " activate"); -+} -+ -+int ipmi_isol_main(struct ipmi_intf * intf, int argc, char ** argv) -+{ -+ int ret = 0; -+ -+ /* -+ * Help -+ */ -+ if (!argc || !strncmp(argv[0], "help", 4)) -+ print_isol_usage(); -+ -+ /* -+ * Info -+ */ -+ else if (!strncmp(argv[0], "info", 4)) { -+ ret = ipmi_print_isol_info(intf); -+ } -+ -+ /* -+ * Set a parameter value -+ */ -+ else if (!strncmp(argv[0], "set", 3)) { -+ if (argc < 3) { -+ print_isol_set_usage(); -+ return -1; - } -+ ret = ipmi_isol_set_param(intf, argv[1], argv[2]); -+ } -+ -+ /* -+ * Activate -+ */ -+ else if (!strncmp(argv[0], "activate", 8)) { -+ ret = ipmi_isol_activate(intf); -+ } -+ -+ else { -+ print_isol_usage(); -+ ret = -1; - } -+ - return ret; - } -diff -urN ipmitool-1.8.9.orig/lib/ipmi_isol.c.orig ipmitool-1.8.9/lib/ipmi_isol.c.orig ---- ipmitool-1.8.9.orig/lib/ipmi_isol.c.orig 1970-01-01 01:00:00.000000000 +0100 -+++ ipmitool-1.8.9/lib/ipmi_isol.c.orig 2007-02-22 08:38:56.000000000 +0000 +Index: ipmitool-1.8.11/lib/ipmi_isol.c.orig +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ipmitool-1.8.11/lib/ipmi_isol.c.orig 2009-03-22 16:48:34.661974936 +0000 @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. @@ -1149,269 +258,12 @@ diff -urN ipmitool-1.8.9.orig/lib/ipmi_isol.c.orig ipmitool-1.8.9/lib/ipmi_isol. + } + return ret; +} -diff -urN ipmitool-1.8.9.orig/src/plugins/lan/lan.c ipmitool-1.8.9/src/plugins/lan/lan.c ---- ipmitool-1.8.9.orig/src/plugins/lan/lan.c 2007-02-22 08:38:57.000000000 +0000 -+++ ipmitool-1.8.9/src/plugins/lan/lan.c 2007-12-13 10:16:57.063986495 +0000 -@@ -79,6 +79,11 @@ - static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf); - static int ipmi_lan_setup(struct ipmi_intf * intf); - static int ipmi_lan_keepalive(struct ipmi_intf * intf); -+static struct ipmi_rs * ipmi_lan_send_payload(struct ipmi_intf * intf, -+ struct ipmi_v2_payload * payload); -+static struct ipmi_rs * ipmi_lan_recv_sol(struct ipmi_intf * intf); -+static struct ipmi_rs * ipmi_lan_send_sol(struct ipmi_intf * intf, -+ struct ipmi_v2_payload * payload); - static struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req); - static int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp); - static int ipmi_lan_open(struct ipmi_intf * intf); -@@ -93,6 +98,8 @@ - close: ipmi_lan_close, - sendrecv: ipmi_lan_send_cmd, - sendrsp: ipmi_lan_send_rsp, -+ recv_sol: ipmi_lan_recv_sol, -+ send_sol: ipmi_lan_send_sol, - keepalive: ipmi_lan_keepalive, - target_addr: IPMI_BMC_SLAVE_ADDR, - }; -@@ -456,80 +463,141 @@ - memcpy(&rsp->session.id, rsp->data+x, 4); - x += 4; - -- if (intf->session->active && (rsp->session.authtype || intf->session->authtype)) -- x += 16; -- -- rsp->session.msglen = rsp->data[x++]; -- rsp->payload.ipmi_response.rq_addr = rsp->data[x++]; -- rsp->payload.ipmi_response.netfn = rsp->data[x] >> 2; -- rsp->payload.ipmi_response.rq_lun = rsp->data[x++] & 0x3; -- x++; /* checksum */ -- rsp->payload.ipmi_response.rs_addr = rsp->data[x++]; -- rsp->payload.ipmi_response.rq_seq = rsp->data[x] >> 2; -- rsp->payload.ipmi_response.rs_lun = rsp->data[x++] & 0x3; -- rsp->payload.ipmi_response.cmd = rsp->data[x++]; -- rsp->ccode = rsp->data[x++]; -- -- if (verbose > 2) -- printbuf(rsp->data, rsp->data_len, "ipmi message header"); -- -- lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header"); -- lprintf(LOG_DEBUG+1, "<< Authtype : %s", -- val2str(rsp->session.authtype, ipmi_authtype_session_vals)); -- lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx", -- (long)rsp->session.seq); -- lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx", -- (long)rsp->session.id); -- lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header"); -- lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x", -- rsp->payload.ipmi_response.rq_addr); -- lprintf(LOG_DEBUG+1, "<< NetFn : %02x", -- rsp->payload.ipmi_response.netfn); -- lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x", -- rsp->payload.ipmi_response.rq_lun); -- lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x", -- rsp->payload.ipmi_response.rs_addr); -- lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x", -- rsp->payload.ipmi_response.rq_seq); -- lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x", -- rsp->payload.ipmi_response.rs_lun); -- lprintf(LOG_DEBUG+1, "<< Command : %02x", -- rsp->payload.ipmi_response.cmd); -- lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x", -- rsp->ccode); -- -- /* now see if we have outstanding entry in request list */ -- entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq, -- rsp->payload.ipmi_response.cmd); -- if (entry) { -- lprintf(LOG_DEBUG+2, "IPMI Request Match found"); -- if ((intf->target_addr != our_address) && bridge_possible) { -- if ((rsp->data_len) && -- (rsp->payload.ipmi_response.cmd != 0x34)) { -- printbuf(&rsp->data[x], rsp->data_len-x, -- "bridge command response"); -- } -- /* bridged command: lose extra header */ -- if (rsp->payload.ipmi_response.cmd == 0x34) { -- if (rsp->data_len == 38) { -- entry->req.msg.cmd = entry->req.msg.target_cmd; -- rsp = ipmi_lan_recv_packet(intf); -- continue; -+ if (rsp->session.id == (intf->session->session_id + 0x10000000)) { -+ /* With SOL, authtype is always NONE, so we have no authcode */ -+ rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_SOL; -+ -+ rsp->session.msglen = rsp->data[x++]; -+ -+ rsp->payload.sol_packet.packet_sequence_number = -+ rsp->data[x++] & 0x0F; -+ -+ rsp->payload.sol_packet.acked_packet_number = -+ rsp->data[x++] & 0x0F; -+ -+ rsp->payload.sol_packet.accepted_character_count = -+ rsp->data[x++]; -+ -+ rsp->payload.sol_packet.is_nack = -+ rsp->data[x] & 0x40; -+ -+ rsp->payload.sol_packet.transfer_unavailable = -+ rsp->data[x] & 0x20; -+ -+ rsp->payload.sol_packet.sol_inactive = -+ rsp->data[x] & 0x10; -+ -+ rsp->payload.sol_packet.transmit_overrun = -+ rsp->data[x] & 0x08; -+ -+ rsp->payload.sol_packet.break_detected = -+ rsp->data[x++] & 0x04; -+ -+ x++; /* On ISOL there's and additional fifth byte before the data starts */ -+ -+ lprintf(LOG_DEBUG, "SOL sequence number : 0x%02x", -+ rsp->payload.sol_packet.packet_sequence_number); -+ -+ lprintf(LOG_DEBUG, "SOL acked packet : 0x%02x", -+ rsp->payload.sol_packet.acked_packet_number); -+ -+ lprintf(LOG_DEBUG, "SOL accepted char count : 0x%02x", -+ rsp->payload.sol_packet.accepted_character_count); -+ -+ lprintf(LOG_DEBUG, "SOL is nack : %s", -+ rsp->payload.sol_packet.is_nack? "true" : "false"); -+ -+ lprintf(LOG_DEBUG, "SOL xfer unavailable : %s", -+ rsp->payload.sol_packet.transfer_unavailable? "true" : "false"); -+ -+ lprintf(LOG_DEBUG, "SOL inactive : %s", -+ rsp->payload.sol_packet.sol_inactive? "true" : "false"); -+ -+ lprintf(LOG_DEBUG, "SOL transmit overrun : %s", -+ rsp->payload.sol_packet.transmit_overrun? "true" : "false"); -+ -+ lprintf(LOG_DEBUG, "SOL break detected : %s", -+ rsp->payload.sol_packet.break_detected? "true" : "false"); -+ } -+ else -+ { -+ /* Standard IPMI 1.5 packet */ -+ rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI; -+ if (intf->session->active && (rsp->session.authtype || intf->session->authtype)) -+ x += 16; -+ -+ rsp->session.msglen = rsp->data[x++]; -+ rsp->payload.ipmi_response.rq_addr = rsp->data[x++]; -+ rsp->payload.ipmi_response.netfn = rsp->data[x] >> 2; -+ rsp->payload.ipmi_response.rq_lun = rsp->data[x++] & 0x3; -+ x++; /* checksum */ -+ rsp->payload.ipmi_response.rs_addr = rsp->data[x++]; -+ rsp->payload.ipmi_response.rq_seq = rsp->data[x] >> 2; -+ rsp->payload.ipmi_response.rs_lun = rsp->data[x++] & 0x3; -+ rsp->payload.ipmi_response.cmd = rsp->data[x++]; -+ rsp->ccode = rsp->data[x++]; -+ -+ if (verbose > 2) -+ printbuf(rsp->data, rsp->data_len, "ipmi message header"); -+ -+ lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header"); -+ lprintf(LOG_DEBUG+1, "<< Authtype : %s", -+ val2str(rsp->session.authtype, ipmi_authtype_session_vals)); -+ lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx", -+ (long)rsp->session.seq); -+ lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx", -+ (long)rsp->session.id); -+ lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header"); -+ lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x", -+ rsp->payload.ipmi_response.rq_addr); -+ lprintf(LOG_DEBUG+1, "<< NetFn : %02x", -+ rsp->payload.ipmi_response.netfn); -+ lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x", -+ rsp->payload.ipmi_response.rq_lun); -+ lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x", -+ rsp->payload.ipmi_response.rs_addr); -+ lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x", -+ rsp->payload.ipmi_response.rq_seq); -+ lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x", -+ rsp->payload.ipmi_response.rs_lun); -+ lprintf(LOG_DEBUG+1, "<< Command : %02x", -+ rsp->payload.ipmi_response.cmd); -+ lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x", -+ rsp->ccode); -+ -+ /* now see if we have outstanding entry in request list */ -+ entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq, -+ rsp->payload.ipmi_response.cmd); -+ if (entry) { -+ lprintf(LOG_DEBUG+2, "IPMI Request Match found"); -+ if ((intf->target_addr != our_address) && bridge_possible) { -+ if ((rsp->data_len) && -+ (rsp->payload.ipmi_response.cmd != 0x34)) { -+ printbuf(&rsp->data[x], rsp->data_len-x, -+ "bridge command response"); -+ } -+ /* bridged command: lose extra header */ -+ if (rsp->payload.ipmi_response.cmd == 0x34) { -+ if (rsp->data_len == 38) { -+ entry->req.msg.cmd = entry->req.msg.target_cmd; -+ rsp = ipmi_lan_recv_packet(intf); -+ continue; -+ } -+ } else { -+ //x += sizeof(rsp->payload.ipmi_response); -+ if (rsp->data[x-1] != 0) -+ lprintf(LOG_DEBUG, "WARNING: Bridged " -+ "cmd ccode = 0x%02x", -+ rsp->data[x-1]); - } -- } else { -- //x += sizeof(rsp->payload.ipmi_response); -- if (rsp->data[x-1] != 0) -- lprintf(LOG_DEBUG, "WARNING: Bridged " -- "cmd ccode = 0x%02x", -- rsp->data[x-1]); - } -+ ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, -+ rsp->payload.ipmi_response.cmd); -+ } else { -+ lprintf(LOG_INFO, "IPMI Request Match NOT FOUND"); -+ rsp = ipmi_lan_recv_packet(intf); -+ continue; - } -- ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, -- rsp->payload.ipmi_response.cmd); -- } else { -- lprintf(LOG_INFO, "IPMI Request Match NOT FOUND"); -- rsp = ipmi_lan_recv_packet(intf); -- continue; - } - - break; -@@ -537,7 +605,9 @@ - - /* shift response data to start of array */ - if (rsp && rsp->data_len > x) { -- rsp->data_len -= x + 1; -+ rsp->data_len -= x; -+ if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) -+ rsp->data_len -= 1; /* We don't want the checksum */ - memmove(rsp->data, rsp->data + x, rsp->data_len); - memset(rsp->data + rsp->data_len, 0, IPMI_BUF_SIZE - rsp->data_len); - } -@@ -553,9 +623,9 @@ - * | rmcp.seq | - * | rmcp.class | - * +--------------------+ -- * | session.authtype | 9 bytes -- * | session.seq | -- * | session.id | -+ * | session.authtype | 9 bytes -+ * | session.seq | -+ * | session.id | - * +--------------------+ - * | [session.authcode] | 16 bytes (AUTHTYPE != none) - * +--------------------+ -@@ -910,6 +980,430 @@ - return 0; +Index: ipmitool-1.8.11/src/plugins/lan/lan.c +=================================================================== +--- ipmitool-1.8.11.orig/src/plugins/lan/lan.c 2009-02-25 20:38:53.000000000 +0000 ++++ ipmitool-1.8.11/src/plugins/lan/lan.c 2009-03-22 16:48:34.681976632 +0000 +@@ -1448,6 +1448,430 @@ + return rsp; } +/* @@ -1841,12 +693,3 @@ diff -urN ipmitool-1.8.9.orig/src/plugins/lan/lan.c ipmitool-1.8.9/src/plugins/l /* send a get device id command to keep session active */ static int ipmi_lan_keepalive(struct ipmi_intf * intf) -@@ -1411,6 +1905,8 @@ - - intf->abort = 1; - -+ intf->session->sol_data.sequence_number = 1; -+ - /* open port to BMC */ - memset(&s->addr, 0, sizeof(struct sockaddr_in)); - s->addr.sin_family = AF_INET; |