2004-01-15 02:24:15 +03:00
|
|
|
/*
|
2005-11-05 22:57:48 +03:00
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
|
|
|
* University Research and Technology
|
|
|
|
* Corporation. All rights reserved.
|
2007-04-25 05:55:40 +04:00
|
|
|
* Copyright (c) 2004-2005 The University of Tennessee and The University
|
2005-11-05 22:57:48 +03:00
|
|
|
* of Tennessee Research Foundation. All rights
|
|
|
|
* reserved.
|
2004-11-28 23:09:25 +03:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
2005-03-24 15:43:37 +03:00
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
2004-11-22 04:38:40 +03:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
2004-01-15 02:24:15 +03:00
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "opal_config.h"
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <string.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <unistd.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <errno.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <sys/types.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <sys/socket.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
2005-03-28 15:55:57 +04:00
|
|
|
#ifdef HAVE_SYS_SOCKIO_H
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#endif
|
2004-10-20 05:03:09 +04:00
|
|
|
#ifdef HAVE_SYS_IOCTL_H
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <sys/ioctl.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <netinet/in.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_ARPA_INET_H
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <arpa/inet.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NET_IF_H
|
2007-01-24 20:31:49 +03:00
|
|
|
#if defined(__APPLE__) && defined(_LP64)
|
|
|
|
/* Apple engineering suggested using options align=power as a
|
|
|
|
workaround for a bug in OS X 10.4 (Tiger) that prevented ioctl(...,
|
|
|
|
SIOCGIFCONF, ...) from working properly in 64 bit mode on Power PC.
|
|
|
|
It turns out that the underlying issue is the size of struct
|
|
|
|
ifconf, which the kernel expects to be 12 and natural 64 bit
|
|
|
|
alignment would make 16. The same bug appears in 64 bit mode on
|
|
|
|
Intel macs, but align=power is a no-op there, so instead, use the
|
|
|
|
pack pragma to instruct the compiler to pack on 4 byte words, which
|
|
|
|
has the same effect as align=power for our needs and works on both
|
|
|
|
Intel and Power PC Macs. */
|
|
|
|
#pragma pack(push,4)
|
2005-08-02 19:14:41 +04:00
|
|
|
#endif
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <net/if.h>
|
2007-01-24 20:31:49 +03:00
|
|
|
#if defined(__APPLE__) && defined(_LP64)
|
|
|
|
#pragma pack(pop)
|
2005-08-02 19:14:41 +04:00
|
|
|
#endif
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NETDB_H
|
2004-01-14 21:24:30 +03:00
|
|
|
#include <netdb.h>
|
2004-10-20 05:03:09 +04:00
|
|
|
#endif
|
2004-01-15 02:24:15 +03:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
#ifdef HAVE_IFADDRS_H
|
|
|
|
#include <ifaddrs.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "opal/ipv6compat.h"
|
|
|
|
|
2005-07-03 20:22:16 +04:00
|
|
|
#include "opal/class/opal_list.h"
|
2005-07-04 05:36:20 +04:00
|
|
|
#include "opal/util/if.h"
|
2005-07-04 03:31:27 +04:00
|
|
|
#include "opal/util/output.h"
|
2005-07-04 06:38:44 +04:00
|
|
|
#include "opal/util/strncpy.h"
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "opal/constants.h"
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-13 17:35:21 +04:00
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_IN
|
2005-07-13 08:16:03 +04:00
|
|
|
|
2004-01-14 21:24:30 +03:00
|
|
|
#ifndef IF_NAMESIZE
|
|
|
|
#define IF_NAMESIZE 32
|
|
|
|
#endif
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
#ifndef MIN
|
|
|
|
# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
|
|
#endif
|
|
|
|
|
2005-04-07 06:18:41 +04:00
|
|
|
/*
|
|
|
|
* Define INADDR_NONE if we don't have it. Solaris is the only system
|
|
|
|
* where I have found that it does not exist, and the man page for
|
|
|
|
* inet_addr() says that it returns -1 upon failure. On Linux and
|
|
|
|
* other systems with INADDR_NONE, it's just a #define to -1 anyway.
|
|
|
|
* So just #define it to -1 here if it doesn't already exist.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if !defined(INADDR_NONE)
|
|
|
|
#define INADDR_NONE -1
|
|
|
|
#endif
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
struct opal_if_t {
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_item_t super;
|
2004-01-14 21:24:30 +03:00
|
|
|
char if_name[IF_NAMESIZE];
|
|
|
|
int if_index;
|
2007-04-25 05:55:40 +04:00
|
|
|
uint16_t if_kernel_index;
|
2005-12-13 01:01:51 +03:00
|
|
|
#ifndef __WINDOWS__
|
2004-01-14 21:24:30 +03:00
|
|
|
int if_flags;
|
2004-10-22 20:06:05 +04:00
|
|
|
#else
|
|
|
|
u_long if_flags;
|
|
|
|
#endif
|
2004-02-05 20:12:59 +03:00
|
|
|
int if_speed;
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
struct sockaddr_in6 if_addr;
|
|
|
|
#else
|
2004-01-14 21:24:30 +03:00
|
|
|
struct sockaddr_in if_addr;
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
|
|
|
uint32_t if_mask;
|
2005-12-13 01:01:51 +03:00
|
|
|
#ifdef __WINDOWS__
|
2004-10-22 20:06:05 +04:00
|
|
|
struct sockaddr_in if_bcast;
|
|
|
|
#endif
|
2004-01-26 21:41:37 +03:00
|
|
|
uint32_t if_bandwidth;
|
2004-01-14 21:24:30 +03:00
|
|
|
};
|
2005-07-04 05:36:20 +04:00
|
|
|
typedef struct opal_if_t opal_if_t;
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
static opal_list_t opal_if_list;
|
2004-11-05 15:58:14 +03:00
|
|
|
static bool already_done = false;
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2004-12-17 19:27:37 +03:00
|
|
|
#define DEFAULT_NUMBER_INTERFACES 10
|
2006-09-26 20:37:04 +04:00
|
|
|
#define MAX_IFCONF_SIZE 10 * 1024 * 1024
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert a CIDR prefixlen to netmask (in network byte order) */
|
|
|
|
uint32_t opal_prefix2netmask (uint32_t prefixlen)
|
|
|
|
{
|
|
|
|
return htonl (((1 << prefixlen) - 1) << (32 - prefixlen));
|
|
|
|
}
|
|
|
|
|
2004-12-17 19:27:37 +03:00
|
|
|
/*
|
|
|
|
* Discover the list of configured interfaces. Don't care about any
|
|
|
|
* interfaces that are not up or are local loopbacks.
|
|
|
|
*/
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
static int opal_ifinit(void)
|
2004-12-17 19:27:37 +03:00
|
|
|
{
|
2005-12-13 01:01:51 +03:00
|
|
|
#ifndef __WINDOWS__
|
2007-04-25 05:55:40 +04:00
|
|
|
|
2004-12-17 19:27:37 +03:00
|
|
|
int sd;
|
|
|
|
int lastlen, num, rem;
|
|
|
|
char *ptr;
|
|
|
|
struct ifconf ifconf;
|
|
|
|
int ifc_len;
|
2006-09-26 20:37:04 +04:00
|
|
|
bool successful_locate = false;
|
2004-12-17 19:27:37 +03:00
|
|
|
|
|
|
|
if (already_done) {
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-12-17 19:27:37 +03:00
|
|
|
}
|
|
|
|
already_done = true;
|
|
|
|
|
|
|
|
/* create the internet socket to test off */
|
2007-04-25 05:55:40 +04:00
|
|
|
/*
|
|
|
|
Change AF_INET to AF_UNSPEC (or AF_INET6) and everything will fail.
|
|
|
|
|
|
|
|
Note that Linux does not support AF_INET6 here, but *BSD (and OSX)
|
|
|
|
probably would.
|
|
|
|
|
|
|
|
ifconf would be replaced by lifconf, SIOCG* by SIOCGL*.
|
|
|
|
*/
|
2004-12-17 19:27:37 +03:00
|
|
|
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0, "opal_ifinit: socket() failed with errno=%d\n", errno);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-12-17 19:27:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get Network Interface configuration
|
|
|
|
*
|
|
|
|
* Some notes on the behavior of ioctl(..., SIOCGIFCONF,...)
|
|
|
|
* when not enough space is allocated for all the entries.
|
|
|
|
*
|
|
|
|
* - Solaris returns -1, errno EINVAL if there is not enough
|
|
|
|
* space
|
|
|
|
* - OS X returns 0, sets .ifc_len to the space used by the
|
|
|
|
* by the entries that did fit.
|
|
|
|
* - Linux returns 0, sets .ifc_len to the space required to
|
|
|
|
* hold all the entries (although it only writes what will
|
|
|
|
* fit in the buffer of .ifc_len passed to the function).
|
|
|
|
* - FreeBSD returns 0, sets .ifc_len to 0.
|
|
|
|
*
|
|
|
|
* Everyone else seems to do one of the four.
|
|
|
|
*/
|
|
|
|
lastlen = 0;
|
|
|
|
ifc_len = sizeof(struct ifreq) * DEFAULT_NUMBER_INTERFACES;
|
|
|
|
do {
|
|
|
|
ifconf.ifc_len = ifc_len;
|
|
|
|
ifconf.ifc_req = malloc(ifc_len);
|
|
|
|
if (NULL == ifconf.ifc_req) {
|
|
|
|
close(sd);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-12-17 19:27:37 +03:00
|
|
|
}
|
|
|
|
|
2005-03-22 19:24:32 +03:00
|
|
|
/* initialize the memory so valgrind and purify won't complain
|
|
|
|
* can't use OMPI_DEBUG_ZERO because sizeof(ifconf.ifc_req)
|
2007-04-25 05:55:40 +04:00
|
|
|
* isn't useful. Since this isn't performance critical, just
|
2005-03-22 19:24:32 +03:00
|
|
|
* always memset.
|
|
|
|
*/
|
|
|
|
memset(ifconf.ifc_req, 0, ifconf.ifc_len);
|
2005-03-22 18:37:58 +03:00
|
|
|
|
2004-12-17 19:27:37 +03:00
|
|
|
if(ioctl(sd, SIOCGIFCONF, &ifconf) < 0) {
|
|
|
|
/* if we got an einval, we probably don't have enough
|
|
|
|
space. so we'll fall down and try to expand our
|
|
|
|
space */
|
|
|
|
if (errno != EINVAL && lastlen != 0) {
|
2007-04-25 05:55:40 +04:00
|
|
|
opal_output(0, "opal_ifinit: ioctl(SIOCGIFCONF) \
|
|
|
|
failed with errno=%d",
|
2004-12-17 19:27:37 +03:00
|
|
|
errno);
|
|
|
|
close(sd);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-12-17 19:27:37 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* if ifc_len is 0 or different than what we set it to at
|
|
|
|
call to ioctl, try again with a bigger buffer. else stop */
|
|
|
|
if (ifconf.ifc_len == lastlen && ifconf.ifc_len > 0) {
|
|
|
|
/* we didn't expand. we're done */
|
2006-09-26 20:37:04 +04:00
|
|
|
successful_locate = true;
|
2004-12-17 19:27:37 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
lastlen = ifconf.ifc_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Yes, we overflowed (or had an EINVAL on the ioctl). Loop
|
|
|
|
back around and try again with a bigger buffer */
|
|
|
|
free(ifconf.ifc_req);
|
|
|
|
ifc_len = (ifc_len == 0) ? 1 : ifc_len * 2;
|
2006-09-26 20:37:04 +04:00
|
|
|
} while (ifc_len < MAX_IFCONF_SIZE);
|
|
|
|
if (!successful_locate) {
|
|
|
|
opal_output(0, "opal_ifinit: unable to find network interfaces.");
|
|
|
|
return OPAL_ERR_FATAL;
|
|
|
|
}
|
2004-12-17 19:27:37 +03:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup indexes
|
|
|
|
*/
|
2005-07-04 05:36:20 +04:00
|
|
|
OBJ_CONSTRUCT(&opal_if_list, opal_list_t);
|
2004-12-17 19:27:37 +03:00
|
|
|
ptr = (char*) ifconf.ifc_req;
|
|
|
|
rem = ifconf.ifc_len;
|
|
|
|
num = 0;
|
|
|
|
|
|
|
|
/* loop through all interfaces */
|
|
|
|
while (rem > 0) {
|
|
|
|
struct ifreq* ifr = (struct ifreq*) ptr;
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t intf;
|
|
|
|
opal_if_t *intf_ptr;
|
2004-12-17 19:27:37 +03:00
|
|
|
int length;
|
|
|
|
|
2006-01-04 23:57:57 +03:00
|
|
|
OMPI_DEBUG_ZERO(intf);
|
2005-07-03 20:22:16 +04:00
|
|
|
OBJ_CONSTRUCT(&intf, opal_list_item_t);
|
2004-12-17 19:27:37 +03:00
|
|
|
|
|
|
|
/* compute offset for entries */
|
|
|
|
#if OMPI_HAVE_SA_LEN
|
|
|
|
length = sizeof(struct sockaddr);
|
|
|
|
|
|
|
|
if (ifr->ifr_addr.sa_len > length) {
|
|
|
|
length = ifr->ifr_addr.sa_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
length += sizeof(ifr->ifr_name);
|
|
|
|
#else
|
|
|
|
length = sizeof(struct ifreq);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rem -= length;
|
|
|
|
ptr += length;
|
|
|
|
|
|
|
|
/* see if we like this entry */
|
2007-04-25 05:55:40 +04:00
|
|
|
if(AF_INET != ifr->ifr_addr.sa_family) {
|
2004-12-17 19:27:37 +03:00
|
|
|
continue;
|
2007-04-25 05:55:40 +04:00
|
|
|
}
|
2004-12-17 19:27:37 +03:00
|
|
|
|
|
|
|
if(ioctl(sd, SIOCGIFFLAGS, ifr) < 0) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0, "opal_ifinit: ioctl(SIOCGIFFLAGS) failed with errno=%d", errno);
|
2004-12-17 19:27:37 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((ifr->ifr_flags & IFF_UP) == 0)
|
|
|
|
continue;
|
2007-01-24 20:40:02 +03:00
|
|
|
#ifdef IFF_SLAVE
|
2007-01-24 19:39:16 +03:00
|
|
|
/* Is this a slave to a load balancer or bonded channel?
|
|
|
|
If so, don't use it -- pick up the master instead */
|
|
|
|
if ((ifr->ifr_flags & IFF_SLAVE) != 0)
|
|
|
|
continue;
|
|
|
|
#endif
|
2004-12-17 19:27:37 +03:00
|
|
|
#if 0
|
|
|
|
if ((ifr->ifr_flags & IFF_LOOPBACK) != 0)
|
|
|
|
continue;
|
|
|
|
#endif
|
2007-04-25 05:55:40 +04:00
|
|
|
|
2004-12-17 19:27:37 +03:00
|
|
|
/* copy entry over into our data structure */
|
|
|
|
strcpy(intf.if_name, ifr->ifr_name);
|
|
|
|
intf.if_flags = ifr->ifr_flags;
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
/* every new address gets its own internal if_index */
|
2005-07-04 05:36:20 +04:00
|
|
|
intf.if_index = opal_list_get_size(&opal_if_list)+1;
|
2007-04-25 05:55:40 +04:00
|
|
|
|
|
|
|
/* assign the kernel index to distinguish different NICs */
|
|
|
|
#ifndef SIOCGIFINDEX
|
|
|
|
intf.if_kernel_index = intf.if_index;
|
2004-01-14 21:24:30 +03:00
|
|
|
#else
|
2004-02-02 19:11:59 +03:00
|
|
|
if(ioctl(sd, SIOCGIFINDEX, ifr) < 0) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0,"opal_ifinit: ioctl(SIOCGIFINDEX) failed with errno=%d", errno);
|
2004-01-14 21:24:30 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#if defined(ifr_ifindex)
|
2007-04-25 05:55:40 +04:00
|
|
|
intf.if_kernel_index = ifr->ifr_ifindex;
|
2004-01-14 21:24:30 +03:00
|
|
|
#elif defined(ifr_index)
|
2007-04-25 05:55:40 +04:00
|
|
|
intf.if_kernel_index = ifr->ifr_index;
|
2004-01-14 21:24:30 +03:00
|
|
|
#else
|
2007-04-25 05:55:40 +04:00
|
|
|
intf.if_kernel_index = -1;
|
2004-01-14 21:24:30 +03:00
|
|
|
#endif
|
2005-03-07 19:00:00 +03:00
|
|
|
#endif /* SIOCGIFINDEX */
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
/* This call returns IPv4 addresses only. Use SIOCGLIFADDR instead */
|
2004-02-02 19:11:59 +03:00
|
|
|
if(ioctl(sd, SIOCGIFADDR, ifr) < 0) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0, "opal_ifinit: ioctl(SIOCGIFADDR) failed with errno=%d", errno);
|
2004-01-14 21:24:30 +03:00
|
|
|
break;
|
|
|
|
}
|
2007-04-25 05:55:40 +04:00
|
|
|
if(AF_INET != ifr->ifr_addr.sa_family) {
|
2004-01-14 21:24:30 +03:00
|
|
|
continue;
|
2007-04-25 05:55:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
/* Bug, FIXME. Works iff sizeof(ifr.ifr_addr) < sizeof(intf.if_addr).
|
|
|
|
This is true for IPv6, but it is a bug in v4 when the source is
|
|
|
|
longer than the target. memcpy isn't what we really want to use
|
|
|
|
here.
|
|
|
|
*/
|
|
|
|
memcpy(&intf.if_addr, &ifr->ifr_addr, sizeof(struct sockaddr_in6));
|
|
|
|
#else
|
2004-01-14 21:24:30 +03:00
|
|
|
memcpy(&intf.if_addr, &ifr->ifr_addr, sizeof(intf.if_addr));
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2004-02-02 19:11:59 +03:00
|
|
|
if(ioctl(sd, SIOCGIFNETMASK, ifr) < 0) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0, "opal_ifinit: ioctl(SIOCGIFNETMASK) failed with errno=%d", errno);
|
2004-01-14 21:24:30 +03:00
|
|
|
continue;
|
|
|
|
}
|
2007-04-25 05:55:40 +04:00
|
|
|
|
|
|
|
/* generate CIDR and assign to netmask */
|
|
|
|
intf.if_mask = prefix(((struct sockaddr_in*) &ifr->ifr_addr)->sin_addr.s_addr);
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
intf_ptr = (opal_if_t*) malloc(sizeof(opal_if_t));
|
2005-04-05 05:57:56 +04:00
|
|
|
OMPI_DEBUG_ZERO(*intf_ptr);
|
2004-01-14 21:24:30 +03:00
|
|
|
if(intf_ptr == 0) {
|
2007-01-31 19:00:15 +03:00
|
|
|
opal_output(0, "opal_ifinit: unable to allocated %lu bytes\n", (unsigned long)sizeof(opal_if_t));
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
2004-02-02 19:11:59 +03:00
|
|
|
memcpy(intf_ptr, &intf, sizeof(intf));
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_list_append(&opal_if_list, (opal_list_item_t*)intf_ptr);
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
2005-04-01 22:02:01 +04:00
|
|
|
free(ifconf.ifc_req);
|
2004-01-14 21:24:30 +03:00
|
|
|
close(sd);
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
#ifdef __linux__ /* Linux does not have SIOCGL*, so parse
|
|
|
|
/proc/net/if_inet6 instead */
|
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
if ((f = fopen("/proc/net/if_inet6", "r"))) {
|
|
|
|
char ifname[IF_NAMESIZE];
|
|
|
|
unsigned int idx, pfxlen, scope, dadstat;
|
|
|
|
struct in6_addr a6;
|
|
|
|
int iter;
|
|
|
|
uint32_t flag;
|
|
|
|
unsigned int addrbyte[16];
|
|
|
|
|
|
|
|
while (fscanf(f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x %2x %2x %2x %2x %20s\n",
|
|
|
|
&addrbyte[0], &addrbyte[1], &addrbyte[2], &addrbyte[3],
|
|
|
|
&addrbyte[4], &addrbyte[5], &addrbyte[6], &addrbyte[7],
|
|
|
|
&addrbyte[8], &addrbyte[9], &addrbyte[10], &addrbyte[11],
|
|
|
|
&addrbyte[12], &addrbyte[13], &addrbyte[14], &addrbyte[15],
|
|
|
|
&idx, &pfxlen, &scope, &dadstat, ifname) != EOF) {
|
|
|
|
opal_if_t intf;
|
|
|
|
opal_if_t *intf_ptr;
|
|
|
|
|
|
|
|
|
|
|
|
OMPI_DEBUG_ZERO(intf);
|
|
|
|
OBJ_CONSTRUCT(&intf, opal_list_item_t);
|
|
|
|
|
|
|
|
for (iter = 0; iter < 16; iter++) {
|
|
|
|
a6.s6_addr[iter] = addrbyte[iter];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we don't want any other scope than global */
|
|
|
|
if (scope != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now construct the opal_if_t */
|
|
|
|
strncpy(intf.if_name, ifname, IF_NAMESIZE);
|
|
|
|
intf.if_index = opal_list_get_size(&opal_if_list)+1;
|
|
|
|
intf.if_kernel_index = (uint16_t) idx;
|
|
|
|
intf.if_addr.sin6_addr = a6;
|
|
|
|
intf.if_addr.sin6_family = AF_INET6;
|
|
|
|
intf.if_addr.sin6_scope_id = scope;
|
|
|
|
intf.if_mask = pfxlen;
|
|
|
|
if (OPAL_SUCCESS == opal_ifindextoflags(opal_ifnametoindex (ifname), &flag)) {
|
|
|
|
intf.if_flags = flag;
|
|
|
|
} else {
|
|
|
|
intf.if_flags = IFF_UP;
|
|
|
|
opal_output(0, "Warning: interface flags not known for %s\n",
|
|
|
|
intf.if_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy new interface information to heap and append
|
|
|
|
to list
|
|
|
|
*/
|
|
|
|
intf_ptr = (opal_if_t*) malloc(sizeof(opal_if_t));
|
|
|
|
OMPI_DEBUG_ZERO(*intf_ptr);
|
|
|
|
if(NULL == intf_ptr) {
|
|
|
|
opal_output(0, "opal_ifinit: unable to allocate %lu bytes\n",
|
|
|
|
(unsigned long)sizeof(opal_if_t));
|
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
memcpy(intf_ptr, &intf, sizeof(intf));
|
|
|
|
opal_list_append(&opal_if_list, (opal_list_item_t*)intf_ptr);
|
|
|
|
} /* of while */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* the bsd ipv6 code below has only been tested on netbsd and linux (glibc>=2.4)
|
|
|
|
*
|
|
|
|
* - getifaddrs() has been included in glibc-2.4, so we can finally use
|
|
|
|
* it in linux, too.
|
|
|
|
* - getifaddrs() should be the prefered way to access interface / address
|
|
|
|
* pairs whenever it is available, for both IPv4 and IPv6
|
|
|
|
* TODO: - more testing
|
|
|
|
* - let configure decide whether getifaddrs() is available,
|
|
|
|
* and use it when available, independent of operating system
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined( __NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \
|
|
|
|
defined(__386BSD__) || defined(__bsdi__) || defined(__APPLE__)
|
|
|
|
/* || defined(__linux__) */
|
|
|
|
|
|
|
|
{
|
|
|
|
struct ifaddrs **ifadd_list;
|
|
|
|
struct ifaddrs *cur_ifaddrs;
|
|
|
|
struct sockaddr_in6* 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;
|
|
|
|
opal_if_t *intf_ptr;
|
|
|
|
struct in6_addr a6;
|
|
|
|
|
|
|
|
/* skip non-ipv6 interface addresses */
|
|
|
|
if(AF_INET6 != cur_ifaddrs->ifa_addr->sa_family) {
|
|
|
|
#if 0
|
|
|
|
printf("skipping non-ipv6 interface %s.\n", cur_ifaddrs->ifa_name);
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip interface if it is down (IFF_UP not set) */
|
|
|
|
if(0 == (cur_ifaddrs->ifa_flags & IFF_UP)) {
|
|
|
|
#if 0
|
|
|
|
printf("skipping non-up interface %s.\n", cur_ifaddrs->ifa_name);
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip interface if it is a loopback device (IFF_LOOPBACK set) */
|
|
|
|
/* or if it is a point-to-point interface */
|
|
|
|
/* TODO: do we really skip p2p? */
|
|
|
|
if(0 != (cur_ifaddrs->ifa_flags & IFF_LOOPBACK)
|
|
|
|
|| 0!= (cur_ifaddrs->ifa_flags & IFF_POINTOPOINT)) {
|
|
|
|
#if 0
|
|
|
|
printf("skipping loopback interface %s.\n", cur_ifaddrs->ifa_name);
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
sin_addr = (struct sockaddr_in6 *) cur_ifaddrs->ifa_addr;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* skip IPv6 address starting with fe80:, as this is supposed to be
|
|
|
|
* link-local scope. sockaddr_in6->sin6_scope_id doesn't always work
|
|
|
|
* TODO: test whether scope id is set to a sensible value on
|
|
|
|
* linux and/or bsd (including osx)
|
|
|
|
*
|
|
|
|
* MacOSX: fe80::... has a scope of 0, but ifconfig -a shows
|
|
|
|
* a scope of 4 on that particular machine,
|
|
|
|
* so the scope returned by getifaddrs() isn't working properly
|
|
|
|
*/
|
|
|
|
|
|
|
|
if((IN6_IS_ADDR_LINKLOCAL (&sin_addr->sin6_addr))) {
|
|
|
|
#if 0
|
|
|
|
printf("skipping link-local ipv6 address on interface \
|
|
|
|
%s with scope %d.\n",
|
|
|
|
cur_ifaddrs->ifa_name, sin_addr->sin6_scope_id);
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
OMPI_DEBUG_ZERO(intf);
|
|
|
|
OBJ_CONSTRUCT(&intf, opal_list_item_t);
|
|
|
|
#if 0
|
|
|
|
char *addr_name = (char *) malloc(48*sizeof(char));
|
|
|
|
inet_ntop(AF_INET6, &sin_addr->sin6_addr, addr_name, 48*sizeof(char));
|
|
|
|
opal_output(0, "ipv6 capable interface %s discovered, address %s.\n",
|
|
|
|
cur_ifaddrs->ifa_name, addr_name);
|
|
|
|
free(addr_name);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* fill values into the opal_if_t */
|
|
|
|
memcpy(&a6, &(sin_addr->sin6_addr), sizeof(struct in6_addr));
|
|
|
|
|
|
|
|
strncpy(intf.if_name, cur_ifaddrs->ifa_name, IF_NAMESIZE);
|
|
|
|
intf.if_index = opal_list_get_size(&opal_if_list) + 1;
|
|
|
|
intf.if_addr.sin6_addr = a6;
|
|
|
|
intf.if_addr.sin6_family = AF_INET6;
|
|
|
|
|
|
|
|
/* since every scope != 0 is ignored, we just set the scope to 0 */
|
|
|
|
intf.if_addr.sin6_scope_id = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* hardcoded netmask, adrian says that's ok
|
|
|
|
*/
|
|
|
|
intf.if_mask = 64;
|
|
|
|
intf.if_flags = cur_ifaddrs->ifa_flags;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: figure out how to gain access to the kernel index
|
|
|
|
* (or create our own), getifaddrs() does not contain such
|
|
|
|
* data
|
|
|
|
*/
|
|
|
|
|
|
|
|
intf.if_kernel_index = (uint16_t) if_nametoindex(cur_ifaddrs->ifa_name);
|
|
|
|
|
|
|
|
intf_ptr = (opal_if_t*) malloc(sizeof(opal_if_t));
|
|
|
|
OMPI_DEBUG_ZERO(*intf_ptr);
|
|
|
|
if(NULL == intf_ptr) {
|
|
|
|
opal_output(0, "opal_ifinit: unable to allocate %lu bytes\n",
|
|
|
|
sizeof(opal_if_t));
|
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
memcpy(intf_ptr, &intf, sizeof(intf));
|
|
|
|
opal_list_append(&opal_if_list, (opal_list_item_t*) intf_ptr);
|
|
|
|
} /* of for loop over ifaddrs list */
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif /* bsd, macosx */
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __sun__
|
|
|
|
/* Solaris IPv6 interface discovery */
|
|
|
|
{
|
|
|
|
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 ( (! 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_ptr;
|
|
|
|
|
|
|
|
OMPI_DEBUG_ZERO(intf);
|
|
|
|
OBJ_CONSTRUCT(&intf, opal_list_item_t);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* copy new interface to heap and append to list */
|
|
|
|
intf_ptr = (opal_if_t*) malloc (sizeof (opal_if_t));
|
|
|
|
OMPI_DEBUG_ZERO (*intf_ptr);
|
|
|
|
if (NULL == intf_ptr) {
|
|
|
|
opal_output (0,
|
|
|
|
"opal_ifinit: unable to allocate %d bytes\n",
|
|
|
|
sizeof (opal_if_t));
|
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
memcpy (intf_ptr, &intf, sizeof (intf));
|
|
|
|
opal_list_append (&opal_if_list, (opal_list_item_t*) intf_ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} /* for */
|
|
|
|
|
|
|
|
if (NULL != lifconf.lifc_buf) {
|
|
|
|
free (lifconf.lifc_buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* __sun__ */
|
|
|
|
|
|
|
|
#endif /* OPAL_WANT_IPV6 */
|
|
|
|
|
2005-12-13 01:01:51 +03:00
|
|
|
#else /* __WINDOWS__ implementation begins */
|
2004-10-22 20:06:05 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
1. check if the interface info list is already populated. If so, return
|
|
|
|
2. get the interface information which is required using WSAIoctl
|
2005-07-04 05:36:20 +04:00
|
|
|
3. construct opal_if_list and populate it with the list of interfaces we have
|
2004-10-22 20:06:05 +04:00
|
|
|
CAVEAT: Does not support the following options which are supported in SIOCGIFCONF
|
|
|
|
- kernel table index
|
|
|
|
- interface name
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MAX_INTERFACES 10 /* Anju: for now assume there are no more than this */
|
2007-04-25 05:55:40 +04:00
|
|
|
int ret;
|
2004-10-22 20:06:05 +04:00
|
|
|
SOCKET sd;
|
|
|
|
INTERFACE_INFO if_list[MAX_INTERFACES];
|
|
|
|
int num_interfaces;
|
|
|
|
unsigned long num_bytes_returned;
|
|
|
|
int i;
|
2007-04-25 05:55:40 +04:00
|
|
|
SOCKADDR_IN *sock_address;
|
2004-10-22 20:06:05 +04:00
|
|
|
unsigned int interface_counter = 0;
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t intf;
|
|
|
|
opal_if_t *intf_ptr;
|
2004-10-22 20:06:05 +04:00
|
|
|
|
|
|
|
/* return if this has been done before */
|
2004-11-05 15:58:14 +03:00
|
|
|
if (already_done) {
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-10-22 20:06:05 +04:00
|
|
|
}
|
2004-11-05 15:58:14 +03:00
|
|
|
already_done = true;
|
2004-10-22 20:06:05 +04:00
|
|
|
|
|
|
|
/* create a socket */
|
|
|
|
sd = WSASocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
|
|
|
|
if (sd == SOCKET_ERROR) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0, "opal_ifinit: WSASocket failed with errno=%d\n",WSAGetLastError());
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-10-22 20:06:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* get the information about the interfaces */
|
|
|
|
if (SOCKET_ERROR == WSAIoctl (sd,
|
|
|
|
SIO_GET_INTERFACE_LIST,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&if_list,
|
2007-04-25 05:55:40 +04:00
|
|
|
sizeof (if_list),
|
2004-10-22 20:06:05 +04:00
|
|
|
&num_bytes_returned,
|
|
|
|
0,
|
2007-04-25 05:55:40 +04:00
|
|
|
0)) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0, "opal_ifinit: WSAIoctl failed with errno=%d\n",WSAGetLastError());
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-10-22 20:06:05 +04:00
|
|
|
}
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
/* create and populate opal_if_list */
|
|
|
|
OBJ_CONSTRUCT (&opal_if_list, opal_list_t);
|
2004-10-22 20:06:05 +04:00
|
|
|
|
|
|
|
|
|
|
|
/* loop through all the interfaces and create the list */
|
|
|
|
num_interfaces = num_bytes_returned / sizeof (INTERFACE_INFO);
|
|
|
|
for (i = 0; i < num_interfaces; ++i) {
|
|
|
|
/* do all this only if the interface is up */
|
|
|
|
if (if_list[i].iiFlags & IFF_UP) {
|
|
|
|
|
2005-07-03 20:22:16 +04:00
|
|
|
OBJ_CONSTRUCT (&intf, opal_list_item_t);
|
2004-10-22 20:06:05 +04:00
|
|
|
|
|
|
|
/* fill in the interface address */
|
|
|
|
memcpy (&intf.if_addr, &(if_list[i].iiAddress), sizeof(intf.if_addr));
|
|
|
|
|
|
|
|
/* fill in the netmask information */
|
|
|
|
memcpy (&intf.if_mask, &(if_list[i].iiNetmask), sizeof(intf.if_mask));
|
|
|
|
|
|
|
|
/* fill in the bcast address */
|
|
|
|
memcpy (&intf.if_bcast, &(if_list[i].iiBroadcastAddress), sizeof(intf.if_bcast));
|
|
|
|
|
|
|
|
/* fill in the flags */
|
|
|
|
intf.if_flags = if_list[i].iiFlags;
|
|
|
|
|
|
|
|
/* fill in the index in the table */
|
2007-04-25 05:55:40 +04:00
|
|
|
intf.if_index = opal_list_get_size(&opal_if_list)+1;
|
2004-10-22 20:06:05 +04:00
|
|
|
|
|
|
|
/* generate the interface name on your own ....
|
|
|
|
loopback: lo
|
|
|
|
Rest: eth0, eth1, ..... */
|
|
|
|
|
|
|
|
if (if_list[i].iiFlags & IFF_LOOPBACK) {
|
|
|
|
sprintf (intf.if_name, "lo");
|
|
|
|
} else {
|
|
|
|
sprintf (intf.if_name, "eth%u", interface_counter++);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy all this into a persistent form and store it in the list */
|
2007-04-25 05:55:40 +04:00
|
|
|
intf_ptr = malloc(sizeof(opal_if_t));
|
2004-10-22 20:06:05 +04:00
|
|
|
if (NULL == intf_ptr) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output (0,"opal_ifinit: Unable to malloc %d bytes",sizeof(opal_list_t));
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
2004-10-22 20:06:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy (intf_ptr, &intf, sizeof(intf));
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_list_append(&opal_if_list, (opal_list_item_t *)intf_ptr);
|
2004-10-22 20:06:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-01 22:02:01 +04:00
|
|
|
/*
|
|
|
|
* Finalize the list of configured interfaces to free malloc'd memory
|
|
|
|
*/
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_iffinalize(void)
|
2005-04-01 22:02:01 +04:00
|
|
|
{
|
2005-07-22 00:20:41 +04:00
|
|
|
if (already_done) {
|
2005-12-13 01:01:51 +03:00
|
|
|
#ifndef __WINDOWS__
|
2005-07-22 00:20:41 +04:00
|
|
|
opal_if_t *intf_ptr;
|
2005-04-01 22:02:01 +04:00
|
|
|
|
2005-07-22 00:20:41 +04:00
|
|
|
while (NULL !=
|
|
|
|
(intf_ptr = (opal_if_t*)opal_list_remove_first(&opal_if_list))) {
|
|
|
|
OBJ_RELEASE(intf_ptr);
|
|
|
|
}
|
|
|
|
OBJ_DESTRUCT(&opal_if_list);
|
2005-04-01 22:02:01 +04:00
|
|
|
#endif
|
2005-08-25 00:27:45 +04:00
|
|
|
already_done = false;
|
2005-07-22 00:20:41 +04:00
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2005-04-01 22:02:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-15 02:24:15 +03:00
|
|
|
/*
|
|
|
|
* Look for interface by name and returns its address
|
|
|
|
* as a dotted decimal formatted string.
|
|
|
|
*/
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
int opal_ifnametoaddr(const char* if_name, struct sockaddr_storage* addr, int length)
|
2004-01-14 21:24:30 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t* intf;
|
|
|
|
int rc = opal_ifinit();
|
2006-02-12 04:33:29 +03:00
|
|
|
if(rc != OPAL_SUCCESS)
|
2004-01-14 21:24:30 +03:00
|
|
|
return rc;
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
2004-01-14 21:24:30 +03:00
|
|
|
if(strcmp(intf->if_name, if_name) == 0) {
|
2004-01-15 03:57:33 +03:00
|
|
|
memcpy(addr, &intf->if_addr, length);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
|
2004-01-29 18:34:47 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for interface by name and returns its
|
2007-04-25 05:55:40 +04:00
|
|
|
* corresponding opal_list index.
|
2004-01-29 18:34:47 +03:00
|
|
|
*/
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_ifnametoindex(const char* if_name)
|
2004-01-29 18:34:47 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t* intf;
|
|
|
|
int rc = opal_ifinit();
|
2006-02-12 04:33:29 +03:00
|
|
|
if(rc != OPAL_SUCCESS)
|
2004-01-29 18:34:47 +03:00
|
|
|
return rc;
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
2004-01-29 18:34:47 +03:00
|
|
|
if(strcmp(intf->if_name, if_name) == 0) {
|
|
|
|
return intf->if_index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-15 02:24:15 +03:00
|
|
|
/*
|
2007-04-25 05:55:40 +04:00
|
|
|
* Look for interface by name and returns its
|
|
|
|
* corresponding kernel index.
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint16_t opal_ifnametokindex(const char* if_name)
|
|
|
|
{
|
|
|
|
opal_if_t* intf;
|
|
|
|
int rc = opal_ifinit();
|
|
|
|
if(rc != OPAL_SUCCESS)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
|
|
|
if(strcmp(intf->if_name, if_name) == 0) {
|
|
|
|
return intf->if_kernel_index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for interface by opal_list index and returns its
|
|
|
|
* corresponding kernel index.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int opal_ifindextokindex(int if_index)
|
|
|
|
{
|
|
|
|
opal_if_t* intf;
|
|
|
|
int rc = opal_ifinit();
|
|
|
|
if(rc != OPAL_SUCCESS)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
|
|
|
if(if_index == intf->if_index) {
|
|
|
|
return intf->if_kernel_index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempt to resolve the adddress (given as either IPv4/IPv6 string
|
|
|
|
* or hostname) and lookup corresponding interface.
|
2004-01-15 02:24:15 +03:00
|
|
|
*/
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_ifaddrtoname(const char* if_addr, char* if_name, int length)
|
2004-01-14 21:24:30 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t* intf;
|
2007-04-25 05:55:40 +04:00
|
|
|
int rc;
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
int error;
|
|
|
|
struct addrinfo hints, *res, *r;
|
|
|
|
#else
|
2005-12-13 01:01:51 +03:00
|
|
|
#ifndef __WINDOWS__
|
2004-10-22 20:06:05 +04:00
|
|
|
in_addr_t inaddr;
|
|
|
|
#else
|
|
|
|
unsigned long inaddr;
|
|
|
|
#endif
|
|
|
|
struct hostent *h;
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2004-10-22 20:06:05 +04:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
rc = opal_ifinit();
|
2006-02-12 04:33:29 +03:00
|
|
|
if (OPAL_SUCCESS != rc) {
|
2004-01-14 21:24:30 +03:00
|
|
|
return rc;
|
2005-03-28 15:55:57 +04:00
|
|
|
}
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = PF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
error = getaddrinfo(if_addr, NULL, &hints, &res);
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
opal_output (0, "opal_ifaddrtoname: unable to resolve %s [Error: %s]\n",
|
|
|
|
if_addr, gai_strerror (error));
|
|
|
|
freeaddrinfo (res);
|
|
|
|
return OPAL_ERR_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (r = res; r != NULL; r = r->ai_next) {
|
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
|
|
|
|
|
|
|
if (AF_INET == r->ai_family) {
|
|
|
|
struct sockaddr_in ipv4;
|
|
|
|
struct sockaddr_in *inaddr;
|
|
|
|
|
|
|
|
inaddr = (struct sockaddr_in*) &intf->if_addr;
|
|
|
|
memcpy (&ipv4, r->ai_addr, r->ai_addrlen);
|
|
|
|
|
|
|
|
if (inaddr->sin_addr.s_addr == ipv4.sin_addr.s_addr) {
|
|
|
|
strncpy(if_name, intf->if_name, length);
|
|
|
|
return OPAL_SUCCESS;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (IN6_ARE_ADDR_EQUAL(&intf->if_addr.sin6_addr,
|
|
|
|
&((struct sockaddr_in6*) r->ai_addr)->sin6_addr)) {
|
|
|
|
strncpy(if_name, intf->if_name, length);
|
|
|
|
return OPAL_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
freeaddrinfo (res);
|
|
|
|
#else
|
|
|
|
inaddr = inet_addr(if_addr);
|
|
|
|
|
2005-03-28 19:42:02 +04:00
|
|
|
if(INADDR_NONE == inaddr) {
|
2004-10-22 20:06:05 +04:00
|
|
|
h = gethostbyname(if_addr);
|
2005-03-28 15:55:57 +04:00
|
|
|
if(0 == h) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_output(0,"opal_ifaddrtoname: unable to resolve %s\n", if_addr);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_FOUND;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
memcpy(&inaddr, h->h_addr, sizeof(inaddr));
|
|
|
|
}
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
2004-01-14 21:24:30 +03:00
|
|
|
if(intf->if_addr.sin_addr.s_addr == inaddr) {
|
|
|
|
strncpy(if_name, intf->if_name, length);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
}
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_FOUND;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
|
2004-01-15 02:24:15 +03:00
|
|
|
/*
|
|
|
|
* Return the number of discovered interface.
|
|
|
|
*/
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_ifcount(void)
|
2004-01-14 21:24:30 +03:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
if(opal_ifinit() != OPAL_SUCCESS)
|
2004-01-14 21:24:30 +03:00
|
|
|
return (-1);
|
2007-04-25 05:55:40 +04:00
|
|
|
return opal_list_get_size(&opal_if_list);
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-15 02:24:15 +03:00
|
|
|
/*
|
2007-04-25 05:55:40 +04:00
|
|
|
* Return the opal_list interface index for the first
|
2004-01-15 02:24:15 +03:00
|
|
|
* interface in our list.
|
|
|
|
*/
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_ifbegin(void)
|
2004-01-14 21:24:30 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t *intf;
|
2006-02-12 04:33:29 +03:00
|
|
|
if(opal_ifinit() != OPAL_SUCCESS)
|
2004-01-14 21:24:30 +03:00
|
|
|
return (-1);
|
2005-07-04 05:36:20 +04:00
|
|
|
intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
2004-07-07 20:28:01 +04:00
|
|
|
if(NULL != intf)
|
2004-01-14 21:24:30 +03:00
|
|
|
return intf->if_index;
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-15 02:24:15 +03:00
|
|
|
/*
|
|
|
|
* Located the current position in the list by if_index and
|
|
|
|
* return the interface index of the next element in our list
|
|
|
|
* (if it exists).
|
|
|
|
*/
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_ifnext(int if_index)
|
2004-01-14 21:24:30 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t *intf;
|
2006-02-12 04:33:29 +03:00
|
|
|
if(opal_ifinit() != OPAL_SUCCESS)
|
2004-01-14 21:24:30 +03:00
|
|
|
return (-1);
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
2004-01-14 21:24:30 +03:00
|
|
|
if(intf->if_index == if_index) {
|
2004-07-07 18:01:55 +04:00
|
|
|
do {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t* if_next = (opal_if_t*)opal_list_get_next(intf);
|
|
|
|
opal_if_t* if_end = (opal_if_t*)opal_list_get_end(&opal_if_list);
|
2004-07-07 20:28:01 +04:00
|
|
|
if (if_next == if_end) {
|
2004-07-07 18:01:55 +04:00
|
|
|
return -1;
|
2004-07-07 20:28:01 +04:00
|
|
|
}
|
|
|
|
intf = if_next;
|
2004-07-07 18:01:55 +04:00
|
|
|
} while(intf->if_index == if_index);
|
|
|
|
return intf->if_index;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-15 02:24:15 +03:00
|
|
|
/*
|
2007-04-25 05:55:40 +04:00
|
|
|
* Lookup the interface by opal_list index and return the
|
2004-01-15 02:24:15 +03:00
|
|
|
* primary address assigned to the interface.
|
|
|
|
*/
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
int opal_ifindextoaddr(int if_index, struct sockaddr_storage* if_addr, unsigned int length)
|
2004-01-14 21:24:30 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t* intf;
|
|
|
|
int rc = opal_ifinit();
|
2006-02-12 04:33:29 +03:00
|
|
|
if(rc != OPAL_SUCCESS)
|
2004-01-14 21:24:30 +03:00
|
|
|
return rc;
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
2004-01-14 21:24:30 +03:00
|
|
|
if(intf->if_index == if_index) {
|
2007-04-25 05:55:40 +04:00
|
|
|
memcpy(if_addr, &intf->if_addr, MIN(length, sizeof (intf->if_addr)));
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-26 21:41:37 +03:00
|
|
|
/*
|
2007-04-25 05:55:40 +04:00
|
|
|
* Lookup the interface by opal_list index and return the
|
2004-01-26 21:41:37 +03:00
|
|
|
* network mask assigned to the interface.
|
|
|
|
*/
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
int opal_ifindextomask(int if_index, uint32_t* if_mask, int length)
|
2004-01-26 21:41:37 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t* intf;
|
|
|
|
int rc = opal_ifinit();
|
2006-02-12 04:33:29 +03:00
|
|
|
if(rc != OPAL_SUCCESS)
|
2004-01-26 21:41:37 +03:00
|
|
|
return rc;
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
2004-01-26 21:41:37 +03:00
|
|
|
if(intf->if_index == if_index) {
|
|
|
|
memcpy(if_mask, &intf->if_mask, length);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-01-26 21:41:37 +03:00
|
|
|
}
|
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-01-26 21:41:37 +03:00
|
|
|
}
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
/*
|
|
|
|
* Lookup the interface by opal_list index and return the
|
|
|
|
* flags assigned to the interface.
|
|
|
|
*
|
|
|
|
* Bug: Make return type portable (compatible with Windows)
|
|
|
|
*/
|
|
|
|
|
|
|
|
int opal_ifindextoflags(int if_index, uint32_t* if_flags)
|
|
|
|
{
|
|
|
|
opal_if_t* intf;
|
|
|
|
int rc = opal_ifinit();
|
|
|
|
if(rc != OPAL_SUCCESS)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
|
|
|
if(intf->if_index == if_index) {
|
|
|
|
memcpy(if_flags, &intf->if_flags, sizeof(uint32_t));
|
|
|
|
return OPAL_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OPAL_ERROR;
|
|
|
|
}
|
|
|
|
|
2004-01-26 21:41:37 +03:00
|
|
|
|
|
|
|
|
2004-01-15 02:24:15 +03:00
|
|
|
/*
|
2007-04-25 05:55:40 +04:00
|
|
|
* Lookup the interface by opal_list index and return
|
2004-01-15 02:24:15 +03:00
|
|
|
* the associated name.
|
|
|
|
*/
|
2004-01-14 21:24:30 +03:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_ifindextoname(int if_index, char* if_name, int length)
|
2004-01-14 21:24:30 +03:00
|
|
|
{
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_if_t *intf;
|
|
|
|
int rc = opal_ifinit();
|
2006-02-12 04:33:29 +03:00
|
|
|
if(rc != OPAL_SUCCESS)
|
2004-01-14 21:24:30 +03:00
|
|
|
return rc;
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
2004-01-14 21:24:30 +03:00
|
|
|
if(intf->if_index == if_index) {
|
|
|
|
strncpy(if_name, intf->if_name, length);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERROR;
|
2004-01-14 21:24:30 +03:00
|
|
|
}
|
2004-10-31 22:01:53 +03:00
|
|
|
|
2006-07-12 00:54:49 +04:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
/*
|
|
|
|
* Lookup the interface by kernel index and return
|
|
|
|
* the associated name.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int opal_ifkindextoname(int if_kindex, char* if_name, int length)
|
|
|
|
{
|
|
|
|
opal_if_t *intf;
|
|
|
|
int rc = opal_ifinit();
|
|
|
|
if(rc != OPAL_SUCCESS)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
for(intf = (opal_if_t*)opal_list_get_first(&opal_if_list);
|
|
|
|
intf != (opal_if_t*)opal_list_get_end(&opal_if_list);
|
|
|
|
intf = (opal_if_t*)opal_list_get_next(intf)) {
|
|
|
|
if(intf->if_kernel_index == if_kindex) {
|
|
|
|
strncpy(if_name, intf->if_name, length);
|
|
|
|
return OPAL_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OPAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
char*
|
|
|
|
opal_sockaddr2str(struct sockaddr_in6 *addr)
|
|
|
|
{
|
|
|
|
char *name = (char *)malloc((NI_MAXHOST + 1) * sizeof(char));
|
|
|
|
int error;
|
|
|
|
socklen_t addrlen;
|
|
|
|
|
|
|
|
OMPI_DEBUG_ZERO(*name);
|
|
|
|
if (NULL == name) {
|
|
|
|
opal_output(0, "opal_sockaddr2str: malloc() failed\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AF_INET6 == addr->sin6_family) {
|
|
|
|
/*
|
|
|
|
hotfix for netbsd: on my netbsd machine, getnameinfo returns an
|
|
|
|
unkown error code.
|
|
|
|
*/
|
|
|
|
#if defined( __NetBSD__)
|
|
|
|
if(NULL == inet_ntop(AF_INET6, &addr->sin6_addr, name, NI_MAXHOST)) {
|
|
|
|
opal_output(0, "opal_sockaddr2str failed with error code %d", errno);
|
|
|
|
free(name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
#else
|
|
|
|
addrlen = sizeof (struct sockaddr_in6);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
/* IPv4 */
|
|
|
|
addrlen = sizeof (struct sockaddr_in);
|
|
|
|
}
|
|
|
|
|
|
|
|
error = getnameinfo((struct sockaddr*)addr, addrlen,
|
|
|
|
name, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
int err = errno;
|
|
|
|
opal_output (0, "opal_sockaddr2str failed:%s (return code %i)\n",
|
|
|
|
gai_strerror(err), error);
|
|
|
|
free (name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-07-12 00:54:49 +04:00
|
|
|
bool
|
2007-04-25 05:55:40 +04:00
|
|
|
opal_ifislocalhost(struct sockaddr_storage *addr)
|
2006-07-12 00:54:49 +04:00
|
|
|
{
|
2007-04-25 05:55:40 +04:00
|
|
|
switch (addr->ss_family) {
|
2006-07-12 00:54:49 +04:00
|
|
|
case AF_INET:
|
|
|
|
{
|
|
|
|
struct sockaddr_in *inaddr = (struct sockaddr_in*) addr;
|
2006-10-01 20:59:44 +04:00
|
|
|
/* if it's in the 127. domain, it shouldn't be routed
|
|
|
|
(0x7f == 127) */
|
|
|
|
if (0x7F000000 == (0x7F000000 & ntohl(inaddr->sin_addr.s_addr))) {
|
2006-07-12 00:54:49 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
case AF_INET6:
|
|
|
|
{
|
|
|
|
struct sockaddr_in6 *inaddr = (struct sockaddr_in6*) addr;
|
|
|
|
if (IN6_IS_ADDR_LOOPBACK (&inaddr->sin6_addr)) {
|
|
|
|
return true; /* Bug, FIXME: check for 127.0.0.1/8 */
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2006-07-12 00:54:49 +04:00
|
|
|
|
|
|
|
default:
|
|
|
|
opal_output(0, "unhandled sa_family %d passed to opal_ifislocalhost",
|
2007-04-25 05:55:40 +04:00
|
|
|
addr->ss_family);
|
2006-07-12 00:54:49 +04:00
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
bool
|
|
|
|
opal_samenetwork(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2,
|
|
|
|
uint32_t prefixlen)
|
|
|
|
{
|
|
|
|
if(addr1->ss_family != addr2->ss_family) {
|
|
|
|
#if 0
|
|
|
|
/* very annoying debug output */
|
|
|
|
opal_output(0, "opal_samenetwork: uncomparable");
|
|
|
|
#endif
|
|
|
|
return false; /* address families must be equal */
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (addr1->ss_family) {
|
|
|
|
case AF_INET:
|
|
|
|
{
|
|
|
|
struct sockaddr_in *inaddr1 = (struct sockaddr_in*) addr1;
|
|
|
|
struct sockaddr_in *inaddr2 = (struct sockaddr_in*) addr2;
|
|
|
|
uint32_t netmask = opal_prefix2netmask (prefixlen);
|
|
|
|
|
|
|
|
if((inaddr1->sin_addr.s_addr & netmask) ==
|
|
|
|
(inaddr2->sin_addr.s_addr & netmask)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
case AF_INET6:
|
|
|
|
{
|
|
|
|
struct sockaddr_in6 *inaddr1 = (struct sockaddr_in6*) addr1;
|
|
|
|
struct sockaddr_in6 *inaddr2 = (struct sockaddr_in6*) addr2;
|
|
|
|
struct in6_addr *a6_1 = (struct in6_addr*) &inaddr1->sin6_addr;
|
|
|
|
struct in6_addr *a6_2 = (struct in6_addr*) &inaddr2->sin6_addr;
|
|
|
|
|
|
|
|
if (64 == prefixlen) {
|
|
|
|
/* prefixlen is always /64, any other case would be routing.
|
|
|
|
Compare the first eight bytes (64 bits) and hope that
|
|
|
|
endianess is not an issue on any system as long as
|
|
|
|
addresses are always stored in network byte order.
|
|
|
|
*/
|
|
|
|
if (((__const uint32_t *) (a6_1))[0] ==
|
|
|
|
((__const uint32_t *) (a6_2))[0] &&
|
|
|
|
((__const uint32_t *) (a6_1))[1] ==
|
|
|
|
((__const uint32_t *) (a6_2))[1]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
opal_output(0, "unhandled sa_family %d passed to opal_samenetwork",
|
|
|
|
addr1->ss_family);
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-07-12 00:54:49 +04:00
|
|
|
|
2004-11-01 17:18:30 +03:00
|
|
|
#define ADDRLEN 100
|
2004-10-31 22:01:53 +03:00
|
|
|
bool
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_ifislocal(char *hostname)
|
2004-10-31 22:01:53 +03:00
|
|
|
{
|
|
|
|
int ret;
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
char addrname[NI_MAXHOST]; /* should be larger than ADDRLEN, but I think
|
|
|
|
they really mean IFNAMESIZE */
|
|
|
|
struct addrinfo hints, *res = NULL;
|
|
|
|
int error;
|
|
|
|
#else
|
|
|
|
char addrname[ADDRLEN + 1];
|
2005-06-01 23:30:05 +04:00
|
|
|
struct hostent *h;
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2005-06-01 23:30:05 +04:00
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
/* opal_ifaddrtoname will complain (rightly) if hostname is not
|
2005-06-01 23:30:05 +04:00
|
|
|
resolveable. check to make sure it's resolveable. If not,
|
|
|
|
definitely not local... */
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = PF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
error = getaddrinfo(hostname, NULL, &hints, &res);
|
|
|
|
if (NULL != res) {
|
|
|
|
freeaddrinfo (res);
|
|
|
|
}
|
|
|
|
if (error) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#else
|
2005-06-01 23:30:05 +04:00
|
|
|
h = gethostbyname(hostname);
|
|
|
|
if (NULL == h) return false;
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2005-07-04 05:36:20 +04:00
|
|
|
ret = opal_ifaddrtoname(hostname, addrname, ADDRLEN);
|
2006-02-12 04:33:29 +03:00
|
|
|
if (OPAL_SUCCESS == ret) return true;
|
2004-10-31 22:01:53 +03:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2005-07-13 08:16:03 +04:00
|
|
|
|
|
|
|
#else /* HAVE_STRUCT_SOCKADDR_IN */
|
|
|
|
|
|
|
|
/* if we don't have struct sockaddr_in, we don't have traditional
|
|
|
|
ethernet devices. Just make everything a no-op error call (except
|
|
|
|
for finailize, which will return successfully) */
|
|
|
|
|
|
|
|
int
|
|
|
|
opal_ifnametoaddr(const char* if_name,
|
2007-04-25 05:55:40 +04:00
|
|
|
struct sockaddr_storage* if_addr, int size)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
opal_ifaddrtoname(const char* if_addr,
|
|
|
|
char* if_name, int size)
|
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-07-13 17:20:22 +04:00
|
|
|
opal_ifnametoindex(const char* if_name)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
uint16_t
|
|
|
|
opal_ifnametokindex(const char* if_name)
|
|
|
|
{
|
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
opal_ifindextokindex(int if_index)
|
|
|
|
{
|
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
2005-07-13 08:16:03 +04:00
|
|
|
int
|
2005-07-13 17:20:22 +04:00
|
|
|
opal_ifcount(void)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-07-13 17:20:22 +04:00
|
|
|
opal_ifbegin(void)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-07-13 17:20:22 +04:00
|
|
|
opal_ifnext(int if_index)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-07-13 17:20:22 +04:00
|
|
|
opal_ifindextoname(int if_index, char* if_name, int length)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2007-04-25 05:55:40 +04:00
|
|
|
opal_ifkindextoname(int kif_index, char* if_name, int length)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2007-04-25 05:55:40 +04:00
|
|
|
opal_ifindextoaddr(int if_index, struct sockaddr_storage* if_addr, int length)
|
|
|
|
{
|
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
opal_ifindextomask(int if_index, struct sockaddr_storage* if_addr, int length)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_NOT_SUPPORTED;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2007-04-25 05:55:40 +04:00
|
|
|
opal_ifislocalhost(struct sockaddr_storage *addr)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
opal_samenetwork(struct sockaddr_storage *addr1,
|
|
|
|
struct sockaddr_storage *addr2, uint32_t prefixlen)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-07-12 00:54:49 +04:00
|
|
|
bool
|
2007-04-25 05:55:40 +04:00
|
|
|
opal_ifislocal(char *hostname)
|
2006-07-12 00:54:49 +04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-07-13 08:16:03 +04:00
|
|
|
int
|
2005-07-13 17:20:22 +04:00
|
|
|
opal_iffinalize(void)
|
2005-07-13 08:16:03 +04:00
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2005-07-13 08:16:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* HAVE_STRUCT_SOCKADDR_IN */
|