diff options
Diffstat (limited to 'src/util/os_network.c')
-rw-r--r-- | src/util/os_network.c | 443 |
1 files changed, 0 insertions, 443 deletions
diff --git a/src/util/os_network.c b/src/util/os_network.c deleted file mode 100644 index 9ee26f0a9..000000000 --- a/src/util/os_network.c +++ /dev/null | |||
@@ -1,443 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2004, 2005, 2006, 2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | |||
20 | */ | ||
21 | /** | ||
22 | * @file util/os_network.c | ||
23 | * @brief function to determine available network interfaces | ||
24 | * @author Nils Durner | ||
25 | * @author Heikki Lindholm | ||
26 | * @author Jake Dust | ||
27 | * @author LRN | ||
28 | * @author Christian Grothoff | ||
29 | */ | ||
30 | #include "platform.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | |||
33 | |||
34 | #define LOG(kind, ...) GNUNET_log_from (kind, "util-os-network", __VA_ARGS__) | ||
35 | #define LOG_STRERROR_FILE(kind, syscall, \ | ||
36 | filename) GNUNET_log_from_strerror_file (kind, \ | ||
37 | "util-os-network", \ | ||
38 | syscall, \ | ||
39 | filename) | ||
40 | |||
41 | |||
42 | #if ! (HAVE_GETIFADDRS && HAVE_FREEIFADDRS) | ||
43 | /** | ||
44 | * Try to enumerate all network interfaces using 'ifconfig'. | ||
45 | * | ||
46 | * @param proc the callback function | ||
47 | * @param proc_cls closure for @a proc | ||
48 | * @return #GNUNET_OK if it worked | ||
49 | */ | ||
50 | static int | ||
51 | try_ifconfig (GNUNET_OS_NetworkInterfaceProcessor proc, | ||
52 | void *proc_cls) | ||
53 | { | ||
54 | int i; | ||
55 | char line[1024]; | ||
56 | char *replace; | ||
57 | const char *start; | ||
58 | char ifc[12]; | ||
59 | char addrstr[128]; | ||
60 | char bcstr[128]; | ||
61 | char netmaskstr[128]; | ||
62 | FILE *f; | ||
63 | int have_ifc; | ||
64 | struct sockaddr_in a4; | ||
65 | struct sockaddr_in6 a6; | ||
66 | struct in_addr v4; | ||
67 | struct in6_addr v6; | ||
68 | struct sockaddr_in bcaddr; | ||
69 | struct sockaddr_in netmask; | ||
70 | struct sockaddr_in6 netmask6; | ||
71 | struct sockaddr *pass_bcaddr; | ||
72 | struct sockaddr *pass_netmask; | ||
73 | int prefixlen; | ||
74 | static char *pcall; | ||
75 | |||
76 | if (NULL == pcall) | ||
77 | { | ||
78 | const char *sbin_ifconfig; | ||
79 | |||
80 | #ifdef IFCONFIG | ||
81 | if (0 == access (IFCONFIG, X_OK)) | ||
82 | sbin_ifconfig = IFCONFIG; | ||
83 | else | ||
84 | #endif | ||
85 | if (0 == access ("/sbin/ifconfig", X_OK)) | ||
86 | sbin_ifconfig = "/sbin/ifconfig"; | ||
87 | else if (0 == access ("/usr/sbin/ifconfig", X_OK)) | ||
88 | sbin_ifconfig = "/usr/sbin/ifconfig"; | ||
89 | else | ||
90 | sbin_ifconfig = "ifconfig"; | ||
91 | GNUNET_asprintf (&pcall, | ||
92 | "%s -a 2> /dev/null", | ||
93 | sbin_ifconfig); | ||
94 | } | ||
95 | f = popen (pcall, "r"); | ||
96 | if (NULL == f) | ||
97 | { | ||
98 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
99 | "popen", | ||
100 | "ifconfig"); | ||
101 | |||
102 | return GNUNET_SYSERR; | ||
103 | } | ||
104 | |||
105 | have_ifc = GNUNET_NO; | ||
106 | ifc[11] = '\0'; | ||
107 | while (NULL != fgets (line, sizeof(line), f)) | ||
108 | { | ||
109 | if (strlen (line) == 0) | ||
110 | { | ||
111 | have_ifc = GNUNET_NO; | ||
112 | continue; | ||
113 | } | ||
114 | if (! isspace (line[0])) | ||
115 | { | ||
116 | have_ifc = (1 == sscanf (line, "%11s", ifc)) ? GNUNET_YES : GNUNET_NO; | ||
117 | /* would end with ':' on OSX, fix it! */ | ||
118 | if (ifc[strlen (ifc) - 1] == ':') | ||
119 | ifc[strlen (ifc) - 1] = '\0'; | ||
120 | continue; | ||
121 | } | ||
122 | if (! have_ifc) | ||
123 | continue; /* strange input, hope for the best */ | ||
124 | |||
125 | /* make parsing of ipv6 addresses easier */ | ||
126 | for (replace = line; *replace != '\0'; replace++) | ||
127 | { | ||
128 | if (*replace == '/') | ||
129 | *replace = ' '; | ||
130 | } | ||
131 | prefixlen = -1; | ||
132 | |||
133 | start = line; | ||
134 | while (('\0' != *start) && (isspace (*start))) | ||
135 | start++; | ||
136 | |||
137 | /* Zero-out stack allocated values */ | ||
138 | memset (addrstr, 0, 128); | ||
139 | memset (netmaskstr, 0, 128); | ||
140 | memset (bcstr, 0, 128); | ||
141 | prefixlen = 0; | ||
142 | |||
143 | if ( /* Linux */ | ||
144 | (3 == sscanf (start, "inet addr:%127s Bcast:%127s Mask:%127s", addrstr, | ||
145 | bcstr, netmaskstr)) || | ||
146 | (2 == sscanf (start, "inet addr:%127s Mask:%127s", addrstr, | ||
147 | netmaskstr)) || | ||
148 | (2 == sscanf (start, "inet6 addr:%127s %d", addrstr, &prefixlen)) || | ||
149 | /* Solaris, OS X */ | ||
150 | (1 == sscanf (start, "inet %127s", addrstr)) || | ||
151 | (1 == sscanf (start, "inet6 %127s", addrstr))) | ||
152 | { | ||
153 | /* IPv4 */ | ||
154 | if (1 == inet_pton (AF_INET, addrstr, &v4)) | ||
155 | { | ||
156 | memset (&a4, 0, sizeof(a4)); | ||
157 | a4.sin_family = AF_INET; | ||
158 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
159 | a4.sin_len = (u_char) sizeof(struct sockaddr_in); | ||
160 | #endif | ||
161 | a4.sin_addr = v4; | ||
162 | |||
163 | pass_bcaddr = NULL; | ||
164 | pass_netmask = NULL; | ||
165 | if (1 == inet_pton (AF_INET, bcstr, &v4)) | ||
166 | { | ||
167 | memset (&bcaddr, 0, sizeof(bcaddr)); | ||
168 | bcaddr.sin_family = AF_INET; | ||
169 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
170 | bcaddr.sin_len = (u_char) sizeof(struct sockaddr_in); | ||
171 | #endif | ||
172 | bcaddr.sin_addr = v4; | ||
173 | pass_bcaddr = (struct sockaddr *) &bcaddr; | ||
174 | } | ||
175 | if (1 == inet_pton (AF_INET, netmaskstr, &v4)) | ||
176 | { | ||
177 | memset (&netmask, 0, sizeof(netmask)); | ||
178 | netmask.sin_family = AF_INET; | ||
179 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
180 | netmask.sin_len = (u_char) sizeof(struct sockaddr_in); | ||
181 | #endif | ||
182 | netmask.sin_addr = v4; | ||
183 | pass_netmask = (struct sockaddr *) &netmask; | ||
184 | } | ||
185 | |||
186 | |||
187 | if (GNUNET_OK != | ||
188 | proc (proc_cls, ifc,(0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE)), | ||
189 | (const struct sockaddr *) &a4, | ||
190 | pass_bcaddr, pass_netmask, sizeof(a4))) | ||
191 | break; | ||
192 | continue; | ||
193 | } | ||
194 | /* IPv6 */ | ||
195 | if (1 == inet_pton (AF_INET6, addrstr, &v6)) | ||
196 | { | ||
197 | memset (&a6, 0, sizeof(a6)); | ||
198 | a6.sin6_family = AF_INET6; | ||
199 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
200 | a6.sin6_len = (u_char) sizeof(struct sockaddr_in6); | ||
201 | #endif | ||
202 | a6.sin6_addr = v6; | ||
203 | |||
204 | pass_netmask = NULL; | ||
205 | if (prefixlen != -1) | ||
206 | { | ||
207 | memset (v6.s6_addr, 0, sizeof(v6.s6_addr)); | ||
208 | for (i = 0; i < prefixlen; i++) | ||
209 | { | ||
210 | v6.s6_addr[i >> 3] |= 1 << (i & 7); | ||
211 | } | ||
212 | memset (&netmask6, 0, sizeof(netmask6)); | ||
213 | netmask6.sin6_family = AF_INET6; | ||
214 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
215 | netmask6.sin6_len = (u_char) sizeof(struct sockaddr_in6); | ||
216 | #endif | ||
217 | netmask6.sin6_addr = v6; | ||
218 | |||
219 | pass_netmask = (struct sockaddr *) &netmask6; | ||
220 | } | ||
221 | |||
222 | if (GNUNET_OK != | ||
223 | proc (proc_cls, ifc,(0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE)), | ||
224 | (const struct sockaddr *) &a6, | ||
225 | NULL, pass_netmask, sizeof(a6))) | ||
226 | break; | ||
227 | continue; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | pclose (f); | ||
232 | return GNUNET_OK; | ||
233 | } | ||
234 | |||
235 | |||
236 | /** | ||
237 | * Try to enumerate all network interfaces using 'ip'. | ||
238 | * | ||
239 | * @param proc the callback function | ||
240 | * @param proc_cls closure for @a proc | ||
241 | * @return #GNUNET_OK if it worked | ||
242 | */ | ||
243 | static int | ||
244 | try_ip (GNUNET_OS_NetworkInterfaceProcessor proc, | ||
245 | void *proc_cls) | ||
246 | { | ||
247 | char line[1024]; | ||
248 | char *replace; | ||
249 | char ifname[64]; | ||
250 | char afstr[6]; | ||
251 | char addrstr[128]; | ||
252 | FILE *f; | ||
253 | struct sockaddr_in a4; | ||
254 | struct sockaddr_in6 a6; | ||
255 | struct in_addr v4; | ||
256 | struct in6_addr v6; | ||
257 | struct sockaddr_in netmask; | ||
258 | struct sockaddr_in6 netmask6; | ||
259 | unsigned int i; | ||
260 | unsigned int prefixlen; | ||
261 | static char *pcall; | ||
262 | |||
263 | if (NULL == pcall) | ||
264 | { | ||
265 | const char *sbin_ip; | ||
266 | |||
267 | #ifdef IFCONFIG | ||
268 | if (0 == access (PATH_TO_IP, X_OK)) | ||
269 | sbin_ip = PATH_TO_IP; | ||
270 | else | ||
271 | #endif | ||
272 | if (0 == access ("/sbin/ip", X_OK)) | ||
273 | sbin_ip = "/sbin/ip"; | ||
274 | else if (0 == access ("/usr/sbin/ip", X_OK)) | ||
275 | sbin_ip = "/usr/sbin/ip"; | ||
276 | else | ||
277 | sbin_ip = "if"; | ||
278 | GNUNET_asprintf (&pcall, | ||
279 | "%s -o add 2> /dev/null", | ||
280 | sbin_ip); | ||
281 | } | ||
282 | f = popen (pcall, "r"); | ||
283 | if (! f) | ||
284 | { | ||
285 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
286 | "popen", | ||
287 | "ip"); | ||
288 | return GNUNET_SYSERR; | ||
289 | } | ||
290 | |||
291 | while (NULL != fgets (line, sizeof(line), f)) | ||
292 | { | ||
293 | /* make parsing easier */ | ||
294 | for (replace = line; *replace != '\0'; replace++) | ||
295 | { | ||
296 | if (*replace == '/') | ||
297 | *replace = ' '; | ||
298 | } | ||
299 | /* Zero-out stack allocated values */ | ||
300 | memset (ifname, 0, 64); | ||
301 | memset (afstr, 0, 6); | ||
302 | memset (addrstr, 0, 128); | ||
303 | if (4 != sscanf (line, | ||
304 | "%*u: %63s %5s %127s %6u", | ||
305 | ifname, | ||
306 | afstr, | ||
307 | addrstr, | ||
308 | &prefixlen)) | ||
309 | continue; | ||
310 | /* IPv4 */ | ||
311 | if ((0 == strcasecmp ("inet", | ||
312 | afstr)) && | ||
313 | (1 == inet_pton (AF_INET, | ||
314 | addrstr, | ||
315 | &v4))) | ||
316 | { | ||
317 | memset (&a4, 0, sizeof(a4)); | ||
318 | a4.sin_family = AF_INET; | ||
319 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
320 | a4.sin_len = (u_char) sizeof(struct sockaddr_in); | ||
321 | #endif | ||
322 | a4.sin_addr = v4; | ||
323 | |||
324 | memset (&v4.s_addr, 0, sizeof(v4.s_addr)); | ||
325 | for (i = 0; i < prefixlen; i++) | ||
326 | v4.s_addr |= 1 << (i & 7); | ||
327 | memset (&netmask, 0, sizeof(netmask)); | ||
328 | netmask.sin_family = AF_INET; | ||
329 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
330 | netmask.sin_len = (u_char) sizeof(struct sockaddr_in); | ||
331 | #endif | ||
332 | netmask.sin_addr = v4; | ||
333 | |||
334 | if (GNUNET_OK != | ||
335 | proc (proc_cls, | ||
336 | ifname, | ||
337 | (0 == strcmp (ifname, | ||
338 | GNUNET_DEFAULT_INTERFACE)), | ||
339 | (const struct sockaddr *) &a4, | ||
340 | NULL, | ||
341 | (const struct sockaddr *) &netmask, | ||
342 | sizeof(a4))) | ||
343 | break; | ||
344 | } | ||
345 | /* IPv6 */ | ||
346 | if ((0 == strcasecmp ("inet6", | ||
347 | afstr)) && | ||
348 | (1 == inet_pton (AF_INET6, | ||
349 | addrstr, | ||
350 | &v6))) | ||
351 | { | ||
352 | memset (&a6, 0, sizeof(a6)); | ||
353 | a6.sin6_family = AF_INET6; | ||
354 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
355 | a6.sin6_len = (u_char) sizeof(struct sockaddr_in6); | ||
356 | #endif | ||
357 | a6.sin6_addr = v6; | ||
358 | |||
359 | memset (v6.s6_addr, 0, sizeof(v6.s6_addr)); | ||
360 | for (i = 0; i < prefixlen; i++) | ||
361 | v6.s6_addr[i >> 3] |= 1 << (i & 7); | ||
362 | memset (&netmask6, 0, sizeof(netmask6)); | ||
363 | netmask6.sin6_family = AF_INET6; | ||
364 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
365 | netmask6.sin6_len = (u_char) sizeof(struct sockaddr_in6); | ||
366 | #endif | ||
367 | netmask6.sin6_addr = v6; | ||
368 | |||
369 | if (GNUNET_OK != | ||
370 | proc (proc_cls, | ||
371 | ifname, | ||
372 | (0 == strcmp (ifname, | ||
373 | GNUNET_DEFAULT_INTERFACE)), | ||
374 | (const struct sockaddr *) &a6, | ||
375 | NULL, | ||
376 | (const struct sockaddr *) &netmask6, | ||
377 | sizeof(a6))) | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | pclose (f); | ||
382 | return GNUNET_OK; | ||
383 | } | ||
384 | |||
385 | |||
386 | #endif | ||
387 | |||
388 | |||
389 | /** | ||
390 | * @brief Enumerate all network interfaces | ||
391 | * | ||
392 | * @param proc the callback function | ||
393 | * @param proc_cls closure for @a proc | ||
394 | */ | ||
395 | void | ||
396 | GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | ||
397 | void *proc_cls) | ||
398 | { | ||
399 | #if HAVE_GETIFADDRS && HAVE_FREEIFADDRS | ||
400 | struct ifaddrs *ifa_first; | ||
401 | struct ifaddrs *ifa_ptr; | ||
402 | socklen_t alen; | ||
403 | |||
404 | if (getifaddrs (&ifa_first) == 0) | ||
405 | { | ||
406 | for (ifa_ptr = ifa_first; ifa_ptr != NULL; ifa_ptr = ifa_ptr->ifa_next) | ||
407 | { | ||
408 | if ((ifa_ptr->ifa_name != NULL) && (ifa_ptr->ifa_addr != NULL) && | ||
409 | ( (ifa_ptr->ifa_flags & IFF_UP) != 0) ) | ||
410 | { | ||
411 | if ((ifa_ptr->ifa_addr->sa_family != AF_INET) && | ||
412 | (ifa_ptr->ifa_addr->sa_family != AF_INET6)) | ||
413 | continue; | ||
414 | if (ifa_ptr->ifa_addr->sa_family == AF_INET) | ||
415 | alen = sizeof(struct sockaddr_in); | ||
416 | else | ||
417 | alen = sizeof(struct sockaddr_in6); | ||
418 | if (GNUNET_OK != | ||
419 | proc (proc_cls, ifa_ptr->ifa_name, | ||
420 | (0 == strcmp (ifa_ptr->ifa_name, GNUNET_DEFAULT_INTERFACE)), | ||
421 | ifa_ptr->ifa_addr, ifa_ptr->ifa_broadaddr, | ||
422 | ifa_ptr->ifa_netmask, alen)) | ||
423 | break; | ||
424 | } | ||
425 | } | ||
426 | freeifaddrs (ifa_first); | ||
427 | } | ||
428 | #else | ||
429 | if (GNUNET_OK == | ||
430 | try_ip (proc, | ||
431 | proc_cls)) | ||
432 | return; | ||
433 | if (GNUNET_OK == | ||
434 | try_ifconfig (proc, | ||
435 | proc_cls)) | ||
436 | return; | ||
437 | LOG (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
438 | "Failed to enumerate network interfaces\n"); | ||
439 | #endif | ||
440 | } | ||
441 | |||
442 | |||
443 | /* end of os_network.c */ | ||