diff options
Diffstat (limited to 'src/plugins/lan/lan.c')
-rw-r--r-- | src/plugins/lan/lan.c | 187 |
1 files changed, 103 insertions, 84 deletions
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; |