/* * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "opal_config.h" #include #include #include "opal/constants.h" #include "opal/mca/if/if.h" #include "opal/util/output.h" #include "opal/util/string_copy.h" static int if_bsdx_open(void); /* Supports specific flavors of BSD: * NetBSD * FreeBSD * OpenBSD * DragonFly */ opal_if_base_component_t mca_if_bsdx_ipv4_component = { /* First, the mca_component_t struct containing meta information about the component itself */ {OPAL_IF_BASE_VERSION_2_0_0, /* Component name and version */ "bsdx_ipv4", OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, OPAL_RELEASE_VERSION, /* Component open and close functions */ if_bsdx_open, NULL}, {/* This component is checkpointable */ MCA_BASE_METADATA_PARAM_CHECKPOINT}, }; /* convert a netmask (in network byte order) to CIDR notation */ static int prefix(uint32_t netmask) { uint32_t mask = ntohl(netmask); int plen = 0; if (0 == mask) { plen = 32; } else { while ((mask % 2) == 0) { plen += 1; mask /= 2; } } return (32 - plen); } /* configure using getifaddrs(3) */ static int if_bsdx_open(void) { struct ifaddrs **ifadd_list; struct ifaddrs *cur_ifaddrs; struct sockaddr_in *sin_addr; /* * the manpage claims that getifaddrs() allocates the memory, * and freeifaddrs() is later used to release the allocated memory. * however, without this malloc the call to getifaddrs() segfaults */ ifadd_list = (struct ifaddrs **) malloc(sizeof(struct ifaddrs *)); /* create the linked list of ifaddrs structs */ if (getifaddrs(ifadd_list) < 0) { opal_output(0, "opal_ifinit: getifaddrs() failed with error=%d\n", errno); return OPAL_ERROR; } for (cur_ifaddrs = *ifadd_list; NULL != cur_ifaddrs; cur_ifaddrs = cur_ifaddrs->ifa_next) { opal_if_t *intf; struct in_addr a4; /* skip non- af_inet interface addresses */ if (AF_INET != cur_ifaddrs->ifa_addr->sa_family) { continue; } /* skip interface if it is down (IFF_UP not set) */ if (0 == (cur_ifaddrs->ifa_flags & IFF_UP)) { continue; } /* skip interface if it is a loopback device (IFF_LOOPBACK set) */ if (!opal_if_retain_loopback && 0 != (cur_ifaddrs->ifa_flags & IFF_LOOPBACK)) { continue; } /* or if it is a point-to-point interface */ /* TODO: do we really skip p2p? */ if (0 != (cur_ifaddrs->ifa_flags & IFF_POINTOPOINT)) { continue; } sin_addr = (struct sockaddr_in *) cur_ifaddrs->ifa_addr; intf = OBJ_NEW(opal_if_t); if (NULL == intf) { opal_output(0, "opal_ifinit: unable to allocate %d bytes\n", (int) sizeof(opal_if_t)); return OPAL_ERR_OUT_OF_RESOURCE; } intf->af_family = AF_INET; /* fill values into the opal_if_t */ memcpy(&a4, &(sin_addr->sin_addr), sizeof(struct in_addr)); opal_string_copy(intf->if_name, cur_ifaddrs->ifa_name, OPAL_IF_NAMESIZE); intf->if_index = opal_list_get_size(&opal_if_list) + 1; ((struct sockaddr_in *) &intf->if_addr)->sin_addr = a4; ((struct sockaddr_in *) &intf->if_addr)->sin_family = AF_INET; ((struct sockaddr_in *) &intf->if_addr)->sin_len = cur_ifaddrs->ifa_addr->sa_len; intf->if_mask = prefix(sin_addr->sin_addr.s_addr); intf->if_flags = cur_ifaddrs->ifa_flags; intf->if_kernel_index = (uint16_t) if_nametoindex(cur_ifaddrs->ifa_name); opal_list_append(&opal_if_list, &(intf->super)); } /* of for loop over ifaddrs list */ return OPAL_SUCCESS; }