summaryrefslogtreecommitdiff
path: root/src/plugins/lanplus/lanplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/lanplus/lanplus.c')
-rw-r--r--src/plugins/lanplus/lanplus.c637
1 files changed, 318 insertions, 319 deletions
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, &params->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
*/