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) 198 return; 199 200 memset(intf->session->hostname, 0, 16); 201 202 if (hostname != NULL) { 203 memcpy(intf->session->hostname, hostname, 204 __min(strlen(hostname), 64)); 205 } 206 } 207 208 void 209 ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username) 210 { 211 if (intf->session == NULL) 212 return; 213 214 memset(intf->session->username, 0, 17); 215 216 if (username == NULL) 217 return; 218 219 memcpy(intf->session->username, username, __min(strlen(username), 16)); 220 } 221 222 void 223 ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password) 224 { 225 if (intf->session == NULL) 226 return; 227 228 memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE); 229 230 if (password == NULL) { 231 intf->session->password = 0; 232 return; 233 } 234 235 intf->session->password = 1; 236 memcpy(intf->session->authcode, password, 237 __min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE)); 238 } 239 240 void 241 ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level) 242 { 243 if (intf->session == NULL) 244 return; 245 246 intf->session->privlvl = level; 247 } 248 249 void 250 ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit) 251 { 252 if (intf->session == NULL) 253 return; 254 255 intf->session->v2_data.lookupbit = lookupbit; 256 } 257 258 void 259 ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id) 260 { 261 if (intf->session == NULL) 262 return; 263 264 intf->session->cipher_suite_id = cipher_suite_id; 265 } 266 267 void 268 ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char) 269 { 270 if (intf->session == NULL) 271 return; 272 273 intf->session->sol_escape_char = sol_escape_char; 274 } 275 276 void 277 ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey) 278 { 279 if (intf->session == NULL) 280 return; 281 282 memset(intf->session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); 283 284 if (kgkey == NULL) 285 return; 286 287 memcpy(intf->session->v2_data.kg, kgkey, 288 __min(strlen(kgkey), IPMI_KG_BUFFER_SIZE)); 289 } 290 291 void 292 ipmi_intf_session_set_port(struct ipmi_intf * intf, int port) 293 { 294 if (intf->session == NULL) 295 return; 296 297 intf->session->port = port; 298 } 299 300 void 301 ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype) 302 { 303 if (intf->session == NULL) 304 return; 305 306 /* clear password field if authtype NONE specified */ 307 if (authtype == IPMI_SESSION_AUTHTYPE_NONE) { 308 memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE); 309 intf->session->password = 0; 310 } 311 312 intf->session->authtype_set = authtype; 313 } 314 315 void 316 ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout) 317 { 318 if (intf->session == NULL) 319 return; 320 321 intf->session->timeout = timeout; 322 } 323 324 void 325 ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry) 326 { 327 if (intf->session == NULL) 328 return; 329 330 intf->session->retry = retry; 331 } 332 333 void 334 ipmi_cleanup(struct ipmi_intf * intf) 335 { 336 ipmi_sdr_list_empty(intf); 337 } 338 339 #if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS) 340 int 341 ipmi_intf_socket_connect(struct ipmi_intf * intf) 342 { 343 struct ipmi_session *session; 344 345 struct sockaddr_storage addr; 346 struct addrinfo hints; 347 struct addrinfo *rp0 = NULL, *rp; 348 char service[NI_MAXSERV]; 349 int rc; 350 351 if (!intf || intf->session == NULL) { 352 return -1; 353 } 354 355 session = intf->session; 356 357 if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) { 358 lprintf(LOG_ERR, "No hostname specified!"); 359 return -1; 360 } 361 362 /* open port to BMC */ 363 memset(&addr, 0, sizeof(addr)); 364 365 sprintf(service, "%d", session->port); 366 /* Obtain address(es) matching host/port */ 367 memset(&hints, 0, sizeof(hints)); 368 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 369 hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ 370 hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */ 371 hints.ai_protocol = IPPROTO_UDP; /* */ 372 373 if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) { 374 lprintf(LOG_ERR, "Address lookup for %s failed", 375 session->hostname); 376 return -1; 377 } 378 379 /* getaddrinfo() returns a list of address structures. 380 * Try each address until we successfully connect(2). 381 * If socket(2) (or connect(2)) fails, we (close the socket 382 * and) try the next address. 383 */ 384 385 session->ai_family = AF_UNSPEC; 386 for (rp = rp0; rp != NULL; rp = rp->ai_next) { 387 /* We are only interested in IPv4 and IPv6 */ 388 if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) { 389 continue; 390 } 391 392 intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 393 if (intf->fd == -1) { 394 continue; 395 } 396 397 if (rp->ai_family == AF_INET) { 398 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 399 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 400 session->addrlen = rp->ai_addrlen; 401 session->ai_family = rp->ai_family; 402 break; /* Success */ 403 } 404 } else if (rp->ai_family == AF_INET6) { 405 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr; 406 char hbuf[NI_MAXHOST]; 407 socklen_t len; 408 409 /* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */ 410 if (addr6->sin6_scope_id != 0) { 411 len = sizeof(struct sockaddr_in6); 412 if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { 413 lprintf(LOG_DEBUG, "Trying address: %s scope=%d", 414 hbuf, 415 addr6->sin6_scope_id); 416 } 417 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 418 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 419 session->addrlen = rp->ai_addrlen; 420 session->ai_family = rp->ai_family; 421 break; /* Success */ 422 } 423 } else { 424 /* No scope specified, try to get this from the list of interfaces */ 425 struct ifaddrs *ifaddrs = NULL; 426 struct ifaddrs *ifa = NULL; 427 428 if (getifaddrs(&ifaddrs) < 0) { 429 lprintf(LOG_ERR, "Interface address lookup for %s failed", 430 session->hostname); 431 break; 432 } 433 434 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 435 if (ifa->ifa_addr == NULL) { 436 continue; 437 } 438 439 if (ifa->ifa_addr->sa_family == AF_INET6) { 440 struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr; 441 442 /* Skip unwanted addresses */ 443 if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) { 444 continue; 445 } 446 if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) { 447 continue; 448 } 449 len = sizeof(struct sockaddr_in6); 450 if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) { 451 lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d", 452 ifa->ifa_name != NULL ? ifa->ifa_name : "???", 453 hbuf, 454 tmp6->sin6_scope_id); 455 } 456 457 if (tmp6->sin6_scope_id != 0) { 458 addr6->sin6_scope_id = tmp6->sin6_scope_id; 459 } else { 460 /* 461 * No scope information in interface address information 462 * On some OS'es, getifaddrs() is returning out the 'kernel' representation 463 * of scoped addresses which stores the scope in the 3rd and 4th 464 * byte. See also this page: 465 * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html 466 */ 467 if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr) 468 && (tmp6->sin6_addr.s6_addr16[1] != 0)) { 469 addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr16[1]); 470 } 471 } 472 473 /* OK, now try to connect with the scope id from this interface address */ 474 if (addr6->sin6_scope_id != 0) { 475 if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) { 476 memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen); 477 session->addrlen = rp->ai_addrlen; 478 session->ai_family = rp->ai_family; 479 lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id); 480 break; /* Success */ 481 } 482 } 483 } 484 } 485 freeifaddrs(ifaddrs); 486 } 487 } 488 if (session->ai_family != AF_UNSPEC) { 489 break; 490 } 491 close(intf->fd); 492 intf->fd = -1; 493 } 494 495 /* No longer needed */ 496 freeaddrinfo(rp0); 497 498 return ((intf->fd != -1) ? 0 : -1); 499 } 500 #endif 501 502 uint16_t 503 ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf) 504 { 505 int16_t size; 506 507 size = intf->max_request_data_size; 508 509 /* check if request size is not specified */ 510 if (!size) { 511 /* 512 * The IPMB standard overall message length for �non -bridging� 513 * messages is specified as 32 bytes, maximum, including slave 514 * address. This sets the upper limit for typical IPMI messages. 515 * With the exception of messages used for bridging messages to 516 * other busses or interfaces (e.g. Master Write-Read and Send Message) 517 * IPMI messages should be designed to fit within this 32-byte maximum. 518 * In order to support bridging, the Master Write -Read and Send Message 519 * commands are allowed to exceed the 32-byte maximum transaction on IPMB 520 */ 521 522 size = IPMI_DEFAULT_PAYLOAD_SIZE; 523 524 /* check if message is forwarded */ 525 if (intf->target_addr && intf->target_addr != intf->my_addr) { 526 /* add Send Message request size */ 527 size += 8; 528 } 529 } 530 531 /* check if message is forwarded */ 532 if (intf->target_addr && intf->target_addr != intf->my_addr) { 533 /* subtract send message request size */ 534 size -= 8; 535 536 /* 537 * Check that forwarded request size is not greater 538 * than the default payload size. 539 */ 540 if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { 541 size = IPMI_DEFAULT_PAYLOAD_SIZE; 542 } 543 544 /* check for double bridging */ 545 if (intf->transit_addr && intf->transit_addr != intf->target_addr) { 546 /* subtract inner send message request size */ 547 size -= 8; 548 } 549 } 550 551 /* check for underflow */ 552 if (size < 0) { 553 return 0; 554 } 555 556 return size; 557 } 558 559 uint16_t 560 ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf) 561 { 562 int16_t size; 563 564 size = intf->max_response_data_size; 565 566 /* check if response size is not specified */ 567 if (!size) { 568 /* 569 * The IPMB standard overall message length for �non -bridging� 570 * messages is specified as 32 bytes, maximum, including slave 571 * address. This sets the upper limit for typical IPMI messages. 572 * With the exception of messages used for bridging messages to 573 * other busses or interfaces (e.g. Master Write-Read and Send Message) 574 * IPMI messages should be designed to fit within this 32-byte maximum. 575 * In order to support bridging, the Master Write -Read and Send Message 576 * commands are allowed to exceed the 32-byte maximum transaction on IPMB 577 */ 578 579 size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */ 580 581 /* check if message is forwarded */ 582 if (intf->target_addr && intf->target_addr != intf->my_addr) { 583 /* add Send Message header size */ 584 size += 7; 585 } 586 } 587 588 /* check if message is forwarded */ 589 if (intf->target_addr && intf->target_addr != intf->my_addr) { 590 /* 591 * Some IPMI controllers like PICMG AMC Carriers embed responses 592 * to the forwarded messages into the Send Message response. 593 * In order to be sure that the response is not truncated, 594 * subtract the internal message header size. 595 */ 596 size -= 8; 597 598 /* 599 * Check that forwarded response is not greater 600 * than the default payload size. 601 */ 602 if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { 603 size = IPMI_DEFAULT_PAYLOAD_SIZE; 604 } 605 606 /* check for double bridging */ 607 if (intf->transit_addr && intf->transit_addr != intf->target_addr) { 608 /* subtract inner send message header size */ 609 size -= 8; 610 } 611 } 612 613 /* check for underflow */ 614 if (size < 0) { 615 return 0; 616 } 617 618 return size; 619 } 620 621 void 622 ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size) 623 { 624 if (size < IPMI_DEFAULT_PAYLOAD_SIZE) { 625 lprintf(LOG_ERR, "Request size is too small (%d), leave default size", 626 size); 627 return; 628 } 629 630 if (intf->set_max_request_data_size) { 631 intf->set_max_request_data_size(intf, size); 632 } else { 633 intf->max_request_data_size = size; 634 } 635 } 636 637 void 638 ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size) 639 { 640 if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) { 641 lprintf(LOG_ERR, "Response size is too small (%d), leave default size", 642 size); 643 return; 644 } 645 646 if (intf->set_max_response_data_size) { 647 intf->set_max_response_data_size(intf, size); 648 } else { 649 intf->max_response_data_size = size; 650 } 651 } 652