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 <time.h> 45 #include <fcntl.h> 46 #include <assert.h> 47 48 #ifdef HAVE_CONFIG_H 49 # include <config.h> 50 #endif 51 #include <ipmitool/helper.h> 52 #include <ipmitool/log.h> 53 #include <ipmitool/ipmi.h> 54 #include <ipmitool/ipmi_lanp.h> 55 #include <ipmitool/ipmi_channel.h> 56 #include <ipmitool/ipmi_intf.h> 57 #include <ipmitool/ipmi_strings.h> 58 #include <ipmitool/bswap.h> 59 #include <openssl/rand.h> 60 61 #include "lanplus.h" 62 #include "lanplus_crypt.h" 63 #include "lanplus_crypt_impl.h" 64 #include "lanplus_dump.h" 65 #include "rmcp.h" 66 #include "asf.h" 67 68 extern const struct valstr ipmi_rakp_return_codes[]; 69 extern const struct valstr ipmi_priv_levels[]; 70 extern const struct valstr ipmi_auth_algorithms[]; 71 extern const struct valstr ipmi_integrity_algorithms[]; 72 extern const struct valstr ipmi_encryption_algorithms[]; 73 74 static struct ipmi_rq_entry * ipmi_req_entries; 75 static struct ipmi_rq_entry * ipmi_req_entries_tail; 76 77 78 static int ipmi_lanplus_setup(struct ipmi_intf * intf); 79 static int ipmi_lanplus_keepalive(struct ipmi_intf * intf); 80 static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len); 81 static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf); 82 static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf); 83 static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, struct ipmi_rq * req); 84 static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf, 85 struct ipmi_v2_payload * payload); 86 static void getIpmiPayloadWireRep( 87 struct ipmi_intf * intf, 88 struct ipmi_v2_payload * payload, /* in */ 89 uint8_t * out, 90 struct ipmi_rq * req, 91 uint8_t rq_seq, 92 uint8_t curr_seq); 93 static void getSolPayloadWireRep( 94 struct ipmi_intf * intf, 95 uint8_t * msg, 96 struct ipmi_v2_payload * payload); 97 static void read_open_session_response(struct ipmi_rs * rsp, int offset); 98 static void read_rakp2_message(struct ipmi_rs * rsp, int offset, uint8_t alg); 99 static void read_rakp4_message(struct ipmi_rs * rsp, int offset, uint8_t alg); 100 static void read_session_data(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s); 101 static void read_session_data_v15(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s); 102 static void read_session_data_v2x(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s); 103 static void read_ipmi_response(struct ipmi_rs * rsp, int * offset); 104 static void read_sol_packet(struct ipmi_rs * rsp, int * offset); 105 static struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf); 106 static struct ipmi_rs * ipmi_lanplus_send_sol( 107 struct ipmi_intf * intf, 108 struct ipmi_v2_payload * payload); 109 static int check_sol_packet_for_new_data( 110 struct ipmi_intf * intf, 111 struct ipmi_rs *rsp); 112 static void ack_sol_packet( 113 struct ipmi_intf * intf, 114 struct ipmi_rs * rsp); 115 116 static uint8_t bridgePossible = 0; 117 118 struct ipmi_intf ipmi_lanplus_intf = { 119 name: "lanplus", 120 desc: "IPMI v2.0 RMCP+ LAN Interface", 121 setup: ipmi_lanplus_setup, 122 open: ipmi_lanplus_open, 123 close: ipmi_lanplus_close, 124 sendrecv: ipmi_lanplus_send_ipmi_cmd, 125 recv_sol: ipmi_lanplus_recv_sol, 126 send_sol: ipmi_lanplus_send_sol, 127 keepalive: ipmi_lanplus_keepalive, 128 target_addr: IPMI_BMC_SLAVE_ADDR, 129 }; 130 131 132 extern int verbose; 133 134 135 136 /* 137 * lanplus_get_requested_ciphers 138 * 139 * Set the authentication, integrity and encryption algorithms based 140 * on the cipher suite ID. See table 22-19 in the IPMIv2 spec for the 141 * source of this information. 142 * 143 * param cipher_suite_id [in] 144 * param auth_alg [out] 145 * param integrity_alg [out] 146 * param crypt_alg [out] 147 * 148 * returns 0 on success 149 * 1 on failure 150 */ 151 int lanplus_get_requested_ciphers(int cipher_suite_id, 152 uint8_t * auth_alg, 153 uint8_t * integrity_alg, 154 uint8_t * crypt_alg) 155 { 156 if ((cipher_suite_id < 0) || (cipher_suite_id > 14)) 157 return 1; 158 159 /* See table 22-19 for the source of the statement */ 160 switch (cipher_suite_id) 161 { 162 case 0: 163 *auth_alg = IPMI_AUTH_RAKP_NONE; 164 *integrity_alg = IPMI_INTEGRITY_NONE; 165 *crypt_alg = IPMI_CRYPT_NONE; 166 break; 167 case 1: 168 *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 169 *integrity_alg = IPMI_INTEGRITY_NONE; 170 *crypt_alg = IPMI_CRYPT_NONE; 171 break; 172 case 2: 173 *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 174 *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 175 *crypt_alg = IPMI_CRYPT_NONE; 176 break; 177 case 3: 178 *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 179 *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 180 *crypt_alg = IPMI_CRYPT_AES_CBC_128; 181 break; 182 case 4: 183 *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 184 *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 185 *crypt_alg = IPMI_CRYPT_XRC4_128; 186 break; 187 case 5: 188 *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 189 *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 190 *crypt_alg = IPMI_CRYPT_XRC4_40; 191 break; 192 case 6: 193 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 194 *integrity_alg = IPMI_INTEGRITY_NONE; 195 *crypt_alg = IPMI_CRYPT_NONE; 196 break; 197 case 7: 198 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 199 *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 200 *crypt_alg = IPMI_CRYPT_NONE; 201 break; 202 case 8: 203 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 204 *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 205 *crypt_alg = IPMI_CRYPT_AES_CBC_128; 206 break; 207 case 9: 208 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 209 *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 210 *crypt_alg = IPMI_CRYPT_XRC4_128; 211 break; 212 case 10: 213 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 214 *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 215 *crypt_alg = IPMI_CRYPT_XRC4_40; 216 break; 217 case 11: 218 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 219 *integrity_alg = IPMI_INTEGRITY_MD5_128; 220 *crypt_alg = IPMI_CRYPT_NONE; 221 break; 222 case 12: 223 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 224 *integrity_alg = IPMI_INTEGRITY_MD5_128; 225 *crypt_alg = IPMI_CRYPT_AES_CBC_128; 226 break; 227 case 13: 228 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 229 *integrity_alg = IPMI_INTEGRITY_MD5_128; 230 *crypt_alg = IPMI_CRYPT_XRC4_128; 231 break; 232 case 14: 233 *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 234 *integrity_alg = IPMI_INTEGRITY_MD5_128; 235 *crypt_alg = IPMI_CRYPT_XRC4_40; 236 break; 237 } 238 239 return 0; 240 } 241 242 243 244 /* 245 * Reverse the order of arbitrarily long strings of bytes 246 */ 247 void lanplus_swap( 248 uint8_t * buffer, 249 int length) 250 { 251 int i; 252 uint8_t temp; 253 254 for (i =0; i < length/2; ++i) 255 { 256 temp = buffer[i]; 257 buffer[i] = buffer[length - 1 - i]; 258 buffer[length - 1 - i] = temp; 259 } 260 } 261 262 263 264 static const struct valstr plus_payload_types_vals[] = { 265 { IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message 266 { IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN) 267 { IPMI_PAYLOAD_TYPE_OEM, "OEM (2)" }, // OEM Explicid 268 269 { IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST, "OpenSession Req (0x10)" }, 270 { IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE,"OpenSession Resp (0x11)" }, 271 { IPMI_PAYLOAD_TYPE_RAKP_1, "RAKP1 (0x12)" }, 272 { IPMI_PAYLOAD_TYPE_RAKP_2, "RAKP2 (0x13)" }, 273 { IPMI_PAYLOAD_TYPE_RAKP_3, "RAKP3 (0x14)" }, 274 { IPMI_PAYLOAD_TYPE_RAKP_4, "RAKP4 (0x15)" }, 275 { 0x00, NULL }, 276 }; 277 278 279 static struct ipmi_rq_entry * 280 ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq) 281 { 282 struct ipmi_rq_entry * e; 283 284 e = malloc(sizeof(struct ipmi_rq_entry)); 285 if (e == NULL) { 286 lprintf(LOG_ERR, "ipmitool: malloc failure"); 287 return NULL; 288 } 289 290 memset(e, 0, sizeof(struct ipmi_rq_entry)); 291 memcpy(&e->req, req, sizeof(struct ipmi_rq)); 292 293 e->intf = intf; 294 e->rq_seq = req_seq; 295 296 if (ipmi_req_entries == NULL) 297 ipmi_req_entries = e; 298 else 299 ipmi_req_entries_tail->next = e; 300 301 ipmi_req_entries_tail = e; 302 lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x", 303 e->rq_seq, e->req.msg.cmd); 304 return e; 305 } 306 307 308 static struct ipmi_rq_entry * 309 ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd) 310 { 311 struct ipmi_rq_entry * e = ipmi_req_entries; 312 313 while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) { 314 if (e == e->next) 315 return NULL; 316 e = e->next; 317 } 318 return e; 319 } 320 321 static void 322 ipmi_req_remove_entry(uint8_t seq, uint8_t cmd) 323 { 324 struct ipmi_rq_entry * p, * e, * saved_next_entry; 325 326 e = p = ipmi_req_entries; 327 328 while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) { 329 p = e; 330 e = e->next; 331 } 332 if (e) { 333 lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x", 334 seq, cmd); 335 saved_next_entry = e->next; 336 p->next = (p->next == e->next) ? NULL : e->next; 337 /* If entry being removed is first in list, fix up list head */ 338 if (ipmi_req_entries == e) { 339 if (ipmi_req_entries != p) 340 ipmi_req_entries = p; 341 else 342 ipmi_req_entries = saved_next_entry; 343 } 344 /* If entry being removed is last in list, fix up list tail */ 345 if (ipmi_req_entries_tail == e) { 346 if (ipmi_req_entries_tail != p) 347 ipmi_req_entries_tail = p; 348 else 349 ipmi_req_entries_tail = NULL; 350 } 351 352 if (e->msg_data) { 353 free(e->msg_data); 354 e->msg_data = NULL; 355 } 356 free(e); 357 e = NULL; 358 } 359 } 360 361 static void 362 ipmi_req_clear_entries(void) 363 { 364 struct ipmi_rq_entry * p, * e; 365 366 e = ipmi_req_entries; 367 while (e) { 368 lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x", 369 e->rq_seq, e->req.msg.cmd); 370 p = e->next; 371 free(e); 372 e = p; 373 } 374 } 375 376 377 int 378 ipmi_lan_send_packet( 379 struct ipmi_intf * intf, 380 uint8_t * data, int 381 data_len) 382 { 383 if (verbose >= 5) 384 printbuf(data, data_len, ">> sending packet"); 385 386 return send(intf->fd, data, data_len, 0); 387 } 388 389 390 391 struct ipmi_rs * 392 ipmi_lan_recv_packet(struct ipmi_intf * intf) 393 { 394 static struct ipmi_rs rsp; 395 fd_set read_set, err_set; 396 struct timeval tmout; 397 int ret; 398 399 FD_ZERO(&read_set); 400 FD_SET(intf->fd, &read_set); 401 402 FD_ZERO(&err_set); 403 FD_SET(intf->fd, &err_set); 404 405 tmout.tv_sec = intf->session->timeout; 406 tmout.tv_usec = 0; 407 408 ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); 409 if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set)) 410 return NULL; 411 412 /* the first read may return ECONNREFUSED because the rmcp ping 413 * packet--sent to UDP port 623--will be processed by both the 414 * BMC and the OS. 415 * 416 * The problem with this is that the ECONNREFUSED takes 417 * priority over any other received datagram; that means that 418 * the Connection Refused shows up _before_ the response packet, 419 * regardless of the order they were sent out. (unless the 420 * response is read before the connection refused is returned) 421 */ 422 ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0); 423 424 if (ret < 0) { 425 FD_ZERO(&read_set); 426 FD_SET(intf->fd, &read_set); 427 428 FD_ZERO(&err_set); 429 FD_SET(intf->fd, &err_set); 430 431 tmout.tv_sec = intf->session->timeout; 432 tmout.tv_usec = 0; 433 434 ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); 435 if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set)) 436 return NULL; 437 438 ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0); 439 if (ret < 0) 440 return NULL; 441 } 442 443 if (ret == 0) 444 return NULL; 445 446 rsp.data[ret] = '\0'; 447 rsp.data_len = ret; 448 449 if (verbose >= 5) 450 printbuf(rsp.data, rsp.data_len, "<< received packet"); 451 452 return &rsp; 453 } 454 455 456 457 /* 458 * parse response RMCP "pong" packet 459 * 460 * return -1 if ping response not received 461 * returns 0 if IPMI is NOT supported 462 * returns 1 if IPMI is supported 463 * 464 * udp.source = 0x026f // RMCP_UDP_PORT 465 * udp.dest = ? // udp.source from rmcp-ping 466 * udp.len = ? 467 * udp.check = ? 468 * rmcp.ver = 0x06 // RMCP Version 1.0 469 * rmcp.__res = 0x00 // RESERVED 470 * rmcp.seq = 0xff // no RMCP ACK 471 * rmcp.class = 0x06 // RMCP_CLASS_ASF 472 * asf.iana = 0x000011be // ASF_RMCP_IANA 473 * asf.type = 0x40 // ASF_TYPE_PONG 474 * asf.tag = ? // asf.tag from rmcp-ping 475 * asf.__res = 0x00 // RESERVED 476 * asf.len = 0x10 // 16 bytes 477 * asf.data[3:0]= 0x000011be // IANA# = RMCP_ASF_IANA if no OEM 478 * asf.data[7:4]= 0x00000000 // OEM-defined (not for IPMI) 479 * asf.data[8] = 0x81 // supported entities 480 * // [7]=IPMI [6:4]=RES [3:0]=ASF_1.0 481 * asf.data[9] = 0x00 // supported interactions (reserved) 482 * asf.data[f:a]= 0x000000000000 483 */ 484 static int 485 ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp) 486 { 487 struct rmcp_pong { 488 struct rmcp_hdr rmcp; 489 struct asf_hdr asf; 490 uint32_t iana; 491 uint32_t oem; 492 uint8_t sup_entities; 493 uint8_t sup_interact; 494 uint8_t reserved[6]; 495 } * pong; 496 497 if (!rsp) 498 return -1; 499 500 pong = (struct rmcp_pong *)rsp->data; 501 502 if (verbose) 503 printf("Received IPMI/RMCP response packet: " 504 "IPMI%s Supported\n", 505 (pong->sup_entities & 0x80) ? "" : " NOT"); 506 507 if (verbose > 1) 508 printf(" ASF Version %s\n" 509 " RMCP Version %s\n" 510 " RMCP Sequence %d\n" 511 " IANA Enterprise %lu\n\n", 512 (pong->sup_entities & 0x01) ? "1.0" : "unknown", 513 (pong->rmcp.ver == 6) ? "1.0" : "unknown", 514 pong->rmcp.seq, 515 (unsigned long)ntohl(pong->iana)); 516 517 return (pong->sup_entities & 0x80) ? 1 : 0; 518 } 519 520 521 /* build and send RMCP presence ping packet 522 * 523 * RMCP ping 524 * 525 * udp.source = ? 526 * udp.dest = 0x026f // RMCP_UDP_PORT 527 * udp.len = ? 528 * udp.check = ? 529 * rmcp.ver = 0x06 // RMCP Version 1.0 530 * rmcp.__res = 0x00 // RESERVED 531 * rmcp.seq = 0xff // no RMCP ACK 532 * rmcp.class = 0x06 // RMCP_CLASS_ASF 533 * asf.iana = 0x000011be // ASF_RMCP_IANA 534 * asf.type = 0x80 // ASF_TYPE_PING 535 * asf.tag = ? // ASF sequence number 536 * asf.__res = 0x00 // RESERVED 537 * asf.len = 0x00 538 * 539 */ 540 int 541 ipmiv2_lan_ping(struct ipmi_intf * intf) 542 { 543 struct asf_hdr asf_ping = { 544 .iana = htonl(ASF_RMCP_IANA), 545 .type = ASF_TYPE_PING, 546 }; 547 struct rmcp_hdr rmcp_ping = { 548 .ver = RMCP_VERSION_1, 549 .class = RMCP_CLASS_ASF, 550 .seq = 0xff, 551 }; 552 uint8_t * data; 553 int len = sizeof(rmcp_ping) + sizeof(asf_ping); 554 int rv; 555 556 data = malloc(len); 557 if (data == NULL) { 558 lprintf(LOG_ERR, "ipmitool: malloc failure"); 559 return -1; 560 } 561 memset(data, 0, len); 562 memcpy(data, &rmcp_ping, sizeof(rmcp_ping)); 563 memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping)); 564 565 lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet"); 566 567 rv = ipmi_lan_send_packet(intf, data, len); 568 569 free(data); 570 data = NULL; 571 572 if (rv < 0) { 573 lprintf(LOG_ERR, "Unable to send IPMI presence ping packet"); 574 return -1; 575 } 576 577 if (ipmi_lan_poll_recv(intf) == 0) 578 return 0; 579 580 return 1; 581 } 582 583 584 /** 585 * 586 * ipmi_lan_poll_recv 587 * 588 * Receive whatever comes back. Ignore received packets that don't correspond 589 * to a request we've sent. 590 * 591 * Returns: the ipmi_rs packet describing the/a reponse we expect. 592 */ 593 static struct ipmi_rs * 594 ipmi_lan_poll_recv(struct ipmi_intf * intf) 595 { 596 struct rmcp_hdr rmcp_rsp; 597 struct ipmi_rs * rsp; 598 struct ipmi_session * session = intf->session; 599 int offset, rv; 600 uint16_t payload_size; 601 uint8_t ourAddress = intf->my_addr; 602 603 if (ourAddress == 0) { 604 ourAddress = IPMI_BMC_SLAVE_ADDR; 605 } 606 607 rsp = ipmi_lan_recv_packet(intf); 608 609 /* 610 * Not positive why we're looping. Do we sometimes get stuff we don't 611 * expect? 612 */ 613 while (rsp != NULL) { 614 615 /* parse response headers */ 616 memcpy(&rmcp_rsp, rsp->data, 4); 617 618 if (rmcp_rsp.class == RMCP_CLASS_ASF) { 619 /* might be ping response packet */ 620 rv = ipmi_handle_pong(intf, rsp); 621 return (rv <= 0) ? NULL : rsp; 622 } 623 624 if (rmcp_rsp.class != RMCP_CLASS_IPMI) { 625 lprintf(LOG_DEBUG, "Invalid RMCP class: %x", 626 rmcp_rsp.class); 627 rsp = ipmi_lan_recv_packet(intf); 628 continue; 629 } 630 631 632 /* 633 * The authtype / payload type determines what we are receiving 634 */ 635 offset = 4; 636 637 638 /*-------------------------------------------------------------------- 639 * 640 * The current packet could be one of several things: 641 * 642 * 1) An IPMI 1.5 packet (the response to our GET CHANNEL 643 * AUTHENTICATION CAPABILITIES request) 644 * 2) An RMCP+ message with an IPMI reponse payload 645 * 3) AN RMCP+ open session response 646 * 4) An RAKP-2 message (response to an RAKP 1 message) 647 * 5) An RAKP-4 message (response to an RAKP 3 message) 648 * 6) A Serial Over LAN packet 649 * 7) An Invalid packet (one that doesn't match a request) 650 * ------------------------------------------------------------------- 651 */ 652 653 read_session_data(rsp, &offset, intf->session); 654 655 if (lanplus_has_valid_auth_code(rsp, intf->session) == 0) 656 { 657 lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!"); 658 rsp = ipmi_lan_recv_packet(intf); 659 assert(0); 660 //continue; 661 } 662 663 if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && 664 (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 665 (rsp->session.bEncrypted)) 666 667 { 668 lanplus_decrypt_payload(session->v2_data.crypt_alg, 669 session->v2_data.k2, 670 rsp->data + offset, 671 rsp->session.msglen, 672 rsp->data + offset, 673 &payload_size); 674 } 675 else 676 payload_size = rsp->session.msglen; 677 678 679 /* 680 * Handle IPMI responses (case #1 and #2) -- all IPMI reponses 681 */ 682 if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) 683 { 684 struct ipmi_rq_entry * entry; 685 int payload_start = offset; 686 int extra_data_length; 687 read_ipmi_response(rsp, &offset); 688 689 lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header"); 690 lprintf(LOG_DEBUG+1, "<< Authtype : %s", 691 val2str(rsp->session.authtype, ipmi_authtype_session_vals)); 692 lprintf(LOG_DEBUG+1, "<< Payload type : %s", 693 val2str(rsp->session.payloadtype, plus_payload_types_vals)); 694 lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx", 695 (long)rsp->session.id); 696 lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx", 697 (long)rsp->session.seq); 698 lprintf(LOG_DEBUG+1, "<< IPMI Msg/Payload Length : %d", 699 rsp->session.msglen); 700 lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header"); 701 lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x", 702 rsp->payload.ipmi_response.rq_addr); 703 lprintf(LOG_DEBUG+1, "<< NetFn : %02x", 704 rsp->payload.ipmi_response.netfn); 705 lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x", 706 rsp->payload.ipmi_response.rq_lun); 707 lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x", 708 rsp->payload.ipmi_response.rs_addr); 709 lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x", 710 rsp->payload.ipmi_response.rq_seq); 711 lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x", 712 rsp->payload.ipmi_response.rs_lun); 713 lprintf(LOG_DEBUG+1, "<< Command : %02x", 714 rsp->payload.ipmi_response.cmd); 715 lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x", 716 rsp->ccode); 717 718 /* Are we expecting this packet? */ 719 entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq, 720 rsp->payload.ipmi_response.cmd); 721 722 if (entry != NULL) { 723 lprintf(LOG_DEBUG+2, "IPMI Request Match found"); 724 if ( intf->target_addr != intf->my_addr && 725 bridgePossible && 726 rsp->data_len && 727 rsp->payload.ipmi_response.cmd == 0x34 && 728 (rsp->payload.ipmi_response.netfn == 0x06 || 729 rsp->payload.ipmi_response.netfn == 0x07) && 730 rsp->payload.ipmi_response.rs_lun == 0 ) 731 { 732 /* Check completion code */ 733 if (rsp->data[offset-1] == 0) 734 { 735 lprintf(LOG_DEBUG, "Bridged command answer," 736 " waiting for next answer... "); 737 ipmi_req_remove_entry( 738 rsp->payload.ipmi_response.rq_seq, 739 rsp->payload.ipmi_response.cmd); 740 return ipmi_lan_poll_recv(intf); 741 } 742 else 743 { 744 lprintf(LOG_DEBUG, "WARNING: Bridged " 745 "cmd ccode = 0x%02x", 746 rsp->data[offset-1]); 747 } 748 749 if (rsp->data_len && 750 rsp->payload.ipmi_response.cmd == 0x34) { 751 memcpy(rsp->data, &rsp->data[offset], 752 (rsp->data_len-offset)); 753 if (verbose > 2) 754 printbuf( &rsp->data[offset], 755 (rsp->data_len-offset), 756 "bridge command response"); 757 } 758 } 759 760 ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, 761 rsp->payload.ipmi_response.cmd); 762 } else { 763 lprintf(LOG_INFO, "IPMI Request Match NOT FOUND"); 764 rsp = ipmi_lan_recv_packet(intf); 765 continue; 766 } 767 768 /* 769 * Good packet. Shift response data to start of array. 770 * rsp->data becomes the variable length IPMI response data 771 * rsp->data_len becomes the length of that data 772 */ 773 extra_data_length = payload_size - (offset - payload_start) - 1; 774 if (rsp != NULL && extra_data_length) 775 { 776 rsp->data_len = extra_data_length; 777 memmove(rsp->data, rsp->data + offset, extra_data_length); 778 } 779 else 780 rsp->data_len = 0; 781 782 break; 783 } 784 785 786 /* 787 * Open Response 788 */ 789 else if (rsp->session.payloadtype == 790 IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE) 791 { 792 if (session->v2_data.session_state != 793 LANPLUS_STATE_OPEN_SESSION_SENT) 794 { 795 lprintf(LOG_ERR, "Error: Received an Unexpected Open Session " 796 "Response"); 797 rsp = ipmi_lan_recv_packet(intf); 798 continue; 799 } 800 801 read_open_session_response(rsp, offset); 802 break; 803 } 804 805 806 /* 807 * RAKP 2 808 */ 809 else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2) 810 { 811 if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT) 812 { 813 lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message"); 814 rsp = ipmi_lan_recv_packet(intf); 815 continue; 816 } 817 818 read_rakp2_message(rsp, offset, session->v2_data.auth_alg); 819 break; 820 } 821 822 823 /* 824 * RAKP 4 825 */ 826 else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4) 827 { 828 if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT) 829 { 830 lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message"); 831 rsp = ipmi_lan_recv_packet(intf); 832 continue; 833 } 834 835 read_rakp4_message(rsp, offset, session->v2_data.auth_alg); 836 break; 837 } 838 839 840 /* 841 * SOL 842 */ 843 else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) 844 { 845 int payload_start = offset; 846 int extra_data_length; 847 848 if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) 849 { 850 lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet"); 851 rsp = ipmi_lan_recv_packet(intf); 852 continue; 853 } 854 855 read_sol_packet(rsp, &offset); 856 extra_data_length = payload_size - (offset - payload_start); 857 if (rsp && extra_data_length) 858 { 859 rsp->data_len = extra_data_length; 860 memmove(rsp->data, rsp->data + offset, extra_data_length); 861 } 862 else 863 rsp->data_len = 0; 864 865 break; 866 } 867 868 else 869 { 870 lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x", 871 rsp->session.payloadtype); 872 assert(0); 873 } 874 } 875 876 return rsp; 877 } 878 879 880 881 /* 882 * read_open_session_reponse 883 * 884 * Initialize the ipmi_rs from the IPMI 2.x open session response data. 885 * 886 * The offset should point to the first byte of the the Open Session Response 887 * payload when this function is called. 888 * 889 * param rsp [in/out] reading from the data and writing to the open_session_response 890 * section 891 * param offset [in] tells us where the Open Session Response payload starts 892 * 893 * returns 0 on success, 1 on error 894 */ 895 void 896 read_open_session_response(struct ipmi_rs * rsp, int offset) 897 { 898 memset(&rsp->payload.open_session_response, 0, 899 sizeof(rsp->payload.open_session_response)); 900 901 /* Message tag */ 902 rsp->payload.open_session_response.message_tag = rsp->data[offset]; 903 904 /* RAKP reponse code */ 905 rsp->payload.open_session_response.rakp_return_code = rsp->data[offset + 1]; 906 907 /* Maximum privilege level */ 908 rsp->payload.open_session_response.max_priv_level = rsp->data[offset + 2]; 909 910 /*** offset + 3 is reserved ***/ 911 912 /* Remote console session ID */ 913 memcpy(&(rsp->payload.open_session_response.console_id), 914 rsp->data + offset + 4, 915 4); 916 #if WORDS_BIGENDIAN 917 rsp->payload.open_session_response.console_id = 918 BSWAP_32(rsp->payload.open_session_response.console_id); 919 #endif 920 921 /* only tag, status, privlvl, and console id are returned if error */ 922 if (rsp->payload.open_session_response.rakp_return_code != 923 IPMI_RAKP_STATUS_NO_ERRORS) 924 return; 925 926 /* BMC session ID */ 927 memcpy(&(rsp->payload.open_session_response.bmc_id), 928 rsp->data + offset + 8, 929 4); 930 #if WORDS_BIGENDIAN 931 rsp->payload.open_session_response.bmc_id = 932 BSWAP_32(rsp->payload.open_session_response.bmc_id); 933 #endif 934 935 /* And of course, our negotiated algorithms */ 936 rsp->payload.open_session_response.auth_alg = rsp->data[offset + 16]; 937 rsp->payload.open_session_response.integrity_alg = rsp->data[offset + 24]; 938 rsp->payload.open_session_response.crypt_alg = rsp->data[offset + 32]; 939 } 940 941 942 943 /* 944 * read_rakp2_message 945 * 946 * Initialize the ipmi_rs from the IPMI 2.x RAKP 2 message 947 * 948 * The offset should point the first byte of the the RAKP 2 payload when this 949 * function is called. 950 * 951 * param rsp [in/out] reading from the data variable and writing to the rakp 2 952 * section 953 * param offset [in] tells us where hte rakp2 payload starts 954 * param auth_alg [in] describes the authentication algorithm was agreed upon in 955 * the open session request/response phase. We need to know that here so 956 * that we know how many bytes (if any) to read fromt the packet. 957 * 958 * returns 0 on success, 1 on error 959 */ 960 void 961 read_rakp2_message( 962 struct ipmi_rs * rsp, 963 int offset, 964 uint8_t auth_alg) 965 { 966 int i; 967 968 /* Message tag */ 969 rsp->payload.rakp2_message.message_tag = rsp->data[offset]; 970 971 /* RAKP reponse code */ 972 rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1]; 973 974 /* Console session ID */ 975 memcpy(&(rsp->payload.rakp2_message.console_id), 976 rsp->data + offset + 4, 977 4); 978 #if WORDS_BIGENDIAN 979 rsp->payload.rakp2_message.console_id = 980 BSWAP_32(rsp->payload.rakp2_message.console_id); 981 #endif 982 983 /* BMC random number */ 984 memcpy(&(rsp->payload.rakp2_message.bmc_rand), 985 rsp->data + offset + 8, 986 16); 987 #if WORDS_BIGENDIAN 988 lanplus_swap(rsp->payload.rakp2_message.bmc_rand, 16); 989 #endif 990 991 /* BMC GUID */ 992 memcpy(&(rsp->payload.rakp2_message.bmc_guid), 993 rsp->data + offset + 24, 994 16); 995 #if WORDS_BIGENDIAN 996 lanplus_swap(rsp->payload.rakp2_message.bmc_guid, 16); 997 #endif 998 999 /* Key exchange authentication code */ 1000 switch (auth_alg) 1001 { 1002 case IPMI_AUTH_RAKP_NONE: 1003 /* Nothing to do here */ 1004 break; 1005 1006 case IPMI_AUTH_RAKP_HMAC_SHA1: 1007 /* We need to copy 20 bytes */ 1008 for (i = 0; i < 20; ++i) 1009 rsp->payload.rakp2_message.key_exchange_auth_code[i] = 1010 rsp->data[offset + 40 + i]; 1011 break; 1012 1013 case IPMI_AUTH_RAKP_HMAC_MD5: 1014 lprintf(LOG_ERR, "read_rakp2_message: no support for " 1015 "IPMI_AUTH_RAKP_HMAC_MD5"); 1016 assert(0); 1017 break; 1018 } 1019 } 1020 1021 1022 1023 /* 1024 * read_rakp4_message 1025 * 1026 * Initialize the ipmi_rs from the IPMI 2.x RAKP 4 message 1027 * 1028 * The offset should point the first byte of the the RAKP 4 payload when this 1029 * function is called. 1030 * 1031 * param rsp [in/out] reading from the data variable and writing to the rakp 1032 * 4 section 1033 * param offset [in] tells us where hte rakp4 payload starts 1034 * param integrity_alg [in] describes the authentication algorithm was 1035 * agreed upon in the open session request/response phase. We need 1036 * to know that here so that we know how many bytes (if any) to read 1037 * from the packet. 1038 * 1039 * returns 0 on success, 1 on error 1040 */ 1041 void 1042 read_rakp4_message( 1043 struct ipmi_rs * rsp, 1044 int offset, 1045 uint8_t auth_alg) 1046 { 1047 int i; 1048 1049 /* Message tag */ 1050 rsp->payload.rakp4_message.message_tag = rsp->data[offset]; 1051 1052 /* RAKP reponse code */ 1053 rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1]; 1054 1055 /* Console session ID */ 1056 memcpy(&(rsp->payload.rakp4_message.console_id), 1057 rsp->data + offset + 4, 1058 4); 1059 #if WORDS_BIGENDIAN 1060 rsp->payload.rakp4_message.console_id = 1061 BSWAP_32(rsp->payload.rakp4_message.console_id); 1062 #endif 1063 1064 1065 /* Integrity check value */ 1066 switch (auth_alg) 1067 { 1068 case IPMI_AUTH_RAKP_NONE: 1069 /* Nothing to do here */ 1070 break; 1071 1072 case IPMI_AUTH_RAKP_HMAC_SHA1: 1073 /* We need to copy 12 bytes */ 1074 for (i = 0; i < 12; ++i) 1075 rsp->payload.rakp4_message.integrity_check_value[i] = 1076 rsp->data[offset + 8 + i]; 1077 break; 1078 1079 case IPMI_AUTH_RAKP_HMAC_MD5: 1080 lprintf(LOG_ERR, "read_rakp4_message: no support " 1081 "for authentication algorithm 0x%x", auth_alg); 1082 assert(0); 1083 break; 1084 } 1085 } 1086 1087 1088 1089 1090 /* 1091 * read_session_data 1092 * 1093 * Initialize the ipmi_rsp from the session data in the packet 1094 * 1095 * The offset should point the first byte of the the IPMI session when this 1096 * function is called. 1097 * 1098 * param rsp [in/out] we read from the data buffer and populate the session 1099 * specific fields. 1100 * param offset [in/out] should point to the beginning of the session when 1101 * this function is called. The offset will be adjusted to 1102 * point to the end of the session when this function exits. 1103 * param session holds our session state 1104 */ 1105 void 1106 read_session_data( 1107 struct ipmi_rs * rsp, 1108 int * offset, 1109 struct ipmi_session * s) 1110 { 1111 /* We expect to read different stuff depending on the authtype */ 1112 rsp->session.authtype = rsp->data[*offset]; 1113 1114 if (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) 1115 read_session_data_v2x(rsp, offset, s); 1116 else 1117 read_session_data_v15(rsp, offset, s); 1118 } 1119 1120 1121 1122 /* 1123 * read_session_data_v2x 1124 * 1125 * Initialize the ipmi_rsp from the v2.x session header of the packet. 1126 * 1127 * The offset should point to the first byte of the the IPMI session when this 1128 * function is called. When this function exits, offset will point to the 1129 * start of payload. 1130 * 1131 * Should decrypt and perform integrity checking here? 1132 * 1133 * param rsp [in/out] we read from the data buffer and populate the session 1134 * specific fields. 1135 * param offset [in/out] should point to the beginning of the session when this 1136 * function is called. The offset will be adjusted to point to 1137 * the end of the session when this function exits. 1138 * param s holds our session state 1139 */ 1140 void 1141 read_session_data_v2x( 1142 struct ipmi_rs * rsp, 1143 int * offset, 1144 struct ipmi_session * s) 1145 { 1146 rsp->session.authtype = rsp->data[(*offset)++]; 1147 1148 rsp->session.bEncrypted = (rsp->data[*offset] & 0x80 ? 1 : 0); 1149 rsp->session.bAuthenticated = (rsp->data[*offset] & 0x40 ? 1 : 0); 1150 1151 1152 /* Payload type */ 1153 rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F; 1154 1155 /* Session ID */ 1156 memcpy(&rsp->session.id, rsp->data + *offset, 4); 1157 *offset += 4; 1158 #if WORDS_BIGENDIAN 1159 rsp->session.id = BSWAP_32(rsp->session.id); 1160 #endif 1161 1162 1163 /* 1164 * Verify that the session ID is what we think it should be 1165 */ 1166 if ((s->v2_data.session_state == LANPLUS_STATE_ACTIVE) && 1167 (rsp->session.id != s->v2_data.console_id)) 1168 { 1169 lprintf(LOG_ERR, "packet session id 0x%x does not " 1170 "match active session 0x%0x", 1171 rsp->session.id, s->v2_data.console_id); 1172 assert(0); 1173 } 1174 1175 1176 /* Ignored, so far */ 1177 memcpy(&rsp->session.seq, rsp->data + *offset, 4); 1178 *offset += 4; 1179 #if WORDS_BIGENDIAN 1180 rsp->session.seq = BSWAP_32(rsp->session.seq); 1181 #endif 1182 1183 memcpy(&rsp->session.msglen, rsp->data + *offset, 2); 1184 *offset += 2; 1185 #if WORDS_BIGENDIAN 1186 rsp->session.msglen = BSWAP_16(rsp->session.msglen); 1187 #endif 1188 } 1189 1190 1191 1192 /* 1193 * read_session_data_v15 1194 * 1195 * Initialize the ipmi_rsp from the session header of the packet. 1196 * 1197 * The offset should point the first byte of the the IPMI session when this 1198 * function is called. When this function exits, the offset will point to 1199 * the start of the IPMI message. 1200 * 1201 * param rsp [in/out] we read from the data buffer and populate the session 1202 * specific fields. 1203 * param offset [in/out] should point to the beginning of the session when this 1204 * function is called. The offset will be adjusted to point to the 1205 * end of the session when this function exits. 1206 * param s holds our session state 1207 */ 1208 void read_session_data_v15( 1209 struct ipmi_rs * rsp, 1210 int * offset, 1211 struct ipmi_session * s) 1212 { 1213 /* All v15 messages are IPMI messages */ 1214 rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI; 1215 1216 rsp->session.authtype = rsp->data[(*offset)++]; 1217 1218 /* All v15 messages that we will receive are unencrypted/unauthenticated */ 1219 rsp->session.bEncrypted = 0; 1220 rsp->session.bAuthenticated = 0; 1221 1222 /* skip the session id and sequence number fields */ 1223 *offset += 8; 1224 1225 /* This is the size of the whole payload */ 1226 rsp->session.msglen = rsp->data[(*offset)++]; 1227 } 1228 1229 1230 1231 /* 1232 * read_ipmi_response 1233 * 1234 * Initialize the ipmi_rs from with the IPMI response specific data 1235 * 1236 * The offset should point the first byte of the the IPMI payload when this 1237 * function is called. 1238 * 1239 * param rsp [in/out] we read from the data buffer and populate the IPMI 1240 * specific fields. 1241 * param offset [in/out] should point to the beginning of the IPMI payload when 1242 * this function is called. 1243 */ 1244 void read_ipmi_response(struct ipmi_rs * rsp, int * offset) 1245 { 1246 /* 1247 * The data here should be decrypted by now. 1248 */ 1249 rsp->payload.ipmi_response.rq_addr = rsp->data[(*offset)++]; 1250 rsp->payload.ipmi_response.netfn = rsp->data[*offset] >> 2; 1251 rsp->payload.ipmi_response.rq_lun = rsp->data[(*offset)++] & 0x3; 1252 (*offset)++; /* checksum */ 1253 rsp->payload.ipmi_response.rs_addr = rsp->data[(*offset)++]; 1254 rsp->payload.ipmi_response.rq_seq = rsp->data[*offset] >> 2; 1255 rsp->payload.ipmi_response.rs_lun = rsp->data[(*offset)++] & 0x3; 1256 rsp->payload.ipmi_response.cmd = rsp->data[(*offset)++]; 1257 rsp->ccode = rsp->data[(*offset)++]; 1258 1259 } 1260 1261 1262 1263 /* 1264 * read_sol_packet 1265 * 1266 * Initialize the ipmi_rs with the SOL response data 1267 * 1268 * The offset should point the first byte of the the SOL payload when this 1269 * function is called. 1270 * 1271 * param rsp [in/out] we read from the data buffer and populate the 1272 * SOL specific fields. 1273 * param offset [in/out] should point to the beginning of the SOL payload 1274 * when this function is called. 1275 */ 1276 void read_sol_packet(struct ipmi_rs * rsp, int * offset) 1277 { 1278 1279 /* 1280 * The data here should be decrypted by now. 1281 */ 1282 rsp->payload.sol_packet.packet_sequence_number = 1283 rsp->data[(*offset)++] & 0x0F; 1284 1285 rsp->payload.sol_packet.acked_packet_number = 1286 rsp->data[(*offset)++] & 0x0F; 1287 1288 rsp->payload.sol_packet.accepted_character_count = 1289 rsp->data[(*offset)++]; 1290 1291 rsp->payload.sol_packet.is_nack = 1292 rsp->data[*offset] & 0x40; 1293 1294 rsp->payload.sol_packet.transfer_unavailable = 1295 rsp->data[*offset] & 0x20; 1296 1297 rsp->payload.sol_packet.sol_inactive = 1298 rsp->data[*offset] & 0x10; 1299 1300 rsp->payload.sol_packet.transmit_overrun = 1301 rsp->data[*offset] & 0x08; 1302 1303 rsp->payload.sol_packet.break_detected = 1304 rsp->data[(*offset)++] & 0x04; 1305 1306 lprintf(LOG_DEBUG, "<<<<<<<<<< RECV FROM BMC <<<<<<<<<<<"); 1307 lprintf(LOG_DEBUG, "< SOL sequence number : 0x%02x", 1308 rsp->payload.sol_packet.packet_sequence_number); 1309 lprintf(LOG_DEBUG, "< SOL acked packet : 0x%02x", 1310 rsp->payload.sol_packet.acked_packet_number); 1311 lprintf(LOG_DEBUG, "< SOL accepted char count : 0x%02x", 1312 rsp->payload.sol_packet.accepted_character_count); 1313 lprintf(LOG_DEBUG, "< SOL is nack : %s", 1314 rsp->payload.sol_packet.is_nack? "true" : "false"); 1315 lprintf(LOG_DEBUG, "< SOL xfer unavailable : %s", 1316 rsp->payload.sol_packet.transfer_unavailable? "true" : "false"); 1317 lprintf(LOG_DEBUG, "< SOL inactive : %s", 1318 rsp->payload.sol_packet.sol_inactive? "true" : "false"); 1319 lprintf(LOG_DEBUG, "< SOL transmit overrun : %s", 1320 rsp->payload.sol_packet.transmit_overrun? "true" : "false"); 1321 lprintf(LOG_DEBUG, "< SOL break detected : %s", 1322 rsp->payload.sol_packet.break_detected? "true" : "false"); 1323 lprintf(LOG_DEBUG, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); 1324 1325 if (verbose >= 5) 1326 printbuf(rsp->data + *offset - 4, 4, "SOL MSG FROM BMC"); 1327 } 1328 1329 1330 1331 /* 1332 * getIpmiPayloadWireRep 1333 * 1334 * param out [out] will contain our wire representation 1335 * param req [in] is the IPMI request to be written 1336 * param crypt_alg [in] specifies the encryption to use 1337 * param rq_seq [in] is the IPMI command sequence number. 1338 */ 1339 void getIpmiPayloadWireRep( 1340 struct ipmi_intf * intf, /* in out */ 1341 struct ipmi_v2_payload * payload, /* in */ 1342 uint8_t * msg, 1343 struct ipmi_rq * req, 1344 uint8_t rq_seq, 1345 uint8_t curr_seq) 1346 { 1347 int cs, tmp, len; 1348 int cs2 = 0; 1349 int cs3 = 0; 1350 uint8_t ourAddress = intf->my_addr; 1351 uint8_t bridgedRequest = 0; 1352 1353 if (ourAddress == 0) 1354 ourAddress = IPMI_BMC_SLAVE_ADDR; 1355 1356 len = 0; 1357 1358 /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */ 1359 if ((intf->target_addr == ourAddress) || (!bridgePossible)) { 1360 cs = len; 1361 } else { 1362 bridgedRequest = 1; 1363 1364 if(intf->transit_addr != ourAddress && intf->transit_addr != 0) 1365 { 1366 bridgedRequest++; 1367 } 1368 /* bridged request: encapsulate w/in Send Message */ 1369 cs = len; 1370 msg[len++] = IPMI_BMC_SLAVE_ADDR; 1371 msg[len++] = IPMI_NETFN_APP << 2; 1372 tmp = len - cs; 1373 msg[len++] = ipmi_csum(msg+cs, tmp); 1374 cs2 = len; 1375 msg[len++] = IPMI_REMOTE_SWID; 1376 msg[len++] = curr_seq << 2; 1377 1378 1379 msg[len++] = 0x34; /* Send Message rqst */ 1380 if(bridgedRequest == 2) 1381 msg[len++] = (0x40|intf->transit_channel); /* Track request*/ 1382 else 1383 msg[len++] = (0x40|intf->target_channel); /* Track request*/ 1384 1385 payload->payload_length += 7; 1386 cs = len; 1387 1388 if(bridgedRequest == 2) 1389 { 1390 /* bridged request: encapsulate w/in Send Message */ 1391 cs = len; 1392 msg[len++] = intf->transit_addr; 1393 msg[len++] = IPMI_NETFN_APP << 2; 1394 tmp = len - cs; 1395 msg[len++] = ipmi_csum(msg+cs, tmp); 1396 cs3 = len; 1397 msg[len++] = intf->my_addr; 1398 msg[len++] = curr_seq << 2; 1399 msg[len++] = 0x34; /* Send Message rqst */ 1400 #if 0 /* From lan.c example */ 1401 entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */ 1402 entry->req.msg.cmd = 0x34; /* (fixup request entry) */ 1403 #endif 1404 msg[len++] = (0x40|intf->target_channel); /* Track request*/ 1405 1406 payload->payload_length += 7; 1407 1408 cs = len; 1409 } 1410 } 1411 1412 lprintf(LOG_DEBUG,"%s RqAddr %#x transit %#x:%#x target %#x:%#x " 1413 "bridgePossible %d", 1414 bridgedRequest ? "Bridging" : "Local", 1415 intf->my_addr, intf->transit_addr, intf->transit_channel, 1416 intf->target_addr, intf->target_channel, 1417 bridgePossible); 1418 1419 /* rsAddr */ 1420 msg[len++] = intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */ 1421 1422 /* net Fn */ 1423 msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3); 1424 tmp = len - cs; 1425 1426 /* checkSum */ 1427 msg[len++] = ipmi_csum(msg+cs, tmp); 1428 cs = len; 1429 1430 /* rqAddr */ 1431 if (!bridgedRequest) 1432 msg[len++] = IPMI_REMOTE_SWID; 1433 else /* Bridged message */ 1434 msg[len++] = intf->my_addr; 1435 1436 /* rqSeq / rqLUN */ 1437 msg[len++] = rq_seq << 2; 1438 1439 /* cmd */ 1440 msg[len++] = req->msg.cmd; 1441 1442 /* message data */ 1443 if (req->msg.data_len) { 1444 memcpy(msg + len, req->msg.data, req->msg.data_len); 1445 len += req->msg.data_len; 1446 } 1447 1448 /* second checksum */ 1449 tmp = len - cs; 1450 msg[len++] = ipmi_csum(msg+cs, tmp); 1451 1452 /* Dual bridged request: 2nd checksum */ 1453 if (bridgedRequest == 2) { 1454 tmp = len - cs3; 1455 msg[len++] = ipmi_csum(msg+cs3, tmp); 1456 payload->payload_length += 1; 1457 } 1458 1459 /* bridged request: 2nd checksum */ 1460 if (bridgedRequest) { 1461 tmp = len - cs2; 1462 msg[len++] = ipmi_csum(msg+cs2, tmp); 1463 payload->payload_length += 1; 1464 } 1465 } 1466 1467 1468 1469 /* 1470 * getSolPayloadWireRep 1471 * 1472 * param msg [out] will contain our wire representation 1473 * param payload [in] holds the v2 payload with our SOL data 1474 */ 1475 void getSolPayloadWireRep( 1476 struct ipmi_intf * intf, /* in out */ 1477 uint8_t * msg, /* output */ 1478 struct ipmi_v2_payload * payload) /* input */ 1479 { 1480 int i = 0; 1481 1482 lprintf(LOG_DEBUG, ">>>>>>>>>> SENDING TO BMC >>>>>>>>>>"); 1483 lprintf(LOG_DEBUG, "> SOL sequence number : 0x%02x", 1484 payload->payload.sol_packet.packet_sequence_number); 1485 lprintf(LOG_DEBUG, "> SOL acked packet : 0x%02x", 1486 payload->payload.sol_packet.acked_packet_number); 1487 lprintf(LOG_DEBUG, "> SOL accepted char count : 0x%02x", 1488 payload->payload.sol_packet.accepted_character_count); 1489 lprintf(LOG_DEBUG, "> SOL is nack : %s", 1490 payload->payload.sol_packet.is_nack ? "true" : "false"); 1491 lprintf(LOG_DEBUG, "> SOL assert ring wor : %s", 1492 payload->payload.sol_packet.assert_ring_wor ? "true" : "false"); 1493 lprintf(LOG_DEBUG, "> SOL generate break : %s", 1494 payload->payload.sol_packet.generate_break ? "true" : "false"); 1495 lprintf(LOG_DEBUG, "> SOL deassert cts : %s", 1496 payload->payload.sol_packet.deassert_cts ? "true" : "false"); 1497 lprintf(LOG_DEBUG, "> SOL deassert dcd dsr : %s", 1498 payload->payload.sol_packet.deassert_dcd_dsr ? "true" : "false"); 1499 lprintf(LOG_DEBUG, "> SOL flush inbound : %s", 1500 payload->payload.sol_packet.flush_inbound ? "true" : "false"); 1501 lprintf(LOG_DEBUG, "> SOL flush outbound : %s", 1502 payload->payload.sol_packet.flush_outbound ? "true" : "false"); 1503 1504 msg[i++] = payload->payload.sol_packet.packet_sequence_number; 1505 msg[i++] = payload->payload.sol_packet.acked_packet_number; 1506 msg[i++] = payload->payload.sol_packet.accepted_character_count; 1507 1508 msg[i] = payload->payload.sol_packet.is_nack ? 0x40 : 0; 1509 msg[i] |= payload->payload.sol_packet.assert_ring_wor ? 0x20 : 0; 1510 msg[i] |= payload->payload.sol_packet.generate_break ? 0x10 : 0; 1511 msg[i] |= payload->payload.sol_packet.deassert_cts ? 0x08 : 0; 1512 msg[i] |= payload->payload.sol_packet.deassert_dcd_dsr ? 0x04 : 0; 1513 msg[i] |= payload->payload.sol_packet.flush_inbound ? 0x02 : 0; 1514 msg[i++] |= payload->payload.sol_packet.flush_outbound ? 0x01 : 0; 1515 1516 /* We may have data to add */ 1517 memcpy(msg + i, 1518 payload->payload.sol_packet.data, 1519 payload->payload.sol_packet.character_count); 1520 1521 lprintf(LOG_DEBUG, "> SOL character count : %d", 1522 payload->payload.sol_packet.character_count); 1523 lprintf(LOG_DEBUG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); 1524 1525 if (verbose >= 5 && payload->payload.sol_packet.character_count) 1526 printbuf(payload->payload.sol_packet.data, payload->payload.sol_packet.character_count, "SOL SEND DATA"); 1527 1528 /* 1529 * At this point, the payload length becomes the whole payload 1530 * length, including the 4 bytes at the beginning of the SOL 1531 * packet 1532 */ 1533 payload->payload_length = payload->payload.sol_packet.character_count + 4; 1534 } 1535 1536 1537 1538 /* 1539 * ipmi_lanplus_build_v2x_msg 1540 * 1541 * Encapsulates the payload data to create the IPMI v2.0 / RMCP+ packet. 1542 * 1543 * 1544 * IPMI v2.0 LAN Request Message Format 1545 * +----------------------+ 1546 * | rmcp.ver | 4 bytes 1547 * | rmcp.__reserved | 1548 * | rmcp.seq | 1549 * | rmcp.class | 1550 * +----------------------+ 1551 * | session.authtype | 10 bytes 1552 * | session.payloadtype | 1553 * | session.id | 1554 * | session.seq | 1555 * +----------------------+ 1556 * | message length | 2 bytes 1557 * +----------------------+ 1558 * | Confidentiality Hdr | var (possibly absent) 1559 * +----------------------+ 1560 * | Paylod | var Payload 1561 * +----------------------+ 1562 * | Confidentiality Trlr | var (possibly absent) 1563 * +----------------------+ 1564 * | Integrity pad | var (possibly absent) 1565 * +----------------------+ 1566 * | Pad length | 1 byte (WTF?) 1567 * +----------------------+ 1568 * | Next Header | 1 byte (WTF?) 1569 * +----------------------+ 1570 * | Authcode | var (possibly absent) 1571 * +----------------------+ 1572 */ 1573 void 1574 ipmi_lanplus_build_v2x_msg( 1575 struct ipmi_intf * intf, /* in */ 1576 struct ipmi_v2_payload * payload, /* in */ 1577 int * msg_len, /* out */ 1578 uint8_t ** msg_data, /* out */ 1579 uint8_t curr_seq) 1580 { 1581 uint32_t session_trailer_length = 0; 1582 struct ipmi_session * session = intf->session; 1583 struct rmcp_hdr rmcp = { 1584 .ver = RMCP_VERSION_1, 1585 .class = RMCP_CLASS_IPMI, 1586 .seq = 0xff, 1587 }; 1588 1589 /* msg will hold the entire message to be sent */ 1590 uint8_t * msg; 1591 int len = 0; 1592 1593 1594 len = 1595 sizeof(rmcp) + // RMCP Header (4) 1596 10 + // IPMI Session Header 1597 2 + // Message length 1598 payload->payload_length + // The actual payload 1599 IPMI_MAX_INTEGRITY_PAD_SIZE + // Integrity Pad 1600 1 + // Pad Length 1601 1 + // Next Header 1602 IPMI_MAX_AUTH_CODE_SIZE; // Authcode 1603 1604 1605 msg = malloc(len); 1606 if (msg == NULL) { 1607 lprintf(LOG_ERR, "ipmitool: malloc failure"); 1608 return; 1609 } 1610 memset(msg, 0, len); 1611 1612 /* 1613 *------------------------------------------ 1614 * RMCP HEADER 1615 *------------------------------------------ 1616 */ 1617 memcpy(msg, &rmcp, sizeof(rmcp)); 1618 len = sizeof(rmcp); 1619 1620 1621 /* 1622 *------------------------------------------ 1623 * IPMI SESSION HEADER 1624 *------------------------------------------ 1625 */ 1626 /* ipmi session Auth Type / Format is always 0x06 for IPMI v2 */ 1627 msg[IPMI_LANPLUS_OFFSET_AUTHTYPE] = 0x06; 1628 1629 /* Payload Type -- also specifies whether were authenticated/encyrpted */ 1630 msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] = payload->payload_type; 1631 1632 if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE) 1633 { 1634 msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |= 1635 ((session->v2_data.crypt_alg != IPMI_CRYPT_NONE )? 0x80 : 0x00); 1636 msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |= 1637 ((session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE)? 0x40 : 0x00); 1638 } 1639 1640 if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE) 1641 { 1642 /* Session ID -- making it LSB */ 1643 msg[IPMI_LANPLUS_OFFSET_SESSION_ID ] = session->v2_data.bmc_id & 0xff; 1644 msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 1] = (session->v2_data.bmc_id >> 8) & 0xff; 1645 msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 2] = (session->v2_data.bmc_id >> 16) & 0xff; 1646 msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 3] = (session->v2_data.bmc_id >> 24) & 0xff; 1647 1648 /* Sequence Number -- making it LSB */ 1649 msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM ] = session->out_seq & 0xff; 1650 msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 1] = (session->out_seq >> 8) & 0xff; 1651 msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 2] = (session->out_seq >> 16) & 0xff; 1652 msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 3] = (session->out_seq >> 24) & 0xff; 1653 } 1654 1655 /* 1656 * Payload Length is set below (we don't know how big the payload is until after 1657 * encryption). 1658 */ 1659 1660 /* 1661 * Payload 1662 * 1663 * At this point we are ready to slam the payload in. 1664 * This includes: 1665 * 1) The confidentiality header 1666 * 2) The payload proper (possibly encrypted) 1667 * 3) The confidentiality trailer 1668 * 1669 */ 1670 switch (payload->payload_type) 1671 { 1672 case IPMI_PAYLOAD_TYPE_IPMI: 1673 getIpmiPayloadWireRep(intf, 1674 payload, /* in */ 1675 msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1676 payload->payload.ipmi_request.request, 1677 payload->payload.ipmi_request.rq_seq, 1678 curr_seq); 1679 break; 1680 1681 case IPMI_PAYLOAD_TYPE_SOL: 1682 getSolPayloadWireRep(intf, 1683 msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1684 payload); 1685 1686 if (verbose >= 5) 1687 printbuf(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 4, "SOL MSG TO BMC"); 1688 1689 len += payload->payload_length; 1690 1691 break; 1692 1693 case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: 1694 /* never encrypted, so our job is easy */ 1695 memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1696 payload->payload.open_session_request.request, 1697 payload->payload_length); 1698 len += payload->payload_length; 1699 break; 1700 1701 case IPMI_PAYLOAD_TYPE_RAKP_1: 1702 /* never encrypted, so our job is easy */ 1703 memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1704 payload->payload.rakp_1_message.message, 1705 payload->payload_length); 1706 len += payload->payload_length; 1707 break; 1708 1709 case IPMI_PAYLOAD_TYPE_RAKP_3: 1710 /* never encrypted, so our job is easy */ 1711 memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1712 payload->payload.rakp_3_message.message, 1713 payload->payload_length); 1714 len += payload->payload_length; 1715 break; 1716 1717 default: 1718 lprintf(LOG_ERR, "unsupported payload type 0x%x", 1719 payload->payload_type); 1720 free(msg); 1721 msg = NULL; 1722 assert(0); 1723 break; 1724 } 1725 1726 1727 /* 1728 *------------------------------------------ 1729 * ENCRYPT THE PAYLOAD IF NECESSARY 1730 *------------------------------------------ 1731 */ 1732 if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE) 1733 { 1734 /* Payload len is adjusted as necessary by lanplus_encrypt_payload */ 1735 lanplus_encrypt_payload(session->v2_data.crypt_alg, /* input */ 1736 session->v2_data.k2, /* input */ 1737 msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* input */ 1738 payload->payload_length, /* input */ 1739 msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* output */ 1740 &(payload->payload_length)); /* output */ 1741 1742 } 1743 1744 /* Now we know the payload length */ 1745 msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE ] = 1746 payload->payload_length & 0xff; 1747 msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE + 1] = 1748 (payload->payload_length >> 8) & 0xff; 1749 1750 1751 /* 1752 *------------------------------------------ 1753 * SESSION TRAILER 1754 *------------------------------------------ 1755 */ 1756 if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && 1757 (session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE)) 1758 { 1759 uint32_t i, hmac_length, integrity_pad_size = 0, hmac_input_size; 1760 uint8_t * hmac_output; 1761 uint32_t start_of_session_trailer = 1762 IPMI_LANPLUS_OFFSET_PAYLOAD + 1763 payload->payload_length; 1764 1765 1766 /* 1767 * Determine the required integrity pad length. We have to make the 1768 * data range covered by the authcode a multiple of 4. 1769 */ 1770 uint32_t length_before_authcode; 1771 1772 if (ipmi_oem_active(intf, "icts")) { 1773 length_before_authcode = 1774 12 + /* the stuff before the payload */ 1775 payload->payload_length; 1776 } else { 1777 length_before_authcode = 1778 12 + /* the stuff before the payload */ 1779 payload->payload_length + 1780 1 + /* pad length field */ 1781 1; /* next header field */ 1782 } 1783 1784 if (length_before_authcode % 4) 1785 integrity_pad_size = 4 - (length_before_authcode % 4); 1786 1787 for (i = 0; i < integrity_pad_size; ++i) 1788 msg[start_of_session_trailer + i] = 0xFF; 1789 1790 /* Pad length */ 1791 msg[start_of_session_trailer + integrity_pad_size] = integrity_pad_size; 1792 1793 /* Next Header */ 1794 msg[start_of_session_trailer + integrity_pad_size + 1] = 1795 0x07; /* Hardcoded per the spec, table 13-8 */ 1796 1797 hmac_input_size = 1798 12 + 1799 payload->payload_length + 1800 integrity_pad_size + 1801 2; 1802 1803 hmac_output = 1804 msg + 1805 IPMI_LANPLUS_OFFSET_PAYLOAD + 1806 payload->payload_length + 1807 integrity_pad_size + 1808 2; 1809 1810 if (verbose > 2) 1811 printbuf(msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, hmac_input_size, "authcode input"); 1812 1813 1814 /* Auth Code */ 1815 lanplus_HMAC(session->v2_data.integrity_alg, 1816 session->v2_data.k1, /* key */ 1817 20, /* key length */ 1818 msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, /* hmac input */ 1819 hmac_input_size, 1820 hmac_output, 1821 &hmac_length); 1822 1823 assert(hmac_length == 20); 1824 1825 if (verbose > 2) 1826 printbuf(hmac_output, 12, "authcode output"); 1827 1828 /* Set session_trailer_length appropriately */ 1829 session_trailer_length = 1830 integrity_pad_size + 1831 2 + /* pad length + next header */ 1832 12; /* Size of the authcode (we only use the first 12 bytes) */ 1833 } 1834 1835 1836 ++(session->out_seq); 1837 if (!session->out_seq) 1838 ++(session->out_seq); 1839 1840 *msg_len = 1841 IPMI_LANPLUS_OFFSET_PAYLOAD + 1842 payload->payload_length + 1843 session_trailer_length; 1844 *msg_data = msg; 1845 } 1846 1847 1848 1849 /* 1850 * ipmi_lanplus_build_v2x_ipmi_cmd 1851 * 1852 * Wraps ipmi_lanplus_build_v2x_msg and returns a new entry object for the 1853 * command 1854 * 1855 */ 1856 static struct ipmi_rq_entry * 1857 ipmi_lanplus_build_v2x_ipmi_cmd( 1858 struct ipmi_intf * intf, 1859 struct ipmi_rq * req, 1860 int isRetry) 1861 { 1862 struct ipmi_v2_payload v2_payload; 1863 struct ipmi_rq_entry * entry; 1864 1865 /* 1866 * We have a problem. we need to know the sequence number here, 1867 * because we use it in our stored entry. But we also need to 1868 * know the sequence number when we generate our IPMI 1869 * representation far below. 1870 */ 1871 static uint8_t curr_seq = 0; 1872 1873 if( isRetry == 0 ) 1874 curr_seq += 1; 1875 1876 if (curr_seq >= 64) 1877 curr_seq = 0; 1878 1879 1880 /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */ 1881 if ((intf->target_addr == intf->my_addr) || (!bridgePossible)) 1882 { 1883 entry = ipmi_req_add_entry(intf, req, curr_seq); 1884 } 1885 else /* it's a bridge command */ 1886 { 1887 unsigned char backup_cmd; 1888 1889 /* Add entry for cmd */ 1890 entry = ipmi_req_add_entry(intf, req, curr_seq); 1891 1892 if(entry) 1893 { 1894 /* Add entry for bridge cmd */ 1895 backup_cmd = req->msg.cmd; 1896 req->msg.cmd = 0x34; 1897 entry = ipmi_req_add_entry(intf, req, curr_seq); 1898 req->msg.cmd = backup_cmd; 1899 } 1900 } 1901 1902 if (entry == NULL) 1903 return NULL; 1904 1905 // Build our payload 1906 v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI; 1907 v2_payload.payload_length = req->msg.data_len + 7; 1908 v2_payload.payload.ipmi_request.request = req; 1909 v2_payload.payload.ipmi_request.rq_seq = curr_seq; 1910 1911 ipmi_lanplus_build_v2x_msg(intf, // in 1912 &v2_payload, // in 1913 &(entry->msg_len), // out 1914 &(entry->msg_data), // out 1915 curr_seq); // in 1916 1917 return entry; 1918 } 1919 1920 1921 1922 1923 1924 /* 1925 * IPMI LAN Request Message Format 1926 * +--------------------+ 1927 * | rmcp.ver | 4 bytes 1928 * | rmcp.__reserved | 1929 * | rmcp.seq | 1930 * | rmcp.class | 1931 * +--------------------+ 1932 * | session.authtype | 9 bytes 1933 * | session.seq | 1934 * | session.id | 1935 * +--------------------+ 1936 * | [session.authcode] | 16 bytes (AUTHTYPE != none) 1937 * +--------------------+ 1938 * | message length | 1 byte 1939 * +--------------------+ 1940 * | message.rs_addr | 6 bytes 1941 * | message.netfn_lun | 1942 * | message.checksum | 1943 * | message.rq_addr | 1944 * | message.rq_seq | 1945 * | message.cmd | 1946 * +--------------------+ 1947 * | [request data] | data_len bytes 1948 * +--------------------+ 1949 * | checksum | 1 byte 1950 * +--------------------+ 1951 */ 1952 static struct ipmi_rq_entry * 1953 ipmi_lanplus_build_v15_ipmi_cmd( 1954 struct ipmi_intf * intf, 1955 struct ipmi_rq * req) 1956 { 1957 struct rmcp_hdr rmcp = { 1958 .ver = RMCP_VERSION_1, 1959 .class = RMCP_CLASS_IPMI, 1960 .seq = 0xff, 1961 }; 1962 uint8_t * msg; 1963 int cs, mp, len = 0, tmp; 1964 struct ipmi_session * session = intf->session; 1965 struct ipmi_rq_entry * entry; 1966 1967 entry = ipmi_req_add_entry(intf, req, 0); 1968 if (entry == NULL) 1969 return NULL; 1970 1971 len = req->msg.data_len + 21; 1972 1973 msg = malloc(len); 1974 if (msg == NULL) { 1975 lprintf(LOG_ERR, "ipmitool: malloc failure"); 1976 return NULL; 1977 } 1978 memset(msg, 0, len); 1979 1980 /* rmcp header */ 1981 memcpy(msg, &rmcp, sizeof(rmcp)); 1982 len = sizeof(rmcp); 1983 1984 /* 1985 * ipmi session header 1986 */ 1987 /* Authtype should always be none for 1.5 packets sent from this 1988 * interface 1989 */ 1990 msg[len++] = IPMI_SESSION_AUTHTYPE_NONE; 1991 1992 msg[len++] = session->out_seq & 0xff; 1993 msg[len++] = (session->out_seq >> 8) & 0xff; 1994 msg[len++] = (session->out_seq >> 16) & 0xff; 1995 msg[len++] = (session->out_seq >> 24) & 0xff; 1996 1997 /* 1998 * The session ID should be all zeroes for pre-session commands. We 1999 * should only be using the 1.5 interface for the pre-session Get 2000 * Channel Authentication Capabilities command 2001 */ 2002 msg[len++] = 0; 2003 msg[len++] = 0; 2004 msg[len++] = 0; 2005 msg[len++] = 0; 2006 2007 /* message length */ 2008 msg[len++] = req->msg.data_len + 7; 2009 2010 /* ipmi message header */ 2011 cs = mp = len; 2012 msg[len++] = IPMI_BMC_SLAVE_ADDR; 2013 msg[len++] = req->msg.netfn << 2; 2014 tmp = len - cs; 2015 msg[len++] = ipmi_csum(msg+cs, tmp); 2016 cs = len; 2017 msg[len++] = IPMI_REMOTE_SWID; 2018 2019 entry->rq_seq = 0; 2020 2021 msg[len++] = entry->rq_seq << 2; 2022 msg[len++] = req->msg.cmd; 2023 2024 lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header"); 2025 lprintf(LOG_DEBUG+1, ">> Authtype : %s", 2026 val2str(IPMI_SESSION_AUTHTYPE_NONE, ipmi_authtype_session_vals)); 2027 lprintf(LOG_DEBUG+1, ">> Sequence : 0x%08lx", 2028 (long)session->out_seq); 2029 lprintf(LOG_DEBUG+1, ">> Session ID : 0x%08lx", 2030 (long)0); 2031 2032 lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header"); 2033 lprintf(LOG_DEBUG+1, ">> Rs Addr : %02x", IPMI_BMC_SLAVE_ADDR); 2034 lprintf(LOG_DEBUG+1, ">> NetFn : %02x", req->msg.netfn); 2035 lprintf(LOG_DEBUG+1, ">> Rs LUN : %01x", 0); 2036 lprintf(LOG_DEBUG+1, ">> Rq Addr : %02x", IPMI_REMOTE_SWID); 2037 lprintf(LOG_DEBUG+1, ">> Rq Seq : %02x", entry->rq_seq); 2038 lprintf(LOG_DEBUG+1, ">> Rq Lun : %01x", 0); 2039 lprintf(LOG_DEBUG+1, ">> Command : %02x", req->msg.cmd); 2040 2041 /* message data */ 2042 if (req->msg.data_len) { 2043 memcpy(msg+len, req->msg.data, req->msg.data_len); 2044 len += req->msg.data_len; 2045 } 2046 2047 /* second checksum */ 2048 tmp = len - cs; 2049 msg[len++] = ipmi_csum(msg+cs, tmp); 2050 2051 entry->msg_len = len; 2052 entry->msg_data = msg; 2053 2054 return entry; 2055 } 2056 2057 2058 2059 /* 2060 * is_sol_packet 2061 */ 2062 static int 2063 is_sol_packet(struct ipmi_rs * rsp) 2064 { 2065 return (rsp && 2066 (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 2067 (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)); 2068 } 2069 2070 2071 2072 /* 2073 * sol_response_acks_packet 2074 */ 2075 static int 2076 sol_response_acks_packet( 2077 struct ipmi_rs * rsp, 2078 struct ipmi_v2_payload * payload) 2079 { 2080 return (is_sol_packet(rsp) && 2081 payload && 2082 (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) && 2083 (rsp->payload.sol_packet.acked_packet_number == 2084 payload->payload.sol_packet.packet_sequence_number)); 2085 } 2086 2087 2088 2089 /* 2090 * ipmi_lanplus_send_payload 2091 * 2092 */ 2093 struct ipmi_rs * 2094 ipmi_lanplus_send_payload( 2095 struct ipmi_intf * intf, 2096 struct ipmi_v2_payload * payload) 2097 { 2098 struct ipmi_rs * rsp = NULL; 2099 uint8_t * msg_data; 2100 int msg_length; 2101 struct ipmi_session * session = intf->session; 2102 int try = 0; 2103 int xmit = 1; 2104 time_t ltime; 2105 uint32_t saved_timeout; 2106 2107 if (!intf->opened && intf->open && intf->open(intf) < 0) 2108 return NULL; 2109 2110 /* 2111 * The session timeout is initialized in the above interface open, 2112 * so it will only be valid after the open completes. 2113 */ 2114 saved_timeout = session->timeout; 2115 while (try < session->retry) { 2116 //ltime = time(NULL); 2117 2118 if (xmit) { 2119 ltime = time(NULL); 2120 2121 if (payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI) 2122 { 2123 /* 2124 * Build an IPMI v1.5 or v2 command 2125 */ 2126 struct ipmi_rq_entry * entry; 2127 struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request; 2128 2129 lprintf(LOG_DEBUG, ""); 2130 lprintf(LOG_DEBUG, ">> Sending IPMI command payload"); 2131 lprintf(LOG_DEBUG, ">> netfn : 0x%02x", ipmi_request->msg.netfn); 2132 lprintf(LOG_DEBUG, ">> command : 0x%02x", ipmi_request->msg.cmd); 2133 2134 if (verbose > 1) 2135 { 2136 uint16_t i; 2137 fprintf(stderr, ">> data : "); 2138 for (i = 0; i < ipmi_request->msg.data_len; ++i) 2139 fprintf(stderr, "0x%02x ", ipmi_request->msg.data[i]); 2140 fprintf(stderr, "\n\n"); 2141 } 2142 2143 2144 /* 2145 * If we are presession, and the command is GET CHANNEL AUTHENTICATION 2146 * CAPABILITIES, we will build the command in v1.5 format. This is so 2147 * that we can ask any server whether it supports IPMI v2 / RMCP+ 2148 * before we attempt to open a v2.x session. 2149 */ 2150 if ((ipmi_request->msg.netfn == IPMI_NETFN_APP) && 2151 (ipmi_request->msg.cmd == IPMI_GET_CHANNEL_AUTH_CAP) && 2152 (session->v2_data.bmc_id == 0)) // jme - check 2153 { 2154 lprintf(LOG_DEBUG+1, "BUILDING A v1.5 COMMAND"); 2155 entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request); 2156 } 2157 else 2158 { 2159 int isRetry = ( try > 0 ? 1 : 0 ); 2160 2161 lprintf(LOG_DEBUG+1, "BUILDING A v2 COMMAND"); 2162 entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request, isRetry); 2163 } 2164 2165 if (entry == NULL) { 2166 lprintf(LOG_ERR, "Aborting send command, unable to build"); 2167 return NULL; 2168 } 2169 2170 msg_data = entry->msg_data; 2171 msg_length = entry->msg_len; 2172 } 2173 2174 else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST) 2175 { 2176 lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n"); 2177 assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION 2178 || session->v2_data.session_state == LANPLUS_STATE_OPEN_SESSION_SENT); 2179 2180 ipmi_lanplus_build_v2x_msg(intf, /* in */ 2181 payload, /* in */ 2182 &msg_length, /* out */ 2183 &msg_data, /* out */ 2184 0); /* irrelevant for this msg*/ 2185 2186 } 2187 2188 else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_1) 2189 { 2190 lprintf(LOG_DEBUG, ">> SENDING A RAKP 1 MESSAGE\n"); 2191 assert(session->v2_data.session_state == 2192 LANPLUS_STATE_OPEN_SESSION_RECEIEVED); 2193 2194 ipmi_lanplus_build_v2x_msg(intf, /* in */ 2195 payload, /* in */ 2196 &msg_length, /* out */ 2197 &msg_data, /* out */ 2198 0); /* irrelevant for this msg*/ 2199 2200 } 2201 2202 else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_3) 2203 { 2204 lprintf(LOG_DEBUG, ">> SENDING A RAKP 3 MESSAGE\n"); 2205 assert(session->v2_data.session_state == 2206 LANPLUS_STATE_RAKP_2_RECEIVED); 2207 2208 ipmi_lanplus_build_v2x_msg(intf, /* in */ 2209 payload, /* in */ 2210 &msg_length, /* out */ 2211 &msg_data, /* out */ 2212 0); /* irrelevant for this msg*/ 2213 2214 } 2215 2216 else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) 2217 { 2218 lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n"); 2219 assert(session->v2_data.session_state == LANPLUS_STATE_ACTIVE); 2220 2221 ipmi_lanplus_build_v2x_msg(intf, /* in */ 2222 payload, /* in */ 2223 &msg_length, /* out */ 2224 &msg_data, /* out */ 2225 0); /* irrelevant for this msg*/ 2226 } 2227 2228 else 2229 { 2230 lprintf(LOG_ERR, "Payload type 0x%0x is unsupported!", 2231 payload->payload_type); 2232 assert(0); 2233 } 2234 2235 2236 if (ipmi_lan_send_packet(intf, msg_data, msg_length) < 0) { 2237 lprintf(LOG_ERR, "IPMI LAN send command failed"); 2238 return NULL; 2239 } 2240 } 2241 2242 /* if we are set to noanswer we do not expect response */ 2243 if (intf->noanswer) 2244 break; 2245 2246 usleep(100); /* Not sure what this is for */ 2247 2248 /* Remember our connection state */ 2249 switch (payload->payload_type) 2250 { 2251 case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: 2252 session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT; 2253 break; 2254 case IPMI_PAYLOAD_TYPE_RAKP_1: 2255 session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT; 2256 break; 2257 case IPMI_PAYLOAD_TYPE_RAKP_3: 2258 session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT; 2259 break; 2260 } 2261 2262 2263 /* 2264 * Special case for SOL outbound packets. 2265 */ 2266 if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) 2267 { 2268 if (! payload->payload.sol_packet.packet_sequence_number) 2269 { 2270 /* We're just sending an ACK. No need to retry. */ 2271 break; 2272 } 2273 2274 2275 rsp = ipmi_lanplus_recv_sol(intf); /* Grab the next packet */ 2276 2277 if (sol_response_acks_packet(rsp, payload)) 2278 break; 2279 2280 else if (is_sol_packet(rsp) && rsp->data_len) 2281 { 2282 /* 2283 * We're still waiting for our ACK, but we more data from 2284 * the BMC 2285 */ 2286 intf->session->sol_data.sol_input_handler(rsp); 2287 /* In order to avoid duplicate output, just set data_len to 0 */ 2288 rsp->data_len = 0; 2289 } 2290 } 2291 2292 2293 /* Non-SOL processing */ 2294 else 2295 { 2296 rsp = ipmi_lan_poll_recv(intf); 2297 2298 /* Duplicate Request ccode most likely indicates a response to 2299 a previous retry. Ignore and keep polling. */ 2300 while ((rsp != NULL) && (rsp->ccode == 0xcf)) 2301 { 2302 rsp = NULL; 2303 rsp = ipmi_lan_poll_recv(intf); 2304 } 2305 2306 if (rsp) 2307 break; 2308 } 2309 2310 /* only timeout if time exceeds the timeout value */ 2311 xmit = ((time(NULL) - ltime) >= session->timeout); 2312 2313 usleep(5000); 2314 2315 if (xmit) { 2316 /* increment session timeout by 1 second each retry */ 2317 session->timeout++; 2318 } 2319 2320 try++; 2321 } 2322 session->timeout = saved_timeout; 2323 2324 /* IPMI messages are deleted under ipmi_lan_poll_recv() */ 2325 switch (payload->payload_type) { 2326 case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: 2327 case IPMI_PAYLOAD_TYPE_RAKP_1: 2328 case IPMI_PAYLOAD_TYPE_RAKP_3: 2329 free(msg_data); 2330 msg_data = NULL; 2331 break; 2332 } 2333 2334 return rsp; 2335 } 2336 2337 2338 2339 /* 2340 * is_sol_partial_ack 2341 * 2342 * Determine if the response is a partial ACK/NACK that indicates 2343 * we need to resend part of our packet. 2344 * 2345 * returns the number of characters we need to resend, or 2346 * 0 if this isn't an ACK or we don't need to resend anything 2347 */ 2348 int is_sol_partial_ack( 2349 struct ipmi_intf * intf, 2350 struct ipmi_v2_payload * v2_payload, 2351 struct ipmi_rs * rs) 2352 { 2353 int chars_to_resend = 0; 2354 2355 if (v2_payload && 2356 rs && 2357 is_sol_packet(rs) && 2358 sol_response_acks_packet(rs, v2_payload) && 2359 (rs->payload.sol_packet.accepted_character_count < 2360 v2_payload->payload.sol_packet.character_count)) 2361 { 2362 if (ipmi_oem_active(intf, "intelplus") && 2363 rs->payload.sol_packet.accepted_character_count == 0) 2364 return 0; 2365 2366 chars_to_resend = 2367 v2_payload->payload.sol_packet.character_count - 2368 rs->payload.sol_packet.accepted_character_count; 2369 } 2370 2371 return chars_to_resend; 2372 } 2373 2374 2375 2376 /* 2377 * set_sol_packet_sequence_number 2378 */ 2379 static void set_sol_packet_sequence_number( 2380 struct ipmi_intf * intf, 2381 struct ipmi_v2_payload * v2_payload) 2382 { 2383 /* Keep our sequence number sane */ 2384 if (intf->session->sol_data.sequence_number > 0x0F) 2385 intf->session->sol_data.sequence_number = 1; 2386 2387 v2_payload->payload.sol_packet.packet_sequence_number = 2388 intf->session->sol_data.sequence_number++; 2389 } 2390 2391 2392 2393 /* 2394 * ipmi_lanplus_send_sol 2395 * 2396 * Sends a SOL packet.. We handle partial ACK/NACKs from the BMC here. 2397 * 2398 * Returns a pointer to the SOL ACK we received, or 2399 * 0 on failure 2400 * 2401 */ 2402 struct ipmi_rs * 2403 ipmi_lanplus_send_sol( 2404 struct ipmi_intf * intf, 2405 struct ipmi_v2_payload * v2_payload) 2406 { 2407 struct ipmi_rs * rs; 2408 2409 /* 2410 * chars_to_resend indicates either that we got a NACK telling us 2411 * that we need to resend some part of our data. 2412 */ 2413 int chars_to_resend = 0; 2414 2415 v2_payload->payload_type = IPMI_PAYLOAD_TYPE_SOL; 2416 2417 /* 2418 * Payload length is just the length of the character 2419 * data here. 2420 */ 2421 v2_payload->payload_length = v2_payload->payload.sol_packet.character_count; 2422 2423 v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */ 2424 2425 set_sol_packet_sequence_number(intf, v2_payload); 2426 2427 v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */ 2428 2429 rs = ipmi_lanplus_send_payload(intf, v2_payload); 2430 2431 /* Determine if we need to resend some of our data */ 2432 chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs); 2433 2434 while (rs && !rs->payload.sol_packet.transfer_unavailable && 2435 !rs->payload.sol_packet.is_nack && 2436 chars_to_resend) 2437 { 2438 /* 2439 * We first need to handle any new data we might have 2440 * received in our NACK 2441 */ 2442 if (rs->data_len) 2443 intf->session->sol_data.sol_input_handler(rs); 2444 2445 set_sol_packet_sequence_number(intf, v2_payload); 2446 2447 /* Just send the required data */ 2448 memmove(v2_payload->payload.sol_packet.data, 2449 v2_payload->payload.sol_packet.data + 2450 rs->payload.sol_packet.accepted_character_count, 2451 chars_to_resend); 2452 2453 v2_payload->payload.sol_packet.character_count = chars_to_resend; 2454 2455 v2_payload->payload_length = v2_payload->payload.sol_packet.character_count; 2456 2457 rs = ipmi_lanplus_send_payload(intf, v2_payload); 2458 2459 chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs); 2460 } 2461 2462 return rs; 2463 } 2464 2465 2466 2467 /* 2468 * check_sol_packet_for_new_data 2469 * 2470 * Determine whether the SOL packet has already been seen 2471 * and whether the packet has new data for us. 2472 * 2473 * This function has the side effect of removing an previously 2474 * seen data, and moving new data to the front. 2475 * 2476 * It also "Remembers" the data so we don't get repeats. 2477 * 2478 * returns the number of new bytes in the SOL packet 2479 */ 2480 static int 2481 check_sol_packet_for_new_data( 2482 struct ipmi_intf * intf, 2483 struct ipmi_rs *rsp) 2484 { 2485 static uint8_t last_received_sequence_number = 0; 2486 static uint8_t last_received_byte_count = 0; 2487 int new_data_size = 0; 2488 2489 2490 if (rsp && 2491 (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 2492 (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)) 2493 { 2494 /* Store the data length before we mod it */ 2495 uint8_t unaltered_data_len = rsp->data_len; 2496 2497 if (rsp->payload.sol_packet.packet_sequence_number == 2498 last_received_sequence_number) 2499 { 2500 2501 /* 2502 * This is the same as the last packet, but may include 2503 * extra data 2504 */ 2505 new_data_size = rsp->data_len - last_received_byte_count; 2506 2507 if (new_data_size > 0) 2508 { 2509 /* We have more data to process */ 2510 memmove(rsp->data, 2511 rsp->data + 2512 rsp->data_len - new_data_size, 2513 new_data_size); 2514 } 2515 2516 rsp->data_len = new_data_size; 2517 } 2518 2519 2520 /* 2521 *Rember the data for next round 2522 */ 2523 if (rsp->payload.sol_packet.packet_sequence_number) 2524 { 2525 last_received_sequence_number = 2526 rsp->payload.sol_packet.packet_sequence_number; 2527 2528 last_received_byte_count = unaltered_data_len; 2529 } 2530 } 2531 2532 2533 return new_data_size; 2534 } 2535 2536 2537 2538 /* 2539 * ack_sol_packet 2540 * 2541 * Provided the specified packet looks reasonable, ACK it. 2542 */ 2543 static void 2544 ack_sol_packet( 2545 struct ipmi_intf * intf, 2546 struct ipmi_rs * rsp) 2547 { 2548 if (rsp && 2549 (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 2550 (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) && 2551 (rsp->payload.sol_packet.packet_sequence_number)) 2552 { 2553 struct ipmi_v2_payload ack; 2554 2555 bzero(&ack, sizeof(struct ipmi_v2_payload)); 2556 2557 ack.payload_type = IPMI_PAYLOAD_TYPE_SOL; 2558 2559 /* 2560 * Payload length is just the length of the character 2561 * data here. 2562 */ 2563 ack.payload_length = 0; 2564 2565 /* ACK packets have sequence numbers of 0 */ 2566 ack.payload.sol_packet.packet_sequence_number = 0; 2567 2568 ack.payload.sol_packet.acked_packet_number = 2569 rsp->payload.sol_packet.packet_sequence_number; 2570 2571 ack.payload.sol_packet.accepted_character_count = rsp->data_len; 2572 2573 ipmi_lanplus_send_payload(intf, &ack); 2574 } 2575 } 2576 2577 2578 2579 /* 2580 * ipmi_lanplus_recv_sol 2581 * 2582 * Receive a SOL packet and send an ACK in response. 2583 * 2584 */ 2585 struct ipmi_rs * 2586 ipmi_lanplus_recv_sol(struct ipmi_intf * intf) 2587 { 2588 struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf); 2589 2590 if (rsp && rsp->session.authtype != 0) 2591 { 2592 ack_sol_packet(intf, rsp); 2593 2594 /* 2595 * Remembers the data sent, and alters the data to just 2596 * include the new stuff. 2597 */ 2598 check_sol_packet_for_new_data(intf, rsp); 2599 } 2600 return rsp; 2601 } 2602 2603 2604 2605 /** 2606 * ipmi_lanplus_send_ipmi_cmd 2607 * 2608 * Build a payload request and dispatch it. 2609 */ 2610 struct ipmi_rs * 2611 ipmi_lanplus_send_ipmi_cmd( 2612 struct ipmi_intf * intf, 2613 struct ipmi_rq * req) 2614 { 2615 struct ipmi_v2_payload v2_payload; 2616 2617 v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI; 2618 v2_payload.payload.ipmi_request.request = req; 2619 2620 return ipmi_lanplus_send_payload(intf, &v2_payload); 2621 } 2622 2623 2624 /* 2625 * ipmi_get_auth_capabilities_cmd 2626 * 2627 * This command may have to be sent twice. We first ask for the 2628 * authentication capabilities with the "request IPMI v2 data bit" 2629 * set. If this fails, we send the same command without that bit 2630 * set. 2631 * 2632 * param intf is the initialized (but possibly) pre-session interface 2633 * on which we will send the command 2634 * param auth_cap [out] will be initialized to hold the Get Channel 2635 * Authentication Capabilities return data on success. Its 2636 * contents will be undefined on error. 2637 * 2638 * returns 0 on success 2639 * non-zero if we were unable to contact the BMC, or we cannot 2640 * get a successful response 2641 * 2642 */ 2643 static int 2644 ipmi_get_auth_capabilities_cmd( 2645 struct ipmi_intf * intf, 2646 struct get_channel_auth_cap_rsp * auth_cap) 2647 { 2648 struct ipmi_rs * rsp; 2649 struct ipmi_rq req; 2650 uint8_t msg_data[2]; 2651 uint8_t backupBridgePossible; 2652 2653 backupBridgePossible = bridgePossible; 2654 2655 bridgePossible = 0; 2656 2657 msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well 2658 msg_data[1] = intf->session->privlvl; 2659 2660 memset(&req, 0, sizeof(req)); 2661 req.msg.netfn = IPMI_NETFN_APP; // 0x06 2662 req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38 2663 req.msg.data = msg_data; 2664 req.msg.data_len = 2; 2665 2666 rsp = intf->sendrecv(intf, &req); 2667 2668 if (rsp == NULL || rsp->ccode > 0) { 2669 /* 2670 * It's very possible that this failed because we asked for IPMI 2671 * v2 data. Ask again, without requesting IPMI v2 data. 2672 */ 2673 msg_data[0] &= 0x7F; 2674 2675 rsp = intf->sendrecv(intf, &req); 2676 2677 if (rsp == NULL) { 2678 lprintf(LOG_INFO, "Get Auth Capabilities error"); 2679 return 1; 2680 } 2681 if (rsp->ccode > 0) { 2682 lprintf(LOG_INFO, "Get Auth Capabilities error: %s", 2683 val2str(rsp->ccode, completion_code_vals)); 2684 return 1; 2685 } 2686 } 2687 2688 2689 memcpy(auth_cap, 2690 rsp->data, 2691 sizeof(struct get_channel_auth_cap_rsp)); 2692 2693 bridgePossible = backupBridgePossible; 2694 2695 return 0; 2696 } 2697 2698 2699 2700 static int 2701 ipmi_close_session_cmd(struct ipmi_intf * intf) 2702 { 2703 struct ipmi_rs * rsp; 2704 struct ipmi_rq req; 2705 uint8_t msg_data[4]; 2706 uint32_t bmc_session_lsbf; 2707 uint8_t backupBridgePossible; 2708 2709 if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE) 2710 return -1; 2711 2712 backupBridgePossible = bridgePossible; 2713 2714 intf->target_addr = IPMI_BMC_SLAVE_ADDR; 2715 bridgePossible = 0; 2716 2717 bmc_session_lsbf = intf->session->v2_data.bmc_id; 2718 #if WORDS_BIGENDIAN 2719 bmc_session_lsbf = BSWAP_32(bmc_session_lsbf); 2720 #endif 2721 2722 memcpy(&msg_data, &bmc_session_lsbf, 4); 2723 2724 memset(&req, 0, sizeof(req)); 2725 req.msg.netfn = IPMI_NETFN_APP; 2726 req.msg.cmd = 0x3c; 2727 req.msg.data = msg_data; 2728 req.msg.data_len = 4; 2729 2730 rsp = intf->sendrecv(intf, &req); 2731 if (rsp == NULL) { 2732 /* Looks like the session was closed */ 2733 lprintf(LOG_ERR, "Close Session command failed"); 2734 return -1; 2735 } 2736 if (verbose > 2) 2737 printbuf(rsp->data, rsp->data_len, "close_session"); 2738 2739 if (rsp->ccode == 0x87) { 2740 lprintf(LOG_ERR, "Failed to Close Session: invalid " 2741 "session ID %08lx", 2742 (long)intf->session->v2_data.bmc_id); 2743 return -1; 2744 } 2745 if (rsp->ccode > 0) { 2746 lprintf(LOG_ERR, "Close Session command failed: %s", 2747 val2str(rsp->ccode, completion_code_vals)); 2748 return -1; 2749 } 2750 2751 lprintf(LOG_DEBUG, "Closed Session %08lx\n", 2752 (long)intf->session->v2_data.bmc_id); 2753 2754 bridgePossible = backupBridgePossible; 2755 2756 return 0; 2757 } 2758 2759 2760 2761 /* 2762 * ipmi_lanplus_open_session 2763 * 2764 * Build and send the open session command. See section 13.17 of the IPMI 2765 * v2 specification for details. 2766 */ 2767 static int 2768 ipmi_lanplus_open_session(struct ipmi_intf * intf) 2769 { 2770 struct ipmi_v2_payload v2_payload; 2771 struct ipmi_session * session = intf->session; 2772 uint8_t * msg; 2773 struct ipmi_rs * rsp; 2774 int rc = 0; 2775 2776 2777 /* 2778 * Build an Open Session Request Payload 2779 */ 2780 msg = (uint8_t*)malloc(IPMI_OPEN_SESSION_REQUEST_SIZE); 2781 if (msg == NULL) { 2782 lprintf(LOG_ERR, "ipmitool: malloc failure"); 2783 return -1; 2784 } 2785 2786 memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE); 2787 2788 msg[0] = 0; /* Message tag */ 2789 if (ipmi_oem_active(intf, "intelplus") || session->privlvl != IPMI_SESSION_PRIV_ADMIN) 2790 msg[1] = session->privlvl; 2791 else 2792 msg[1] = 0; /* Give us highest privlg level based on supported algorithms */ 2793 msg[2] = 0; /* reserved */ 2794 msg[3] = 0; /* reserved */ 2795 2796 /* Choose our session ID for easy recognition in the packet dump */ 2797 session->v2_data.console_id = 0xA0A2A3A4; 2798 msg[4] = session->v2_data.console_id & 0xff; 2799 msg[5] = (session->v2_data.console_id >> 8) & 0xff; 2800 msg[6] = (session->v2_data.console_id >> 16) & 0xff; 2801 msg[7] = (session->v2_data.console_id >> 24) & 0xff; 2802 2803 2804 if (lanplus_get_requested_ciphers(session->cipher_suite_id, 2805 &(session->v2_data.requested_auth_alg), 2806 &(session->v2_data.requested_integrity_alg), 2807 &(session->v2_data.requested_crypt_alg))) 2808 { 2809 lprintf(LOG_WARNING, "Unsupported cipher suite ID : %d\n", 2810 session->cipher_suite_id); 2811 free(msg); 2812 msg = NULL; 2813 return -1; 2814 } 2815 2816 2817 /* 2818 * Authentication payload 2819 */ 2820 msg[8] = 0; /* specifies authentication payload */ 2821 msg[9] = 0; /* reserved */ 2822 msg[10] = 0; /* reserved */ 2823 msg[11] = 8; /* payload length */ 2824 msg[12] = session->v2_data.requested_auth_alg; 2825 msg[13] = 0; /* reserved */ 2826 msg[14] = 0; /* reserved */ 2827 msg[15] = 0; /* reserved */ 2828 2829 /* 2830 * Integrity payload 2831 */ 2832 msg[16] = 1; /* specifies integrity payload */ 2833 msg[17] = 0; /* reserved */ 2834 msg[18] = 0; /* reserved */ 2835 msg[19] = 8; /* payload length */ 2836 msg[20] = session->v2_data.requested_integrity_alg; 2837 msg[21] = 0; /* reserved */ 2838 msg[22] = 0; /* reserved */ 2839 msg[23] = 0; /* reserved */ 2840 2841 /* 2842 * Confidentiality/Encryption payload 2843 */ 2844 msg[24] = 2; /* specifies confidentiality payload */ 2845 msg[25] = 0; /* reserved */ 2846 msg[26] = 0; /* reserved */ 2847 msg[27] = 8; /* payload length */ 2848 msg[28] = session->v2_data.requested_crypt_alg; 2849 msg[29] = 0; /* reserved */ 2850 msg[30] = 0; /* reserved */ 2851 msg[31] = 0; /* reserved */ 2852 2853 2854 v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST; 2855 v2_payload.payload_length = IPMI_OPEN_SESSION_REQUEST_SIZE; 2856 v2_payload.payload.open_session_request.request = msg; 2857 2858 rsp = ipmi_lanplus_send_payload(intf, &v2_payload); 2859 2860 free(msg); 2861 msg = NULL; 2862 if (!rsp) { 2863 lprintf(LOG_WARNING, "Error sending open session message."); 2864 return -1; 2865 } 2866 if (verbose) 2867 lanplus_dump_open_session_response(rsp); 2868 2869 2870 if (rsp->payload.open_session_response.rakp_return_code != 2871 IPMI_RAKP_STATUS_NO_ERRORS) 2872 { 2873 lprintf(LOG_WARNING, "Error in open session response message : %s\n", 2874 val2str(rsp->payload.open_session_response.rakp_return_code, 2875 ipmi_rakp_return_codes)); 2876 return -1; 2877 } 2878 else 2879 { 2880 if (rsp->payload.open_session_response.console_id != 2881 session->v2_data.console_id) { 2882 lprintf(LOG_WARNING, "Warning: Console session ID is not " 2883 "what we requested"); 2884 } 2885 2886 session->v2_data.max_priv_level = 2887 rsp->payload.open_session_response.max_priv_level; 2888 session->v2_data.bmc_id = 2889 rsp->payload.open_session_response.bmc_id; 2890 session->v2_data.auth_alg = 2891 rsp->payload.open_session_response.auth_alg; 2892 session->v2_data.integrity_alg = 2893 rsp->payload.open_session_response.integrity_alg; 2894 session->v2_data.crypt_alg = 2895 rsp->payload.open_session_response.crypt_alg; 2896 session->v2_data.session_state = 2897 LANPLUS_STATE_OPEN_SESSION_RECEIEVED; 2898 2899 2900 /* 2901 * Verify that we have agreed on a cipher suite 2902 */ 2903 if (rsp->payload.open_session_response.auth_alg != 2904 session->v2_data.requested_auth_alg) 2905 { 2906 lprintf(LOG_WARNING, "Authentication algorithm 0x%02x is " 2907 "not what we requested 0x%02x\n", 2908 rsp->payload.open_session_response.auth_alg, 2909 session->v2_data.requested_auth_alg); 2910 rc = -1; 2911 } 2912 else if (rsp->payload.open_session_response.integrity_alg != 2913 session->v2_data.requested_integrity_alg) 2914 { 2915 lprintf(LOG_WARNING, "Integrity algorithm 0x%02x is " 2916 "not what we requested 0x%02x\n", 2917 rsp->payload.open_session_response.integrity_alg, 2918 session->v2_data.requested_integrity_alg); 2919 rc = -1; 2920 } 2921 else if (rsp->payload.open_session_response.crypt_alg != 2922 session->v2_data.requested_crypt_alg) 2923 { 2924 lprintf(LOG_WARNING, "Encryption algorithm 0x%02x is " 2925 "not what we requested 0x%02x\n", 2926 rsp->payload.open_session_response.crypt_alg, 2927 session->v2_data.requested_crypt_alg); 2928 rc = -1; 2929 } 2930 2931 } 2932 2933 return rc; 2934 } 2935 2936 2937 2938 /* 2939 * ipmi_lanplus_rakp1 2940 * 2941 * Build and send the RAKP 1 message as part of the IPMI v2 / RMCP+ session 2942 * negotiation protocol. We also read and validate the RAKP 2 message received 2943 * from the BMC, here. See section 13.20 of the IPMI v2 specification for 2944 * details. 2945 * 2946 * returns 0 on success 2947 * 1 on failure 2948 * 2949 * Note that failure is only indicated if we have an internal error of 2950 * some kind. If we actually get a RAKP 2 message in response to our 2951 * RAKP 1 message, any errors will be stored in 2952 * session->v2_data.rakp2_return_code and sent to the BMC in the RAKP 2953 * 3 message. 2954 */ 2955 static int 2956 ipmi_lanplus_rakp1(struct ipmi_intf * intf) 2957 { 2958 struct ipmi_v2_payload v2_payload; 2959 struct ipmi_session * session = intf->session; 2960 uint8_t * msg; 2961 struct ipmi_rs * rsp; 2962 int rc = 0; 2963 2964 /* 2965 * Build a RAKP 1 message 2966 */ 2967 msg = (uint8_t*)malloc(IPMI_RAKP1_MESSAGE_SIZE); 2968 if (msg == NULL) { 2969 lprintf(LOG_ERR, "ipmitool: malloc failure"); 2970 return 1; 2971 } 2972 memset(msg, 0, IPMI_RAKP1_MESSAGE_SIZE); 2973 2974 2975 msg[0] = 0; /* Message tag */ 2976 2977 msg[1] = 0; /* reserved */ 2978 msg[2] = 0; /* reserved */ 2979 msg[3] = 0; /* reserved */ 2980 2981 /* BMC session ID */ 2982 msg[4] = session->v2_data.bmc_id & 0xff; 2983 msg[5] = (session->v2_data.bmc_id >> 8) & 0xff; 2984 msg[6] = (session->v2_data.bmc_id >> 16) & 0xff; 2985 msg[7] = (session->v2_data.bmc_id >> 24) & 0xff; 2986 2987 2988 /* We need a 16 byte random number */ 2989 if (lanplus_rand(session->v2_data.console_rand, 16)) 2990 { 2991 // ERROR; 2992 lprintf(LOG_ERR, "ERROR generating random number " 2993 "in ipmi_lanplus_rakp1"); 2994 free(msg); 2995 msg = NULL; 2996 return 1; 2997 } 2998 memcpy(msg + 8, session->v2_data.console_rand, 16); 2999 #if WORDS_BIGENDIAN 3000 lanplus_swap(msg + 8, 16); 3001 #endif 3002 3003 if (verbose > 1) 3004 printbuf(session->v2_data.console_rand, 16, 3005 ">> Console generated random number"); 3006 3007 3008 /* 3009 * Requested maximum privilege level. 3010 */ 3011 msg[24] = session->privlvl | session->v2_data.lookupbit; 3012 session->v2_data.requested_role = msg[24]; 3013 msg[25] = 0; /* reserved */ 3014 msg[26] = 0; /* reserved */ 3015 3016 3017 /* Username specification */ 3018 msg[27] = strlen((const char *)session->username); 3019 if (msg[27] > IPMI_MAX_USER_NAME_LENGTH) 3020 { 3021 lprintf(LOG_ERR, "ERROR: user name too long. " 3022 "(Exceeds %d characters)", 3023 IPMI_MAX_USER_NAME_LENGTH); 3024 free(msg); 3025 msg = NULL; 3026 return 1; 3027 } 3028 memcpy(msg + 28, session->username, msg[27]); 3029 3030 v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1; 3031 v2_payload.payload_length = 3032 IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]); 3033 v2_payload.payload.rakp_1_message.message = msg; 3034 3035 rsp = ipmi_lanplus_send_payload(intf, &v2_payload); 3036 3037 free(msg); 3038 msg = NULL; 3039 3040 if (rsp == NULL) 3041 { 3042 lprintf(LOG_INFO, "> Error: no response from RAKP 1 message"); 3043 return 1; 3044 } 3045 3046 session->v2_data.session_state = LANPLUS_STATE_RAKP_2_RECEIVED; 3047 3048 if (verbose) 3049 lanplus_dump_rakp2_message(rsp, session->v2_data.auth_alg); 3050 3051 3052 3053 if (rsp->payload.rakp2_message.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS) 3054 { 3055 lprintf(LOG_INFO, "RAKP 2 message indicates an error : %s", 3056 val2str(rsp->payload.rakp2_message.rakp_return_code, 3057 ipmi_rakp_return_codes)); 3058 rc = 1; 3059 } 3060 3061 else 3062 { 3063 memcpy(session->v2_data.bmc_rand, rsp->payload.rakp2_message.bmc_rand, 16); 3064 memcpy(session->v2_data.bmc_guid, rsp->payload.rakp2_message.bmc_guid, 16); 3065 3066 if (verbose > 2) 3067 printbuf(session->v2_data.bmc_rand, 16, "bmc_rand"); 3068 3069 /* 3070 * It is at this point that we have to decode the random number and determine 3071 * whether the BMC has authenticated. 3072 */ 3073 if (! lanplus_rakp2_hmac_matches(session, 3074 rsp->payload.rakp2_message.key_exchange_auth_code, 3075 intf)) 3076 { 3077 /* Error */ 3078 lprintf(LOG_INFO, "> RAKP 2 HMAC is invalid"); 3079 session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE; 3080 rc = 1; 3081 } 3082 else 3083 { 3084 /* Success */ 3085 session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_NO_ERRORS; 3086 } 3087 } 3088 3089 return rc; 3090 } 3091 3092 3093 3094 /* 3095 * ipmi_lanplus_rakp3 3096 * 3097 * Build and send the RAKP 3 message as part of the IPMI v2 / RMCP+ session 3098 * negotiation protocol. We also read and validate the RAKP 4 message received 3099 * from the BMC, here. See section 13.20 of the IPMI v2 specification for 3100 * details. 3101 * 3102 * If the RAKP 2 return code is not IPMI_RAKP_STATUS_NO_ERRORS, we will 3103 * exit with an error code immediately after sendint the RAKP 3 message. 3104 * 3105 * param intf is the intf that holds all the state we are concerned with 3106 * 3107 * returns 0 on success 3108 * 1 on failure 3109 */ 3110 static int 3111 ipmi_lanplus_rakp3(struct ipmi_intf * intf) 3112 { 3113 struct ipmi_v2_payload v2_payload; 3114 struct ipmi_session * session = intf->session; 3115 uint8_t * msg; 3116 struct ipmi_rs * rsp; 3117 3118 assert(session->v2_data.session_state == LANPLUS_STATE_RAKP_2_RECEIVED); 3119 3120 /* 3121 * Build a RAKP 3 message 3122 */ 3123 msg = (uint8_t*)malloc(IPMI_RAKP3_MESSAGE_MAX_SIZE); 3124 if (msg == NULL) { 3125 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3126 return 1; 3127 } 3128 memset(msg, 0, IPMI_RAKP3_MESSAGE_MAX_SIZE); 3129 3130 3131 msg[0] = 0; /* Message tag */ 3132 msg[1] = session->v2_data.rakp2_return_code; 3133 3134 msg[2] = 0; /* reserved */ 3135 msg[3] = 0; /* reserved */ 3136 3137 /* BMC session ID */ 3138 msg[4] = session->v2_data.bmc_id & 0xff; 3139 msg[5] = (session->v2_data.bmc_id >> 8) & 0xff; 3140 msg[6] = (session->v2_data.bmc_id >> 16) & 0xff; 3141 msg[7] = (session->v2_data.bmc_id >> 24) & 0xff; 3142 3143 v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_3; 3144 v2_payload.payload_length = 8; 3145 v2_payload.payload.rakp_3_message.message = msg; 3146 3147 /* 3148 * If the rakp2 return code indicates and error, we don't have to 3149 * generate an authcode or session integrity key. In that case, we 3150 * are simply sending a RAKP 3 message to indicate to the BMC that the 3151 * RAKP 2 message caused an error. 3152 */ 3153 if (session->v2_data.rakp2_return_code == IPMI_RAKP_STATUS_NO_ERRORS) 3154 { 3155 uint32_t auth_length; 3156 3157 if (lanplus_generate_rakp3_authcode(msg + 8, session, &auth_length, intf)) 3158 { 3159 /* Error */ 3160 lprintf(LOG_INFO, "> Error generating RAKP 3 authcode"); 3161 free(msg); 3162 msg = NULL; 3163 return 1; 3164 } 3165 else 3166 { 3167 /* Success */ 3168 v2_payload.payload_length += auth_length; 3169 } 3170 3171 /* Generate our Session Integrity Key, K1, and K2 */ 3172 if (lanplus_generate_sik(session, intf)) 3173 { 3174 /* Error */ 3175 lprintf(LOG_INFO, "> Error generating session integrity key"); 3176 free(msg); 3177 msg = NULL; 3178 return 1; 3179 } 3180 else if (lanplus_generate_k1(session)) 3181 { 3182 /* Error */ 3183 lprintf(LOG_INFO, "> Error generating K1 key"); 3184 free(msg); 3185 msg = NULL; 3186 return 1; 3187 } 3188 else if (lanplus_generate_k2(session)) 3189 { 3190 /* Error */ 3191 lprintf(LOG_INFO, "> Error generating K1 key"); 3192 free(msg); 3193 msg = NULL; 3194 return 1; 3195 } 3196 } 3197 3198 3199 rsp = ipmi_lanplus_send_payload(intf, &v2_payload); 3200 3201 free(msg); 3202 msg = NULL; 3203 3204 if (session->v2_data.rakp2_return_code != IPMI_RAKP_STATUS_NO_ERRORS) 3205 { 3206 /* 3207 * If the previous RAKP 2 message received was deemed erroneous, 3208 * we have nothing else to do here. We only sent the RAKP 3 message 3209 * to indicate to the BMC that the RAKP 2 message failed. 3210 */ 3211 return 1; 3212 } 3213 else if (rsp == NULL) 3214 { 3215 lprintf(LOG_INFO, "> Error: no response from RAKP 3 message"); 3216 return 1; 3217 } 3218 3219 3220 /* 3221 * We have a RAKP 4 message to chew on. 3222 */ 3223 if (verbose) 3224 lanplus_dump_rakp4_message(rsp, session->v2_data.auth_alg); 3225 3226 3227 if (rsp->payload.open_session_response.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS) 3228 { 3229 lprintf(LOG_INFO, "RAKP 4 message indicates an error : %s", 3230 val2str(rsp->payload.rakp4_message.rakp_return_code, 3231 ipmi_rakp_return_codes)); 3232 return 1; 3233 } 3234 3235 else 3236 { 3237 /* Validate the authcode */ 3238 if (lanplus_rakp4_hmac_matches(session, 3239 rsp->payload.rakp4_message.integrity_check_value, 3240 intf)) 3241 { 3242 /* Success */ 3243 session->v2_data.session_state = LANPLUS_STATE_ACTIVE; 3244 } 3245 else 3246 { 3247 /* Error */ 3248 lprintf(LOG_INFO, "> RAKP 4 message has invalid integrity check value"); 3249 return 1; 3250 } 3251 } 3252 3253 intf->abort = 0; 3254 return 0; 3255 } 3256 3257 3258 3259 /** 3260 * ipmi_lan_close 3261 */ 3262 void 3263 ipmi_lanplus_close(struct ipmi_intf * intf) 3264 { 3265 if (!intf->abort) 3266 ipmi_close_session_cmd(intf); 3267 3268 if (intf->fd >= 0) 3269 close(intf->fd); 3270 3271 ipmi_req_clear_entries(); 3272 3273 if (intf->session) { 3274 free(intf->session); 3275 intf->session = NULL; 3276 } 3277 3278 intf->session = NULL; 3279 intf->opened = 0; 3280 intf->manufacturer_id = IPMI_OEM_UNKNOWN; 3281 intf = NULL; 3282 } 3283 3284 3285 3286 static int 3287 ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) 3288 { 3289 struct ipmi_rs * rsp; 3290 struct ipmi_rq req; 3291 uint8_t backupBridgePossible; 3292 uint8_t privlvl = intf->session->privlvl; 3293 3294 if (privlvl <= IPMI_SESSION_PRIV_USER) 3295 return 0; /* no need to set higher */ 3296 3297 backupBridgePossible = bridgePossible; 3298 3299 bridgePossible = 0; 3300 3301 memset(&req, 0, sizeof(req)); 3302 req.msg.netfn = IPMI_NETFN_APP; 3303 req.msg.cmd = 0x3b; 3304 req.msg.data = &privlvl; 3305 req.msg.data_len = 1; 3306 3307 rsp = intf->sendrecv(intf, &req); 3308 if (rsp == NULL) { 3309 lprintf(LOG_ERR, "Set Session Privilege Level to %s failed", 3310 val2str(privlvl, ipmi_privlvl_vals)); 3311 bridgePossible = backupBridgePossible; 3312 return -1; 3313 } 3314 if (verbose > 2) 3315 printbuf(rsp->data, rsp->data_len, "set_session_privlvl"); 3316 3317 if (rsp->ccode > 0) { 3318 lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s", 3319 val2str(privlvl, ipmi_privlvl_vals), 3320 val2str(rsp->ccode, completion_code_vals)); 3321 bridgePossible = backupBridgePossible; 3322 return -1; 3323 } 3324 3325 lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n", 3326 val2str(rsp->data[0], ipmi_privlvl_vals)); 3327 3328 bridgePossible = backupBridgePossible; 3329 3330 return 0; 3331 } 3332 3333 /** 3334 * ipmi_lanplus_open 3335 */ 3336 int 3337 ipmi_lanplus_open(struct ipmi_intf * intf) 3338 { 3339 int rc; 3340 struct get_channel_auth_cap_rsp auth_cap; 3341 struct ipmi_session *session; 3342 3343 if (!intf || !intf->session) 3344 return -1; 3345 session = intf->session; 3346 3347 3348 if (!session->port) 3349 session->port = IPMI_LANPLUS_PORT; 3350 if (!session->privlvl) 3351 session->privlvl = IPMI_SESSION_PRIV_ADMIN; 3352 if (!session->timeout) 3353 session->timeout = IPMI_LAN_TIMEOUT; 3354 if (!session->retry) 3355 session->retry = IPMI_LAN_RETRY; 3356 3357 if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) { 3358 lprintf(LOG_ERR, "No hostname specified!"); 3359 return -1; 3360 } 3361 3362 intf->abort = 1; 3363 3364 3365 /* Setup our lanplus session state */ 3366 session->v2_data.session_state = LANPLUS_STATE_PRESESSION; 3367 session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE; 3368 session->v2_data.crypt_alg = IPMI_CRYPT_NONE; 3369 session->v2_data.console_id = 0x00; 3370 session->v2_data.bmc_id = 0x00; 3371 session->sol_data.sequence_number = 1; 3372 //session->sol_data.last_received_sequence_number = 0; 3373 //session->sol_data.last_received_byte_count = 0; 3374 memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE); 3375 3376 /* Kg is set in ipmi_intf */ 3377 //memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); 3378 3379 if (ipmi_intf_socket_connect (intf) == -1) { 3380 lprintf(LOG_ERR, "Could not open socket!"); 3381 return -1; 3382 } 3383 3384 if (intf->fd < 0) { 3385 lperror(LOG_ERR, "Connect to %s failed", 3386 session->hostname); 3387 intf->close(intf); 3388 return -1; 3389 } 3390 3391 intf->opened = 1; 3392 3393 /* 3394 * 3395 * Make sure the BMC supports IPMI v2 / RMCP+ 3396 */ 3397 if (!ipmi_oem_active(intf, "i82571spt") && 3398 ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) { 3399 lprintf(LOG_INFO, "Error issuing Get Channel " 3400 "Authentication Capabilies request"); 3401 goto fail; 3402 } 3403 3404 if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available) 3405 { 3406 lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+"); 3407 goto fail; 3408 } 3409 3410 3411 /* 3412 * Open session 3413 */ 3414 if (ipmi_lanplus_open_session(intf)){ 3415 intf->close(intf); 3416 goto fail; 3417 } 3418 3419 /* 3420 * RAKP 1 3421 */ 3422 if (ipmi_lanplus_rakp1(intf)){ 3423 intf->close(intf); 3424 goto fail; 3425 } 3426 3427 3428 /* 3429 * RAKP 3 3430 */ 3431 if (ipmi_lanplus_rakp3(intf)){ 3432 intf->close(intf); 3433 goto fail; 3434 } 3435 3436 3437 lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n"); 3438 3439 if (!ipmi_oem_active(intf, "i82571spt")) { 3440 rc = ipmi_set_session_privlvl_cmd(intf); 3441 if (rc < 0) 3442 goto fail; 3443 } 3444 intf->manufacturer_id = ipmi_get_oem(intf); 3445 bridgePossible = 1; 3446 3447 return intf->fd; 3448 3449 fail: 3450 lprintf(LOG_ERR, "Error: Unable to establish IPMI v2 / RMCP+ session"); 3451 intf->opened = 0; 3452 return -1; 3453 } 3454 3455 3456 3457 void test_crypt1(void) 3458 { 3459 uint8_t key[] = 3460 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 3461 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}; 3462 3463 uint16_t bytes_encrypted; 3464 uint16_t bytes_decrypted; 3465 uint8_t decrypt_buffer[1000]; 3466 uint8_t encrypt_buffer[1000]; 3467 3468 uint8_t data[] = 3469 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 3470 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 3471 0x11, 0x12}; 3472 3473 printbuf(data, sizeof(data), "original data"); 3474 3475 if (lanplus_encrypt_payload(IPMI_CRYPT_AES_CBC_128, 3476 key, 3477 data, 3478 sizeof(data), 3479 encrypt_buffer, 3480 &bytes_encrypted)) 3481 { 3482 lprintf(LOG_ERR, "Encrypt test failed"); 3483 assert(0); 3484 } 3485 printbuf(encrypt_buffer, bytes_encrypted, "encrypted payload"); 3486 3487 3488 if (lanplus_decrypt_payload(IPMI_CRYPT_AES_CBC_128, 3489 key, 3490 encrypt_buffer, 3491 bytes_encrypted, 3492 decrypt_buffer, 3493 &bytes_decrypted)) 3494 { 3495 lprintf(LOG_ERR, "Decrypt test failed\n"); 3496 assert(0); 3497 } 3498 printbuf(decrypt_buffer, bytes_decrypted, "decrypted payload"); 3499 3500 lprintf(LOG_DEBUG, "\nDone testing the encrypt/decyrpt methods!\n"); 3501 exit(0); 3502 } 3503 3504 3505 3506 void test_crypt2(void) 3507 { 3508 uint8_t key[] = 3509 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 3510 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}; 3511 uint8_t iv[] = 3512 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 3513 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}; 3514 uint8_t data[8] = "12345678"; 3515 3516 uint8_t encrypt_buffer[1000]; 3517 uint8_t decrypt_buffer[1000]; 3518 uint32_t bytes_encrypted; 3519 uint32_t bytes_decrypted; 3520 3521 printbuf((const uint8_t *)data, strlen((const char *)data), "input data"); 3522 3523 lanplus_encrypt_aes_cbc_128(iv, 3524 key, 3525 data, 3526 strlen((const char *)data), 3527 encrypt_buffer, 3528 &bytes_encrypted); 3529 printbuf((const uint8_t *)encrypt_buffer, bytes_encrypted, "encrypt_buffer"); 3530 3531 lanplus_decrypt_aes_cbc_128(iv, 3532 key, 3533 encrypt_buffer, 3534 bytes_encrypted, 3535 decrypt_buffer, 3536 &bytes_decrypted); 3537 printbuf((const uint8_t *)decrypt_buffer, bytes_decrypted, "decrypt_buffer"); 3538 3539 lprintf(LOG_INFO, "\nDone testing the encrypt/decyrpt methods!\n"); 3540 exit(0); 3541 } 3542 3543 3544 /** 3545 * send a get device id command to keep session active 3546 */ 3547 static int 3548 ipmi_lanplus_keepalive(struct ipmi_intf * intf) 3549 { 3550 struct ipmi_rs * rsp; 3551 struct ipmi_rq req = { msg: { 3552 netfn: IPMI_NETFN_APP, 3553 cmd: 1, 3554 }}; 3555 3556 if (!intf->opened) 3557 return 0; 3558 3559 rsp = intf->sendrecv(intf, &req); 3560 while (rsp != NULL && is_sol_packet(rsp)) { 3561 /* rsp was SOL data instead of our answer */ 3562 /* since it didn't go through the sol recv, do sol recv stuff here */ 3563 ack_sol_packet(intf, rsp); 3564 check_sol_packet_for_new_data(intf, rsp); 3565 if (rsp->data_len) 3566 intf->session->sol_data.sol_input_handler(rsp); 3567 rsp = ipmi_lan_poll_recv(intf); 3568 if (rsp == NULL) /* the get device id answer never got back, but retry mechanism was bypassed by SOL data */ 3569 return 0; /* so get device id command never returned, the connection is still alive */ 3570 } 3571 3572 if (rsp == NULL) 3573 return -1; 3574 if (rsp->ccode > 0) 3575 return -1; 3576 3577 return 0; 3578 } 3579 3580 3581 /** 3582 * ipmi_lanplus_setup 3583 */ 3584 static int ipmi_lanplus_setup(struct ipmi_intf * intf) 3585 { 3586 //test_crypt1(); 3587 assert("ipmi_lanplus_setup"); 3588 3589 if (lanplus_seed_prng(16)) 3590 return -1; 3591 3592 intf->session = malloc(sizeof(struct ipmi_session)); 3593 if (intf->session == NULL) { 3594 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3595 return -1; 3596 } 3597 memset(intf->session, 0, sizeof(struct ipmi_session)); 3598 return 0; 3599 } 3600