1
1
openmpi/opal/mca/if/solaris_ipv6/if_solaris_ipv6.c
2015-06-23 20:59:57 -07:00

166 строки
5.1 KiB
C

/*
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include <stdlib.h>
#include <string.h>
#include "opal/constants.h"
#include "opal/util/output.h"
#include "opal/mca/if/if.h"
static int if_solaris_ipv6_open(void);
/* Discovers Solaris IPv6 interfaces */
opal_if_base_component_t mca_if_solaris_ipv6_component = {
/* First, the mca_component_t struct containing meta information
about the component itself */
{
OPAL_IF_BASE_VERSION_2_0_0,
/* Component name and version */
"solaris_ipv6",
OPAL_MAJOR_VERSION,
OPAL_MINOR_VERSION,
OPAL_RELEASE_VERSION,
/* Component open and close functions */
if_solaris_ipv6_open,
NULL
},
{
/* This component is checkpointable */
MCA_BASE_METADATA_PARAM_CHECKPOINT
},
};
/* configure using getifaddrs(3) */
static int if_solaris_ipv6_open(void)
{
#if OPAL_ENABLE_IPV6
int i;
int sd;
int error;
uint16_t kindex;
struct lifnum lifnum;
struct lifconf lifconf;
struct lifreq *lifreq, lifquery;
sd = socket (AF_INET6, SOCK_DGRAM, 0);
if (sd < 0) {
opal_output (0, "opal_ifinit: unable to open IPv6 socket\n");
return OPAL_ERROR;
}
/* we only ask for IPv6; IPv4 discovery has already been done */
lifnum.lifn_family = AF_INET6;
lifnum.lifn_flags = 0;
lifnum.lifn_count = 0;
/* get the number of interfaces in the system */
error = ioctl (sd, SIOCGLIFNUM, &lifnum);
if (error < 0) {
opal_output (0,
"opal_ifinit: ioctl SIOCGLIFNUM failed with errno=%d\n", errno);
return OPAL_ERROR;
}
memset (&lifconf, 0, sizeof (struct lifconf));
memset (&lifquery, 0, sizeof (struct lifreq));
lifconf.lifc_family = AF_INET6;
lifconf.lifc_flags = 0;
lifconf.lifc_len = lifnum.lifn_count * sizeof (struct lifreq) * 2;
lifconf.lifc_buf = malloc (lifconf.lifc_len);
if (NULL == lifconf.lifc_buf) {
opal_output (0, "opal_ifinit: IPv6 discovery: malloc() failed\n");
return OPAL_ERR_OUT_OF_RESOURCE;
}
memset (lifconf.lifc_buf, 0, lifconf.lifc_len);
error = ioctl (sd, SIOCGLIFCONF, &lifconf);
if (error < 0) {
opal_output (0,
"opal_ifinit: IPv6 SIOCGLIFCONF failed with errno=%d\n", errno);
}
for (i = 0; i + sizeof (struct lifreq) <= lifconf.lifc_len;
i += sizeof (*lifreq)) {
lifreq = (struct lifreq *)((caddr_t)lifconf.lifc_buf + i);
strncpy (lifquery.lifr_name, lifreq->lifr_name,
sizeof (lifquery.lifr_name));
/* lookup kernel index */
error = ioctl (sd, SIOCGLIFINDEX, &lifquery);
if (error < 0) {
opal_output (0,
"opal_ifinit: SIOCGLIFINDEX failed with errno=%d\n", errno);
return OPAL_ERROR;
}
kindex = lifquery.lifr_index;
/* lookup interface flags */
error = ioctl (sd, SIOCGLIFFLAGS, &lifquery);
if (error < 0) {
opal_output (0,
"opal_ifinit: SIOCGLIFFLAGS failed with errno=%d\n", errno);
return OPAL_ERROR;
}
if (AF_INET6 == lifreq->lifr_addr.ss_family) {
struct sockaddr_in6* my_addr = (struct sockaddr_in6*) &lifreq->lifr_addr;
/* we surely want to check for sin6_scope_id, but Solaris
does not set it correctly, so we have to look for
global scope. For now, global is anything which is
neither loopback nor link local.
Bug, FIXME: site-local, multicast, ... missing
Check for 2000::/3?
*/
if ( (!opal_if_retain_loopback && !IN6_IS_ADDR_LOOPBACK (&my_addr->sin6_addr)) &&
(! IN6_IS_ADDR_LINKLOCAL (&my_addr->sin6_addr))) {
/* create interface for newly found address */
opal_if_t *intf;
intf = OBJ_NEW(opal_if_t);
if (NULL == intf) {
opal_output (0,
"opal_ifinit: unable to allocate %d bytes\n",
sizeof (opal_if_t));
return OPAL_ERR_OUT_OF_RESOURCE;
}
intf->af_family = AF_INET6;
strncpy (intf->if_name, lifreq->lifr_name, IF_NAMESIZE);
intf->if_index = opal_list_get_size(&opal_if_list)+1;
memcpy(&intf->if_addr, my_addr, sizeof (*my_addr));
intf->if_mask = 64;
/* lifrq flags are uint64_t */
intf->if_flags =
(uint32_t)(0x00000000ffffffff) & lifquery.lifr_flags;
/* append to list */
opal_list_append (&opal_if_list, &(intf->super));
}
}
} /* for */
if (NULL != lifconf.lifc_buf) {
free (lifconf.lifc_buf);
}
#endif /* OPAL_ENABLE_IPV6 */
return OPAL_SUCCESS;
}