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