summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2010-01-20 10:54:48 -0800
committerSan Mehat <san@google.com>2010-01-20 10:55:28 -0800
commit33b344454b95ed99bad7d3fe4d493870923deaf6 (patch)
tree44dc7f7854a014e1db6dfa22d7684bdb8703e771 /src
parent5658bcb797978c3472335d93554405aba8236f66 (diff)
downloadandroid_external_dnsmasq-33b344454b95ed99bad7d3fe4d493870923deaf6.tar.gz
android_external_dnsmasq-33b344454b95ed99bad7d3fe4d493870923deaf6.tar.bz2
android_external_dnsmasq-33b344454b95ed99bad7d3fe4d493870923deaf6.zip
dnsmasq: Allow runtime changing of DNS servers via STDIN
Signed-off-by: San Mehat <san@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/Android.mk1
-rwxr-xr-xsrc/dnsmasq.c55
-rwxr-xr-xsrc/dnsmasq.h3
-rwxr-xr-xsrc/log.c24
-rwxr-xr-xsrc/network.c101
5 files changed, 182 insertions, 2 deletions
diff --git a/src/Android.mk b/src/Android.mk
index f68a09b..35f6dd6 100644
--- a/src/Android.mk
+++ b/src/Android.mk
@@ -11,6 +11,7 @@ LOCAL_MODULE := dnsmasq
LOCAL_C_INCLUDES := external/dnsmasq/src
LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils
include $(BUILD_EXECUTABLE)
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 5d05f28..1a9d808 100755
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -64,6 +64,10 @@ static void sig_handler(int sig);
static void async_event(int pipe, time_t now);
static void fatal_event(struct event_desc *ev);
static void poll_resolv(void);
+#ifdef __ANDROID__
+static int set_android_listeners(fd_set *set, int *maxfdp);
+static int check_android_listeners(fd_set *set);
+#endif
int main (int argc, char **argv)
{
@@ -278,7 +282,9 @@ int main (int argc, char **argv)
if (!(daemon->options & OPT_DEBUG))
{
+#ifndef __ANDROID__
int nullfd;
+#endif
/* The following code "daemonizes" the process.
See Stevens section 12.4 */
@@ -344,13 +350,15 @@ int main (int argc, char **argv)
_exit(0);
}
}
-
+
+#ifndef __ANDROID__
/* open stdout etc to /dev/null */
nullfd = open("/dev/null", O_RDWR);
dup2(nullfd, STDOUT_FILENO);
dup2(nullfd, STDERR_FILENO);
dup2(nullfd, STDIN_FILENO);
close(nullfd);
+#endif
}
log_err = log_start(ent_pw, err_pipe[1]);
@@ -577,6 +585,9 @@ int main (int argc, char **argv)
t.tv_usec = 0;
tp = &t;
}
+#ifdef __ANDROID__
+ set_android_listeners(&rset, &maxfd);
+#endif
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
if (daemon->tftp_trans ||
@@ -668,6 +679,10 @@ int main (int argc, char **argv)
}
check_dbus_listeners(&rset, &wset, &eset);
#endif
+
+#ifdef __ANDROID__
+ check_android_listeners(&rset);
+#endif
check_dns_listeners(&rset, now);
@@ -960,6 +975,44 @@ void clear_cache_and_reload(time_t now)
#endif
}
+#ifdef __ANDROID__
+
+static int set_android_listeners(fd_set *set, int *maxfdp) {
+ FD_SET(STDIN_FILENO, set);
+ bump_maxfd(STDIN_FILENO, maxfdp);
+ return 0;
+}
+
+static int check_android_listeners(fd_set *set) {
+ if (FD_ISSET(STDIN_FILENO, set)) {
+ char buffer[1024];
+ int rc;
+
+ if ((rc = read(STDIN_FILENO, buffer, sizeof(buffer) -1)) < 0) {
+ my_syslog(LOG_ERR, _("Error reading from stdin (%s)"), strerror(errno));
+ return -1;
+ }
+ buffer[rc] = '\0';
+ char *next = buffer;
+ char *cmd;
+
+ if (!(cmd = strsep(&next, ":"))) {
+ my_syslog(LOG_ERR, _("Malformatted msg '%s'"), buffer);
+ return -1;
+ }
+
+ if (!strcmp(buffer, "update_dns")) {
+ set_servers(&buffer[11]);
+ check_servers();
+ } else {
+ my_syslog(LOG_ERR, _("Unknown cmd '%s'"), cmd);
+ return -1;
+ }
+ }
+ return 0;
+}
+#endif
+
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
{
struct serverfd *serverfdp;
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index f204cbf..e2dedc6 100755
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -779,6 +779,9 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
int random_sock(int family);
void pre_allocate_sfds(void);
int reload_servers(char *fname);
+#ifdef __ANDROID__
+int set_servers(const char *servers);
+#endif
void check_servers(void);
int enumerate_interfaces();
struct listener *create_wildcard_listeners(void);
diff --git a/src/log.c b/src/log.c
index 7ec491d..2fc0c6e 100755
--- a/src/log.c
+++ b/src/log.c
@@ -16,6 +16,10 @@
#include "dnsmasq.h"
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
/* Implement logging to /dev/log asynchronously. If syslogd is
making DNS lookups through dnsmasq, and dnsmasq blocks awaiting
syslogd, then the two daemons can deadlock. We get around this
@@ -261,6 +265,9 @@ void my_syslog(int priority, const char *format, ...)
size_t len;
pid_t pid = getpid();
char *func = "";
+#ifdef __ANDROID__
+ int alog_lvl;
+#endif
if ((LOG_FACMASK & priority) == MS_TFTP)
func = "-tftp";
@@ -278,6 +285,20 @@ void my_syslog(int priority, const char *format, ...)
fputc('\n', stderr);
}
+#ifdef __ANDROID__
+ if (priority <= LOG_ERR)
+ alog_lvl = ANDROID_LOG_ERROR;
+ else if (priority == LOG_WARNING)
+ alog_lvl = ANDROID_LOG_WARN;
+ else if (priority <= LOG_INFO)
+ alog_lvl = ANDROID_LOG_INFO;
+ else
+ alog_lvl = ANDROID_LOG_DEBUG;
+ va_start(ap, format);
+ __android_log_vprint(alog_lvl, "dnsmasq", format, ap);
+ va_end(ap);
+#else
+
if (log_fd == -1)
{
/* fall-back to syslog if we die during startup or fail during running. */
@@ -369,7 +390,8 @@ void my_syslog(int priority, const char *format, ...)
/* Have another go now */
log_write();
}
- }
+ }
+#endif
}
void set_log_writer(fd_set *set, int *maxfdp)
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 @@ void check_servers(void)
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)