OSDN Git Service

Add a netcontext variant of gethostbyaddr
authorBen Schwartz <bemasc@google.com>
Mon, 24 Apr 2017 21:57:11 +0000 (17:57 -0400)
committerBen Schwartz <bemasc@google.com>
Thu, 18 May 2017 18:32:21 +0000 (14:32 -0400)
Bug: 34953048
Test: Integration tests pass
Change-Id: Id04830345be56cd7a077981c6e2acfb5568e7a88

13 files changed:
libc/dns/include/resolv_netid.h
libc/dns/include/resolv_params.h
libc/dns/include/resolv_private.h
libc/dns/net/gethnamaddr.c
libc/dns/net/getnameinfo.c
libc/dns/resolv/res_send.c
libc/libc.arm.map
libc/libc.arm64.map
libc/libc.map.txt
libc/libc.mips.map
libc/libc.mips64.map
libc/libc.x86.map
libc/libc.x86_64.map

index 37c1891..711792b 100644 (file)
@@ -34,6 +34,7 @@
  */
 #include <sys/cdefs.h>
 #include <netinet/in.h>
+#include "resolv_params.h"
 #include <stdio.h>
 
 /*
@@ -71,6 +72,7 @@ struct android_net_context {
     unsigned dns_netid;
     unsigned dns_mark;
     uid_t uid;
+    res_send_qhook qhook;
 };
 
 #define NET_CONTEXT_INVALID_UID ((uid_t)-1)
@@ -83,6 +85,7 @@ int android_getaddrinfofornet(const char *, const char *, const struct addrinfo
  * TODO: consider refactoring android_getaddrinfo_proxy() to serve as an
  * explore_fqdn() dispatch table method, with the below function only making DNS calls.
  */
+struct hostent *android_gethostbyaddrfornetcontext(const void *, socklen_t, int, const struct android_net_context *) __used_in_netd;
 int android_getaddrinfofornetcontext(const char *, const char *, const struct addrinfo *,
     const struct android_net_context *, struct addrinfo **) __used_in_netd;
 
@@ -97,7 +100,7 @@ extern void _resolv_flush_cache_for_net(unsigned netid) __used_in_netd;
 extern void _resolv_delete_cache_for_net(unsigned netid) __used_in_netd;
 
 /* Internal use only. */
-struct hostent *android_gethostbyaddrfornet_proxy(const void *, socklen_t, int , unsigned, unsigned) __LIBC_HIDDEN__;
+struct hostent *android_gethostbyaddrfornetcontext_proxy(const void *, socklen_t, int , const struct android_net_context *) __LIBC_HIDDEN__;
 int android_getnameinfofornet(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, unsigned, unsigned) __LIBC_HIDDEN__;
 FILE* android_open_proxy(void) __LIBC_HIDDEN__;
 
index 49ae691..1b9d433 100644 (file)
@@ -43,4 +43,15 @@ struct __res_params {
     uint8_t max_samples; // max # samples taken into account for statistics
 };
 
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+       res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)(struct sockaddr * const *,
+                                             const u_char **, int *,
+                                             u_char *, int, int *);
+
+typedef res_sendhookact (*res_send_rhook)(const struct sockaddr *,
+                                             const u_char *, int, u_char *,
+                                             int, int *);
+
 #endif // _RESOLV_PARAMS_H
index 54b9626..284270c 100644 (file)
@@ -116,17 +116,6 @@ struct __res_state; /* forward */
 #endif
 #endif
 
-typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
-       res_sendhookact;
-
-typedef res_sendhookact (*res_send_qhook)(struct sockaddr * const *,
-                                             const u_char **, int *,
-                                             u_char *, int, int *);
-
-typedef res_sendhookact (*res_send_rhook)(const struct sockaddr *,
-                                             const u_char *, int, u_char *,
-                                             int, int *);
-
 struct res_sym {
        int             number;    /* Identifying number, like T_MX */
        const char *    name;      /* Its symbolic name, like "MX" */
index 75cb2b3..036ad1d 100644 (file)
@@ -119,6 +119,14 @@ static const int DnsProxyQueryResult = 222;
 static const char AskedForGot[] =
                          "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
 
+static const struct android_net_context NETCONTEXT_UNSET = {
+       .app_mark = MARK_UNSET,
+       .app_netid = NETID_UNSET,
+       .dns_mark = MARK_UNSET,
+       .dns_netid = NETID_UNSET,
+       .uid = NET_CONTEXT_INVALID_UID
+};
+
 #define        MAXPACKET       (64*1024)
 
 typedef union {
@@ -153,8 +161,8 @@ static int _dns_gethtbyname(void *, void *, va_list);
 
 static struct hostent *gethostbyname_internal(const char *, int, res_state,
     struct hostent *, char *, size_t, int *, unsigned, unsigned);
-static struct hostent* android_gethostbyaddrfornet_proxy_internal(const void*, socklen_t,
-    int, struct hostent *, char *, size_t, int *, unsigned, unsigned);
+static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t,
+    int, struct hostent *, char *, size_t, int *, const struct android_net_context *);
 
 static const ns_src default_dns_files[] = {
        { NSSRC_FILES,  NS_SUCCESS },
@@ -850,8 +858,8 @@ gethostbyname_internal(const char *name, int af, res_state res, struct hostent *
 int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf,
                     size_t buflen, struct hostent **result, int *h_errnop)
 {
-       *result = android_gethostbyaddrfornet_proxy_internal(addr, len, af, hp, buf, buflen, h_errnop,
-                                                       NETID_UNSET, MARK_UNSET);
+       *result = android_gethostbyaddrfornetcontext_proxy_internal(
+               addr, len, af, hp, buf, buflen, h_errnop, &NETCONTEXT_UNSET);
        if (!*result && errno == ENOSPC) {
                errno = ERANGE;
                return ERANGE;
@@ -860,8 +868,9 @@ int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
 }
 
 static struct hostent *
-android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, struct hostent *hp,
-                                 char *buf, size_t buflen, int *he, unsigned netid, unsigned mark)
+android_gethostbyaddrfornetcontext_real(const void *addr, socklen_t len, int af, struct hostent *hp,
+                                 char *buf, size_t buflen, int *he,
+                                const struct android_net_context *netcontext)
 {
        const u_char *uaddr = (const u_char *)addr;
        socklen_t size;
@@ -913,21 +922,21 @@ android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, struct
        info.he = he;
        *he = NETDB_INTERNAL;
        if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
-           default_dns_files, uaddr, len, af, netid, mark) != NS_SUCCESS)
+           default_dns_files, uaddr, len, af, netcontext) != NS_SUCCESS)
                return NULL;
        *he = NETDB_SUCCESS;
        return hp;
 }
 
 static struct hostent*
-android_gethostbyaddrfornet_proxy_internal(const void* addr, socklen_t len, int af,
+android_gethostbyaddrfornetcontext_proxy_internal(const void* addr, socklen_t len, int af,
                              struct hostent *hp, char *hbuf, size_t hbuflen, int *he,
-                             unsigned netid, unsigned mark)
+                             const struct android_net_context *netcontext)
 {
        FILE* proxy = android_open_proxy();
        if (proxy == NULL) {
                // Either we're not supposed to be using the proxy or the proxy is unavailable.
-               return android_gethostbyaddrfornet_real(addr,len, af, hp, hbuf, hbuflen, he, netid, mark);
+               return android_gethostbyaddrfornetcontext_real(addr,len, af, hp, hbuf, hbuflen, he, netcontext);
        }
 
        char buf[INET6_ADDRSTRLEN];  //big enough for IPv4 and IPv6
@@ -937,7 +946,7 @@ android_gethostbyaddrfornet_proxy_internal(const void* addr, socklen_t len, int
                return NULL;
        }
 
-       netid = __netdClientDispatch.netIdForResolv(netid);
+       unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
 
        if (fprintf(proxy, "gethostbyaddr %s %d %d %u",
                        addrStr, len, af, netid) < 0) {
@@ -1238,15 +1247,14 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
        char *bf;
        size_t blen;
        struct getnamaddr *info = rv;
-       unsigned netid, mark;
+       const struct android_net_context *netcontext;
 
        _DIAGASSERT(rv != NULL);
 
        uaddr = va_arg(ap, unsigned char *);
        info->hp->h_length = va_arg(ap, int);
        info->hp->h_addrtype = va_arg(ap, int);
-       netid = va_arg(ap, unsigned);
-       mark = va_arg(ap, unsigned);
+       netcontext = va_arg(ap, const struct android_net_context *);
 
        switch (info->hp->h_addrtype) {
        case AF_INET:
@@ -1288,8 +1296,8 @@ _dns_gethtbyaddr(void *rv, void   *cb_data, va_list ap)
                free(buf);
                return NS_NOTFOUND;
        }
-       res_setnetid(res, netid);
-       res_setmark(res, mark);
+       res_setnetid(res, netcontext->dns_netid);
+       res_setmark(res, netcontext->dns_mark);
        n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
        if (n < 0) {
                free(buf);
@@ -1585,6 +1593,21 @@ gethostbyname2(const char *name, int af)
        return result;
 }
 
+// android_gethostby*fornet can be called in two different contexts.
+//  - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
+//  - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
+// The netcontext is constructed before checking which context we are in.
+// Therefore, we have to populate both fields, and rely on the downstream code to check whether
+// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
+static struct android_net_context make_context(unsigned netid, unsigned mark) {
+       struct android_net_context netcontext = NETCONTEXT_UNSET;
+       netcontext.app_netid = netid;
+       netcontext.app_mark = mark;
+       netcontext.dns_netid = netid;
+       netcontext.dns_mark = mark;
+       return netcontext;
+}
+
 struct hostent *
 android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark)
 {
@@ -1602,22 +1625,30 @@ android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned m
 struct hostent *
 gethostbyaddr(const void *addr, socklen_t len, int af)
 {
-       return android_gethostbyaddrfornet_proxy(addr, len, af, NETID_UNSET, MARK_UNSET);
+       return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
 }
 
 struct hostent *
 android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
 {
-       return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark);
+       const struct android_net_context netcontext = make_context(netid, mark);
+       return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
+}
+
+struct hostent *
+android_gethostbyaddrfornetcontext(const void *addr, socklen_t len, int af,
+       const struct android_net_context *netcontext)
+{
+       return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
 }
 
 __LIBC_HIDDEN__ struct hostent*
-android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af,
-                                  unsigned netid, unsigned mark)
+android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
+                                  const struct android_net_context *netcontext)
 {
        res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
-       return android_gethostbyaddrfornet_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
-                                                    sizeof(rs->hostbuf), &h_errno, netid, mark);
+       return android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
+                                                    sizeof(rs->hostbuf), &h_errno, netcontext);
 }
 
 struct hostent *
index 236e7f2..5fa4e37 100644 (file)
@@ -300,7 +300,10 @@ getnameinfo_inet(const struct sockaddr* sa, socklen_t salen,
                        break;
                }
        } else {
-               hp = android_gethostbyaddrfornet_proxy(addr, afd->a_addrlen, afd->a_af, netid, mark);
+               // This code should only run in the app context, not inside netd, so netid is
+               // the app's netid.  netd doesn't use getnameinfo for network requests.
+               const struct android_net_context netcontext = { .app_netid = netid, .app_mark = mark };
+               hp = android_gethostbyaddrfornetcontext_proxy(addr, afd->a_addrlen, afd->a_af, &netcontext);
                if (hp) {
 #if 0
                        /*
index f53da5f..71cc852 100644 (file)
@@ -523,6 +523,10 @@ res_nsend(res_state statp,
                                        res_nclose(statp);
                                        goto next_ns;
                                case res_done:
+                                       if (cache_status == RESOLV_CACHE_NOTFOUND) {
+                                               _resolv_cache_add(statp->netid, buf, buflen,
+                                                               ans, resplen);
+                                       }
                                        return (resplen);
                                case res_modified:
                                        /* give the hook another try */
index 0e1c988..5b94f80 100644 (file)
@@ -1494,6 +1494,7 @@ LIBC_PRIVATE {
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
index 34b8b19..cd1aff6 100644 (file)
@@ -1242,6 +1242,7 @@ LIBC_PRIVATE {
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     free_malloc_leak_info;
     get_malloc_leak_info;
index c4bc262..90929f5 100644 (file)
@@ -1520,6 +1520,7 @@ LIBC_PRIVATE {
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
index d80e659..bdfd3b8 100644 (file)
@@ -1337,6 +1337,7 @@ LIBC_PRIVATE {
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
index 34b8b19..cd1aff6 100644 (file)
@@ -1242,6 +1242,7 @@ LIBC_PRIVATE {
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     free_malloc_leak_info;
     get_malloc_leak_info;
index 8ba5e69..dd2ecca 100644 (file)
@@ -1336,6 +1336,7 @@ LIBC_PRIVATE {
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
index 34b8b19..cd1aff6 100644 (file)
@@ -1242,6 +1242,7 @@ LIBC_PRIVATE {
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     free_malloc_leak_info;
     get_malloc_leak_info;