xref: /openbmc/ipmitool/src/plugins/ipmi_intf.c (revision d531785a)
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