Blame src/plugins/ipmi_intf.c

Packit d14fb6
/*
Packit d14fb6
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution and use in source and binary forms, with or without
Packit d14fb6
 * modification, are permitted provided that the following conditions
Packit d14fb6
 * are met:
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution of source code must retain the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer.
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution in binary form must reproduce the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer in the
Packit d14fb6
 * documentation and/or other materials provided with the distribution.
Packit d14fb6
 * 
Packit d14fb6
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit d14fb6
 * contributors may be used to endorse or promote products derived
Packit d14fb6
 * from this software without specific prior written permission.
Packit d14fb6
 * 
Packit d14fb6
 * This software is provided "AS IS," without a warranty of any kind.
Packit d14fb6
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit d14fb6
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit d14fb6
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit d14fb6
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit d14fb6
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit d14fb6
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit d14fb6
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit d14fb6
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit d14fb6
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit d14fb6
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit d14fb6
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit d14fb6
 */
Packit d14fb6
#define _XOPEN_SOURCE 700
Packit d14fb6
#define _GNU_SOURCE 1
Packit d14fb6
#define _DARWIN_C_SOURCE 1
Packit d14fb6
Packit d14fb6
#include <stdio.h>
Packit d14fb6
#include <stdlib.h>
Packit d14fb6
#include <string.h>
Packit d14fb6
#if defined(HAVE_CONFIG_H)
Packit d14fb6
# include <config.h>
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
Packit d14fb6
#include <sys/types.h>
Packit d14fb6
#include <sys/socket.h>
Packit d14fb6
#include <netinet/in.h>
Packit d14fb6
#include <arpa/inet.h>
Packit d14fb6
#include <ifaddrs.h>
Packit d14fb6
#include <unistd.h>
Packit d14fb6
#include <netdb.h>
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
Packit d14fb6
#include <ipmitool/ipmi_intf.h>
Packit d14fb6
#include <ipmitool/ipmi.h>
Packit d14fb6
#include <ipmitool/ipmi_sdr.h>
Packit d14fb6
#include <ipmitool/log.h>
Packit 8d0f0b
#include <ipmitool/helper.h>
Packit d14fb6
Packit d14fb6
#define IPMI_DEFAULT_PAYLOAD_SIZE   25
Packit d14fb6
Packit d14fb6
#ifdef IPMI_INTF_OPEN
Packit d14fb6
extern struct ipmi_intf ipmi_open_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_IMB
Packit d14fb6
extern struct ipmi_intf ipmi_imb_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_LIPMI
Packit d14fb6
extern struct ipmi_intf ipmi_lipmi_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_BMC
Packit d14fb6
extern struct ipmi_intf ipmi_bmc_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_LAN
Packit d14fb6
extern struct ipmi_intf ipmi_lan_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_LANPLUS
Packit d14fb6
extern struct ipmi_intf ipmi_lanplus_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_FREE
Packit d14fb6
extern struct ipmi_intf ipmi_free_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_SERIAL
Packit d14fb6
extern struct ipmi_intf ipmi_serial_term_intf;
Packit d14fb6
extern struct ipmi_intf ipmi_serial_bm_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_DUMMY
Packit d14fb6
extern struct ipmi_intf ipmi_dummy_intf;
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_USB
Packit d14fb6
extern struct ipmi_intf ipmi_usb_intf;
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
struct ipmi_intf * ipmi_intf_table[] = {
Packit d14fb6
#ifdef IPMI_INTF_OPEN
Packit d14fb6
	&ipmi_open_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_IMB
Packit d14fb6
	&ipmi_imb_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_LIPMI
Packit d14fb6
	&ipmi_lipmi_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_BMC
Packit d14fb6
	&ipmi_bmc_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_LAN
Packit d14fb6
	&ipmi_lan_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_LANPLUS
Packit d14fb6
	&ipmi_lanplus_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_FREE
Packit d14fb6
	&ipmi_free_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_SERIAL
Packit d14fb6
	&ipmi_serial_term_intf,
Packit d14fb6
	&ipmi_serial_bm_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_DUMMY
Packit d14fb6
	&ipmi_dummy_intf,
Packit d14fb6
#endif
Packit d14fb6
#ifdef IPMI_INTF_USB
Packit d14fb6
	&ipmi_usb_intf,
Packit d14fb6
#endif
Packit d14fb6
	NULL
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
/* ipmi_intf_print  -  Print list of interfaces
Packit d14fb6
 *
Packit d14fb6
 * no meaningful return code
Packit d14fb6
 */
Packit d14fb6
void ipmi_intf_print(struct ipmi_intf_support * intflist)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_intf ** intf;
Packit d14fb6
	struct ipmi_intf_support * sup;
Packit d14fb6
	int def = 1;
Packit d14fb6
	int found;
Packit d14fb6
Packit d14fb6
	lprintf(LOG_NOTICE, "Interfaces:");
Packit d14fb6
Packit d14fb6
	for (intf = ipmi_intf_table; intf && *intf; intf++) {
Packit d14fb6
Packit d14fb6
		if (intflist != NULL) {
Packit d14fb6
			found = 0;
Packit d14fb6
			for (sup=intflist; sup->name != NULL; sup++) {
Packit d14fb6
				if (strncmp(sup->name, (*intf)->name, strlen(sup->name)) == 0 &&
Packit d14fb6
				    strncmp(sup->name, (*intf)->name, strlen((*intf)->name)) == 0 &&
Packit d14fb6
				    sup->supported == 1)
Packit d14fb6
					found = 1;
Packit d14fb6
			}
Packit d14fb6
			if (found == 0)
Packit d14fb6
				continue;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		lprintf(LOG_NOTICE, "\t%-12s  %s %s",
Packit d14fb6
			(*intf)->name, (*intf)->desc,
Packit d14fb6
			def ? "[default]" : "");
Packit d14fb6
		def = 0;
Packit d14fb6
	}
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* ipmi_intf_load  -  Load an interface from the interface table above
Packit d14fb6
 *                    If no interface name is given return first entry
Packit d14fb6
 *
Packit d14fb6
 * @name:	interface name to try and load
Packit d14fb6
 *
Packit d14fb6
 * returns pointer to inteface structure if found
Packit d14fb6
 * returns NULL on error
Packit d14fb6
 */
Packit d14fb6
struct ipmi_intf * ipmi_intf_load(char * name)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_intf ** intf;
Packit d14fb6
	struct ipmi_intf * i;
Packit d14fb6
Packit d14fb6
	if (name == NULL) {
Packit d14fb6
		i = ipmi_intf_table[0];
Packit d14fb6
		if (i->setup != NULL && (i->setup(i) < 0)) {
Packit d14fb6
			lprintf(LOG_ERR, "Unable to setup "
Packit d14fb6
				"interface %s", name);
Packit d14fb6
			return NULL;
Packit d14fb6
		}
Packit d14fb6
		return i;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	for (intf = ipmi_intf_table;
Packit d14fb6
	     ((intf != NULL) && (*intf != NULL));
Packit d14fb6
	     intf++) {
Packit d14fb6
		i = *intf;
Packit d14fb6
		if (strncmp(name, i->name, strlen(name)) == 0) {
Packit d14fb6
			if (i->setup != NULL && (i->setup(i) < 0)) {
Packit d14fb6
				lprintf(LOG_ERR, "Unable to setup "
Packit d14fb6
					"interface %s", name);
Packit d14fb6
				return NULL;
Packit d14fb6
			}
Packit d14fb6
			return i;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return NULL;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname)
Packit d14fb6
{
Packit d14fb6
	if (intf->ssn_params.hostname != NULL) {
Packit d14fb6
		free(intf->ssn_params.hostname);
Packit d14fb6
		intf->ssn_params.hostname = NULL;
Packit d14fb6
	}
Packit d14fb6
	if (hostname == NULL) {
Packit d14fb6
		return;
Packit d14fb6
	}
Packit d14fb6
	intf->ssn_params.hostname = strdup(hostname);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username)
Packit d14fb6
{
Packit d14fb6
	memset(intf->ssn_params.username, 0, 17);
Packit d14fb6
Packit d14fb6
	if (username == NULL)
Packit d14fb6
		return;
Packit d14fb6
Packit d14fb6
	memcpy(intf->ssn_params.username, username, __min(strlen(username), 16));
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password)
Packit d14fb6
{
Packit d14fb6
	memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE);
Packit d14fb6
Packit d14fb6
	if (password == NULL) {
Packit d14fb6
		intf->ssn_params.password = 0;
Packit d14fb6
		return;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	intf->ssn_params.password = 1;
Packit d14fb6
	memcpy(intf->ssn_params.authcode_set, password,
Packit d14fb6
	       __min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE));
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level)
Packit d14fb6
{
Packit d14fb6
	intf->ssn_params.privlvl = level;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit)
Packit d14fb6
{
Packit d14fb6
	intf->ssn_params.lookupbit = lookupbit;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id)
Packit d14fb6
{
Packit d14fb6
	intf->ssn_params.cipher_suite_id = cipher_suite_id;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char)
Packit d14fb6
{
Packit d14fb6
	intf->ssn_params.sol_escape_char = sol_escape_char;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_kgkey(struct ipmi_intf *intf, const uint8_t *kgkey)
Packit d14fb6
{
Packit d14fb6
	memcpy(intf->ssn_params.kg, kgkey, IPMI_KG_BUFFER_SIZE);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_port(struct ipmi_intf * intf, int port)
Packit d14fb6
{
Packit d14fb6
	intf->ssn_params.port = port;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype)
Packit d14fb6
{
Packit d14fb6
	/* clear password field if authtype NONE specified */
Packit d14fb6
	if (authtype == IPMI_SESSION_AUTHTYPE_NONE) {
Packit d14fb6
		memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE);
Packit d14fb6
		intf->ssn_params.password = 0;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	intf->ssn_params.authtype_set = authtype;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout)
Packit d14fb6
{
Packit d14fb6
	intf->ssn_params.timeout = timeout;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry)
Packit d14fb6
{
Packit d14fb6
	intf->ssn_params.retry = retry;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_session_cleanup(struct ipmi_intf *intf)
Packit d14fb6
{
Packit d14fb6
	if (intf->session == NULL) {
Packit d14fb6
		return;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	free(intf->session);
Packit d14fb6
	intf->session = NULL;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_cleanup(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
	ipmi_sdr_list_empty(intf);
Packit d14fb6
	ipmi_intf_session_set_hostname(intf, NULL);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
Packit d14fb6
int
Packit d14fb6
ipmi_intf_socket_connect(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_session_params *params;
Packit d14fb6
Packit d14fb6
	struct sockaddr_storage addr;
Packit d14fb6
	struct addrinfo hints;
Packit d14fb6
	struct addrinfo *rp0 = NULL, *rp;
Packit d14fb6
	char service[NI_MAXSERV];
Packit d14fb6
Packit d14fb6
	if (!intf) {
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	params = &intf->ssn_params;
Packit d14fb6
Packit d14fb6
	if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) {
Packit d14fb6
		lprintf(LOG_ERR, "No hostname specified!");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* open port to BMC */
Packit d14fb6
	memset(&addr, 0, sizeof(addr));
Packit d14fb6
Packit d14fb6
	sprintf(service, "%d", params->port);
Packit d14fb6
	/* Obtain address(es) matching host/port */
Packit d14fb6
	memset(&hints, 0, sizeof(hints));
Packit d14fb6
	hints.ai_family   = intf->ai_family;    /* Allow IPv4 or IPv6 */
Packit d14fb6
	hints.ai_socktype = SOCK_DGRAM;   /* Datagram socket */
Packit d14fb6
	hints.ai_flags    = 0;            /* use AI_NUMERICSERV for no name resolution */
Packit d14fb6
	hints.ai_protocol = IPPROTO_UDP; /*  */
Packit d14fb6
Packit d14fb6
	if (getaddrinfo(params->hostname, service, &hints, &rp0) != 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Address lookup for %s failed",
Packit d14fb6
				params->hostname);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* getaddrinfo() returns a list of address structures.
Packit d14fb6
	 * Try each address until we successfully connect(2).
Packit d14fb6
	 * If socket(2) (or connect(2)) fails, we (close the socket
Packit d14fb6
	 * and) try the next address.
Packit d14fb6
	 */
Packit d14fb6
Packit d14fb6
	for (rp = rp0; rp != NULL; rp = rp->ai_next) {
Packit d14fb6
		/* We are only interested in IPv4 and IPv6 */
Packit d14fb6
		if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) {
Packit d14fb6
			continue;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
Packit d14fb6
		if (intf->fd == -1) {
Packit d14fb6
			continue;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (rp->ai_family == AF_INET) {
Packit d14fb6
			if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
Packit d14fb6
				hints.ai_family = rp->ai_family;
Packit d14fb6
				break;  /* Success */
Packit d14fb6
			}
Packit d14fb6
		}  else if (rp->ai_family == AF_INET6) {
Packit d14fb6
			struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr;
Packit d14fb6
			char hbuf[NI_MAXHOST];
Packit d14fb6
			socklen_t len;
Packit d14fb6
Packit d14fb6
			/* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */
Packit d14fb6
			if (addr6->sin6_scope_id != 0) {
Packit d14fb6
				len = sizeof(struct sockaddr_in6);
Packit d14fb6
				if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
Packit d14fb6
					lprintf(LOG_DEBUG, "Trying address: %s scope=%d",
Packit d14fb6
						hbuf,
Packit d14fb6
						addr6->sin6_scope_id);
Packit d14fb6
				}
Packit d14fb6
				if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
Packit d14fb6
					hints.ai_family = rp->ai_family;
Packit d14fb6
					break;  /* Success */
Packit d14fb6
				}
Packit d14fb6
			} else {
Packit d14fb6
				/* No scope specified, try to get this from the list of interfaces */
Packit d14fb6
				struct ifaddrs *ifaddrs = NULL;
Packit d14fb6
				struct ifaddrs *ifa = NULL;
Packit d14fb6
Packit d14fb6
				if (getifaddrs(&ifaddrs) < 0) {
Packit d14fb6
					lprintf(LOG_ERR, "Interface address lookup for %s failed",
Packit d14fb6
						params->hostname);
Packit d14fb6
					break;
Packit d14fb6
				}
Packit d14fb6
Packit d14fb6
				for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
Packit d14fb6
					if (ifa->ifa_addr == NULL) {
Packit d14fb6
						continue;
Packit d14fb6
					}
Packit d14fb6
Packit d14fb6
					if (ifa->ifa_addr->sa_family == AF_INET6) {
Packit d14fb6
						struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr;
Packit d14fb6
Packit d14fb6
						/* Skip unwanted addresses */
Packit d14fb6
						if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) {
Packit d14fb6
							continue;
Packit d14fb6
						}
Packit d14fb6
						if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) {
Packit d14fb6
							continue;
Packit d14fb6
						}
Packit d14fb6
						len = sizeof(struct sockaddr_in6);
Packit d14fb6
						if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
Packit d14fb6
							lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d",
Packit d14fb6
								ifa->ifa_name != NULL ? ifa->ifa_name : "???",
Packit d14fb6
								hbuf,
Packit d14fb6
								tmp6->sin6_scope_id);
Packit d14fb6
						}
Packit d14fb6
Packit d14fb6
						if (tmp6->sin6_scope_id != 0) {
Packit d14fb6
							addr6->sin6_scope_id = tmp6->sin6_scope_id;
Packit d14fb6
						} else {
Packit d14fb6
							/*
Packit d14fb6
							 * No scope information in interface address information
Packit d14fb6
							 * On some OS'es, getifaddrs() is returning out the 'kernel' representation
Packit d14fb6
							 * of scoped addresses which stores the scope in the 3rd and 4th
Packit d14fb6
							 * byte. See also this page:
Packit d14fb6
							 * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html
Packit d14fb6
							 */
Packit d14fb6
							if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)
Packit d14fb6
									&& (tmp6->sin6_addr.s6_addr[1] != 0)) {
Packit d14fb6
								addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr[1]);
Packit d14fb6
							}
Packit d14fb6
						}
Packit d14fb6
Packit d14fb6
						/* OK, now try to connect with the scope id from this interface address */
Packit d14fb6
						if (addr6->sin6_scope_id != 0 || !IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)) {
Packit d14fb6
							if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
Packit d14fb6
								hints.ai_family = rp->ai_family;
Packit d14fb6
								lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id);
Packit d14fb6
								break;  /* Success */
Packit d14fb6
							}
Packit d14fb6
						}
Packit d14fb6
					}
Packit d14fb6
				}
Packit d14fb6
				freeifaddrs(ifaddrs);
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		if (hints.ai_family != AF_UNSPEC) {
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
		close(intf->fd);
Packit d14fb6
		intf->fd = -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* No longer needed */
Packit d14fb6
	freeaddrinfo(rp0);
Packit d14fb6
Packit d14fb6
	return ((intf->fd != -1) ? 0 : -1);
Packit d14fb6
}
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
uint16_t
Packit d14fb6
ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
	int16_t size;
Packit d14fb6
Packit d14fb6
	size = intf->max_request_data_size;
Packit d14fb6
Packit d14fb6
	/* check if request size is not specified */
Packit d14fb6
	if (!size) {
Packit d14fb6
		/*
Packit d14fb6
		 * The IPMB standard overall message length for ‘non -bridging’
Packit d14fb6
		 * messages is specified as 32 bytes, maximum, including slave
Packit d14fb6
		 * address. This sets the upper limit for typical IPMI messages.
Packit d14fb6
		 * With the exception of messages used for bridging messages to
Packit d14fb6
		 * other busses or interfaces (e.g. Master Write-Read and Send Message)
Packit d14fb6
		 * IPMI messages should be designed to fit within this 32-byte maximum.
Packit d14fb6
		 * In order to support bridging, the Master Write -Read and Send Message
Packit d14fb6
		 * commands are allowed to exceed the 32-byte maximum transaction on IPMB
Packit d14fb6
		 */
Packit d14fb6
Packit d14fb6
		size = IPMI_DEFAULT_PAYLOAD_SIZE;
Packit d14fb6
Packit d14fb6
		/* check if message is forwarded */
Packit d14fb6
		if (intf->target_addr && intf->target_addr != intf->my_addr) {
Packit d14fb6
			/* add Send Message request size */
Packit d14fb6
			size += 8;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* check if message is forwarded */
Packit d14fb6
	if (intf->target_addr && intf->target_addr != intf->my_addr) {
Packit d14fb6
		/* subtract send message request size */
Packit d14fb6
		size -= 8;
Packit d14fb6
Packit d14fb6
		/*
Packit d14fb6
		 * Check that forwarded request size is not greater
Packit d14fb6
		 * than the default payload size.
Packit d14fb6
		 */
Packit d14fb6
		if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
Packit d14fb6
			size = IPMI_DEFAULT_PAYLOAD_SIZE;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* check for double bridging */
Packit d14fb6
		if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
Packit d14fb6
			/* subtract inner send message request size */
Packit d14fb6
			size -= 8;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* check for underflow */
Packit d14fb6
	if (size < 0) {
Packit d14fb6
		return 0;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return size;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
uint16_t
Packit d14fb6
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
	int16_t size;
Packit d14fb6
Packit d14fb6
	size = intf->max_response_data_size;
Packit d14fb6
Packit d14fb6
	/* check if response size is not specified */
Packit d14fb6
	if (!size) {
Packit d14fb6
		/*
Packit d14fb6
		 * The IPMB standard overall message length for ‘non -bridging’
Packit d14fb6
		 * messages is specified as 32 bytes, maximum, including slave
Packit d14fb6
		 * address. This sets the upper limit for typical IPMI messages.
Packit d14fb6
		 * With the exception of messages used for bridging messages to
Packit d14fb6
		 * other busses or interfaces (e.g. Master Write-Read and Send Message)
Packit d14fb6
		 * IPMI messages should be designed to fit within this 32-byte maximum.
Packit d14fb6
		 * In order to support bridging, the Master Write -Read and Send Message
Packit d14fb6
		 * commands are allowed to exceed the 32-byte maximum transaction on IPMB
Packit d14fb6
		 */
Packit d14fb6
Packit d14fb6
		size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */
Packit d14fb6
Packit d14fb6
		/* check if message is forwarded */
Packit d14fb6
		if (intf->target_addr && intf->target_addr != intf->my_addr) {
Packit d14fb6
			/* add Send Message header size */
Packit d14fb6
			size += 7;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* check if message is forwarded */
Packit d14fb6
	if (intf->target_addr && intf->target_addr != intf->my_addr) {
Packit d14fb6
		/*
Packit d14fb6
		 * Some IPMI controllers like PICMG AMC Carriers embed responses
Packit d14fb6
		 * to the forwarded messages into the Send Message response.
Packit d14fb6
		 * In order to be sure that the response is not truncated,
Packit d14fb6
		 * subtract the internal message header size.
Packit d14fb6
		 */
Packit d14fb6
		size -= 8;
Packit d14fb6
Packit d14fb6
		/*
Packit d14fb6
		 * Check that forwarded response is not greater
Packit d14fb6
		 * than the default payload size.
Packit d14fb6
		 */
Packit d14fb6
		if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
Packit d14fb6
			size = IPMI_DEFAULT_PAYLOAD_SIZE;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* check for double bridging */
Packit d14fb6
		if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
Packit d14fb6
			/* subtract inner send message header size */
Packit d14fb6
			size -= 8;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* check for underflow */
Packit d14fb6
	if (size < 0) {
Packit d14fb6
		return 0;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return size;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size)
Packit d14fb6
{
Packit d14fb6
	if (size < IPMI_DEFAULT_PAYLOAD_SIZE) {
Packit d14fb6
		lprintf(LOG_ERR, "Request size is too small (%d), leave default size",
Packit d14fb6
				size);
Packit d14fb6
		return;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (intf->set_max_request_data_size) {
Packit d14fb6
		intf->set_max_request_data_size(intf, size);
Packit d14fb6
	} else {
Packit d14fb6
		intf->max_request_data_size = size;
Packit d14fb6
	}
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size)
Packit d14fb6
{
Packit d14fb6
	if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) {
Packit d14fb6
		lprintf(LOG_ERR, "Response size is too small (%d), leave default size",
Packit d14fb6
				size);
Packit d14fb6
		return;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (intf->set_max_response_data_size) {
Packit d14fb6
		intf->set_max_response_data_size(intf, size);
Packit d14fb6
	} else {
Packit d14fb6
		intf->max_response_data_size = size;
Packit d14fb6
	}
Packit d14fb6
}