aboutsummaryrefslogtreecommitdiff
path: root/src/util/os_network.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-10-03 16:38:55 +0000
committerChristian Grothoff <christian@grothoff.org>2015-10-03 16:38:55 +0000
commit52c3cb9d9ec0cbef542fafc4ed399681deecdadc (patch)
tree4cfe143c71df1db8b893218c58d93ed397d77b22 /src/util/os_network.c
parent45f20489fa00f70e9a5468566259800e1dd36f9d (diff)
downloadgnunet-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.c291
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 */
42void 46static int
43GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, 47try_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 */
223static int
224try_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 */
353void
354GNUNET_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