fix segfault in SOL when remote BMC does not return packet

This commit is contained in:
Duncan Laurie 2006-07-06 21:38:21 +00:00
parent a92765fbc9
commit c99e8595e4
2 changed files with 101 additions and 116 deletions

View File

@ -1404,7 +1404,7 @@ ipmi_sol_red_pill(struct ipmi_intf * intf)
output(rs); output(rs);
} }
/* /*
* ERROR in select * ERROR in select
*/ */
@ -1414,7 +1414,7 @@ ipmi_sol_red_pill(struct ipmi_intf * intf)
bShouldExit = 1; bShouldExit = 1;
} }
} }
} }
leave_raw_mode(); leave_raw_mode();

View File

@ -302,7 +302,7 @@ ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_se
memcpy(&e->req, req, sizeof(struct ipmi_rq)); memcpy(&e->req, req, sizeof(struct ipmi_rq));
e->intf = intf; e->intf = intf;
e->rq_seq = req_seq; e->rq_seq = req_seq;
if (ipmi_req_entries == NULL) if (ipmi_req_entries == NULL)
ipmi_req_entries = e; ipmi_req_entries = e;
@ -355,7 +355,7 @@ ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
else else
ipmi_req_entries_tail = NULL; ipmi_req_entries_tail = NULL;
} }
if (e->msg_data) if (e->msg_data)
free(e->msg_data); free(e->msg_data);
free(e); free(e);
@ -581,17 +581,14 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
struct rmcp_hdr rmcp_rsp; struct rmcp_hdr rmcp_rsp;
struct ipmi_rs * rsp; struct ipmi_rs * rsp;
struct ipmi_session * session = intf->session; struct ipmi_session * session = intf->session;
int offset, rv; int offset, rv;
uint16_t payload_size; uint16_t payload_size;
uint8_t ourAddress = intf->my_addr;
if (ourAddress == 0) {
ourAddress = IPMI_BMC_SLAVE_ADDR;
}
uint8_t ourAddress = intf->my_addr;
if(ourAddress == 0)
{
ourAddress = IPMI_BMC_SLAVE_ADDR;
}
rsp = ipmi_lan_recv_packet(intf); rsp = ipmi_lan_recv_packet(intf);
/* /*
@ -608,7 +605,7 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
rv = ipmi_handle_pong(intf, rsp); rv = ipmi_handle_pong(intf, rsp);
return (rv <= 0) ? NULL : rsp; return (rv <= 0) ? NULL : rsp;
} }
if (rmcp_rsp.class != RMCP_CLASS_IPMI) { if (rmcp_rsp.class != RMCP_CLASS_IPMI) {
lprintf(LOG_DEBUG, "Invalid RMCP class: %x", lprintf(LOG_DEBUG, "Invalid RMCP class: %x",
rmcp_rsp.class); rmcp_rsp.class);
@ -648,18 +645,17 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
//continue; //continue;
} }
if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
(rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
(rsp->session.bEncrypted)) (rsp->session.bEncrypted))
{ {
lanplus_decrypt_payload(session->v2_data.crypt_alg, lanplus_decrypt_payload(session->v2_data.crypt_alg,
session->v2_data.k2, session->v2_data.k2,
rsp->data + offset, rsp->data + offset,
rsp->session.msglen, rsp->session.msglen,
rsp->data + offset, rsp->data + offset,
&payload_size); &payload_size);
} }
else else
payload_size = rsp->session.msglen; payload_size = rsp->session.msglen;
@ -684,7 +680,6 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
(long)rsp->session.id); (long)rsp->session.id);
lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx", lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx",
(long)rsp->session.seq); (long)rsp->session.seq);
lprintf(LOG_DEBUG+1, "<< IPMI Msg/Payload Length : %d", lprintf(LOG_DEBUG+1, "<< IPMI Msg/Payload Length : %d",
rsp->session.msglen); rsp->session.msglen);
lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header"); lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header");
@ -707,48 +702,40 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
/* Are we expecting this packet? */ /* Are we expecting this packet? */
entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq, entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
rsp->payload.ipmi_response.cmd); rsp->payload.ipmi_response.cmd);
if (entry != NULL) { if (entry != NULL) {
lprintf(LOG_DEBUG+2, "IPMI Request Match found"); lprintf(LOG_DEBUG+2, "IPMI Request Match found");
if ( if (intf->target_addr != ourAddress &&
(intf->target_addr != ourAddress) && bridgePossible) {
(bridgePossible) if (rsp->data_len &&
) rsp->payload.ipmi_response.cmd != 0x34) {
{ printbuf(
if( &rsp->data[offset],
(rsp->data_len) && (rsp->data_len-offset),
(rsp->payload.ipmi_response.cmd != 0x34) "bridge command response");
) }
{ /* bridged command: lose extra header */
printbuf( if (rsp->payload.ipmi_response.cmd == 0x34) {
&rsp->data[offset], if (rsp->data_len == 38) {
(rsp->data_len-offset), entry->req.msg.cmd = entry->req.msg.target_cmd;
"bridge command response"); rsp = ipmi_lan_recv_packet(intf);
} continue;
/* bridged command: lose extra header */ }
if (rsp->payload.ipmi_response.cmd == 0x34) { } else {
if( rsp->data_len == 38 ) //x += sizeof(rsp->payload.ipmi_response);
{ if (rsp->data[offset-1] != 0)
entry->req.msg.cmd = entry->req.msg.target_cmd; lprintf(LOG_DEBUG, "WARNING: Bridged "
rsp = ipmi_lan_recv_packet(intf); "cmd ccode = 0x%02x",
continue; rsp->data[offset-1]);
} }
} else { }
//x += sizeof(rsp->payload.ipmi_response);
if (rsp->data[offset-1] != 0)
lprintf(LOG_DEBUG, "WARNING: Bridged "
"cmd ccode = 0x%02x",
rsp->data[offset-1]);
}
}
ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
rsp->payload.ipmi_response.cmd); rsp->payload.ipmi_response.cmd);
} else { } else {
lprintf(LOG_INFO, "IPMI Request Match NOT FOUND"); lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
rsp = ipmi_lan_recv_packet(intf); rsp = ipmi_lan_recv_packet(intf);
continue; continue;
} }
/* /*
* Good packet. Shift response data to start of array. * Good packet. Shift response data to start of array.
@ -772,13 +759,13 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
* Open Response * Open Response
*/ */
else if (rsp->session.payloadtype == else if (rsp->session.payloadtype ==
IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE) IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE)
{ {
if (session->v2_data.session_state != if (session->v2_data.session_state !=
LANPLUS_STATE_OPEN_SESSION_SENT) LANPLUS_STATE_OPEN_SESSION_SENT)
{ {
lprintf(LOG_ERR, "Error: Received an Unexpected Open Session " lprintf(LOG_ERR, "Error: Received an Unexpected Open Session "
"Response"); "Response");
rsp = ipmi_lan_recv_packet(intf); rsp = ipmi_lan_recv_packet(intf);
continue; continue;
} }
@ -786,7 +773,7 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
read_open_session_response(rsp, offset); read_open_session_response(rsp, offset);
break; break;
} }
/* /*
* RAKP 2 * RAKP 2
@ -821,7 +808,7 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
break; break;
} }
/* /*
* SOL * SOL
*/ */
@ -853,7 +840,7 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
else else
{ {
lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x", lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x",
rsp->session.payloadtype); rsp->session.payloadtype);
assert(0); assert(0);
} }
} }
@ -1416,7 +1403,7 @@ void getIpmiPayloadWireRep(
* param payload [in] holds the v2 payload with our SOL data * param payload [in] holds the v2 payload with our SOL data
*/ */
void getSolPayloadWireRep( void getSolPayloadWireRep(
struct ipmi_intf * intf, /* in out */ struct ipmi_intf * intf, /* in out */
uint8_t * msg, /* output */ uint8_t * msg, /* output */
struct ipmi_v2_payload * payload) /* input */ struct ipmi_v2_payload * payload) /* input */
{ {
@ -1490,7 +1477,7 @@ ipmi_lanplus_build_v2x_msg(
struct ipmi_v2_payload * payload, /* in */ struct ipmi_v2_payload * payload, /* in */
int * msg_len, /* out */ int * msg_len, /* out */
uint8_t ** msg_data, /* out */ uint8_t ** msg_data, /* out */
uint8_t curr_seq) uint8_t curr_seq)
{ {
uint32_t session_trailer_length = 0; uint32_t session_trailer_length = 0;
struct ipmi_session * session = intf->session; struct ipmi_session * session = intf->session;
@ -1588,16 +1575,16 @@ ipmi_lanplus_build_v2x_msg(
{ {
case IPMI_PAYLOAD_TYPE_IPMI: case IPMI_PAYLOAD_TYPE_IPMI:
getIpmiPayloadWireRep(intf, getIpmiPayloadWireRep(intf,
payload, /* in */ payload, /* in */
msg + IPMI_LANPLUS_OFFSET_PAYLOAD, msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
payload->payload.ipmi_request.request, payload->payload.ipmi_request.request,
payload->payload.ipmi_request.rq_seq, payload->payload.ipmi_request.rq_seq,
curr_seq); curr_seq);
break; break;
case IPMI_PAYLOAD_TYPE_SOL: case IPMI_PAYLOAD_TYPE_SOL:
getSolPayloadWireRep(intf, getSolPayloadWireRep(intf,
msg + IPMI_LANPLUS_OFFSET_PAYLOAD, msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
payload); payload);
len += payload->payload_length; len += payload->payload_length;
@ -1804,7 +1791,7 @@ ipmi_lanplus_build_v2x_ipmi_cmd(
&v2_payload, // in &v2_payload, // in
&(entry->msg_len), // out &(entry->msg_len), // out
&(entry->msg_data), // out &(entry->msg_data), // out
curr_seq); // in curr_seq); // in
return entry; return entry;
} }
@ -2056,7 +2043,7 @@ ipmi_lanplus_send_payload(
payload, /* in */ payload, /* in */
&msg_length, /* out */ &msg_length, /* out */
&msg_data, /* out */ &msg_data, /* out */
0); /* irrelevant for this msg*/ 0); /* irrelevant for this msg*/
} }
@ -2070,7 +2057,7 @@ ipmi_lanplus_send_payload(
payload, /* in */ payload, /* in */
&msg_length, /* out */ &msg_length, /* out */
&msg_data, /* out */ &msg_data, /* out */
0); /* irrelevant for this msg*/ 0); /* irrelevant for this msg*/
} }
@ -2084,7 +2071,7 @@ ipmi_lanplus_send_payload(
payload, /* in */ payload, /* in */
&msg_length, /* out */ &msg_length, /* out */
&msg_data, /* out */ &msg_data, /* out */
0); /* irrelevant for this msg*/ 0); /* irrelevant for this msg*/
} }
@ -2097,7 +2084,7 @@ ipmi_lanplus_send_payload(
payload, /* in */ payload, /* in */
&msg_length, /* out */ &msg_length, /* out */
&msg_data, /* out */ &msg_data, /* out */
0); /* irrelevant for this msg*/ 0); /* irrelevant for this msg*/
} }
else else
@ -2169,7 +2156,6 @@ ipmi_lanplus_send_payload(
if (sol_response_acks_packet(rsp, payload)) if (sol_response_acks_packet(rsp, payload))
break; break;
else if (is_sol_packet(rsp) && rsp->data_len) else if (is_sol_packet(rsp) && rsp->data_len)
{ {
/* /*
@ -2195,7 +2181,6 @@ ipmi_lanplus_send_payload(
try++; try++;
} }
/* IPMI messages are deleted under ipmi_lan_poll_recv() */ /* IPMI messages are deleted under ipmi_lan_poll_recv() */
switch (payload->payload_type) { switch (payload->payload_type) {
case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
@ -2361,8 +2346,7 @@ check_sol_packet_for_new_data(
{ {
/* Store the data length before we mod it */ /* Store the data length before we mod it */
uint8_t unaltered_data_len = rsp->data_len; uint8_t unaltered_data_len = rsp->data_len;
if (rsp->payload.sol_packet.packet_sequence_number == if (rsp->payload.sol_packet.packet_sequence_number ==
last_received_sequence_number) last_received_sequence_number)
{ {
@ -2438,7 +2422,7 @@ ack_sol_packet(
rsp->payload.sol_packet.packet_sequence_number; rsp->payload.sol_packet.packet_sequence_number;
ack.payload.sol_packet.accepted_character_count = rsp->data_len; ack.payload.sol_packet.accepted_character_count = rsp->data_len;
ipmi_lanplus_send_payload(intf, &ack); ipmi_lanplus_send_payload(intf, &ack);
} }
} }
@ -2455,17 +2439,17 @@ struct ipmi_rs *
ipmi_lanplus_recv_sol(struct ipmi_intf * intf) ipmi_lanplus_recv_sol(struct ipmi_intf * intf)
{ {
struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf); struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf);
if(rsp->session.authtype != 0)
{
ack_sol_packet(intf, rsp);
/* if (rsp && rsp->session.authtype != 0)
* Remembers the data sent, and alters the data to just {
* include the new stuff. ack_sol_packet(intf, rsp);
*/
check_sol_packet_for_new_data(intf, rsp); /*
} * Remembers the data sent, and alters the data to just
* include the new stuff.
*/
check_sol_packet_for_new_data(intf, rsp);
}
return rsp; return rsp;
} }
@ -2517,11 +2501,11 @@ ipmi_get_auth_capabilities_cmd(
struct ipmi_rs * rsp; struct ipmi_rs * rsp;
struct ipmi_rq req; struct ipmi_rq req;
uint8_t msg_data[2]; uint8_t msg_data[2];
uint8_t backupBridgePossible; uint8_t backupBridgePossible;
backupBridgePossible = bridgePossible; backupBridgePossible = bridgePossible;
bridgePossible = 0; bridgePossible = 0;
msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well 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->session->privlvl;
@ -2559,7 +2543,7 @@ ipmi_get_auth_capabilities_cmd(
rsp->data, rsp->data,
sizeof(struct get_channel_auth_cap_rsp)); sizeof(struct get_channel_auth_cap_rsp));
bridgePossible = backupBridgePossible; bridgePossible = backupBridgePossible;
return 0; return 0;
} }
@ -2573,20 +2557,20 @@ impi_close_session_cmd(struct ipmi_intf * intf)
struct ipmi_rq req; struct ipmi_rq req;
uint8_t msg_data[4]; uint8_t msg_data[4];
uint32_t bmc_session_lsbf; uint32_t bmc_session_lsbf;
uint8_t backupBridgePossible; uint8_t backupBridgePossible;
if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE) if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
return -1; return -1;
backupBridgePossible = bridgePossible; backupBridgePossible = bridgePossible;
bridgePossible = 0; bridgePossible = 0;
bmc_session_lsbf = intf->session->v2_data.bmc_id; bmc_session_lsbf = intf->session->v2_data.bmc_id;
#if WORDS_BIGENDIAN #if WORDS_BIGENDIAN
bmc_session_lsbf = BSWAP_32(bmc_session_lsbf); bmc_session_lsbf = BSWAP_32(bmc_session_lsbf);
#endif #endif
memcpy(&msg_data, &bmc_session_lsbf, 4); memcpy(&msg_data, &bmc_session_lsbf, 4);
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
@ -2619,7 +2603,8 @@ impi_close_session_cmd(struct ipmi_intf * intf)
lprintf(LOG_DEBUG, "Closed Session %08lx\n", lprintf(LOG_DEBUG, "Closed Session %08lx\n",
(long)intf->session->v2_data.bmc_id); (long)intf->session->v2_data.bmc_id);
bridgePossible = backupBridgePossible; bridgePossible = backupBridgePossible;
return 0; return 0;
} }
@ -3119,15 +3104,15 @@ ipmi_lanplus_close(struct ipmi_intf * intf)
{ {
if (!intf->abort) if (!intf->abort)
impi_close_session_cmd(intf); impi_close_session_cmd(intf);
if (intf->fd >= 0) if (intf->fd >= 0)
close(intf->fd); close(intf->fd);
ipmi_req_clear_entries(); ipmi_req_clear_entries();
if (intf->session) if (intf->session)
free(intf->session); free(intf->session);
intf->session = NULL; intf->session = NULL;
intf->opened = 0; intf->opened = 0;
intf = NULL; intf = NULL;
@ -3140,16 +3125,16 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
{ {
struct ipmi_rs * rsp; struct ipmi_rs * rsp;
struct ipmi_rq req; struct ipmi_rq req;
uint8_t backupBridgePossible; uint8_t backupBridgePossible;
uint8_t privlvl = intf->session->privlvl; uint8_t privlvl = intf->session->privlvl;
if (privlvl <= IPMI_SESSION_PRIV_USER) if (privlvl <= IPMI_SESSION_PRIV_USER)
return 0; /* no need to set higher */ return 0; /* no need to set higher */
backupBridgePossible = bridgePossible; backupBridgePossible = bridgePossible;
bridgePossible = 0; bridgePossible = 0;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = 0x3b; req.msg.cmd = 0x3b;
@ -3175,8 +3160,8 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n", lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n",
val2str(rsp->data[0], ipmi_privlvl_vals)); val2str(rsp->data[0], ipmi_privlvl_vals));
bridgePossible = backupBridgePossible; bridgePossible = backupBridgePossible;
return 0; return 0;
} }
@ -3329,8 +3314,8 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n"); lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
bridgePossible = 1; bridgePossible = 1;
rc = ipmi_set_session_privlvl_cmd(intf); rc = ipmi_set_session_privlvl_cmd(intf);
if (rc < 0) if (rc < 0)
goto fail; goto fail;