1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * Redistribution of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Neither the name of Sun Microsystems, Inc. or the names of 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * This software is provided "AS IS," without a warranty of any kind. 20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #if defined(HAVE_CONFIG_H) 37 # include <config.h> 38 #endif 39 40 #if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS) 41 #include <sys/types.h> 42 #include <sys/socket.h> 43 #include <netinet/in.h> 44 #include <arpa/inet.h> 45 #include <ifaddrs.h> 46 #include <unistd.h> 47 #include <netdb.h> 48 #endif 49 50 51 #include <ipmitool/ipmi_intf.h> 52 #include <ipmitool/ipmi.h> 53 #include <ipmitool/ipmi_sdr.h> 54 #include <ipmitool/log.h> 55 56 #define IPMI_DEFAULT_PAYLOAD_SIZE 25 57 58 #ifdef IPMI_INTF_OPEN 59 extern struct ipmi_intf ipmi_open_intf; 60 #endif 61 #ifdef IPMI_INTF_IMB 62 extern struct ipmi_intf ipmi_imb_intf; 63 #endif 64 #ifdef IPMI_INTF_LIPMI 65 extern struct ipmi_intf ipmi_lipmi_intf; 66 #endif 67 #ifdef IPMI_INTF_BMC 68 extern struct ipmi_intf ipmi_bmc_intf; 69 #endif 70 #ifdef IPMI_INTF_LAN 71 extern struct ipmi_intf ipmi_lan_intf; 72 #endif 73 #ifdef IPMI_INTF_LANPLUS 74 extern struct ipmi_intf ipmi_lanplus_intf; 75 #endif 76 #ifdef IPMI_INTF_FREE 77 extern struct ipmi_intf ipmi_free_intf; 78 #endif 79 #ifdef IPMI_INTF_SERIAL 80 extern struct ipmi_intf ipmi_serial_term_intf; 81 extern struct ipmi_intf ipmi_serial_bm_intf; 82 #endif 83 #ifdef IPMI_INTF_DUMMY 84 extern struct ipmi_intf ipmi_dummy_intf; 85 #endif 86 87 struct ipmi_intf * ipmi_intf_table[] = { 88 #ifdef IPMI_INTF_OPEN 89 &ipmi_open_intf, 90 #endif 91 #ifdef IPMI_INTF_IMB 92 &ipmi_imb_intf, 93 #endif 94 #ifdef IPMI_INTF_LIPMI 95 &ipmi_lipmi_intf, 96 #endif 97 #ifdef IPMI_INTF_BMC 98 &ipmi_bmc_intf, 99 #endif 100 #ifdef IPMI_INTF_LAN 101 &ipmi_lan_intf, 102 #endif 103 #ifdef IPMI_INTF_LANPLUS 104 &ipmi_lanplus_intf, 105 #endif 106 #ifdef IPMI_INTF_FREE 107 &ipmi_free_intf, 108 #endif 109 #ifdef IPMI_INTF_SERIAL 110 &ipmi_serial_term_intf, 111 &ipmi_serial_bm_intf, 112 #endif 113 #ifdef IPMI_INTF_DUMMY 114 &ipmi_dummy_intf, 115 #endif 116 NULL 117 }; 118 119 /* ipmi_intf_print - Print list of interfaces 120 * 121 * no meaningful return code 122 */ 123 void ipmi_intf_print(struct ipmi_intf_support * intflist) 124 { 125 struct ipmi_intf ** intf; 126 struct ipmi_intf_support * sup; 127 int def = 1; 128 int found; 129 130 lprintf(LOG_NOTICE, "Interfaces:"); 131 132 for (intf = ipmi_intf_table; intf && *intf; intf++) { 133 134 if (intflist != NULL) { 135 found = 0; 136 for (sup=intflist; sup->name != NULL; sup++) { 137 if (strncmp(sup->name, (*intf)->name, strlen(sup->name)) == 0 && 138 strncmp(sup->name, (*intf)->name, strlen((*intf)->name)) == 0 && 139 sup->supported == 1) 140 found = 1; 141 } 142 if (found == 0) 143 continue; 144 } 145 146 lprintf(LOG_NOTICE, "\t%-12s %s %s", 147 (*intf)->name, (*intf)->desc, 148 def ? "[default]" : ""); 149 def = 0; 150 } 151 lprintf(LOG_NOTICE, ""); 152 } 153 154 /* ipmi_intf_load - Load an interface from the interface table above 155 * If no interface name is given return first entry 156 * 157 * @name: interface name to try and load 158 * 159 * returns pointer to inteface structure if found 160 * returns NULL on error 161 */ 162 struct ipmi_intf * ipmi_intf_load(char * name) 163 { 164 struct ipmi_intf ** intf; 165 struct ipmi_intf * i; 166 167 if (name == NULL) { 168 i = ipmi_intf_table[0]; 169 if (i->setup != NULL && (i->setup(i) < 0)) { 170 lprintf(LOG_ERR, "Unable to setup " 171 "interface %s", name); 172 return NULL; 173 } 174 return i; 175 } 176 177 for (intf = ipmi_intf_table; 178 ((intf != NULL) && (*intf != NULL)); 179 intf++) { 180 i = *intf; 181 if (strncmp(name, i->name, strlen(name)) == 0) { 182 if (i->setup != NULL && (i->setup(i) < 0)) { 183 lprintf(LOG_ERR, "Unable to setup " 184 "interface %s", name); 185 return NULL; 186 } 187 return i; 188 } 189 } 190 191 return NULL; 192 } 193 194 void 195 ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname) 196 { 197 if (intf->session == NULL || hostname == NULL) { 198 return; 199 } 200 if (intf->session->hostname != NULL) { 201 free(intf->session->hostname); 202 intf->session->hostname = NULL; 203 } 204 intf->session->hostname = strdup(hostname); 205 } 206 207 void 208 ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username) 209 { 210 if (intf->session == NULL) 211 return; 212 213 memset(intf->session->username, 0, 17); 214 215 if (username == NULL) 216 return; 217 218 memcpy(intf->session->username, username, __min(strlen(username), 16)); 219 } 220 221 void 222 ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password) 223 { 224 if (intf->session == NULL) 225 return; 226 227 memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE); 228 229 if (password == NULL) { 230 intf->session->password = 0; 231 return; 232 } 233 234 intf->session->password = 1; 235 memcpy(intf->session->authcode, password, 236 __min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE)); 237 } 238 239 void 240 ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level) 241 { 242 if (intf->session == NULL) 243 return; 244 245 intf->session->privlvl = level; 246 } 247 248 void 249 ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit) 250 { 251 if (intf->session == NULL) 252 return; 253 254 intf->session->v2_data.lookupbit = lookupbit; 255 } 256 257 void 258 ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id) 259 { 260 if (intf->session == NULL) 261 return; 262 263 intf->session->cipher_suite_id = cipher_suite_id; 264 } 265 266 void 267 ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char) 268 { 269 if (intf->session == NULL) 270 return; 271 272 intf->session->sol_escape_char = sol_escape_char; 273 } 274 275 void 276 ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey) 277 { 278 if (intf->session == NULL) 279 return; 280 281 memset(intf->session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); 282 283 if (kgkey == NULL) 284 return; 285 286 memcpy(intf->session->v2_data.kg, kgkey, 287 __min(strlen(kgkey), IPMI_KG_BUFFER_SIZE)); 288 } 289 290 void 291 ipmi_intf_session_set_port(struct ipmi_intf * intf, int port) 292 { 293 if (intf->session == NULL) 294 return; 295 296 intf->session->port = port; 297 } 298 299 void 300 ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype) 301 { 302 if (intf->session == NULL) 303 return; 304 305 /* clear password field if authtype NONE specified */ 306 if (authtype == IPMI_SESSION_AUTHTYPE_NONE) { 307 memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE); 308 intf->session->password = 0; 309 } 310 311 intf->session->authtype_set = authtype; 312 } 313 314 void 315 ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout) 316 { 317 if (intf->session == NULL) 318 return; 319 320 intf->session->timeout = timeout; 321 } 322 323 void 324 ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry) 325 { 326 if (intf->session == NULL) 327 return; 328 329 intf->session->retry = retry; 330 } 331 332 void 333 ipmi_intf_session_cleanup(struct ipmi_intf *intf) 334 { 335 if (intf->session == NULL) { 336 return; 337 } 338 if (intf->session->hostname != NULL) { 339 free(intf->session->hostname); 340 intf->session->hostname = NULL; 341 } 342 free(intf->session); 343 intf->session = NULL; 344 } 345 346 void 347 ipmi_cleanup(struct ipmi_intf * intf) 348 { 349 ipmi_sdr_list_empty(intf); 350 } 351 352 #if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS) 353 int 354 ipmi_intf_socket_connect(struct ipmi_intf * intf) 355 { 356 struct ipmi_session *session; 357 358 struct sockaddr_storage addr; 359 struct addrinfo hints; 360 struct addrinfo *rp0 = NULL, *rp; 361 char service[NI_MAXSERV]; 362 int rc; 363 364 if (!intf || intf->session == NULL) { 365 return -1; 366 } 367 368 session = intf->session; 369 370 if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) { 371 lprintf(LOG_ERR, "No hostname specified!"); 372 return -1; 373 } 374 375 /* open port to BMC */ 376 memset(&addr, 0, sizeof(addr)); 377 378 sprintf(service, "%d", session->port); 379 /* Obtain address(es) matching host/port */ 380 memset(&hints, 0, sizeof(hints)); 381 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 382 hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ 383 hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */ 384 hints.ai_protocol = IPPROTO_UDP; /* */ 385 386 if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) { 387 lprintf(LOG_ERR, "Address lookup for %s failed", 388 session->hostname); 389 return -1; 390 } 391 392 /* getaddrinfo() returns a list of address structures. 393 * Try each address until we successfully connect(2). 394 * If socket(2) (or connect(2)) fails, we (close the socket 395 * and) try the next address. 396 */ 397 398 session->ai_family = AF_UNSPEC; 399 for (rp = rp0; rp != NULL; rp = rp->ai_next) { 400 /* We are only interested in IPv4 and IPv6 */ 401 if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) { 402 continue; 403 } 404 405 intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 406 if (intf->fd == -1) { 407 continue; 408 } 409 410 if (rp->ai_family == AF_INET) { 411 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 412 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 413 session->addrlen = rp->ai_addrlen; 414 session->ai_family = rp->ai_family; 415 break; /* Success */ 416 } 417 } else if (rp->ai_family == AF_INET6) { 418 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr; 419 char hbuf[NI_MAXHOST]; 420 socklen_t len; 421 422 /* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */ 423 if (addr6->sin6_scope_id != 0) { 424 len = sizeof(struct sockaddr_in6); 425 if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { 426 lprintf(LOG_DEBUG, "Trying address: %s scope=%d", 427 hbuf, 428 addr6->sin6_scope_id); 429 } 430 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 431 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 432 session->addrlen = rp->ai_addrlen; 433 session->ai_family = rp->ai_family; 434 break; /* Success */ 435 } 436 } else { 437 /* No scope specified, try to get this from the list of interfaces */ 438 struct ifaddrs *ifaddrs = NULL; 439 struct ifaddrs *ifa = NULL; 440 441 if (getifaddrs(&ifaddrs) < 0) { 442 lprintf(LOG_ERR, "Interface address lookup for %s failed", 443 session->hostname); 444 break; 445 } 446 447 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 448 if (ifa->ifa_addr == NULL) { 449 continue; 450 } 451 452 if (ifa->ifa_addr->sa_family == AF_INET6) { 453 struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr; 454 455 /* Skip unwanted addresses */ 456 if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) { 457 continue; 458 } 459 if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) { 460 continue; 461 } 462 len = sizeof(struct sockaddr_in6); 463 if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { 464 lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d", 465 ifa->ifa_name != NULL ? ifa->ifa_name : "???", 466 hbuf, 467 tmp6->sin6_scope_id); 468 } 469 470 if (tmp6->sin6_scope_id != 0) { 471 addr6->sin6_scope_id = tmp6->sin6_scope_id; 472 } else { 473 /* 474 * No scope information in interface address information 475 * On some OS'es, getifaddrs() is returning out the 'kernel' representation 476 * of scoped addresses which stores the scope in the 3rd and 4th 477 * byte. See also this page: 478 * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html 479 */ 480 if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr) 481 && (tmp6->sin6_addr.s6_addr16[1] != 0)) { 482 addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr16[1]); 483 } 484 } 485 486 /* OK, now try to connect with the scope id from this interface address */ 487 if (addr6->sin6_scope_id != 0) { 488 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 489 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 490 session->addrlen = rp->ai_addrlen; 491 session->ai_family = rp->ai_family; 492 lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id); 493 break; /* Success */ 494 } 495 } 496 } 497 } 498 freeifaddrs(ifaddrs); 499 } 500 } 501 if (session->ai_family != AF_UNSPEC) { 502 break; 503 } 504 close(intf->fd); 505 intf->fd = -1; 506 } 507 508 /* No longer needed */ 509 freeaddrinfo(rp0); 510 511 return ((intf->fd != -1) ? 0 : -1); 512 } 513 #endif 514 515 uint16_t 516 ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf) 517 { 518 int16_t size; 519 520 size = intf->max_request_data_size; 521 522 /* check if request size is not specified */ 523 if (!size) { 524 /* 525 * The IPMB standard overall message length for �non -bridging� 526 * messages is specified as 32 bytes, maximum, including slave 527 * address. This sets the upper limit for typical IPMI messages. 528 * With the exception of messages used for bridging messages to 529 * other busses or interfaces (e.g. Master Write-Read and Send Message) 530 * IPMI messages should be designed to fit within this 32-byte maximum. 531 * In order to support bridging, the Master Write -Read and Send Message 532 * commands are allowed to exceed the 32-byte maximum transaction on IPMB 533 */ 534 535 size = IPMI_DEFAULT_PAYLOAD_SIZE; 536 537 /* check if message is forwarded */ 538 if (intf->target_addr && intf->target_addr != intf->my_addr) { 539 /* add Send Message request size */ 540 size += 8; 541 } 542 } 543 544 /* check if message is forwarded */ 545 if (intf->target_addr && intf->target_addr != intf->my_addr) { 546 /* subtract send message request size */ 547 size -= 8; 548 549 /* 550 * Check that forwarded request size is not greater 551 * than the default payload size. 552 */ 553 if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { 554 size = IPMI_DEFAULT_PAYLOAD_SIZE; 555 } 556 557 /* check for double bridging */ 558 if (intf->transit_addr && intf->transit_addr != intf->target_addr) { 559 /* subtract inner send message request size */ 560 size -= 8; 561 } 562 } 563 564 /* check for underflow */ 565 if (size < 0) { 566 return 0; 567 } 568 569 return size; 570 } 571 572 uint16_t 573 ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf) 574 { 575 int16_t size; 576 577 size = intf->max_response_data_size; 578 579 /* check if response size is not specified */ 580 if (!size) { 581 /* 582 * The IPMB standard overall message length for �non -bridging� 583 * messages is specified as 32 bytes, maximum, including slave 584 * address. This sets the upper limit for typical IPMI messages. 585 * With the exception of messages used for bridging messages to 586 * other busses or interfaces (e.g. Master Write-Read and Send Message) 587 * IPMI messages should be designed to fit within this 32-byte maximum. 588 * In order to support bridging, the Master Write -Read and Send Message 589 * commands are allowed to exceed the 32-byte maximum transaction on IPMB 590 */ 591 592 size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */ 593 594 /* check if message is forwarded */ 595 if (intf->target_addr && intf->target_addr != intf->my_addr) { 596 /* add Send Message header size */ 597 size += 7; 598 } 599 } 600 601 /* check if message is forwarded */ 602 if (intf->target_addr && intf->target_addr != intf->my_addr) { 603 /* 604 * Some IPMI controllers like PICMG AMC Carriers embed responses 605 * to the forwarded messages into the Send Message response. 606 * In order to be sure that the response is not truncated, 607 * subtract the internal message header size. 608 */ 609 size -= 8; 610 611 /* 612 * Check that forwarded response is not greater 613 * than the default payload size. 614 */ 615 if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { 616 size = IPMI_DEFAULT_PAYLOAD_SIZE; 617 } 618 619 /* check for double bridging */ 620 if (intf->transit_addr && intf->transit_addr != intf->target_addr) { 621 /* subtract inner send message header size */ 622 size -= 8; 623 } 624 } 625 626 /* check for underflow */ 627 if (size < 0) { 628 return 0; 629 } 630 631 return size; 632 } 633 634 void 635 ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size) 636 { 637 if (size < IPMI_DEFAULT_PAYLOAD_SIZE) { 638 lprintf(LOG_ERR, "Request size is too small (%d), leave default size", 639 size); 640 return; 641 } 642 643 if (intf->set_max_request_data_size) { 644 intf->set_max_request_data_size(intf, size); 645 } else { 646 intf->max_request_data_size = size; 647 } 648 } 649 650 void 651 ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size) 652 { 653 if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) { 654 lprintf(LOG_ERR, "Response size is too small (%d), leave default size", 655 size); 656 return; 657 } 658 659 if (intf->set_max_response_data_size) { 660 intf->set_max_response_data_size(intf, size); 661 } else { 662 intf->max_response_data_size = size; 663 } 664 } 665