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