mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
Incremental changes for SOL. Now receiving (and acking) data from the
BMC.
This commit is contained in:
parent
781d59161e
commit
00b6abee9d
@ -88,9 +88,11 @@ static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf);
|
||||
static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
|
||||
static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf,
|
||||
struct ipmi_v2_payload * payload);
|
||||
void getIpmiPayloadWireRep(unsigned char * out,
|
||||
static void getIpmiPayloadWireRep(unsigned char * out,
|
||||
struct ipmi_rq * req,
|
||||
unsigned char rq_seq);
|
||||
static void getSolPayloadWireRep(unsigned char * msg,
|
||||
struct ipmi_v2_payload * payload);
|
||||
static void read_open_session_response(struct ipmi_rs * rsp, int offset);
|
||||
static void read_rakp2_message(struct ipmi_rs * rsp, int offset, unsigned char alg);
|
||||
static void read_rakp4_message(struct ipmi_rs * rsp, int offset, unsigned char alg);
|
||||
@ -98,14 +100,16 @@ static void read_session_data(struct ipmi_rs * rsp, int * offset, struct ipmi_se
|
||||
static void read_session_data_v15(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
|
||||
static void read_session_data_v2x(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
|
||||
static void read_ipmi_response(struct ipmi_rs * rsp, int * offset);
|
||||
|
||||
static void read_sol_packet(struct ipmi_rs * rsp, int * offset);
|
||||
struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf);
|
||||
|
||||
|
||||
struct ipmi_intf ipmi_lanplus_intf = {
|
||||
.open = ipmi_lanplus_open,
|
||||
.close = ipmi_lanplus_close,
|
||||
.sendrecv = ipmi_lanplus_send_ipmi_cmd,
|
||||
.sendrecv_v2 = ipmi_lanplus_send_payload,
|
||||
.recv_sol = ipmi_lanplus_recv_sol
|
||||
/* .send_sol = ipmi_lanplus_send_sol */
|
||||
};
|
||||
|
||||
|
||||
@ -484,18 +488,19 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
||||
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)
|
||||
* 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) An Invalid packet (one that doesn't match a request)
|
||||
* ----------------------------------------------------------------------
|
||||
* 6) A Serial Over LAN packet
|
||||
* 7) An Invalid packet (one that doesn't match a request)
|
||||
* -------------------------------------------------------------------
|
||||
*/
|
||||
read_session_data(rsp, &offset, intf->session);
|
||||
|
||||
@ -508,8 +513,8 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
|
||||
if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
|
||||
(rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
|
||||
if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
|
||||
(rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
|
||||
(rsp->session.bEncrypted))
|
||||
|
||||
{
|
||||
@ -519,6 +524,8 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
||||
rsp->session.msglen,
|
||||
rsp->data + offset,
|
||||
&payload_size);
|
||||
|
||||
printf("DECRYPTING PAYLOAD size %d\n", payload_size);
|
||||
}
|
||||
else
|
||||
payload_size = rsp->session.msglen;
|
||||
@ -538,20 +545,32 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
||||
printf("<< IPMI Response Session Header\n");
|
||||
printf("<< Authtype : %s\n",
|
||||
val2str(rsp->session.authtype, ipmi_authtype_vals));
|
||||
printf("<< Payload type : 0x%x\n", rsp->session.payloadtype);
|
||||
printf("<< Session ID : 0x%08lx\n", rsp->session.id);
|
||||
printf("<< Sequence : 0x%08lx\n", rsp->session.seq);
|
||||
printf("<< Payload type : 0x%x\n",
|
||||
rsp->session.payloadtype);
|
||||
printf("<< Session ID : 0x%08lx\n",
|
||||
rsp->session.id);
|
||||
printf("<< Sequence : 0x%08lx\n",
|
||||
rsp->session.seq);
|
||||
|
||||
printf("<< IPMI Msg/Payload Length : %d\n", rsp->session.msglen);
|
||||
printf("<< IPMI Msg/Payload Length : %d\n",
|
||||
rsp->session.msglen);
|
||||
printf("<< IPMI Response Message Header\n");
|
||||
printf("<< Rq Addr : %02x\n", rsp->payload.ipmi_response.rq_addr);
|
||||
printf("<< NetFn : %02x\n", rsp->payload.ipmi_response.netfn);
|
||||
printf("<< Rq LUN : %01x\n", rsp->payload.ipmi_response.rq_lun);
|
||||
printf("<< Rs Addr : %02x\n", rsp->payload.ipmi_response.rs_addr);
|
||||
printf("<< Rq Seq : %02x\n", rsp->payload.ipmi_response.rq_seq);
|
||||
printf("<< Rs Lun : %01x\n", rsp->payload.ipmi_response.rs_lun);
|
||||
printf("<< Command : %02x\n", rsp->payload.ipmi_response.cmd);
|
||||
printf("<< Compl Code : 0x%02x\n", rsp->ccode);
|
||||
printf("<< Rq Addr : %02x\n",
|
||||
rsp->payload.ipmi_response.rq_addr);
|
||||
printf("<< NetFn : %02x\n",
|
||||
rsp->payload.ipmi_response.netfn);
|
||||
printf("<< Rq LUN : %01x\n",
|
||||
rsp->payload.ipmi_response.rq_lun);
|
||||
printf("<< Rs Addr : %02x\n",
|
||||
rsp->payload.ipmi_response.rs_addr);
|
||||
printf("<< Rq Seq : %02x\n",
|
||||
rsp->payload.ipmi_response.rq_seq);
|
||||
printf("<< Rs Lun : %01x\n",
|
||||
rsp->payload.ipmi_response.rs_lun);
|
||||
printf("<< Command : %02x\n",
|
||||
rsp->payload.ipmi_response.cmd);
|
||||
printf("<< Compl Code : 0x%02x\n",
|
||||
rsp->ccode);
|
||||
}
|
||||
|
||||
/* Are we expecting this packet? */
|
||||
@ -585,11 +604,14 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
|
||||
else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE)
|
||||
else if (rsp->session.payloadtype ==
|
||||
IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE)
|
||||
{
|
||||
if (session->v2_data.session_state != LANPLUS_STATE_OPEN_SESSION_SENT)
|
||||
if (session->v2_data.session_state !=
|
||||
LANPLUS_STATE_OPEN_SESSION_SENT)
|
||||
{
|
||||
printf("Error: Received an Unexpected Open Session Response\n");
|
||||
printf("Error: Received an Unexpected Open Session "
|
||||
"Response\n");
|
||||
rsp = ipmi_lan_recv_packet(intf);
|
||||
continue;
|
||||
}
|
||||
@ -624,9 +646,33 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
printf("Error: Received an Unexpected SOL packet\n");
|
||||
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);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
printf("Invalid RMCP+ payload type : 0x%x\n", rsp->session.payloadtype);
|
||||
printf("Invalid RMCP+ payload type : 0x%x\n",
|
||||
rsp->session.payloadtype);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
@ -769,12 +815,13 @@ void read_rakp2_message(struct ipmi_rs * rsp, int offset, unsigned char auth_alg
|
||||
* The offset should point the first byte of the the RAKP 4 payload when this
|
||||
* function is called.
|
||||
*
|
||||
* param rsp [in/out] reading from the data variable and writing to the rakp 4
|
||||
* section
|
||||
* param rsp [in/out] reading from the data variable and writing to the rakp
|
||||
* 4 section
|
||||
* param offset [in] tells us where hte rakp4 payload starts
|
||||
* param integrity_alg [in] describes the authentication algorithm was agreed upon
|
||||
* in the open session request/response phase. We need to know that here so
|
||||
* that we know how many bytes (if any) to read fromt the packet.
|
||||
* param integrity_alg [in] describes the authentication algorithm was
|
||||
* agreed upon in the open session request/response phase. We need
|
||||
* to know that here so that we know how many bytes (if any) to read
|
||||
* from the packet.
|
||||
*
|
||||
* returns 0 on success, 1 on error
|
||||
*/
|
||||
@ -814,8 +861,8 @@ void read_rakp4_message(struct ipmi_rs * rsp, int offset, unsigned char integrit
|
||||
|
||||
case IPMI_INTEGRITY_HMAC_MD5_128:
|
||||
case IPMI_INTEGRITY_MD5_128:
|
||||
printf("read_rakp4_message: no support for integrity algorithm 0x%x\n",
|
||||
integrity_alg);
|
||||
printf("read_rakp4_message: no support for integrity algorithm "
|
||||
"0x%x\n", integrity_alg);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
@ -987,6 +1034,78 @@ void read_ipmi_response(struct ipmi_rs * rsp, int * offset)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* read_sol_packet
|
||||
*
|
||||
* Initialize the impi_rs with the SOL response data
|
||||
*
|
||||
* The offset should point the first byte of the the SOL payload when this
|
||||
* function is called.
|
||||
*
|
||||
* param rsp [in/out] we read from the data buffer and populate the
|
||||
* SOL specific fields.
|
||||
* param offset [in/out] should point to the beginning of the SOL payload
|
||||
* when this function is called.
|
||||
*/
|
||||
void read_sol_packet(struct ipmi_rs * rsp, int * offset)
|
||||
{
|
||||
/*
|
||||
* The data here should be decrypted by now.
|
||||
*/
|
||||
rsp->payload.sol_packet.packet_sequence_number =
|
||||
rsp->data[(*offset)++] & 0x0F;
|
||||
|
||||
rsp->payload.sol_packet.acked_packet_number =
|
||||
rsp->data[(*offset)++] & 0x0F;
|
||||
|
||||
rsp->payload.sol_packet.accepted_character_count =
|
||||
rsp->data[(*offset)++] & 0x0F;
|
||||
|
||||
rsp->payload.sol_packet.is_nack =
|
||||
rsp->data[*offset] & 0x40;
|
||||
|
||||
rsp->payload.sol_packet.transfer_unavailable =
|
||||
rsp->data[*offset] & 0x20;
|
||||
|
||||
rsp->payload.sol_packet.sol_inactive =
|
||||
rsp->data[*offset] & 0x10;
|
||||
|
||||
rsp->payload.sol_packet.transmit_overrun =
|
||||
rsp->data[*offset] & 0x08;
|
||||
|
||||
rsp->payload.sol_packet.break_detected =
|
||||
rsp->data[(*offset)++] & 0x04;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
printf("SOL sequence number : 0x%02x\n",
|
||||
rsp->payload.sol_packet.packet_sequence_number);
|
||||
|
||||
printf("SOL acked packet : 0x%02x\n",
|
||||
rsp->payload.sol_packet.acked_packet_number);
|
||||
|
||||
printf("SOL accepted char count : 0x%02x\n",
|
||||
rsp->payload.sol_packet.accepted_character_count);
|
||||
|
||||
printf("SOL is nack : %s\n",
|
||||
rsp->payload.sol_packet.is_nack? "true" : "false");
|
||||
|
||||
printf("SOL xfer unavailable : %s\n",
|
||||
rsp->payload.sol_packet.transfer_unavailable? "true" : "false");
|
||||
|
||||
printf("SOL inactive : %s\n",
|
||||
rsp->payload.sol_packet.sol_inactive? "true" : "false");
|
||||
|
||||
printf("SOL transmit overrun : %s\n",
|
||||
rsp->payload.sol_packet.transmit_overrun? "true" : "false");
|
||||
|
||||
printf("SOL break detected : %s\n",
|
||||
rsp->payload.sol_packet.break_detected? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* getIpmiPayloadWireRep
|
||||
*
|
||||
@ -1041,6 +1160,44 @@ void getIpmiPayloadWireRep(unsigned char * msg,
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* getSolPayloadWireRep
|
||||
*
|
||||
* param msg [out] will contain our wire representation
|
||||
* param payload [in] holds the v2 payload with our SOL data
|
||||
*/
|
||||
void getSolPayloadWireRep(unsigned char * msg, /* output */
|
||||
struct ipmi_v2_payload * payload) /* input */
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
msg[i++] = payload->payload.sol_packet.packet_sequence_number;
|
||||
msg[i++] = payload->payload.sol_packet.acked_packet_number;
|
||||
msg[i++] = payload->payload.sol_packet.accepted_character_count;
|
||||
|
||||
msg[i] = payload->payload.sol_packet.is_nack ? 0x40 : 0;
|
||||
msg[i] |= payload->payload.sol_packet.assert_ring_wor ? 0x20 : 0;
|
||||
msg[i] |= payload->payload.sol_packet.generate_break ? 0x10 : 0;
|
||||
msg[i] |= payload->payload.sol_packet.deassert_cts ? 0x08 : 0;
|
||||
msg[i] |= payload->payload.sol_packet.deassert_dcd_dsr ? 0x04 : 0;
|
||||
msg[i] |= payload->payload.sol_packet.flush_inbound ? 0x02 : 0;
|
||||
msg[i++] |= payload->payload.sol_packet.flush_outbound ? 0x01 : 0;
|
||||
|
||||
/* We may have data to add */
|
||||
memcpy(msg + i,
|
||||
payload->payload.sol_packet.data,
|
||||
payload->payload_length);
|
||||
|
||||
/*
|
||||
* At this point, the payload length becomes the whole payload
|
||||
* length, including the 4 bytes at the beginning of the SOL
|
||||
* packet
|
||||
*/
|
||||
payload->payload_length = payload->payload_length + 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ipmi_lanplus_build_v2x_msg
|
||||
*
|
||||
@ -1177,6 +1334,13 @@ void
|
||||
payload->payload.ipmi_request.rq_seq);
|
||||
break;
|
||||
|
||||
case IPMI_PAYLOAD_TYPE_SOL:
|
||||
getSolPayloadWireRep(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
|
||||
payload);
|
||||
len += payload->payload_length;
|
||||
|
||||
break;
|
||||
|
||||
case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
|
||||
/* never encrypted, so our job is easy */
|
||||
memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
|
||||
@ -1201,7 +1365,6 @@ void
|
||||
len += payload->payload_length;
|
||||
break;
|
||||
|
||||
case IPMI_PAYLOAD_TYPE_SOL:
|
||||
default:
|
||||
printf("unsupported payload type 0x%x\n", payload->payload_type);
|
||||
assert(0);
|
||||
@ -1209,7 +1372,6 @@ void
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*------------------------------------------
|
||||
* ENCRYPT THE PAYLOAD IF NECESSARY
|
||||
@ -1342,9 +1504,10 @@ static struct ipmi_rq_entry *
|
||||
struct ipmi_rq_entry * entry;
|
||||
|
||||
/*
|
||||
* We have a problem. we need to know the sequence number here, because we use it
|
||||
* in our stored entry. But we also need to know the sequence number when we
|
||||
* generate our IPMI representation far below.
|
||||
* We have a problem. we need to know the sequence number here,
|
||||
* because we use it in our stored entry. But we also need to
|
||||
* know the sequence number when we generate our IPMI
|
||||
* representation far below.
|
||||
*/
|
||||
static unsigned char curr_seq = 0;
|
||||
if (curr_seq >= 64)
|
||||
@ -1455,7 +1618,9 @@ static struct ipmi_rq_entry *
|
||||
/*
|
||||
* ipmi session header
|
||||
*/
|
||||
/* Authtype should always be none for 1.5 packets sent from this interface */
|
||||
/* Authtype should always be none for 1.5 packets sent from this
|
||||
* interface
|
||||
*/
|
||||
msg[len++] = IPMI_SESSION_AUTHTYPE_NONE;
|
||||
|
||||
msg[len++] = session->out_seq & 0xff;
|
||||
@ -1464,9 +1629,9 @@ static struct ipmi_rq_entry *
|
||||
msg[len++] = (session->out_seq >> 24) & 0xff;
|
||||
|
||||
/*
|
||||
* The session ID should be all zeroes for pre-session commands. We should only
|
||||
* be using the 1.5 interface for the pre-session Get Channel Authentication
|
||||
* Capabilities command
|
||||
* The session ID should be all zeroes for pre-session commands. We
|
||||
* should only be using the 1.5 interface for the pre-session Get
|
||||
* Channel Authentication Capabilities command
|
||||
*/
|
||||
msg[len++] = 0;
|
||||
msg[len++] = 0;
|
||||
@ -1556,23 +1721,39 @@ struct ipmi_rs *
|
||||
struct ipmi_rq_entry * entry;
|
||||
struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request;
|
||||
|
||||
if (verbose >= 1)
|
||||
{
|
||||
unsigned short i;
|
||||
|
||||
printf("\n");
|
||||
printf(">> Sending IPMI command payload\n");
|
||||
printf(">> netfn : 0x%02x\n", ipmi_request->msg.netfn);
|
||||
printf(">> command : 0x%02x\n", ipmi_request->msg.cmd);
|
||||
printf(">> data : ");
|
||||
|
||||
for (i = 0; i < ipmi_request->msg.data_len; ++i)
|
||||
printf("0x%02x ", ipmi_request->msg.data[i]);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we are presession, and the command is GET CHANNEL AUTHENTICATION
|
||||
* CAPABILITIES, we will build the command in v1.5 format. This is so
|
||||
* that we can ask any server whether it supports IPMI v2 / RMCP+ before
|
||||
* we attempt to open a v2.x session.
|
||||
* that we can ask any server whether it supports IPMI v2 / RMCP+
|
||||
* before we attempt to open a v2.x session.
|
||||
*/
|
||||
if ((ipmi_request->msg.netfn == IPMI_NETFN_APP) &&
|
||||
(ipmi_request->msg.cmd == IPMI_GET_CHANNEL_AUTH_CAP) &&
|
||||
(session->v2_data.bmc_id == 0)) // jme - check
|
||||
{
|
||||
if (verbose)
|
||||
if (verbose >= 2)
|
||||
printf("BUILDING A v1.5 COMMAND\n");
|
||||
entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbose)
|
||||
if (verbose >= 2)
|
||||
printf("BUILDING A v2 COMMAND\n");
|
||||
entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request);
|
||||
}
|
||||
@ -1603,7 +1784,8 @@ struct ipmi_rs *
|
||||
{
|
||||
if (verbose)
|
||||
printf(">> SENDING A RAKP 1 MESSAGE \n\n");
|
||||
assert(session->v2_data.session_state == LANPLUS_STATE_OPEN_SESSION_RECEIEVED);
|
||||
assert(session->v2_data.session_state ==
|
||||
LANPLUS_STATE_OPEN_SESSION_RECEIEVED);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
@ -1616,7 +1798,8 @@ struct ipmi_rs *
|
||||
{
|
||||
if (verbose)
|
||||
printf(">> SENDING A RAKP 3 MESSAGE \n\n");
|
||||
assert(session->v2_data.session_state == LANPLUS_STATE_RAKP_2_RECEIVED);
|
||||
assert(session->v2_data.session_state ==
|
||||
LANPLUS_STATE_RAKP_2_RECEIVED);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
@ -1625,6 +1808,18 @@ struct ipmi_rs *
|
||||
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
|
||||
{
|
||||
if (verbose)
|
||||
printf(">> SENDING A SOL MESSAGE \n\n");
|
||||
assert(session->v2_data.session_state == LANPLUS_STATE_ACTIVE);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
&msg_length, /* out */
|
||||
&msg_data); /* out */
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
@ -1659,6 +1854,13 @@ struct ipmi_rs *
|
||||
break;
|
||||
}
|
||||
|
||||
if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
|
||||
{
|
||||
// jme : todo. If the payload is not an ACK we need to wait
|
||||
// for an ack. And if we don't receive an ACK, we need to
|
||||
// resend.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
rsp = ipmi_lan_poll_recv(intf);
|
||||
@ -1674,6 +1876,45 @@ struct ipmi_rs *
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ipmi_lanplus_recv_sol
|
||||
*
|
||||
* Receive a SOL packet and send an ACK in response.
|
||||
*
|
||||
*/
|
||||
struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf)
|
||||
{
|
||||
struct ipmi_v2_payload ack;
|
||||
struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf);
|
||||
|
||||
/* If the SOL packet looks good, ACK it */
|
||||
if (rsp)
|
||||
{
|
||||
bzero(&ack, sizeof(struct ipmi_v2_payload));
|
||||
|
||||
ack.payload_type = IPMI_PAYLOAD_TYPE_SOL;
|
||||
|
||||
/*
|
||||
* Payload length is just the length of the character
|
||||
* data here.
|
||||
*/
|
||||
ack.payload_length = 0;
|
||||
|
||||
ack.payload.sol_packet.packet_sequence_number =
|
||||
intf->session->sol_data.sequence_number++;
|
||||
|
||||
ack.payload.sol_packet.acked_packet_number =
|
||||
rsp->payload.sol_packet.packet_sequence_number;
|
||||
|
||||
ack.payload.sol_packet.accepted_character_count = rsp->data_len;
|
||||
|
||||
ipmi_lanplus_send_payload(intf, &ack);
|
||||
}
|
||||
|
||||
return rsp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ipmi_lanplus_send_ipmi_cmd
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user