diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-02-20 02:12:40 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-02-20 02:12:40 +0100 |
commit | 97d6a2e491c6ed08473beb2c4bac47c5cbc1201a (patch) | |
tree | 728b931c62b22ea55a13b292f6f77930897067fd /src | |
parent | 55031e72e6c02b4ae63e9052bad1a4b40002ac18 (diff) |
Imported Upstream version 1.8.16upstream/1.8.16
Diffstat (limited to 'src')
29 files changed, 1936 insertions, 642 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 5da68bb..06b33a8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -291,6 +291,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/ipmievd.c b/src/ipmievd.c index f940579..cc1ca0f 100644 --- a/src/ipmievd.c +++ b/src/ipmievd.c @@ -29,6 +29,7 @@ * 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 #include <stdio.h> #include <fcntl.h> @@ -122,13 +123,13 @@ static int openipmi_setup(struct ipmi_event_intf * eintf); static int openipmi_wait(struct ipmi_event_intf * eintf); static int openipmi_read(struct ipmi_event_intf * eintf); static struct ipmi_event_intf openipmi_event_intf = { - name: "open", - desc: "OpenIPMI asyncronous notification of events", - prefix: "", - setup: openipmi_setup, - wait: openipmi_wait, - read: openipmi_read, - log: log_event, + .name = "open", + .desc = "OpenIPMI asyncronous notification of events", + .prefix = "", + .setup = openipmi_setup, + .wait = openipmi_wait, + .read = openipmi_read, + .log = log_event, }; #endif /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -139,13 +140,13 @@ static int selwatch_wait(struct ipmi_event_intf * eintf); static int selwatch_read(struct ipmi_event_intf * eintf); static int selwatch_check(struct ipmi_event_intf * eintf); static struct ipmi_event_intf selwatch_event_intf = { - name: "sel", - desc: "Poll SEL for notification of events", - setup: selwatch_setup, - wait: selwatch_wait, - read: selwatch_read, - check: selwatch_check, - log: log_event, + .name = "sel", + .desc = "Poll SEL for notification of events", + .setup = selwatch_setup, + .wait = selwatch_wait, + .read = selwatch_read, + .check = selwatch_check, + .log = log_event, }; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -283,7 +284,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) eintf->prefix, type, sdr->record.full->id_string, - desc ? : "", + desc ? desc : "", (evt->sel_type.standard_type.event_dir ? "Deasserted" : "Asserted"), (trigger_reading==(int)trigger_reading) ? 0 : 2, @@ -303,7 +304,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) */ lprintf(LOG_NOTICE, "%s%s sensor %s %s %s", eintf->prefix, type, - sdr->record.full->id_string, desc ? : "", + sdr->record.full->id_string, desc ? desc : "", (evt->sel_type.standard_type.event_dir ? "Deasserted" : "Asserted")); if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) { @@ -316,7 +317,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) */ lprintf(LOG_NOTICE, "%s%s sensor %s %s %s", eintf->prefix, type, - sdr->record.full->id_string, desc ? : "", + sdr->record.full->id_string, desc ? desc : "", (evt->sel_type.standard_type.event_dir ? "Deasserted" : "Asserted")); } @@ -325,7 +326,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) case SDR_RECORD_TYPE_COMPACT_SENSOR: lprintf(LOG_NOTICE, "%s%s sensor %s - %s %s", eintf->prefix, type, - sdr->record.compact->id_string, desc ? : "", + sdr->record.compact->id_string, desc ? desc : "", (evt->sel_type.standard_type.event_dir ? "Deasserted" : "Asserted")); break; @@ -333,7 +334,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) default: lprintf(LOG_NOTICE, "%s%s sensor - %s", eintf->prefix, type, - evt->sel_type.standard_type.sensor_num, desc ? : ""); + evt->sel_type.standard_type.sensor_num, desc ? desc : ""); break; } @@ -703,7 +704,6 @@ ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv) memset(pidfile, 0, 64); sprintf(pidfile, "%s%d", DEFAULT_PIDFILE, eintf->intf->devnum); - lprintf(LOG_NOTICE, "ipmievd: using pidfile %s", pidfile); for (i = 0; i < argc; i++) { if (strncasecmp(argv[i], "help", 4) == 0) { @@ -738,6 +738,8 @@ ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv) } } + lprintf(LOG_DEBUG, "ipmievd: using pidfile %s", pidfile); + /* * We need to open interface before forking daemon * so error messages are not lost to syslog and @@ -831,8 +833,8 @@ ipmievd_sel_main(struct ipmi_intf * intf, int argc, char ** argv) if (intf->session != NULL) { snprintf(eintf->prefix, - strlen((const char *)intf->session->hostname) + 3, - "%s: ", intf->session->hostname); + strlen((const char *)intf->ssn_params.hostname) + 3, + "%s: ", intf->ssn_params.hostname); } return ipmievd_main(eintf, argc, argv); diff --git a/src/ipmishell.c b/src/ipmishell.c index 4eebcd8..6cfcbe8 100644 --- a/src/ipmishell.c +++ b/src/ipmishell.c @@ -301,7 +301,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv) return (-1); } printf("Set session hostname to %s\n", - intf->session->hostname); + intf->ssn_params.hostname); } else if (strncmp(argv[0], "user", 4) == 0 || strncmp(argv[0], "username", 8) == 0) { @@ -311,7 +311,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv) return (-1); } printf("Set session username to %s\n", - intf->session->username); + intf->ssn_params.username); } else if (strncmp(argv[0], "pass", 4) == 0 || strncmp(argv[0], "password", 8) == 0) { @@ -336,7 +336,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv) return (-1); } printf("Set session authtype to %s\n", - val2str(intf->session->authtype_set, + val2str(intf->ssn_params.authtype_set, ipmi_authtype_session_vals)); } else if (strncmp(argv[0], "privlvl", 7) == 0) { @@ -354,7 +354,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv) return (-1); } printf("Set session privilege level to %s\n", - val2str(intf->session->privlvl, + val2str(intf->ssn_params.privlvl, ipmi_privlvl_vals)); } else if (strncmp(argv[0], "port", 4) == 0) { @@ -369,7 +369,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv) lprintf(LOG_ERR, "Failed to set session port."); return (-1); } - printf("Set session port to %d\n", intf->session->port); + printf("Set session port to %d\n", intf->ssn_params.port); } else if (strncmp(argv[0], "localaddr", 9) == 0) { uint8_t my_addr = 0; @@ -467,6 +467,10 @@ int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv) __argv[__argc++] = strdup(tok); if (__argv[__argc-1] == NULL) { lprintf(LOG_ERR, "ipmitool: malloc failure"); + if (fp) { + fclose(fp); + fp = NULL; + } return -1; } tmp = __argv[__argc-1]; diff --git a/src/ipmitool.c b/src/ipmitool.c index 6230e5c..164fd44 100644 --- a/src/ipmitool.c +++ b/src/ipmitool.c @@ -65,6 +65,7 @@ #include <ipmitool/ipmi_ekanalyzer.h> #include <ipmitool/ipmi_ime.h> #include <ipmitool/ipmi_dcmi.h> +#include <ipmitool/ipmi_vita.h> #ifdef HAVE_CONFIG_H # include <config.h> @@ -103,7 +104,8 @@ struct ipmi_cmd ipmitool_cmd_list[] = { { ipmi_user_main, "user", "Configure Management Controller users" }, { ipmi_channel_main, "channel", "Configure Management Controller channels" }, { ipmi_session_main, "session", "Print session information" }, - { ipmi_dcmi_main, "dcmi", "Data Center Management Interface"}, + { ipmi_dcmi_main, "dcmi", "Data Center Management Interface"}, + { ipmi_nm_main, "nm", "Node Manager Interface"}, { ipmi_sunoem_main, "sunoem", "OEM Commands for Sun servers" }, { ipmi_kontronoem_main, "kontronoem", "OEM Commands for Kontron devices"}, { ipmi_picmg_main, "picmg", "Run a PICMG/ATCA extended cmd"}, @@ -119,6 +121,7 @@ struct ipmi_cmd ipmitool_cmd_list[] = { { ipmi_hpmfwupg_main,"hpm", "Update HPM components using PICMG HPM.1 file"}, { ipmi_ekanalyzer_main,"ekanalyzer", "run FRU-Ekeying analyzer using FRU files"}, { ipmi_ime_main, "ime", "Update Intel Manageability Engine Firmware"}, + { ipmi_vita_main, "vita", "Run a VITA 46.11 extended cmd"}, { NULL }, }; diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 19b5f11..a2c48ff 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -32,8 +32,8 @@ MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_srcdir)/include -SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ -DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy +SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@ +DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb noinst_LTLIBRARIES = libintf.la libintf_la_SOURCES = ipmi_intf.c diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in index daa57d1..f38697a 100644 --- a/src/plugins/Makefile.in +++ b/src/plugins/Makefile.in @@ -284,6 +284,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -380,8 +382,8 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_srcdir)/include -SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ -DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy +SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@ +DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb noinst_LTLIBRARIES = libintf.la libintf_la_SOURCES = ipmi_intf.c libintf_la_LDFLAGS = -export-dynamic diff --git a/src/plugins/bmc/Makefile.in b/src/plugins/bmc/Makefile.in index 8c98861..6ed1ee7 100644 --- a/src/plugins/bmc/Makefile.in +++ b/src/plugins/bmc/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/dummy/Makefile.in b/src/plugins/dummy/Makefile.in index 1cd85a5..86475ba 100644 --- a/src/plugins/dummy/Makefile.in +++ b/src/plugins/dummy/Makefile.in @@ -211,6 +211,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/dummy/dummy.c b/src/plugins/dummy/dummy.c index eb2d086..8bfc4cf 100644 --- a/src/plugins/dummy/dummy.c +++ b/src/plugins/dummy/dummy.c @@ -117,7 +117,7 @@ data_write(int fd, void *data_ptr, int data_len) /* TODO - add poll() */ data_written = write(fd, data_ptr, data_len); errno_save = errno; - if (data_read > 0) { + if (data_written > 0) { data_total+= data_written; } if (errno_save != 0) { @@ -149,9 +149,6 @@ static void ipmi_dummyipmi_close(struct ipmi_intf *intf) { struct dummy_rq req; - int data_total = 0; - int data_written = 0; - int try = 0; if (intf->fd < 0) { return; } @@ -245,7 +242,7 @@ ipmi_dummyipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req) return NULL; } } - + memset(&rsp_dummy, 0, sizeof(rsp_dummy)); if (data_read(intf->fd, &rsp_dummy, sizeof(struct dummy_rs)) != 0) { return NULL; @@ -276,11 +273,11 @@ ipmi_dummyipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req) } struct ipmi_intf ipmi_dummy_intf = { - name: "dummy", - desc: "Linux DummyIPMI Interface", - open: ipmi_dummyipmi_open, - close: ipmi_dummyipmi_close, - sendrecv: ipmi_dummyipmi_send_cmd, - my_addr: IPMI_BMC_SLAVE_ADDR, - target_addr: IPMI_BMC_SLAVE_ADDR, + .name = "dummy", + .desc = "Linux DummyIPMI Interface", + .open = ipmi_dummyipmi_open, + .close = ipmi_dummyipmi_close, + .sendrecv = ipmi_dummyipmi_send_cmd, + .my_addr = IPMI_BMC_SLAVE_ADDR, + .target_addr = IPMI_BMC_SLAVE_ADDR, }; diff --git a/src/plugins/free/Makefile.in b/src/plugins/free/Makefile.in index 9b2eda0..d8eb9e6 100644 --- a/src/plugins/free/Makefile.in +++ b/src/plugins/free/Makefile.in @@ -215,6 +215,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/free/free.c b/src/plugins/free/free.c index f89925d..56c8157 100644 --- a/src/plugins/free/free.c +++ b/src/plugins/free/free.c @@ -203,12 +203,12 @@ static void ipmi_free_close(struct ipmi_intf * intf) static struct ipmi_rs * ipmi_free_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) { - u_int8_t lun = req->msg.lun; - u_int8_t cmd = req->msg.cmd; - u_int8_t netfn = req->msg.netfn; - u_int8_t rq_buf[IPMI_BUF_SIZE]; - u_int8_t rs_buf[IPMI_BUF_SIZE]; - u_int32_t rs_buf_len = IPMI_BUF_SIZE; + uint8_t lun = req->msg.lun; + uint8_t cmd = req->msg.cmd; + uint8_t netfn = req->msg.netfn; + uint8_t rq_buf[IPMI_BUF_SIZE]; + uint8_t rs_buf[IPMI_BUF_SIZE]; + uint32_t rs_buf_len = IPMI_BUF_SIZE; int32_t rs_len; static struct ipmi_rs rsp; diff --git a/src/plugins/imb/Makefile.in b/src/plugins/imb/Makefile.in index a65eca7..d1ded78 100644 --- a/src/plugins/imb/Makefile.in +++ b/src/plugins/imb/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/imb/imb.c b/src/plugins/imb/imb.c index cb97e81..0044159 100644 --- a/src/plugins/imb/imb.c +++ b/src/plugins/imb/imb.c @@ -121,11 +121,11 @@ static struct ipmi_rs * ipmi_imb_send_cmd(struct ipmi_intf * intf, struct ipmi_r } struct ipmi_intf ipmi_imb_intf = { - name: "imb", - desc: "Intel IMB Interface", - open: ipmi_imb_open, - close: ipmi_imb_close, - sendrecv: ipmi_imb_send_cmd, - target_addr: IPMI_BMC_SLAVE_ADDR, + .name = "imb", + .desc = "Intel IMB Interface", + .open = ipmi_imb_open, + .close = ipmi_imb_close, + .sendrecv = ipmi_imb_send_cmd, + .target_addr = IPMI_BMC_SLAVE_ADDR, }; diff --git a/src/plugins/imb/imbapi.c b/src/plugins/imb/imbapi.c index 37d3abe..899c47a 100644 --- a/src/plugins/imb/imbapi.c +++ b/src/plugins/imb/imbapi.c @@ -97,6 +97,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <string.h> #endif #include "imbapi.h" +#include <asm/socket.h> #ifdef SCO_UW #define NO_MACRO_ARGS 1 @@ -104,7 +105,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define IMB_DEVICE "/dev/instru/mismic" #else #define IMB_DEVICE "/dev/imb" -#define PAGESIZE EXEC_PAGESIZE +#ifndef PAGESIZE +# define PAGESIZE EXEC_PAGESIZE +#endif #endif /*Just to make the DEBUG code cleaner.*/ @@ -1981,7 +1984,7 @@ MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress ) unsigned int length = addressLength; off_t startpAddress = (off_t)startAddress; unsigned int diff; - caddr_t startvAddress; + char *startvAddress; if ((startAddress == 0) || (addressLength <= 0)) return ACCESN_ERROR; @@ -2000,13 +2003,13 @@ MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress ) startpAddress -= diff; length += diff; - if ( (startvAddress = mmap( (caddr_t)0, + if ( (startvAddress = mmap(0, length, PROT_READ, MAP_SHARED, fd, startpAddress - ) ) == (caddr_t)-1) + ) ) == MAP_FAILED) { char buf[128]; diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c index a84237e..19ba5e3 100644 --- a/src/plugins/ipmi_intf.c +++ b/src/plugins/ipmi_intf.c @@ -29,6 +29,8 @@ * 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 _GNU_SOURCE 1 #include <stdio.h> #include <stdlib.h> @@ -83,6 +85,9 @@ extern struct ipmi_intf ipmi_serial_bm_intf; #ifdef IPMI_INTF_DUMMY extern struct ipmi_intf ipmi_dummy_intf; #endif +#ifdef IPMI_INTF_USB +extern struct ipmi_intf ipmi_usb_intf; +#endif struct ipmi_intf * ipmi_intf_table[] = { #ifdef IPMI_INTF_OPEN @@ -113,6 +118,9 @@ struct ipmi_intf * ipmi_intf_table[] = { #ifdef IPMI_INTF_DUMMY &ipmi_dummy_intf, #endif +#ifdef IPMI_INTF_USB + &ipmi_usb_intf, +#endif NULL }; @@ -194,139 +202,106 @@ struct ipmi_intf * ipmi_intf_load(char * name) void ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname) { - if (intf->session == NULL || hostname == NULL) { - return; + if (intf->ssn_params.hostname != NULL) { + free(intf->ssn_params.hostname); + intf->ssn_params.hostname = NULL; } - if (intf->session->hostname != NULL) { - free(intf->session->hostname); - intf->session->hostname = NULL; + if (hostname == NULL) { + return; } - intf->session->hostname = strdup(hostname); + intf->ssn_params.hostname = strdup(hostname); } void ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username) { - if (intf->session == NULL) - return; - - memset(intf->session->username, 0, 17); + memset(intf->ssn_params.username, 0, 17); if (username == NULL) return; - memcpy(intf->session->username, username, __min(strlen(username), 16)); + memcpy(intf->ssn_params.username, username, __min(strlen(username), 16)); } void ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password) { - if (intf->session == NULL) - return; - - memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE); + memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE); if (password == NULL) { - intf->session->password = 0; + intf->ssn_params.password = 0; return; } - intf->session->password = 1; - memcpy(intf->session->authcode, password, + intf->ssn_params.password = 1; + memcpy(intf->ssn_params.authcode_set, password, __min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE)); } void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level) { - if (intf->session == NULL) - return; - - intf->session->privlvl = level; + intf->ssn_params.privlvl = level; } void ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit) { - if (intf->session == NULL) - return; - - intf->session->v2_data.lookupbit = lookupbit; + intf->ssn_params.lookupbit = lookupbit; } void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id) { - if (intf->session == NULL) - return; - - intf->session->cipher_suite_id = cipher_suite_id; + intf->ssn_params.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; + intf->ssn_params.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); + memset(intf->ssn_params.kg, 0, IPMI_KG_BUFFER_SIZE); if (kgkey == NULL) return; - memcpy(intf->session->v2_data.kg, kgkey, + memcpy(intf->ssn_params.kg, kgkey, __min(strlen(kgkey), IPMI_KG_BUFFER_SIZE)); } void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port) { - if (intf->session == NULL) - return; - - intf->session->port = port; + intf->ssn_params.port = port; } void ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype) { - if (intf->session == NULL) - return; - /* clear password field if authtype NONE specified */ if (authtype == IPMI_SESSION_AUTHTYPE_NONE) { - memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE); - intf->session->password = 0; + memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE); + intf->ssn_params.password = 0; } - intf->session->authtype_set = authtype; + intf->ssn_params.authtype_set = authtype; } void ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout) { - if (intf->session == NULL) - return; - - intf->session->timeout = timeout; + intf->ssn_params.timeout = timeout; } void ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry) { - if (intf->session == NULL) - return; - - intf->session->retry = retry; + intf->ssn_params.retry = retry; } void @@ -335,10 +310,7 @@ ipmi_intf_session_cleanup(struct ipmi_intf *intf) if (intf->session == NULL) { return; } - if (intf->session->hostname != NULL) { - free(intf->session->hostname); - intf->session->hostname = NULL; - } + free(intf->session); intf->session = NULL; } @@ -347,27 +319,27 @@ void ipmi_cleanup(struct ipmi_intf * intf) { ipmi_sdr_list_empty(intf); + ipmi_intf_session_set_hostname(intf, NULL); } #if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS) int ipmi_intf_socket_connect(struct ipmi_intf * intf) { - struct ipmi_session *session; + struct ipmi_session_params *params; struct sockaddr_storage addr; struct addrinfo hints; struct addrinfo *rp0 = NULL, *rp; char service[NI_MAXSERV]; - int rc; - if (!intf || intf->session == NULL) { + if (!intf) { return -1; } - session = intf->session; + params = &intf->ssn_params; - if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) { + if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) { lprintf(LOG_ERR, "No hostname specified!"); return -1; } @@ -375,27 +347,26 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf) /* open port to BMC */ memset(&addr, 0, sizeof(addr)); - sprintf(service, "%d", session->port); + sprintf(service, "%d", params->port); /* Obtain address(es) matching host/port */ memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_family = intf->ai_family; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */ hints.ai_protocol = IPPROTO_UDP; /* */ - if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) { + if (getaddrinfo(params->hostname, service, &hints, &rp0) != 0) { lprintf(LOG_ERR, "Address lookup for %s failed", - session->hostname); + params->hostname); return -1; } /* getaddrinfo() returns a list of address structures. * Try each address until we successfully connect(2). * If socket(2) (or connect(2)) fails, we (close the socket - * and) try the next address. + * and) try the next address. */ - session->ai_family = AF_UNSPEC; for (rp = rp0; rp != NULL; rp = rp->ai_next) { /* We are only interested in IPv4 and IPv6 */ if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) { @@ -409,9 +380,7 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf) if (rp->ai_family == AF_INET) { if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { - memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); - session->addrlen = rp->ai_addrlen; - session->ai_family = rp->ai_family; + hints.ai_family = rp->ai_family; break; /* Success */ } } else if (rp->ai_family == AF_INET6) { @@ -423,14 +392,12 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf) if (addr6->sin6_scope_id != 0) { len = sizeof(struct sockaddr_in6); if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { - lprintf(LOG_DEBUG, "Trying address: %s scope=%d", - hbuf, + lprintf(LOG_DEBUG, "Trying address: %s scope=%d", + hbuf, addr6->sin6_scope_id); } if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { - memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); - session->addrlen = rp->ai_addrlen; - session->ai_family = rp->ai_family; + hints.ai_family = rp->ai_family; break; /* Success */ } } else { @@ -440,7 +407,7 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf) if (getifaddrs(&ifaddrs) < 0) { lprintf(LOG_ERR, "Interface address lookup for %s failed", - session->hostname); + params->hostname); break; } @@ -461,44 +428,42 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf) } len = sizeof(struct sockaddr_in6); if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { - lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d", - ifa->ifa_name != NULL ? ifa->ifa_name : "???", - hbuf, + lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d", + ifa->ifa_name != NULL ? ifa->ifa_name : "???", + hbuf, tmp6->sin6_scope_id); } if (tmp6->sin6_scope_id != 0) { addr6->sin6_scope_id = tmp6->sin6_scope_id; } else { - /* - * No scope information in interface address information + /* + * No scope information in interface address information * On some OS'es, getifaddrs() is returning out the 'kernel' representation * of scoped addresses which stores the scope in the 3rd and 4th * byte. See also this page: * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html */ if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr) - && (tmp6->sin6_addr.s6_addr16[1] != 0)) { - addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr16[1]); + && (tmp6->sin6_addr.s6_addr[1] != 0)) { + addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr[1]); } } /* OK, now try to connect with the scope id from this interface address */ if (addr6->sin6_scope_id != 0) { if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { - memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); - session->addrlen = rp->ai_addrlen; - session->ai_family = rp->ai_family; + hints.ai_family = rp->ai_family; lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id); break; /* Success */ } - } + } } } freeifaddrs(ifaddrs); } } - if (session->ai_family != AF_UNSPEC) { + if (hints.ai_family != AF_UNSPEC) { break; } close(intf->fd); diff --git a/src/plugins/lan/Makefile.in b/src/plugins/lan/Makefile.in index fc48fe4..9d1ce80 100644 --- a/src/plugins/lan/Makefile.in +++ b/src/plugins/lan/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/lan/lan.c b/src/plugins/lan/lan.c index dd90706..14730d3 100644 --- a/src/plugins/lan/lan.c +++ b/src/plugins/lan/lan.c @@ -29,12 +29,15 @@ * 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 _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <inttypes.h> #include <string.h> +#include <sys/time.h> #include <sys/types.h> +#include <sys/select.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -100,19 +103,19 @@ static void ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size static void ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size); struct ipmi_intf ipmi_lan_intf = { - name: "lan", - desc: "IPMI v1.5 LAN Interface", - setup: ipmi_lan_setup, - open: ipmi_lan_open, - 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, - set_max_request_data_size: ipmi_lan_set_max_rq_data_size, - set_max_response_data_size: ipmi_lan_set_max_rp_data_size, - target_addr: IPMI_BMC_SLAVE_ADDR, + .name = "lan", + .desc = "IPMI v1.5 LAN Interface", + .setup = ipmi_lan_setup, + .open = ipmi_lan_open, + .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, + .set_max_request_data_size = ipmi_lan_set_max_rq_data_size, + .set_max_response_data_size = ipmi_lan_set_max_rp_data_size, + .target_addr = IPMI_BMC_SLAVE_ADDR, }; static struct ipmi_rq_entry * @@ -214,6 +217,7 @@ ipmi_req_clear_entries(void) } } ipmi_req_entries = NULL; + ipmi_req_entries_tail = NULL; } static int @@ -248,7 +252,8 @@ static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf) { static struct ipmi_rs rsp; - fd_set read_set, err_set; + fd_set read_set; + fd_set err_set; struct timeval tmout; int ret; @@ -258,7 +263,7 @@ ipmi_lan_recv_packet(struct ipmi_intf * intf) FD_ZERO(&err_set); FD_SET(intf->fd, &err_set); - tmout.tv_sec = intf->session->timeout; + tmout.tv_sec = intf->ssn_params.timeout; tmout.tv_usec = 0; ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); @@ -284,7 +289,7 @@ ipmi_lan_recv_packet(struct ipmi_intf * intf) FD_ZERO(&err_set); FD_SET(intf->fd, &err_set); - tmout.tv_sec = intf->session->timeout; + tmout.tv_sec = intf->ssn_params.timeout; tmout.tv_usec = 0; ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); @@ -813,7 +818,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req, int isRetry) } /* ipmi message header */ - msg[len++] = intf->target_addr; + msg[len++] = entry->bridging_level ? intf->target_addr : IPMI_BMC_SLAVE_ADDR; msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3); tmp = len - cs; msg[len++] = ipmi_csum(msg+cs, tmp); @@ -951,7 +956,7 @@ ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) break; usleep(5000); - if (++try >= intf->session->retry) { + if (++try >= intf->ssn_params.retry) { lprintf(LOG_DEBUG, " No response from remote controller"); break; } @@ -1301,7 +1306,7 @@ ipmi_lan_send_sol_payload(struct ipmi_intf * intf, } usleep(5000); - if (++try >= intf->session->retry) { + if (++try >= intf->ssn_params.retry) { lprintf(LOG_DEBUG, " No response from remote controller"); break; } @@ -1548,10 +1553,12 @@ static int ipmi_lan_keepalive(struct ipmi_intf * intf) { struct ipmi_rs * rsp; - struct ipmi_rq req = { msg: { - netfn: IPMI_NETFN_APP, - cmd: 1, - }}; + struct ipmi_rq req = { + .msg = { + .netfn = IPMI_NETFN_APP, + .cmd = 1, + } + }; if (!intf->opened) return 0; @@ -1574,10 +1581,11 @@ ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf) struct ipmi_rs * rsp; struct ipmi_rq req; struct ipmi_session * s = intf->session; + struct ipmi_session_params *p = &intf->ssn_params; uint8_t msg_data[2]; msg_data[0] = IPMI_LAN_CHANNEL_E; - msg_data[1] = s->privlvl; + msg_data[1] = p->privlvl; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; @@ -1628,44 +1636,44 @@ ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf) s->authstatus = rsp->data[2]; - if (s->password && - (s->authtype_set == 0 || - s->authtype_set == IPMI_SESSION_AUTHTYPE_MD5) && + if (p->password && + (p->authtype_set == 0 || + p->authtype_set == IPMI_SESSION_AUTHTYPE_MD5) && (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5)) { s->authtype = IPMI_SESSION_AUTHTYPE_MD5; } - else if (s->password && - (s->authtype_set == 0 || - s->authtype_set == IPMI_SESSION_AUTHTYPE_MD2) && + else if (p->password && + (p->authtype_set == 0 || + p->authtype_set == IPMI_SESSION_AUTHTYPE_MD2) && (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2)) { s->authtype = IPMI_SESSION_AUTHTYPE_MD2; } - else if (s->password && - (s->authtype_set == 0 || - s->authtype_set == IPMI_SESSION_AUTHTYPE_PASSWORD) && + else if (p->password && + (p->authtype_set == 0 || + p->authtype_set == IPMI_SESSION_AUTHTYPE_PASSWORD) && (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD)) { s->authtype = IPMI_SESSION_AUTHTYPE_PASSWORD; } - else if (s->password && - (s->authtype_set == 0 || - s->authtype_set == IPMI_SESSION_AUTHTYPE_OEM) && + else if (p->password && + (p->authtype_set == 0 || + p->authtype_set == IPMI_SESSION_AUTHTYPE_OEM) && (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM)) { s->authtype = IPMI_SESSION_AUTHTYPE_OEM; } - else if ((s->authtype_set == 0 || - s->authtype_set == IPMI_SESSION_AUTHTYPE_NONE) && + else if ((p->authtype_set == 0 || + p->authtype_set == IPMI_SESSION_AUTHTYPE_NONE) && (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE)) { s->authtype = IPMI_SESSION_AUTHTYPE_NONE; } else { - if (!(rsp->data[1] & 1<<s->authtype_set)) + if (!(rsp->data[1] & 1<<p->authtype_set)) lprintf(LOG_ERR, "Authentication type %s not supported", - val2str(s->authtype_set, ipmi_authtype_session_vals)); + val2str(p->authtype_set, ipmi_authtype_session_vals)); else lprintf(LOG_ERR, "No supported authtypes found"); @@ -1692,7 +1700,7 @@ ipmi_get_session_challenge_cmd(struct ipmi_intf * intf) memset(msg_data, 0, 17); msg_data[0] = s->authtype; - memcpy(msg_data+1, s->username, 16); + memcpy(msg_data+1, intf->ssn_params.username, 16); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; @@ -1749,12 +1757,12 @@ ipmi_activate_session_cmd(struct ipmi_intf * intf) req.msg.cmd = 0x3a; msg_data[0] = s->authtype; - msg_data[1] = s->privlvl; + msg_data[1] = intf->ssn_params.privlvl; /* supermicro oem authentication hack */ if (ipmi_oem_active(intf, "supermicro")) { uint8_t * special = ipmi_auth_special(s); - memcpy(s->authcode, special, 16); + memcpy(intf->session->authcode, special, 16); memset(msg_data + 2, 0, 16); lprintf(LOG_DEBUG, " OEM Auth : %s", buf2str(special, 16)); @@ -1831,8 +1839,6 @@ ipmi_activate_session_cmd(struct ipmi_intf * intf) return -1; } - bridge_possible = 1; - lprintf(LOG_DEBUG, "\nSession Activated"); lprintf(LOG_DEBUG, " Auth Type : %s", val2str(rsp->data[0], ipmi_authtype_session_vals)); @@ -1853,7 +1859,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) { struct ipmi_rs * rsp; struct ipmi_rq req; - uint8_t privlvl = intf->session->privlvl; + uint8_t privlvl = intf->ssn_params.privlvl; uint8_t backup_bridge_possible = bridge_possible; if (privlvl <= IPMI_SESSION_PRIV_USER) @@ -1986,23 +1992,27 @@ ipmi_lan_activate_session(struct ipmi_intf * intf) rc = ipmi_set_session_privlvl_cmd(intf); if (rc < 0) - goto fail; + goto close_fail; return 0; + close_fail: + ipmi_close_session_cmd(intf); fail: lprintf(LOG_ERR, "Error: Unable to establish LAN session"); return -1; } -static void +void ipmi_lan_close(struct ipmi_intf * intf) { - if (intf->abort == 0) + if (!intf->abort && intf->session) ipmi_close_session_cmd(intf); - if (intf->fd >= 0) + if (intf->fd >= 0) { close(intf->fd); + intf->fd = -1; + } ipmi_req_clear_entries(); ipmi_intf_session_cleanup(intf); @@ -2016,69 +2026,78 @@ ipmi_lan_open(struct ipmi_intf * intf) { int rc; struct ipmi_session *s; + struct ipmi_session_params *p; - if (intf == NULL || intf->session == NULL) + if (intf == NULL || intf->opened) return -1; - s = intf->session; - - if (s->port == 0) - s->port = IPMI_LAN_PORT; - if (s->privlvl == 0) - s->privlvl = IPMI_SESSION_PRIV_ADMIN; - if (s->timeout == 0) - s->timeout = IPMI_LAN_TIMEOUT; - if (s->retry == 0) - s->retry = IPMI_LAN_RETRY; - if (s->hostname == NULL || strlen((const char *)s->hostname) == 0) { + s = intf->session; + p = &intf->ssn_params; + + if (p->port == 0) + p->port = IPMI_LAN_PORT; + if (p->privlvl == 0) + p->privlvl = IPMI_SESSION_PRIV_ADMIN; + if (p->timeout == 0) + p->timeout = IPMI_LAN_TIMEOUT; + if (p->retry == 0) + p->retry = IPMI_LAN_RETRY; + + if (p->hostname == NULL || strlen((const char *)p->hostname) == 0) { lprintf(LOG_ERR, "No hostname specified!"); return -1; } - intf->abort = 1; - - intf->session->sol_data.sequence_number = 1; - - if (ipmi_intf_socket_connect (intf) == -1) { + if (ipmi_intf_socket_connect(intf) == -1) { lprintf(LOG_ERR, "Could not open socket!"); return -1; } - if (intf->fd < 0) { - lperror(LOG_ERR, "Connect to %s failed", - s->hostname); - intf->close(intf); - return -1; + s = (struct ipmi_session *)malloc(sizeof(struct ipmi_session)); + if (!s) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + goto fail; } intf->opened = 1; + intf->abort = 1; + + intf->session = s; + + memset(s, 0, sizeof(struct ipmi_session)); + s->sol_data.sequence_number = 1; + s->timeout = p->timeout; + memcpy(&s->authcode, &p->authcode_set, sizeof(s->authcode)); + s->addrlen = sizeof(s->addr); + if (getsockname(intf->fd, (struct sockaddr *)&s->addr, &s->addrlen)) { + goto fail; + } /* try to open session */ rc = ipmi_lan_activate_session(intf); if (rc < 0) { - intf->close(intf); - intf->opened = 0; - return -1; + goto fail; } - intf->manufacturer_id = ipmi_get_oem(intf); - /* automatically detect interface request and response sizes */ hpm2_detect_max_payload_size(intf); + /* set manufactirer OEM id */ + intf->manufacturer_id = ipmi_get_oem(intf); + + /* now allow bridging */ + bridge_possible = 1; return intf->fd; + + fail: + lprintf(LOG_ERR, "Error: Unable to establish IPMI v1.5 / RMCP session"); + intf->close(intf); + return -1; } static int ipmi_lan_setup(struct ipmi_intf * intf) { - intf->session = malloc(sizeof(struct ipmi_session)); - if (intf->session == NULL) { - lprintf(LOG_ERR, "ipmitool: malloc failure"); - return -1; - } - memset(intf->session, 0, sizeof(struct ipmi_session)); - /* setup default LAN maximum request and response sizes */ intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE; intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE; diff --git a/src/plugins/lanplus/Makefile.in b/src/plugins/lanplus/Makefile.in index 09458aa..eef233d 100644 --- a/src/plugins/lanplus/Makefile.in +++ b/src/plugins/lanplus/Makefile.in @@ -242,6 +242,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c index 0bff5b2..8776212 100644 --- a/src/plugins/lanplus/lanplus.c +++ b/src/plugins/lanplus/lanplus.c @@ -29,12 +29,15 @@ * 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 _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <inttypes.h> #include <string.h> +#include <sys/time.h> #include <sys/types.h> +#include <sys/select.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -126,18 +129,18 @@ static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t siz static uint8_t bridgePossible = 0; struct ipmi_intf ipmi_lanplus_intf = { - name: "lanplus", - desc: "IPMI v2.0 RMCP+ LAN Interface", - setup: ipmi_lanplus_setup, - open: ipmi_lanplus_open, - close: ipmi_lanplus_close, - sendrecv: ipmi_lanplus_send_ipmi_cmd, - recv_sol: ipmi_lanplus_recv_sol, - send_sol: ipmi_lanplus_send_sol, - keepalive: ipmi_lanplus_keepalive, - set_max_request_data_size: ipmi_lanp_set_max_rq_data_size, - set_max_response_data_size: ipmi_lanp_set_max_rp_data_size, - target_addr: IPMI_BMC_SLAVE_ADDR, + .name = "lanplus", + .desc = "IPMI v2.0 RMCP+ LAN Interface", + .setup = ipmi_lanplus_setup, + .open = ipmi_lanplus_open, + .close = ipmi_lanplus_close, + .sendrecv = ipmi_lanplus_send_ipmi_cmd, + .recv_sol = ipmi_lanplus_recv_sol, + .send_sol = ipmi_lanplus_send_sol, + .keepalive = ipmi_lanplus_keepalive, + .set_max_request_data_size = ipmi_lanp_set_max_rq_data_size, + .set_max_response_data_size = ipmi_lanp_set_max_rp_data_size, + .target_addr = IPMI_BMC_SLAVE_ADDR, }; @@ -383,6 +386,9 @@ ipmi_req_clear_entries(void) free(e); e = p; } + + ipmi_req_entries = NULL; + ipmi_req_entries_tail = NULL; } @@ -595,7 +601,7 @@ ipmiv2_lan_ping(struct ipmi_intf * intf) /** * - * ipmi_lan_poll_recv + * ipmi_lan_poll_single * * Receive whatever comes back. Ignore received packets that don't correspond * to a request we've sent. @@ -603,99 +609,88 @@ ipmiv2_lan_ping(struct ipmi_intf * intf) * Returns: the ipmi_rs packet describing the/a reponse we expect. */ static struct ipmi_rs * -ipmi_lan_poll_recv(struct ipmi_intf * intf) +ipmi_lan_poll_single(struct ipmi_intf * intf) { - struct rmcp_hdr rmcp_rsp; + struct rmcp_hdr * rmcp_rsp; struct ipmi_rs * rsp; struct ipmi_session * session = intf->session; int offset, rv; uint16_t payload_size; - uint8_t ourAddress = intf->my_addr; - - if (ourAddress == 0) { - ourAddress = IPMI_BMC_SLAVE_ADDR; - } + /* receive packet */ rsp = ipmi_lan_recv_packet(intf); - /* - * Not positive why we're looping. Do we sometimes get stuff we don't - * expect? - */ - while (rsp != NULL) { - - /* parse response headers */ - memcpy(&rmcp_rsp, rsp->data, 4); - - if (rmcp_rsp.class == RMCP_CLASS_ASF) { - /* might be ping response packet */ - rv = ipmi_handle_pong(intf, rsp); - return (rv <= 0) ? NULL : rsp; - } + /* check if no packet has come */ + if (rsp == NULL) { + return NULL; + } - if (rmcp_rsp.class != RMCP_CLASS_IPMI) { - lprintf(LOG_DEBUG, "Invalid RMCP class: %x", - rmcp_rsp.class); - rsp = ipmi_lan_recv_packet(intf); - continue; - } + /* parse response headers */ + rmcp_rsp = (struct rmcp_hdr *)rsp->data; + if (rmcp_rsp->class == RMCP_CLASS_ASF) { + /* might be ping response packet */ + rv = ipmi_handle_pong(intf, rsp); + return (rv <= 0) ? NULL : rsp; + } - /* - * The authtype / payload type determines what we are receiving - */ - offset = 4; - - - /*-------------------------------------------------------------------- - * - * The current packet could be one of several things: - * - * 1) An IPMI 1.5 packet (the response to our GET CHANNEL - * AUTHENTICATION CAPABILITIES request) - * 2) An RMCP+ message with an IPMI reponse payload - * 3) AN RMCP+ open session response - * 4) An RAKP-2 message (response to an RAKP 1 message) - * 5) An RAKP-4 message (response to an RAKP 3 message) - * 6) A Serial Over LAN packet - * 7) An Invalid packet (one that doesn't match a request) - * ------------------------------------------------------------------- - */ + if (rmcp_rsp->class != RMCP_CLASS_IPMI) { + lprintf(LOG_DEBUG, "Invalid RMCP class: %x", rmcp_rsp->class); + /* read one more packet */ + return (struct ipmi_rs *)1; + } - read_session_data(rsp, &offset, intf->session); + /* + * The authtype / payload type determines what we are receiving + */ + offset = 4; - if (lanplus_has_valid_auth_code(rsp, intf->session) == 0) - { - lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!"); - rsp = ipmi_lan_recv_packet(intf); - assert(0); - //continue; - } + /*-------------------------------------------------------------------- + * + * The current packet could be one of several things: + * + * 1) An IPMI 1.5 packet (the response to our GET CHANNEL + * AUTHENTICATION CAPABILITIES request) + * 2) An RMCP+ message with an IPMI reponse payload + * 3) AN RMCP+ open session response + * 4) An RAKP-2 message (response to an RAKP 1 message) + * 5) An RAKP-4 message (response to an RAKP 3 message) + * 6) A Serial Over LAN packet + * 7) An Invalid packet (one that doesn't match a request) + * ------------------------------------------------------------------- + */ - if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && - (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && - (rsp->session.bEncrypted)) + read_session_data(rsp, &offset, intf->session); - { - lanplus_decrypt_payload(session->v2_data.crypt_alg, - session->v2_data.k2, - rsp->data + offset, - rsp->session.msglen, - rsp->data + offset, - &payload_size); - } - else - payload_size = rsp->session.msglen; + if (lanplus_has_valid_auth_code(rsp, intf->session) == 0) { + lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!"); + return NULL; + } + if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && + (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && + (rsp->session.bEncrypted)) { + lanplus_decrypt_payload(session->v2_data.crypt_alg, + session->v2_data.k2, + rsp->data + offset, + rsp->session.msglen, + rsp->data + offset, + &payload_size); + } else { + payload_size = rsp->session.msglen; + } - /* - * Handle IPMI responses (case #1 and #2) -- all IPMI reponses - */ - if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) - { - struct ipmi_rq_entry * entry; - int payload_start = offset; - int extra_data_length; + /* + * Handle IPMI responses (case #1 and #2) -- all IPMI reponses + */ + if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) { + struct ipmi_rq_entry * entry; + int payload_start = offset; + int extra_data_length; + int loop = 1; + + while (loop--) { + /* fill-in response data */ read_ipmi_response(rsp, &offset); lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header"); @@ -731,159 +726,154 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf) entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq, rsp->payload.ipmi_response.cmd); - if (entry != NULL) { - lprintf(LOG_DEBUG+2, "IPMI Request Match found"); - if ( intf->target_addr != intf->my_addr && - bridgePossible && - rsp->data_len && - rsp->payload.ipmi_response.cmd == 0x34 && - (rsp->payload.ipmi_response.netfn == 0x06 || - rsp->payload.ipmi_response.netfn == 0x07) && - rsp->payload.ipmi_response.rs_lun == 0 ) - { - /* Check completion code */ - if (rsp->data[offset-1] == 0) - { - lprintf(LOG_DEBUG, "Bridged command answer," - " waiting for next answer... "); - ipmi_req_remove_entry( - rsp->payload.ipmi_response.rq_seq, - rsp->payload.ipmi_response.cmd); - return ipmi_lan_poll_recv(intf); - } - else - { - lprintf(LOG_DEBUG, "WARNING: Bridged " - "cmd ccode = 0x%02x", - rsp->data[offset-1]); + if (entry == NULL) { + lprintf(LOG_INFO, "IPMI Request Match NOT FOUND"); + /* read one more packet */ + return (struct ipmi_rs *)1; + }; + + uint8_t target_cmd = entry->req.msg.target_cmd; + + lprintf(LOG_DEBUG+2, "IPMI Request Match found"); + + if (entry->bridging_level) { + /* Check completion code */ + if (rsp->ccode) { + lprintf(LOG_DEBUG, "WARNING: Bridged " + "cmd ccode = 0x%02x", rsp->ccode); + } else { + /* decrement bridging level */ + entry->bridging_level--; + if (!entry->bridging_level) { + entry->req.msg.cmd = entry->req.msg.target_cmd; } - if (rsp->data_len && - rsp->payload.ipmi_response.cmd == 0x34) { - memcpy(rsp->data, &rsp->data[offset], - (rsp->data_len-offset)); - if (verbose > 2) - printbuf( &rsp->data[offset], - (rsp->data_len-offset), - "bridge command response"); + /* check if bridged response is embedded */ + if (payload_size > 8) { + printbuf(&rsp->data[offset], (rsp->data_len-offset-1), + "bridge command response"); + /* + * decrement payload size + * (cks2 for outer Send Message) + */ + payload_size--; + + /* + * need to make a loop for embedded bridged response + */ + loop++; + } else { + lprintf(LOG_DEBUG, "Bridged command answer," + " waiting for next answer... "); + /* read one more packet */ + return (struct ipmi_rs *)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; } + /* Remove request entry */ + ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, + rsp->payload.ipmi_response.cmd); + /* * Good packet. Shift response data to start of array. * rsp->data becomes the variable length IPMI response data * rsp->data_len becomes the length of that data */ extra_data_length = payload_size - (offset - payload_start) - 1; - if (rsp != NULL && extra_data_length) - { + if (extra_data_length) { rsp->data_len = extra_data_length; memmove(rsp->data, rsp->data + offset, extra_data_length); - } - else + } else { rsp->data_len = 0; - - break; + } } - - - /* - * Open Response - */ - else if (rsp->session.payloadtype == - IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE) - { - if (session->v2_data.session_state != - LANPLUS_STATE_OPEN_SESSION_SENT) - { - lprintf(LOG_ERR, "Error: Received an Unexpected Open Session " + /* + * Open Response + */ + } else if (rsp->session.payloadtype == + IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE) { + if (session->v2_data.session_state != + LANPLUS_STATE_OPEN_SESSION_SENT) { + lprintf(LOG_ERR, "Error: Received an Unexpected Open Session " "Response"); - rsp = ipmi_lan_recv_packet(intf); - continue; - } - - read_open_session_response(rsp, offset); - break; + /* read one more packet */ + return (struct ipmi_rs *)1; } - - - /* - * RAKP 2 - */ - else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2) - { - if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT) - { - lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message"); - rsp = ipmi_lan_recv_packet(intf); - continue; - } - - read_rakp2_message(rsp, offset, session->v2_data.auth_alg); - break; + read_open_session_response(rsp, offset); + /* + * RAKP 2 + */ + } else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2) { + if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT) { + lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message"); + /* read one more packet */ + return (struct ipmi_rs *)1; } - - - /* - * RAKP 4 - */ - else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4) - { - if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT) - { - lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message"); - rsp = ipmi_lan_recv_packet(intf); - continue; - } - - read_rakp4_message(rsp, offset, session->v2_data.auth_alg); - break; + read_rakp2_message(rsp, offset, session->v2_data.auth_alg); + /* + * RAKP 4 + */ + } else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4) { + if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT) { + lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message"); + /* read one more packet */ + return (struct ipmi_rs *)1; } + read_rakp4_message(rsp, offset, session->v2_data.auth_alg); + /* + * SOL + */ + } else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) { + int payload_start = offset; + int extra_data_length; + + if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) { + lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet"); + /* read one more packet */ + return (struct ipmi_rs *)1; + } + read_sol_packet(rsp, &offset); + extra_data_length = payload_size - (offset - payload_start); + if (rsp && extra_data_length) { + rsp->data_len = extra_data_length; + memmove(rsp->data, rsp->data + offset, extra_data_length); + } else { + rsp->data_len = 0; + } + /* + * Unknown Payload type + */ + } else { + lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x", + rsp->session.payloadtype); + /* read one more packet */ + return (struct ipmi_rs *)1; + } + return rsp; +} - /* - * SOL - */ - else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) - { - int payload_start = offset; - int extra_data_length; - - if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) - { - lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet"); - rsp = ipmi_lan_recv_packet(intf); - continue; - } - read_sol_packet(rsp, &offset); - extra_data_length = payload_size - (offset - payload_start); - if (rsp && extra_data_length) - { - rsp->data_len = extra_data_length; - memmove(rsp->data, rsp->data + offset, extra_data_length); - } - else - rsp->data_len = 0; - break; - } +/** + * + * ipmi_lan_poll_recv + * + * Receive whatever comes back. Ignore received packets that don't correspond + * to a request we've sent. + * + * Returns: the ipmi_rs packet describing the/a reponse we expect. + */ +static struct ipmi_rs * +ipmi_lan_poll_recv(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; - else - { - lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x", - rsp->session.payloadtype); - assert(0); - } - } + do { + /* poll single packet */ + rsp = ipmi_lan_poll_single(intf); + } while (rsp == (struct ipmi_rs *) 1); return rsp; } @@ -1406,7 +1396,7 @@ void getIpmiPayloadWireRep( tmp = len - cs; msg[len++] = ipmi_csum(msg+cs, tmp); cs3 = len; - msg[len++] = intf->my_addr; + msg[len++] = IPMI_REMOTE_SWID; msg[len++] = curr_seq << 2; msg[len++] = 0x34; /* Send Message rqst */ #if 0 /* From lan.c example */ @@ -1429,7 +1419,10 @@ void getIpmiPayloadWireRep( bridgePossible); /* rsAddr */ - msg[len++] = intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */ + if (bridgedRequest) + msg[len++] = intf->target_addr; + else + msg[len++] = IPMI_BMC_SLAVE_ADDR; /* net Fn */ msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3); @@ -1440,7 +1433,7 @@ void getIpmiPayloadWireRep( cs = len; /* rqAddr */ - if (!bridgedRequest) + if (bridgedRequest < 2) msg[len++] = IPMI_REMOTE_SWID; else /* Bridged message */ msg[len++] = intf->my_addr; @@ -1690,7 +1683,7 @@ ipmi_lanplus_build_v2x_msg( curr_seq); break; - case IPMI_PAYLOAD_TYPE_SOL: + case IPMI_PAYLOAD_TYPE_SOL: getSolPayloadWireRep(intf, msg + IPMI_LANPLUS_OFFSET_PAYLOAD, payload); @@ -1890,26 +1883,26 @@ ipmi_lanplus_build_v2x_ipmi_cmd( /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */ - if ((intf->target_addr == intf->my_addr) || (!bridgePossible)) - { - entry = ipmi_req_add_entry(intf, req, curr_seq); - } - else /* it's a bridge command */ - { - unsigned char backup_cmd; - - /* Add entry for cmd */ - entry = ipmi_req_add_entry(intf, req, curr_seq); - - if(entry) - { - /* Add entry for bridge cmd */ - backup_cmd = req->msg.cmd; - req->msg.cmd = 0x34; - entry = ipmi_req_add_entry(intf, req, curr_seq); - req->msg.cmd = backup_cmd; - } - } + if ((intf->target_addr == intf->my_addr) || (!bridgePossible)) { + entry = ipmi_req_add_entry(intf, req, curr_seq); + /* it's a bridge command */ + } else { + unsigned char backup_cmd; + + /* Add entry for cmd */ + entry = ipmi_req_add_entry(intf, req, curr_seq); + + if (entry) { + entry->req.msg.target_cmd = entry->req.msg.cmd; + entry->req.msg.cmd = 0x34; + + if (intf->transit_addr && + intf->transit_addr != intf->my_addr) + entry->bridging_level = 2; + else + entry->bridging_level = 1; + } + } if (entry == NULL) return NULL; @@ -2125,7 +2118,7 @@ ipmi_lanplus_send_payload( * so it will only be valid after the open completes. */ saved_timeout = session->timeout; - while (try < session->retry) { + while (try < intf->ssn_params.retry) { //ltime = time(NULL); if (xmit) { @@ -2263,16 +2256,16 @@ ipmi_lanplus_send_payload( case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT; /* not retryable for timeouts, force no retry */ - try = session->retry; + try = intf->ssn_params.retry; break; case IPMI_PAYLOAD_TYPE_RAKP_1: session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT; /* not retryable for timeouts, force no retry */ - try = session->retry; + try = intf->ssn_params.retry; break; case IPMI_PAYLOAD_TYPE_RAKP_3: /* not retryable for timeouts, force no retry */ - try = session->retry; + try = intf->ssn_params.retry; session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT; break; } @@ -2574,7 +2567,7 @@ ack_sol_packet( { struct ipmi_v2_payload ack; - bzero(&ack, sizeof(struct ipmi_v2_payload)); + memset(&ack, 0, sizeof(struct ipmi_v2_payload)); ack.payload_type = IPMI_PAYLOAD_TYPE_SOL; @@ -2677,7 +2670,7 @@ ipmi_get_auth_capabilities_cmd( bridgePossible = 0; msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well - msg_data[1] = intf->session->privlvl; + msg_data[1] = intf->ssn_params.privlvl; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; // 0x06 @@ -2728,7 +2721,8 @@ ipmi_close_session_cmd(struct ipmi_intf * intf) uint32_t bmc_session_lsbf; uint8_t backupBridgePossible; - if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE) + if (intf->session == NULL + || intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE) return -1; backupBridgePossible = bridgePossible; @@ -2809,8 +2803,8 @@ ipmi_lanplus_open_session(struct ipmi_intf * intf) memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE); msg[0] = 0; /* Message tag */ - if (ipmi_oem_active(intf, "intelplus") || session->privlvl != IPMI_SESSION_PRIV_ADMIN) - msg[1] = session->privlvl; + if (ipmi_oem_active(intf, "intelplus") || intf->ssn_params.privlvl != IPMI_SESSION_PRIV_ADMIN) + msg[1] = intf->ssn_params.privlvl; else msg[1] = 0; /* Give us highest privlg level based on supported algorithms */ msg[2] = 0; /* reserved */ @@ -2824,13 +2818,13 @@ ipmi_lanplus_open_session(struct ipmi_intf * intf) msg[7] = (session->v2_data.console_id >> 24) & 0xff; - if (lanplus_get_requested_ciphers(session->cipher_suite_id, + if (lanplus_get_requested_ciphers(intf->ssn_params.cipher_suite_id, &(session->v2_data.requested_auth_alg), &(session->v2_data.requested_integrity_alg), &(session->v2_data.requested_crypt_alg))) { lprintf(LOG_WARNING, "Unsupported cipher suite ID : %d\n", - session->cipher_suite_id); + intf->ssn_params.cipher_suite_id); free(msg); msg = NULL; return 1; @@ -3030,14 +3024,14 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf) /* * Requested maximum privilege level. */ - msg[24] = session->privlvl | session->v2_data.lookupbit; + msg[24] = intf->ssn_params.privlvl | intf->ssn_params.lookupbit; session->v2_data.requested_role = msg[24]; msg[25] = 0; /* reserved */ msg[26] = 0; /* reserved */ /* Username specification */ - msg[27] = strlen((const char *)session->username); + msg[27] = strlen((const char *)intf->ssn_params.username); if (msg[27] > IPMI_MAX_USER_NAME_LENGTH) { lprintf(LOG_ERR, "ERROR: user name too long. " @@ -3047,11 +3041,20 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf) msg = NULL; return 1; } - memcpy(msg + 28, session->username, msg[27]); + memcpy(msg + 28, intf->ssn_params.username, msg[27]); - v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1; - v2_payload.payload_length = - IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]); + v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1; + if (ipmi_oem_active(intf, "i82571spt")) { + /* + * The IPMI v2.0 spec hints on that all user name bytes + * must be occupied (29:44). The Intel 82571 GbE refuses + * to establish a session if this field is shorter. + */ + v2_payload.payload_length = IPMI_RAKP1_MESSAGE_SIZE; + } else { + v2_payload.payload_length = + IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]); + } v2_payload.payload.rakp_1_message.message = msg; rsp = ipmi_lanplus_send_payload(intf, &v2_payload); @@ -3284,15 +3287,16 @@ ipmi_lanplus_rakp3(struct ipmi_intf * intf) void ipmi_lanplus_close(struct ipmi_intf * intf) { - if (!intf->abort) + if (!intf->abort && intf->session) ipmi_close_session_cmd(intf); - if (intf->fd >= 0) + if (intf->fd >= 0) { close(intf->fd); + intf->fd = -1; + } ipmi_req_clear_entries(); ipmi_intf_session_cleanup(intf); - intf->session = NULL; intf->opened = 0; intf->manufacturer_id = IPMI_OEM_UNKNOWN; intf = NULL; @@ -3306,7 +3310,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) struct ipmi_rs * rsp; struct ipmi_rq req; uint8_t backupBridgePossible; - uint8_t privlvl = intf->session->privlvl; + uint8_t privlvl = intf->ssn_params.privlvl; if (privlvl <= IPMI_SESSION_PRIV_USER) return 0; /* no need to set higher */ @@ -3356,55 +3360,54 @@ ipmi_lanplus_open(struct ipmi_intf * intf) int rc; int retry; struct get_channel_auth_cap_rsp auth_cap; + struct ipmi_session_params *params; struct ipmi_session *session; - if (!intf || !intf->session) + if (!intf) return -1; - session = intf->session; - - if (!session->port) - session->port = IPMI_LANPLUS_PORT; - if (!session->privlvl) - session->privlvl = IPMI_SESSION_PRIV_ADMIN; - if (!session->timeout) - session->timeout = IPMI_LAN_TIMEOUT; - if (!session->retry) - session->retry = IPMI_LAN_RETRY; - - if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) { + + if (intf->opened) + return intf->fd; + + params = &intf->ssn_params; + + if (!params->port) + params->port = IPMI_LANPLUS_PORT; + if (!params->privlvl) + params->privlvl = IPMI_SESSION_PRIV_ADMIN; + if (!params->timeout) + params->timeout = IPMI_LAN_TIMEOUT; + if (!params->retry) + params->retry = IPMI_LAN_RETRY; + + if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) { lprintf(LOG_ERR, "No hostname specified!"); return -1; } - intf->abort = 1; + if (ipmi_intf_socket_connect(intf) == -1) { + lprintf(LOG_ERR, "Could not open socket!"); + goto fail; + } + + session = (struct ipmi_session *)malloc(sizeof (struct ipmi_session)); + if (!session) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + goto fail; + } + intf->session = session; /* Setup our lanplus session state */ + memset(session, 0, sizeof(struct ipmi_session)); + session->timeout = params->timeout; + memcpy(&session->authcode, ¶ms->authcode_set, sizeof(session->authcode)); session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE; session->v2_data.crypt_alg = IPMI_CRYPT_NONE; - session->v2_data.console_id = 0x00; - session->v2_data.bmc_id = 0x00; session->sol_data.sequence_number = 1; - //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); - - /* Kg is set in ipmi_intf */ - //memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); - - if (ipmi_intf_socket_connect (intf) == -1) { - lprintf(LOG_ERR, "Could not open socket!"); - return -1; - } - - if (intf->fd < 0) { - lperror(LOG_ERR, "Connect to %s failed", - session->hostname); - intf->close(intf); - return -1; - } intf->opened = 1; + intf->abort = 1; /* * @@ -3417,8 +3420,7 @@ ipmi_lanplus_open(struct ipmi_intf * intf) goto fail; } - if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available) - { + if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available) { lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+"); goto fail; } @@ -3434,7 +3436,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf) * Open session */ if ((rc = ipmi_lanplus_open_session(intf)) == 1) { - intf->close(intf); goto fail; } if (rc == 2) { @@ -3445,7 +3446,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf) * RAKP 1 */ if ((rc = ipmi_lanplus_rakp1(intf)) == 1) { - intf->close(intf); goto fail; } if (rc == 2) { @@ -3456,7 +3456,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf) * RAKP 3 */ if ((rc = ipmi_lanplus_rakp3(intf)) == 1) { - intf->close(intf); goto fail; } if (rc == 0) break; @@ -3465,24 +3464,29 @@ ipmi_lanplus_open(struct ipmi_intf * intf) lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n"); + intf->abort = 0; + if (!ipmi_oem_active(intf, "i82571spt")) { rc = ipmi_set_session_privlvl_cmd(intf); if (rc < 0) { - intf->close(intf); goto fail; } + + /* automatically detect interface request and response sizes */ + hpm2_detect_max_payload_size(intf); } - intf->manufacturer_id = ipmi_get_oem(intf); + bridgePossible = 1; - /* automatically detect interface request and response sizes */ - hpm2_detect_max_payload_size(intf); + if (!ipmi_oem_active(intf, "i82571spt")) { + intf->manufacturer_id = ipmi_get_oem(intf); + } return intf->fd; fail: lprintf(LOG_ERR, "Error: Unable to establish IPMI v2 / RMCP+ session"); - intf->opened = 0; + intf->close(intf); return -1; } @@ -3582,10 +3586,12 @@ static int ipmi_lanplus_keepalive(struct ipmi_intf * intf) { struct ipmi_rs * rsp; - struct ipmi_rq req = { msg: { - netfn: IPMI_NETFN_APP, - cmd: 1, - }}; + struct ipmi_rq req = { + .msg = { + .netfn = IPMI_NETFN_APP, + .cmd = 1, + } + }; if (!intf->opened) return 0; @@ -3623,13 +3629,6 @@ static int ipmi_lanplus_setup(struct ipmi_intf * intf) if (lanplus_seed_prng(16)) return -1; - intf->session = malloc(sizeof(struct ipmi_session)); - if (intf->session == NULL) { - lprintf(LOG_ERR, "ipmitool: malloc failure"); - return -1; - } - memset(intf->session, 0, sizeof(struct ipmi_session)); - /* setup default LAN maximum request and response sizes */ intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE; intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE; @@ -3639,7 +3638,7 @@ static int ipmi_lanplus_setup(struct ipmi_intf * intf) static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size) { - if (intf->session->cipher_suite_id == 3) { + if (intf->ssn_params.cipher_suite_id == 3) { /* * encrypted payload can only be multiple of 16 bytes */ @@ -3657,7 +3656,7 @@ static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t siz static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size) { - if (intf->session->cipher_suite_id == 3) { + if (intf->ssn_params.cipher_suite_id == 3) { /* * encrypted payload can only be multiple of 16 bytes */ diff --git a/src/plugins/lanplus/lanplus_crypt.c b/src/plugins/lanplus/lanplus_crypt.c index 54fd5cb..1cdd050 100644 --- a/src/plugins/lanplus/lanplus_crypt.c +++ b/src/plugins/lanplus/lanplus_crypt.c @@ -95,7 +95,7 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session, 16 + /* GUIDc */ 1 + /* ROLEm */ 1 + /* ULENGTHm */ - strlen((const char *)session->username); /* optional */ + strlen((const char *)intf->ssn_params.username); /* optional */ buffer = malloc(bufferLength); if (buffer == NULL) { @@ -163,11 +163,11 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session, } /* ULENGTHm */ - buffer[57] = strlen((const char *)session->username); + buffer[57] = strlen((const char *)intf->ssn_params.username); /* UserName [optional] */ for (i = 0; i < buffer[57]; ++i) - buffer[58 + i] = session->username[i]; + buffer[58 + i] = intf->ssn_params.username[i]; if (verbose > 2) { @@ -375,7 +375,7 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer, 4 + /* SIDm */ 1 + /* ROLEm */ 1 + /* ULENGTHm */ - strlen((const char *)session->username); + strlen((const char *)intf->ssn_params.username); input_buffer = malloc(input_buffer_length); if (input_buffer == NULL) { @@ -406,16 +406,16 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer, /* ROLEm */ if (ipmi_oem_active(intf, "intelplus") || ipmi_oem_active(intf, "i82571spt")) - input_buffer[20] = session->privlvl; + input_buffer[20] = intf->ssn_params.privlvl; else input_buffer[20] = session->v2_data.requested_role; /* ULENGTHm */ - input_buffer[21] = strlen((const char *)session->username); + input_buffer[21] = strlen((const char *)intf->ssn_params.username); /* USERNAME */ for (i = 0; i < input_buffer[21]; ++i) - input_buffer[22 + i] = session->username[i]; + input_buffer[22 + i] = intf->ssn_params.username[i]; if (verbose > 2) { @@ -491,7 +491,7 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf) 16 + /* Rc */ 1 + /* ROLEm */ 1 + /* ULENGTHm */ - strlen((const char *)session->username); + strlen((const char *)intf->ssn_params.username); input_buffer = malloc(input_buffer_length); if (input_buffer == NULL) { @@ -536,13 +536,13 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf) } /* ULENGTHm */ - input_buffer[33] = strlen((const char *)session->username); + input_buffer[33] = strlen((const char *)intf->ssn_params.username); /* USERNAME */ for (i = 0; i < input_buffer[33]; ++i) - input_buffer[34 + i] = session->username[i]; + input_buffer[34 + i] = intf->ssn_params.username[i]; - if (session->v2_data.kg[0]) + if (intf->ssn_params.kg[0]) { /* We will be hashing with Kg */ /* @@ -550,7 +550,7 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf) * using Kg. It specifies that Kg should not be truncated. * Kg is set in ipmi_intf. */ - input_key = session->v2_data.kg; + input_key = intf->ssn_params.kg; } else { diff --git a/src/plugins/lipmi/Makefile.in b/src/plugins/lipmi/Makefile.in index d70d55d..eb8000f 100644 --- a/src/plugins/lipmi/Makefile.in +++ b/src/plugins/lipmi/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/open/Makefile.in b/src/plugins/open/Makefile.in index da116b7..bb4be5e 100644 --- a/src/plugins/open/Makefile.in +++ b/src/plugins/open/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c index f1ea0dd..fc685de 100644 --- a/src/plugins/open/open.c +++ b/src/plugins/open/open.c @@ -29,6 +29,7 @@ * 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 _POSIX_SOURCE #include <stdio.h> #include <fcntl.h> @@ -38,6 +39,7 @@ #include <stdlib.h> #include <string.h> #include <sys/types.h> +#include <sys/select.h> #include <sys/stat.h> #include <ipmitool/ipmi.h> @@ -81,6 +83,9 @@ */ #define IPMI_OPENIPMI_MAX_RS_DATA_SIZE 35 +/* Timeout for reading data from BMC in seconds */ +#define IPMI_OPENIPMI_READ_TIMEOUT 15 + extern int verbose; static int @@ -164,19 +169,21 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) struct ipmi_recv recv; struct ipmi_addr addr; struct ipmi_system_interface_addr bmc_addr = { - addr_type: IPMI_SYSTEM_INTERFACE_ADDR_TYPE, - channel: IPMI_BMC_CHANNEL, + .addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE, + .channel = IPMI_BMC_CHANNEL, }; struct ipmi_ipmb_addr ipmb_addr = { - addr_type: IPMI_IPMB_ADDR_TYPE, + .addr_type = IPMI_IPMB_ADDR_TYPE, }; struct ipmi_req _req; static struct ipmi_rs rsp; + struct timeval read_timeout; static int curr_seq = 0; fd_set rset; uint8_t * data = NULL; int data_len = 0; + int retval = 0; if (intf == NULL || req == NULL) @@ -325,14 +332,23 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) FD_ZERO(&rset); FD_SET(intf->fd, &rset); - - if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) { + read_timeout.tv_sec = IPMI_OPENIPMI_READ_TIMEOUT; + read_timeout.tv_usec = 0; + retval = select(intf->fd+1, &rset, NULL, NULL, &read_timeout); + if (retval < 0) { lperror(LOG_ERR, "I/O Error"); if (data != NULL) { free(data); data = NULL; } return NULL; + } else if (retval == 0) { + lprintf(LOG_ERR, "No data available"); + if (data != NULL) { + free(data); + data = NULL; + } + return NULL; } if (FD_ISSET(intf->fd, &rset) == 0) { lprintf(LOG_ERR, "No data available"); @@ -375,8 +391,6 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) } if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) { - uint8_t index = 0; - /* ipmb_addr.transit_slave_addr = intf->transit_addr; */ lprintf(LOG_DEBUG, "Decapsulating data received from transit " "IPMB target @ 0x%x", intf->transit_addr); @@ -432,13 +446,13 @@ int ipmi_openipmi_setup(struct ipmi_intf * intf) } struct ipmi_intf ipmi_open_intf = { - name: "open", - desc: "Linux OpenIPMI Interface", - setup: ipmi_openipmi_setup, - open: ipmi_openipmi_open, - close: ipmi_openipmi_close, - sendrecv: ipmi_openipmi_send_cmd, - set_my_addr: ipmi_openipmi_set_my_addr, - my_addr: IPMI_BMC_SLAVE_ADDR, - target_addr: 0, /* init so -m local_addr does not cause bridging */ + .name = "open", + .desc = "Linux OpenIPMI Interface", + .setup = ipmi_openipmi_setup, + .open = ipmi_openipmi_open, + .close = ipmi_openipmi_close, + .sendrecv = ipmi_openipmi_send_cmd, + .set_my_addr = ipmi_openipmi_set_my_addr, + .my_addr = IPMI_BMC_SLAVE_ADDR, + .target_addr = 0, /* init so -m local_addr does not cause bridging */ }; diff --git a/src/plugins/serial/Makefile.in b/src/plugins/serial/Makefile.in index 9826ebf..cae1857 100644 --- a/src/plugins/serial/Makefile.in +++ b/src/plugins/serial/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/serial/serial_basic.c b/src/plugins/serial/serial_basic.c index 871593f..fe2ebff 100644 --- a/src/plugins/serial/serial_basic.c +++ b/src/plugins/serial/serial_basic.c @@ -29,9 +29,11 @@ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ +#define _GNU_SOURCE 1 /* Serial Interface, Basic Mode plugin. */ +#include <alloca.h> #include <stdio.h> #include <fcntl.h> #include <time.h> @@ -183,16 +185,10 @@ static int is_system; static int serial_bm_setup(struct ipmi_intf * intf) { - intf->session = malloc(sizeof(struct ipmi_session)); - if (intf->session == NULL) { - lprintf(LOG_ERR, "ipmitool: malloc failure"); - return -1; - } - memset(intf->session, 0, sizeof(struct ipmi_session)); - /* setup default LAN maximum request and response sizes */ intf->max_request_data_size = SERIAL_BM_MAX_RQ_SIZE; intf->max_response_data_size = SERIAL_BM_MAX_RS_SIZE; + return 0; } @@ -285,10 +281,10 @@ serial_bm_open(struct ipmi_intf * intf) /* set the new options for the port with flushing */ tcsetattr(intf->fd, TCSAFLUSH, &ti); - if (intf->session->timeout == 0) - intf->session->timeout = SERIAL_BM_TIMEOUT; - if (intf->session->retry == 0) - intf->session->retry = SERIAL_BM_RETRY_COUNT; + if (intf->ssn_params.timeout == 0) + intf->ssn_params.timeout = SERIAL_BM_TIMEOUT; + if (intf->ssn_params.retry == 0) + intf->ssn_params.retry = SERIAL_BM_RETRY_COUNT; intf->opened = 1; @@ -459,7 +455,7 @@ serial_bm_wait_for_data(struct ipmi_intf * intf) pfd.events = POLLIN; pfd.revents = 0; - n = poll(&pfd, 1, intf->session->timeout*1000); + n = poll(&pfd, 1, intf->ssn_params.timeout * 1000); if (n < 0) { lperror(LOG_ERR, "Poll for serial data failed"); return -1; @@ -887,7 +883,7 @@ serial_bm_get_message(struct ipmi_intf * intf, tm = clock() - start; tm /= CLOCKS_PER_SEC; - } while (tm < intf->session->timeout); + } while (tm < intf->ssn_params.timeout); return 0; } @@ -910,7 +906,7 @@ serial_bm_send_request(struct ipmi_intf * intf, struct ipmi_rq * req) read_ctx.max_buffer_size = SERIAL_BM_MAX_BUFFER_SIZE; /* Send the message and receive the answer */ - for (retry = 0; retry < intf->session->retry; retry++) { + for (retry = 0; retry < intf->ssn_params.retry; retry++) { /* build output message */ bridging_level = serial_bm_build_msg(intf, req, msg, sizeof (msg), req_ctx, &msg_len); @@ -956,7 +952,7 @@ serial_bm_send_request(struct ipmi_intf * intf, struct ipmi_rq * req) /* check if response for inner request is not encapsulated */ } else if (rv == 1) { /* wait for response for inner request */ - rv = serial_bm_wait_response(intf, &req_ctx[0], + rv = serial_bm_wait_response(intf, &req_ctx[1], &read_ctx, msg, sizeof (msg)); /* check for IO error */ @@ -1003,22 +999,14 @@ serial_bm_send_request(struct ipmi_intf * intf, struct ipmi_rq * req) return NULL; } -int -serial_bm_set_my_addr(struct ipmi_intf * intf, uint8_t addr) -{ - intf->my_addr = addr; - return 0; -} - /* * Serial BM interface */ struct ipmi_intf ipmi_serial_bm_intf = { - name: "serial-basic", - desc: "Serial Interface, Basic Mode", - setup: serial_bm_setup, - open: serial_bm_open, - close: serial_bm_close, - sendrecv: serial_bm_send_request, - set_my_addr:serial_bm_set_my_addr + .name = "serial-basic", + .desc = "Serial Interface, Basic Mode", + .setup = serial_bm_setup, + .open = serial_bm_open, + .close = serial_bm_close, + .sendrecv = serial_bm_send_request, }; diff --git a/src/plugins/serial/serial_terminal.c b/src/plugins/serial/serial_terminal.c index 34c6fc5..dfcc202 100644 --- a/src/plugins/serial/serial_terminal.c +++ b/src/plugins/serial/serial_terminal.c @@ -29,9 +29,11 @@ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ +#define _GNU_SOURCE 1 /* Serial Interface, Terminal Mode plugin. */ +#include <alloca.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> @@ -225,10 +227,10 @@ ipmi_serial_term_open(struct ipmi_intf * intf) /* set the new options for the port with flushing */ tcsetattr(intf->fd, TCSAFLUSH, &ti); - if (intf->session->timeout == 0) - intf->session->timeout = IPMI_SERIAL_TIMEOUT; - if (intf->session->retry == 0) - intf->session->retry = IPMI_SERIAL_RETRY; + if (intf->ssn_params.timeout == 0) + intf->ssn_params.timeout = IPMI_SERIAL_TIMEOUT; + if (intf->ssn_params.retry == 0) + intf->ssn_params.retry = IPMI_SERIAL_RETRY; intf->opened = 1; @@ -259,7 +261,7 @@ serial_wait_for_data(struct ipmi_intf * intf) pfd.events = POLLIN; pfd.revents = 0; - n = poll(&pfd, 1, intf->session->timeout*1000); + n = poll(&pfd, 1, intf->ssn_params.timeout*1000); if (n < 0) { lperror(LOG_ERR, "Poll for serial data failed"); return -1; @@ -357,7 +359,7 @@ recv_response(struct ipmi_intf * intf, unsigned char *data, int len) { char hex_rs[IPMI_SERIAL_MAX_RESPONSE * 3]; int i, j, resp_len = 0; - unsigned long rv; + long rv; char *p, *pp; char ch, str_hex[3]; @@ -769,7 +771,7 @@ serial_term_get_message(struct ipmi_intf * intf, tm = clock() - start; tm /= CLOCKS_PER_SEC; - } while (tm < intf->session->timeout); + } while (tm < intf->ssn_params.timeout); return 0; } @@ -787,7 +789,7 @@ ipmi_serial_term_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) } /* Send the message and receive the answer */ - for (retry = 0; retry < intf->session->retry; retry++) { + for (retry = 0; retry < intf->ssn_params.retry; retry++) { /* build output message */ bridging_level = serial_term_build_msg(intf, req, msg, sizeof (msg), req_ctx, &msg_len); @@ -882,33 +884,18 @@ ipmi_serial_term_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) static int ipmi_serial_term_setup(struct ipmi_intf * intf) { - intf->session = malloc(sizeof(struct ipmi_session)); - if (intf->session == NULL) { - lprintf(LOG_ERR, "ipmitool: malloc failure"); - return -1; - } - - memset(intf->session, 0, sizeof(struct ipmi_session)); - /* setup default LAN maximum request and response sizes */ intf->max_request_data_size = IPMI_SERIAL_MAX_RQ_SIZE; intf->max_response_data_size = IPMI_SERIAL_MAX_RS_SIZE; - return 0; -} -int -ipmi_serial_term_set_my_addr(struct ipmi_intf * intf, uint8_t addr) -{ - intf->my_addr = addr; return 0; } struct ipmi_intf ipmi_serial_term_intf = { - name: "serial-terminal", - desc: "Serial Interface, Terminal Mode", - setup: ipmi_serial_term_setup, - open: ipmi_serial_term_open, - close: ipmi_serial_term_close, - sendrecv: ipmi_serial_term_send_cmd, - set_my_addr:ipmi_serial_term_set_my_addr + .name = "serial-terminal", + .desc = "Serial Interface, Terminal Mode", + .setup = ipmi_serial_term_setup, + .open = ipmi_serial_term_open, + .close = ipmi_serial_term_close, + .sendrecv = ipmi_serial_term_send_cmd, }; diff --git a/src/plugins/usb/Makefile.am b/src/plugins/usb/Makefile.am new file mode 100644 index 0000000..2a431f7 --- /dev/null +++ b/src/plugins/usb/Makefile.am @@ -0,0 +1,40 @@ + # + # Copyright (c) 2015 American Megatrends, 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: + # + # 1. Redistributions of source code must retain the above copyright notice, + # this list of conditions and the following disclaimer. + # + # 2. Redistributions 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. + # + # 3. Neither the name of the copyright holder nor the names of its contributors + # may be used to endorse or promote products derived from this software + # without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + # AND ANY EXPRESS OR IMPLIED WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE + # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + # POSSIBILITY OF SUCH DAMAGE. + # + +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I$(top_srcdir)/include + +EXTRA_LTLIBRARIES = libintf_usb.la +noinst_LTLIBRARIES = @INTF_USB_LIB@ +libintf_usb_la_LIBADD = $(top_builddir)/lib/libipmitool.la +libintf_usb_la_SOURCES = usb.c + diff --git a/src/plugins/usb/Makefile.in b/src/plugins/usb/Makefile.in new file mode 100644 index 0000000..298e11d --- /dev/null +++ b/src/plugins/usb/Makefile.in @@ -0,0 +1,637 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/plugins/usb +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libintf_usb_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la +am_libintf_usb_la_OBJECTS = usb.lo +libintf_usb_la_OBJECTS = $(am_libintf_usb_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libintf_usb_la_SOURCES) +DIST_SOURCES = $(libintf_usb_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ARCH = @ARCH@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASEDIR = @BASEDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTRO = @DISTRO@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTF_BMC = @INTF_BMC@ +INTF_BMC_LIB = @INTF_BMC_LIB@ +INTF_DUMMY = @INTF_DUMMY@ +INTF_DUMMY_LIB = @INTF_DUMMY_LIB@ +INTF_FREE = @INTF_FREE@ +INTF_FREE_LIB = @INTF_FREE_LIB@ +INTF_IMB = @INTF_IMB@ +INTF_IMB_LIB = @INTF_IMB_LIB@ +INTF_LAN = @INTF_LAN@ +INTF_LANPLUS = @INTF_LANPLUS@ +INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@ +INTF_LAN_LIB = @INTF_LAN_LIB@ +INTF_LIPMI = @INTF_LIPMI@ +INTF_LIPMI_LIB = @INTF_LIPMI_LIB@ +INTF_OPEN = @INTF_OPEN@ +INTF_OPEN_LIB = @INTF_OPEN_LIB@ +INTF_SERIAL = @INTF_SERIAL@ +INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ +IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OS = @OS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POW_LIB = @POW_LIB@ +PSTAMP = @PSTAMP@ +RANLIB = @RANLIB@ +RPMBUILD = @RPMBUILD@ +RPM_RELEASE = @RPM_RELEASE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_configure_args = @ac_configure_args@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in +INCLUDES = -I$(top_srcdir)/include +EXTRA_LTLIBRARIES = libintf_usb.la +noinst_LTLIBRARIES = @INTF_USB_LIB@ +libintf_usb_la_LIBADD = $(top_builddir)/lib/libipmitool.la +libintf_usb_la_SOURCES = usb.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/usb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/usb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libintf_usb.la: $(libintf_usb_la_OBJECTS) $(libintf_usb_la_DEPENDENCIES) $(EXTRA_libintf_usb_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libintf_usb_la_OBJECTS) $(libintf_usb_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + # + # Copyright (c) 2015 American Megatrends, 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: + # + # 1. Redistributions of source code must retain the above copyright notice, + # this list of conditions and the following disclaimer. + # + # 2. Redistributions 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. + # + # 3. Neither the name of the copyright holder nor the names of its contributors + # may be used to endorse or promote products derived from this software + # without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + # AND ANY EXPRESS OR IMPLIED WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE + # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + # POSSIBILITY OF SUCH DAMAGE. + # + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/plugins/usb/usb.c b/src/plugins/usb/usb.c new file mode 100644 index 0000000..0049400 --- /dev/null +++ b/src/plugins/usb/usb.c @@ -0,0 +1,614 @@ +/* + * Copyright (c) 2015 American Megatrends, 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: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define _BSD_SOURCE + +#include <ipmitool/helper.h> +#include <ipmitool/log.h> +#include <ipmitool/bswap.h> +#include <ipmitool/ipmi.h> +#include <ipmitool/ipmi_intf.h> +#include <ipmitool/ipmi_oem.h> +#include <ipmitool/ipmi_strings.h> +#include <ipmitool/ipmi_constants.h> +#include <scsi/sg.h> +#include <sys/ioctl.h> +#include <scsi/scsi_ioctl.h> +#include <scsi/scsi.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#define PACKED __attribute__ ((packed)) +#define BEGIN_SIG "$G2-CONFIG-HOST$" +#define BEGIN_SIG_LEN 16 +#define MAX_REQUEST_SIZE 64 * 1024 +#define CMD_RESERVED 0x0000 +#define SCSI_AMICMD_CURI_WRITE 0xE2 +#define SCSI_AMICMD_CURI_READ 0xE3 +#define SCSI_AMIDEF_CMD_SECTOR 0x01 +#define SCSI_AMIDEF_DATA_SECTOR 0x02 +#define ERR_SUCCESS 0 /* Success */ +#define ERR_BIG_DATA 1 /* Too Much Data */ +#define ERR_NO_DATA 2 /* No/Less Data Available */ +#define ERR_UNSUPPORTED 3 /* Unsupported Command */ +#define IN_PROCESS 0x8000 /* Bit 15 of Status */ +#define SCSI_AMICMD_ID 0xEE + +/* SCSI Command Packets */ +typedef struct { + unsigned char OpCode; + unsigned char Lun; + unsigned int Lba; + union { + struct { + unsigned char Reserved6; + unsigned short Length; + unsigned char Reserved9[3]; + } PACKED Cmd10; + struct Len32 { + unsigned int Length32; + unsigned char Reserved10[2]; + } PACKED Cmd12; + } PACKED CmdLen; +} PACKED SCSI_COMMAND_PACKET; + +typedef struct { + uint8_t byNetFnLUN; + uint8_t byCmd; + uint8_t byData[MAX_REQUEST_SIZE]; +} PACKED IPMIUSBRequest_T; + +typedef struct { + uint8_t BeginSig[BEGIN_SIG_LEN]; + uint16_t Command; + uint16_t Status; + uint32_t DataInLen; + uint32_t DataOutLen; + uint32_t InternalUseDataIn; + uint32_t InternalUseDataOut; +} CONFIG_CMD; + +static int ipmi_usb_setup(struct ipmi_intf *intf); +static struct ipmi_rs *ipmi_usb_send_cmd(struct ipmi_intf *intf, + struct ipmi_rq *req); + +struct ipmi_intf ipmi_usb_intf = { + .name = "usb", + .desc = "IPMI USB Interface(OEM Interface for AMI Devices)", + .setup = ipmi_usb_setup, + .sendrecv = ipmi_usb_send_cmd, +}; + +int +scsiProbeNew(int *num_ami_devices, int *sg_nos) +{ + int inplen = *num_ami_devices; + int numdevfound = 0; + char linebuf[81]; + char vendor[81]; + int lineno = 0; + FILE *fp; + + fp = fopen("/proc/scsi/sg/device_strs", "r"); + if (fp == NULL) { + /* Return 1 on error */ + return 1; + } + + while (1) { + /* Read line by line and search for "AMI" */ + if (fgets(linebuf, 80, fp) == NULL) { + break; + } + + if (sscanf(linebuf, "%s", vendor) == 1) { + if (strncmp(vendor, "AMI", strlen("AMI")) == 0) { + numdevfound++; + sg_nos[numdevfound - 1] = lineno; + if (numdevfound == inplen) { + break; + } + } + lineno++; + } + } + + *num_ami_devices = numdevfound; + if (fp != NULL) { + fclose(fp); + fp = NULL; + } + + return 0; +} + +int +OpenCD(struct ipmi_intf *intf, char *CDName) +{ + intf->fd = open(CDName, O_RDWR); + if (intf->fd == (-1)) { + lprintf(LOG_ERR, "OpenCD:Unable to open device, %s", + strerror(errno)); + return 1; + } + return 0; +} + +int +sendscsicmd_SGIO(int cd_desc, unsigned char *cdb_buf, unsigned char cdb_len, + void *data_buf, unsigned int *data_len, int direction, + void *sense_buf, unsigned char slen, unsigned int timeout) +{ + sg_io_hdr_t io_hdr; + + /* Prepare command */ + memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = cdb_len; + + /* Transfer direction and length */ + io_hdr.dxfer_direction = direction; + io_hdr.dxfer_len = *data_len; + + io_hdr.dxferp = data_buf; + + io_hdr.cmdp = cdb_buf; + + io_hdr.sbp = (unsigned char *)sense_buf; + io_hdr.mx_sb_len = slen; + + io_hdr.timeout = timeout; + + if (!timeout) { + io_hdr.timeout = 20000; + } + + if (ioctl(cd_desc, SG_IO, &io_hdr) < 0) { + lprintf(LOG_ERR, "sendscsicmd_SGIO: SG_IO ioctl error"); + return 1; + } else { + if (io_hdr.status != 0) { + return 1; + } + } + + if (!timeout) { + return 0; + } + + if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { + lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - Not OK"); + } else { + lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - OK"); + return 0; + } + + return 1; +} + +int +AMI_SPT_CMD_Identify(int cd_desc, char *szSignature) +{ + SCSI_COMMAND_PACKET IdPkt = {0}; + int ret; + unsigned int siglen = 10; + + IdPkt.OpCode = SCSI_AMICMD_ID; + ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&IdPkt, + 10, szSignature, &siglen, SG_DXFER_FROM_DEV, + NULL, 0, 5000); + + return ret; +} + +int +IsG2Drive(int cd_desc) +{ + char szSignature[15]; + int ret; + + memset(szSignature, 0, 15); + + flock(cd_desc, LOCK_EX); + ret = AMI_SPT_CMD_Identify(cd_desc, szSignature); + flock(cd_desc, LOCK_UN); + if (ret != 0) { + lprintf(LOG_DEBUG, + "IsG2Drive:Unable to send ID command to the device"); + return 1; + } + + if (strncmp(szSignature, "$$$AMI$$$", strlen("$$$AMI$$$")) != 0) { + lprintf(LOG_ERR, + "IsG2Drive:Signature mismatch when ID command sent"); + return 1; + } + + return 0; +} + +int +FindG2CDROM(struct ipmi_intf *intf) +{ + int err = 0; + char device[256]; + int devarray[16]; + int numdev = 16; + int iter; + err = scsiProbeNew(&numdev, devarray); + + if (err == 0 && numdev > 0) { + for (iter = 0; iter < numdev; iter++) { + sprintf(device, "/dev/sg%d", devarray[iter]); + + if (!OpenCD(intf, device)) { + if (!IsG2Drive(intf->fd)) { + lprintf(LOG_DEBUG, "USB Device found"); + return 1; + } + close(intf->fd); + } + } + } else { + lprintf(LOG_DEBUG, "Unable to find Virtual CDROM Device"); + } + + return 0; +} + +static int +ipmi_usb_setup(struct ipmi_intf *intf) +{ + if (FindG2CDROM(intf) == 0) { + lprintf(LOG_ERR, "Error in USB session setup \n"); + return (-1); + } + intf->opened = 1; + return 0; +} + +void +InitCmdHeader(CONFIG_CMD *pG2CDCmdHeader) +{ + memset(pG2CDCmdHeader, 0, sizeof(CONFIG_CMD)); + memcpy((char *)pG2CDCmdHeader->BeginSig, BEGIN_SIG, BEGIN_SIG_LEN); +} + +int +AMI_SPT_CMD_SendCmd(int cd_desc, char *Buffer, char type, uint16_t buflen, + unsigned int timeout) +{ + SCSI_COMMAND_PACKET Cmdpkt; + char sensebuff[32]; + int ret; + unsigned int pktLen; + int count = 3; + + memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET)); + + Cmdpkt.OpCode = SCSI_AMICMD_CURI_WRITE; + Cmdpkt.Lba = htonl(type); + Cmdpkt.CmdLen.Cmd10.Length = htons(1); + + pktLen = buflen; + while (count > 0) { + ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt, + 10, Buffer, &pktLen, SG_DXFER_TO_DEV, + sensebuff, 32, timeout); + count--; + if (ret == 0) { + break; + } else { + ret = (-1); + } + } + + return ret; +} + +int +AMI_SPT_CMD_RecvCmd(int cd_desc, char *Buffer, char type, uint16_t buflen) +{ + SCSI_COMMAND_PACKET Cmdpkt; + char sensebuff[32]; + int ret; + unsigned int pktLen; + int count = 3; + + memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET)); + + Cmdpkt.OpCode = SCSI_AMICMD_CURI_READ; + Cmdpkt.Lba = htonl(type); + Cmdpkt.CmdLen.Cmd10.Length = htons(1); + + pktLen = buflen; + while (count > 0) { + ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt, + 10, Buffer, &pktLen, SG_DXFER_FROM_DEV, + sensebuff, 32, 5000); + count--; + if (0 == ret) { + break; + } else { + ret = (-1); + } + } + + return ret; +} + +int +ReadCD(int cd_desc, char CmdData, char *Buffer, uint32_t DataLen) +{ + int ret; + + ret = AMI_SPT_CMD_RecvCmd(cd_desc, Buffer, CmdData, DataLen); + if (ret != 0) { + lprintf(LOG_ERR, "Error while reading CD-Drive"); + return (-1); + } + return 0; +} + +int +WriteCD(int cd_desc, char CmdData, char *Buffer, unsigned int timeout, + uint32_t DataLen) +{ + int ret; + + ret = AMI_SPT_CMD_SendCmd(cd_desc, Buffer, CmdData, DataLen, timeout); + if (ret != 0) { + lprintf(LOG_ERR, "Error while writing to CD-Drive"); + return (-1); + } + return 0; +} + +int +WriteSplitData(struct ipmi_intf *intf, char *Buffer, char Sector, + uint32_t NumBytes, uint32_t timeout) +{ + uint32_t BytesWritten = 0; + int retVal; + + if (NumBytes == 0) { + return 0; + } + + while (BytesWritten < NumBytes) { + if ((retVal = WriteCD(intf->fd, Sector, + (Buffer + BytesWritten), + timeout, NumBytes)) != 0) { + return retVal; + } + + BytesWritten += NumBytes; + } + + return 0; +} + +int +ReadSplitData(struct ipmi_intf *intf, char *Buffer, char Sector, + uint32_t NumBytes) +{ + uint32_t BytesRead = 0; + + if (NumBytes == 0) { + return 0; + } + + while (BytesRead < NumBytes) { + if (ReadCD(intf->fd, Sector, (Buffer + BytesRead), + NumBytes) == (-1)) { + return 1; + } + BytesRead += NumBytes; + } + + return 0; +} + +int +WaitForCommandCompletion(struct ipmi_intf *intf, CONFIG_CMD *pG2CDCmdHeader, + uint32_t timeout, uint32_t DataLen) +{ + uint32_t TimeCounter = 0; + + do { + if (ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR, + (char *)(pG2CDCmdHeader), DataLen) == (-1)) { + lprintf(LOG_ERR, "ReadCD returned ERROR"); + return 1; + } + + if (pG2CDCmdHeader->Status & IN_PROCESS) { + usleep(1000); + if (timeout > 0) { + TimeCounter++; + if (TimeCounter == (timeout + 1)) { + return 2; + } + } + } else { + lprintf(LOG_DEBUG, "Command completed"); + break; + } + } while (1); + + return 0; +} + +int +SendDataToUSBDriver(struct ipmi_intf *intf, char *ReqBuffer, + unsigned int ReqBuffLen, unsigned char *ResBuffer, + int *ResBuffLen, unsigned int timeout) +{ + char CmdHeaderBuffer[sizeof(CONFIG_CMD)]; + int retVal; + int waitretval = 0; + unsigned int to = 0; + uint32_t DataLen = 0; + + CONFIG_CMD *pG2CDCmdHeader = (CONFIG_CMD *)CmdHeaderBuffer; + + /* FillHeader */ + InitCmdHeader(pG2CDCmdHeader); + + /* Set command number */ + pG2CDCmdHeader->Command = CMD_RESERVED; + + /* Fill Lengths */ + pG2CDCmdHeader->DataOutLen = *ResBuffLen; + pG2CDCmdHeader->DataInLen = ReqBuffLen; + + if (!timeout) { + to = 3000; + } + + DataLen = sizeof(CONFIG_CMD); + + if (WriteCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR, + (char *)(pG2CDCmdHeader), to, DataLen) == (-1)) { + lprintf(LOG_ERR, + "Error in Write CD of SCSI_AMIDEF_CMD_SECTOR"); + return (-1); + } + + /* Write the data to hard disk */ + if ((retVal = WriteSplitData(intf, ReqBuffer, + SCSI_AMIDEF_DATA_SECTOR, + ReqBuffLen, timeout)) != 0) { + lprintf(LOG_ERR, + "Error in WriteSplitData of SCSI_AMIDEF_DATA_SECTOR"); + return (-1); + } + + if (!timeout) { + return 0; + } + + /* Read Status now */ + waitretval = WaitForCommandCompletion(intf, pG2CDCmdHeader, timeout, + DataLen); + if (waitretval != 0) { + lprintf(LOG_ERR, "WaitForCommandComplete failed"); + return (0 - waitretval); + } else { + lprintf(LOG_DEBUG, "WaitForCommandCompletion SUCCESS"); + } + + switch (pG2CDCmdHeader->Status) { + case ERR_SUCCESS: + *ResBuffLen = pG2CDCmdHeader->DataOutLen; + lprintf(LOG_DEBUG, "Before ReadSplitData %x", *ResBuffLen); + if (ReadSplitData(intf, (char *)ResBuffer, + SCSI_AMIDEF_DATA_SECTOR, + pG2CDCmdHeader->DataOutLen) != 0) { + lprintf(LOG_ERR, + "Err ReadSplitData SCSI_AMIDEF_DATA_SCTR"); + return (-1); + } + /* Additional read to see verify there was not problem + * with the previous read + */ + DataLen = sizeof(CONFIG_CMD); + ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR, + (char *)(pG2CDCmdHeader), DataLen); + break; + case ERR_BIG_DATA: + lprintf(LOG_ERR, "Too much data"); + break; + case ERR_NO_DATA: + lprintf(LOG_ERR, "Too little data"); + break; + case ERR_UNSUPPORTED: + lprintf(LOG_ERR, "Unsupported command"); + break; + default: + lprintf(LOG_ERR, "Unknown status"); + } + + return pG2CDCmdHeader->Status; +} + +static struct ipmi_rs * +ipmi_usb_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req) +{ + static struct ipmi_rs rsp; + long timeout = 20000; + uint8_t byRet = 0; + char ReqBuff[MAX_REQUEST_SIZE] = {0}; + IPMIUSBRequest_T *pReqPkt = (IPMIUSBRequest_T *)ReqBuff; + int retries = 0; + /********** FORM IPMI PACKET *****************/ + pReqPkt->byNetFnLUN = req->msg.netfn << 2; + pReqPkt->byNetFnLUN += req->msg.lun; + pReqPkt->byCmd = req->msg.cmd; + if (req->msg.data_len) { + memcpy(pReqPkt->byData, req->msg.data, req->msg.data_len); + } + + /********** SEND DATA TO USB ******************/ + while (retries < 3) { + retries++; + byRet = SendDataToUSBDriver(intf, ReqBuff, + 2 + req->msg.data_len, rsp.data, + &rsp.data_len,timeout); + + if (byRet == 0) { + break; + } + } + + if (retries == 3) { + lprintf(LOG_ERR, + "Error while sending command using", + "SendDataToUSBDriver"); + rsp.ccode = byRet; + return &rsp; + } + + rsp.ccode = rsp.data[0]; + + /* Save response data for caller */ + if ((rsp.ccode == 0) && (rsp.data_len > 0)) { + memmove(rsp.data, rsp.data + 1, rsp.data_len - 1); + rsp.data[rsp.data_len] = 0; + rsp.data_len -= 1; + } + return &rsp; +} |