summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2014-09-03 05:49:13 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-09-03 05:49:13 +0000
commit7a92013e2adf74e3d4e4aae3c5ffeb62c28b8c6a (patch)
tree664d70327bd2e2c7c4af566bfc8989333b3aa586
parentd17378f90186b0071ce2279e0d03f16f0a76cb58 (diff)
parent68eff53e7ed9df06f194478930f39b31c7a32458 (diff)
downloadandroid_external_dnsmasq-7a92013e2adf74e3d4e4aae3c5ffeb62c28b8c6a.tar.gz
android_external_dnsmasq-7a92013e2adf74e3d4e4aae3c5ffeb62c28b8c6a.tar.bz2
android_external_dnsmasq-7a92013e2adf74e3d4e4aae3c5ffeb62c28b8c6a.zip
am 68eff53e: Allow configuring a socket mark for DNS packets.
* commit '68eff53e7ed9df06f194478930f39b31c7a32458': Allow configuring a socket mark for DNS packets.
-rwxr-xr-xsrc/dnsmasq.h4
-rwxr-xr-xsrc/forward.c17
-rwxr-xr-xsrc/network.c37
3 files changed, 44 insertions, 14 deletions
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index c4fda28..0b9dbd2 100755
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -321,6 +321,7 @@ struct serverfd {
union mysockaddr source_addr;
char interface[IF_NAMESIZE+1];
struct serverfd *next;
+ uint32_t mark;
};
struct randfd {
@@ -335,6 +336,7 @@ struct server {
char *domain; /* set if this server only handles a domain. */
int flags, tcpfd;
unsigned int queries, failed_queries;
+ uint32_t mark;
struct server *next;
};
@@ -775,7 +777,7 @@ struct frec *get_new_frec(time_t now, int *wait);
/* network.c */
int indextoname(int fd, int index, char *name);
-int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
+int local_bind(int fd, union mysockaddr *addr, char *intname, uint32_t mark, int is_tcp);
int random_sock(int family);
void pre_allocate_sfds(void);
int reload_servers(char *fname);
diff --git a/src/forward.c b/src/forward.c
index 40cda1c..a121123 100755
--- a/src/forward.c
+++ b/src/forward.c
@@ -318,8 +318,20 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
daemon->rfd_save = forward->rfd4;
fd = forward->rfd4->fd;
}
+
+#ifdef ANDROID
+ // Mark the socket so it goes out on the correct network. Note
+ // that we never clear the mark, only re-set it the next time we
+ // allocate a new random fd. This is because we buffer DNS
+ // queries (in daemon->srv_save, daemon->packet_len) and socket
+ // file descriptors (in daemon->rfd_save) with the expectation of
+ // being able to use them again.
+ //
+ // Server fds are marked separately in allocate_sfd.
+ setsockopt(fd, SOL_SOCKET, SO_MARK, &start->mark, sizeof(start->mark));
+#endif
}
-
+
if (sendto(fd, (char *)header, plen, 0,
&start->addr.sa,
sa_len(&start->addr)) == -1)
@@ -815,7 +827,8 @@ unsigned char *tcp_request(int confd, time_t now,
if ((last_server->tcpfd == -1) &&
(last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 &&
- (!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
+ (!local_bind(last_server->tcpfd, &last_server->source_addr,
+ last_server->interface, last_server->mark, 1) ||
connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
{
close(last_server->tcpfd);
diff --git a/src/network.c b/src/network.c
index cb2001d..43b1573 100755
--- a/src/network.c
+++ b/src/network.c
@@ -680,7 +680,7 @@ int random_sock(int family)
}
-int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
+int local_bind(int fd, union mysockaddr *addr, char *intname, uint32_t mark, int is_tcp)
{
union mysockaddr addr_copy = *addr;
@@ -704,10 +704,13 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
return 0;
#endif
+ if (mark != 0 && setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) == -1)
+ return 0;
+
return 1;
}
-static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
+static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname, uint32_t mark)
{
struct serverfd *sfd;
int errsave;
@@ -734,6 +737,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
/* may have a suitable one already */
for (sfd = daemon->sfds; sfd; sfd = sfd->next )
if (sockaddr_isequal(&sfd->source_addr, addr) &&
+ mark == sfd->mark &&
strcmp(intname, sfd->interface) == 0)
return sfd;
@@ -748,7 +752,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
return NULL;
}
- if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
+ if (!local_bind(sfd->fd, addr, intname, mark, 0) || !fix_fd(sfd->fd))
{
errsave = errno; /* save error from bind. */
close(sfd->fd);
@@ -759,6 +763,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
strcpy(sfd->interface, intname);
sfd->source_addr = *addr;
+ sfd->mark = mark;
sfd->next = daemon->sfds;
daemon->sfds = sfd;
return sfd;
@@ -780,7 +785,7 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(struct sockaddr_in);
#endif
- allocate_sfd(&addr, "");
+ allocate_sfd(&addr, "", 0);
#ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6;
@@ -789,13 +794,13 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
- allocate_sfd(&addr, "");
+ allocate_sfd(&addr, "", 0);
#endif
}
for (srv = daemon->servers; srv; srv = srv->next)
if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
- !allocate_sfd(&srv->source_addr, srv->interface) &&
+ !allocate_sfd(&srv->source_addr, srv->interface, srv->mark) &&
errno != 0 &&
(daemon->options & OPT_NOWILD))
{
@@ -845,7 +850,7 @@ void check_servers(void)
/* Do we need a socket set? */
if (!new->sfd &&
- !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
+ !(new->sfd = allocate_sfd(&new->source_addr, new->interface, new->mark)) &&
errno != 0)
{
my_syslog(LOG_WARNING,
@@ -999,7 +1004,9 @@ void set_interfaces(const char *interfaces)
}
/*
- * Takes a string in the format "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.
*/
int set_servers(const char *servers)
{
@@ -1007,6 +1014,8 @@ int set_servers(const char *servers)
struct server *old_servers = NULL;
struct server *new_servers = NULL;
struct server *serv;
+ char *mark_string;
+ uint32_t mark;
strncpy(s, servers, sizeof(s));
@@ -1031,10 +1040,14 @@ int set_servers(const char *servers)
serv = tmp;
}
- char *next = s;
- char *saddr;
+ char *next = s;
+ char *saddr;
+
+ /* Parse the mark. */
+ mark_string = strsep(&next, ":");
+ mark = strtoul(mark_string, NULL, 0);
- while ((saddr = strsep(&next, ":"))) {
+ while ((saddr = strsep(&next, ":"))) {
union mysockaddr addr, source_addr;
memset(&addr, 0, sizeof(addr));
memset(&source_addr, 0, sizeof(source_addr));
@@ -1080,6 +1093,7 @@ int set_servers(const char *servers)
serv->source_addr = source_addr;
serv->domain = NULL;
serv->interface[0] = 0;
+ serv->mark = mark;
serv->sfd = NULL;
serv->flags = SERV_FROM_RESOLV;
serv->queries = serv->failed_queries = 0;
@@ -1193,6 +1207,7 @@ int reload_servers(char *fname)
serv->source_addr = source_addr;
serv->domain = NULL;
serv->interface[0] = 0;
+ serv->mark = 0;
serv->sfd = NULL;
serv->flags = SERV_FROM_RESOLV;
serv->queries = serv->failed_queries = 0;