1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <assert.h> 29 #include <inttypes.h> 30 #include <string.h> 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 #include <netinet/in.h> 34 #include <arpa/inet.h> 35 #include <errno.h> 36 #include <unistd.h> 37 #include <netdb.h> 38 #include <fcntl.h> 39 40 #include "libipmi.h" 41 #include "ipmi_lan.h" 42 #include "ipmi_impl.h" 43 44 #define DEF_IPMI_LAN_TIMEOUT 3 /* seconds */ 45 #define DEF_IPMI_LAN_NUM_RETRIES 5 46 #define IPMI_LAN_CHANNEL_E 0x0e 47 48 typedef struct ipmi_rs { 49 uint8_t ir_data[IPMI_BUF_SIZE]; 50 int ir_dlen; 51 ipmi_msg_hdr_t ir_ihdr; 52 uint8_t ir_ccode; 53 } ipmi_rs_t; 54 55 static ipmi_rs_t *ipmi_lan_poll_recv(ipmi_handle_t *); 56 57 typedef struct ipmi_rq_entry { 58 ipmi_list_t ire_list; 59 ipmi_cmd_t ire_req; 60 uint8_t ire_target_cmd; 61 uint8_t ire_rq_seq; 62 uint8_t *ire_msg_data; 63 int ire_msg_len; 64 } ipmi_rq_entry_t; 65 66 ipmi_rq_entry_t *ipmi_req_entries = NULL; 67 68 /* 69 * LAN transport-specific data 70 */ 71 typedef struct ipmi_lan { 72 ipmi_handle_t *il_ihp; 73 char il_host[MAXHOSTNAMELEN + 1]; 74 uint16_t il_port; 75 char il_user[17]; 76 char il_authcode[IPMI_AUTHCODE_BUF_SIZE + 1]; 77 uint8_t il_challenge[16]; 78 uint32_t il_session_id; 79 int il_sd; 80 boolean_t il_send_authcode; 81 boolean_t il_session_active; 82 uint8_t il_authtype; 83 uint8_t il_privlvl; 84 uint8_t il_num_retries; 85 uint32_t il_in_seq; 86 uint32_t il_timeout; 87 struct sockaddr_in il_addr; 88 socklen_t il_addrlen; 89 } ipmi_lan_t; 90 91 /* 92 * Calculate and returns IPMI checksum 93 * 94 * Checksum algorithm is described in Section 13.8 95 * 96 * d: buffer to check 97 * s: position in buffer to start checksum from 98 */ 99 static uint8_t 100 ipmi_csum(uint8_t *d, int s) 101 { 102 uint8_t c = 0; 103 for (; s > 0; s--, d++) 104 c += *d; 105 return (-c); 106 } 107 108 static ipmi_rq_entry_t * 109 ipmi_req_add_entry(ipmi_handle_t *ihp, ipmi_cmd_t *req) 110 { 111 ipmi_rq_entry_t *e; 112 113 if ((e = ipmi_zalloc(ihp, sizeof (ipmi_rq_entry_t))) == NULL) 114 return (NULL); 115 116 (void) memcpy(&e->ire_req, req, sizeof (ipmi_cmd_t)); 117 ipmi_list_append(&ipmi_req_entries->ire_list, e); 118 119 return (e); 120 } 121 122 /*ARGSUSED*/ 123 static ipmi_rq_entry_t * 124 ipmi_req_lookup_entry(ipmi_handle_t *ihp, uint8_t seq, uint8_t cmd) 125 { 126 ipmi_rq_entry_t *e; 127 128 for (e = ipmi_list_next(&ipmi_req_entries->ire_list); e != NULL; 129 e = ipmi_list_next(e)) 130 if (e->ire_rq_seq == seq && e->ire_req.ic_cmd == cmd) 131 return (e); 132 133 return (NULL); 134 } 135 136 static void 137 ipmi_req_remove_entry(ipmi_handle_t *ihp, uint8_t seq, uint8_t cmd) 138 { 139 ipmi_rq_entry_t *e; 140 141 e = ipmi_req_lookup_entry(ihp, seq, cmd); 142 143 if (e) { 144 ipmi_list_delete(&ipmi_req_entries->ire_list, e); 145 ipmi_free(ihp, e->ire_msg_data); 146 ipmi_free(ihp, e); 147 } 148 } 149 150 static void 151 ipmi_req_clear_entries(ipmi_handle_t *ihp) 152 { 153 ipmi_rq_entry_t *e; 154 155 while ((e = ipmi_list_next(&ipmi_req_entries->ire_list)) != NULL) { 156 ipmi_list_delete(&ipmi_req_entries->ire_list, e); 157 ipmi_free(ihp, e); 158 } 159 } 160 161 static int 162 get_random(void *buf, uint_t len) 163 { 164 int fd; 165 166 assert(buf != NULL && len > 0); 167 if ((fd = open("/dev/urandom", O_RDONLY)) < 0) 168 return (-1); 169 170 if (read(fd, buf, len) < 0) { 171 (void) close(fd); 172 return (-1); 173 } 174 (void) close(fd); 175 return (0); 176 } 177 178 static int 179 ipmi_lan_send_packet(ipmi_handle_t *ihp, uint8_t *data, int dlen) 180 { 181 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 182 183 return (send(ilp->il_sd, data, dlen, 0)); 184 } 185 186 static ipmi_rs_t * 187 ipmi_lan_recv_packet(ipmi_handle_t *ihp) 188 { 189 static ipmi_rs_t rsp; 190 fd_set read_set, err_set; 191 struct timeval tmout; 192 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 193 int ret; 194 195 FD_ZERO(&read_set); 196 FD_SET(ilp->il_sd, &read_set); 197 198 FD_ZERO(&err_set); 199 FD_SET(ilp->il_sd, &err_set); 200 201 tmout.tv_sec = ilp->il_timeout; 202 tmout.tv_usec = 0; 203 204 ret = select(ilp->il_sd + 1, &read_set, NULL, &err_set, &tmout); 205 if (ret < 0 || FD_ISSET(ilp->il_sd, &err_set) || 206 !FD_ISSET(ilp->il_sd, &read_set)) 207 return (NULL); 208 209 /* 210 * The first read may return ECONNREFUSED because the rmcp ping 211 * packet--sent to UDP port 623--will be processed by both the 212 * BMC and the OS. 213 * 214 * The problem with this is that the ECONNREFUSED takes 215 * priority over any other received datagram; that means that 216 * the Connection Refused shows up _before_ the response packet, 217 * regardless of the order they were sent out. (unless the 218 * response is read before the connection refused is returned) 219 */ 220 ret = recv(ilp->il_sd, &rsp.ir_data, IPMI_BUF_SIZE, 0); 221 222 if (ret < 0) { 223 FD_ZERO(&read_set); 224 FD_SET(ilp->il_sd, &read_set); 225 226 FD_ZERO(&err_set); 227 FD_SET(ilp->il_sd, &err_set); 228 229 tmout.tv_sec = ilp->il_timeout; 230 tmout.tv_usec = 0; 231 232 ret = select(ilp->il_sd + 1, &read_set, NULL, &err_set, &tmout); 233 if (ret < 0) { 234 if (FD_ISSET(ilp->il_sd, &err_set) || 235 !FD_ISSET(ilp->il_sd, &read_set)) 236 return (NULL); 237 238 ret = recv(ilp->il_sd, &rsp.ir_data, IPMI_BUF_SIZE, 0); 239 if (ret < 0) 240 return (NULL); 241 } 242 } 243 244 if (ret == 0) 245 return (NULL); 246 247 rsp.ir_data[ret] = '\0'; 248 rsp.ir_dlen = ret; 249 250 return (&rsp); 251 } 252 253 254 /* 255 * ASF/RMCP Pong Message 256 * 257 * See section 13.2.4 258 */ 259 struct rmcp_pong { 260 rmcp_hdr_t rp_rmcp; 261 asf_hdr_t rp_asf; 262 uint32_t rp_iana; 263 uint32_t rp_oem; 264 uint8_t rp_sup_entities; 265 uint8_t rp_sup_interact; 266 uint8_t rp_reserved[6]; 267 }; 268 269 /* 270 * parse response RMCP "pong" packet 271 * 272 * return -1 if ping response not received 273 * returns 0 if IPMI is NOT supported 274 * returns 1 if IPMI is supported 275 */ 276 /*ARGSUSED*/ 277 static int 278 ipmi_handle_pong(ipmi_handle_t *ihp, ipmi_rs_t *rsp) 279 { 280 struct rmcp_pong *pong; 281 282 if (rsp == NULL) 283 return (-1); 284 285 /*LINTED: E_BAD_PTR_CAST_ALIGN*/ 286 pong = (struct rmcp_pong *)rsp->ir_data; 287 288 return ((pong->rp_sup_entities & 0x80) ? 1 : 0); 289 } 290 291 /* 292 * Build and send RMCP presence ping message 293 */ 294 static int 295 ipmi_lan_ping(ipmi_handle_t *ihp) 296 { 297 rmcp_hdr_t rmcp_ping; 298 asf_hdr_t asf_ping; 299 uint8_t *data; 300 int rv, dlen = sizeof (rmcp_ping) + sizeof (asf_ping); 301 302 (void) memset(&rmcp_ping, 0, sizeof (rmcp_ping)); 303 rmcp_ping.rh_version = RMCP_VERSION_1; 304 rmcp_ping.rh_msg_class = RMCP_CLASS_ASF; 305 rmcp_ping.rh_seq = 0xff; 306 307 (void) memset(&asf_ping, 0, sizeof (asf_ping)); 308 asf_ping.ah_iana = htonl(ASF_RMCP_IANA); 309 asf_ping.ah_msg_type = ASF_TYPE_PING; 310 311 if ((data = ipmi_zalloc(ihp, dlen)) == NULL) 312 return (-1); 313 314 (void) memcpy(data, &rmcp_ping, sizeof (rmcp_ping)); 315 (void) memcpy(data + sizeof (rmcp_ping), &asf_ping, sizeof (asf_ping)); 316 317 rv = ipmi_lan_send_packet(ihp, data, dlen); 318 319 ipmi_free(ihp, data); 320 321 if (rv < 0) 322 return (ipmi_set_error(ihp, EIPMI_LAN_PING_FAILED, NULL)); 323 324 if (ipmi_lan_poll_recv(ihp) == NULL) 325 return (ipmi_set_error(ihp, EIPMI_LAN_PING_FAILED, NULL)); 326 327 return (0); 328 } 329 330 static ipmi_rs_t * 331 ipmi_lan_poll_recv(ipmi_handle_t *ihp) 332 { 333 rmcp_hdr_t rmcp_rsp; 334 ipmi_rs_t *rsp; 335 ipmi_rq_entry_t *entry; 336 int off = 0, rv; 337 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 338 uint8_t rsp_authtype; 339 340 rsp = ipmi_lan_recv_packet(ihp); 341 342 while (rsp != NULL) { 343 344 /* parse response headers */ 345 (void) memcpy(&rmcp_rsp, rsp->ir_data, 4); 346 347 switch (rmcp_rsp.rh_msg_class) { 348 case RMCP_CLASS_ASF: 349 /* ping response packet */ 350 rv = ipmi_handle_pong(ihp, rsp); 351 return ((rv <= 0) ? NULL : rsp); 352 case RMCP_CLASS_IPMI: 353 /* handled by rest of function */ 354 break; 355 default: 356 /* Invalid RMCP class */ 357 rsp = ipmi_lan_recv_packet(ihp); 358 continue; 359 } 360 361 off = sizeof (rmcp_hdr_t); 362 rsp_authtype = rsp->ir_data[off]; 363 if (ilp->il_send_authcode && (rsp_authtype || ilp->il_authtype)) 364 off += 26; 365 else 366 off += 10; 367 368 (void) memcpy(&rsp->ir_ihdr, (void *)(rsp->ir_data + off), 369 sizeof (rsp->ir_ihdr)); 370 rsp->ir_ihdr.imh_seq = rsp->ir_ihdr.imh_seq >> 2; 371 off += sizeof (rsp->ir_ihdr); 372 rsp->ir_ccode = rsp->ir_data[off++]; 373 374 entry = ipmi_req_lookup_entry(ihp, rsp->ir_ihdr.imh_seq, 375 rsp->ir_ihdr.imh_cmd); 376 if (entry) { 377 ipmi_req_remove_entry(ihp, rsp->ir_ihdr.imh_seq, 378 rsp->ir_ihdr.imh_cmd); 379 } else { 380 rsp = ipmi_lan_recv_packet(ihp); 381 continue; 382 } 383 break; 384 } 385 386 /* shift response data to start of array */ 387 if (rsp && rsp->ir_dlen > off) { 388 rsp->ir_dlen -= off + 1; 389 (void) memmove(rsp->ir_data, rsp->ir_data + off, rsp->ir_dlen); 390 (void) memset(rsp->ir_data + rsp->ir_dlen, 0, 391 IPMI_BUF_SIZE - rsp->ir_dlen); 392 } 393 return (rsp); 394 } 395 396 /* 397 * IPMI LAN Request Message Format 398 * 399 * See section 13.8 400 * 401 * +---------------------+ 402 * | rmcp_hdr_t | 4 bytes 403 * +---------------------+ 404 * | v15_session_hdr_t | 9 bytes 405 * +---------------------+ 406 * | [authcode] | 16 bytes (if AUTHTYPE != none) 407 * +---------------------+ 408 * | msg length | 1 byte 409 * +---------------------+ 410 * | ipmi_msg_hdr_t | 6 bytes 411 * +---------------------+ 412 * | [msg data] | variable 413 * +---------------------+ 414 * | msg data checksum | 1 byte 415 * +---------------------+ 416 */ 417 static ipmi_rq_entry_t * 418 ipmi_lan_build_cmd(ipmi_handle_t *ihp, ipmi_cmd_t *req) 419 { 420 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 421 rmcp_hdr_t rmcp_hdr; 422 v15_session_hdr_t session_hdr; 423 ipmi_msg_hdr_t msg_hdr; 424 uint8_t *msg; 425 int cs, tmp, off = 0, len; 426 ipmi_rq_entry_t *entry; 427 static int curr_seq = 0; 428 429 if (curr_seq >= 64) 430 curr_seq = 0; 431 432 if ((entry = ipmi_req_add_entry(ihp, req)) == NULL) 433 return (NULL); 434 435 len = req->ic_dlen + 29; 436 if (ilp->il_send_authcode && ilp->il_authtype) 437 len += 16; 438 439 if ((msg = ipmi_zalloc(ihp, len)) == NULL) 440 /* ipmi_errno set */ 441 return (NULL); 442 443 /* RMCP header */ 444 (void) memset(&rmcp_hdr, 0, sizeof (rmcp_hdr)); 445 rmcp_hdr.rh_version = RMCP_VERSION_1; 446 rmcp_hdr.rh_msg_class = RMCP_CLASS_IPMI; 447 rmcp_hdr.rh_seq = 0xff; 448 (void) memcpy(msg, &rmcp_hdr, sizeof (rmcp_hdr)); 449 off = sizeof (rmcp_hdr); 450 451 /* IPMI session header */ 452 (void) memset(&session_hdr, 0, sizeof (session_hdr)); 453 if (! ilp->il_send_authcode) 454 session_hdr.sh_authtype = 0x00; 455 else 456 /* hardcode passwd authentication */ 457 session_hdr.sh_authtype = 0x04; 458 459 (void) memcpy(&session_hdr.sh_seq, &ilp->il_in_seq, sizeof (uint32_t)); 460 (void) memcpy(&session_hdr.sh_id, &ilp->il_session_id, 461 sizeof (uint32_t)); 462 463 (void) memcpy(msg + off, &session_hdr, sizeof (session_hdr)); 464 off += sizeof (session_hdr); 465 466 /* IPMI session authcode */ 467 if (ilp->il_send_authcode && ilp->il_authtype) { 468 (void) memcpy(msg + off, ilp->il_authcode, 16); 469 off += 16; 470 } 471 472 /* message length */ 473 msg[off++] = req->ic_dlen + 7; 474 cs = off; 475 476 /* IPMI message header */ 477 (void) memset(&msg_hdr, 0, sizeof (msg_hdr)); 478 msg_hdr.imh_addr1 = IPMI_BMC_SLAVE_ADDR; 479 msg_hdr.imh_lun = req->ic_lun; 480 msg_hdr.imh_netfn = req->ic_netfn; 481 tmp = off - cs; 482 msg_hdr.imh_csum = ipmi_csum(msg + cs, tmp); 483 cs = off; 484 msg_hdr.imh_addr2 = IPMI_BMC_SLAVE_ADDR; 485 entry->ire_rq_seq = curr_seq++; 486 msg_hdr.imh_seq = entry->ire_rq_seq << 2; 487 msg_hdr.imh_cmd = req->ic_cmd; 488 (void) memcpy(msg + off, &msg_hdr, sizeof (msg_hdr)); 489 off += sizeof (msg_hdr); 490 491 /* message data */ 492 if (req->ic_dlen != 0) { 493 (void) memcpy(msg + off, req->ic_data, req->ic_dlen); 494 off += req->ic_dlen; 495 } 496 497 /* message data checksum */ 498 tmp = off - cs; 499 msg[off++] = ipmi_csum(msg + cs, tmp); 500 501 if (ilp->il_in_seq) { 502 ilp->il_in_seq++; 503 if (ilp->il_in_seq == 0) 504 ilp->il_in_seq++; 505 } 506 507 entry->ire_msg_len = off; 508 entry->ire_msg_data = msg; 509 510 return (entry); 511 } 512 513 static int 514 ipmi_lan_send(void *data, ipmi_cmd_t *cmd, ipmi_cmd_t *response, 515 int *completion) 516 { 517 ipmi_lan_t *ilp = (ipmi_lan_t *)data; 518 ipmi_rq_entry_t *entry = NULL; 519 ipmi_rs_t *rsp = NULL; 520 uint_t try = 0; 521 522 for (;;) { 523 if ((entry = ipmi_lan_build_cmd(ilp->il_ihp, cmd)) == NULL) 524 return (-1); 525 526 if (ipmi_lan_send_packet(ilp->il_ihp, entry->ire_msg_data, 527 entry->ire_msg_len) < 0) { 528 if (++try >= ilp->il_num_retries) 529 return (-1); 530 (void) usleep(5000); 531 continue; 532 } 533 534 (void) usleep(100); 535 536 if ((rsp = ipmi_lan_poll_recv(ilp->il_ihp)) != NULL) 537 break; 538 539 (void) usleep(5000); 540 ipmi_req_remove_entry(ilp->il_ihp, entry->ire_rq_seq, 541 entry->ire_req.ic_cmd); 542 543 if (++try >= ilp->il_num_retries) 544 return (-1); 545 } 546 response->ic_netfn = rsp->ir_ihdr.imh_netfn; 547 response->ic_lun = rsp->ir_ihdr.imh_lun; 548 response->ic_cmd = rsp->ir_ihdr.imh_cmd; 549 if (rsp->ir_ccode != 0) { 550 *completion = rsp->ir_ccode; 551 response->ic_dlen = 0; 552 response->ic_data = NULL; 553 } else { 554 *completion = 0; 555 response->ic_dlen = rsp->ir_dlen; 556 response->ic_data = rsp->ir_data; 557 } 558 return (0); 559 } 560 561 /* 562 * IPMI Get Session Challenge Command 563 * 564 * Copies the returned session ID and 16-byte challenge string to the supplied 565 * buffers 566 * 567 * See section 22.16 568 */ 569 static int 570 ipmi_get_session_challenge_cmd(ipmi_handle_t *ihp, uint32_t *session_id, 571 uint8_t *challenge) 572 { 573 ipmi_cmd_t cmd, resp; 574 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 575 char msg_data[17]; 576 int ccode; 577 578 (void) memset(msg_data, 0, 17); 579 580 switch (ilp->il_authtype) { 581 case IPMI_SESSION_AUTHTYPE_NONE: 582 msg_data[0] = 0x00; 583 break; 584 case IPMI_SESSION_AUTHTYPE_MD2: 585 msg_data[0] = 0x01; 586 break; 587 case IPMI_SESSION_AUTHTYPE_MD5: 588 msg_data[0] = 0x02; 589 break; 590 case IPMI_SESSION_AUTHTYPE_PASSWORD: 591 msg_data[0] = 0x04; 592 break; 593 case IPMI_SESSION_AUTHTYPE_OEM: 594 msg_data[0] = 0x05; 595 break; 596 } 597 (void) memcpy(msg_data + 1, ilp->il_user, 16); 598 599 cmd.ic_netfn = IPMI_NETFN_APP; 600 cmd.ic_lun = 0; 601 cmd.ic_cmd = IPMI_CMD_GET_SESSION_CHALLENGE; 602 cmd.ic_data = msg_data; 603 cmd.ic_dlen = 17; 604 605 if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0 || ccode) 606 return (ipmi_set_error(ihp, EIPMI_LAN_CHALLENGE, NULL)); 607 608 (void) memcpy(session_id, resp.ic_data, 4); 609 (void) memcpy(challenge, (uint8_t *)resp.ic_data + 4, 16); 610 611 return (0); 612 } 613 614 /* 615 * IPMI Activate Session Command 616 * 617 * See section 22.17 618 */ 619 static int 620 ipmi_activate_session_cmd(ipmi_handle_t *ihp) 621 { 622 ipmi_cmd_t cmd, resp; 623 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 624 uint8_t msg_data[22], *resp_data; 625 int ccode; 626 627 cmd.ic_netfn = IPMI_NETFN_APP; 628 cmd.ic_lun = 0; 629 cmd.ic_cmd = IPMI_CMD_ACTIVATE_SESSION; 630 631 switch (ilp->il_authtype) { 632 case IPMI_SESSION_AUTHTYPE_NONE: 633 msg_data[0] = 0x00; 634 break; 635 case IPMI_SESSION_AUTHTYPE_MD2: 636 msg_data[0] = 0x01; 637 break; 638 case IPMI_SESSION_AUTHTYPE_MD5: 639 msg_data[0] = 0x02; 640 break; 641 case IPMI_SESSION_AUTHTYPE_PASSWORD: 642 msg_data[0] = 0x04; 643 break; 644 case IPMI_SESSION_AUTHTYPE_OEM: 645 msg_data[0] = 0x05; 646 break; 647 } 648 msg_data[1] = ilp->il_privlvl; 649 650 (void) memcpy(msg_data + 2, ilp->il_challenge, 16); 651 652 /* setup initial outbound sequence number */ 653 (void) get_random(msg_data + 18, 4); 654 655 cmd.ic_data = msg_data; 656 cmd.ic_dlen = 22; 657 658 ilp->il_send_authcode = B_TRUE; 659 660 if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0 || ccode) { 661 ilp->il_send_authcode = B_FALSE; 662 return (ipmi_set_error(ihp, EIPMI_LAN_SESSION, NULL)); 663 } 664 665 resp_data = (uint8_t *)resp.ic_data; 666 (void) memcpy(&ilp->il_session_id, resp_data + 1, 4); 667 ilp->il_in_seq = resp_data[8] << 24 | resp_data[7] << 16 | 668 resp_data[6] << 8 | resp_data[5]; 669 if (ilp->il_in_seq == 0) 670 ++ilp->il_in_seq; 671 672 return (0); 673 } 674 675 676 /* 677 * See section 22.18 678 * 679 * returns privilege level or -1 on error 680 */ 681 static int 682 ipmi_set_session_privlvl_cmd(ipmi_handle_t *ihp, uint8_t privlvl) 683 { 684 ipmi_cmd_t cmd, resp; 685 int ret = 0, ccode; 686 687 if (privlvl > IPMI_SESSION_PRIV_OEM) 688 return (ipmi_set_error(ihp, EIPMI_BADPARAM, NULL)); 689 690 cmd.ic_netfn = IPMI_NETFN_APP; 691 cmd.ic_lun = 0; 692 cmd.ic_cmd = IPMI_CMD_SET_SESSION_PRIVLVL; 693 cmd.ic_data = &privlvl; 694 cmd.ic_dlen = 1; 695 696 if (ipmi_lan_send(ihp->ih_tdata, &cmd, &resp, &ccode) != 0) 697 ret = ipmi_set_error(ihp, EIPMI_LAN_SETPRIV, NULL); 698 699 return (ret); 700 } 701 702 /* 703 * See section 22.19 704 */ 705 static int 706 ipmi_close_session_cmd(ipmi_handle_t *ihp) 707 { 708 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 709 ipmi_cmd_t cmd, resp; 710 uint8_t msg_data[4]; 711 int ret = 0, ccode; 712 713 if (! ilp->il_session_active) 714 return (-1); 715 716 (void) memcpy(&msg_data, &ilp->il_session_id, 4); 717 718 cmd.ic_netfn = IPMI_NETFN_APP; 719 cmd.ic_lun = 0; 720 cmd.ic_cmd = IPMI_CMD_CLOSE_SESSION; 721 cmd.ic_data = msg_data; 722 cmd.ic_dlen = 4; 723 724 if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0) 725 ret = -1; 726 727 return (ret); 728 } 729 730 /* 731 * IPMI LAN Session Activation 732 * 733 * See section 13.14 734 * 735 * 1. send "RMCP Presence Ping" message, response message will 736 * indicate whether the platform supports IPMI 737 * 2. send "Get Channel Authentication Capabilities" command 738 * with AUTHTYPE = none, response packet will contain information 739 * about supported challenge/response authentication types 740 * 3. send "Get Session Challenge" command with AUTHTYPE = none 741 * and indicate the authentication type in the message, response 742 * packet will contain challenge string and temporary session ID. 743 * 4. send "Activate Session" command, authenticated with AUTHTYPE 744 * sent in previous message. Also sends the initial value for 745 * the outbound sequence number for BMC. 746 * 5. BMC returns response confirming session activation and 747 * session ID for this session and initial inbound sequence. 748 */ 749 static int 750 ipmi_lan_activate_session(ipmi_handle_t *ihp) 751 { 752 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata; 753 ipmi_channel_auth_caps_t *ac; 754 755 if (ipmi_lan_ping(ihp) != 0) 756 return (-1); 757 758 if ((ac = ipmi_get_channel_auth_caps(ihp, IPMI_LAN_CHANNEL_E, 759 ilp->il_privlvl)) == NULL) 760 return (-1); 761 762 /* 763 * For the sake of simplicity, we're just supporting basic password 764 * authentication. If this authentication type is not supported then 765 * we'll bail here. 766 */ 767 if (!(ac->cap_authtype & IPMI_SESSION_AUTHTYPE_PASSWORD)) { 768 free(ac); 769 return (ipmi_set_error(ihp, EIPMI_LAN_PASSWD_NOTSUP, NULL)); 770 } 771 free(ac); 772 773 if (ipmi_get_session_challenge_cmd(ihp, &ilp->il_session_id, 774 ilp->il_challenge) != 0) 775 return (-1); 776 777 if (ipmi_activate_session_cmd(ihp) != 0) 778 return (-1); 779 780 ilp->il_session_active = B_TRUE; 781 782 if (ipmi_set_session_privlvl_cmd(ihp, ilp->il_privlvl) != 0) 783 return (-1); 784 785 return (0); 786 } 787 788 static void 789 ipmi_lan_close(void *data) 790 { 791 ipmi_lan_t *ilp = (ipmi_lan_t *)data; 792 793 if (ilp->il_session_active) 794 (void) ipmi_close_session_cmd(ilp->il_ihp); 795 796 if (ilp->il_sd >= 0) 797 (void) close(ilp->il_sd); 798 799 ipmi_req_clear_entries(ilp->il_ihp); 800 ipmi_free(ilp->il_ihp, ipmi_req_entries); 801 ipmi_free(ilp->il_ihp, ilp); 802 } 803 804 static void * 805 ipmi_lan_open(ipmi_handle_t *ihp, nvlist_t *params) 806 { 807 int rc; 808 struct hostent *host; 809 ipmi_lan_t *ilp; 810 char *hostname, *user, *authcode; 811 812 if ((ilp = ipmi_zalloc(ihp, sizeof (ipmi_lan_t))) == NULL) { 813 /* ipmi errno set */ 814 return (NULL); 815 } 816 ilp->il_ihp = ihp; 817 ihp->ih_tdata = ilp; 818 819 /* 820 * Parse the parameters passed in the params nvlist. The following 821 * parameters are required 822 * IPMI_LAN_HOST, IPMI_LAN_USER and IPMI_LAN_PASSWD 823 * 824 * If any of these were not specified then we abort 825 */ 826 if (nvlist_lookup_string(params, IPMI_LAN_HOST, &hostname) || 827 nvlist_lookup_string(params, IPMI_LAN_USER, &user) || 828 nvlist_lookup_string(params, IPMI_LAN_PASSWD, &authcode)) { 829 ipmi_free(ihp, ilp); 830 (void) ipmi_set_error(ihp, EIPMI_BADPARAM, NULL); 831 return (NULL); 832 } 833 (void) strncpy(ilp->il_host, hostname, MAXHOSTNAMELEN); 834 (void) strncpy(ilp->il_user, user, 16); 835 (void) strncpy(ilp->il_authcode, authcode, 16); 836 837 /* 838 * IPMI_LAN_PORT is an optional parameter and defaults to port 623 839 * IPMI_LAN_PRIVLVL is also optional and defaults to admin 840 * IPMI_LAN_TIMEOUT is optional and will default to 3 seconds 841 * IPMI_LAN_NUM_RETIES is optional and will default to 5 842 */ 843 if (nvlist_lookup_uint16(params, IPMI_LAN_PORT, &ilp->il_port)) 844 ilp->il_port = RMCP_UDP_PORT; 845 846 if (nvlist_lookup_uint8(params, IPMI_LAN_PRIVLVL, &ilp->il_privlvl)) 847 ilp->il_privlvl = IPMI_SESSION_PRIV_ADMIN; 848 849 if (nvlist_lookup_uint32(params, IPMI_LAN_TIMEOUT, &ilp->il_timeout)) 850 ilp->il_timeout = DEF_IPMI_LAN_TIMEOUT; 851 852 if (nvlist_lookup_uint8(params, IPMI_LAN_NUM_RETRIES, 853 &ilp->il_num_retries)) 854 ilp->il_num_retries = DEF_IPMI_LAN_NUM_RETRIES; 855 856 ilp->il_authtype = IPMI_SESSION_AUTHTYPE_PASSWORD; 857 858 /* 859 * Open up and connect a UDP socket between us and the service 860 * processor 861 */ 862 ilp->il_addr.sin_family = AF_INET; 863 ilp->il_addr.sin_port = htons(ilp->il_port); 864 865 rc = inet_pton(AF_INET, (const char *)ilp->il_host, 866 &ilp->il_addr.sin_addr); 867 if (rc <= 0) { 868 if ((host = gethostbyname((const char *)ilp->il_host)) 869 == NULL) { 870 ipmi_free(ihp, ilp); 871 (void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL); 872 return (NULL); 873 } 874 ilp->il_addr.sin_family = host->h_addrtype; 875 (void) memcpy(&ilp->il_addr.sin_addr, host->h_addr, 876 host->h_length); 877 } 878 879 if ((ilp->il_sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 880 ipmi_free(ihp, ilp); 881 (void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL); 882 return (NULL); 883 } 884 if (connect(ilp->il_sd, (struct sockaddr *)&ilp->il_addr, 885 sizeof (struct sockaddr_in)) < 0) { 886 ipmi_lan_close(ilp); 887 (void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL); 888 return (NULL); 889 } 890 891 if ((ipmi_req_entries = ipmi_zalloc(ihp, sizeof (ipmi_rq_entry_t))) 892 == NULL) 893 return (NULL); 894 895 /* 896 * Finally we start up the IPMI LAN session 897 */ 898 if ((rc = ipmi_lan_activate_session(ihp)) < 0) { 899 ipmi_lan_close(ilp); 900 return (NULL); 901 } 902 903 return (ilp); 904 } 905 906 ipmi_transport_t ipmi_transport_lan = { 907 ipmi_lan_open, 908 ipmi_lan_close, 909 ipmi_lan_send 910 }; 911