chiark / gitweb /
noip.c (get_local_ipaddrs): Rewrite to use getifaddrs(3).
authorMark Wooding <mdw@distorted.org.uk>
Fri, 25 Apr 2014 08:49:26 +0000 (09:49 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 25 Apr 2014 08:57:49 +0000 (09:57 +0100)
This is a much better function to use because it actually gives us all
of the addresses on each interface rather than just the first.

Also, discard duplicate addresses, because they're more likely now.  We
should have done this already, but unaccountably neglected to.

noip.c

diff --git a/noip.c b/noip.c
index 804fc8ad0579169eae07ca09ca7f585d6f4aeb54..aaf21b4d3d641b92daef4f330c779d1ed811bc1e 100644 (file)
--- a/noip.c
+++ b/noip.c
@@ -51,7 +51,7 @@
 #include <arpa/inet.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
-#include <net/if.h>
+#include <ifaddrs.h>
 
 /*----- Data structures ---------------------------------------------------*/
 
@@ -1081,27 +1081,31 @@ static void cleanup_sockdir(void)
  */
 static void get_local_ipaddrs(void)
 {
-  struct if_nameindex *ifn;
-  struct ifreq ifr;
-  int sk;
+  struct ifaddrs *ifa_head, *ifa;
+  const struct in_addr *a;
   int i;
 
-  ifn = if_nameindex();
-  if ((sk = real_socket(PF_INET, SOCK_STREAM, 00)) < 0)
-    return;
-  for (i = n_local_ipaddrs = 0;
-       n_local_ipaddrs < MAX_LOCAL_IPADDRS &&
-        ifn[i].if_name && *ifn[i].if_name;
-       i++) {
-    strcpy(ifr.ifr_name, ifn[i].if_name);
-    if (ioctl(sk, SIOCGIFADDR, &ifr) || ifr.ifr_addr.sa_family != AF_INET)
+  if (getifaddrs(&ifa_head)) { perror("getifaddrs"); return; }
+  for (n_local_ipaddrs = 0, ifa = ifa_head;
+       n_local_ipaddrs < MAX_LOCAL_IPADDRS && ifa;
+       ifa = ifa->ifa_next) {
+    if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
       continue;
-    local_ipaddrs[n_local_ipaddrs++] =
-      SIN(&ifr.ifr_addr)->sin_addr;
-    D( fprintf(stderr, "noip: local addr %s = %s\n", ifn[i].if_name,
-              inet_ntoa(local_ipaddrs[n_local_ipaddrs - 1])); )
+    a = &SIN(ifa->ifa_addr)->sin_addr;
+    D( fprintf(stderr, "noip: local addr %s = %s",
+              ifa->ifa_name, inet_ntoa(*a)); )
+    for (i = 0; i < n_local_ipaddrs; i++) {
+      if (local_ipaddrs[i].s_addr == a->s_addr) {
+       D( fprintf(stderr, " (duplicate)\n"); )
+       goto skip;
+      }
+    }
+    D( fprintf(stderr, "\n"); )
+    local_ipaddrs[n_local_ipaddrs] = *a;
+    n_local_ipaddrs++;
+  skip:;
   }
-  close(sk);
+  freeifaddrs(ifa_head);
 }
 
 /* Print the given message to standard error.  Avoids stdio. */