文章目录
- 2 dns服务器可用性统计参数配置流程
- 2.1 方案一,cmd socket命令方式,当前使用中
- 2.1.1 netd接收ResolverCmd命令,resolver setnetdns < netId> < domains> < dns1> [< dns2> ...] [--params < params>]
- 2.1.2 解析--params参数,含:sample_validity,success_threshold,min_samples、max_samples
- 2.1.3 ResolverController::setDnsServers
- 2.1.4 libc dns协议栈中将netd传入的dns 参数设置到该网络的dns cache中,含dns server可用性配置,_resolv_set_nameservers_for_net
- 2.1.5 dns server名称、IP存入该网络的全局dns cache中(cache_info->nsaddrinfo[index])
- 2.1.6 将全局该网络dns cache中的dns server地址,赋值到res_state statp中,供dns查询流程使用
- 2.1.7 res_state获取
2 dns服务器可用性统计参数配置流程
2.1 方案一,cmd socket命令方式,当前使用中
2.1.1 netd接收ResolverCmd命令,resolver setnetdns < netId> < domains> < dns1> [< dns2> …] [–params < params>]
2.1.2 解析–params参数,含:sample_validity,success_threshold,min_samples、max_samples
system\netd\server\CommandListener.cpp
bool CommandListener::ResolverCmd::parseAndExecuteSetNetDns(int netId, int argc,
const char** argv) {
// "resolver setnetdns <netId> <domains> <dns1> [<dns2> ...] [--params <params>]"
// TODO: This code has to be replaced by a Binder call ASAP
if (argc < 5) {
return false;
}
int end = argc;
__res_params params;
const __res_params* paramsPtr = nullptr;
if (end > 6 && !strcmp(argv[end - 2], "--params")) {
const char* paramsStr = argv[end - 1];
end -= 2;
if (sscanf(paramsStr, "%hu %hhu %hhu %hhu", ¶ms.sample_validity,
¶ms.success_threshold, ¶ms.min_samples, ¶ms.max_samples) != 4) {
return false;
}
paramsPtr = ¶ms;
}
return gCtls->resolverCtrl.setDnsServers(netId, argv[3], &argv[4], end - 4, paramsPtr) == 0;
}
2.1.3 ResolverController::setDnsServers
system\netd\server\ResolverController.cpp
int ResolverController::setDnsServers(unsigned netId, const char* searchDomains,
const char** servers, int numservers, const __res_params* params) {
if (DBG) {
ALOGD("setDnsServers netId = %u, numservers = %d", netId, numservers);
}
/*AR000AT6PU liuheng 00308202 20180720 begin */
/*DTS2018090604542 ,maguofeng 00345783 20180912 begin */
int dataServiceType = DATASERVER_UNSPEC;
unsigned cmdNumber = sizeof(MOBILE_IFACE_IP) / sizeof(char*);
unsigned rmnetNetid = 0;
unsigned cmdIndex = 0;
unsigned wlanNetid = 0;
wlanNetid = net::gCtls->netCtrl.getNetworkForInterface("wlan0");
if (0 != wlanNetid && wlanNetid == netId) {
dataServiceType = DATASERVER_WIFI;
}
for (cmdIndex = 0; cmdIndex < cmdNumber; cmdIndex++) {
rmnetNetid = 0;
rmnetNetid = net::gCtls->netCtrl.getNetworkForInterface(MOBILE_IFACE_IP[cmdIndex]);
if (0 != rmnetNetid && rmnetNetid == netId) {
dataServiceType = DATASERVER_CELL;
break;
}
}
/*DTS2018090604542 ,maguofeng 00345783 20180912 end */
return -_resolv_set_nameservers_for_net(netId, servers, numservers, searchDomains, params, dataServiceType);
/*AR000AT6PU liuheng 00308202 20180720 end */
}
2.1.4 libc dns协议栈中将netd传入的dns 参数设置到该网络的dns cache中,含dns server可用性配置,_resolv_set_nameservers_for_net
bionic\libc\dns\resolv\res_cache.c
int
_resolv_set_nameservers_for_net(unsigned netid, const char** servers, unsigned numservers,
const char *domains, const struct __res_params* params, int dataServiceType)
{
char sbuf[NI_MAXSERV];
register char *cp;
int *offset;
struct addrinfo* nsaddrinfo[MAXNS];
int index;
if (numservers > MAXNS) {
XLOG("%s: numservers=%u, MAXNS=%u", __FUNCTION__, numservers, MAXNS);
return E2BIG;
}
// Parse the addresses before actually locking or changing any state, in case there is an error.
// As a side effect this also reduces the time the lock is kept.
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_DGRAM,
.ai_flags = AI_NUMERICHOST
};
snprintf(sbuf, sizeof(sbuf), "%u", NAMESERVER_PORT);
for (unsigned i = 0; i < numservers; i++) {
// The addrinfo structures allocated here are freed in _free_nameservers_locked().
int rt = getaddrinfo(servers[i], sbuf, &hints, &nsaddrinfo[i]);
if (rt != 0) {
for (unsigned j = 0 ; j < i ; j++) {
freeaddrinfo(nsaddrinfo[j]);
nsaddrinfo[j] = NULL;
}
XLOG("%s: getaddrinfo(%s)=%s", __FUNCTION__, servers[i], gai_strerror(rt));
return EINVAL;
}
}
pthread_once(&_res_cache_once, _res_cache_init);
pthread_mutex_lock(&_res_cache_list_lock);
// creates the cache if not created
_get_res_cache_for_net_locked(netid);
struct resolv_cache_info* cache_info = _find_cache_info_locked(netid);
if (cache_info != NULL) {
uint8_t old_max_samples = cache_info->params.max_samples;
if (params != NULL) {
cache_info->params = *params;
} else {
_resolv_set_default_params(&cache_info->params);
}
2.1.5 dns server名称、IP存入该网络的全局dns cache中(cache_info->nsaddrinfo[index])
res_cache.c
_resolv_set_nameservers_for_net(unsigned netid, const char** servers, unsigned numservers,
const char *domains, const struct __res_params* params, int dataServiceType)
{
......
struct resolv_cache_info* cache_info = _find_cache_info_locked(netid);
if (cache_info != NULL) {
uint8_t old_max_samples = cache_info->params.max_samples;
if (params != NULL) {
cache_info->params = *params;
} else {
_resolv_set_default_params(&cache_info->params);
}
if (!_resolv_is_nameservers_equal_locked(cache_info, servers, numservers)) {
// free current before adding new
_free_nameservers_locked(cache_info);
unsigned i;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
snprintf(sbuf, sizeof(sbuf), "%u", NAMESERVER_PORT);
index = 0;
for (i = 0; i < numservers && i < MAXNS; i++) {
int rt = getaddrinfo(servers[i], sbuf, &hints, &cache_info->nsaddrinfo[index]);
if (rt == 0) {
cache_info->nameservers[index] = strdup(servers[i]);
index++;
XLOG("%s: zwwxx netid = %u, addr = %s\n", __FUNCTION__, netid, servers[i]);
} else {
cache_info->nsaddrinfo[index] = NULL;
}
}
cache_info->nscount = numservers;
2.1.6 将全局该网络dns cache中的dns server地址,赋值到res_state statp中,供dns查询流程使用
_resolv_populate_res_for_net(res_state statp)
{
if (statp == NULL) {
return;
}
pthread_once(&_res_cache_once, _res_cache_init);
pthread_mutex_lock(&_res_cache_list_lock);
struct resolv_cache_info* info = _find_cache_info_locked(statp->netid);
if (info != NULL) {
int nserv;
struct addrinfo* ai;
XLOG("%s: %u\n", __FUNCTION__, statp->netid);
for (nserv = 0; nserv < MAXNS; nserv++) {
ai = info->nsaddrinfo[nserv];
if (ai == NULL) {
break;
}
if ((size_t) ai->ai_addrlen <= sizeof(statp->_u._ext.ext->nsaddrs[0])) {
if (statp->_u._ext.ext != NULL) {
memcpy(&statp->_u._ext.ext->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen);
statp->nsaddr_list[nserv].sin_family = AF_UNSPEC;
} else {
if ((size_t) ai->ai_addrlen
<= sizeof(statp->nsaddr_list[0])) {
//cache中的dns server地址赋值到statp中
memcpy(&statp->nsaddr_list[nserv], ai->ai_addr,
ai->ai_addrlen);
} else {
statp->nsaddr_list[nserv].sin_family = AF_UNSPEC;
}
}
} else {
XLOG("%s: found too long addrlen", __FUNCTION__);
}
}
statp->nscount = nserv;
2.1.7 res_state获取
_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
{
.......
res = __res_get_state();
.....
}
2.1.7.1 __res_state , _res_thread
typedef struct {
int _h_errno;
// TODO: Have one __res_state per network so we don't have to repopulate frequently.
struct __res_state _nres[1];
struct res_static _rstatic[1];
} _res_thread;
2.1.7.2 线程首次调用时alloc创建__res_state,并初始化res_ninit(可能初始用getenv(“LOCALDOMAIN”))
static _res_thread*
_res_thread_get(void)
{
_res_thread* rt;
rt = pthread_getspecific( _res_key );
if (rt != NULL) {
return rt;
}
/* It is the first time this function is called in this thread,
* we need to create a new thread-specific DNS resolver state. */
rt = _res_thread_alloc();
}
/* This function has to be reachable by res_data.c but not publicly. */
int
__res_vinit(res_state statp, int preinit) {
.....
/* Allow user to override the local domain definition */
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
}