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

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