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 365 if (!intf || intf->session == NULL) { 366 return -1; 367 } 368 369 session = intf->session; 370 371 if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) { 372 lprintf(LOG_ERR, "No hostname specified!"); 373 return -1; 374 } 375 376 /* open port to BMC */ 377 memset(&addr, 0, sizeof(addr)); 378 379 sprintf(service, "%d", session->port); 380 /* Obtain address(es) matching host/port */ 381 memset(&hints, 0, sizeof(hints)); 382 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 383 hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ 384 hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */ 385 hints.ai_protocol = IPPROTO_UDP; /* */ 386 387 if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) { 388 lprintf(LOG_ERR, "Address lookup for %s failed", 389 session->hostname); 390 return -1; 391 } 392 393 /* getaddrinfo() returns a list of address structures. 394 * Try each address until we successfully connect(2). 395 * If socket(2) (or connect(2)) fails, we (close the socket 396 * and) try the next address. 397 */ 398 399 session->ai_family = AF_UNSPEC; 400 for (rp = rp0; rp != NULL; rp = rp->ai_next) { 401 /* We are only interested in IPv4 and IPv6 */ 402 if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) { 403 continue; 404 } 405 406 intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 407 if (intf->fd == -1) { 408 continue; 409 } 410 411 if (rp->ai_family == AF_INET) { 412 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 413 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 414 session->addrlen = rp->ai_addrlen; 415 session->ai_family = rp->ai_family; 416 break; /* Success */ 417 } 418 } else if (rp->ai_family == AF_INET6) { 419 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr; 420 char hbuf[NI_MAXHOST]; 421 socklen_t len; 422 423 /* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */ 424 if (addr6->sin6_scope_id != 0) { 425 len = sizeof(struct sockaddr_in6); 426 if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { 427 lprintf(LOG_DEBUG, "Trying address: %s scope=%d", 428 hbuf, 429 addr6->sin6_scope_id); 430 } 431 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 432 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 433 session->addrlen = rp->ai_addrlen; 434 session->ai_family = rp->ai_family; 435 break; /* Success */ 436 } 437 } else { 438 /* No scope specified, try to get this from the list of interfaces */ 439 struct ifaddrs *ifaddrs = NULL; 440 struct ifaddrs *ifa = NULL; 441 442 if (getifaddrs(&ifaddrs) < 0) { 443 lprintf(LOG_ERR, "Interface address lookup for %s failed", 444 session->hostname); 445 break; 446 } 447 448 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 449 if (ifa->ifa_addr == NULL) { 450 continue; 451 } 452 453 if (ifa->ifa_addr->sa_family == AF_INET6) { 454 struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr; 455 456 /* Skip unwanted addresses */ 457 if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) { 458 continue; 459 } 460 if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) { 461 continue; 462 } 463 len = sizeof(struct sockaddr_in6); 464 if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { 465 lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d", 466 ifa->ifa_name != NULL ? ifa->ifa_name : "???", 467 hbuf, 468 tmp6->sin6_scope_id); 469 } 470 471 if (tmp6->sin6_scope_id != 0) { 472 addr6->sin6_scope_id = tmp6->sin6_scope_id; 473 } else { 474 /* 475 * No scope information in interface address information 476 * On some OS'es, getifaddrs() is returning out the 'kernel' representation 477 * of scoped addresses which stores the scope in the 3rd and 4th 478 * byte. See also this page: 479 * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html 480 */ 481 if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr) 482 && (tmp6->sin6_addr.s6_addr[1] != 0)) { 483 addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr[1]); 484 } 485 } 486 487 /* OK, now try to connect with the scope id from this interface address */ 488 if (addr6->sin6_scope_id != 0) { 489 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 490 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 491 session->addrlen = rp->ai_addrlen; 492 session->ai_family = rp->ai_family; 493 lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id); 494 break; /* Success */ 495 } 496 } 497 } 498 } 499 freeifaddrs(ifaddrs); 500 } 501 } 502 if (session->ai_family != AF_UNSPEC) { 503 break; 504 } 505 close(intf->fd); 506 intf->fd = -1; 507 } 508 509 /* No longer needed */ 510 freeaddrinfo(rp0); 511 512 return ((intf->fd != -1) ? 0 : -1); 513 } 514 #endif 515 516 uint16_t 517 ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf) 518 { 519 int16_t size; 520 521 size = intf->max_request_data_size; 522 523 /* check if request size is not specified */ 524 if (!size) { 525 /* 526 * The IPMB standard overall message length for �non -bridging� 527 * messages is specified as 32 bytes, maximum, including slave 528 * address. This sets the upper limit for typical IPMI messages. 529 * With the exception of messages used for bridging messages to 530 * other busses or interfaces (e.g. Master Write-Read and Send Message) 531 * IPMI messages should be designed to fit within this 32-byte maximum. 532 * In order to support bridging, the Master Write -Read and Send Message 533 * commands are allowed to exceed the 32-byte maximum transaction on IPMB 534 */ 535 536 size = IPMI_DEFAULT_PAYLOAD_SIZE; 537 538 /* check if message is forwarded */ 539 if (intf->target_addr && intf->target_addr != intf->my_addr) { 540 /* add Send Message request size */ 541 size += 8; 542 } 543 } 544 545 /* check if message is forwarded */ 546 if (intf->target_addr && intf->target_addr != intf->my_addr) { 547 /* subtract send message request size */ 548 size -= 8; 549 550 /* 551 * Check that forwarded request size is not greater 552 * than the default payload size. 553 */ 554 if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { 555 size = IPMI_DEFAULT_PAYLOAD_SIZE; 556 } 557 558 /* check for double bridging */ 559 if (intf->transit_addr && intf->transit_addr != intf->target_addr) { 560 /* subtract inner send message request size */ 561 size -= 8; 562 } 563 } 564 565 /* check for underflow */ 566 if (size < 0) { 567 return 0; 568 } 569 570 return size; 571 } 572 573 uint16_t 574 ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf) 575 { 576 int16_t size; 577 578 size = intf->max_response_data_size; 579 580 /* check if response size is not specified */ 581 if (!size) { 582 /* 583 * The IPMB standard overall message length for �non -bridging� 584 * messages is specified as 32 bytes, maximum, including slave 585 * address. This sets the upper limit for typical IPMI messages. 586 * With the exception of messages used for bridging messages to 587 * other busses or interfaces (e.g. Master Write-Read and Send Message) 588 * IPMI messages should be designed to fit within this 32-byte maximum. 589 * In order to support bridging, the Master Write -Read and Send Message 590 * commands are allowed to exceed the 32-byte maximum transaction on IPMB 591 */ 592 593 size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */ 594 595 /* check if message is forwarded */ 596 if (intf->target_addr && intf->target_addr != intf->my_addr) { 597 /* add Send Message header size */ 598 size += 7; 599 } 600 } 601 602 /* check if message is forwarded */ 603 if (intf->target_addr && intf->target_addr != intf->my_addr) { 604 /* 605 * Some IPMI controllers like PICMG AMC Carriers embed responses 606 * to the forwarded messages into the Send Message response. 607 * In order to be sure that the response is not truncated, 608 * subtract the internal message header size. 609 */ 610 size -= 8; 611 612 /* 613 * Check that forwarded response is not greater 614 * than the default payload size. 615 */ 616 if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { 617 size = IPMI_DEFAULT_PAYLOAD_SIZE; 618 } 619 620 /* check for double bridging */ 621 if (intf->transit_addr && intf->transit_addr != intf->target_addr) { 622 /* subtract inner send message header size */ 623 size -= 8; 624 } 625 } 626 627 /* check for underflow */ 628 if (size < 0) { 629 return 0; 630 } 631 632 return size; 633 } 634 635 void 636 ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size) 637 { 638 if (size < IPMI_DEFAULT_PAYLOAD_SIZE) { 639 lprintf(LOG_ERR, "Request size is too small (%d), leave default size", 640 size); 641 return; 642 } 643 644 if (intf->set_max_request_data_size) { 645 intf->set_max_request_data_size(intf, size); 646 } else { 647 intf->max_request_data_size = size; 648 } 649 } 650 651 void 652 ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size) 653 { 654 if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) { 655 lprintf(LOG_ERR, "Response size is too small (%d), leave default size", 656 size); 657 return; 658 } 659 660 if (intf->set_max_response_data_size) { 661 intf->set_max_response_data_size(intf, size); 662 } else { 663 intf->max_response_data_size = size; 664 } 665 } 666