android dns之dns服务器可用性机制,成功率低于门限则惩罚抑制(三)参数配置流程1

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", &params.sample_validity,
                &params.success_threshold, &params.min_samples, &params.max_samples) != 4) {
            return false;
        }
        paramsPtr = &params;
    }
    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) {
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值