root/opal/mca/pmix/pmix4x/pmix/src/util/net.c

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

DEFINITIONS

This source file includes following definitions.
  1. pmix_net_isaddr
  2. hostname_cleanup
  3. get_hostname_buffer
  4. pmix_net_init
  5. pmix_net_finalize
  6. pmix_net_prefix2netmask
  7. pmix_net_islocalhost
  8. pmix_net_samenetwork
  9. pmix_net_addr_isipv4public
  10. pmix_net_get_hostname
  11. pmix_net_get_port
  12. pmix_net_init
  13. pmix_net_finalize
  14. pmix_net_prefix2netmask
  15. pmix_net_islocalhost
  16. pmix_net_samenetwork
  17. pmix_net_addr_isipv4public
  18. pmix_net_get_hostname
  19. pmix_net_get_port

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2005 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2007      Los Alamos National Security, LLC.  All rights
  13  *                         reserved.
  14  * Copyright (c) 2009-2015 Cisco Systems, Inc.  All rights reserved.
  15  * Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
  16  * Copyright (c) 2015      Research Organization for Information Science
  17  *                         and Technology (RIST). All rights reserved.
  18  * $COPYRIGHT$
  19  *
  20  * Additional copyrights may follow
  21  *
  22  * $HEADER$
  23  */
  24 
  25 #include "pmix_config.h"
  26 #include "pmix_common.h"
  27 
  28 #include <stdio.h>
  29 #include <string.h>
  30 #ifdef HAVE_UNISTD_H
  31 #include <unistd.h>
  32 #endif
  33 #include <errno.h>
  34 #ifdef HAVE_SYS_TYPES_H
  35 #include <sys/types.h>
  36 #endif
  37 #ifdef HAVE_SYS_SOCKET_H
  38 #include <sys/socket.h>
  39 #endif
  40 #ifdef HAVE_SYS_SOCKIO_H
  41 #include <sys/sockio.h>
  42 #endif
  43 #ifdef HAVE_SYS_IOCTL_H
  44 #include <sys/ioctl.h>
  45 #endif
  46 #ifdef HAVE_NETINET_IN_H
  47 #include <netinet/in.h>
  48 #endif
  49 #ifdef HAVE_ARPA_INET_H
  50 #include <arpa/inet.h>
  51 #endif
  52 #ifdef HAVE_NET_IF_H
  53 #include <net/if.h>
  54 #endif
  55 #ifdef HAVE_NETDB_H
  56 #include <netdb.h>
  57 #endif
  58 #ifdef HAVE_IFADDRS_H
  59 #include <ifaddrs.h>
  60 #endif
  61 
  62 #include "src/util/net.h"
  63 #include "src/util/output.h"
  64 #include "src/util/argv.h"
  65 #include "src/util/show_help.h"
  66 #include "src/threads/tsd.h"
  67 #include "src/runtime/pmix_rte.h"
  68 
  69 /* this function doesn't depend on sockaddr_h */
  70 bool pmix_net_isaddr(const char *name)
  71 {
  72     struct addrinfo hint, *res = NULL;
  73 
  74     /* initialize the hint */
  75     memset(&hint, '\0', sizeof hint);
  76 
  77     /* indicate that we don't know the family */
  78     hint.ai_family = PF_UNSPEC;
  79     hint.ai_flags = AI_NUMERICHOST;
  80 
  81     if (0 != getaddrinfo(name, NULL, &hint, &res)) {
  82         /* the input wasn't a recognizable address */
  83         return false;
  84     }
  85     /* we don't care what family - all we care is that
  86      * it is indeed an address
  87      */
  88     freeaddrinfo(res);
  89     return true;
  90 }
  91 
  92 #ifdef HAVE_STRUCT_SOCKADDR_IN
  93 
  94 typedef struct private_ipv4_t {
  95     in_addr_t addr;
  96     uint32_t netmask_bits;
  97 } private_ipv4_t;
  98 
  99 static private_ipv4_t* private_ipv4 = NULL;
 100 
 101 static pmix_tsd_key_t hostname_tsd_key;
 102 
 103 
 104 static void
 105 hostname_cleanup(void *value)
 106 {
 107     if (NULL != value) free(value);
 108 }
 109 
 110 
 111 static char*
 112 get_hostname_buffer(void)
 113 {
 114     void *buffer;
 115     int ret;
 116 
 117     ret = pmix_tsd_getspecific(hostname_tsd_key, &buffer);
 118     if (PMIX_SUCCESS != ret) return NULL;
 119 
 120     if (NULL == buffer) {
 121         buffer = (void*) malloc((NI_MAXHOST + 1) * sizeof(char));
 122         ret = pmix_tsd_setspecific(hostname_tsd_key, buffer);
 123     }
 124 
 125     return (char*) buffer;
 126 }
 127 
 128 int
 129 pmix_net_init(void)
 130 {
 131     char **args, *arg;
 132     uint32_t a, b, c, d, bits, addr;
 133     int i, count, found_bad = 0;
 134 
 135     args = pmix_argv_split(pmix_net_private_ipv4, ';');
 136     if( NULL != args ) {
 137         count = pmix_argv_count(args);
 138         private_ipv4 = (private_ipv4_t*)malloc( (count + 1) * sizeof(private_ipv4_t));
 139         if( NULL == private_ipv4 ) {
 140             pmix_output(0, "Unable to allocate memory for the private addresses array" );
 141             pmix_argv_free(args);
 142             goto do_local_init;
 143         }
 144         for( i = 0; i < count; i++ ) {
 145             arg = args[i];
 146 
 147             (void)sscanf( arg, "%u.%u.%u.%u/%u", &a, &b, &c, &d, &bits );
 148 
 149             if( (a > 255) || (b > 255) || (c > 255) ||
 150                 (d > 255) || (bits > 32) ) {
 151                 if (0 == found_bad) {
 152                     pmix_show_help("help-pmix-runtime.txt",
 153                                    "malformed net_private_ipv4",
 154                                    true, args[i]);
 155                     found_bad = 1;
 156                 }
 157                 continue;
 158             }
 159             addr = (a << 24) | (b << 16) | (c << 8) | d;
 160             private_ipv4[i].addr = htonl(addr);
 161             private_ipv4[i].netmask_bits = bits;
 162         }
 163         private_ipv4[i].addr         = 0;
 164         private_ipv4[i].netmask_bits = 0;
 165         pmix_argv_free(args);
 166     }
 167 
 168  do_local_init:
 169     return pmix_tsd_key_create(&hostname_tsd_key, hostname_cleanup);
 170 }
 171 
 172 
 173 int
 174 pmix_net_finalize()
 175 {
 176     free(private_ipv4);
 177     private_ipv4 = NULL;
 178 
 179     return PMIX_SUCCESS;
 180 }
 181 
 182 
 183 /* convert a CIDR prefixlen to netmask (in network byte order) */
 184 uint32_t
 185 pmix_net_prefix2netmask(uint32_t prefixlen)
 186 {
 187     return htonl (((1 << prefixlen) - 1) << (32 - prefixlen));
 188 }
 189 
 190 
 191 bool
 192 pmix_net_islocalhost(const struct sockaddr *addr)
 193 {
 194     switch (addr->sa_family) {
 195     case AF_INET:
 196         {
 197             const struct sockaddr_in *inaddr = (struct sockaddr_in*) addr;
 198             /* if it's in the 127. domain, it shouldn't be routed
 199                (0x7f == 127) */
 200             if (0x7F000000 == (0x7F000000 & ntohl(inaddr->sin_addr.s_addr))) {
 201                 return true;
 202             }
 203             return false;
 204         }
 205         break;
 206 
 207     case AF_INET6:
 208         {
 209             const struct sockaddr_in6 *inaddr = (struct sockaddr_in6*) addr;
 210             if (IN6_IS_ADDR_LOOPBACK (&inaddr->sin6_addr)) {
 211                return true; /* Bug, FIXME: check for 127.0.0.1/8 */
 212             }
 213             return false;
 214         }
 215         break;
 216 
 217     default:
 218         pmix_output(0, "unhandled sa_family %d passed to pmix_net_islocalhost",
 219                     addr->sa_family);
 220         return false;
 221         break;
 222     }
 223 }
 224 
 225 
 226 bool
 227 pmix_net_samenetwork(const struct sockaddr *addr1,
 228                      const struct sockaddr *addr2,
 229                      uint32_t plen)
 230 {
 231     uint32_t prefixlen;
 232 
 233     if(addr1->sa_family != addr2->sa_family) {
 234         return false; /* address families must be equal */
 235     }
 236 
 237     switch (addr1->sa_family) {
 238     case AF_INET:
 239         {
 240             if (0 == plen) {
 241                 prefixlen = 32;
 242             } else {
 243                 prefixlen = plen;
 244             }
 245             struct sockaddr_in inaddr1, inaddr2;
 246             /* Use temporary variables and memcpy's so that we don't
 247                run into bus errors on Solaris/SPARC */
 248             memcpy(&inaddr1, addr1, sizeof(inaddr1));
 249             memcpy(&inaddr2, addr2, sizeof(inaddr2));
 250             uint32_t netmask = pmix_net_prefix2netmask (prefixlen);
 251 
 252             if((inaddr1.sin_addr.s_addr & netmask) ==
 253                (inaddr2.sin_addr.s_addr & netmask)) {
 254                 return true;
 255             }
 256             return false;
 257         }
 258         break;
 259 
 260     case AF_INET6:
 261         {
 262             struct sockaddr_in6 inaddr1, inaddr2;
 263             /* Use temporary variables and memcpy's so that we don't
 264                run into bus errors on Solaris/SPARC */
 265             memcpy(&inaddr1, addr1, sizeof(inaddr1));
 266             memcpy(&inaddr2, addr2, sizeof(inaddr2));
 267             struct in6_addr *a6_1 = (struct in6_addr*) &inaddr1.sin6_addr;
 268             struct in6_addr *a6_2 = (struct in6_addr*) &inaddr2.sin6_addr;
 269 
 270             if (0 == plen) {
 271                 prefixlen = 64;
 272             } else {
 273                 prefixlen = plen;
 274             }
 275             if (64 == prefixlen) {
 276                 /* prefixlen is always /64, any other case would be routing.
 277                    Compare the first eight bytes (64 bits) and hope that
 278                    endianess is not an issue on any system as long as
 279                    addresses are always stored in network byte order.
 280                 */
 281                 if (((const uint32_t *) (a6_1))[0] ==
 282                     ((const uint32_t *) (a6_2))[0] &&
 283                     ((const uint32_t *) (a6_1))[1] ==
 284                     ((const uint32_t *) (a6_2))[1]) {
 285                     return true;
 286                 }
 287             }
 288             return false;
 289         }
 290         break;
 291 
 292     default:
 293         pmix_output(0, "unhandled sa_family %d passed to pmix_samenetwork",
 294                     addr1->sa_family);
 295     }
 296 
 297     return false;
 298 }
 299 
 300 
 301 /**
 302  * Returns true if the given address is a public IPv4 address.
 303  */
 304 bool
 305 pmix_net_addr_isipv4public(const struct sockaddr *addr)
 306 {
 307     switch (addr->sa_family) {
 308         case AF_INET6:
 309             return false;
 310 
 311         case AF_INET:
 312             {
 313                 const struct sockaddr_in *inaddr = (struct sockaddr_in*) addr;
 314                 int i;
 315 
 316                 if( NULL == private_ipv4 ) {
 317                     return true;
 318                 }
 319 
 320                 for( i = 0; private_ipv4[i].addr != 0; i++ ) {
 321                     if( private_ipv4[i].addr == (inaddr->sin_addr.s_addr &
 322                                                  pmix_net_prefix2netmask(private_ipv4[i].netmask_bits)) )
 323                         return false;
 324                 }
 325 
 326             }
 327             return true;
 328         default:
 329             pmix_output (0,
 330                          "unhandled sa_family %d passed to pmix_net_addr_isipv4public\n",
 331                          addr->sa_family);
 332     }
 333 
 334     return false;
 335 }
 336 
 337 
 338 char*
 339 pmix_net_get_hostname(const struct sockaddr *addr)
 340 {
 341     char *name = get_hostname_buffer();
 342     int error;
 343     socklen_t addrlen;
 344     char *p;
 345 
 346     if (NULL == name) {
 347         pmix_output(0, "pmix_sockaddr2str: malloc() failed\n");
 348         return NULL;
 349     }
 350     memset(name, 0, sizeof(*name));
 351 
 352     switch (addr->sa_family) {
 353     case AF_INET:
 354         addrlen = sizeof (struct sockaddr_in);
 355         break;
 356     case AF_INET6:
 357 #if defined( __NetBSD__)
 358         /* hotfix for netbsd: on my netbsd machine, getnameinfo
 359            returns an unkown error code. */
 360         if(NULL == inet_ntop(AF_INET6, &((struct sockaddr_in6*) addr)->sin6_addr,
 361                              name, NI_MAXHOST)) {
 362             pmix_output(0, "pmix_sockaddr2str failed with error code %d", errno);
 363             free(name);
 364             return NULL;
 365         }
 366         return name;
 367 #else
 368         addrlen = sizeof (struct sockaddr_in6);
 369 #endif
 370         break;
 371     default:
 372         free(name);
 373         return NULL;
 374     }
 375 
 376     error = getnameinfo(addr, addrlen,
 377                         name, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
 378 
 379     if (error) {
 380        int err = errno;
 381        pmix_output (0, "pmix_sockaddr2str failed:%s (return code %i)\n",
 382                     gai_strerror(err), error);
 383        free (name);
 384        return NULL;
 385     }
 386     /* strip any trailing % data as it isn't pertinent */
 387     if (NULL != (p = strrchr(name, '%'))) {
 388         *p = '\0';
 389     }
 390     return name;
 391 }
 392 
 393 
 394 int
 395 pmix_net_get_port(const struct sockaddr *addr)
 396 {
 397     switch (addr->sa_family) {
 398     case AF_INET:
 399         return ntohs(((struct sockaddr_in*) addr)->sin_port);
 400         break;
 401 
 402     case AF_INET6:
 403         return ntohs(((struct sockaddr_in6*) addr)->sin6_port);
 404         break;
 405     }
 406 
 407     return -1;
 408 }
 409 
 410 
 411 #else /* HAVE_STRUCT_SOCKADDR_IN */
 412 
 413 int
 414 pmix_net_init()
 415 {
 416     return PMIX_SUCCESS;
 417 }
 418 
 419 
 420 int
 421 pmix_net_finalize()
 422 {
 423     return PMIX_SUCCESS;
 424 }
 425 
 426 
 427 uint32_t
 428 pmix_net_prefix2netmask(uint32_t prefixlen)
 429 {
 430     return 0;
 431 }
 432 
 433 
 434 bool
 435 pmix_net_islocalhost(const struct sockaddr *addr)
 436 {
 437     return false;
 438 }
 439 
 440 
 441 bool
 442 pmix_net_samenetwork(const struct sockaddr *addr1,
 443                      const struct sockaddr *addr2,
 444                      uint32_t prefixlen)
 445 {
 446     return false;
 447 }
 448 
 449 
 450 bool
 451 pmix_net_addr_isipv4public(const struct sockaddr *addr)
 452 {
 453     return false;
 454 }
 455 
 456 
 457 char*
 458 pmix_net_get_hostname(const struct sockaddr *addr)
 459 {
 460     return NULL;
 461 }
 462 
 463 
 464 int
 465 pmix_net_get_port(const struct sockaddr *addr)
 466 {
 467     return -1;
 468 }
 469 
 470 #endif /* HAVE_STRUCT_SOCKADDR_IN */

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