diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-02-20 02:12:42 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-02-20 02:12:42 +0100 |
commit | a61a5992cefc2204a99f25b2395b108092098e2c (patch) | |
tree | 3b25da535866adf0458f6d172fd242fc933c77db /src/plugins/lanplus | |
parent | 15edf42f095e3cc26e372547ebcaaae558d0cce2 (diff) | |
parent | 97d6a2e491c6ed08473beb2c4bac47c5cbc1201a (diff) |
Merge tag 'upstream/1.8.16'
Upstream version 1.8.16
Diffstat (limited to 'src/plugins/lanplus')
-rw-r--r-- | src/plugins/lanplus/Makefile.in | 2 | ||||
-rw-r--r-- | src/plugins/lanplus/lanplus.c | 637 | ||||
-rw-r--r-- | src/plugins/lanplus/lanplus_crypt.c | 24 |
3 files changed, 332 insertions, 331 deletions
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 { |