root/opal/mca/if/bsdx_ipv6/if_bsdx_ipv6.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. if_bsdx_ipv6_open

   1 /*
   2  * Copyright (c) 2010      Cisco Systems, Inc.  All rights reserved.
   3  * Copyright (c) 2010      Oracle and/or its affiliates.  All rights reserved.
   4  * Copyright (c) 2018      Amazon.com, Inc. or its affiliates.  All Rights
   5  *                         reserved.
   6  * $COPYRIGHT$
   7  *
   8  * Additional copyrights may follow
   9  *
  10  * $HEADER$
  11  */
  12 
  13 #include "opal_config.h"
  14 #include "opal/constants.h"
  15 #include "opal/util/output.h"
  16 #include "opal/util/string_copy.h"
  17 
  18 #include <string.h>
  19 #ifdef HAVE_UNISTD_H
  20 #include <unistd.h>
  21 #endif
  22 #include <errno.h>
  23 #ifdef HAVE_SYS_TYPES_H
  24 #include <sys/types.h>
  25 #endif
  26 #ifdef HAVE_SYS_SOCKET_H
  27 #include <sys/socket.h>
  28 #endif
  29 #ifdef HAVE_SYS_SOCKIO_H
  30 #include <sys/sockio.h>
  31 #endif
  32 #ifdef HAVE_SYS_IOCTL_H
  33 #include <sys/ioctl.h>
  34 #endif
  35 #ifdef HAVE_NETINET_IN_H
  36 #include <netinet/in.h>
  37 #endif
  38 #ifdef HAVE_ARPA_INET_H
  39 #include <arpa/inet.h>
  40 #endif
  41 #ifdef HAVE_NET_IF_H
  42 #include <net/if.h>
  43 #endif
  44 #ifdef HAVE_NETDB_H
  45 #include <netdb.h>
  46 #endif
  47 #ifdef HAVE_IFADDRS_H
  48 #include <ifaddrs.h>
  49 #endif
  50 
  51 #include "opal/mca/if/if.h"
  52 #include "opal/mca/if/base/base.h"
  53 
  54 static int if_bsdx_ipv6_open(void);
  55 
  56 /* Discovers IPv6 interfaces for:
  57  *
  58  * NetBSD
  59  * OpenBSD
  60  * FreeBSD
  61  * 386BSD
  62  * bsdi
  63  * Apple
  64  */
  65 opal_if_base_component_t mca_if_bsdx_ipv6_component = {
  66     /* First, the mca_component_t struct containing meta information
  67        about the component itself */
  68     {
  69         OPAL_IF_BASE_VERSION_2_0_0,
  70 
  71         /* Component name and version */
  72         "bsdx_ipv6",
  73         OPAL_MAJOR_VERSION,
  74         OPAL_MINOR_VERSION,
  75         OPAL_RELEASE_VERSION,
  76 
  77         /* Component open and close functions */
  78         if_bsdx_ipv6_open,
  79         NULL
  80     },
  81     {
  82         /* This component is checkpointable */
  83         MCA_BASE_METADATA_PARAM_CHECKPOINT
  84     },
  85 };
  86 
  87 /* configure using getifaddrs(3) */
  88 static int if_bsdx_ipv6_open(void)
  89 {
  90 #if OPAL_ENABLE_IPV6
  91     struct ifaddrs **ifadd_list;
  92     struct ifaddrs *cur_ifaddrs;
  93     struct sockaddr_in6* sin_addr;
  94 
  95     opal_output_verbose(1, opal_if_base_framework.framework_output,
  96                         "searching for IPv6 interfaces");
  97 
  98     /*
  99      * the manpage claims that getifaddrs() allocates the memory,
 100      * and freeifaddrs() is later used to release the allocated memory.
 101      * however, without this malloc the call to getifaddrs() segfaults
 102      */
 103     ifadd_list = (struct ifaddrs **) malloc(sizeof(struct ifaddrs*));
 104 
 105     /* create the linked list of ifaddrs structs */
 106     if (getifaddrs(ifadd_list) < 0) {
 107         opal_output(0, "opal_ifinit: getifaddrs() failed with error=%d\n",
 108                     errno);
 109         free(ifadd_list);
 110         return OPAL_ERROR;
 111     }
 112 
 113     for (cur_ifaddrs = *ifadd_list; NULL != cur_ifaddrs;
 114          cur_ifaddrs = cur_ifaddrs->ifa_next) {
 115         opal_if_t *intf;
 116         struct in6_addr a6;
 117 
 118         /* skip non-ipv6 interface addresses */
 119         if (AF_INET6 != cur_ifaddrs->ifa_addr->sa_family) {
 120             opal_output_verbose(1, opal_if_base_framework.framework_output,
 121                                 "skipping non-ipv6 interface %s[%d].\n",
 122                                 cur_ifaddrs->ifa_name, (int)cur_ifaddrs->ifa_addr->sa_family);
 123             continue;
 124         }
 125 
 126         /* skip interface if it is down (IFF_UP not set) */
 127         if (0 == (cur_ifaddrs->ifa_flags & IFF_UP)) {
 128             opal_output_verbose(1, opal_if_base_framework.framework_output,
 129                                 "skipping non-up interface %s.\n", cur_ifaddrs->ifa_name);
 130             continue;
 131         }
 132 
 133         /* skip interface if it is a loopback device (IFF_LOOPBACK set) */
 134         if (!opal_if_retain_loopback && 0 != (cur_ifaddrs->ifa_flags & IFF_LOOPBACK)) {
 135             opal_output_verbose(1, opal_if_base_framework.framework_output,
 136                                 "skipping loopback interface %s.\n", cur_ifaddrs->ifa_name);
 137             continue;
 138         }
 139 
 140         /* or if it is a point-to-point interface */
 141         /* TODO: do we really skip p2p? */
 142         if (0!= (cur_ifaddrs->ifa_flags & IFF_POINTOPOINT)) {
 143             opal_output_verbose(1, opal_if_base_framework.framework_output,
 144                                 "skipping p2p interface %s.\n", cur_ifaddrs->ifa_name);
 145             continue;
 146         }
 147 
 148         sin_addr = (struct sockaddr_in6 *) cur_ifaddrs->ifa_addr;
 149 
 150         /*
 151          * skip IPv6 address starting with fe80:, as this is supposed to be
 152          * link-local scope. sockaddr_in6->sin6_scope_id doesn't always work
 153          * TODO: test whether scope id is set to a sensible value on
 154          * linux and/or bsd (including osx)
 155          *
 156          * MacOSX: fe80::... has a scope of 0, but ifconfig -a shows
 157          * a scope of 4 on that particular machine,
 158          * so the scope returned by getifaddrs() isn't working properly
 159          */
 160 
 161         if ((IN6_IS_ADDR_LINKLOCAL (&sin_addr->sin6_addr))) {
 162             opal_output_verbose(1, opal_if_base_framework.framework_output,
 163                                 "skipping link-local ipv6 address on interface "
 164                                 "%s with scope %d.\n",
 165                                 cur_ifaddrs->ifa_name, sin_addr->sin6_scope_id);
 166             continue;
 167         }
 168 
 169         if (0 < opal_output_get_verbosity(opal_if_base_framework.framework_output)) {
 170             char *addr_name = (char *) malloc(48*sizeof(char));
 171             inet_ntop(AF_INET6, &sin_addr->sin6_addr, addr_name, 48*sizeof(char));
 172             opal_output(0, "ipv6 capable interface %s discovered, address %s.\n",
 173                         cur_ifaddrs->ifa_name, addr_name);
 174             free(addr_name);
 175         }
 176 
 177         /* fill values into the opal_if_t */
 178         memcpy(&a6, &(sin_addr->sin6_addr), sizeof(struct in6_addr));
 179 
 180         intf = OBJ_NEW(opal_if_t);
 181         if (NULL == intf) {
 182             opal_output(0, "opal_ifinit: unable to allocate %lu bytes\n",
 183                         sizeof(opal_if_t));
 184             free(ifadd_list);
 185             return OPAL_ERR_OUT_OF_RESOURCE;
 186         }
 187         intf->af_family = AF_INET6;
 188         opal_string_copy(intf->if_name, cur_ifaddrs->ifa_name, IF_NAMESIZE);
 189         intf->if_index = opal_list_get_size(&opal_if_list) + 1;
 190         ((struct sockaddr_in6*) &intf->if_addr)->sin6_addr = a6;
 191         ((struct sockaddr_in6*) &intf->if_addr)->sin6_family = AF_INET6;
 192 
 193         /* since every scope != 0 is ignored, we just set the scope to 0 */
 194         ((struct sockaddr_in6*) &intf->if_addr)->sin6_scope_id = 0;
 195 
 196         /*
 197          * hardcoded netmask, adrian says that's ok
 198          */
 199         intf->if_mask = 64;
 200         intf->if_flags = cur_ifaddrs->ifa_flags;
 201 
 202         /*
 203          * FIXME: figure out how to gain access to the kernel index
 204          * (or create our own), getifaddrs() does not contain such
 205          * data
 206          */
 207         intf->if_kernel_index =
 208             (uint16_t) if_nametoindex(cur_ifaddrs->ifa_name);
 209         opal_list_append(&opal_if_list, &(intf->super));
 210     }   /*  of for loop over ifaddrs list */
 211 
 212     free(ifadd_list);
 213 #endif  /* OPAL_ENABLE_IPV6 */
 214 
 215     return OPAL_SUCCESS;
 216 }
 217 
 218 

/* [<][>][^][v][top][bottom][index][help] */