dnsmasq: Allow runtime changing of DNS servers via STDIN

Signed-off-by: San Mehat <san@google.com>
diff --git a/src/network.c b/src/network.c
index 68113fb..b0ffc6b 100755
--- a/src/network.c
+++ b/src/network.c
@@ -737,6 +737,107 @@
   daemon->servers = ret;
 }
 
+#ifdef __ANDROID__
+/*
+ * Takes a string in the format "1.2.3.4:1.2.3.4:..." - up to 1024 bytes in length
+ */
+int set_servers(const char *servers)
+{
+  char s[1024];
+  struct server *old_servers = NULL;
+  struct server *new_servers = NULL;
+  struct server *serv;
+
+  strncpy(s, servers, sizeof(s));
+
+  /* move old servers to free list - we can reuse the memory
+     and not risk malloc if there are the same or fewer new servers.
+     Servers which were specced on the command line go to the new list. */
+  for (serv = daemon->servers; serv;)
+    {
+      struct server *tmp = serv->next;
+      if (serv->flags & SERV_FROM_RESOLV)
+	{
+	  serv->next = old_servers;
+	  old_servers = serv;
+	  /* forward table rules reference servers, so have to blow them away */
+	  server_gone(serv);
+	}
+      else
+	{
+	  serv->next = new_servers;
+	  new_servers = serv;
+	}
+      serv = tmp;
+    }
+
+    char *next = s;
+    char *saddr;
+
+ while ((saddr = strsep(&next, ":"))) {
+      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)
+	{
+#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_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)
+	{
+#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_addr = in6addr_any;
+	  source_addr.in6.sin6_port = htons(daemon->query_port);
+	}
+#endif /* IPV6 */
+      else
+	continue;
+
+      if (old_servers)
+	{
+	  serv = old_servers;
+	  old_servers = old_servers->next;
+	}
+      else if (!(serv = whine_malloc(sizeof (struct server))))
+	continue;
+
+      /* this list is reverse ordered:
+	 it gets reversed again in check_servers */
+      serv->next = new_servers;
+      new_servers = serv;
+      serv->addr = addr;
+      serv->source_addr = source_addr;
+      serv->domain = NULL;
+      serv->interface[0] = 0;
+      serv->sfd = NULL;
+      serv->flags = SERV_FROM_RESOLV;
+      serv->queries = serv->failed_queries = 0;
+    }
+
+  /* Free any memory not used. */
+  while (old_servers)
+    {
+      struct server *tmp = old_servers->next;
+      free(old_servers);
+      old_servers = tmp;
+    }
+
+  daemon->servers = new_servers;
+  return 0;
+}
+#endif
+
 /* Return zero if no servers found, in that case we keep polling.
    This is a protection against an update-time/write race on resolv.conf */
 int reload_servers(char *fname)