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