/* * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018-2020 Intel, Inc. All rights reserved. * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "pmix_config.h" #include "pmix_common.h" #include #ifdef HAVE_UNISTD_H # include #endif #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #ifdef HAVE_SYS_SOCKIO_H # include #endif #ifdef HAVE_SYS_IOCTL_H # include #endif #ifdef HAVE_NETINET_IN_H # include #endif #ifdef HAVE_ARPA_INET_H # include #endif #ifdef HAVE_NET_IF_H # include #endif #ifdef HAVE_NETDB_H # include #endif #ifdef HAVE_IFADDRS_H # include #endif #include "src/mca/pif/base/base.h" #include "src/mca/pif/pif.h" #include "src/util/pmix_output.h" #include "src/util/pmix_if.h" static int if_linux_ipv6_open(void); /* Discovers Linux IPv6 interfaces */ pmix_pif_base_component_t pmix_mca_pif_linux_ipv6_component = { PMIX_PIF_BASE_VERSION_2_0_0, /* Component name and version */ .pmix_mca_component_name = "linux_ipv6", PMIX_MCA_BASE_MAKE_VERSION(component, PMIX_MAJOR_VERSION, PMIX_MINOR_VERSION, PMIX_RELEASE_VERSION), /* Component open and close functions */ .pmix_mca_open_component = if_linux_ipv6_open }; /* configure using getifaddrs(3) */ static int if_linux_ipv6_open(void) { FILE *f; if ((f = fopen("/proc/net/if_inet6", "r"))) { /* IF_NAMESIZE is normally 16 on Linux, but the next scanf allows up to 21 bytes */ char ifname[PMIX_IF_NAMESIZE]; unsigned int idx, pfxlen, scope, dadstat; struct in6_addr a6; int iter; uint32_t flag; unsigned int addrbyte[PMIX_IF_NAMESIZE]; memset(addrbyte, 0, PMIX_IF_NAMESIZE * sizeof(unsigned int)); memset(ifname, 0, PMIX_IF_NAMESIZE * sizeof(char)); while (fscanf(f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x %x %x %x %x %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) { pmix_pif_t *intf; pmix_output_verbose( 1, pmix_pif_base_framework.framework_output, "found interface %2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x scope " "%x\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], scope); /* Only interested in global (0x00) scope */ if (scope != 0x00) { pmix_output_verbose( 1, pmix_pif_base_framework.framework_output, "skipping interface %2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x " "scope %x\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], scope); continue; } intf = PMIX_NEW(pmix_pif_t); if (NULL == intf) { pmix_output(0, "pmix_ifinit: unable to allocate %lu bytes\n", (unsigned long) sizeof(pmix_pif_t)); fclose(f); return PMIX_ERR_OUT_OF_RESOURCE; } intf->af_family = AF_INET6; for (iter = 0; iter < 16; iter++) { a6.s6_addr[iter] = addrbyte[iter]; } /* now construct the pmix_pif_t */ pmix_strncpy(intf->if_name, ifname, PMIX_IF_NAMESIZE - 1); intf->if_index = pmix_list_get_size(&pmix_if_list) + 1; intf->if_kernel_index = (uint16_t) idx; ((struct sockaddr_in6 *) &intf->if_addr)->sin6_addr = a6; ((struct sockaddr_in6 *) &intf->if_addr)->sin6_family = AF_INET6; ((struct sockaddr_in6 *) &intf->if_addr)->sin6_scope_id = scope; intf->if_mask = pfxlen; if (PMIX_SUCCESS == pmix_ifindextoflags(pmix_ifnametoindex(ifname), &flag)) { intf->if_flags = flag; } else { intf->if_flags = IFF_UP; } /* copy new interface information to heap and append to list */ pmix_list_append(&pmix_if_list, &(intf->super)); pmix_output_verbose( 1, pmix_pif_base_framework.framework_output, "added interface %2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x:%2x%2x\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]); } /* of while */ fclose(f); } return PMIX_SUCCESS; }