diff --git a/ipmitool/src/plugins/lan/lan.c b/ipmitool/src/plugins/lan/lan.c index 9d17d96..05ca03c 100644 --- a/ipmitool/src/plugins/lan/lan.c +++ b/ipmitool/src/plugins/lan/lan.c @@ -75,6 +75,8 @@ static struct ipmi_rq_entry * ipmi_req_entries_tail; 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); @@ -398,6 +400,14 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf) struct ipmi_rs * rsp; struct ipmi_rq_entry * entry; int x=0, rv; + uint8_t ourAddress = intf->my_addr; + + if(ourAddress == 0) + { + ourAddress = IPMI_BMC_SLAVE_ADDR; + } + + rsp = ipmi_lan_recv_packet(intf); @@ -476,16 +486,29 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf) rsp->payload.ipmi_response.cmd); if (entry) { lprintf(LOG_DEBUG+2, "IPMI Request Match found"); - if (intf->target_addr != IPMI_BMC_SLAVE_ADDR) { - if (rsp->data_len) - lprintf(LOG_DEBUG+1, "Bridged cmd %02x resp: %s", - rsp->payload.ipmi_response.cmd, - buf2str(&rsp->data[x],rsp->data_len)); + if ( + (intf->target_addr != ourAddress) && + (bridgePossible) + ) + { + if( + (rsp->data_len) && + (rsp->payload.ipmi_response.cmd != 0x34) + ) + { + printbuf( + &rsp->data[x], + (rsp->data_len-x), + "bridge command response"); + } /* bridged command: lose extra header */ if (rsp->payload.ipmi_response.cmd == 0x34) { + if( rsp->data_len == 38 ) + { entry->req.msg.cmd = entry->req.msg.target_cmd; rsp = ipmi_lan_recv_packet(intf); continue; + } } else { //x += sizeof(rsp->payload.ipmi_response); if (rsp->data[x-1] != 0) @@ -559,6 +582,13 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) struct ipmi_rq_entry * entry; struct ipmi_session * s = intf->session; static int curr_seq = 0; + uint8_t ourAddress = intf->my_addr; + uint8_t bridgedRequest = 0; + + if(ourAddress == 0) + { + ourAddress = IPMI_BMC_SLAVE_ADDR; + } if (curr_seq >= 64) curr_seq = 0; @@ -599,15 +629,22 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) } /* message length */ - if (intf->target_addr == IPMI_BMC_SLAVE_ADDR) { + if ( + (intf->target_addr == ourAddress) || + (!bridgePossible) + ) + { msg[len++] = req->msg.data_len + 7; cs = mp = len; } - else { + else + { /* bridged request: encapsulate w/in Send Message */ + bridgedRequest = 1; msg[len++] = req->msg.data_len + 15; cs = mp = len; msg[len++] = IPMI_BMC_SLAVE_ADDR; + msg[len++] = IPMI_NETFN_APP << 2; tmp = len - cs; msg[len++] = ipmi_csum(msg+cs, tmp); @@ -617,7 +654,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) msg[len++] = 0x34; /* Send Message rqst */ entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */ entry->req.msg.cmd = 0x34; /* (fixup request entry) */ - msg[len++] = 0x40; /* Track request, Channel=IPMB */ + msg[len++] = (0x40|intf->target_channel); /* Track request*/ cs = len; } @@ -627,8 +664,11 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) tmp = len - cs; msg[len++] = ipmi_csum(msg+cs, tmp); cs = len; + if (!bridgedRequest) msg[len++] = IPMI_REMOTE_SWID; + else /* Bridged message */ + msg[len++] = intf->my_addr; entry->rq_seq = curr_seq++; msg[len++] = entry->rq_seq << 2; msg[len++] = req->msg.cmd; @@ -658,11 +698,13 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) msg[len++] = ipmi_csum(msg+cs, tmp); /* bridged request: 2nd checksum */ - if (intf->target_addr != IPMI_BMC_SLAVE_ADDR) { + if (bridgedRequest) + { tmp = len - cs2; msg[len++] = ipmi_csum(msg+cs2, tmp); } + if (s->active) { /* * s->authcode is already copied to msg+ap but some @@ -1149,6 +1191,8 @@ ipmi_activate_session_cmd(struct ipmi_intf * intf) return -1; } + bridgePossible = 1; + lprintf(LOG_DEBUG, "\nSession Activated"); lprintf(LOG_DEBUG, " Auth Type : %s", val2str(rsp->data[0], ipmi_authtype_session_vals)); @@ -1170,6 +1214,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) struct ipmi_rs * rsp; struct ipmi_rq req; uint8_t privlvl = intf->session->privlvl; + uint8_t backupBridgePossible = bridgePossible; if (privlvl <= IPMI_SESSION_PRIV_USER) return 0; /* no need to set higher */ @@ -1180,7 +1225,12 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) req.msg.data = &privlvl; req.msg.data_len = 1; + bridgePossible = 0; + rsp = intf->sendrecv(intf, &req); + + bridgePossible = backupBridgePossible; + if (rsp == NULL) { lprintf(LOG_ERR, "Set Session Privilege Level to %s failed", val2str(privlvl, ipmi_privlvl_vals)); @@ -1214,6 +1264,7 @@ ipmi_close_session_cmd(struct ipmi_intf * intf) return -1; intf->target_addr = IPMI_BMC_SLAVE_ADDR; + bridgePossible = 0; /* Not a bridge message */ memcpy(&msg_data, &session_id, 4); diff --git a/ipmitool/src/plugins/lanplus/lanplus.c b/ipmitool/src/plugins/lanplus/lanplus.c index f05f96e..9c090d8 100644 --- a/ipmitool/src/plugins/lanplus/lanplus.c +++ b/ipmitool/src/plugins/lanplus/lanplus.c @@ -92,10 +92,14 @@ static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, stru static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf, struct ipmi_v2_payload * payload); static void getIpmiPayloadWireRep( + struct ipmi_intf * intf, + struct ipmi_v2_payload * payload, /* in */ uint8_t * out, struct ipmi_rq * req, - uint8_t rq_seq); + uint8_t rq_seq, + uint8_t curr_seq); static void getSolPayloadWireRep( + struct ipmi_intf * intf, uint8_t * msg, struct ipmi_v2_payload * payload); static void read_open_session_response(struct ipmi_rs * rsp, int offset); @@ -117,6 +121,7 @@ static void ack_sol_packet( struct ipmi_intf * intf, struct ipmi_rs * rsp); +static uint8_t bridgePossible = 0; struct ipmi_intf ipmi_lanplus_intf = { name: "lanplus", @@ -584,6 +589,13 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf) int offset, rv; uint16_t payload_size; + uint8_t ourAddress = intf->my_addr; + + if(ourAddress == 0) + { + ourAddress = IPMI_BMC_SLAVE_ADDR; + } + rsp = ipmi_lan_recv_packet(intf); /* @@ -702,6 +714,37 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf) rsp->payload.ipmi_response.cmd); if (entry != NULL) { lprintf(LOG_DEBUG+2, "IPMI Request Match found"); + if ( + (intf->target_addr != ourAddress) && + (bridgePossible) + ) + { + if( + (rsp->data_len) && + (rsp->payload.ipmi_response.cmd != 0x34) + ) + { + printbuf( + &rsp->data[offset], + (rsp->data_len-offset), + "bridge command response"); + } + /* bridged command: lose extra header */ + if (rsp->payload.ipmi_response.cmd == 0x34) { + if( rsp->data_len == 38 ) + { + entry->req.msg.cmd = entry->req.msg.target_cmd; + rsp = ipmi_lan_recv_packet(intf); + continue; + } + } else { + //x += sizeof(rsp->payload.ipmi_response); + if (rsp->data[offset-1] != 0) + lprintf(LOG_DEBUG, "WARNING: Bridged " + "cmd ccode = 0x%02x", + rsp->data[offset-1]); + } + } ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, rsp->payload.ipmi_response.cmd); } else { @@ -1284,48 +1327,104 @@ void read_sol_packet(struct ipmi_rs * rsp, int * offset) * param rq_seq [in] is the IPMI command sequence number. */ void getIpmiPayloadWireRep( + struct ipmi_intf * intf, /* in out */ + struct ipmi_v2_payload * payload, /* in */ uint8_t * msg, struct ipmi_rq * req, - uint8_t rq_seq) + uint8_t rq_seq, + uint8_t curr_seq) { - int cs, mp, tmp, i; + int cs, /*mp,*/ tmp, len; - i = 0; + int cs2 = 0; + + uint8_t ourAddress = intf->my_addr; + uint8_t bridgedRequest = 0; + + if(ourAddress == 0) + { + ourAddress = IPMI_BMC_SLAVE_ADDR; + } + + len = 0; /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */ - cs = mp = i, + if ( + (intf->target_addr == ourAddress) || + (!bridgePossible) + ) + { + cs = len; + } + else + { + /* bridged request: encapsulate w/in Send Message */ + bridgedRequest = 1; + + cs = len; + + msg[len++] = IPMI_BMC_SLAVE_ADDR; + + msg[len++] = IPMI_NETFN_APP << 2; + tmp = len - cs; + msg[len++] = ipmi_csum(msg+cs, tmp); + cs2 = len; + msg[len++] = IPMI_REMOTE_SWID; + msg[len++] = curr_seq << 2; + msg[len++] = 0x34; /* Send Message rqst */ +#if 0 /* From lan.c example */ + entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */ + entry->req.msg.cmd = 0x34; /* (fixup request entry) */ +#endif + msg[len++] = (0x40|intf->target_channel); /* Track request*/ + + payload->payload_length += 7; + + cs = len; + } /* rsAddr */ - msg[i++] = IPMI_BMC_SLAVE_ADDR; + msg[len++] = intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */ /* net Fn */ - msg[i++] = req->msg.netfn << 2; - tmp = i - cs; + msg[len++] = req->msg.netfn << 2; + tmp = len - cs; /* checkSum */ - msg[i++] = ipmi_csum(msg+cs, tmp); - cs = i; + msg[len++] = ipmi_csum(msg+cs, tmp); + cs = len; /* rqAddr */ - msg[i++] = IPMI_REMOTE_SWID; + if (!bridgedRequest) + msg[len++] = IPMI_REMOTE_SWID; + else /* Bridged message */ + msg[len++] = intf->my_addr; /* rqSeq / rqLUN */ - msg[i++] = rq_seq << 2; + msg[len++] = rq_seq << 2; /* cmd */ - msg[i++] = req->msg.cmd; + msg[len++] = req->msg.cmd; /* message data */ if (req->msg.data_len) { - memcpy(msg + i, + memcpy(msg + len, req->msg.data, req->msg.data_len); - i += req->msg.data_len; + len += req->msg.data_len; } /* second checksum */ - tmp = i - cs; - msg[i++] = ipmi_csum(msg+cs, tmp); + tmp = len - cs; + msg[len++] = ipmi_csum(msg+cs, tmp); + + /* bridged request: 2nd checksum */ + if (bridgedRequest) + { + tmp = len - cs2; + msg[len++] = ipmi_csum(msg+cs2, tmp); + payload->payload_length += 1; + } } @@ -1337,6 +1436,7 @@ void getIpmiPayloadWireRep( * param payload [in] holds the v2 payload with our SOL data */ void getSolPayloadWireRep( + struct ipmi_intf * intf, /* in out */ uint8_t * msg, /* output */ struct ipmi_v2_payload * payload) /* input */ { @@ -1409,7 +1509,8 @@ ipmi_lanplus_build_v2x_msg( struct ipmi_intf * intf, /* in */ struct ipmi_v2_payload * payload, /* in */ int * msg_len, /* out */ - uint8_t ** msg_data) /* out */ + uint8_t ** msg_data, /* out */ + uint8_t curr_seq) { uint32_t session_trailer_length = 0; struct ipmi_session * session = intf->session; @@ -1506,13 +1607,17 @@ ipmi_lanplus_build_v2x_msg( switch (payload->payload_type) { case IPMI_PAYLOAD_TYPE_IPMI: - getIpmiPayloadWireRep(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, + getIpmiPayloadWireRep(intf, + payload, /* in */ + msg + IPMI_LANPLUS_OFFSET_PAYLOAD, payload->payload.ipmi_request.request, - payload->payload.ipmi_request.rq_seq); + payload->payload.ipmi_request.rq_seq, + curr_seq); break; case IPMI_PAYLOAD_TYPE_SOL: - getSolPayloadWireRep(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, + getSolPayloadWireRep(intf, + msg + IPMI_LANPLUS_OFFSET_PAYLOAD, payload); len += payload->payload_length; @@ -1718,7 +1823,8 @@ ipmi_lanplus_build_v2x_ipmi_cmd( ipmi_lanplus_build_v2x_msg(intf, // in &v2_payload, // in &(entry->msg_len), // out - &(entry->msg_data)); // out + &(entry->msg_data), // out + curr_seq); // in return entry; } @@ -1969,7 +2075,8 @@ ipmi_lanplus_send_payload( ipmi_lanplus_build_v2x_msg(intf, /* in */ payload, /* in */ &msg_length, /* out */ - &msg_data); /* out */ + &msg_data, /* out */ + 0); /* irrelevant for this msg*/ } @@ -1982,7 +2089,8 @@ ipmi_lanplus_send_payload( ipmi_lanplus_build_v2x_msg(intf, /* in */ payload, /* in */ &msg_length, /* out */ - &msg_data); /* out */ + &msg_data, /* out */ + 0); /* irrelevant for this msg*/ } @@ -1995,7 +2103,8 @@ ipmi_lanplus_send_payload( ipmi_lanplus_build_v2x_msg(intf, /* in */ payload, /* in */ &msg_length, /* out */ - &msg_data); /* out */ + &msg_data, /* out */ + 0); /* irrelevant for this msg*/ } @@ -2007,7 +2116,8 @@ ipmi_lanplus_send_payload( ipmi_lanplus_build_v2x_msg(intf, /* in */ payload, /* in */ &msg_length, /* out */ - &msg_data); /* out */ + &msg_data, /* out */ + 0); /* irrelevant for this msg*/ } else @@ -2421,6 +2531,11 @@ ipmi_get_auth_capabilities_cmd( struct ipmi_rs * rsp; struct ipmi_rq req; uint8_t msg_data[2]; + uint8_t backupBridgePossible; + + backupBridgePossible = bridgePossible; + + bridgePossible = 0; msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well msg_data[1] = intf->session->privlvl; @@ -2458,6 +2573,7 @@ ipmi_get_auth_capabilities_cmd( rsp->data, sizeof(struct get_channel_auth_cap_rsp)); + bridgePossible = backupBridgePossible; return 0; } @@ -2471,10 +2587,14 @@ impi_close_session_cmd(struct ipmi_intf * intf) struct ipmi_rq req; uint8_t msg_data[4]; uint32_t bmc_session_lsbf; + uint8_t backupBridgePossible; if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE) return -1; + backupBridgePossible = bridgePossible; + + bridgePossible = 0; bmc_session_lsbf = intf->session->v2_data.bmc_id; #if WORDS_BIGENDIAN @@ -2513,6 +2633,7 @@ impi_close_session_cmd(struct ipmi_intf * intf) lprintf(LOG_DEBUG, "Closed Session %08lx\n", (long)intf->session->v2_data.bmc_id); + bridgePossible = backupBridgePossible; return 0; } @@ -3033,11 +3154,16 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) { struct ipmi_rs * rsp; struct ipmi_rq req; + uint8_t backupBridgePossible; uint8_t privlvl = intf->session->privlvl; if (privlvl <= IPMI_SESSION_PRIV_USER) return 0; /* no need to set higher */ + backupBridgePossible = bridgePossible; + + bridgePossible = 0; + memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = 0x3b; @@ -3063,6 +3189,8 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n", val2str(rsp->data[0], ipmi_privlvl_vals)); + bridgePossible = backupBridgePossible; + return 0; } @@ -3217,6 +3345,8 @@ ipmi_lanplus_open(struct ipmi_intf * intf) lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n"); + bridgePossible = 1; + rc = ipmi_set_session_privlvl_cmd(intf); if (rc < 0) goto fail;