1e66f31c5Sopenharmony_ci/* Copyright libuv project contributors. All rights reserved.
2e66f31c5Sopenharmony_ci *
3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the
6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions:
9e66f31c5Sopenharmony_ci *
10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software.
12e66f31c5Sopenharmony_ci *
13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19e66f31c5Sopenharmony_ci * IN THE SOFTWARE.
20e66f31c5Sopenharmony_ci */
21e66f31c5Sopenharmony_ci
22e66f31c5Sopenharmony_ci#include "uv.h"
23e66f31c5Sopenharmony_ci#include "internal.h"
24e66f31c5Sopenharmony_ci
25e66f31c5Sopenharmony_ci#include <errno.h>
26e66f31c5Sopenharmony_ci#include <stddef.h>
27e66f31c5Sopenharmony_ci
28e66f31c5Sopenharmony_ci#include <ifaddrs.h>
29e66f31c5Sopenharmony_ci#include <net/if.h>
30e66f31c5Sopenharmony_ci#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
31e66f31c5Sopenharmony_ci#include <net/if_dl.h>
32e66f31c5Sopenharmony_ci#endif
33e66f31c5Sopenharmony_ci
34e66f31c5Sopenharmony_ci#if defined(__HAIKU__)
35e66f31c5Sopenharmony_ci#define IFF_RUNNING IFF_LINK
36e66f31c5Sopenharmony_ci#endif
37e66f31c5Sopenharmony_ci
38e66f31c5Sopenharmony_cistatic int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
39e66f31c5Sopenharmony_ci  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
40e66f31c5Sopenharmony_ci    return 1;
41e66f31c5Sopenharmony_ci  if (ent->ifa_addr == NULL)
42e66f31c5Sopenharmony_ci    return 1;
43e66f31c5Sopenharmony_ci#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
44e66f31c5Sopenharmony_ci  /*
45e66f31c5Sopenharmony_ci   * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family`
46e66f31c5Sopenharmony_ci   * equals `AF_LINK`. Otherwise, the result depends on the operating
47e66f31c5Sopenharmony_ci   * system with `AF_LINK` or `PF_INET`.
48e66f31c5Sopenharmony_ci   */
49e66f31c5Sopenharmony_ci  if (exclude_type == UV__EXCLUDE_IFPHYS)
50e66f31c5Sopenharmony_ci    return (ent->ifa_addr->sa_family != AF_LINK);
51e66f31c5Sopenharmony_ci#endif
52e66f31c5Sopenharmony_ci#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \
53e66f31c5Sopenharmony_ci    defined(__HAIKU__)
54e66f31c5Sopenharmony_ci  /*
55e66f31c5Sopenharmony_ci   * On BSD getifaddrs returns information related to the raw underlying
56e66f31c5Sopenharmony_ci   * devices. We're not interested in this information.
57e66f31c5Sopenharmony_ci   */
58e66f31c5Sopenharmony_ci  if (ent->ifa_addr->sa_family == AF_LINK)
59e66f31c5Sopenharmony_ci    return 1;
60e66f31c5Sopenharmony_ci#elif defined(__NetBSD__) || defined(__OpenBSD__)
61e66f31c5Sopenharmony_ci  if (ent->ifa_addr->sa_family != PF_INET &&
62e66f31c5Sopenharmony_ci      ent->ifa_addr->sa_family != PF_INET6)
63e66f31c5Sopenharmony_ci    return 1;
64e66f31c5Sopenharmony_ci#endif
65e66f31c5Sopenharmony_ci  return 0;
66e66f31c5Sopenharmony_ci}
67e66f31c5Sopenharmony_ci
68e66f31c5Sopenharmony_ciint uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
69e66f31c5Sopenharmony_ci  struct ifaddrs* addrs;
70e66f31c5Sopenharmony_ci  struct ifaddrs* ent;
71e66f31c5Sopenharmony_ci  uv_interface_address_t* address;
72e66f31c5Sopenharmony_ci#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
73e66f31c5Sopenharmony_ci  int i;
74e66f31c5Sopenharmony_ci#endif
75e66f31c5Sopenharmony_ci
76e66f31c5Sopenharmony_ci  *count = 0;
77e66f31c5Sopenharmony_ci  *addresses = NULL;
78e66f31c5Sopenharmony_ci
79e66f31c5Sopenharmony_ci  if (getifaddrs(&addrs) != 0)
80e66f31c5Sopenharmony_ci    return UV__ERR(errno);
81e66f31c5Sopenharmony_ci
82e66f31c5Sopenharmony_ci  /* Count the number of interfaces */
83e66f31c5Sopenharmony_ci  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
84e66f31c5Sopenharmony_ci    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
85e66f31c5Sopenharmony_ci      continue;
86e66f31c5Sopenharmony_ci    (*count)++;
87e66f31c5Sopenharmony_ci  }
88e66f31c5Sopenharmony_ci
89e66f31c5Sopenharmony_ci  if (*count == 0) {
90e66f31c5Sopenharmony_ci    freeifaddrs(addrs);
91e66f31c5Sopenharmony_ci    return 0;
92e66f31c5Sopenharmony_ci  }
93e66f31c5Sopenharmony_ci
94e66f31c5Sopenharmony_ci  /* Make sure the memory is initiallized to zero using calloc() */
95e66f31c5Sopenharmony_ci  *addresses = uv__calloc(*count, sizeof(**addresses));
96e66f31c5Sopenharmony_ci
97e66f31c5Sopenharmony_ci  if (*addresses == NULL) {
98e66f31c5Sopenharmony_ci    freeifaddrs(addrs);
99e66f31c5Sopenharmony_ci    return UV_ENOMEM;
100e66f31c5Sopenharmony_ci  }
101e66f31c5Sopenharmony_ci
102e66f31c5Sopenharmony_ci  address = *addresses;
103e66f31c5Sopenharmony_ci
104e66f31c5Sopenharmony_ci  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
105e66f31c5Sopenharmony_ci    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
106e66f31c5Sopenharmony_ci      continue;
107e66f31c5Sopenharmony_ci
108e66f31c5Sopenharmony_ci    address->name = uv__strdup(ent->ifa_name);
109e66f31c5Sopenharmony_ci
110e66f31c5Sopenharmony_ci    if (ent->ifa_addr->sa_family == AF_INET6) {
111e66f31c5Sopenharmony_ci      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
112e66f31c5Sopenharmony_ci    } else {
113e66f31c5Sopenharmony_ci      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
114e66f31c5Sopenharmony_ci    }
115e66f31c5Sopenharmony_ci
116e66f31c5Sopenharmony_ci    if (ent->ifa_netmask == NULL) {
117e66f31c5Sopenharmony_ci      memset(&address->netmask, 0, sizeof(address->netmask));
118e66f31c5Sopenharmony_ci    } else if (ent->ifa_netmask->sa_family == AF_INET6) {
119e66f31c5Sopenharmony_ci      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
120e66f31c5Sopenharmony_ci    } else {
121e66f31c5Sopenharmony_ci      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
122e66f31c5Sopenharmony_ci    }
123e66f31c5Sopenharmony_ci
124e66f31c5Sopenharmony_ci    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
125e66f31c5Sopenharmony_ci
126e66f31c5Sopenharmony_ci    address++;
127e66f31c5Sopenharmony_ci  }
128e66f31c5Sopenharmony_ci
129e66f31c5Sopenharmony_ci#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
130e66f31c5Sopenharmony_ci  /* Fill in physical addresses for each interface */
131e66f31c5Sopenharmony_ci  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
132e66f31c5Sopenharmony_ci    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
133e66f31c5Sopenharmony_ci      continue;
134e66f31c5Sopenharmony_ci
135e66f31c5Sopenharmony_ci    address = *addresses;
136e66f31c5Sopenharmony_ci
137e66f31c5Sopenharmony_ci    for (i = 0; i < *count; i++) {
138e66f31c5Sopenharmony_ci      if (strcmp(address->name, ent->ifa_name) == 0) {
139e66f31c5Sopenharmony_ci        struct sockaddr_dl* sa_addr;
140e66f31c5Sopenharmony_ci        sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
141e66f31c5Sopenharmony_ci        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
142e66f31c5Sopenharmony_ci      }
143e66f31c5Sopenharmony_ci      address++;
144e66f31c5Sopenharmony_ci    }
145e66f31c5Sopenharmony_ci  }
146e66f31c5Sopenharmony_ci#endif
147e66f31c5Sopenharmony_ci
148e66f31c5Sopenharmony_ci  freeifaddrs(addrs);
149e66f31c5Sopenharmony_ci
150e66f31c5Sopenharmony_ci  return 0;
151e66f31c5Sopenharmony_ci}
152e66f31c5Sopenharmony_ci
153e66f31c5Sopenharmony_ci
154e66f31c5Sopenharmony_civoid uv_free_interface_addresses(uv_interface_address_t* addresses,
155e66f31c5Sopenharmony_ci                                 int count) {
156e66f31c5Sopenharmony_ci  int i;
157e66f31c5Sopenharmony_ci
158e66f31c5Sopenharmony_ci  for (i = 0; i < count; i++) {
159e66f31c5Sopenharmony_ci    uv__free(addresses[i].name);
160e66f31c5Sopenharmony_ci  }
161e66f31c5Sopenharmony_ci
162e66f31c5Sopenharmony_ci  uv__free(addresses);
163e66f31c5Sopenharmony_ci}
164