1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * Redistribution of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Neither the name of Sun Microsystems, Inc. or the names of 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * This software is provided "AS IS," without a warranty of any kind. 20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 33 #include <stdlib.h> 34 #include <stdio.h> 35 #include <inttypes.h> 36 #include <string.h> 37 #include <sys/types.h> 38 #include <sys/socket.h> 39 #include <netinet/in.h> 40 #include <arpa/inet.h> 41 #include <errno.h> 42 #include <unistd.h> 43 #include <netdb.h> 44 #include <fcntl.h> 45 46 #include <ipmitool/helper.h> 47 #include <ipmitool/log.h> 48 #include <ipmitool/bswap.h> 49 #include <ipmitool/ipmi.h> 50 #include <ipmitool/ipmi_sel.h> 51 #include <ipmitool/ipmi_intf.h> 52 #include <ipmitool/ipmi_oem.h> 53 #include <ipmitool/ipmi_strings.h> 54 #include <ipmitool/ipmi_constants.h> 55 56 #if HAVE_CONFIG_H 57 # include <config.h> 58 #endif 59 60 #include "lan.h" 61 #include "rmcp.h" 62 #include "asf.h" 63 #include "auth.h" 64 65 #define IPMI_LAN_TIMEOUT 2 66 #define IPMI_LAN_RETRY 4 67 #define IPMI_LAN_PORT 0x26f 68 #define IPMI_LAN_CHANNEL_E 0x0e 69 70 extern const struct valstr ipmi_privlvl_vals[]; 71 extern const struct valstr ipmi_authtype_session_vals[]; 72 extern int verbose; 73 74 struct ipmi_rq_entry * ipmi_req_entries; 75 static struct ipmi_rq_entry * ipmi_req_entries_tail; 76 static uint8_t bridge_possible = 0; 77 78 static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len); 79 static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf); 80 static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf); 81 static int ipmi_lan_setup(struct ipmi_intf * intf); 82 static int ipmi_lan_keepalive(struct ipmi_intf * intf); 83 static struct ipmi_rs * ipmi_lan_recv_sol(struct ipmi_intf * intf); 84 static struct ipmi_rs * ipmi_lan_send_sol(struct ipmi_intf * intf, 85 struct ipmi_v2_payload * payload); 86 static struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req); 87 static int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp); 88 static int ipmi_lan_open(struct ipmi_intf * intf); 89 static void ipmi_lan_close(struct ipmi_intf * intf); 90 static int ipmi_lan_ping(struct ipmi_intf * intf); 91 92 struct ipmi_intf ipmi_lan_intf = { 93 name: "lan", 94 desc: "IPMI v1.5 LAN Interface", 95 setup: ipmi_lan_setup, 96 open: ipmi_lan_open, 97 close: ipmi_lan_close, 98 sendrecv: ipmi_lan_send_cmd, 99 sendrsp: ipmi_lan_send_rsp, 100 recv_sol: ipmi_lan_recv_sol, 101 send_sol: ipmi_lan_send_sol, 102 keepalive: ipmi_lan_keepalive, 103 target_addr: IPMI_BMC_SLAVE_ADDR, 104 }; 105 106 static struct ipmi_rq_entry * 107 ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq) 108 { 109 struct ipmi_rq_entry * e; 110 111 e = malloc(sizeof(struct ipmi_rq_entry)); 112 if (e == NULL) { 113 lprintf(LOG_ERR, "ipmitool: malloc failure"); 114 return NULL; 115 } 116 117 memset(e, 0, sizeof(struct ipmi_rq_entry)); 118 memcpy(&e->req, req, sizeof(struct ipmi_rq)); 119 120 e->intf = intf; 121 e->rq_seq = req_seq; 122 123 if (ipmi_req_entries == NULL) 124 ipmi_req_entries = e; 125 else 126 ipmi_req_entries_tail->next = e; 127 128 ipmi_req_entries_tail = e; 129 lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x", 130 e->rq_seq, e->req.msg.cmd); 131 return e; 132 } 133 134 static struct ipmi_rq_entry * 135 ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd) 136 { 137 struct ipmi_rq_entry * e = ipmi_req_entries; 138 while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) { 139 if (e->next == NULL || e == e->next) 140 return NULL; 141 e = e->next; 142 } 143 return e; 144 } 145 146 static void 147 ipmi_req_remove_entry(uint8_t seq, uint8_t cmd) 148 { 149 struct ipmi_rq_entry * p, * e, * saved_next_entry; 150 151 e = p = ipmi_req_entries; 152 153 while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) { 154 p = e; 155 e = e->next; 156 } 157 if (e) { 158 lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x", 159 seq, cmd); 160 saved_next_entry = e->next; 161 p->next = (p->next == e->next) ? NULL : e->next; 162 /* If entry being removed is first in list, fix up list head */ 163 if (ipmi_req_entries == e) { 164 if (ipmi_req_entries != p) 165 ipmi_req_entries = p; 166 else 167 ipmi_req_entries = saved_next_entry; 168 } 169 /* If entry being removed is last in list, fix up list tail */ 170 if (ipmi_req_entries_tail == e) { 171 if (ipmi_req_entries_tail != p) 172 ipmi_req_entries_tail = p; 173 else 174 ipmi_req_entries_tail = NULL; 175 } 176 if (e->msg_data) { 177 free(e->msg_data); 178 e->msg_data = NULL; 179 } 180 free(e); 181 e = NULL; 182 } 183 } 184 185 static void 186 ipmi_req_clear_entries(void) 187 { 188 struct ipmi_rq_entry * p, * e; 189 190 e = ipmi_req_entries; 191 while (e) { 192 lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x", 193 e->rq_seq, e->req.msg.cmd); 194 if (e->next != NULL) { 195 p = e->next; 196 free(e); 197 e = p; 198 } else { 199 free(e); 200 e = NULL; 201 break; 202 } 203 } 204 ipmi_req_entries = NULL; 205 } 206 207 static int 208 get_random(void *data, int len) 209 { 210 int fd = open("/dev/urandom", O_RDONLY); 211 int rv; 212 213 if (fd < 0) 214 return errno; 215 if (len < 0) { 216 close(fd); 217 return errno; /* XXX: ORLY? */ 218 } 219 220 rv = read(fd, data, len); 221 222 close(fd); 223 return rv; 224 } 225 226 static int 227 ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len) 228 { 229 if (verbose > 2) 230 printbuf(data, data_len, "send_packet"); 231 232 return send(intf->fd, data, data_len, 0); 233 } 234 235 static struct ipmi_rs * 236 ipmi_lan_recv_packet(struct ipmi_intf * intf) 237 { 238 static struct ipmi_rs rsp; 239 fd_set read_set, err_set; 240 struct timeval tmout; 241 int ret; 242 243 FD_ZERO(&read_set); 244 FD_SET(intf->fd, &read_set); 245 246 FD_ZERO(&err_set); 247 FD_SET(intf->fd, &err_set); 248 249 tmout.tv_sec = intf->session->timeout; 250 tmout.tv_usec = 0; 251 252 ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); 253 if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set)) 254 return NULL; 255 256 /* the first read may return ECONNREFUSED because the rmcp ping 257 * packet--sent to UDP port 623--will be processed by both the 258 * BMC and the OS. 259 * 260 * The problem with this is that the ECONNREFUSED takes 261 * priority over any other received datagram; that means that 262 * the Connection Refused shows up _before_ the response packet, 263 * regardless of the order they were sent out. (unless the 264 * response is read before the connection refused is returned) 265 */ 266 ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0); 267 268 if (ret < 0) { 269 FD_ZERO(&read_set); 270 FD_SET(intf->fd, &read_set); 271 272 FD_ZERO(&err_set); 273 FD_SET(intf->fd, &err_set); 274 275 tmout.tv_sec = intf->session->timeout; 276 tmout.tv_usec = 0; 277 278 ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); 279 if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set)) 280 return NULL; 281 282 ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0); 283 if (ret < 0) 284 return NULL; 285 } 286 287 if (ret == 0) 288 return NULL; 289 290 rsp.data[ret] = '\0'; 291 rsp.data_len = ret; 292 293 if (verbose > 2) 294 printbuf(rsp.data, rsp.data_len, "recv_packet"); 295 296 return &rsp; 297 } 298 299 /* 300 * parse response RMCP "pong" packet 301 * 302 * return -1 if ping response not received 303 * returns 0 if IPMI is NOT supported 304 * returns 1 if IPMI is supported 305 * 306 * udp.source = 0x026f // RMCP_UDP_PORT 307 * udp.dest = ? // udp.source from rmcp-ping 308 * udp.len = ? 309 * udp.check = ? 310 * rmcp.ver = 0x06 // RMCP Version 1.0 311 * rmcp.__res = 0x00 // RESERVED 312 * rmcp.seq = 0xff // no RMCP ACK 313 * rmcp.class = 0x06 // RMCP_CLASS_ASF 314 * asf.iana = 0x000011be // ASF_RMCP_IANA 315 * asf.type = 0x40 // ASF_TYPE_PONG 316 * asf.tag = ? // asf.tag from rmcp-ping 317 * asf.__res = 0x00 // RESERVED 318 * asf.len = 0x10 // 16 bytes 319 * asf.data[3:0]= 0x000011be // IANA# = RMCP_ASF_IANA if no OEM 320 * asf.data[7:4]= 0x00000000 // OEM-defined (not for IPMI) 321 * asf.data[8] = 0x81 // supported entities 322 * // [7]=IPMI [6:4]=RES [3:0]=ASF_1.0 323 * asf.data[9] = 0x00 // supported interactions (reserved) 324 * asf.data[f:a]= 0x000000000000 325 */ 326 static int 327 ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp) 328 { 329 struct rmcp_pong * pong; 330 331 if (rsp == NULL) 332 return -1; 333 334 pong = (struct rmcp_pong *)rsp->data; 335 336 lprintf(LOG_DEBUG, 337 "Received IPMI/RMCP response packet: \n" 338 " IPMI%s Supported\n" 339 " ASF Version %s\n" 340 " RMCP Version %s\n" 341 " RMCP Sequence %d\n" 342 " IANA Enterprise %ld\n", 343 (pong->sup_entities & 0x80) ? "" : " NOT", 344 (pong->sup_entities & 0x01) ? "1.0" : "unknown", 345 (pong->rmcp.ver == 6) ? "1.0" : "unknown", 346 pong->rmcp.seq, 347 ntohl(pong->iana)); 348 349 return (pong->sup_entities & 0x80) ? 1 : 0; 350 } 351 352 /* build and send RMCP presence ping packet 353 * 354 * RMCP ping 355 * 356 * udp.source = ? 357 * udp.dest = 0x026f // RMCP_UDP_PORT 358 * udp.len = ? 359 * udp.check = ? 360 * rmcp.ver = 0x06 // RMCP Version 1.0 361 * rmcp.__res = 0x00 // RESERVED 362 * rmcp.seq = 0xff // no RMCP ACK 363 * rmcp.class = 0x06 // RMCP_CLASS_ASF 364 * asf.iana = 0x000011be // ASF_RMCP_IANA 365 * asf.type = 0x80 // ASF_TYPE_PING 366 * asf.tag = ? // ASF sequence number 367 * asf.__res = 0x00 // RESERVED 368 * asf.len = 0x00 369 * 370 */ 371 static int 372 ipmi_lan_ping(struct ipmi_intf * intf) 373 { 374 struct asf_hdr asf_ping = { 375 .iana = htonl(ASF_RMCP_IANA), 376 .type = ASF_TYPE_PING, 377 }; 378 struct rmcp_hdr rmcp_ping = { 379 .ver = RMCP_VERSION_1, 380 .class = RMCP_CLASS_ASF, 381 .seq = 0xff, 382 }; 383 uint8_t * data; 384 int len = sizeof(rmcp_ping) + sizeof(asf_ping); 385 int rv; 386 387 data = malloc(len); 388 if (data == NULL) { 389 lprintf(LOG_ERR, "ipmitool: malloc failure"); 390 return -1; 391 } 392 memset(data, 0, len); 393 memcpy(data, &rmcp_ping, sizeof(rmcp_ping)); 394 memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping)); 395 396 lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet"); 397 398 rv = ipmi_lan_send_packet(intf, data, len); 399 400 free(data); 401 data = NULL; 402 403 if (rv < 0) { 404 lprintf(LOG_ERR, "Unable to send IPMI presence ping packet"); 405 return -1; 406 } 407 408 if (ipmi_lan_poll_recv(intf) == 0) 409 return 0; 410 411 return 1; 412 } 413 414 /* 415 * The "thump" functions are used to send an extra packet following each 416 * request message. This may kick-start some BMCs that get confused with 417 * bad passwords or operate poorly under heavy network load. 418 */ 419 static void 420 ipmi_lan_thump_first(struct ipmi_intf * intf) 421 { 422 /* is this random data? */ 423 uint8_t data[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 424 0x07, 0x20, 0x18, 0xc8, 0xc2, 0x01, 0x01, 0x3c }; 425 ipmi_lan_send_packet(intf, data, 16); 426 } 427 428 static void 429 ipmi_lan_thump(struct ipmi_intf * intf) 430 { 431 uint8_t data[10] = "thump"; 432 ipmi_lan_send_packet(intf, data, 10); 433 } 434 435 static struct ipmi_rs * 436 ipmi_lan_poll_recv(struct ipmi_intf * intf) 437 { 438 struct rmcp_hdr rmcp_rsp; 439 struct ipmi_rs * rsp; 440 struct ipmi_rq_entry * entry; 441 int x=0, rv; 442 uint8_t our_address = intf->my_addr; 443 444 if (our_address == 0) 445 our_address = IPMI_BMC_SLAVE_ADDR; 446 447 rsp = ipmi_lan_recv_packet(intf); 448 449 while (rsp != NULL) { 450 451 /* parse response headers */ 452 memcpy(&rmcp_rsp, rsp->data, 4); 453 454 switch (rmcp_rsp.class) { 455 case RMCP_CLASS_ASF: 456 /* ping response packet */ 457 rv = ipmi_handle_pong(intf, rsp); 458 return (rv <= 0) ? NULL : rsp; 459 case RMCP_CLASS_IPMI: 460 /* handled by rest of function */ 461 break; 462 default: 463 lprintf(LOG_DEBUG, "Invalid RMCP class: %x", 464 rmcp_rsp.class); 465 rsp = ipmi_lan_recv_packet(intf); 466 continue; 467 } 468 469 x = 4; 470 rsp->session.authtype = rsp->data[x++]; 471 memcpy(&rsp->session.seq, rsp->data+x, 4); 472 x += 4; 473 memcpy(&rsp->session.id, rsp->data+x, 4); 474 x += 4; 475 476 if (rsp->session.id == (intf->session->session_id + 0x10000000)) { 477 /* With SOL, authtype is always NONE, so we have no authcode */ 478 rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_SOL; 479 480 rsp->session.msglen = rsp->data[x++]; 481 482 rsp->payload.sol_packet.packet_sequence_number = 483 rsp->data[x++] & 0x0F; 484 485 rsp->payload.sol_packet.acked_packet_number = 486 rsp->data[x++] & 0x0F; 487 488 rsp->payload.sol_packet.accepted_character_count = 489 rsp->data[x++]; 490 491 rsp->payload.sol_packet.is_nack = 492 rsp->data[x] & 0x40; 493 494 rsp->payload.sol_packet.transfer_unavailable = 495 rsp->data[x] & 0x20; 496 497 rsp->payload.sol_packet.sol_inactive = 498 rsp->data[x] & 0x10; 499 500 rsp->payload.sol_packet.transmit_overrun = 501 rsp->data[x] & 0x08; 502 503 rsp->payload.sol_packet.break_detected = 504 rsp->data[x++] & 0x04; 505 506 x++; /* On ISOL there's and additional fifth byte before the data starts */ 507 508 lprintf(LOG_DEBUG, "SOL sequence number : 0x%02x", 509 rsp->payload.sol_packet.packet_sequence_number); 510 511 lprintf(LOG_DEBUG, "SOL acked packet : 0x%02x", 512 rsp->payload.sol_packet.acked_packet_number); 513 514 lprintf(LOG_DEBUG, "SOL accepted char count : 0x%02x", 515 rsp->payload.sol_packet.accepted_character_count); 516 517 lprintf(LOG_DEBUG, "SOL is nack : %s", 518 rsp->payload.sol_packet.is_nack? "true" : "false"); 519 520 lprintf(LOG_DEBUG, "SOL xfer unavailable : %s", 521 rsp->payload.sol_packet.transfer_unavailable? "true" : "false"); 522 523 lprintf(LOG_DEBUG, "SOL inactive : %s", 524 rsp->payload.sol_packet.sol_inactive? "true" : "false"); 525 526 lprintf(LOG_DEBUG, "SOL transmit overrun : %s", 527 rsp->payload.sol_packet.transmit_overrun? "true" : "false"); 528 529 lprintf(LOG_DEBUG, "SOL break detected : %s", 530 rsp->payload.sol_packet.break_detected? "true" : "false"); 531 } 532 else 533 { 534 /* Standard IPMI 1.5 packet */ 535 rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI; 536 if (intf->session->active && (rsp->session.authtype || intf->session->authtype)) 537 x += 16; 538 539 rsp->session.msglen = rsp->data[x++]; 540 rsp->payload.ipmi_response.rq_addr = rsp->data[x++]; 541 rsp->payload.ipmi_response.netfn = rsp->data[x] >> 2; 542 rsp->payload.ipmi_response.rq_lun = rsp->data[x++] & 0x3; 543 x++; /* checksum */ 544 rsp->payload.ipmi_response.rs_addr = rsp->data[x++]; 545 rsp->payload.ipmi_response.rq_seq = rsp->data[x] >> 2; 546 rsp->payload.ipmi_response.rs_lun = rsp->data[x++] & 0x3; 547 rsp->payload.ipmi_response.cmd = rsp->data[x++]; 548 rsp->ccode = rsp->data[x++]; 549 550 if (verbose > 2) 551 printbuf(rsp->data, rsp->data_len, "ipmi message header"); 552 553 lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header"); 554 lprintf(LOG_DEBUG+1, "<< Authtype : %s", 555 val2str(rsp->session.authtype, ipmi_authtype_session_vals)); 556 lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx", 557 (long)rsp->session.seq); 558 lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx", 559 (long)rsp->session.id); 560 lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header"); 561 lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x", 562 rsp->payload.ipmi_response.rq_addr); 563 lprintf(LOG_DEBUG+1, "<< NetFn : %02x", 564 rsp->payload.ipmi_response.netfn); 565 lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x", 566 rsp->payload.ipmi_response.rq_lun); 567 lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x", 568 rsp->payload.ipmi_response.rs_addr); 569 lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x", 570 rsp->payload.ipmi_response.rq_seq); 571 lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x", 572 rsp->payload.ipmi_response.rs_lun); 573 lprintf(LOG_DEBUG+1, "<< Command : %02x", 574 rsp->payload.ipmi_response.cmd); 575 lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x", 576 rsp->ccode); 577 578 /* now see if we have outstanding entry in request list */ 579 entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq, 580 rsp->payload.ipmi_response.cmd); 581 if (entry) { 582 lprintf(LOG_DEBUG+2, "IPMI Request Match found"); 583 if ((intf->target_addr != our_address) && bridge_possible) { 584 if ((rsp->data_len) && (rsp->payload.ipmi_response.netfn == 7) && 585 (rsp->payload.ipmi_response.cmd != 0x34)) { 586 if (verbose > 2) 587 printbuf(&rsp->data[x], rsp->data_len-x, 588 "bridge command response"); 589 } 590 /* bridged command: lose extra header */ 591 if (entry->bridging_level && 592 rsp->payload.ipmi_response.netfn == 7 && 593 rsp->payload.ipmi_response.cmd == 0x34) { 594 entry->bridging_level--; 595 if (rsp->data_len - x - 1 == 0) { 596 rsp = !rsp->ccode ? ipmi_lan_recv_packet(intf) : NULL; 597 if (!entry->bridging_level) 598 entry->req.msg.cmd = entry->req.msg.target_cmd; 599 if (rsp == NULL) { 600 ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.cmd); 601 } 602 continue; 603 } else { 604 /* The bridged answer data are inside the incoming packet */ 605 memmove(rsp->data + x - 7, 606 rsp->data + x, 607 rsp->data_len - x - 1); 608 rsp->data[x - 8] -= 8; 609 rsp->data_len -= 8; 610 entry->rq_seq = rsp->data[x - 3] >> 2; 611 if (!entry->bridging_level) 612 entry->req.msg.cmd = entry->req.msg.target_cmd; 613 continue; 614 } 615 } else { 616 //x += sizeof(rsp->payload.ipmi_response); 617 if (rsp->data[x-1] != 0) 618 lprintf(LOG_DEBUG, "WARNING: Bridged " 619 "cmd ccode = 0x%02x", 620 rsp->data[x-1]); 621 } 622 } 623 ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, 624 rsp->payload.ipmi_response.cmd); 625 } else { 626 lprintf(LOG_INFO, "IPMI Request Match NOT FOUND"); 627 rsp = ipmi_lan_recv_packet(intf); 628 continue; 629 } 630 } 631 632 break; 633 } 634 635 /* shift response data to start of array */ 636 if (rsp && rsp->data_len > x) { 637 rsp->data_len -= x; 638 if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) 639 rsp->data_len -= 1; /* We don't want the checksum */ 640 memmove(rsp->data, rsp->data + x, rsp->data_len); 641 memset(rsp->data + rsp->data_len, 0, IPMI_BUF_SIZE - rsp->data_len); 642 } 643 644 return rsp; 645 } 646 647 /* 648 * IPMI LAN Request Message Format 649 * +--------------------+ 650 * | rmcp.ver | 4 bytes 651 * | rmcp.__reserved | 652 * | rmcp.seq | 653 * | rmcp.class | 654 * +--------------------+ 655 * | session.authtype | 9 bytes 656 * | session.seq | 657 * | session.id | 658 * +--------------------+ 659 * | [session.authcode] | 16 bytes (AUTHTYPE != none) 660 * +--------------------+ 661 * | message length | 1 byte 662 * +--------------------+ 663 * | message.rs_addr | 6 bytes 664 * | message.netfn_lun | 665 * | message.checksum | 666 * | message.rq_addr | 667 * | message.rq_seq | 668 * | message.cmd | 669 * +--------------------+ 670 * | [request data] | data_len bytes 671 * +--------------------+ 672 * | checksum | 1 byte 673 * +--------------------+ 674 */ 675 static struct ipmi_rq_entry * 676 ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req, int isRetry) 677 { 678 struct rmcp_hdr rmcp = { 679 .ver = RMCP_VERSION_1, 680 .class = RMCP_CLASS_IPMI, 681 .seq = 0xff, 682 }; 683 uint8_t * msg, * temp; 684 int cs, mp, tmp; 685 int ap = 0; 686 int len = 0; 687 int cs2 = 0, cs3 = 0; 688 struct ipmi_rq_entry * entry; 689 struct ipmi_session * s = intf->session; 690 static int curr_seq = 0; 691 uint8_t our_address = intf->my_addr; 692 693 if (our_address == 0) 694 our_address = IPMI_BMC_SLAVE_ADDR; 695 696 if (isRetry == 0) 697 curr_seq++; 698 699 if (curr_seq >= 64) 700 curr_seq = 0; 701 702 // Bug in the existing code where it keeps on adding same command/seq pair 703 // in the lookup entry list. 704 // Check if we have cmd,seq pair already in our list. As we are not changing 705 // the seq number we have to re-use the node which has existing 706 // command and sequence number. If we add then we will have redundant node with 707 // same cmd,seq pair 708 entry = ipmi_req_lookup_entry(curr_seq, req->msg.cmd); 709 if (entry) 710 { 711 // This indicates that we have already same command and seq in list 712 // No need to add once again and we will re-use the existing node. 713 // Only thing we have to do is clear the msg_data as we create 714 // a new one below in the code for it. 715 if (entry->msg_data) { 716 free(entry->msg_data); 717 entry->msg_data = NULL; 718 } 719 } 720 else 721 { 722 // We dont have this request in the list so we can add it 723 // to the list 724 entry = ipmi_req_add_entry(intf, req, curr_seq); 725 if (entry == NULL) 726 return NULL; 727 } 728 729 len = req->msg.data_len + 29; 730 if (s->active && s->authtype) 731 len += 16; 732 if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0) 733 len += 8; 734 msg = malloc(len); 735 if (msg == NULL) { 736 lprintf(LOG_ERR, "ipmitool: malloc failure"); 737 return NULL; 738 } 739 memset(msg, 0, len); 740 741 /* rmcp header */ 742 memcpy(msg, &rmcp, sizeof(rmcp)); 743 len = sizeof(rmcp); 744 745 /* ipmi session header */ 746 msg[len++] = s->active ? s->authtype : 0; 747 748 msg[len++] = s->in_seq & 0xff; 749 msg[len++] = (s->in_seq >> 8) & 0xff; 750 msg[len++] = (s->in_seq >> 16) & 0xff; 751 msg[len++] = (s->in_seq >> 24) & 0xff; 752 memcpy(msg+len, &s->session_id, 4); 753 len += 4; 754 755 /* ipmi session authcode */ 756 if (s->active && s->authtype) { 757 ap = len; 758 memcpy(msg+len, s->authcode, 16); 759 len += 16; 760 } 761 762 /* message length */ 763 if ((intf->target_addr == our_address) || !bridge_possible) { 764 entry->bridging_level = 0; 765 msg[len++] = req->msg.data_len + 7; 766 cs = mp = len; 767 } else { 768 /* bridged request: encapsulate w/in Send Message */ 769 entry->bridging_level = 1; 770 msg[len++] = req->msg.data_len + 15 + 771 (intf->transit_addr != intf->my_addr && intf->transit_addr != 0 ? 8 : 0); 772 cs = mp = len; 773 msg[len++] = IPMI_BMC_SLAVE_ADDR; 774 msg[len++] = IPMI_NETFN_APP << 2; 775 tmp = len - cs; 776 msg[len++] = ipmi_csum(msg+cs, tmp); 777 cs2 = len; 778 msg[len++] = IPMI_REMOTE_SWID; 779 msg[len++] = curr_seq << 2; 780 msg[len++] = 0x34; /* Send Message rqst */ 781 entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */ 782 entry->req.msg.cmd = 0x34; /* (fixup request entry) */ 783 784 if (intf->transit_addr == intf->my_addr || intf->transit_addr == 0) { 785 msg[len++] = (0x40|intf->target_channel); /* Track request*/ 786 } else { 787 entry->bridging_level++; 788 msg[len++] = (0x40|intf->transit_channel); /* Track request*/ 789 cs = len; 790 msg[len++] = intf->transit_addr; 791 msg[len++] = IPMI_NETFN_APP << 2; 792 tmp = len - cs; 793 msg[len++] = ipmi_csum(msg+cs, tmp); 794 cs3 = len; 795 msg[len++] = intf->my_addr; 796 msg[len++] = curr_seq << 2; 797 msg[len++] = 0x34; /* Send Message rqst */ 798 msg[len++] = (0x40|intf->target_channel); /* Track request */ 799 } 800 cs = len; 801 } 802 803 /* ipmi message header */ 804 msg[len++] = intf->target_addr; 805 msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3); 806 tmp = len - cs; 807 msg[len++] = ipmi_csum(msg+cs, tmp); 808 cs = len; 809 810 if (!entry->bridging_level) 811 msg[len++] = IPMI_REMOTE_SWID; 812 /* Bridged message */ 813 else if (entry->bridging_level) 814 msg[len++] = intf->my_addr; 815 816 entry->rq_seq = curr_seq; 817 msg[len++] = entry->rq_seq << 2; 818 msg[len++] = req->msg.cmd; 819 820 lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header (level %d)", entry->bridging_level); 821 lprintf(LOG_DEBUG+1, ">> Authtype : %s", 822 val2str(s->authtype, ipmi_authtype_session_vals)); 823 lprintf(LOG_DEBUG+1, ">> Sequence : 0x%08lx", (long)s->in_seq); 824 lprintf(LOG_DEBUG+1, ">> Session ID : 0x%08lx", (long)s->session_id); 825 lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header"); 826 lprintf(LOG_DEBUG+1, ">> Rs Addr : %02x", intf->target_addr); 827 lprintf(LOG_DEBUG+1, ">> NetFn : %02x", req->msg.netfn); 828 lprintf(LOG_DEBUG+1, ">> Rs LUN : %01x", 0); 829 lprintf(LOG_DEBUG+1, ">> Rq Addr : %02x", IPMI_REMOTE_SWID); 830 lprintf(LOG_DEBUG+1, ">> Rq Seq : %02x", entry->rq_seq); 831 lprintf(LOG_DEBUG+1, ">> Rq Lun : %01x", 0); 832 lprintf(LOG_DEBUG+1, ">> Command : %02x", req->msg.cmd); 833 834 /* message data */ 835 if (req->msg.data_len) { 836 memcpy(msg+len, req->msg.data, req->msg.data_len); 837 len += req->msg.data_len; 838 } 839 840 /* second checksum */ 841 tmp = len - cs; 842 msg[len++] = ipmi_csum(msg+cs, tmp); 843 844 /* bridged request: 2nd checksum */ 845 if (entry->bridging_level) { 846 if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0) { 847 tmp = len - cs3; 848 msg[len++] = ipmi_csum(msg+cs3, tmp); 849 } 850 tmp = len - cs2; 851 msg[len++] = ipmi_csum(msg+cs2, tmp); 852 } 853 854 if (s->active) { 855 /* 856 * s->authcode is already copied to msg+ap but some 857 * authtypes require portions of the ipmi message to 858 * create the authcode so they must be done last. 859 */ 860 switch (s->authtype) { 861 case IPMI_SESSION_AUTHTYPE_MD5: 862 temp = ipmi_auth_md5(s, msg+mp, msg[mp-1]); 863 memcpy(msg+ap, temp, 16); 864 break; 865 case IPMI_SESSION_AUTHTYPE_MD2: 866 temp = ipmi_auth_md2(s, msg+mp, msg[mp-1]); 867 memcpy(msg+ap, temp, 16); 868 break; 869 } 870 } 871 872 if (s->in_seq) { 873 s->in_seq++; 874 if (s->in_seq == 0) 875 s->in_seq++; 876 } 877 878 entry->msg_len = len; 879 entry->msg_data = msg; 880 881 return entry; 882 } 883 884 static struct ipmi_rs * 885 ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) 886 { 887 struct ipmi_rq_entry * entry; 888 struct ipmi_rs * rsp = NULL; 889 int try = 0; 890 int isRetry = 0; 891 892 lprintf(LOG_DEBUG, "ipmi_lan_send_cmd:opened=[%d], open=[%d]", 893 intf->opened, intf->open); 894 895 if (intf->opened == 0 && intf->open != NULL) { 896 if (intf->open(intf) < 0) { 897 lprintf(LOG_DEBUG, "Failed to open LAN interface"); 898 return NULL; 899 } 900 lprintf(LOG_DEBUG, "\topened=[%d], open=[%d]", 901 intf->opened, intf->open); 902 } 903 904 for (;;) { 905 isRetry = ( try > 0 ) ? 1 : 0; 906 907 entry = ipmi_lan_build_cmd(intf, req, isRetry); 908 if (entry == NULL) { 909 lprintf(LOG_ERR, "Aborting send command, unable to build"); 910 return NULL; 911 } 912 913 if (ipmi_lan_send_packet(intf, entry->msg_data, entry->msg_len) < 0) { 914 try++; 915 usleep(5000); 916 ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.target_cmd); 917 continue; 918 } 919 920 /* if we are set to noanswer we do not expect response */ 921 if (intf->noanswer) 922 break; 923 924 if (ipmi_oem_active(intf, "intelwv2")) 925 ipmi_lan_thump(intf); 926 927 usleep(100); 928 929 rsp = ipmi_lan_poll_recv(intf); 930 931 /* Duplicate Request ccode most likely indicates a response to 932 a previous retry. Ignore and keep polling. */ 933 if((rsp != NULL) && (rsp->ccode == 0xcf)) { 934 rsp = NULL; 935 rsp = ipmi_lan_poll_recv(intf); 936 } 937 938 if (rsp) 939 break; 940 941 usleep(5000); 942 if (++try >= intf->session->retry) { 943 lprintf(LOG_DEBUG, " No response from remote controller"); 944 break; 945 } 946 } 947 948 // We need to cleanup the existing entries from the list. Because if we 949 // keep it and then when we send the new command and if the response is for 950 // old command it still matches it and then returns success. 951 // This is the corner case where the remote controller responds very slowly. 952 // 953 // Example: We have to send command 23 and 2d. 954 // If we send command,seq as 23,10 and if we dont get any response it will 955 // retry 4 times with 23,10 and then come out here and indicate that there is no 956 // reponse from the remote controller and will send the next command for 957 // ie 2d,11. And if the BMC is slow to respond and returns 23,10 then it 958 // will match it in the list and will take response of command 23 as response 959 // for command 2d and return success. So ideally when retries are done and 960 // are out of this function we should be clearing the list to be safe so that 961 // we dont match the old response with new request. 962 // [23, 10] --> BMC 963 // [23, 10] --> BMC 964 // [23, 10] --> BMC 965 // [23, 10] --> BMC 966 // [2D, 11] --> BMC 967 // <-- [23, 10] 968 // here if we maintain 23,10 in the list then it will get matched and consider 969 // 23 response as response for 2D. 970 ipmi_req_clear_entries(); 971 972 return rsp; 973 } 974 975 static uint8_t * 976 ipmi_lan_build_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp, int * llen) 977 { 978 struct rmcp_hdr rmcp = { 979 .ver = RMCP_VERSION_1, 980 .class = RMCP_CLASS_IPMI, 981 .seq = 0xff, 982 }; 983 struct ipmi_session * s = intf->session; 984 int cs, mp, ap = 0, tmp; 985 int len; 986 uint8_t * msg; 987 988 len = rsp->data_len + 22; 989 if (s->active) 990 len += 16; 991 992 msg = malloc(len); 993 if (msg == NULL) { 994 lprintf(LOG_ERR, "ipmitool: malloc failure"); 995 return NULL; 996 } 997 memset(msg, 0, len); 998 999 /* rmcp header */ 1000 memcpy(msg, &rmcp, 4); 1001 len = sizeof(rmcp); 1002 1003 /* ipmi session header */ 1004 msg[len++] = s->active ? s->authtype : 0; 1005 1006 if (s->in_seq) { 1007 s->in_seq++; 1008 if (s->in_seq == 0) 1009 s->in_seq++; 1010 } 1011 memcpy(msg+len, &s->in_seq, 4); 1012 len += 4; 1013 memcpy(msg+len, &s->session_id, 4); 1014 len += 4; 1015 1016 /* session authcode, if session active and authtype is not none */ 1017 if (s->active && s->authtype) { 1018 ap = len; 1019 memcpy(msg+len, s->authcode, 16); 1020 len += 16; 1021 } 1022 1023 /* message length */ 1024 msg[len++] = rsp->data_len + 8; 1025 1026 /* message header */ 1027 cs = mp = len; 1028 msg[len++] = IPMI_REMOTE_SWID; 1029 msg[len++] = rsp->msg.netfn << 2; 1030 tmp = len - cs; 1031 msg[len++] = ipmi_csum(msg+cs, tmp); 1032 cs = len; 1033 msg[len++] = IPMI_BMC_SLAVE_ADDR; 1034 msg[len++] = (rsp->msg.seq << 2) | (rsp->msg.lun & 3); 1035 msg[len++] = rsp->msg.cmd; 1036 1037 /* completion code */ 1038 msg[len++] = rsp->ccode; 1039 1040 /* message data */ 1041 if (rsp->data_len) { 1042 memcpy(msg+len, rsp->data, rsp->data_len); 1043 len += rsp->data_len; 1044 } 1045 1046 /* second checksum */ 1047 tmp = len - cs; 1048 msg[len++] = ipmi_csum(msg+cs, tmp); 1049 1050 if (s->active) { 1051 uint8_t * d; 1052 switch (s->authtype) { 1053 case IPMI_SESSION_AUTHTYPE_MD5: 1054 d = ipmi_auth_md5(s, msg+mp, msg[mp-1]); 1055 memcpy(msg+ap, d, 16); 1056 break; 1057 case IPMI_SESSION_AUTHTYPE_MD2: 1058 d = ipmi_auth_md2(s, msg+mp, msg[mp-1]); 1059 memcpy(msg+ap, d, 16); 1060 break; 1061 } 1062 } 1063 1064 *llen = len; 1065 return msg; 1066 } 1067 1068 static int 1069 ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp) 1070 { 1071 uint8_t * msg; 1072 int len = 0; 1073 int rv; 1074 1075 msg = ipmi_lan_build_rsp(intf, rsp, &len); 1076 if (len <= 0 || msg == NULL) { 1077 lprintf(LOG_ERR, "Invalid response packet"); 1078 if (msg != NULL) { 1079 free(msg); 1080 msg = NULL; 1081 } 1082 return -1; 1083 } 1084 1085 rv = sendto(intf->fd, msg, len, 0, 1086 (struct sockaddr *)&intf->session->addr, 1087 intf->session->addrlen); 1088 if (rv < 0) { 1089 lprintf(LOG_ERR, "Packet send failed"); 1090 if (msg != NULL) { 1091 free(msg); 1092 msg = NULL; 1093 } 1094 return -1; 1095 } 1096 1097 if (msg != NULL) { 1098 free(msg); 1099 msg = NULL; 1100 } 1101 return 0; 1102 } 1103 1104 /* 1105 * IPMI SOL Payload Format 1106 * +--------------------+ 1107 * | rmcp.ver | 4 bytes 1108 * | rmcp.__reserved | 1109 * | rmcp.seq | 1110 * | rmcp.class | 1111 * +--------------------+ 1112 * | session.authtype | 9 bytes 1113 * | session.seq | 1114 * | session.id | 1115 * +--------------------+ 1116 * | message length | 1 byte 1117 * +--------------------+ 1118 * | sol.seq | 5 bytes 1119 * | sol.ack_seq | 1120 * | sol.acc_count | 1121 * | sol.control | 1122 * | sol.__reserved | 1123 * +--------------------+ 1124 * | [request data] | data_len bytes 1125 * +--------------------+ 1126 */ 1127 uint8_t * ipmi_lan_build_sol_msg(struct ipmi_intf * intf, 1128 struct ipmi_v2_payload * payload, 1129 int * llen) 1130 { 1131 struct rmcp_hdr rmcp = { 1132 .ver = RMCP_VERSION_1, 1133 .class = RMCP_CLASS_IPMI, 1134 .seq = 0xff, 1135 }; 1136 struct ipmi_session * session = intf->session; 1137 1138 /* msg will hold the entire message to be sent */ 1139 uint8_t * msg; 1140 1141 int len = 0; 1142 1143 len = sizeof(rmcp) + // RMCP Header (4) 1144 10 + // IPMI Session Header 1145 5 + // SOL header 1146 payload->payload.sol_packet.character_count; // The actual payload 1147 1148 msg = malloc(len); 1149 if (msg == NULL) { 1150 lprintf(LOG_ERR, "ipmitool: malloc failure"); 1151 return NULL; 1152 } 1153 memset(msg, 0, len); 1154 1155 /* rmcp header */ 1156 memcpy(msg, &rmcp, sizeof(rmcp)); 1157 len = sizeof(rmcp); 1158 1159 /* ipmi session header */ 1160 msg[len++] = 0; /* SOL is always authtype = NONE */ 1161 msg[len++] = session->in_seq & 0xff; 1162 msg[len++] = (session->in_seq >> 8) & 0xff; 1163 msg[len++] = (session->in_seq >> 16) & 0xff; 1164 msg[len++] = (session->in_seq >> 24) & 0xff; 1165 1166 msg[len++] = session->session_id & 0xff; 1167 msg[len++] = (session->session_id >> 8) & 0xff; 1168 msg[len++] = (session->session_id >> 16) & 0xff; 1169 msg[len++] = ((session->session_id >> 24) + 0x10) & 0xff; /* Add 0x10 to MSB for SOL */ 1170 1171 msg[len++] = payload->payload.sol_packet.character_count + 5; 1172 1173 /* sol header */ 1174 msg[len++] = payload->payload.sol_packet.packet_sequence_number; 1175 msg[len++] = payload->payload.sol_packet.acked_packet_number; 1176 msg[len++] = payload->payload.sol_packet.accepted_character_count; 1177 msg[len] = payload->payload.sol_packet.is_nack ? 0x40 : 0; 1178 msg[len] |= payload->payload.sol_packet.assert_ring_wor ? 0x20 : 0; 1179 msg[len] |= payload->payload.sol_packet.generate_break ? 0x10 : 0; 1180 msg[len] |= payload->payload.sol_packet.deassert_cts ? 0x08 : 0; 1181 msg[len] |= payload->payload.sol_packet.deassert_dcd_dsr ? 0x04 : 0; 1182 msg[len] |= payload->payload.sol_packet.flush_inbound ? 0x02 : 0; 1183 msg[len++] |= payload->payload.sol_packet.flush_outbound ? 0x01 : 0; 1184 1185 len++; /* On SOL there's and additional fifth byte before the data starts */ 1186 1187 if (payload->payload.sol_packet.character_count) { 1188 /* We may have data to add */ 1189 memcpy(msg + len, 1190 payload->payload.sol_packet.data, 1191 payload->payload.sol_packet.character_count); 1192 len += payload->payload.sol_packet.character_count; 1193 } 1194 1195 session->in_seq++; 1196 if (session->in_seq == 0) 1197 session->in_seq++; 1198 1199 *llen = len; 1200 return msg; 1201 } 1202 1203 /* 1204 * is_sol_packet 1205 */ 1206 static int 1207 is_sol_packet(struct ipmi_rs * rsp) 1208 { 1209 return (rsp && 1210 (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)); 1211 } 1212 1213 1214 1215 /* 1216 * sol_response_acks_packet 1217 */ 1218 static int 1219 sol_response_acks_packet(struct ipmi_rs * rsp, 1220 struct ipmi_v2_payload * payload) 1221 { 1222 return (is_sol_packet(rsp) && 1223 payload && 1224 (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) && 1225 (rsp->payload.sol_packet.acked_packet_number == 1226 payload->payload.sol_packet.packet_sequence_number)); 1227 } 1228 1229 /* 1230 * ipmi_lan_send_sol_payload 1231 * 1232 */ 1233 static struct ipmi_rs * 1234 ipmi_lan_send_sol_payload(struct ipmi_intf * intf, 1235 struct ipmi_v2_payload * payload) 1236 { 1237 struct ipmi_rs * rsp = NULL; 1238 uint8_t * msg; 1239 int len; 1240 int try = 0; 1241 1242 if (intf->opened == 0 && intf->open != NULL) { 1243 if (intf->open(intf) < 0) 1244 return NULL; 1245 } 1246 1247 msg = ipmi_lan_build_sol_msg(intf, payload, &len); 1248 if (len <= 0 || msg == NULL) { 1249 lprintf(LOG_ERR, "Invalid SOL payload packet"); 1250 if (msg != NULL) { 1251 free(msg); 1252 msg = NULL; 1253 } 1254 return NULL; 1255 } 1256 1257 lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n"); 1258 1259 for (;;) { 1260 if (ipmi_lan_send_packet(intf, msg, len) < 0) { 1261 try++; 1262 usleep(5000); 1263 continue; 1264 } 1265 1266 /* if we are set to noanswer we do not expect response */ 1267 if (intf->noanswer) 1268 break; 1269 1270 if (payload->payload.sol_packet.packet_sequence_number == 0) { 1271 /* We're just sending an ACK. No need to retry. */ 1272 break; 1273 } 1274 1275 usleep(100); 1276 1277 rsp = ipmi_lan_recv_sol(intf); /* Grab the next packet */ 1278 1279 if (sol_response_acks_packet(rsp, payload)) 1280 break; 1281 1282 else if (is_sol_packet(rsp) && rsp->data_len) 1283 { 1284 /* 1285 * We're still waiting for our ACK, but we more data from 1286 * the BMC 1287 */ 1288 intf->session->sol_data.sol_input_handler(rsp); 1289 } 1290 1291 usleep(5000); 1292 if (++try >= intf->session->retry) { 1293 lprintf(LOG_DEBUG, " No response from remote controller"); 1294 break; 1295 } 1296 } 1297 1298 if (msg != NULL) { 1299 free(msg); 1300 msg = NULL; 1301 } 1302 return rsp; 1303 } 1304 1305 /* 1306 * is_sol_partial_ack 1307 * 1308 * Determine if the response is a partial ACK/NACK that indicates 1309 * we need to resend part of our packet. 1310 * 1311 * returns the number of characters we need to resend, or 1312 * 0 if this isn't an ACK or we don't need to resend anything 1313 */ 1314 static int is_sol_partial_ack(struct ipmi_v2_payload * v2_payload, 1315 struct ipmi_rs * rsp) 1316 { 1317 int chars_to_resend = 0; 1318 1319 if (v2_payload && 1320 rsp && 1321 is_sol_packet(rsp) && 1322 sol_response_acks_packet(rsp, v2_payload) && 1323 (rsp->payload.sol_packet.accepted_character_count < 1324 v2_payload->payload.sol_packet.character_count)) 1325 { 1326 if (rsp->payload.sol_packet.accepted_character_count == 0) { 1327 /* We should not resend data */ 1328 chars_to_resend = 0; 1329 } 1330 else 1331 { 1332 chars_to_resend = 1333 v2_payload->payload.sol_packet.character_count - 1334 rsp->payload.sol_packet.accepted_character_count; 1335 } 1336 } 1337 1338 return chars_to_resend; 1339 } 1340 1341 /* 1342 * set_sol_packet_sequence_number 1343 */ 1344 static void set_sol_packet_sequence_number(struct ipmi_intf * intf, 1345 struct ipmi_v2_payload * v2_payload) 1346 { 1347 /* Keep our sequence number sane */ 1348 if (intf->session->sol_data.sequence_number > 0x0F) 1349 intf->session->sol_data.sequence_number = 1; 1350 1351 v2_payload->payload.sol_packet.packet_sequence_number = 1352 intf->session->sol_data.sequence_number++; 1353 } 1354 1355 /* 1356 * ipmi_lan_send_sol 1357 * 1358 * Sends a SOL packet.. We handle partial ACK/NACKs from the BMC here. 1359 * 1360 * Returns a pointer to the SOL ACK we received, or 1361 * 0 on failure 1362 * 1363 */ 1364 struct ipmi_rs * 1365 ipmi_lan_send_sol(struct ipmi_intf * intf, 1366 struct ipmi_v2_payload * v2_payload) 1367 { 1368 struct ipmi_rs * rsp; 1369 int chars_to_resend = 0; 1370 1371 v2_payload->payload_type = IPMI_PAYLOAD_TYPE_SOL; 1372 1373 /* 1374 * Payload length is just the length of the character 1375 * data here. 1376 */ 1377 v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */ 1378 1379 set_sol_packet_sequence_number(intf, v2_payload); 1380 1381 v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */ 1382 1383 rsp = ipmi_lan_send_sol_payload(intf, v2_payload); 1384 1385 /* Determine if we need to resend some of our data */ 1386 chars_to_resend = is_sol_partial_ack(v2_payload, rsp); 1387 1388 while (chars_to_resend) 1389 { 1390 /* 1391 * We first need to handle any new data we might have 1392 * received in our NACK 1393 */ 1394 if (rsp->data_len) 1395 intf->session->sol_data.sol_input_handler(rsp); 1396 1397 set_sol_packet_sequence_number(intf, v2_payload); 1398 1399 /* Just send the required data */ 1400 memmove(v2_payload->payload.sol_packet.data, 1401 v2_payload->payload.sol_packet.data + 1402 rsp->payload.sol_packet.accepted_character_count, 1403 chars_to_resend); 1404 1405 v2_payload->payload.sol_packet.character_count = chars_to_resend; 1406 1407 rsp = ipmi_lan_send_sol_payload(intf, v2_payload); 1408 1409 chars_to_resend = is_sol_partial_ack(v2_payload, rsp); 1410 } 1411 1412 return rsp; 1413 } 1414 1415 /* 1416 * check_sol_packet_for_new_data 1417 * 1418 * Determine whether the SOL packet has already been seen 1419 * and whether the packet has new data for us. 1420 * 1421 * This function has the side effect of removing an previously 1422 * seen data, and moving new data to the front. 1423 * 1424 * It also "Remembers" the data so we don't get repeats. 1425 * 1426 */ 1427 static int 1428 check_sol_packet_for_new_data(struct ipmi_intf * intf, 1429 struct ipmi_rs *rsp) 1430 { 1431 static uint8_t last_received_sequence_number = 0; 1432 static uint8_t last_received_byte_count = 0; 1433 int new_data_size = 0; 1434 1435 if (rsp && 1436 (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)) 1437 1438 { 1439 uint8_t unaltered_data_len = rsp->data_len; 1440 if (rsp->payload.sol_packet.packet_sequence_number == 1441 last_received_sequence_number) 1442 { 1443 /* 1444 * This is the same as the last packet, but may include 1445 * extra data 1446 */ 1447 new_data_size = rsp->data_len - last_received_byte_count; 1448 1449 if (new_data_size > 0) 1450 { 1451 /* We have more data to process */ 1452 memmove(rsp->data, 1453 rsp->data + 1454 rsp->data_len - new_data_size, 1455 new_data_size); 1456 } 1457 1458 rsp->data_len = new_data_size; 1459 } 1460 1461 /* 1462 *Rember the data for next round 1463 */ 1464 if (rsp && rsp->payload.sol_packet.packet_sequence_number) 1465 { 1466 last_received_sequence_number = 1467 rsp->payload.sol_packet.packet_sequence_number; 1468 last_received_byte_count = unaltered_data_len; 1469 } 1470 } 1471 1472 return new_data_size; 1473 } 1474 1475 /* 1476 * ack_sol_packet 1477 * 1478 * Provided the specified packet looks reasonable, ACK it. 1479 */ 1480 static void 1481 ack_sol_packet(struct ipmi_intf * intf, 1482 struct ipmi_rs * rsp) 1483 { 1484 if (rsp && 1485 (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) && 1486 (rsp->payload.sol_packet.packet_sequence_number)) 1487 { 1488 struct ipmi_v2_payload ack; 1489 1490 memset(&ack, 0, sizeof(struct ipmi_v2_payload)); 1491 1492 ack.payload_type = IPMI_PAYLOAD_TYPE_SOL; 1493 1494 /* 1495 * Payload length is just the length of the character 1496 * data here. 1497 */ 1498 ack.payload_length = 0; 1499 1500 /* ACK packets have sequence numbers of 0 */ 1501 ack.payload.sol_packet.packet_sequence_number = 0; 1502 1503 ack.payload.sol_packet.acked_packet_number = 1504 rsp->payload.sol_packet.packet_sequence_number; 1505 1506 ack.payload.sol_packet.accepted_character_count = rsp->data_len; 1507 1508 ipmi_lan_send_sol_payload(intf, &ack); 1509 } 1510 } 1511 1512 /* 1513 * ipmi_recv_sol 1514 * 1515 * Receive a SOL packet and send an ACK in response. 1516 * 1517 */ 1518 static struct ipmi_rs * 1519 ipmi_lan_recv_sol(struct ipmi_intf * intf) 1520 { 1521 struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf); 1522 1523 ack_sol_packet(intf, rsp); 1524 1525 /* 1526 * Remembers the data sent, and alters the data to just 1527 * include the new stuff. 1528 */ 1529 check_sol_packet_for_new_data(intf, rsp); 1530 1531 return rsp; 1532 } 1533 1534 /* send a get device id command to keep session active */ 1535 static int 1536 ipmi_lan_keepalive(struct ipmi_intf * intf) 1537 { 1538 struct ipmi_rs * rsp; 1539 struct ipmi_rq req = { msg: { 1540 netfn: IPMI_NETFN_APP, 1541 cmd: 1, 1542 }}; 1543 1544 if (!intf->opened) 1545 return 0; 1546 1547 rsp = intf->sendrecv(intf, &req); 1548 if (rsp == NULL) 1549 return -1; 1550 if (rsp->ccode > 0) 1551 return -1; 1552 1553 return 0; 1554 } 1555 1556 /* 1557 * IPMI Get Channel Authentication Capabilities Command 1558 */ 1559 static int 1560 ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf) 1561 { 1562 struct ipmi_rs * rsp; 1563 struct ipmi_rq req; 1564 struct ipmi_session * s = intf->session; 1565 uint8_t msg_data[2]; 1566 1567 msg_data[0] = IPMI_LAN_CHANNEL_E; 1568 msg_data[1] = s->privlvl; 1569 1570 memset(&req, 0, sizeof(req)); 1571 req.msg.netfn = IPMI_NETFN_APP; 1572 req.msg.cmd = 0x38; 1573 req.msg.data = msg_data; 1574 req.msg.data_len = 2; 1575 1576 rsp = intf->sendrecv(intf, &req); 1577 if (rsp == NULL) { 1578 lprintf(LOG_INFO, "Get Auth Capabilities command failed"); 1579 return -1; 1580 } 1581 if (verbose > 2) 1582 printbuf(rsp->data, rsp->data_len, "get_auth_capabilities"); 1583 1584 if (rsp->ccode > 0) { 1585 lprintf(LOG_INFO, "Get Auth Capabilities command failed: %s", 1586 val2str(rsp->ccode, completion_code_vals)); 1587 return -1; 1588 } 1589 1590 lprintf(LOG_DEBUG, "Channel %02x Authentication Capabilities:", 1591 rsp->data[0]); 1592 lprintf(LOG_DEBUG, " Privilege Level : %s", 1593 val2str(req.msg.data[1], ipmi_privlvl_vals)); 1594 lprintf(LOG_DEBUG, " Auth Types : %s%s%s%s%s", 1595 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "", 1596 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "", 1597 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "", 1598 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "", 1599 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : ""); 1600 lprintf(LOG_DEBUG, " Per-msg auth : %sabled", 1601 (rsp->data[2] & IPMI_AUTHSTATUS_PER_MSG_DISABLED) ? 1602 "dis" : "en"); 1603 lprintf(LOG_DEBUG, " User level auth : %sabled", 1604 (rsp->data[2] & IPMI_AUTHSTATUS_PER_USER_DISABLED) ? 1605 "dis" : "en"); 1606 lprintf(LOG_DEBUG, " Non-null users : %sabled", 1607 (rsp->data[2] & IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED) ? 1608 "en" : "dis"); 1609 lprintf(LOG_DEBUG, " Null users : %sabled", 1610 (rsp->data[2] & IPMI_AUTHSTATUS_NULL_USERS_ENABLED) ? 1611 "en" : "dis"); 1612 lprintf(LOG_DEBUG, " Anonymous login : %sabled", 1613 (rsp->data[2] & IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED) ? 1614 "en" : "dis"); 1615 lprintf(LOG_DEBUG, ""); 1616 1617 s->authstatus = rsp->data[2]; 1618 1619 if (s->password && 1620 (s->authtype_set == 0 || 1621 s->authtype_set == IPMI_SESSION_AUTHTYPE_MD5) && 1622 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5)) 1623 { 1624 s->authtype = IPMI_SESSION_AUTHTYPE_MD5; 1625 } 1626 else if (s->password && 1627 (s->authtype_set == 0 || 1628 s->authtype_set == IPMI_SESSION_AUTHTYPE_MD2) && 1629 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2)) 1630 { 1631 s->authtype = IPMI_SESSION_AUTHTYPE_MD2; 1632 } 1633 else if (s->password && 1634 (s->authtype_set == 0 || 1635 s->authtype_set == IPMI_SESSION_AUTHTYPE_PASSWORD) && 1636 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD)) 1637 { 1638 s->authtype = IPMI_SESSION_AUTHTYPE_PASSWORD; 1639 } 1640 else if (s->password && 1641 (s->authtype_set == 0 || 1642 s->authtype_set == IPMI_SESSION_AUTHTYPE_OEM) && 1643 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM)) 1644 { 1645 s->authtype = IPMI_SESSION_AUTHTYPE_OEM; 1646 } 1647 else if ((s->authtype_set == 0 || 1648 s->authtype_set == IPMI_SESSION_AUTHTYPE_NONE) && 1649 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE)) 1650 { 1651 s->authtype = IPMI_SESSION_AUTHTYPE_NONE; 1652 } 1653 else { 1654 if (!(rsp->data[1] & 1<<s->authtype_set)) 1655 lprintf(LOG_ERR, "Authentication type %s not supported", 1656 val2str(s->authtype_set, ipmi_authtype_session_vals)); 1657 else 1658 lprintf(LOG_ERR, "No supported authtypes found"); 1659 1660 return -1; 1661 } 1662 1663 lprintf(LOG_DEBUG, "Proceeding with AuthType %s", 1664 val2str(s->authtype, ipmi_authtype_session_vals)); 1665 1666 return 0; 1667 } 1668 1669 /* 1670 * IPMI Get Session Challenge Command 1671 * returns a temporary session ID and 16 byte challenge string 1672 */ 1673 static int 1674 ipmi_get_session_challenge_cmd(struct ipmi_intf * intf) 1675 { 1676 struct ipmi_rs * rsp; 1677 struct ipmi_rq req; 1678 struct ipmi_session * s = intf->session; 1679 uint8_t msg_data[17]; 1680 1681 memset(msg_data, 0, 17); 1682 msg_data[0] = s->authtype; 1683 memcpy(msg_data+1, s->username, 16); 1684 1685 memset(&req, 0, sizeof(req)); 1686 req.msg.netfn = IPMI_NETFN_APP; 1687 req.msg.cmd = 0x39; 1688 req.msg.data = msg_data; 1689 req.msg.data_len = 17; /* 1 byte for authtype, 16 for user */ 1690 1691 rsp = intf->sendrecv(intf, &req); 1692 if (rsp == NULL) { 1693 lprintf(LOG_ERR, "Get Session Challenge command failed"); 1694 return -1; 1695 } 1696 if (verbose > 2) 1697 printbuf(rsp->data, rsp->data_len, "get_session_challenge"); 1698 1699 if (rsp->ccode > 0) { 1700 switch (rsp->ccode) { 1701 case 0x81: 1702 lprintf(LOG_ERR, "Invalid user name"); 1703 break; 1704 case 0x82: 1705 lprintf(LOG_ERR, "NULL user name not enabled"); 1706 break; 1707 default: 1708 lprintf(LOG_ERR, "Get Session Challenge command failed: %s", 1709 val2str(rsp->ccode, completion_code_vals)); 1710 } 1711 return -1; 1712 } 1713 1714 memcpy(&s->session_id, rsp->data, 4); 1715 memcpy(s->challenge, rsp->data + 4, 16); 1716 1717 lprintf(LOG_DEBUG, "Opening Session"); 1718 lprintf(LOG_DEBUG, " Session ID : %08lx", (long)s->session_id); 1719 lprintf(LOG_DEBUG, " Challenge : %s", buf2str(s->challenge, 16)); 1720 1721 return 0; 1722 } 1723 1724 /* 1725 * IPMI Activate Session Command 1726 */ 1727 static int 1728 ipmi_activate_session_cmd(struct ipmi_intf * intf) 1729 { 1730 struct ipmi_rs * rsp; 1731 struct ipmi_rq req; 1732 struct ipmi_session * s = intf->session; 1733 uint8_t msg_data[22]; 1734 1735 memset(&req, 0, sizeof(req)); 1736 req.msg.netfn = IPMI_NETFN_APP; 1737 req.msg.cmd = 0x3a; 1738 1739 msg_data[0] = s->authtype; 1740 msg_data[1] = s->privlvl; 1741 1742 /* supermicro oem authentication hack */ 1743 if (ipmi_oem_active(intf, "supermicro")) { 1744 uint8_t * special = ipmi_auth_special(s); 1745 memcpy(s->authcode, special, 16); 1746 memset(msg_data + 2, 0, 16); 1747 lprintf(LOG_DEBUG, " OEM Auth : %s", 1748 buf2str(special, 16)); 1749 } else { 1750 memcpy(msg_data + 2, s->challenge, 16); 1751 } 1752 1753 /* setup initial outbound sequence number */ 1754 get_random(msg_data+18, 4); 1755 1756 req.msg.data = msg_data; 1757 req.msg.data_len = 22; 1758 1759 s->active = 1; 1760 1761 lprintf(LOG_DEBUG, " Privilege Level : %s", 1762 val2str(msg_data[1], ipmi_privlvl_vals)); 1763 lprintf(LOG_DEBUG, " Auth Type : %s", 1764 val2str(s->authtype, ipmi_authtype_session_vals)); 1765 1766 rsp = intf->sendrecv(intf, &req); 1767 if (rsp == NULL) { 1768 lprintf(LOG_ERR, "Activate Session command failed"); 1769 s->active = 0; 1770 return -1; 1771 } 1772 if (verbose > 2) 1773 printbuf(rsp->data, rsp->data_len, "activate_session"); 1774 1775 if (rsp->ccode) { 1776 fprintf(stderr, "Activate Session error:"); 1777 switch (rsp->ccode) { 1778 case 0x81: 1779 lprintf(LOG_ERR, "\tNo session slot available"); 1780 break; 1781 case 0x82: 1782 lprintf(LOG_ERR, "\tNo slot available for given user - " 1783 "limit reached"); 1784 break; 1785 case 0x83: 1786 lprintf(LOG_ERR, "\tNo slot available to support user " 1787 "due to maximum privilege capacity"); 1788 break; 1789 case 0x84: 1790 lprintf(LOG_ERR, "\tSession sequence out of range"); 1791 break; 1792 case 0x85: 1793 lprintf(LOG_ERR, "\tInvalid session ID in request"); 1794 break; 1795 case 0x86: 1796 lprintf(LOG_ERR, "\tRequested privilege level " 1797 "exceeds limit"); 1798 break; 1799 case 0xd4: 1800 lprintf(LOG_ERR, "\tInsufficient privilege level"); 1801 break; 1802 default: 1803 lprintf(LOG_ERR, "\t%s", 1804 val2str(rsp->ccode, completion_code_vals)); 1805 } 1806 return -1; 1807 } 1808 1809 memcpy(&s->session_id, rsp->data + 1, 4); 1810 s->in_seq = rsp->data[8] << 24 | rsp->data[7] << 16 | rsp->data[6] << 8 | rsp->data[5]; 1811 if (s->in_seq == 0) 1812 ++s->in_seq; 1813 1814 if (s->authstatus & IPMI_AUTHSTATUS_PER_MSG_DISABLED) 1815 s->authtype = IPMI_SESSION_AUTHTYPE_NONE; 1816 else if (s->authtype != (rsp->data[0] & 0xf)) { 1817 lprintf(LOG_ERR, "Invalid Session AuthType %s in response", 1818 val2str(s->authtype, ipmi_authtype_session_vals)); 1819 return -1; 1820 } 1821 1822 bridge_possible = 1; 1823 1824 lprintf(LOG_DEBUG, "\nSession Activated"); 1825 lprintf(LOG_DEBUG, " Auth Type : %s", 1826 val2str(rsp->data[0], ipmi_authtype_session_vals)); 1827 lprintf(LOG_DEBUG, " Max Priv Level : %s", 1828 val2str(rsp->data[9], ipmi_privlvl_vals)); 1829 lprintf(LOG_DEBUG, " Session ID : %08lx", (long)s->session_id); 1830 lprintf(LOG_DEBUG, " Inbound Seq : %08lx\n", (long)s->in_seq); 1831 1832 return 0; 1833 } 1834 1835 1836 /* 1837 * IPMI Set Session Privilege Level Command 1838 */ 1839 static int 1840 ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) 1841 { 1842 struct ipmi_rs * rsp; 1843 struct ipmi_rq req; 1844 uint8_t privlvl = intf->session->privlvl; 1845 uint8_t backup_bridge_possible = bridge_possible; 1846 1847 if (privlvl <= IPMI_SESSION_PRIV_USER) 1848 return 0; /* no need to set higher */ 1849 1850 memset(&req, 0, sizeof(req)); 1851 req.msg.netfn = IPMI_NETFN_APP; 1852 req.msg.cmd = 0x3b; 1853 req.msg.data = &privlvl; 1854 req.msg.data_len = 1; 1855 1856 bridge_possible = 0; 1857 rsp = intf->sendrecv(intf, &req); 1858 bridge_possible = backup_bridge_possible; 1859 1860 if (rsp == NULL) { 1861 lprintf(LOG_ERR, "Set Session Privilege Level to %s failed", 1862 val2str(privlvl, ipmi_privlvl_vals)); 1863 return -1; 1864 } 1865 if (verbose > 2) 1866 printbuf(rsp->data, rsp->data_len, "set_session_privlvl"); 1867 1868 if (rsp->ccode > 0) { 1869 lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s", 1870 val2str(privlvl, ipmi_privlvl_vals), 1871 val2str(rsp->ccode, completion_code_vals)); 1872 return -1; 1873 } 1874 1875 lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n", 1876 val2str(rsp->data[0], ipmi_privlvl_vals)); 1877 1878 return 0; 1879 } 1880 1881 static int 1882 ipmi_close_session_cmd(struct ipmi_intf * intf) 1883 { 1884 struct ipmi_rs * rsp; 1885 struct ipmi_rq req; 1886 uint8_t msg_data[4]; 1887 uint32_t session_id = intf->session->session_id; 1888 1889 if (intf->session->active == 0) 1890 return -1; 1891 1892 intf->target_addr = IPMI_BMC_SLAVE_ADDR; 1893 bridge_possible = 0; /* Not a bridge message */ 1894 1895 memcpy(&msg_data, &session_id, 4); 1896 1897 memset(&req, 0, sizeof(req)); 1898 req.msg.netfn = IPMI_NETFN_APP; 1899 req.msg.cmd = 0x3c; 1900 req.msg.data = msg_data; 1901 req.msg.data_len = 4; 1902 1903 rsp = intf->sendrecv(intf, &req); 1904 if (rsp == NULL) { 1905 lprintf(LOG_ERR, "Close Session command failed"); 1906 return -1; 1907 } 1908 if (verbose > 2) 1909 printbuf(rsp->data, rsp->data_len, "close_session"); 1910 1911 if (rsp->ccode == 0x87) { 1912 lprintf(LOG_ERR, "Failed to Close Session: invalid " 1913 "session ID %08lx", (long)session_id); 1914 return -1; 1915 } 1916 if (rsp->ccode > 0) { 1917 lprintf(LOG_ERR, "Close Session command failed: %s", 1918 val2str(rsp->ccode, completion_code_vals)); 1919 return -1; 1920 } 1921 1922 lprintf(LOG_DEBUG, "Closed Session %08lx\n", (long)session_id); 1923 1924 return 0; 1925 } 1926 1927 /* 1928 * IPMI LAN Session Activation (IPMI spec v1.5 section 12.9) 1929 * 1930 * 1. send "RMCP Presence Ping" message, response message will 1931 * indicate whether the platform supports IPMI 1932 * 2. send "Get Channel Authentication Capabilities" command 1933 * with AUTHTYPE = none, response packet will contain information 1934 * about supported challenge/response authentication types 1935 * 3. send "Get Session Challenge" command with AUTHTYPE = none 1936 * and indicate the authentication type in the message, response 1937 * packet will contain challenge string and temporary session ID. 1938 * 4. send "Activate Session" command, authenticated with AUTHTYPE 1939 * sent in previous message. Also sends the initial value for 1940 * the outbound sequence number for BMC. 1941 * 5. BMC returns response confirming session activation and 1942 * session ID for this session and initial inbound sequence. 1943 */ 1944 static int 1945 ipmi_lan_activate_session(struct ipmi_intf * intf) 1946 { 1947 int rc; 1948 1949 /* don't fail on ping because its not always supported. 1950 * Supermicro's IPMI LAN 1.5 cards don't tolerate pings. 1951 */ 1952 if (!ipmi_oem_active(intf, "supermicro")) 1953 ipmi_lan_ping(intf); 1954 1955 /* Some particular Intel boards need special help 1956 */ 1957 if (ipmi_oem_active(intf, "intelwv2")) 1958 ipmi_lan_thump_first(intf); 1959 1960 rc = ipmi_get_auth_capabilities_cmd(intf); 1961 if (rc < 0) { 1962 goto fail; 1963 } 1964 1965 rc = ipmi_get_session_challenge_cmd(intf); 1966 if (rc < 0) 1967 goto fail; 1968 1969 rc = ipmi_activate_session_cmd(intf); 1970 if (rc < 0) 1971 goto fail; 1972 1973 intf->abort = 0; 1974 1975 rc = ipmi_set_session_privlvl_cmd(intf); 1976 if (rc < 0) 1977 goto fail; 1978 1979 return 0; 1980 1981 fail: 1982 lprintf(LOG_ERR, "Error: Unable to establish LAN session"); 1983 return -1; 1984 } 1985 1986 static void 1987 ipmi_lan_close(struct ipmi_intf * intf) 1988 { 1989 if (intf->abort == 0) 1990 ipmi_close_session_cmd(intf); 1991 1992 if (intf->fd >= 0) 1993 close(intf->fd); 1994 1995 ipmi_req_clear_entries(); 1996 1997 if (intf->session != NULL) { 1998 free(intf->session); 1999 intf->session = NULL; 2000 } 2001 2002 intf->opened = 0; 2003 intf->manufacturer_id = IPMI_OEM_UNKNOWN; 2004 intf = NULL; 2005 } 2006 2007 static int 2008 ipmi_lan_open(struct ipmi_intf * intf) 2009 { 2010 int rc; 2011 struct ipmi_session *s; 2012 2013 if (intf == NULL || intf->session == NULL) 2014 return -1; 2015 s = intf->session; 2016 2017 if (s->port == 0) 2018 s->port = IPMI_LAN_PORT; 2019 if (s->privlvl == 0) 2020 s->privlvl = IPMI_SESSION_PRIV_ADMIN; 2021 if (s->timeout == 0) 2022 s->timeout = IPMI_LAN_TIMEOUT; 2023 if (s->retry == 0) 2024 s->retry = IPMI_LAN_RETRY; 2025 2026 if (s->hostname == NULL || strlen((const char *)s->hostname) == 0) { 2027 lprintf(LOG_ERR, "No hostname specified!"); 2028 return -1; 2029 } 2030 2031 intf->abort = 1; 2032 2033 intf->session->sol_data.sequence_number = 1; 2034 2035 if (ipmi_intf_socket_connect (intf) == -1) { 2036 lprintf(LOG_ERR, "Could not open socket!"); 2037 return -1; 2038 } 2039 2040 if (intf->fd < 0) { 2041 lperror(LOG_ERR, "Connect to %s failed", 2042 s->hostname); 2043 intf->close(intf); 2044 return -1; 2045 } 2046 2047 intf->opened = 1; 2048 2049 /* try to open session */ 2050 rc = ipmi_lan_activate_session(intf); 2051 if (rc < 0) { 2052 intf->close(intf); 2053 intf->opened = 0; 2054 return -1; 2055 } 2056 2057 intf->manufacturer_id = ipmi_get_oem(intf); 2058 return intf->fd; 2059 } 2060 2061 static int 2062 ipmi_lan_setup(struct ipmi_intf * intf) 2063 { 2064 intf->session = malloc(sizeof(struct ipmi_session)); 2065 if (intf->session == NULL) { 2066 lprintf(LOG_ERR, "ipmitool: malloc failure"); 2067 return -1; 2068 } 2069 memset(intf->session, 0, sizeof(struct ipmi_session)); 2070 return 0; 2071 } 2072