use select() instead of alarm signal for receive timeout

This commit is contained in:
Duncan Laurie 2006-05-17 23:57:44 +00:00
parent 83a924d7ed
commit ce3636894d
2 changed files with 94 additions and 98 deletions

View File

@ -41,7 +41,6 @@
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <setjmp.h>
#include <netdb.h> #include <netdb.h>
#include <fcntl.h> #include <fcntl.h>
@ -63,23 +62,29 @@
#include "asf.h" #include "asf.h"
#include "auth.h" #include "auth.h"
#define IPMI_LAN_TIMEOUT 2
#define IPMI_LAN_RETRY 4
#define IPMI_LAN_PORT 0x26f
#define IPMI_LAN_CHANNEL_E 0x0e
extern const struct valstr ipmi_privlvl_vals[]; extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_session_vals[]; extern const struct valstr ipmi_authtype_session_vals[];
extern int verbose;
struct ipmi_rq_entry * ipmi_req_entries; struct ipmi_rq_entry * ipmi_req_entries;
static struct ipmi_rq_entry * ipmi_req_entries_tail; static struct ipmi_rq_entry * ipmi_req_entries_tail;
static uint8_t bridge_possible = 0;
extern int verbose;
static uint8_t bridgePossible = 0;
static sigjmp_buf jmpbuf;
static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len); static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len);
static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf); static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf);
static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf); static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf);
static int ipmi_lan_setup(struct ipmi_intf * intf); static int ipmi_lan_setup(struct ipmi_intf * intf);
static int ipmi_lan_keepalive(struct ipmi_intf * intf); static int ipmi_lan_keepalive(struct ipmi_intf * intf);
static struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
static int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp);
static int ipmi_lan_open(struct ipmi_intf * intf);
static void ipmi_lan_close(struct ipmi_intf * intf);
static int ipmi_lan_ping(struct ipmi_intf * intf);
struct ipmi_intf ipmi_lan_intf = { struct ipmi_intf ipmi_lan_intf = {
name: "lan", name: "lan",
@ -93,13 +98,6 @@ struct ipmi_intf ipmi_lan_intf = {
target_addr: IPMI_BMC_SLAVE_ADDR, target_addr: IPMI_BMC_SLAVE_ADDR,
}; };
static void
query_alarm(int signo)
{
siglongjmp(jmpbuf, 1);
}
static struct ipmi_rq_entry * static struct ipmi_rq_entry *
ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req) ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req)
{ {
@ -208,7 +206,8 @@ get_random(void *data, int len)
return rv; return rv;
} }
int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len) static int
ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len)
{ {
if (verbose > 2) if (verbose > 2)
printbuf(data, data_len, "send_packet"); printbuf(data, data_len, "send_packet");
@ -216,20 +215,26 @@ int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len)
return send(intf->fd, data, data_len, 0); return send(intf->fd, data, data_len, 0);
} }
struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf) static struct ipmi_rs *
ipmi_lan_recv_packet(struct ipmi_intf * intf)
{ {
static struct ipmi_rs rsp; static struct ipmi_rs rsp;
int rc; fd_set read_set, err_set;
struct timeval tmout;
int ret;
/* setup alarm timeout */ FD_ZERO(&read_set);
if (sigsetjmp(jmpbuf, 1) != 0) { FD_SET(intf->fd, &read_set);
alarm(0);
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; 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 /* the first read may return ECONNREFUSED because the rmcp ping
* packet--sent to UDP port 623--will be processed by both the * packet--sent to UDP port 623--will be processed by both the
@ -241,17 +246,31 @@ struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf)
* 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) * response is read before the connection refused is returned)
*/ */
if (rc < 0) { ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
alarm(intf->session->timeout);
rc = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0); if (ret < 0) {
alarm(0); FD_ZERO(&read_set);
if (rc < 0) { FD_SET(intf->fd, &read_set);
perror("recv failed");
return NULL; 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; rsp.data[ret] = '\0';
rsp.data_len = ret;
return &rsp; return &rsp;
} }
@ -328,7 +347,7 @@ ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
* asf.len = 0x00 * asf.len = 0x00
* *
*/ */
int static int
ipmi_lan_ping(struct ipmi_intf * intf) ipmi_lan_ping(struct ipmi_intf * intf)
{ {
struct asf_hdr asf_ping = { struct asf_hdr asf_ping = {
@ -375,7 +394,8 @@ ipmi_lan_ping(struct ipmi_intf * intf)
* request message. This may kick-start some BMCs that get confused with * request message. This may kick-start some BMCs that get confused with
* bad passwords or operate poorly under heavy network load. * bad passwords or operate poorly under heavy network load.
*/ */
static void ipmi_lan_thump_first(struct ipmi_intf * intf) static void
ipmi_lan_thump_first(struct ipmi_intf * intf)
{ {
/* is this random data? */ /* is this random data? */
uint8_t data[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, uint8_t data[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -383,7 +403,8 @@ static void ipmi_lan_thump_first(struct ipmi_intf * intf)
ipmi_lan_send_packet(intf, data, 16); ipmi_lan_send_packet(intf, data, 16);
} }
static void ipmi_lan_thump(struct ipmi_intf * intf) static void
ipmi_lan_thump(struct ipmi_intf * intf)
{ {
uint8_t data[10] = "thump"; uint8_t data[10] = "thump";
ipmi_lan_send_packet(intf, data, 10); ipmi_lan_send_packet(intf, data, 10);
@ -396,10 +417,10 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
struct ipmi_rs * rsp; struct ipmi_rs * rsp;
struct ipmi_rq_entry * entry; struct ipmi_rq_entry * entry;
int x=0, rv; int x=0, rv;
uint8_t ourAddress = intf->my_addr; uint8_t our_address = intf->my_addr;
if (ourAddress == 0) if (our_address == 0)
ourAddress = IPMI_BMC_SLAVE_ADDR; our_address = IPMI_BMC_SLAVE_ADDR;
rsp = ipmi_lan_recv_packet(intf); rsp = ipmi_lan_recv_packet(intf);
@ -441,7 +462,7 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
rsp->payload.ipmi_response.rs_addr = rsp->data[x++]; rsp->payload.ipmi_response.rs_addr = rsp->data[x++];
rsp->payload.ipmi_response.rq_seq = rsp->data[x] >> 2; rsp->payload.ipmi_response.rq_seq = rsp->data[x] >> 2;
rsp->payload.ipmi_response.rs_lun = rsp->data[x++] & 0x3; rsp->payload.ipmi_response.rs_lun = rsp->data[x++] & 0x3;
rsp->payload.ipmi_response.cmd = rsp->data[x++]; rsp->payload.ipmi_response.cmd = rsp->data[x++];
rsp->ccode = rsp->data[x++]; rsp->ccode = rsp->data[x++];
if (verbose > 2) if (verbose > 2)
@ -454,7 +475,6 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
(long)rsp->session.seq); (long)rsp->session.seq);
lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx", lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx",
(long)rsp->session.id); (long)rsp->session.id);
lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header"); lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header");
lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x", lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x",
rsp->payload.ipmi_response.rq_addr); rsp->payload.ipmi_response.rq_addr);
@ -478,7 +498,7 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
rsp->payload.ipmi_response.cmd); rsp->payload.ipmi_response.cmd);
if (entry) { if (entry) {
lprintf(LOG_DEBUG+2, "IPMI Request Match found"); lprintf(LOG_DEBUG+2, "IPMI Request Match found");
if ((intf->target_addr != ourAddress) && bridgePossible) { if ((intf->target_addr != our_address) && bridge_possible) {
if ((rsp->data_len) && if ((rsp->data_len) &&
(rsp->payload.ipmi_response.cmd != 0x34)) { (rsp->payload.ipmi_response.cmd != 0x34)) {
printbuf(&rsp->data[x], rsp->data_len-x, printbuf(&rsp->data[x], rsp->data_len-x,
@ -564,11 +584,11 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
struct ipmi_rq_entry * entry; struct ipmi_rq_entry * entry;
struct ipmi_session * s = intf->session; struct ipmi_session * s = intf->session;
static int curr_seq = 0; static int curr_seq = 0;
uint8_t ourAddress = intf->my_addr; uint8_t our_address = intf->my_addr;
uint8_t bridgedRequest = 0; uint8_t bridge_request = 0;
if (ourAddress == 0) if (our_address == 0)
ourAddress = IPMI_BMC_SLAVE_ADDR; our_address = IPMI_BMC_SLAVE_ADDR;
if (curr_seq >= 64) if (curr_seq >= 64)
curr_seq = 0; curr_seq = 0;
@ -609,12 +629,12 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
} }
/* message length */ /* message length */
if ((intf->target_addr == ourAddress) || !bridgePossible) { if ((intf->target_addr == our_address) || !bridge_possible) {
msg[len++] = req->msg.data_len + 7; msg[len++] = req->msg.data_len + 7;
cs = mp = len; cs = mp = len;
} else { } else {
/* bridged request: encapsulate w/in Send Message */ /* bridged request: encapsulate w/in Send Message */
bridgedRequest = 1; bridge_request = 1;
msg[len++] = req->msg.data_len + 15; msg[len++] = req->msg.data_len + 15;
cs = mp = len; cs = mp = len;
msg[len++] = IPMI_BMC_SLAVE_ADDR; msg[len++] = IPMI_BMC_SLAVE_ADDR;
@ -638,7 +658,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
msg[len++] = ipmi_csum(msg+cs, tmp); msg[len++] = ipmi_csum(msg+cs, tmp);
cs = len; cs = len;
if (!bridgedRequest) if (!bridge_request)
msg[len++] = IPMI_REMOTE_SWID; msg[len++] = IPMI_REMOTE_SWID;
else /* Bridged message */ else /* Bridged message */
msg[len++] = intf->my_addr; msg[len++] = intf->my_addr;
@ -672,7 +692,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
msg[len++] = ipmi_csum(msg+cs, tmp); msg[len++] = ipmi_csum(msg+cs, tmp);
/* bridged request: 2nd checksum */ /* bridged request: 2nd checksum */
if (bridgedRequest) { if (bridge_request) {
tmp = len - cs2; tmp = len - cs2;
msg[len++] = ipmi_csum(msg+cs2, tmp); msg[len++] = ipmi_csum(msg+cs2, tmp);
} }
@ -707,7 +727,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
return entry; return entry;
} }
struct ipmi_rs * static struct ipmi_rs *
ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
{ {
struct ipmi_rq_entry * entry; struct ipmi_rq_entry * entry;
@ -719,8 +739,7 @@ ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
if (intf->opened == 0 && intf->open != NULL) { if (intf->opened == 0 && intf->open != NULL) {
if (intf->open(intf) < 0) { if (intf->open(intf) < 0) {
lprintf(LOG_ERR, lprintf(LOG_DEBUG, "Failed to open LAN interface");
"ipmi_lan_send_cmd failed to open intf");
return NULL; return NULL;
} }
lprintf(LOG_DEBUG, "\topened=[%d], open=[%d]", lprintf(LOG_DEBUG, "\topened=[%d], open=[%d]",
@ -763,7 +782,8 @@ ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
return rsp; return rsp;
} }
uint8_t * ipmi_lan_build_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp, int * llen) static uint8_t *
ipmi_lan_build_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp, int * llen)
{ {
struct rmcp_hdr rmcp = { struct rmcp_hdr rmcp = {
.ver = RMCP_VERSION_1, .ver = RMCP_VERSION_1,
@ -848,17 +868,19 @@ uint8_t * ipmi_lan_build_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp, int
d = ipmi_auth_md2(s, msg+mp, msg[mp-1]); d = ipmi_auth_md2(s, msg+mp, msg[mp-1]);
memcpy(msg+ap, d, 16); memcpy(msg+ap, d, 16);
break; break;
} }
} }
*llen = len; *llen = len;
return msg; return msg;
} }
int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp) static int
ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp)
{ {
uint8_t * msg; uint8_t * msg;
int len, rv; int len = 0;
int rv;
msg = ipmi_lan_build_rsp(intf, rsp, &len); msg = ipmi_lan_build_rsp(intf, rsp, &len);
if (len <= 0 || msg == NULL) { if (len <= 0 || msg == NULL) {
@ -1069,7 +1091,7 @@ ipmi_get_session_challenge_cmd(struct ipmi_intf * intf)
lprintf(LOG_DEBUG, "Opening Session"); lprintf(LOG_DEBUG, "Opening Session");
lprintf(LOG_DEBUG, " Session ID : %08lx", (long)s->session_id); lprintf(LOG_DEBUG, " Session ID : %08lx", (long)s->session_id);
lprintf(LOG_DEBUG, " Challenge : %s", buf2str(s->challenge, 16)); lprintf(LOG_DEBUG, " Challenge : %s", buf2str(s->challenge, 16));
return 0; return 0;
} }
@ -1171,8 +1193,8 @@ ipmi_activate_session_cmd(struct ipmi_intf * intf)
return -1; return -1;
} }
bridgePossible = 1; bridge_possible = 1;
lprintf(LOG_DEBUG, "\nSession Activated"); lprintf(LOG_DEBUG, "\nSession Activated");
lprintf(LOG_DEBUG, " Auth Type : %s", lprintf(LOG_DEBUG, " Auth Type : %s",
val2str(rsp->data[0], ipmi_authtype_session_vals)); val2str(rsp->data[0], ipmi_authtype_session_vals));
@ -1194,7 +1216,7 @@ 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 privlvl = intf->session->privlvl; uint8_t privlvl = intf->session->privlvl;
uint8_t backupBridgePossible = bridgePossible; uint8_t backup_bridge_possible = bridge_possible;
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 */
@ -1205,12 +1227,10 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
req.msg.data = &privlvl; req.msg.data = &privlvl;
req.msg.data_len = 1; req.msg.data_len = 1;
bridgePossible = 0; bridge_possible = 0;
rsp = intf->sendrecv(intf, &req); rsp = intf->sendrecv(intf, &req);
bridge_possible = backup_bridge_possible;
bridgePossible = backupBridgePossible;
if (rsp == NULL) { if (rsp == NULL) {
lprintf(LOG_ERR, "Set Session Privilege Level to %s failed", lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
val2str(privlvl, ipmi_privlvl_vals)); val2str(privlvl, ipmi_privlvl_vals));
@ -1244,7 +1264,7 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
return -1; return -1;
intf->target_addr = IPMI_BMC_SLAVE_ADDR; intf->target_addr = IPMI_BMC_SLAVE_ADDR;
bridgePossible = 0; /* Not a bridge message */ bridge_possible = 0; /* Not a bridge message */
memcpy(&msg_data, &session_id, 4); memcpy(&msg_data, &session_id, 4);
@ -1340,7 +1360,8 @@ ipmi_lan_activate_session(struct ipmi_intf * intf)
return -1; return -1;
} }
void ipmi_lan_close(struct ipmi_intf * intf) static void
ipmi_lan_close(struct ipmi_intf * intf)
{ {
if (intf->abort == 0) if (intf->abort == 0)
ipmi_close_session_cmd(intf); ipmi_close_session_cmd(intf);
@ -1359,10 +1380,10 @@ void ipmi_lan_close(struct ipmi_intf * intf)
intf = NULL; intf = NULL;
} }
int ipmi_lan_open(struct ipmi_intf * intf) static int
ipmi_lan_open(struct ipmi_intf * intf)
{ {
int rc; int rc;
struct sigaction act;
struct ipmi_session *s; struct ipmi_session *s;
if (intf == NULL || intf->session == NULL) if (intf == NULL || intf->session == NULL)
@ -1420,16 +1441,6 @@ int ipmi_lan_open(struct ipmi_intf * intf)
return -1; 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 setup failed");
intf->close(intf);
return -1;
}
intf->opened = 1; intf->opened = 1;
/* try to open session */ /* try to open session */
@ -1443,7 +1454,8 @@ int ipmi_lan_open(struct ipmi_intf * intf)
return intf->fd; return intf->fd;
} }
static int ipmi_lan_setup(struct ipmi_intf * intf) static int
ipmi_lan_setup(struct ipmi_intf * intf)
{ {
intf->session = malloc(sizeof(struct ipmi_session)); intf->session = malloc(sizeof(struct ipmi_session));
if (intf->session == NULL) { if (intf->session == NULL) {

View File

@ -36,22 +36,6 @@
#include <ipmitool/ipmi.h> #include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h> #include <ipmitool/ipmi_intf.h>
#define IPMI_LAN_CHANNEL_1 0x07
#define IPMI_LAN_CHANNEL_2 0x06
#define IPMI_LAN_CHANNEL_E 0x0e
#define IPMI_LAN_PORT 0x26f
#define IPMI_LAN_TIMEOUT 2
#define IPMI_LAN_RETRY 4
struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp);
int ipmi_lan_open(struct ipmi_intf * intf);
void ipmi_lan_close(struct ipmi_intf * intf);
void ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel);
int ipmi_lan_ping(struct ipmi_intf * intf);
extern struct ipmi_intf ipmi_lan_intf; extern struct ipmi_intf ipmi_lan_intf;
#endif /*IPMI_LAN_H*/ #endif /*IPMI_LAN_H*/