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