root/opal/mca/pmix/pmix4x/pmix/src/mca/pif/solaris_ipv6/pif_solaris_ipv6.c

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

DEFINITIONS

This source file includes following definitions.
  1. if_solaris_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) 2016      Research Organization for Information Science
   5  *                         and Technology (RIST). All rights reserved.
   6  * Copyright (c) 2016-2018 Intel, Inc.  All rights reserved.
   7  * $COPYRIGHT$
   8  *
   9  * Additional copyrights may follow
  10  *
  11  * $HEADER$
  12  */
  13 
  14 #include "pmix_config.h"
  15 #include "pmix_common.h"
  16 
  17 #include <string.h>
  18 #ifdef HAVE_UNISTD_H
  19 #include <unistd.h>
  20 #endif
  21 #include <errno.h>
  22 #ifdef HAVE_SYS_TYPES_H
  23 #include <sys/types.h>
  24 #endif
  25 #ifdef HAVE_SYS_SOCKET_H
  26 #include <sys/socket.h>
  27 #endif
  28 #ifdef HAVE_SYS_SOCKIO_H
  29 #include <sys/sockio.h>
  30 #endif
  31 #ifdef HAVE_SYS_IOCTL_H
  32 #include <sys/ioctl.h>
  33 #endif
  34 #ifdef HAVE_NETINET_IN_H
  35 #include <netinet/in.h>
  36 #endif
  37 #ifdef HAVE_ARPA_INET_H
  38 #include <arpa/inet.h>
  39 #endif
  40 #ifdef HAVE_NET_IF_H
  41 #if defined(__APPLE__) && defined(_LP64)
  42 /* Apple engineering suggested using options align=power as a
  43    workaround for a bug in OS X 10.4 (Tiger) that prevented ioctl(...,
  44    SIOCGIFCONF, ...) from working properly in 64 bit mode on Power PC.
  45    It turns out that the underlying issue is the size of struct
  46    ifconf, which the kernel expects to be 12 and natural 64 bit
  47    alignment would make 16.  The same bug appears in 64 bit mode on
  48    Intel macs, but align=power is a no-op there, so instead, use the
  49    pack pragma to instruct the compiler to pack on 4 byte words, which
  50    has the same effect as align=power for our needs and works on both
  51    Intel and Power PC Macs. */
  52 #pragma pack(push,4)
  53 #endif
  54 #include <net/if.h>
  55 #if defined(__APPLE__) && defined(_LP64)
  56 #pragma pack(pop)
  57 #endif
  58 #endif
  59 #ifdef HAVE_NETDB_H
  60 #include <netdb.h>
  61 #endif
  62 #ifdef HAVE_IFADDRS_H
  63 #include <ifaddrs.h>
  64 #endif
  65 
  66 #include "src/util/output.h"
  67 #include "src/util/pif.h"
  68 #include "src/mca/pif/pif.h"
  69 #include "src/mca/pif/base/base.h"
  70 
  71 static int if_solaris_ipv6_open(void);
  72 
  73 /* Discovers Solaris IPv6 interfaces */
  74 pmix_pif_base_component_t mca_pif_solaris_ipv6_component = {
  75     /* First, the mca_component_t struct containing meta information
  76        about the component itself */
  77     .base = {
  78         PMIX_PIF_BASE_VERSION_2_0_0,
  79 
  80         /* Component name and version */
  81         "solaris_ipv6",
  82         PMIX_MAJOR_VERSION,
  83         PMIX_MINOR_VERSION,
  84         PMIX_RELEASE_VERSION,
  85 
  86         /* Component open and close functions */
  87         if_solaris_ipv6_open,
  88         NULL
  89     },
  90     .data = {
  91         /* This component is checkpointable */
  92         PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT
  93     },
  94 };
  95 
  96 /* configure using getifaddrs(3) */
  97 static int if_solaris_ipv6_open(void)
  98 {
  99     int i;
 100     int sd;
 101     int error;
 102     uint16_t kindex;
 103     struct lifnum lifnum;
 104     struct lifconf lifconf;
 105     struct lifreq *lifreq, lifquery;
 106 
 107     sd = socket (AF_INET6, SOCK_DGRAM, 0);
 108     if (sd < 0) {
 109         pmix_output (0, "pmix_ifinit: unable to open IPv6 socket\n");
 110         return PMIX_ERROR;
 111     }
 112 
 113     /* we only ask for IPv6; IPv4 discovery has already been done */
 114     lifnum.lifn_family = AF_INET6;
 115     lifnum.lifn_flags = 0;
 116     lifnum.lifn_count = 0;
 117 
 118     /* get the number of interfaces in the system */
 119     error = ioctl (sd, SIOCGLIFNUM, &lifnum);
 120     if (error < 0) {
 121         pmix_output (0,
 122                      "pmix_ifinit: ioctl SIOCGLIFNUM failed with errno=%d\n", errno);
 123         return PMIX_ERROR;
 124     }
 125 
 126     memset (&lifconf, 0, sizeof (struct lifconf));
 127     memset (&lifquery, 0, sizeof (struct lifreq));
 128     lifconf.lifc_family = AF_INET6;
 129     lifconf.lifc_flags = 0;
 130     lifconf.lifc_len = lifnum.lifn_count * sizeof (struct lifreq) * 2;
 131     lifconf.lifc_buf = malloc (lifconf.lifc_len);
 132     if (NULL == lifconf.lifc_buf) {
 133         pmix_output (0, "pmix_ifinit: IPv6 discovery: malloc() failed\n");
 134         return PMIX_ERR_OUT_OF_RESOURCE;
 135     }
 136 
 137     memset (lifconf.lifc_buf, 0, lifconf.lifc_len);
 138 
 139     error = ioctl (sd, SIOCGLIFCONF, &lifconf);
 140     if (error < 0) {
 141         pmix_output (0,
 142                      "pmix_ifinit: IPv6 SIOCGLIFCONF failed with errno=%d\n", errno);
 143     }
 144 
 145     for (i = 0; i + sizeof (struct lifreq) <= lifconf.lifc_len;
 146          i += sizeof (*lifreq)) {
 147 
 148         lifreq = (struct lifreq *)((caddr_t)lifconf.lifc_buf + i);
 149         pmix_strncpy (lifquery.lifr_name, lifreq->lifr_name,
 150                  sizeof (lifquery.lifr_name)-1);
 151 
 152         /* lookup kernel index */
 153         error = ioctl (sd, SIOCGLIFINDEX, &lifquery);
 154         if (error < 0) {
 155             pmix_output (0,
 156                          "pmix_ifinit: SIOCGLIFINDEX failed with errno=%d\n", errno);
 157             return PMIX_ERROR;
 158         }
 159         kindex = lifquery.lifr_index;
 160 
 161         /* lookup interface flags */
 162         error = ioctl (sd, SIOCGLIFFLAGS, &lifquery);
 163         if (error < 0) {
 164             pmix_output (0,
 165                          "pmix_ifinit: SIOCGLIFFLAGS failed with errno=%d\n", errno);
 166             return PMIX_ERROR;
 167         }
 168 
 169         if (AF_INET6 == lifreq->lifr_addr.ss_family) {
 170             struct sockaddr_in6* my_addr = (struct sockaddr_in6*) &lifreq->lifr_addr;
 171             /* we surely want to check for sin6_scope_id, but Solaris
 172                does not set it correctly, so we have to look for
 173                global scope. For now, global is anything which is
 174                neither loopback nor link local.
 175 
 176                Bug, FIXME: site-local, multicast, ... missing
 177                Check for 2000::/3?
 178             */
 179             if ( (!pmix_if_retain_loopback && !IN6_IS_ADDR_LOOPBACK (&my_addr->sin6_addr)) &&
 180                  (! IN6_IS_ADDR_LINKLOCAL (&my_addr->sin6_addr))) {
 181                 /* create interface for newly found address */
 182                 pmix_pif_t *intf;
 183 
 184                 intf = PMIX_NEW(pmix_pif_t);
 185                 if (NULL == intf) {
 186                     pmix_output (0,
 187                                  "pmix_ifinit: unable to allocate %d bytes\n",
 188                                  sizeof (pmix_pif_t));
 189                     return PMIX_ERR_OUT_OF_RESOURCE;
 190                 }
 191                 intf->af_family = AF_INET6;
 192 
 193                 pmix_strncpy (intf->if_name, lifreq->lifr_name, IF_NAMESIZE-1);
 194                 intf->if_index = pmix_list_get_size(&pmix_if_list)+1;
 195                 memcpy(&intf->if_addr, my_addr, sizeof (*my_addr));
 196                 intf->if_mask = 64;
 197                 /* lifrq flags are uint64_t */
 198                 intf->if_flags =
 199                     (uint32_t)(0x00000000ffffffff) & lifquery.lifr_flags;
 200 
 201                 /* append to list */
 202                 pmix_list_append (&pmix_if_list, &(intf->super));
 203             }
 204         }
 205     } /* for */
 206 
 207     if (NULL != lifconf.lifc_buf) {
 208         free (lifconf.lifc_buf);
 209     }
 210 
 211     return PMIX_SUCCESS;
 212 }

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