#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
* 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 */
#ifndef _RES_STATS_H
#define _RES_STATS_H
+#include <sys/socket.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
};
/* 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.
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
*/
#include "resolv_cache.h"
+
#include <resolv.h>
#include <stdarg.h>
#include <stdio.h>
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
};
}
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;
struct __res_params params;
int revision_id = _resolv_cache_get_resolver_stats(statp->netid, ¶ms, stats);
bool usable_servers[MAXNS];
- _res_stats_get_usable_servers(¶ms, stats, statp->nscount, usable_servers);
+ android_net_res_stats_get_usable_servers(¶ms, stats, statp->nscount,
+ usable_servers);
for (ns = 0; ns < statp->nscount; ns++) {
if (!usable_servers[ns]) continue;
/* 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
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) {
}
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]);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;