mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
fix SOLv2 NACK and retry handling for Intel ESB2 BMC
This commit is contained in:
parent
fa21266ec2
commit
d572add750
@ -530,6 +530,7 @@ typedef enum IPMI_OEM {
|
||||
IPMI_OEM_TYAN = 6653,
|
||||
IPMI_OEM_NEWISYS = 9237,
|
||||
IPMI_OEM_SUPERMICRO = 10876,
|
||||
IPMI_OEM_GOOGLE = 11129,
|
||||
IPMI_OEM_KONTRON = 15000,
|
||||
} IPMI_OEM;
|
||||
|
||||
|
@ -97,13 +97,13 @@ void printbuf(const uint8_t * buf, int len, const char * desc)
|
||||
if (verbose < 1)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "%s (%d bytes)\n", desc, len);
|
||||
fprintf(stderr, "%s (%d bytes)\r\n", desc, len);
|
||||
for (i=0; i<len; i++) {
|
||||
if (((i%16) == 0) && (i != 0))
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "\r\n");
|
||||
fprintf(stderr, " %2.2x", buf[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "\r\n");
|
||||
}
|
||||
|
||||
const char * val2str(uint16_t val, const struct valstr *vs)
|
||||
|
@ -104,9 +104,9 @@ ipmi_get_sol_info(
|
||||
{
|
||||
struct ipmi_rs * rsp;
|
||||
struct ipmi_rq req;
|
||||
uint8_t data[4];
|
||||
uint8_t data[4];
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_TRANSPORT;
|
||||
req.msg.cmd = IMPI_GET_SOL_CONFIG_PARAMETERS;
|
||||
req.msg.data_len = 4;
|
||||
@ -121,12 +121,12 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SET_IN_PROGRESS; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 2) {
|
||||
params->set_in_progress = rsp->data[1];
|
||||
} else {
|
||||
@ -137,12 +137,12 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
val2str(data[1], sol_parameter_vals));
|
||||
break;
|
||||
default:
|
||||
lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
|
||||
val2str(data[1], sol_parameter_vals),
|
||||
val2str(data[1], sol_parameter_vals),
|
||||
val2str(rsp->ccode, completion_code_vals));
|
||||
return -1;
|
||||
}
|
||||
@ -159,12 +159,12 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SOL_ENABLE; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 2) {
|
||||
params->enabled = rsp->data[1];
|
||||
} else {
|
||||
@ -175,7 +175,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
val2str(data[1], sol_parameter_vals));
|
||||
break;
|
||||
default:
|
||||
@ -197,11 +197,11 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SOL_AUTHENTICATION; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 2) {
|
||||
params->force_encryption = ((rsp->data[1] & 0x80)? 1 : 0);
|
||||
params->force_authentication = ((rsp->data[1] & 0x40)? 1 : 0);
|
||||
@ -214,7 +214,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
val2str(data[1], sol_parameter_vals));
|
||||
break;
|
||||
default:
|
||||
@ -236,11 +236,11 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_CHARACTER_INTERVAL; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 3) {
|
||||
params->character_accumulate_level = rsp->data[1];
|
||||
params->character_send_threshold = rsp->data[2];
|
||||
@ -252,7 +252,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
val2str(data[1], sol_parameter_vals));
|
||||
break;
|
||||
default:
|
||||
@ -274,14 +274,14 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SOL_RETRY; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 3) {
|
||||
params->retry_count = rsp->data[1];
|
||||
params->retry_interval = rsp->data[2];
|
||||
params->retry_interval = rsp->data[2];
|
||||
} else {
|
||||
lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
|
||||
"for SOL parameter '%s'",
|
||||
@ -290,7 +290,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
val2str(data[1], sol_parameter_vals));
|
||||
break;
|
||||
default:
|
||||
@ -312,11 +312,11 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 2) {
|
||||
params->non_volatile_bit_rate = rsp->data[1] & 0x0F;
|
||||
} else {
|
||||
@ -327,7 +327,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
val2str(data[1], sol_parameter_vals));
|
||||
break;
|
||||
default:
|
||||
@ -349,11 +349,11 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SOL_VOLATILE_BIT_RATE; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 2) {
|
||||
params->volatile_bit_rate = rsp->data[1] & 0x0F;
|
||||
} else {
|
||||
@ -364,7 +364,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
|
||||
val2str(data[1], sol_parameter_vals));
|
||||
break;
|
||||
default:
|
||||
@ -386,11 +386,11 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SOL_PAYLOAD_CHANNEL; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 2) {
|
||||
params->payload_channel = rsp->data[1];
|
||||
} else {
|
||||
@ -401,7 +401,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to 0x%02x",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to 0x%02x",
|
||||
val2str(data[1], sol_parameter_vals), channel);
|
||||
params->payload_channel = channel;
|
||||
break;
|
||||
@ -424,11 +424,11 @@ ipmi_get_sol_info(
|
||||
data[1] = SOL_PARAMETER_SOL_PAYLOAD_PORT; /* parameter selector */
|
||||
data[2] = 0x00; /* set selector */
|
||||
data[3] = 0x00; /* block selector */
|
||||
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
if (rsp->data_len == 3) {
|
||||
params->payload_port = (rsp->data[1]) | (rsp->data[2] << 8);
|
||||
} else {
|
||||
@ -439,7 +439,7 @@ ipmi_get_sol_info(
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to %d",
|
||||
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to %d",
|
||||
val2str(data[1], sol_parameter_vals), intf->session->port);
|
||||
params->payload_port = intf->session->port;
|
||||
break;
|
||||
@ -468,7 +468,7 @@ ipmi_print_sol_info(struct ipmi_intf * intf, uint8_t channel)
|
||||
struct sol_config_parameters params = {0};
|
||||
if (ipmi_get_sol_info(intf, channel, ¶ms))
|
||||
return -1;
|
||||
|
||||
|
||||
if (csv_output)
|
||||
{
|
||||
printf("%s,",
|
||||
@ -549,16 +549,15 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
{
|
||||
struct ipmi_rs * rsp;
|
||||
struct ipmi_rq req;
|
||||
uint8_t data[4];
|
||||
uint8_t data[4];
|
||||
int bGuarded = 1; /* Use set-in-progress indicator? */
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_TRANSPORT; /* 0x0c */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_TRANSPORT; /* 0x0c */
|
||||
req.msg.cmd = IMPI_SET_SOL_CONFIG_PARAMETERS; /* 0x21 */
|
||||
req.msg.data = data;
|
||||
|
||||
|
||||
data[0] = channel;
|
||||
|
||||
|
||||
/*
|
||||
* set-in-progress
|
||||
@ -638,11 +637,11 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
param);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
data[2] |= params.force_authentication? 0x40 : 0x00;
|
||||
data[2] |= params.privilege_level;
|
||||
data[2] |= params.privilege_level;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* force-payload-authentication
|
||||
@ -676,9 +675,9 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
}
|
||||
|
||||
data[2] |= params.force_encryption? 0x80 : 0x00;
|
||||
data[2] |= params.privilege_level;
|
||||
data[2] |= params.privilege_level;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* privilege-level
|
||||
@ -738,7 +737,7 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
param);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
data[3] = params.character_send_threshold;
|
||||
}
|
||||
|
||||
@ -764,7 +763,7 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
|
||||
data[2] = params.character_accumulate_level;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* retry-count
|
||||
@ -807,11 +806,11 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
param);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
data[2] = params.retry_count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* non-volatile-bit-rate
|
||||
*/
|
||||
@ -853,7 +852,7 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* volatile-bit-rate
|
||||
@ -896,7 +895,6 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
lprintf(LOG_ERR, "Error: invalid SOL parameter %s", param);
|
||||
@ -924,7 +922,7 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
if (rsp == NULL) {
|
||||
lprintf(LOG_ERR, "Error setting SOL parameter '%s'", param);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rsp->ccode > 0) {
|
||||
lprintf(LOG_ERR, "Error setting SOL parameter '%s': %s",
|
||||
@ -938,9 +936,8 @@ ipmi_sol_set_param(struct ipmi_intf * intf,
|
||||
{
|
||||
lprintf(LOG_ERR, "Error could not set \"set-in-progress\" "
|
||||
"to \"set-complete\"");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1084,9 +1081,21 @@ printSolEscapeSequences(struct ipmi_intf * intf)
|
||||
static void
|
||||
output(struct ipmi_rs * rsp)
|
||||
{
|
||||
if (rsp)
|
||||
/* Add checks to make sure it is actually SOL data, in general I see
|
||||
* outside code mostly trying to guard against this happening, but
|
||||
* some places fail to do so, so I do so here to make sure nothing gets
|
||||
* through. If non-sol data comes through here, there is probably
|
||||
* a packet that won't get processed somewhere else, but the alternative
|
||||
* of outputting corrupt data is worse. Generally I see the get device
|
||||
* id response make it here somehow. I assume it is a heartbeat and the
|
||||
* other code will retry if it cares about the response and misses it.
|
||||
*/
|
||||
if (rsp &&
|
||||
(rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
|
||||
(rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rsp->data_len; ++i)
|
||||
putc(rsp->data[i], stdout);
|
||||
|
||||
@ -1104,9 +1113,9 @@ ipmi_sol_deactivate(struct ipmi_intf * intf)
|
||||
{
|
||||
struct ipmi_rs * rsp;
|
||||
struct ipmi_rq req;
|
||||
uint8_t data[6];
|
||||
uint8_t data[6];
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_APP;
|
||||
req.msg.cmd = IPMI_DEACTIVATE_PAYLOAD;
|
||||
req.msg.data_len = 6;
|
||||
@ -1126,7 +1135,7 @@ ipmi_sol_deactivate(struct ipmi_intf * intf)
|
||||
|
||||
if (NULL != rsp) {
|
||||
switch (rsp->ccode) {
|
||||
case 0x00:
|
||||
case 0x00:
|
||||
return 0;
|
||||
case 0x80:
|
||||
lprintf(LOG_ERR, "Info: SOL payload already de-activated");
|
||||
@ -1144,7 +1153,7 @@ ipmi_sol_deactivate(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1184,7 +1193,7 @@ processSolUserInput(
|
||||
|
||||
if (escape_pending){
|
||||
escape_pending = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Process a possible escape sequence.
|
||||
*/
|
||||
@ -1242,7 +1251,7 @@ processSolUserInput(
|
||||
last_was_cr = (ch == '\r' || ch == '\n');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* If there is anything left to process we dispatch it to the BMC,
|
||||
* send intf->session->sol_data.max_outbound_payload_size bytes
|
||||
@ -1254,8 +1263,9 @@ processSolUserInput(
|
||||
int try = 0;
|
||||
|
||||
while (try < intf->session->retry) {
|
||||
|
||||
|
||||
v2_payload.payload.sol_packet.character_count = length;
|
||||
|
||||
rsp = intf->send_sol(intf, &v2_payload);
|
||||
|
||||
if (rsp)
|
||||
@ -1308,7 +1318,6 @@ ipmi_sol_keepalive(struct ipmi_intf * intf)
|
||||
static int
|
||||
ipmi_sol_red_pill(struct ipmi_intf * intf)
|
||||
{
|
||||
|
||||
char * buffer;
|
||||
int numRead;
|
||||
int bShouldExit = 0;
|
||||
@ -1326,7 +1335,7 @@ ipmi_sol_red_pill(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
/* Initialize keepalive start time */
|
||||
gettimeofday(&_start_keepalive, 0);
|
||||
gettimeofday(&_start_keepalive, 0);
|
||||
|
||||
enter_raw_mode();
|
||||
|
||||
@ -1370,11 +1379,11 @@ ipmi_sol_red_pill(struct ipmi_intf * intf)
|
||||
numRead = read(fileno(stdin),
|
||||
buffer,
|
||||
buffer_size);
|
||||
|
||||
|
||||
if (numRead > 0)
|
||||
{
|
||||
int rc = processSolUserInput(intf, (uint8_t *)buffer, numRead);
|
||||
|
||||
|
||||
if (rc)
|
||||
{
|
||||
if (rc < 0)
|
||||
@ -1401,7 +1410,9 @@ ipmi_sol_red_pill(struct ipmi_intf * intf)
|
||||
bShouldExit = bBmcClosedSession = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
output(rs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1449,7 +1460,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval)
|
||||
struct ipmi_rs * rsp;
|
||||
struct ipmi_rq req;
|
||||
struct activate_payload_rsp ap_rsp;
|
||||
uint8_t data[6];
|
||||
uint8_t data[6];
|
||||
uint8_t bSolEncryption = 1;
|
||||
uint8_t bSolAuthentication = 1;
|
||||
|
||||
@ -1497,7 +1508,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval)
|
||||
data[4] = 0x00; /* reserved */
|
||||
data[5] = 0x00; /* reserved */
|
||||
|
||||
G_u8ActiveSOL = 1;
|
||||
G_u8ActiveSOL = 1;
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
|
||||
if (NULL != rsp) {
|
||||
@ -1539,7 +1550,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval)
|
||||
|
||||
|
||||
memcpy(&ap_rsp, rsp->data, sizeof(struct activate_payload_rsp));
|
||||
|
||||
|
||||
intf->session->sol_data.max_inbound_payload_size =
|
||||
(ap_rsp.inbound_payload_size[1] << 8) |
|
||||
ap_rsp.inbound_payload_size[0];
|
||||
@ -1551,7 +1562,6 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval)
|
||||
intf->session->sol_data.port =
|
||||
(ap_rsp.payload_udp_port[1] << 8) |
|
||||
ap_rsp.payload_udp_port[0];
|
||||
|
||||
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
@ -1564,7 +1574,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval)
|
||||
#endif
|
||||
|
||||
|
||||
intf->session->timeout = 3;
|
||||
intf->session->timeout = 1;
|
||||
|
||||
|
||||
/* NOTE: the spec does allow for SOL traffic to be sent on
|
||||
@ -1582,7 +1592,6 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("[SOL Session operational. Use %c? for help]\r\n",
|
||||
intf->session->sol_escape_char);
|
||||
@ -1592,7 +1601,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval)
|
||||
ipmi_sol_deactivate(intf);
|
||||
usleep(interval*1000);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we are good to go with our SOL session. We
|
||||
@ -1678,7 +1687,7 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
||||
channel = (uint8_t)strtol(argv[1], NULL, 0);
|
||||
else
|
||||
{
|
||||
print_sol_usage();
|
||||
print_sol_usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1701,13 +1710,13 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
||||
print_sol_set_usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
retval = ipmi_sol_set_param(intf,
|
||||
channel,
|
||||
argv[1],
|
||||
argv[2]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Activate
|
||||
@ -1715,12 +1724,13 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
||||
else if (!strncmp(argv[0], "activate", 8))
|
||||
retval = ipmi_sol_activate(intf, 0, 0);
|
||||
|
||||
|
||||
/*
|
||||
* Dectivate
|
||||
*/
|
||||
else if (!strncmp(argv[0], "deactivate", 10))
|
||||
retval = ipmi_sol_deactivate(intf);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* SOL loop test: Activate and then Dectivate
|
||||
@ -1730,9 +1740,9 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
||||
int cnt = 200;
|
||||
int interval = 100; /* Unit is: ms */
|
||||
|
||||
if(argc > 3)
|
||||
if (argc > 3)
|
||||
{
|
||||
print_sol_usage();
|
||||
print_sol_usage();
|
||||
return -1;
|
||||
}
|
||||
if (argc != 1) /* at least 2 */
|
||||
@ -1745,12 +1755,12 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
||||
interval = strtol(argv[2], NULL, 10);
|
||||
if(interval < 0) interval = 0;
|
||||
}
|
||||
|
||||
while(cnt > 0)
|
||||
|
||||
while (cnt > 0)
|
||||
{
|
||||
printf("remain loop test counter: %d\n", cnt);
|
||||
retval = ipmi_sol_activate(intf, 1, interval);
|
||||
if(retval)
|
||||
if (retval)
|
||||
{
|
||||
printf("SOL looptest failed: %d\n", retval);
|
||||
break;
|
||||
|
@ -44,6 +44,7 @@ const struct valstr ipmi_oem_info[] = {
|
||||
{ IPMI_OEM_TYAN, "Tyan Computer Corporation" },
|
||||
{ IPMI_OEM_NEWISYS, "Newisys" },
|
||||
{ IPMI_OEM_SUPERMICRO, "Supermicro" },
|
||||
{ IPMI_OEM_GOOGLE, "Google" },
|
||||
{ IPMI_OEM_KONTRON, "Kontron" },
|
||||
{ 0xffff , NULL },
|
||||
};
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
@ -40,9 +40,8 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
@ -76,9 +75,6 @@ static struct ipmi_rq_entry * ipmi_req_entries;
|
||||
static struct ipmi_rq_entry * ipmi_req_entries_tail;
|
||||
|
||||
|
||||
static sigjmp_buf jmpbuf;
|
||||
|
||||
|
||||
static int ipmi_lanplus_setup(struct ipmi_intf * intf);
|
||||
static int ipmi_lanplus_keepalive(struct ipmi_intf * intf);
|
||||
static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len);
|
||||
@ -265,13 +261,6 @@ void lanplus_swap(
|
||||
|
||||
|
||||
|
||||
static void
|
||||
query_alarm(int signo)
|
||||
{
|
||||
siglongjmp(jmpbuf, 1);
|
||||
}
|
||||
|
||||
|
||||
static const struct valstr plus_payload_types_vals[] = {
|
||||
{ IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message
|
||||
{ IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN)
|
||||
@ -384,7 +373,7 @@ ipmi_lan_send_packet(
|
||||
uint8_t * data, int
|
||||
data_len)
|
||||
{
|
||||
if (verbose >= 2)
|
||||
if (verbose >= 5)
|
||||
printbuf(data, data_len, ">> sending packet");
|
||||
|
||||
return send(intf->fd, data, data_len, 0);
|
||||
@ -396,17 +385,22 @@ struct ipmi_rs *
|
||||
ipmi_lan_recv_packet(struct ipmi_intf * intf)
|
||||
{
|
||||
static struct ipmi_rs rsp;
|
||||
int rc;
|
||||
fd_set read_set, err_set;
|
||||
struct timeval tmout;
|
||||
int ret;
|
||||
|
||||
/* setup alarm timeout */
|
||||
if (sigsetjmp(jmpbuf, 1) != 0) {
|
||||
alarm(0);
|
||||
FD_ZERO(&read_set);
|
||||
FD_SET(intf->fd, &read_set);
|
||||
|
||||
FD_ZERO(&err_set);
|
||||
FD_SET(intf->fd, &err_set);
|
||||
|
||||
tmout.tv_sec = intf->session->timeout;
|
||||
tmout.tv_usec = 0;
|
||||
|
||||
ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
|
||||
if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
alarm(intf->session->timeout);
|
||||
rc = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
|
||||
alarm(0);
|
||||
|
||||
/* the first read may return ECONNREFUSED because the rmcp ping
|
||||
* packet--sent to UDP port 623--will be processed by both the
|
||||
@ -415,25 +409,40 @@ ipmi_lan_recv_packet(struct ipmi_intf * intf)
|
||||
* The problem with this is that the ECONNREFUSED takes
|
||||
* priority over any other received datagram; that means that
|
||||
* the Connection Refused shows up _before_ the response packet,
|
||||
* regardless of the order they were sent out. (unless the
|
||||
* regardless of the order they were sent out. (unless the
|
||||
* response is read before the connection refused is returned)
|
||||
*/
|
||||
if (rc < 0) {
|
||||
alarm(intf->session->timeout);
|
||||
rc = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
|
||||
alarm(0);
|
||||
if (rc < 0) {
|
||||
perror("recv failed");
|
||||
return NULL;
|
||||
ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
FD_ZERO(&read_set);
|
||||
FD_SET(intf->fd, &read_set);
|
||||
|
||||
FD_ZERO(&err_set);
|
||||
FD_SET(intf->fd, &err_set);
|
||||
|
||||
tmout.tv_sec = intf->session->timeout;
|
||||
tmout.tv_usec = 0;
|
||||
|
||||
ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
|
||||
if (ret < 0) {
|
||||
if (FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
|
||||
return NULL;
|
||||
|
||||
ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
rsp.data[rc] = '\0';
|
||||
rsp.data_len = rc;
|
||||
|
||||
if (verbose >= 2)
|
||||
{
|
||||
printbuf(rsp.data, rsp.data_len, "<< Received data");
|
||||
}
|
||||
if (ret == 0)
|
||||
return NULL;
|
||||
|
||||
rsp.data[ret] = '\0';
|
||||
rsp.data_len = ret;
|
||||
|
||||
if (verbose >= 5)
|
||||
printbuf(rsp.data, rsp.data_len, "<< received packet");
|
||||
|
||||
return &rsp;
|
||||
}
|
||||
@ -1247,6 +1256,7 @@ void read_ipmi_response(struct ipmi_rs * rsp, int * offset)
|
||||
*/
|
||||
void read_sol_packet(struct ipmi_rs * rsp, int * offset)
|
||||
{
|
||||
|
||||
/*
|
||||
* The data here should be decrypted by now.
|
||||
*/
|
||||
@ -1265,38 +1275,34 @@ void read_sol_packet(struct ipmi_rs * rsp, int * offset)
|
||||
rsp->payload.sol_packet.transfer_unavailable =
|
||||
rsp->data[*offset] & 0x20;
|
||||
|
||||
rsp->payload.sol_packet.sol_inactive =
|
||||
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;
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL sequence number : 0x%02x",
|
||||
lprintf(LOG_DEBUG, "< SOL sequence number : 0x%02x",
|
||||
rsp->payload.sol_packet.packet_sequence_number);
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL acked packet : 0x%02x",
|
||||
lprintf(LOG_DEBUG, "< SOL acked packet : 0x%02x",
|
||||
rsp->payload.sol_packet.acked_packet_number);
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL accepted char count : 0x%02x",
|
||||
lprintf(LOG_DEBUG, "< SOL accepted char count : 0x%02x",
|
||||
rsp->payload.sol_packet.accepted_character_count);
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL is nack : %s",
|
||||
lprintf(LOG_DEBUG, "< SOL is nack : %s",
|
||||
rsp->payload.sol_packet.is_nack? "true" : "false");
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL xfer unavailable : %s",
|
||||
lprintf(LOG_DEBUG, "< SOL xfer unavailable : %s",
|
||||
rsp->payload.sol_packet.transfer_unavailable? "true" : "false");
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL inactive : %s",
|
||||
lprintf(LOG_DEBUG, "< SOL inactive : %s",
|
||||
rsp->payload.sol_packet.sol_inactive? "true" : "false");
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL transmit overrun : %s",
|
||||
lprintf(LOG_DEBUG, "< SOL transmit overrun : %s",
|
||||
rsp->payload.sol_packet.transmit_overrun? "true" : "false");
|
||||
|
||||
lprintf(LOG_DEBUG, "SOL break detected : %s",
|
||||
lprintf(LOG_DEBUG, "< SOL break detected : %s",
|
||||
rsp->payload.sol_packet.break_detected? "true" : "false");
|
||||
|
||||
if (verbose >= 5)
|
||||
printbuf(rsp->data + *offset - 4, 4, "SOL MSG FROM BMC");
|
||||
}
|
||||
|
||||
|
||||
@ -1409,10 +1415,31 @@ void getSolPayloadWireRep(
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
lprintf(LOG_DEBUG, "> SOL sequence number : 0x%02x",
|
||||
payload->payload.sol_packet.packet_sequence_number);
|
||||
lprintf(LOG_DEBUG, "> SOL acked packet : 0x%02x",
|
||||
payload->payload.sol_packet.acked_packet_number);
|
||||
lprintf(LOG_DEBUG, "> SOL accepted char count : 0x%02x",
|
||||
payload->payload.sol_packet.accepted_character_count);
|
||||
lprintf(LOG_DEBUG, "> SOL is nack : %s",
|
||||
payload->payload.sol_packet.is_nack ? "true" : "false");
|
||||
lprintf(LOG_DEBUG, "> SOL assert ring wor : %s",
|
||||
payload->payload.sol_packet.assert_ring_wor ? "true" : "false");
|
||||
lprintf(LOG_DEBUG, "> SOL generate break : %s",
|
||||
payload->payload.sol_packet.generate_break ? "true" : "false");
|
||||
lprintf(LOG_DEBUG, "> SOL deassert cts : %s",
|
||||
payload->payload.sol_packet.deassert_cts ? "true" : "false");
|
||||
lprintf(LOG_DEBUG, "> SOL deassert dcd dsr : %s",
|
||||
payload->payload.sol_packet.deassert_dcd_dsr ? "true" : "false");
|
||||
lprintf(LOG_DEBUG, "> SOL flush inbound : %s",
|
||||
payload->payload.sol_packet.flush_inbound ? "true" : "false");
|
||||
lprintf(LOG_DEBUG, "> SOL flush outbound : %s",
|
||||
payload->payload.sol_packet.flush_outbound ? "true" : "false");
|
||||
|
||||
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;
|
||||
@ -1426,6 +1453,12 @@ void getSolPayloadWireRep(
|
||||
payload->payload.sol_packet.data,
|
||||
payload->payload.sol_packet.character_count);
|
||||
|
||||
lprintf(LOG_DEBUG, "> SOL character count : %d",
|
||||
payload->payload.sol_packet.character_count);
|
||||
|
||||
if (payload->payload.sol_packet.character_count)
|
||||
printbuf(payload->payload.sol_packet.data, payload->payload.sol_packet.character_count, "SOL SEND DATA");
|
||||
|
||||
/*
|
||||
* At this point, the payload length becomes the whole payload
|
||||
* length, including the 4 bytes at the beginning of the SOL
|
||||
@ -1489,7 +1522,6 @@ ipmi_lanplus_build_v2x_msg(
|
||||
|
||||
/* msg will hold the entire message to be sent */
|
||||
uint8_t * msg;
|
||||
|
||||
int len = 0;
|
||||
|
||||
|
||||
@ -1531,7 +1563,6 @@ ipmi_lanplus_build_v2x_msg(
|
||||
/* Payload Type -- also specifies whether were authenticated/encyrpted */
|
||||
msg[IMPI_LANPLUS_OFFSET_PAYLOAD_TYPE] = payload->payload_type;
|
||||
|
||||
|
||||
if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
|
||||
{
|
||||
msg[IMPI_LANPLUS_OFFSET_PAYLOAD_TYPE] |=
|
||||
@ -1554,17 +1585,16 @@ ipmi_lanplus_build_v2x_msg(
|
||||
msg[IMPI_LANPLUS_OFFSET_SEQUENCE_NUM + 2] = (session->out_seq >> 16) & 0xff;
|
||||
msg[IMPI_LANPLUS_OFFSET_SEQUENCE_NUM + 3] = (session->out_seq >> 24) & 0xff;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Payload Length is set below (we don't know how big the payload is until after
|
||||
* encryption).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Payload
|
||||
*
|
||||
* At this point we are ready to slam the payload in.
|
||||
* At this point we are ready to slam the payload in.
|
||||
* This includes:
|
||||
* 1) The confidentiality header
|
||||
* 2) The payload proper (possibly encrypted)
|
||||
@ -1586,6 +1616,10 @@ ipmi_lanplus_build_v2x_msg(
|
||||
getSolPayloadWireRep(intf,
|
||||
msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
|
||||
payload);
|
||||
|
||||
if (verbose >= 5)
|
||||
printbuf(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 4, "SOL MSG TO BMC");
|
||||
|
||||
len += payload->payload_length;
|
||||
|
||||
break;
|
||||
@ -1640,14 +1674,12 @@ ipmi_lanplus_build_v2x_msg(
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Now we know the payload length */
|
||||
msg[IMPI_LANPLUS_OFFSET_PAYLOAD_SIZE ] =
|
||||
payload->payload_length & 0xff;
|
||||
msg[IMPI_LANPLUS_OFFSET_PAYLOAD_SIZE + 1] =
|
||||
(payload->payload_length >> 8) & 0xff;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*------------------------------------------
|
||||
@ -1684,11 +1716,10 @@ ipmi_lanplus_build_v2x_msg(
|
||||
|
||||
if (length_before_authcode % 4)
|
||||
integrity_pad_size = 4 - (length_before_authcode % 4);
|
||||
|
||||
|
||||
for (i = 0; i < integrity_pad_size; ++i)
|
||||
msg[start_of_session_trailer + i] = 0xFF;
|
||||
|
||||
|
||||
/* Pad length */
|
||||
msg[start_of_session_trailer + integrity_pad_size] = integrity_pad_size;
|
||||
|
||||
@ -1696,7 +1727,6 @@ ipmi_lanplus_build_v2x_msg(
|
||||
msg[start_of_session_trailer + integrity_pad_size + 1] =
|
||||
0x07; /* Hardcoded per the spec, table 13-8 */
|
||||
|
||||
|
||||
hmac_input_size =
|
||||
12 +
|
||||
payload->payload_length +
|
||||
@ -1771,9 +1801,9 @@ ipmi_lanplus_build_v2x_ipmi_cmd(
|
||||
* representation far below.
|
||||
*/
|
||||
static uint8_t curr_seq = 0;
|
||||
|
||||
curr_seq += 1;
|
||||
|
||||
|
||||
curr_seq += 1;
|
||||
|
||||
if (curr_seq >= 64)
|
||||
curr_seq = 0;
|
||||
|
||||
@ -1786,12 +1816,12 @@ ipmi_lanplus_build_v2x_ipmi_cmd(
|
||||
v2_payload.payload_length = req->msg.data_len + 7;
|
||||
v2_payload.payload.ipmi_request.request = req;
|
||||
v2_payload.payload.ipmi_request.rq_seq = curr_seq;
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, // in
|
||||
&v2_payload, // in
|
||||
&(entry->msg_len), // out
|
||||
&(entry->msg_data), // out
|
||||
curr_seq); // in
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, // in
|
||||
&v2_payload, // in
|
||||
&(entry->msg_len), // out
|
||||
&(entry->msg_data), // out
|
||||
curr_seq); // in
|
||||
|
||||
return entry;
|
||||
}
|
||||
@ -1975,132 +2005,137 @@ ipmi_lanplus_send_payload(
|
||||
struct ipmi_v2_payload * payload)
|
||||
{
|
||||
struct ipmi_rs * rsp = NULL;
|
||||
uint8_t * msg_data;
|
||||
uint8_t * msg_data;
|
||||
int msg_length;
|
||||
struct ipmi_session * session = intf->session;
|
||||
int try = 0;
|
||||
int xmit = 1;
|
||||
time_t ltime;
|
||||
|
||||
if (!intf->opened && intf->open && intf->open(intf) < 0)
|
||||
return NULL;
|
||||
|
||||
if (payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI)
|
||||
{
|
||||
/*
|
||||
* Build an IPMI v1.5 or v2 command
|
||||
*/
|
||||
struct ipmi_rq_entry * entry;
|
||||
struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request;
|
||||
|
||||
lprintf(LOG_DEBUG, "");
|
||||
lprintf(LOG_DEBUG, ">> Sending IPMI command payload");
|
||||
lprintf(LOG_DEBUG, ">> netfn : 0x%02x", ipmi_request->msg.netfn);
|
||||
lprintf(LOG_DEBUG, ">> command : 0x%02x", ipmi_request->msg.cmd);
|
||||
|
||||
if (verbose > 1)
|
||||
{
|
||||
uint16_t i;
|
||||
fprintf(stderr, ">> data : ");
|
||||
for (i = 0; i < ipmi_request->msg.data_len; ++i)
|
||||
fprintf(stderr, "0x%02x ", ipmi_request->msg.data[i]);
|
||||
fprintf(stderr, "\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.
|
||||
*/
|
||||
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
|
||||
{
|
||||
lprintf(LOG_DEBUG+1, "BUILDING A v1.5 COMMAND");
|
||||
entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request);
|
||||
}
|
||||
else
|
||||
{
|
||||
lprintf(LOG_DEBUG+1, "BUILDING A v2 COMMAND");
|
||||
entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request);
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
lprintf(LOG_ERR, "Aborting send command, unable to build");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg_data = entry->msg_data;
|
||||
msg_length = entry->msg_len;
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n");
|
||||
assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
&msg_length, /* out */
|
||||
&msg_data, /* out */
|
||||
0); /* irrelevant for this msg*/
|
||||
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_1)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING A RAKP 1 MESSAGE\n");
|
||||
assert(session->v2_data.session_state ==
|
||||
LANPLUS_STATE_OPEN_SESSION_RECEIEVED);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
&msg_length, /* out */
|
||||
&msg_data, /* out */
|
||||
0); /* irrelevant for this msg*/
|
||||
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_3)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING A RAKP 3 MESSAGE\n");
|
||||
assert(session->v2_data.session_state ==
|
||||
LANPLUS_STATE_RAKP_2_RECEIVED);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
&msg_length, /* out */
|
||||
&msg_data, /* out */
|
||||
0); /* irrelevant for this msg*/
|
||||
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\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 */
|
||||
0); /* irrelevant for this msg*/
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
lprintf(LOG_ERR, "Payload type 0x%0x is unsupported!",
|
||||
payload->payload_type);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
while (try < session->retry) {
|
||||
ltime = time(NULL);
|
||||
|
||||
if (xmit) {
|
||||
|
||||
if (payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI)
|
||||
{
|
||||
/*
|
||||
* Build an IPMI v1.5 or v2 command
|
||||
*/
|
||||
struct ipmi_rq_entry * entry;
|
||||
struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request;
|
||||
|
||||
lprintf(LOG_DEBUG, "");
|
||||
lprintf(LOG_DEBUG, ">> Sending IPMI command payload");
|
||||
lprintf(LOG_DEBUG, ">> netfn : 0x%02x", ipmi_request->msg.netfn);
|
||||
lprintf(LOG_DEBUG, ">> command : 0x%02x", ipmi_request->msg.cmd);
|
||||
|
||||
if (verbose > 1)
|
||||
{
|
||||
uint16_t i;
|
||||
fprintf(stderr, ">> data : ");
|
||||
for (i = 0; i < ipmi_request->msg.data_len; ++i)
|
||||
fprintf(stderr, "0x%02x ", ipmi_request->msg.data[i]);
|
||||
fprintf(stderr, "\n\n");
|
||||
}
|
||||
|
||||
|
||||
if (ipmi_lan_send_packet(intf, msg_data, msg_length) < 0) {
|
||||
lprintf(LOG_ERR, "IPMI LAN send command failed");
|
||||
return NULL;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
{
|
||||
lprintf(LOG_DEBUG+1, "BUILDING A v1.5 COMMAND");
|
||||
entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request);
|
||||
}
|
||||
else
|
||||
{
|
||||
lprintf(LOG_DEBUG+1, "BUILDING A v2 COMMAND");
|
||||
entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request);
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
lprintf(LOG_ERR, "Aborting send command, unable to build");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg_data = entry->msg_data;
|
||||
msg_length = entry->msg_len;
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n");
|
||||
assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
&msg_length, /* out */
|
||||
&msg_data, /* out */
|
||||
0); /* irrelevant for this msg*/
|
||||
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_1)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING A RAKP 1 MESSAGE\n");
|
||||
assert(session->v2_data.session_state ==
|
||||
LANPLUS_STATE_OPEN_SESSION_RECEIEVED);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
&msg_length, /* out */
|
||||
&msg_data, /* out */
|
||||
0); /* irrelevant for this msg*/
|
||||
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_3)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING A RAKP 3 MESSAGE\n");
|
||||
assert(session->v2_data.session_state ==
|
||||
LANPLUS_STATE_RAKP_2_RECEIVED);
|
||||
|
||||
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
||||
payload, /* in */
|
||||
&msg_length, /* out */
|
||||
&msg_data, /* out */
|
||||
0); /* irrelevant for this msg*/
|
||||
|
||||
}
|
||||
|
||||
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
|
||||
{
|
||||
lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\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 */
|
||||
0); /* irrelevant for this msg*/
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
lprintf(LOG_ERR, "Payload type 0x%0x is unsupported!",
|
||||
payload->payload_type);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
if (ipmi_lan_send_packet(intf, msg_data, msg_length) < 0) {
|
||||
lprintf(LOG_ERR, "IPMI LAN send command failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we are set to noanswer we do not expect response */
|
||||
@ -2173,11 +2208,17 @@ ipmi_lanplus_send_payload(
|
||||
rsp = ipmi_lan_poll_recv(intf);
|
||||
if (rsp)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
xmit = ((time(NULL) - ltime) >= intf->session->timeout);
|
||||
|
||||
usleep(5000);
|
||||
|
||||
if (xmit) {
|
||||
/* incremet session timeout each retry */
|
||||
intf->session->timeout++;
|
||||
}
|
||||
|
||||
try++;
|
||||
}
|
||||
|
||||
@ -2205,6 +2246,7 @@ ipmi_lanplus_send_payload(
|
||||
* 0 if this isn't an ACK or we don't need to resend anything
|
||||
*/
|
||||
int is_sol_partial_ack(
|
||||
struct ipmi_intf * intf,
|
||||
struct ipmi_v2_payload * v2_payload,
|
||||
struct ipmi_rs * rs)
|
||||
{
|
||||
@ -2217,6 +2259,10 @@ int is_sol_partial_ack(
|
||||
(rs->payload.sol_packet.accepted_character_count <
|
||||
v2_payload->payload.sol_packet.character_count))
|
||||
{
|
||||
if (ipmi_oem_active(intf, "intelplus") &&
|
||||
rs->payload.sol_packet.accepted_character_count == 0)
|
||||
return 0;
|
||||
|
||||
chars_to_resend =
|
||||
v2_payload->payload.sol_packet.character_count -
|
||||
rs->payload.sol_packet.accepted_character_count;
|
||||
@ -2277,16 +2323,17 @@ ipmi_lanplus_send_sol(
|
||||
v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */
|
||||
|
||||
set_sol_packet_sequence_number(intf, v2_payload);
|
||||
|
||||
|
||||
v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */
|
||||
|
||||
rs = ipmi_lanplus_send_payload(intf, v2_payload);
|
||||
|
||||
/* Determine if we need to resend some of our data */
|
||||
chars_to_resend = is_sol_partial_ack(v2_payload, rs);
|
||||
chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
|
||||
|
||||
|
||||
while (chars_to_resend)
|
||||
while (rs && !rs->payload.sol_packet.transfer_unavailable &&
|
||||
!rs->payload.sol_packet.is_nack &&
|
||||
chars_to_resend)
|
||||
{
|
||||
/*
|
||||
* We first need to handle any new data we might have
|
||||
@ -2296,7 +2343,7 @@ ipmi_lanplus_send_sol(
|
||||
intf->session->sol_data.sol_input_handler(rs);
|
||||
|
||||
set_sol_packet_sequence_number(intf, v2_payload);
|
||||
|
||||
|
||||
/* Just send the required data */
|
||||
memmove(v2_payload->payload.sol_packet.data,
|
||||
v2_payload->payload.sol_packet.data +
|
||||
@ -2309,7 +2356,7 @@ ipmi_lanplus_send_sol(
|
||||
|
||||
rs = ipmi_lanplus_send_payload(intf, v2_payload);
|
||||
|
||||
chars_to_resend = is_sol_partial_ack(v2_payload, rs);
|
||||
chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
|
||||
}
|
||||
|
||||
return rs;
|
||||
@ -2533,7 +2580,7 @@ ipmi_get_auth_capabilities_cmd(
|
||||
}
|
||||
if (rsp->ccode > 0) {
|
||||
lprintf(LOG_INFO, "Get Auth Capabilities error: %s",
|
||||
val2str(rsp->ccode, completion_code_vals));
|
||||
val2str(rsp->ccode, completion_code_vals));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -3172,7 +3219,6 @@ int
|
||||
ipmi_lanplus_open(struct ipmi_intf * intf)
|
||||
{
|
||||
int rc;
|
||||
struct sigaction act;
|
||||
struct get_channel_auth_cap_rsp auth_cap;
|
||||
struct sockaddr_in addr;
|
||||
struct ipmi_session *session;
|
||||
@ -3250,16 +3296,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* setup alarm handler */
|
||||
act.sa_handler = query_alarm;
|
||||
act.sa_flags = 0;
|
||||
if (sigemptyset(&act.sa_mask) == 0 &&
|
||||
sigaction(SIGALRM, &act, NULL) < 0) {
|
||||
lperror(LOG_ERR, "alarm signal");
|
||||
intf->close(intf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
intf->opened = 1;
|
||||
|
||||
|
||||
|
@ -66,7 +66,7 @@
|
||||
#define IPMI_LAN_CHANNEL_2 0x06
|
||||
#define IPMI_LAN_CHANNEL_E 0x0e
|
||||
|
||||
#define IPMI_LAN_TIMEOUT 2
|
||||
#define IPMI_LAN_TIMEOUT 1
|
||||
#define IPMI_LAN_RETRY 4
|
||||
|
||||
#define IPMI_PRIV_CALLBACK 1
|
||||
|
@ -30,6 +30,7 @@
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include "ipmitool/log.h"
|
||||
#include "ipmitool/ipmi_constants.h"
|
||||
#include "lanplus.h"
|
||||
#include "lanplus_crypt_impl.h"
|
||||
@ -124,7 +125,7 @@ lanplus_HMAC(uint8_t mac,
|
||||
evp_md = EVP_sha1();
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid mac type 0x%x in lanplus_HMAC\n", mac);
|
||||
lprintf(LOG_DEBUG, "Invalid mac type 0x%x in lanplus_HMAC\n", mac);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
@ -165,7 +166,7 @@ lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
|
||||
if (input_length == 0)
|
||||
return;
|
||||
|
||||
if (verbose > 2)
|
||||
if (verbose >= 5)
|
||||
{
|
||||
printbuf(iv, 16, "encrypting with this IV");
|
||||
printbuf(key, 16, "encrypting with this key");
|
||||
@ -233,10 +234,9 @@ lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
if (verbose >= 5)
|
||||
{
|
||||
printbuf(iv, 16, "decrypting with this IV");
|
||||
printbuf(key, 16, "decrypting with this key");
|
||||
@ -260,7 +260,7 @@ lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
|
||||
if (!EVP_DecryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
|
||||
{
|
||||
/* Error */
|
||||
fprintf(stderr, "ERROR: decrypt update failed");
|
||||
lprintf(LOG_DEBUG, "ERROR: decrypt update failed");
|
||||
*bytes_written = 0;
|
||||
return;
|
||||
}
|
||||
@ -272,8 +272,8 @@ lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
|
||||
{
|
||||
char buffer[1000];
|
||||
ERR_error_string(ERR_get_error(), buffer);
|
||||
fprintf(stderr, "the ERR error %s", buffer);
|
||||
fprintf(stderr, "ERROR: decrypt final failed");
|
||||
lprintf(LOG_DEBUG, "the ERR error %s", buffer);
|
||||
lprintf(LOG_DEBUG, "ERROR: decrypt final failed");
|
||||
*bytes_written = 0;
|
||||
return; /* Error */
|
||||
}
|
||||
@ -285,9 +285,9 @@ lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose > 1)
|
||||
if (verbose >= 5)
|
||||
{
|
||||
fprintf(stderr, "Decrypted %d encrypted bytes", input_length);
|
||||
lprintf(LOG_DEBUG, "Decrypted %d encrypted bytes", input_length);
|
||||
printbuf(output, *bytes_written, "Decrypted this data");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user