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