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