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