OSDN Git Service

Add new info functions to resolver for use by Netd.
authorPierre Imai <imaipi@google.com>
Mon, 18 Apr 2016 03:00:12 +0000 (12:00 +0900)
committerPierre Imai <imaipi@google.com>
Thu, 21 Apr 2016 01:07:26 +0000 (10:07 +0900)
android_net_res_stats_get_info_for_net returns the current name servers, search
domains, parameters and stats for the given network ID.

android_net_res_stats_aggregate provides statistics such as errors counts from
the raw stats data reported by android_net_res_stats_get_info_for_net.

android_net_res_stats_get_usable_servers uses the data returned by
android_net_res_stats_aggregate to determine which of the servers are
considered valid or broken by the resolver.

BUG: 25731675

Change-Id: I6059b68e5e8b809027a4d3135f6081588bee8a7d

16 files changed:
libc/dns/include/resolv_params.h
libc/dns/include/resolv_private.h
libc/dns/include/resolv_stats.h
libc/dns/resolv/res_cache.c
libc/dns/resolv/res_send.c
libc/dns/resolv/res_stats.c
libc/libc.arm.brillo.map
libc/libc.arm.map
libc/libc.arm64.map
libc/libc.map.txt
libc/libc.mips.brillo.map
libc/libc.mips.map
libc/libc.mips64.map
libc/libc.x86.brillo.map
libc/libc.x86.map
libc/libc.x86_64.map

index f6948c0..5ee265f 100644 (file)
 #include <stdint.h>
 
 /* Hard-coded defines */
-#define        MAXNS                   4       /* max # name servers we'll track */
-#define        MAXNSSAMPLES            64      /* max # samples to store per server */
+#define MAXNS                  4       /* max # name servers we'll track */
+#define MAXDNSRCH              6       /* max # domains in search path */
+#define MAXDNSRCHPATH          256     /* max length of domain search paths */
+#define MAXNSSAMPLES           64      /* max # samples to store per server */
 
 /* Defaults used for initializing __res_params */
 #define SUCCESS_THRESHOLD      75      /* if successes * 100 / total_samples is less than
index 8cdcc2e..3ab8ea6 100644 (file)
@@ -140,7 +140,6 @@ struct res_sym {
  * Global defines and variables for resolver stub.
  */
 #define        MAXDFLSRCH              3       /* # default domain levels to try */
-#define        MAXDNSRCH               6       /* max # domains in search path */
 #define        LOCALDOMAINPARTS        2       /* min levels in name that is "local" */
 
 #define        RES_TIMEOUT             5       /* min. seconds between retries */
index aaf6bd8..c7901d7 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _RES_STATS_H
 #define _RES_STATS_H
 
+#include <sys/socket.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <time.h>
@@ -46,18 +47,13 @@ struct __res_stats {
 };
 
 /* Calculate the round-trip-time from start time t0 and end time t1. */
-int
+extern int
 _res_stats_calculate_rtt(const struct timespec* t1, const struct timespec* t0);
 
 /* Initialize a sample for calculating server reachability statistics. */
 extern void
 _res_stats_set_sample(struct __res_sample* sample, time_t now, int rcode, int rtt);
 
-/* Aggregates the reachability statistics for the given server based on on the stored samples. */
-extern void
-_res_stats_aggregate(struct __res_stats* stats, int* successes, int* errors, int* timeouts,
-             int* internal_errors, int* rtt_avg, time_t* last_sample_time);
-
 /* Returns true if the server is considered unusable, i.e. if the success rate is not lower than the
  * threshold for the stored stored samples. If not enough samples are stored, the server is
  * considered usable.
@@ -65,9 +61,24 @@ _res_stats_aggregate(struct __res_stats* stats, int* successes, int* errors, int
 extern bool
 _res_stats_usable_server(const struct __res_params* params, struct __res_stats* stats);
 
+__BEGIN_DECLS
+/* Aggregates the reachability statistics for the given server based on on the stored samples. */
+extern void
+android_net_res_stats_aggregate(struct __res_stats* stats, int* successes, int* errors,
+        int* timeouts, int* internal_errors, int* rtt_avg, time_t* last_sample_time)
+    __attribute__((visibility ("default")));
+
+extern int
+android_net_res_stats_get_info_for_net(unsigned netid, int* nscount,
+        struct sockaddr_storage servers[MAXNS], int* dcount, char domains[MAXDNSRCH][MAXDNSRCHPATH],
+        struct __res_params* params, struct __res_stats stats[MAXNS])
+    __attribute__((visibility ("default")));
+
 /* Returns an array of bools indicating which servers are considered good */
 extern void
-_res_stats_get_usable_servers(const struct __res_params* params, struct __res_stats stats[],
-        int nscount, bool valid_servers[]);
+android_net_res_stats_get_usable_servers(const struct __res_params* params,
+        struct __res_stats stats[], int nscount, bool valid_servers[])
+    __attribute__((visibility ("default")));
+__END_DECLS
 
 #endif  // _RES_STATS_H
index 5f51c49..02887f2 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include "resolv_cache.h"
+
 #include <resolv.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -1238,8 +1239,7 @@ struct resolv_cache_info {
     int                         revision_id; // # times the nameservers have been replaced
     struct __res_params         params;
     struct __res_stats          nsstats[MAXNS];
-    // TODO: replace with char* defdname[MAXDNSRCH]
-    char                        defdname[256];
+    char                        defdname[MAXDNSRCHPATH];
     int                         dnsrch_offset[MAXDNSRCH+1];  // offsets into defdname
 };
 
@@ -2183,6 +2183,68 @@ _res_cache_clear_stats_locked(struct resolv_cache_info* cache_info) {
 }
 
 int
+android_net_res_stats_get_info_for_net(unsigned netid, int* nscount,
+        struct sockaddr_storage servers[MAXNS], int* dcount, char domains[MAXDNSRCH][MAXDNSRCHPATH],
+        struct __res_params* params, struct __res_stats stats[MAXNS]) {
+    int revision_id = -1;
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    struct resolv_cache_info* info = _find_cache_info_locked(netid);
+    if (info) {
+        if (info->nscount > MAXNS) {
+            pthread_mutex_unlock(&_res_cache_list_lock);
+            XLOG("%s: nscount %d > MAXNS %d", __FUNCTION__, info->nscount, MAXNS);
+            errno = EFAULT;
+            return -1;
+        }
+        int i;
+        for (i = 0; i < info->nscount; i++) {
+            // Verify that the following assumptions are held, failure indicates corruption:
+            //  - getaddrinfo() may never return a sockaddr > sockaddr_storage
+            //  - all addresses are valid
+            //  - there is only one address per addrinfo thanks to numeric resolution
+            int addrlen = info->nsaddrinfo[i]->ai_addrlen;
+            if (addrlen < (int) sizeof(struct sockaddr) ||
+                    addrlen > (int) sizeof(servers[0])) {
+                pthread_mutex_unlock(&_res_cache_list_lock);
+                XLOG("%s: nsaddrinfo[%d].ai_addrlen == %d", __FUNCTION__, i, addrlen);
+                errno = EMSGSIZE;
+                return -1;
+            }
+            if (info->nsaddrinfo[i]->ai_addr == NULL) {
+                pthread_mutex_unlock(&_res_cache_list_lock);
+                XLOG("%s: nsaddrinfo[%d].ai_addr == NULL", __FUNCTION__, i);
+                errno = ENOENT;
+                return -1;
+            }
+            if (info->nsaddrinfo[i]->ai_next != NULL) {
+                pthread_mutex_unlock(&_res_cache_list_lock);
+                XLOG("%s: nsaddrinfo[%d].ai_next != NULL", __FUNCTION__, i);
+                errno = ENOTUNIQ;
+                return -1;
+            }
+        }
+        *nscount = info->nscount;
+        for (i = 0; i < info->nscount; i++) {
+            memcpy(&servers[i], info->nsaddrinfo[i]->ai_addr, info->nsaddrinfo[i]->ai_addrlen);
+            stats[i] = info->nsstats[i];
+        }
+        for (i = 0; i < MAXDNSRCH; i++) {
+            if (info->dnsrch_offset[i] == -1) {
+                break;
+            }
+            strlcpy(domains[i], info->defdname + info->dnsrch_offset[i], MAXDNSRCHPATH);
+        }
+        *dcount = i;
+        *params = info->params;
+        revision_id = info->revision_id;
+    }
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+    return revision_id;
+}
+
+int
 _resolv_cache_get_resolver_stats( unsigned netid, struct __res_params* params,
         struct __res_stats stats[MAXNS]) {
     int revision_id = -1;
index bfc6e1a..0e30b28 100644 (file)
@@ -492,7 +492,8 @@ res_nsend(res_state statp,
            struct __res_params params;
            int revision_id = _resolv_cache_get_resolver_stats(statp->netid, &params, stats);
            bool usable_servers[MAXNS];
-           _res_stats_get_usable_servers(&params, stats, statp->nscount, usable_servers);
+           android_net_res_stats_get_usable_servers(&params, stats, statp->nscount,
+                   usable_servers);
 
            for (ns = 0; ns < statp->nscount; ns++) {
                if (!usable_servers[ns]) continue;
index 5cc592e..99c79e4 100644 (file)
@@ -54,8 +54,8 @@ _res_stats_clear_samples(struct __res_stats* stats)
 
 /* Aggregates the reachability statistics for the given server based on on the stored samples. */
 void
-_res_stats_aggregate(struct __res_stats* stats, int* successes, int* errors, int* timeouts,
-             int* internal_errors, int* rtt_avg, time_t* last_sample_time)
+android_net_res_stats_aggregate(struct __res_stats* stats, int* successes, int* errors,
+        int* timeouts, int* internal_errors, int* rtt_avg, time_t* last_sample_time)
 {
     int s = 0;   // successes
     int e = 0;   // errors
@@ -123,8 +123,8 @@ _res_stats_usable_server(const struct __res_params* params, struct __res_stats*
     int internal_errors = -1;
     int rtt_avg = -1;
     time_t last_sample_time = 0;
-    _res_stats_aggregate(stats, &successes, &errors, &timeouts, &internal_errors, &rtt_avg,
-            &last_sample_time);
+    android_net_res_stats_aggregate(stats, &successes, &errors, &timeouts, &internal_errors,
+            &rtt_avg, &last_sample_time);
     if (successes >= 0 && errors >= 0 && timeouts >= 0) {
         int total = successes + errors + timeouts;
         if (DBG) {
@@ -164,8 +164,8 @@ _res_stats_usable_server(const struct __res_params* params, struct __res_stats*
 }
 
 void
-_res_stats_get_usable_servers(const struct __res_params* params, struct __res_stats stats[],
-        int nscount, bool usable_servers[]) {
+android_net_res_stats_get_usable_servers(const struct __res_params* params,
+        struct __res_stats stats[], int nscount, bool usable_servers[]) {
     unsigned usable_servers_found = 0;
     for (int ns = 0; ns < nscount; ns++) {
         bool usable = _res_stats_usable_server(params, &stats[ns]);
index 541dbb2..b0c8299 100644 (file)
@@ -1468,3 +1468,10 @@ LIBC_PRIVATE {
     SHA1Transform; # arm x86 mips
     SHA1Update; # arm x86 mips
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 1784b95..7a3b8bd 100644 (file)
@@ -1507,3 +1507,10 @@ LIBC_PRIVATE {
     wait3; # arm x86 mips nobrillo
     wcswcs; # arm x86 mips nobrillo
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 7daa557..217d95e 100644 (file)
@@ -1222,3 +1222,10 @@ LIBC_PRIVATE {
     get_malloc_leak_info;
     gMallocLeakZygoteChild;
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index f51c5d3..c7f9058 100644 (file)
@@ -1533,3 +1533,10 @@ LIBC_PRIVATE {
     wait3; # arm x86 mips nobrillo
     wcswcs; # arm x86 mips nobrillo
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 953fc29..2b92162 100644 (file)
@@ -1309,3 +1309,10 @@ LIBC_PRIVATE {
     SHA1Transform; # arm x86 mips
     SHA1Update; # arm x86 mips
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 90db79d..934b23b 100644 (file)
@@ -1348,3 +1348,10 @@ LIBC_PRIVATE {
     wait3; # arm x86 mips nobrillo
     wcswcs; # arm x86 mips nobrillo
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 7daa557..217d95e 100644 (file)
@@ -1222,3 +1222,10 @@ LIBC_PRIVATE {
     get_malloc_leak_info;
     gMallocLeakZygoteChild;
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 9f6cc52..d973ac1 100644 (file)
@@ -1308,3 +1308,10 @@ LIBC_PRIVATE {
     SHA1Transform; # arm x86 mips
     SHA1Update; # arm x86 mips
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 4443731..b3f9394 100644 (file)
@@ -1347,3 +1347,10 @@ LIBC_PRIVATE {
     wait3; # arm x86 mips nobrillo
     wcswcs; # arm x86 mips nobrillo
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;
index 7daa557..217d95e 100644 (file)
@@ -1222,3 +1222,10 @@ LIBC_PRIVATE {
     get_malloc_leak_info;
     gMallocLeakZygoteChild;
 } LIBC_O;
+
+LIBC_PLATFORM {
+  global:
+    android_net_res_stats_get_info_for_net;
+    android_net_res_stats_aggregate;
+    android_net_res_stats_get_usable_servers;
+} LIBC_O;