ID:319 - Interface safe re-open

Currently, interface-management code in the ipmitool does not allow safe
interface re-opening (i.e. closing and opening again). It is because the session
is allocated in the interface setup callback while is freed in the close
callback. So, normal re-opening of the interface, which can be required for
example durng the HPM.1 upgrade, leads to segmentation fault. That's why in the
ipmi_hpmfwupg.c instead of normal closing interface, directly access the
interface data for subsequent re-opening.

Commit for Dmitry Bazhenov
This commit is contained in:
Zdenek Styblik
2015-03-11 19:41:34 +01:00
parent 9caa78be38
commit eb54136775
14 changed files with 290 additions and 339 deletions

View File

@@ -750,7 +750,7 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
"DCMI Discovery is available only when LANplus(IPMI v2.0) is enabled.");
return (-1);
# else
struct ipmi_session *s;
struct ipmi_session_params *p;
if (intf->opened == 0 && intf->open != NULL) {
if (intf->open(intf) < 0)
@@ -759,18 +759,18 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
if (intf == NULL || intf->session == NULL)
return -1;
s = intf->session;
p = &intf->ssn_params;
if (s->port == 0)
s->port = IPMI_LAN_PORT;
if (s->privlvl == 0)
s->privlvl = IPMI_SESSION_PRIV_ADMIN;
if (s->timeout == 0)
s->timeout = IPMI_LAN_TIMEOUT;
if (s->retry == 0)
s->retry = IPMI_LAN_RETRY;
if (p->port == 0)
p->port = IPMI_LAN_PORT;
if (p->privlvl == 0)
p->privlvl = IPMI_SESSION_PRIV_ADMIN;
if (p->timeout == 0)
p->timeout = IPMI_LAN_TIMEOUT;
if (p->retry == 0)
p->retry = IPMI_LAN_RETRY;
if (s->hostname == NULL || strlen((const char *)s->hostname) == 0) {
if (p->hostname == NULL || strlen((const char *)p->hostname) == 0) {
lprintf(LOG_ERR, "No hostname specified!");
return -1;
}
@@ -785,7 +785,7 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
if (intf->fd < 0) {
lperror(LOG_ERR, "Connect to %s failed",
s->hostname);
p->hostname);
intf->close(intf);
return -1;
}

View File

@@ -2194,18 +2194,15 @@ HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req,
lprintf(LOG_DEBUG, "HPM: try to re-open IOL session");
{
/* force session re-open */
intf->opened = 0;
intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE;
intf->session->session_id = 0;
intf->session->in_seq = 0;
intf->session->out_seq = 0;
intf->session->active = 0;
intf->session->retry = 10;
intf->abort = 1;
intf->close(intf);
while (intf->open(intf) == HPMFWUPG_ERROR
&& inaccessTimeoutCounter < inaccessTimeout) {
inaccessTimeoutCounter += (time(NULL) - timeoutSec1);
timeoutSec1 = time(NULL);
}
/* Fake timeout to retry command */
fakeRsp.ccode = 0xc3;
rsp = &fakeRsp;

View File

@@ -272,9 +272,7 @@ void ipmi_catch_sigint()
if (ipmi_main_intf != NULL) {
printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc);
/* reduce retry count to a single retry */
if (ipmi_main_intf->session) {
ipmi_main_intf->session->retry = 1;
}
ipmi_main_intf->ssn_params.retry = 1;
/* close interface */
ipmi_main_intf->close(ipmi_main_intf);
}

View File

@@ -544,8 +544,8 @@ ipmi_get_sol_info(
case 0x80:
if( intf->session != NULL ) {
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;
val2str(data[1], sol_parameter_vals), intf->ssn_params.port);
params->payload_port = intf->ssn_params.port;
} else {
lprintf(LOG_ERR,
"Info: SOL parameter '%s' not supported - can't determine which "
@@ -1235,14 +1235,14 @@ printSolEscapeSequences(struct ipmi_intf * intf)
%c? - this message\n\
%c%c - send the escape character by typing it twice\n\
(Note that escapes are only recognized immediately after newline.)\n",
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char);
}
@@ -1379,25 +1379,25 @@ processSolUserInput(
switch (ch) {
case '.':
printf("%c. [terminated ipmitool]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
retval = 1;
break;
case 'Z' - 64:
printf("%c^Z [suspend ipmitool]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
suspendSelf(1); /* Restore tty back to raw */
continue;
case 'X' - 64:
printf("%c^Z [suspend ipmitool]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
suspendSelf(0); /* Don't restore to raw mode */
continue;
case 'B':
printf("%cB [send break]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
sendBreak(intf);
continue;
@@ -1406,16 +1406,16 @@ processSolUserInput(
continue;
default:
if (ch != intf->session->sol_escape_char)
if (ch != intf->ssn_params.sol_escape_char)
v2_payload.payload.sol_packet.data[length++] =
intf->session->sol_escape_char;
intf->ssn_params.sol_escape_char;
v2_payload.payload.sol_packet.data[length++] = ch;
}
}
else
{
if (last_was_cr && (ch == intf->session->sol_escape_char)) {
if (last_was_cr && (ch == intf->ssn_params.sol_escape_char)) {
escape_pending = 1;
continue;
}
@@ -1441,7 +1441,7 @@ processSolUserInput(
struct ipmi_rs * rsp = NULL;
int try = 0;
while (try < intf->session->retry) {
while (try < intf->ssn_params.retry) {
v2_payload.payload.sol_packet.character_count = length;
@@ -1827,12 +1827,12 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
/* NOTE: the spec does allow for SOL traffic to be sent on
* a different port. we do not yet support that feature. */
if (intf->session->sol_data.port != intf->session->port)
if (intf->session->sol_data.port != intf->ssn_params.port)
{
/* try byteswapping port in case BMC sent it incorrectly */
uint16_t portswap = BSWAP_16(intf->session->sol_data.port);
if (portswap == intf->session->port) {
if (portswap == intf->ssn_params.port) {
intf->session->sol_data.port = portswap;
}
else {
@@ -1842,7 +1842,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
}
printf("[SOL Session operational. Use %c? for help]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
if(looptest == 1)
{

View File

@@ -185,12 +185,12 @@ print_escape_seq(struct ipmi_intf *intf)
" %c? - this message\n"
" %c%c - send the escape character by typing it twice\n"
" (Note that escapes are only recognized immediately after newline.)",
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char,
intf->ssn_params.sol_escape_char);
}
static int
@@ -264,7 +264,7 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len)
for(i = 0; i < len ;) {
if (!in_esc) {
if (last_was_cr &&
(in_buff[i] == intf->session->sol_escape_char)) {
(in_buff[i] == intf->ssn_params.sol_escape_char)) {
in_esc = 1;
memmove(in_buff, in_buff + 1, len - i - 1);
len--;
@@ -272,7 +272,7 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len)
}
}
if (in_esc) {
if (in_buff[i] == intf->session->sol_escape_char) {
if (in_buff[i] == intf->ssn_params.sol_escape_char) {
in_esc = 0;
i++;
continue;
@@ -281,23 +281,23 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len)
switch (in_buff[i]) {
case '.':
printf("%c. [terminated ipmitool]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
return -1;
case 'Z' - 64:
printf("%c^Z [suspend ipmitool]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
/* Restore tty back to raw */
suspend_self(1);
break;
case 'X' - 64:
printf("%c^X [suspend ipmitool]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
/* Don't restore to raw mode */
suspend_self(0);
break;
case '?':
printf("%c? [ipmitool help]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
print_escape_seq(intf);
break;
}
@@ -425,20 +425,20 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv)
sin.sin_port = htons(port);
sa_in = (struct sockaddr_in *)&intf->session->addr;
result = inet_pton(AF_INET, (const char *)intf->session->hostname,
result = inet_pton(AF_INET, (const char *)intf->ssn_params.hostname,
&sa_in->sin_addr);
if (result <= 0) {
struct hostent *host = gethostbyname((const char *)intf->session->hostname);
struct hostent *host = gethostbyname((const char *)intf->ssn_params.hostname);
if (host == NULL ) {
lprintf(LOG_ERR, "Address lookup for %s failed",
intf->session->hostname);
intf->ssn_params.hostname);
return -1;
}
if (host->h_addrtype != AF_INET) {
lprintf(LOG_ERR,
"Address lookup for %s failed. Got %s, expected IPv4 address.",
intf->session->hostname,
intf->ssn_params.hostname,
(host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown");
return (-1);
}
@@ -501,7 +501,7 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv)
}
printf("[SOL Session operational. Use %c? for help]\n",
intf->session->sol_escape_char);
intf->ssn_params.sol_escape_char);
gettimeofday(&_start_keepalive, 0);