[automerger] Add extra (size_t) cast to avoid compiler warning. am: 1387a89b14 am: bc2ee79a6e am: 53787550a7 am: 95129dbdb6 am: 10d8009592 am: e04fe5b516 am: aca21c9df5 am: db203bf112 am: 14cd06a72d am: 2e47278b09

Change-Id: I5a5e4e39a3fafda1ae7692841a1b5ae449a9c6c4
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..c6180e1
--- /dev/null
+++ b/README.version
@@ -0,0 +1,3 @@
+URL: http://www.thekelleys.org.uk/dnsmasq/dnsmasq-2.51.tar.gz
+Version: 2.51
+BugComponent: 31808
diff --git a/src/Android.mk b/src/Android.mk
index dfe3f5b..911a07b 100644
--- a/src/Android.mk
+++ b/src/Android.mk
@@ -10,7 +10,7 @@
 
 LOCAL_C_INCLUDES := external/dnsmasq/src
 
-LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
+LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DIPV6 -DNO_TFTP -DNO_SCRIPT -D_BSD_SOURCE
 LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 LOCAL_SHARED_LIBRARIES := libcutils liblog
 
diff --git a/src/cache.c b/src/cache.c
index d641ae7..6c0f225 100755
--- a/src/cache.c
+++ b/src/cache.c
@@ -1245,6 +1245,7 @@
   if (addr)
     {
 #ifdef HAVE_IPV6
+      /* TODO: support scoped addresses. struct all_addr doesn't store scope IDs. */
       inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
 		addr, addrbuff, ADDRSTRLEN);
 #else
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 2f0fbb6..a1b6578 100755
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -64,7 +64,7 @@
 static void async_event(int pipe, time_t now);
 static void fatal_event(struct event_desc *ev);
 static void poll_resolv(void);
-#ifdef __ANDROID__
+#if defined(__ANDROID__) && !defined(__BRILLO__)
 static int set_android_listeners(fd_set *set, int *maxfdp);
 static int check_android_listeners(fd_set *set);
 #endif
@@ -282,7 +282,7 @@
   
   if (!(daemon->options & OPT_DEBUG))   
     {
-#ifndef __ANDROID__
+#if !defined(__ANDROID__) || defined(__BRILLO__)
       int nullfd;
 #endif
 
@@ -351,7 +351,7 @@
 	    }
 	}
 
-#ifndef __ANDROID__
+#if !defined(__ANDROID__) || defined(__BRILLO__)
       /* open  stdout etc to /dev/null */
       nullfd = open("/dev/null", O_RDWR);
       dup2(nullfd, STDOUT_FILENO);
@@ -591,7 +591,7 @@
 	  t.tv_usec = 0;
 	  tp = &t;
 	}
-#ifdef __ANDROID__
+#if defined(__ANDROID__) && !defined(__BRILLO__)
       set_android_listeners(&rset, &maxfd);
 #endif
 
@@ -686,7 +686,7 @@
       check_dbus_listeners(&rset, &wset, &eset);
 #endif
 
-#ifdef __ANDROID__
+#if defined(__ANDROID__) && !defined(__BRILLO__)
       check_android_listeners(&rset);
 #endif
       
@@ -981,7 +981,7 @@
 #endif
 }
 
-#ifdef __ANDROID__
+#if defined(__ANDROID__) && !defined(__BRILLO__)
 
 static int set_android_listeners(fd_set *set, int *maxfdp) {
     FD_SET(STDIN_FILENO, set);
@@ -1007,7 +1007,7 @@
             char *params = current_cmd;
             int len = strlen(current_cmd);
 
-            cmd = strsep(&params, ":");
+            cmd = strsep(&params, "|");
             if (!strcmp(cmd, "update_dns")) {
                 if (params != NULL) {
                     set_servers(params);
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 0b9dbd2..2887546 100755
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -742,8 +742,9 @@
 time_t dnsmasq_time(void);
 int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
 int retry_send(void);
+int parse_addr(int family, const char *addrstr, union mysockaddr *addr);
 void prettyprint_time(char *buf, unsigned int t);
-int prettyprint_addr(union mysockaddr *addr, char *buf);
+int prettyprint_addr(const union mysockaddr *addr, char *buf);
 int parse_hex(char *in, unsigned char *out, int maxlen, 
 	      unsigned int *wildcard_mask, int *mac_type);
 int memcmp_masked(unsigned char *a, unsigned char *b, int len, 
@@ -781,7 +782,7 @@
 int random_sock(int family);
 void pre_allocate_sfds(void);
 int reload_servers(char *fname);
-#ifdef __ANDROID__
+#if defined(__ANDROID__) && !defined(__BRILLO__)
 int set_servers(const char *servers);
 void set_interfaces(const char *interfaces);
 #endif
diff --git a/src/network.c b/src/network.c
index c7431df..2df8c75 100755
--- a/src/network.c
+++ b/src/network.c
@@ -16,6 +16,8 @@
 
 #include "dnsmasq.h"
 
+static const char SEPARATOR[] = "|";
+
 #ifdef HAVE_LINUX_NETWORK
 
 int indextoname(int fd, int index, char *name)
@@ -102,7 +104,9 @@
 #ifdef HAVE_IPV6
 	    else if (family == AF_INET6 &&
 		     IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, 
-					&addr->addr.addr6))
+					&addr->addr.addr6) &&
+		     (!IN6_IS_ADDR_LINKLOCAL(&addr->addr.addr6) ||
+		      (tmp->addr.in6.sin6_scope_id == (uint32_t) *indexp)))
 	      ret = tmp->used = 1;
 #endif
 	  }          
@@ -182,8 +186,9 @@
       dhcp_ok = 0;
   
 #ifdef HAVE_IPV6
+  int ifindex = (int) addr->in6.sin6_scope_id;
   if (addr->sa.sa_family == AF_INET6 &&
-      !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL))
+      !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &ifindex))
     return 1;
 #endif
 
@@ -219,7 +224,15 @@
   addr.in6.sin6_family = AF_INET6;
   addr.in6.sin6_addr = *local;
   addr.in6.sin6_port = htons(daemon->port);
-  addr.in6.sin6_scope_id = scope;
+  /**
+   * Only populate the scope ID if the address is link-local.
+   * Scope IDs are not meaningful for global addresses. Also, we do not want to
+   * think that two addresses are different if they differ only in scope ID,
+   * because the kernel will treat them as if they are the same.
+   */
+  if (IN6_IS_ADDR_LINKLOCAL(local)) {
+    addr.in6.sin6_scope_id = scope;
+  }
   
   return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
 }
@@ -445,6 +458,8 @@
       /* An interface may have an IPv6 address which is still undergoing DAD.
          If so, the bind will fail until the DAD completes, so we try over 20 seconds
          before failing. */
+      /* TODO: What to do here? 20 seconds is way too long. We use optimistic addresses, so bind()
+         will only fail if the address has already failed DAD, in which case retrying won't help. */
       if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) &&
           dad_count++ < DAD_WAIT)
       {
@@ -506,34 +521,21 @@
 }
 
 /**
- * Close the sockets listening on the given interface
+ * Closes the sockets of the specified listener, deletes it from the list, and frees it.
  *
- * This new function is needed as we're dynamically changing the interfaces
- * we listen on.  Before they'd be opened once in create_bound_listeners and stay
- * until we exited.  Now, if an interface moves off the to-listen list we need to
- * close out the listeners and keep trucking.
- *
- * interface - input of the interface details to listen on
  */
-int close_bound_listener(struct irec *interface)
+int delete_listener(struct listener **l)
 {
-  /* find the listener */
-  struct listener **l, *listener;
-  for (l = &(daemon->listeners); *l; l = &((*l)->next)) {
-    struct irec *listener_iface = (*l)->iface;
-    if (listener_iface && interface) {
-      if (sockaddr_isequal(&listener_iface->addr, &interface->addr)) {
-        break;
-      }
-    } else {
-      if (interface == NULL && listener_iface == NULL) {
-        break;
-      }
-    }
-  }
-  listener = *l;
+  struct listener *listener = *l;
   if (listener == NULL) return 0;
 
+  if (listener->iface) {
+    int port = prettyprint_addr(&listener->iface->addr, daemon->namebuff);
+    my_syslog(LOG_INFO, _("Closing listener [%s]:%d"), daemon->namebuff, port);
+  } else {
+    my_syslog(LOG_INFO, _("Closing wildcard listener family=%d"), listener->family);
+  }
+
   if (listener->tftpfd != -1)
   {
     close(listener->tftpfd);
@@ -553,6 +555,39 @@
   free(listener);
   return -1;
 }
+
+/**
+ * Close the sockets listening on the given interface
+ *
+ * This new function is needed as we're dynamically changing the interfaces
+ * we listen on.  Before they'd be opened once in create_bound_listeners and stay
+ * until we exited.  Now, if an interface moves off the to-listen list we need to
+ * close out the listeners and keep trucking.
+ *
+ * interface - input of the interface details to listen on
+ */
+int close_bound_listener(struct irec *iface)
+{
+  /* find the listener */
+  int ret = 0;
+  struct listener **l = &daemon->listeners;
+  while (*l) {
+    struct irec *listener_iface = (*l)->iface;
+    struct listener **next = &((*l)->next);
+    if (iface && listener_iface && sockaddr_isequal(&listener_iface->addr, &iface->addr)) {
+      // Listener bound to an IP address. There can be only one of these.
+      ret = delete_listener(l);
+      break;
+    }
+    if (iface == NULL && listener_iface == NULL) {
+      // Wildcard listener. There is one of these per address family.
+      ret = delete_listener(l);
+      continue;
+    }
+    l = next;
+  }
+  return ret;
+}
 #endif /* __ANDROID__ */
 
 struct listener *create_bound_listeners(void)
@@ -916,13 +951,13 @@
   daemon->servers = ret;
 }
 
-#ifdef __ANDROID__
+#if defined(__ANDROID__) && !defined(__BRILLO__)
 /* #define __ANDROID_DEBUG__ 1 */
 /*
  * Ingests a new list of interfaces and starts to listen on them, adding only the new
  * and stopping to listen to any interfaces not on the new list.
  *
- * interfaces - input in the format "bt-pan:eth0:wlan0:..>" up to 1024 bytes long
+ * interfaces - input in the format "bt-pan|eth0|wlan0|..>" up to 1024 bytes long
  */
 void set_interfaces(const char *interfaces)
 {
@@ -947,7 +982,7 @@
         die(_("interface string too long: %s"), NULL, EC_BADNET);
     }
     strncpy(s, interfaces, sizeof(s));
-    while((interface = strsep(&next, ":"))) {
+    while((interface = strsep(&next, SEPARATOR))) {
         if_tmp = safe_malloc(sizeof(struct iname));
         memset(if_tmp, 0, sizeof(struct iname));
         if ((if_tmp->name = strdup(interface)) == NULL) {
@@ -1034,7 +1069,7 @@
 }
 
 /*
- * Takes a string in the format "0x100b:1.2.3.4:1.2.3.4:..." - up to 1024 bytes in length
+ * Takes a string in the format "0x100b|1.2.3.4|1.2.3.4|..." - up to 1024 bytes in length
  *  - The first element is the socket mark to set on sockets that forward DNS queries.
  *  - The subsequent elements are the DNS servers to forward queries to.
  */
@@ -1074,32 +1109,26 @@
   char *saddr;
 
   /* Parse the mark. */
-  mark_string = strsep(&next, ":");
+  mark_string = strsep(&next, SEPARATOR);
   mark = strtoul(mark_string, NULL, 0);
 
-  while ((saddr = strsep(&next, ":"))) {
+  while ((saddr = strsep(&next, SEPARATOR))) {
       union mysockaddr addr, source_addr;
       memset(&addr, 0, sizeof(addr));
       memset(&source_addr, 0, sizeof(source_addr));
 
-      if ((addr.in.sin_addr.s_addr = inet_addr(saddr)) != (in_addr_t) -1)
+      if (parse_addr(AF_INET, saddr, &addr) == 0)
 	{
-#ifdef HAVE_SOCKADDR_SA_LEN
-	  source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
-#endif
-	  source_addr.in.sin_family = addr.in.sin_family = AF_INET;
 	  addr.in.sin_port = htons(NAMESERVER_PORT);
+	  source_addr.in.sin_family = AF_INET;
 	  source_addr.in.sin_addr.s_addr = INADDR_ANY;
 	  source_addr.in.sin_port = htons(daemon->query_port);
 	}
 #ifdef HAVE_IPV6
-      else if (inet_pton(AF_INET6, saddr, &addr.in6.sin6_addr) > 0)
+      else if (parse_addr(AF_INET6, saddr, &addr) == 0)
 	{
-#ifdef HAVE_SOCKADDR_SA_LEN
-	  source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
-#endif
-	  source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
 	  addr.in6.sin6_port = htons(NAMESERVER_PORT);
+	  source_addr.in6.sin6_family = AF_INET6;
 	  source_addr.in6.sin6_addr = in6addr_any;
 	  source_addr.in6.sin6_port = htons(daemon->query_port);
 	}
@@ -1195,25 +1224,19 @@
       
       memset(&addr, 0, sizeof(addr));
       memset(&source_addr, 0, sizeof(source_addr));
-      
-      if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
+
+      if (parse_addr(AF_INET, token, &addr) == 0)
 	{
-#ifdef HAVE_SOCKADDR_SA_LEN
-	  source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
-#endif
-	  source_addr.in.sin_family = addr.in.sin_family = AF_INET;
 	  addr.in.sin_port = htons(NAMESERVER_PORT);
+	  source_addr.in.sin_family = AF_INET;
 	  source_addr.in.sin_addr.s_addr = INADDR_ANY;
 	  source_addr.in.sin_port = htons(daemon->query_port);
 	}
 #ifdef HAVE_IPV6
-      else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
+      else if (parse_addr(AF_INET6, token, &addr) == 0)
 	{
-#ifdef HAVE_SOCKADDR_SA_LEN
-	  source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
-#endif
-	  source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
 	  addr.in6.sin6_port = htons(NAMESERVER_PORT);
+	  source_addr.in6.sin6_family = AF_INET6;
 	  source_addr.in6.sin6_addr = in6addr_any;
 	  source_addr.in6.sin6_port = htons(daemon->query_port);
 	}
diff --git a/src/option.c b/src/option.c
index 49b6f3f..9e7ac2f 100755
--- a/src/option.c
+++ b/src/option.c
@@ -1352,25 +1352,9 @@
 	comma = split(arg);
 	unhide_metas(arg);
 	new->next = daemon->if_addrs;
-	if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
-	  {
-	    new->addr.sa.sa_family = AF_INET;
-#ifdef HAVE_SOCKADDR_SA_LEN
-	    new->addr.in.sin_len = sizeof(new->addr.in);
-#endif
-	  }
-#ifdef HAVE_IPV6
-	else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
-	  {
-	    new->addr.sa.sa_family = AF_INET6;
-	    new->addr.in6.sin6_flowinfo = 0;
-	    new->addr.in6.sin6_scope_id = 0;
-#ifdef HAVE_SOCKADDR_SA_LEN
-	    new->addr.in6.sin6_len = sizeof(new->addr.in6);
-#endif
-	  }
-#endif
-	else
+	if (arg &&
+	    parse_addr(AF_INET, arg, &new->addr) != 0 &&
+	    parse_addr(AF_INET6, arg, &new->addr) != 0)
 	  {
 	    option = '?'; /* error */
 	    break;
@@ -1449,18 +1433,16 @@
 		!atoi_check16(portno, &serv_port))
 	      problem = _("bad port");
 	    
-	    if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
+	    if (parse_addr(AF_INET, arg, &newlist->addr) == 0)
 	      {
 		newlist->addr.in.sin_port = htons(serv_port);	
-		newlist->source_addr.in.sin_port = htons(source_port); 
-		newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
 #ifdef HAVE_SOCKADDR_SA_LEN
 		newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
 #endif
 		if (source)
 		  {
 		    newlist->flags |= SERV_HAS_SOURCE;
-		    if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
+		    if (parse_addr(AF_INET, source, &newlist->addr) != 0)
 		      {
 #if defined(SO_BINDTODEVICE)
 			newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
@@ -1472,20 +1454,18 @@
 		  }
 		else
 		  newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
+
+		newlist->source_addr.in.sin_port = htons(source_port);
+		newlist->source_addr.sa.sa_family = AF_INET;
 	      }
 #ifdef HAVE_IPV6
-	    else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
+	    else if (parse_addr(AF_INET6, arg, &newlist->addr) == 0)
 	      {
 		newlist->addr.in6.sin6_port = htons(serv_port);
-		newlist->source_addr.in6.sin6_port = htons(source_port);
-		newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
-#ifdef HAVE_SOCKADDR_SA_LEN
-		newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
-#endif
 		if (source)
 		  {
 		     newlist->flags |= SERV_HAS_SOURCE;
-		     if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
+		     if (parse_addr(AF_INET6, source, &newlist->source_addr) != 0)
 		      {
 #if defined(SO_BINDTODEVICE)
 			newlist->source_addr.in6.sin6_addr = in6addr_any; 
@@ -1497,6 +1477,9 @@
 		  }
 		else
 		  newlist->source_addr.in6.sin6_addr = in6addr_any; 
+
+		newlist->source_addr.in6.sin6_port = htons(source_port);
+		newlist->source_addr.sa.sa_family = AF_INET6;
 	      }
 #endif
 	    else
diff --git a/src/rfc1035.c b/src/rfc1035.c
index d13f5bf..e440e8a 100755
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -241,6 +241,8 @@
 	 that we can since there is no reason not to.
       */
 
+      /* TODO: does this make sense? */
+
       if (*name == '\\' && *(name+1) == '[' && 
 	  (*(name+2) == 'x' || *(name+2) == 'X'))
 	{	  
diff --git a/src/util.c b/src/util.c
index ce77f05..e44b8fa 100755
--- a/src/util.c
+++ b/src/util.c
@@ -20,6 +20,8 @@
 
 #include "dnsmasq.h"
 
+#include <netdb.h>
+
 #ifdef HAVE_BROKEN_RTC
 #include <sys/times.h>
 #endif
@@ -260,7 +262,9 @@
 #ifdef HAVE_IPV6      
       if (s1->sa.sa_family == AF_INET6 &&
 	  s1->in6.sin6_port == s2->in6.sin6_port &&
-	  IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
+	  IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr) &&
+	  (!IN6_IS_ADDR_LINKLOCAL(&s1->in6.sin6_addr) ||
+	   (s1->in6.sin6_scope_id == s2->in6.sin6_scope_id)))
 	return 1;
 #endif
     }
@@ -322,22 +326,47 @@
   return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
 } 
 
+int parse_addr(int family, const char *addrstr, union mysockaddr *addr)
+{
+  struct addrinfo *res, hints = {
+    .ai_flags = AI_NUMERICHOST,
+    .ai_family = family,
+    .ai_socktype = SOCK_DGRAM,
+  };
+
+  int ret = getaddrinfo(addrstr, NULL, &hints, &res);
+  if (ret) {
+    return ret;
+  }
+
+  switch (res->ai_family) {
+    case AF_INET:
+      addr->in = *((struct sockaddr_in *) res->ai_addr);
+      break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      addr->in6 = *((struct sockaddr_in6 *) res->ai_addr);
+      break;
+#endif
+    default:
+      errno = EAFNOSUPPORT;
+      ret = -1;
+      break;
+  }
+  freeaddrinfo(res);
+  return ret;
+}
+
 /* returns port number from address */
-int prettyprint_addr(union mysockaddr *addr, char *buf)
+int prettyprint_addr(const union mysockaddr *addr, char *buf)
 {
   int port = 0;
   
 #ifdef HAVE_IPV6
-  if (addr->sa.sa_family == AF_INET)
-    {
-      inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
-      port = ntohs(addr->in.sin_port);
-    }
-  else if (addr->sa.sa_family == AF_INET6)
-    {
-      inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
-      port = ntohs(addr->in6.sin6_port);
-    }
+  char portstr[strlen("65535")];
+  getnameinfo((const struct sockaddr *) addr, sizeof(*addr), buf, ADDRSTRLEN,
+              portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
+  port = atoi(portstr);
 #else
   strcpy(buf, inet_ntoa(addr->in.sin_addr));
   port = ntohs(addr->in.sin_port);