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