概述
ConnectivityService会通过netd将DNS参数设置到解析库的cache中,设置接口是_resolv_set_nameservers_for_net(),后续在DNS查询过程中,解析库会从cache中获取设置的DNS服务器地址。
数据结构
Android中,将DNS信息保存到了resolv_cache_info中,该结构中与DNS有关的信息如下所示:
struct resolv_cache_info {
//网卡的netid
unsigned netid;
//所有的cache_info构成一个列表
struct resolv_cache_info* next;
//设置的DNS服务器地址的数目,即下面nameservers数组中有效数据由几个
int nscount;
//保存设置的DNS服务器地址,当前限制最多可以设置4个DNS服务器地址
char* nameservers[MAXNS];
//转换后的DNS服务器地址信息,用于查询
struct addrinfo* nsaddrinfo[MAXNS];
//见注释,DNS服务器地址每变更一次,该成员的值加1
int revision_id; // # times the nameservers have been replaced
//这两个参数用于域名搜索,具体见hostname(7),Android中基本上不使用,可以忽略
char defdname[MAXDNSRCHPATH];
int dnsrch_offset[MAXDNSRCH+1]; // offsets into defdname
};
_resolv_set_nameservers_for_net()
@netid:要设置的网卡;DNS服务器地址的设定都是基于网卡的
@servers:DNS服务器地址,字符串格式,最多可以设置4个
@numservers:要设置的DNS服务器地址个数,即servers[]数组的长度
@domains:本地域名,通常为空,用于DNS域名搜索,Android中基本不适用,可以不关注
@params:DNS缓存使用的几个参数
int _resolv_set_nameservers_for_net(unsigned netid, const char** servers, unsigned numservers,
const char *domains, const struct __res_params* params)
{
char sbuf[NI_MAXSERV];
register char *cp;
int *offset;
struct addrinfo* nsaddrinfo[MAXNS];
//要设置的DNS服务器地址不能超过MAXNS,当前为4个
if (numservers > MAXNS) {
XLOG("%s: numservers=%u, MAXNS=%u", __FUNCTION__, numservers, MAXNS);
return E2BIG;
}
//下面这段逻辑对要设置的DNS服务器地址进行一种简单的校验,这种校验只是调用getaddinfo()转换一下而已
// 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
};
//该地址的53号端口是否有对应的服务
snprintf(sbuf, sizeof(sbuf), "%u", NAMESERVER_PORT);
for (unsigned i = 0; i &