e96b5f486f
All interface APIs for accessing the info remain unchanged in opal/util/if.c. This has been tested on Mac, Linux, and NetBSD. Nobody else seemed interested in testing it, so there may be some future problems revealed as people try it on other OSs. This commit was SVN r23743.
161 строка
4.9 KiB
C
161 строка
4.9 KiB
C
/*
|
|
* Copyright (c) 2010 Cisco Systems, Inc. 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/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)
|
|
{
|
|
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 ( (!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;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
|