Path: blob/master/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
3156 views
/* Copyright libuv project contributors. All rights reserved.1*2* Permission is hereby granted, free of charge, to any person obtaining a copy3* of this software and associated documentation files (the "Software"), to4* deal in the Software without restriction, including without limitation the5* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or6* sell copies of the Software, and to permit persons to whom the Software is7* furnished to do so, subject to the following conditions:8*9* The above copyright notice and this permission notice shall be included in10* all copies or substantial portions of the Software.11*12* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR13* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,14* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE15* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER16* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING17* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS18* IN THE SOFTWARE.19*/2021#include "uv.h"22#include "internal.h"2324#include <errno.h>25#include <stddef.h>2627#include <ifaddrs.h>28#include <net/if.h>29#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)30#include <net/if_dl.h>31#endif3233#if defined(__HAIKU__)34#define IFF_RUNNING IFF_LINK35#endif3637static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {38if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))39return 1;40if (ent->ifa_addr == NULL)41return 1;42#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)43/*44* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family`45* equals `AF_LINK`. Otherwise, the result depends on the operating46* system with `AF_LINK` or `PF_INET`.47*/48if (exclude_type == UV__EXCLUDE_IFPHYS)49return (ent->ifa_addr->sa_family != AF_LINK);50#endif51#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \52defined(__HAIKU__)53/*54* On BSD getifaddrs returns information related to the raw underlying55* devices. We're not interested in this information.56*/57if (ent->ifa_addr->sa_family == AF_LINK)58return 1;59#elif defined(__NetBSD__) || defined(__OpenBSD__)60if (ent->ifa_addr->sa_family != PF_INET &&61ent->ifa_addr->sa_family != PF_INET6)62return 1;63#endif64return 0;65}6667int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {68struct ifaddrs* addrs;69struct ifaddrs* ent;70uv_interface_address_t* address;71#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)72int i;73#endif7475*count = 0;76*addresses = NULL;7778if (getifaddrs(&addrs) != 0)79return UV__ERR(errno);8081/* Count the number of interfaces */82for (ent = addrs; ent != NULL; ent = ent->ifa_next) {83if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))84continue;85(*count)++;86}8788if (*count == 0) {89freeifaddrs(addrs);90return 0;91}9293/* Make sure the memory is initiallized to zero using calloc() */94*addresses = uv__calloc(*count, sizeof(**addresses));9596if (*addresses == NULL) {97freeifaddrs(addrs);98return UV_ENOMEM;99}100101address = *addresses;102103for (ent = addrs; ent != NULL; ent = ent->ifa_next) {104if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))105continue;106107address->name = uv__strdup(ent->ifa_name);108109if (ent->ifa_addr->sa_family == AF_INET6) {110address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);111} else {112address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);113}114115if (ent->ifa_netmask == NULL) {116memset(&address->netmask, 0, sizeof(address->netmask));117} else if (ent->ifa_netmask->sa_family == AF_INET6) {118address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);119} else {120address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);121}122123address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);124125address++;126}127128#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)129/* Fill in physical addresses for each interface */130for (ent = addrs; ent != NULL; ent = ent->ifa_next) {131if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))132continue;133134address = *addresses;135136for (i = 0; i < *count; i++) {137if (strcmp(address->name, ent->ifa_name) == 0) {138struct sockaddr_dl* sa_addr;139sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);140memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));141}142address++;143}144}145#endif146147freeifaddrs(addrs);148149return 0;150}151152153void uv_free_interface_addresses(uv_interface_address_t* addresses,154int count) {155int i;156157for (i = 0; i < count; i++) {158uv__free(addresses[i].name);159}160161uv__free(addresses);162}163164165