diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-10-03 16:38:55 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-10-03 16:38:55 +0000 |
commit | 52c3cb9d9ec0cbef542fafc4ed399681deecdadc (patch) | |
tree | 4cfe143c71df1db8b893218c58d93ed397d77b22 /src/util/os_network.c | |
parent | 45f20489fa00f70e9a5468566259800e1dd36f9d (diff) | |
download | gnunet-52c3cb9d9ec0cbef542fafc4ed399681deecdadc.tar.gz gnunet-52c3cb9d9ec0cbef542fafc4ed399681deecdadc.zip |
find network interfaces also using 'ip' command (#3911)
Diffstat (limited to 'src/util/os_network.c')
-rw-r--r-- | src/util/os_network.c | 291 |
1 files changed, 226 insertions, 65 deletions
diff --git a/src/util/os_network.c b/src/util/os_network.c index 19b60b6b4..deb114ee2 100644 --- a/src/util/os_network.c +++ b/src/util/os_network.c | |||
@@ -25,6 +25,7 @@ | |||
25 | * @author Heikki Lindholm | 25 | * @author Heikki Lindholm |
26 | * @author Jake Dust | 26 | * @author Jake Dust |
27 | * @author LRN | 27 | * @author LRN |
28 | * @author Christian Grothoff | ||
28 | */ | 29 | */ |
29 | #include "platform.h" | 30 | #include "platform.h" |
30 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
@@ -33,73 +34,19 @@ | |||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) | 34 | #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) |
34 | #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) | 35 | #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) |
35 | 36 | ||
37 | |||
38 | #if ! (HAVE_GETIFADDRS && HAVE_FREEIFADDRS) | ||
36 | /** | 39 | /** |
37 | * @brief Enumerate all network interfaces | 40 | * Try to enumerate all network interfaces using 'ifconfig'. |
38 | * | 41 | * |
39 | * @param proc the callback function | 42 | * @param proc the callback function |
40 | * @param proc_cls closure for @a proc | 43 | * @param proc_cls closure for @a proc |
44 | * @return #GNUNET_OK if it worked | ||
41 | */ | 45 | */ |
42 | void | 46 | static int |
43 | GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | 47 | try_ifconfig (GNUNET_OS_NetworkInterfaceProcessor proc, |
44 | void *proc_cls) | 48 | void *proc_cls) |
45 | { | 49 | { |
46 | #ifdef MINGW | ||
47 | int r; | ||
48 | int i; | ||
49 | struct EnumNICs3_results *results = NULL; | ||
50 | int results_count; | ||
51 | |||
52 | r = EnumNICs3 (&results, &results_count); | ||
53 | if (r != GNUNET_OK) | ||
54 | return; | ||
55 | |||
56 | for (i = 0; i < results_count; i++) | ||
57 | { | ||
58 | if (GNUNET_OK != | ||
59 | proc (proc_cls, results[i].pretty_name, results[i].is_default, | ||
60 | (const struct sockaddr *) &results[i].address, | ||
61 | results[i]. | ||
62 | flags & ENUMNICS3_BCAST_OK ? | ||
63 | (const struct sockaddr *) &results[i].broadcast : NULL, | ||
64 | results[i].flags & ENUMNICS3_MASK_OK ? | ||
65 | (const struct sockaddr *) &results[i].mask : NULL, | ||
66 | results[i].addr_size)) | ||
67 | break; | ||
68 | } | ||
69 | EnumNICs3_free (results); | ||
70 | return; | ||
71 | |||
72 | #elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS | ||
73 | |||
74 | struct ifaddrs *ifa_first; | ||
75 | struct ifaddrs *ifa_ptr; | ||
76 | socklen_t alen; | ||
77 | |||
78 | if (getifaddrs (&ifa_first) == 0) | ||
79 | { | ||
80 | for (ifa_ptr = ifa_first; ifa_ptr != NULL; ifa_ptr = ifa_ptr->ifa_next) | ||
81 | { | ||
82 | if (ifa_ptr->ifa_name != NULL && ifa_ptr->ifa_addr != NULL && | ||
83 | (ifa_ptr->ifa_flags & IFF_UP) != 0) | ||
84 | { | ||
85 | if ((ifa_ptr->ifa_addr->sa_family != AF_INET) && | ||
86 | (ifa_ptr->ifa_addr->sa_family != AF_INET6)) | ||
87 | continue; | ||
88 | if (ifa_ptr->ifa_addr->sa_family == AF_INET) | ||
89 | alen = sizeof (struct sockaddr_in); | ||
90 | else | ||
91 | alen = sizeof (struct sockaddr_in6); | ||
92 | if (GNUNET_OK != | ||
93 | proc (proc_cls, ifa_ptr->ifa_name, | ||
94 | 0 == strcmp (ifa_ptr->ifa_name, GNUNET_DEFAULT_INTERFACE), | ||
95 | ifa_ptr->ifa_addr, ifa_ptr->ifa_broadaddr, | ||
96 | ifa_ptr->ifa_netmask, alen)) | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | freeifaddrs (ifa_first); | ||
101 | } | ||
102 | #else | ||
103 | int i; | 50 | int i; |
104 | char line[1024]; | 51 | char line[1024]; |
105 | char *replace; | 52 | char *replace; |
@@ -122,17 +69,19 @@ GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | |||
122 | int prefixlen; | 69 | int prefixlen; |
123 | 70 | ||
124 | if (system ("ifconfig -a > /dev/null 2> /dev/null")) | 71 | if (system ("ifconfig -a > /dev/null 2> /dev/null")) |
125 | if (system ("/sbin/ifconfig -a > /dev/null 2> /dev/null") == 0) | 72 | if (0 == system ("/sbin/ifconfig -a > /dev/null 2> /dev/null")) |
126 | f = popen ("/sbin/ifconfig -a 2> /dev/null", "r"); | 73 | f = popen ("/sbin/ifconfig -a 2> /dev/null", "r"); |
127 | else | 74 | else |
128 | f = NULL; | 75 | f = NULL; |
129 | else | 76 | else |
130 | f = popen ("ifconfig -a 2> /dev/null", "r"); | 77 | f = popen ("ifconfig -a 2> /dev/null", "r"); |
131 | if (!f) | 78 | if (! f) |
132 | { | 79 | { |
133 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | 80 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, |
134 | "popen", "ifconfig"); | 81 | "popen", |
135 | return; | 82 | "ifconfig"); |
83 | |||
84 | return GNUNET_SYSERR; | ||
136 | } | 85 | } |
137 | 86 | ||
138 | have_ifc = GNUNET_NO; | 87 | have_ifc = GNUNET_NO; |
@@ -260,6 +209,218 @@ GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | |||
260 | } | 209 | } |
261 | } | 210 | } |
262 | pclose (f); | 211 | pclose (f); |
212 | return GNUNET_OK; | ||
213 | } | ||
214 | |||
215 | |||
216 | /** | ||
217 | * Try to enumerate all network interfaces using 'ip'. | ||
218 | * | ||
219 | * @param proc the callback function | ||
220 | * @param proc_cls closure for @a proc | ||
221 | * @return #GNUNET_OK if it worked | ||
222 | */ | ||
223 | static int | ||
224 | try_ip (GNUNET_OS_NetworkInterfaceProcessor proc, | ||
225 | void *proc_cls) | ||
226 | { | ||
227 | char line[1024]; | ||
228 | char *replace; | ||
229 | char ifname[64]; | ||
230 | char afstr[6]; | ||
231 | char addrstr[128]; | ||
232 | FILE *f; | ||
233 | struct sockaddr_in a4; | ||
234 | struct sockaddr_in6 a6; | ||
235 | struct in_addr v4; | ||
236 | struct in6_addr v6; | ||
237 | struct sockaddr_in netmask; | ||
238 | struct sockaddr_in6 netmask6; | ||
239 | unsigned int i; | ||
240 | unsigned int prefixlen; | ||
241 | |||
242 | f = popen ("ip -o add 2> /dev/null", "r"); | ||
243 | if (! f) | ||
244 | { | ||
245 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
246 | "popen", | ||
247 | "ip"); | ||
248 | return GNUNET_SYSERR; | ||
249 | } | ||
250 | |||
251 | while (NULL != fgets (line, sizeof (line), f)) | ||
252 | { | ||
253 | /* make parsing easier */ | ||
254 | for (replace = line; *replace != '\0'; replace++) | ||
255 | { | ||
256 | if (*replace == '/') | ||
257 | *replace = ' '; | ||
258 | } | ||
259 | /* Zero-out stack allocated values */ | ||
260 | memset (ifname, 0, 64); | ||
261 | memset (afstr, 0, 6); | ||
262 | memset (addrstr, 0, 128); | ||
263 | if (4 != SSCANF (line, | ||
264 | "%*u: %63s %5s %127s %6u", | ||
265 | ifname, | ||
266 | afstr, | ||
267 | addrstr, | ||
268 | &prefixlen)) | ||
269 | continue; | ||
270 | /* IPv4 */ | ||
271 | if ( (0 == strcasecmp ("inet", | ||
272 | afstr)) && | ||
273 | (1 == inet_pton (AF_INET, | ||
274 | addrstr, | ||
275 | &v4)) ) | ||
276 | { | ||
277 | memset (&a4, 0, sizeof (a4)); | ||
278 | a4.sin_family = AF_INET; | ||
279 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
280 | a4.sin_len = (u_char) sizeof (struct sockaddr_in); | ||
281 | #endif | ||
282 | a4.sin_addr = v4; | ||
283 | |||
284 | memset (&v4.s_addr, 0, sizeof (v4.s_addr)); | ||
285 | for (i = 0; i < prefixlen; i++) | ||
286 | v4.s_addr |= 1 << (i & 7); | ||
287 | memset (&netmask, 0, sizeof (netmask)); | ||
288 | netmask.sin_family = AF_INET; | ||
289 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
290 | netmask.sin_len = (u_char) sizeof (struct sockaddr_in); | ||
291 | #endif | ||
292 | netmask.sin_addr = v4; | ||
293 | |||
294 | if (GNUNET_OK != | ||
295 | proc (proc_cls, | ||
296 | ifname, | ||
297 | (0 == strcmp (ifname, | ||
298 | GNUNET_DEFAULT_INTERFACE)), | ||
299 | (const struct sockaddr *) &a4, | ||
300 | NULL, | ||
301 | (const struct sockaddr *) &netmask, | ||
302 | sizeof (a4))) | ||
303 | break; | ||
304 | } | ||
305 | /* IPv6 */ | ||
306 | if ( (0 == strcasecmp ("inet6", | ||
307 | afstr)) && | ||
308 | (1 == inet_pton (AF_INET6, | ||
309 | addrstr, | ||
310 | &v6)) ) | ||
311 | { | ||
312 | memset (&a6, 0, sizeof (a6)); | ||
313 | a6.sin6_family = AF_INET6; | ||
314 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
315 | a6.sin6_len = (u_char) sizeof (struct sockaddr_in6); | ||
316 | #endif | ||
317 | a6.sin6_addr = v6; | ||
318 | |||
319 | memset (v6.s6_addr, 0, sizeof (v6.s6_addr)); | ||
320 | for (i = 0; i < prefixlen; i++) | ||
321 | v6.s6_addr[i >> 3] |= 1 << (i & 7); | ||
322 | memset (&netmask6, 0, sizeof (netmask6)); | ||
323 | netmask6.sin6_family = AF_INET6; | ||
324 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
325 | netmask6.sin6_len = (u_char) sizeof (struct sockaddr_in6); | ||
326 | #endif | ||
327 | netmask6.sin6_addr = v6; | ||
328 | |||
329 | if (GNUNET_OK != | ||
330 | proc (proc_cls, | ||
331 | ifname, | ||
332 | (0 == strcmp (ifname, | ||
333 | GNUNET_DEFAULT_INTERFACE)), | ||
334 | (const struct sockaddr *) &a6, | ||
335 | NULL, | ||
336 | (const struct sockaddr *) &netmask6, | ||
337 | sizeof (a6))) | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | pclose (f); | ||
342 | return GNUNET_OK; | ||
343 | } | ||
344 | #endif | ||
345 | |||
346 | |||
347 | /** | ||
348 | * @brief Enumerate all network interfaces | ||
349 | * | ||
350 | * @param proc the callback function | ||
351 | * @param proc_cls closure for @a proc | ||
352 | */ | ||
353 | void | ||
354 | GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | ||
355 | void *proc_cls) | ||
356 | { | ||
357 | #ifdef MINGW | ||
358 | int r; | ||
359 | int i; | ||
360 | struct EnumNICs3_results *results = NULL; | ||
361 | int results_count; | ||
362 | |||
363 | r = EnumNICs3 (&results, &results_count); | ||
364 | if (r != GNUNET_OK) | ||
365 | return; | ||
366 | |||
367 | for (i = 0; i < results_count; i++) | ||
368 | { | ||
369 | if (GNUNET_OK != | ||
370 | proc (proc_cls, results[i].pretty_name, results[i].is_default, | ||
371 | (const struct sockaddr *) &results[i].address, | ||
372 | results[i]. | ||
373 | flags & ENUMNICS3_BCAST_OK ? | ||
374 | (const struct sockaddr *) &results[i].broadcast : NULL, | ||
375 | results[i].flags & ENUMNICS3_MASK_OK ? | ||
376 | (const struct sockaddr *) &results[i].mask : NULL, | ||
377 | results[i].addr_size)) | ||
378 | break; | ||
379 | } | ||
380 | EnumNICs3_free (results); | ||
381 | return; | ||
382 | |||
383 | #elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS | ||
384 | |||
385 | struct ifaddrs *ifa_first; | ||
386 | struct ifaddrs *ifa_ptr; | ||
387 | socklen_t alen; | ||
388 | |||
389 | if (getifaddrs (&ifa_first) == 0) | ||
390 | { | ||
391 | for (ifa_ptr = ifa_first; ifa_ptr != NULL; ifa_ptr = ifa_ptr->ifa_next) | ||
392 | { | ||
393 | if (ifa_ptr->ifa_name != NULL && ifa_ptr->ifa_addr != NULL && | ||
394 | (ifa_ptr->ifa_flags & IFF_UP) != 0) | ||
395 | { | ||
396 | if ((ifa_ptr->ifa_addr->sa_family != AF_INET) && | ||
397 | (ifa_ptr->ifa_addr->sa_family != AF_INET6)) | ||
398 | continue; | ||
399 | if (ifa_ptr->ifa_addr->sa_family == AF_INET) | ||
400 | alen = sizeof (struct sockaddr_in); | ||
401 | else | ||
402 | alen = sizeof (struct sockaddr_in6); | ||
403 | if (GNUNET_OK != | ||
404 | proc (proc_cls, ifa_ptr->ifa_name, | ||
405 | 0 == strcmp (ifa_ptr->ifa_name, GNUNET_DEFAULT_INTERFACE), | ||
406 | ifa_ptr->ifa_addr, ifa_ptr->ifa_broadaddr, | ||
407 | ifa_ptr->ifa_netmask, alen)) | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | freeifaddrs (ifa_first); | ||
412 | } | ||
413 | #else | ||
414 | if (GNUNET_OK == | ||
415 | try_ip (proc, | ||
416 | proc_cls)) | ||
417 | return; | ||
418 | if (GNUNET_OK == | ||
419 | try_ifconfig (proc, | ||
420 | proc_cls)) | ||
421 | return; | ||
422 | LOG (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
423 | "Failed to enumerate network interfaces\n"); | ||
263 | #endif | 424 | #endif |
264 | } | 425 | } |
265 | 426 | ||