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

147 строки
4.0 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_bsdx_open(void);
/* Supports specific flavors of BSD:
* NetBSD
* FreeBSD
* OpenBSD
* DragonFly
*/
opal_if_base_component_t mca_if_bsdx_ipv4_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 */
"bsdx_ipv4",
OPAL_MAJOR_VERSION,
OPAL_MINOR_VERSION,
OPAL_RELEASE_VERSION,
/* Component open and close functions */
if_bsdx_open,
NULL
},
{
/* This component is checkpointable */
MCA_BASE_METADATA_PARAM_CHECKPOINT
},
};
/* convert a netmask (in network byte order) to CIDR notation */
static int prefix (uint32_t netmask)
{
uint32_t mask = ntohl(netmask);
int plen = 0;
if (0 == mask) {
plen = 32;
} else {
while ((mask % 2) == 0) {
plen += 1;
mask /= 2;
}
}
return (32 - plen);
}
/* configure using getifaddrs(3) */
static int if_bsdx_open(void)
{
struct ifaddrs **ifadd_list;
struct ifaddrs *cur_ifaddrs;
struct sockaddr_in* sin_addr;
/*
* the manpage claims that getifaddrs() allocates the memory,
* and freeifaddrs() is later used to release the allocated memory.
* however, without this malloc the call to getifaddrs() segfaults
*/
ifadd_list = (struct ifaddrs **) malloc(sizeof(struct ifaddrs*));
/* create the linked list of ifaddrs structs */
if (getifaddrs(ifadd_list) < 0) {
opal_output(0, "opal_ifinit: getifaddrs() failed with error=%d\n",
errno);
return OPAL_ERROR;
}
for (cur_ifaddrs = *ifadd_list; NULL != cur_ifaddrs;
cur_ifaddrs = cur_ifaddrs->ifa_next) {
opal_if_t *intf;
struct in_addr a4;
/* skip non- af_inet interface addresses */
if (AF_INET != cur_ifaddrs->ifa_addr->sa_family) {
continue;
}
/* skip interface if it is down (IFF_UP not set) */
if (0 == (cur_ifaddrs->ifa_flags & IFF_UP)) {
continue;
}
/* skip interface if it is a loopback device (IFF_LOOPBACK set) */
if (!opal_if_retain_loopback && 0 != (cur_ifaddrs->ifa_flags & IFF_LOOPBACK)) {
continue;
}
/* or if it is a point-to-point interface */
/* TODO: do we really skip p2p? */
if (0 != (cur_ifaddrs->ifa_flags & IFF_POINTOPOINT)) {
continue;
}
sin_addr = (struct sockaddr_in *) cur_ifaddrs->ifa_addr;
intf = OBJ_NEW(opal_if_t);
if (NULL == intf) {
opal_output(0, "opal_ifinit: unable to allocate %d bytes\n",
(int) sizeof(opal_if_t));
return OPAL_ERR_OUT_OF_RESOURCE;
}
intf->af_family = AF_INET;
/* fill values into the opal_if_t */
memcpy(&a4, &(sin_addr->sin_addr), sizeof(struct in_addr));
strncpy(intf->if_name, cur_ifaddrs->ifa_name, IF_NAMESIZE);
intf->if_index = opal_list_get_size(&opal_if_list) + 1;
((struct sockaddr_in*) &intf->if_addr)->sin_addr = a4;
((struct sockaddr_in*) &intf->if_addr)->sin_family = AF_INET;
((struct sockaddr_in*) &intf->if_addr)->sin_len = cur_ifaddrs->ifa_addr->sa_len;
intf->if_mask = prefix( sin_addr->sin_addr.s_addr);
intf->if_flags = cur_ifaddrs->ifa_flags;
intf->if_kernel_index =
(uint16_t) if_nametoindex(cur_ifaddrs->ifa_name);
opal_list_append(&opal_if_list, &(intf->super));
} /* of for loop over ifaddrs list */
return OPAL_SUCCESS;
}