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