Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
3156 views
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
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
69
struct ifaddrs* addrs;
70
struct ifaddrs* ent;
71
uv_interface_address_t* address;
72
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
73
int i;
74
#endif
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
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
84
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
85
continue;
86
(*count)++;
87
}
88
89
if (*count == 0) {
90
freeifaddrs(addrs);
91
return 0;
92
}
93
94
/* Make sure the memory is initiallized to zero using calloc() */
95
*addresses = uv__calloc(*count, sizeof(**addresses));
96
97
if (*addresses == NULL) {
98
freeifaddrs(addrs);
99
return UV_ENOMEM;
100
}
101
102
address = *addresses;
103
104
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
105
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
106
continue;
107
108
address->name = uv__strdup(ent->ifa_name);
109
110
if (ent->ifa_addr->sa_family == AF_INET6) {
111
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
112
} else {
113
address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
114
}
115
116
if (ent->ifa_netmask == NULL) {
117
memset(&address->netmask, 0, sizeof(address->netmask));
118
} else if (ent->ifa_netmask->sa_family == AF_INET6) {
119
address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
120
} else {
121
address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
122
}
123
124
address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
125
126
address++;
127
}
128
129
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
130
/* Fill in physical addresses for each interface */
131
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
132
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
133
continue;
134
135
address = *addresses;
136
137
for (i = 0; i < *count; i++) {
138
if (strcmp(address->name, ent->ifa_name) == 0) {
139
struct sockaddr_dl* sa_addr;
140
sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
141
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
142
}
143
address++;
144
}
145
}
146
#endif
147
148
freeifaddrs(addrs);
149
150
return 0;
151
}
152
153
154
void uv_free_interface_addresses(uv_interface_address_t* addresses,
155
int count) {
156
int i;
157
158
for (i = 0; i < count; i++) {
159
uv__free(addresses[i].name);
160
}
161
162
uv__free(addresses);
163
}
164
165