+
+ if (GNUNET_OK !=
+ proc (proc_cls, ifc, 0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE),
+ (const struct sockaddr *) &a6,
+ NULL, pass_netmask, sizeof (a6)))
+ break;
+ continue;
+ }
+ }
+ }
+ pclose (f);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Try to enumerate all network interfaces using 'ip'.
+ *
+ * @param proc the callback function
+ * @param proc_cls closure for @a proc
+ * @return #GNUNET_OK if it worked
+ */
+static int
+try_ip (GNUNET_OS_NetworkInterfaceProcessor proc,
+ void *proc_cls)
+{
+ char line[1024];
+ char *replace;
+ char ifname[64];
+ char afstr[6];
+ char addrstr[128];
+ FILE *f;
+ struct sockaddr_in a4;
+ struct sockaddr_in6 a6;
+ struct in_addr v4;
+ struct in6_addr v6;
+ struct sockaddr_in netmask;
+ struct sockaddr_in6 netmask6;
+ unsigned int i;
+ unsigned int prefixlen;
+
+ f = popen ("ip -o add 2> /dev/null", "r");
+ if (! f)
+ {
+ LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+ "popen",
+ "ip");
+ return GNUNET_SYSERR;
+ }
+
+ while (NULL != fgets (line, sizeof (line), f))
+ {
+ /* make parsing easier */
+ for (replace = line; *replace != '\0'; replace++)
+ {
+ if (*replace == '/')
+ *replace = ' ';
+ }
+ /* Zero-out stack allocated values */
+ memset (ifname, 0, 64);
+ memset (afstr, 0, 6);
+ memset (addrstr, 0, 128);
+ if (4 != SSCANF (line,
+ "%*u: %63s %5s %127s %6u",
+ ifname,
+ afstr,
+ addrstr,
+ &prefixlen))
+ continue;
+ /* IPv4 */
+ if ( (0 == strcasecmp ("inet",
+ afstr)) &&
+ (1 == inet_pton (AF_INET,
+ addrstr,
+ &v4)) )
+ {
+ memset (&a4, 0, sizeof (a4));
+ a4.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ a4.sin_len = (u_char) sizeof (struct sockaddr_in);
+#endif
+ a4.sin_addr = v4;
+
+ memset (&v4.s_addr, 0, sizeof (v4.s_addr));
+ for (i = 0; i < prefixlen; i++)
+ v4.s_addr |= 1 << (i & 7);
+ memset (&netmask, 0, sizeof (netmask));
+ netmask.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ netmask.sin_len = (u_char) sizeof (struct sockaddr_in);
+#endif
+ netmask.sin_addr = v4;
+
+ if (GNUNET_OK !=
+ proc (proc_cls,
+ ifname,
+ (0 == strcmp (ifname,
+ GNUNET_DEFAULT_INTERFACE)),
+ (const struct sockaddr *) &a4,
+ NULL,
+ (const struct sockaddr *) &netmask,
+ sizeof (a4)))
+ break;
+ }
+ /* IPv6 */
+ if ( (0 == strcasecmp ("inet6",
+ afstr)) &&
+ (1 == inet_pton (AF_INET6,
+ addrstr,
+ &v6)) )
+ {
+ memset (&a6, 0, sizeof (a6));
+ a6.sin6_family = AF_INET6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ a6.sin6_len = (u_char) sizeof (struct sockaddr_in6);
+#endif
+ a6.sin6_addr = v6;
+
+ memset (v6.s6_addr, 0, sizeof (v6.s6_addr));
+ for (i = 0; i < prefixlen; i++)
+ v6.s6_addr[i >> 3] |= 1 << (i & 7);
+ memset (&netmask6, 0, sizeof (netmask6));
+ netmask6.sin6_family = AF_INET6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ netmask6.sin6_len = (u_char) sizeof (struct sockaddr_in6);
+#endif
+ netmask6.sin6_addr = v6;
+
+ if (GNUNET_OK !=
+ proc (proc_cls,
+ ifname,
+ (0 == strcmp (ifname,
+ GNUNET_DEFAULT_INTERFACE)),
+ (const struct sockaddr *) &a6,
+ NULL,
+ (const struct sockaddr *) &netmask6,
+ sizeof (a6)))
+ break;