diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2014-09-03 05:49:13 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-09-03 05:49:13 +0000 |
commit | 7a92013e2adf74e3d4e4aae3c5ffeb62c28b8c6a (patch) | |
tree | 664d70327bd2e2c7c4af566bfc8989333b3aa586 | |
parent | d17378f90186b0071ce2279e0d03f16f0a76cb58 (diff) | |
parent | 68eff53e7ed9df06f194478930f39b31c7a32458 (diff) | |
download | android_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-x | src/dnsmasq.h | 4 | ||||
-rwxr-xr-x | src/forward.c | 17 | ||||
-rwxr-xr-x | src/network.c | 37 |
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; |