[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(¶ms, ":");
+ cmd = strsep(¶ms, "|");
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);