DnsProxyListener和Android系統中的DNS管理有關。什么是DNS呢?Android系統中DNS又有什么特點呢?來看下文。
**1. Android DNS介紹[3]**
DNS是Domain Name System(域名系統)的縮寫。其主要目的是在域名和IP地址之間建立一種映射。簡單點說,DNS的功能類似于電話簿,它可將人名映射到相應的電話號碼。在DNS中,人名就是域名,電話號碼就是IP地址。域名系統的管理由DNS服務器來完成。全球范圍內的DNS服務器共同構成了一個分布式的域名-IP數據庫。
對使用域名來發起網絡操作的網絡程序來說,其域名解析工作主要分兩步:
- 1)第一步工作就是需要將域名轉換成IP。由于域名和IP的轉換關系存儲在DNS服務器上,所以該網絡程序要向DNS服務器發起請求,以獲取域名對應的IP地址。
- 2)DNS服務器根據DNS解析規則解析并得到該域名對應的IP地址,然后返回給客戶端。在DNS中,每一個域名和IP的對應關系被稱之為一條記錄。客戶端一般會緩存這條記錄以備后續之用。
>[info] **提醒**:DNS解析規則比較復雜,感興趣的讀者可研究DNS的相關協議。
對軟件開發者來說,常用的域名解析socket API有兩個:
- getaddrinfo:它根據指定的host名或service名得到對應的IP地址(該IP地址由結構體addrinfo表達)。
- getnameinfo:根據指定的IP地址(由結構體sockaddr表達)得到對應的host或service的名稱。
Android中,這兩個函數均由Bionic C實現。其代碼實現基于NetBSD的解析庫(resolver library),并經過一些修改。這些修改包括:
- 沒有實現name-server-switch功能。這是為了保持Bionic C庫的輕便性而做的裁剪。
- DNS服務器的配置文件由/etc/resolv.conf變成/system/etc/resolv.conf[^1]。在Android系統中,/etc目錄實際上為/system/etc目錄的鏈接。resolv.conf存儲的是DNS服務器的IP地址。
- 系統屬性中保存了一些DNS服務器的地址,它們通過諸如"net.dns1"或"net.dns2"之類的屬性來表達。這些屬性由dhcpd進程或其他系統模塊負責維護。
- 每個進程還可以設置進程特定的DNS服務器地址。它們通過諸如"net.dns1.<pid>"或"net.dns2.<pid>"的系統屬性來表達。
- 不同的網絡設備也有對應的DNS服務器地址,例如通過wlan接口發起的網絡操作,其對應的DNS服務器由系統屬性“net.wlan.dns1”表示。
圖2-6所示為三星Galaxy Note2中有關dns信息的示意圖。
:-: 
圖2-6 net.dns設置示意圖
由圖2-6可知:
- 系統中有些進程有自己特定的DNS服務器。
- 不同網絡設備也設置了對應的DNS服務器地址。
**2. getaddrinfo函數分析**
本節將介紹Android中getaddrinfo的實現,我們將只關注Android對其做的改動。
**getaddrinfo.c::getaddrinfo**
~~~
int getaddrinfo(const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
......//getaddrinfo的正常處理
//Android平臺的特殊定制
if (android_getaddrinfo_proxy(hostname, servname, hints, res) == 0) {
return 0;
}
......//如果上述函數處理失敗,則繼續getaddrinfo的正常處理
return error
}
~~~
由上述代碼可知,Android平臺中的getaddrinfo會調用其定制的android_getaddrinfo_proxy函數完成一些特殊操作,該函數的實現如下所示:
**getaddrinfo.c::android_getaddrinfo_proxy**
~~~
static int android_getaddrinfo_proxy(const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
.......
//取ANDROID_DNS_MODE環境變量。只有Netd進程設置了它
const char* cache_mode = getenv("ANDROID_DNS_MODE");
......
//由于Netd進程設置了此環境變量,故Netd進程調用getaddrinfo的話,將不會采用這套定制的方法
if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
return -1;
}
//獲取本進程對應的DNS地址
snprintf(propname, sizeof(propname), "net.dns1.%d", getpid());
if (__system_property_get(propname, propvalue) > 0) {
return -1;
}
//建立和Netd中DnsProxyListener的連接,將請求轉發給它去執行
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
return -1;
}
......
strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd",
sizeof(proxy_addr.sun_path));
......//發送請求,處理回復等
return -1;
}
~~~
由上述代碼可知:
- 當Netd進程調用getaddrinfo時,由于其設置了ANDROID_DNS_MODE環境變量,所以該函數會繼續原來的流程。
- 當非Netd進程調用getaddrinfo函數時,首先會開展android_getaddrinfo_proxy中的工作,即判斷該進程是否有定制的DNS服務器,如果沒有的話它將和位于Netd進程中的"dnsproxyd"監聽socket建立連接,然后把請求發給DnsProxyListener去執行。
**3. DnsProxyListener命令介紹**
下面來介紹DnsProxyListener(以后簡稱DPL),圖2-7所示為其家族成員示意圖:
:-: 
圖2-7 DPL家族示意圖
由圖2-7可知,DPL僅定義了兩個命令:
- GetAddrInfoCmd,和Bionic C庫的getaddrinfo函數對應。
- GetHostByAddrCmd,和Bionic C庫的gethostbyaddr函數對應。
這個兩條命令的處理比較簡單,此處就不擬展開詳細的代碼。
為方便讀者理解,我們將給出調用序列圖,如圖2-8所示。
:-: 
圖2-8 GetAddrInfoCmd處理流程示意圖
由圖2-8所示,GetAddrInfoHandler最終的處理還是交由Bionic C的getaddrinfo函數來完成。根據前文所述,由于Netd進程設置了ANDROID_DNS_MODE環境變量,故Netd調用的getaddrinfo將走正常的流程。這個正常流程就是Netd進程將向指定的DNS服務器發起請求以解析域名。
Android系統中,通過這種方式來管理DNS的好處是所有解析后得到的DNS記錄都將緩存在Netd進程中,從而使這些信息成為了一個公共的資源,最大程度內做到了信息共享。
[^1]:此處結論來自bioni c/li bc/docs/OVERVIEW.txt 文件,不過根據同目錄下CHANGE S. txt 的說明, resolv. conf將不再使用。
- 前言
- 第1章 準備工作
- 1.1 Android系統架構
- 1.2 工具使用
- 1.2.1 Source Insight的使用
- 1.2.2 Eclipse的使用
- 1.2.3 BusyBox的使用
- 1.3 本書資源下載說明
- 第2章 深入理解Netd
- 2.1 概述
- 2.2 Netd工作流程
- 2.2.1 main函數分析
- 2.2.2 NetlinkManager分析
- 2.2.3 CommandListener分析
- 2.2.4 DnsProxyListener分析
- 2.2.5 MDnsSdListener分析
- 2.3 CommandListener中的命令
- 2.3.1 iptables、tc和ip命令
- 2.3.2 CommandListener構造函數和測試工具ndc
- 2.3.3 InterfaceCmd命令
- 2.3.4 IpFwd和FirewallCmd命令
- 2.3.5 ListTtysCmd和PppdCmd命令
- 2.3.6 BandwidthControlCmd和IdletimerControlCmd命令
- 2.3.7 NatCmd命令
- 2.3.8 TetherCmd和SoftapCmd命令
- 2.3.9 ResolverCmd命令
- 2.4 NetworkManagementService介紹
- 2.4.1 create函數詳解
- 2.4.2 systemReady函數詳解
- 2.5 本章總結和參考資料說明
- 2.5.1 本章總結
- 2.5.2 參考資料說明
- 第3章 Wi-Fi基礎知識
- 3.1 概述
- 3.2 無線電頻譜和802.11協議的發展歷程
- 3.2.1 無線電頻譜知識
- 3.2.2 IEEE 802.11發展歷程
- 3.3 802.11無線網絡技術
- 3.3.1 OSI基本參考模型及相關基本概念
- 3.3.2 802.11知識點導讀
- 3.3.3 802.11組件
- 3.3.4 802.11 Service介紹
- 3.3.5 802.11 MAC服務和幀
- 3.3.6 802.11 MAC管理實體
- 3.3.7 無線網絡安全技術知識點
- 3.4 Linux Wi-Fi編程API介紹
- 3.4.1 Linux Wireless Extensions介紹
- 3.4.2 nl80211介紹
- 3.5 本章總結和參考資料說明
- 3.5.1 本章總結
- 3.5.2 參考資料說明
- 第4章 深入理解wpa_supplicant
- 4.1 概述
- 4.2 初識wpa_supplicant
- 4.2.1 wpa_supplicant架構
- 4.2.2 wpa_supplicant編譯配置
- 4.2.3 wpa_supplicant命令和控制API
- 4.2.4 git的使用
- 4.3 wpa_supplicant初始化流程
- 4.3.1 main函數分析
- 4.3.2 wpa_supplicant_init函數分析
- 4.3.3 wpa_supplicant_add_iface函數分析
- 4.3.4 wpa_supplicant_init_iface函數分析
- 4.4 EAP和EAPOL模塊
- 4.4.1 EAP模塊分析
- 4.4.2 EAPOL模塊分析
- 4.5 wpa_supplicant連接無線網絡分析
- 4.5.1 ADD_NETWORK命令處理
- 4.5.2 SET_NETWORK命令處理
- 4.5.3 ENABLE_NETWORK命令處理
- 4.6 本章總結和參考資料說明
- 4.6.1 本章總結
- 4.6.2 參考資料說明
- 第5章 深入理解WifiService
- 5.1 概述
- 5.2 WifiService的創建及初始化
- 5.2.1 HSM和AsyncChannel介紹
- 5.2.2 WifiService構造函數分析
- 5.2.3 WifiStateMachine介紹
- 5.3 加入無線網絡分析
- 5.3.1 Settings操作Wi-Fi分析
- 5.3.2 WifiService操作Wi-Fi分析
- 5.4 WifiWatchdogStateMachine介紹
- 5.5 Captive Portal Check介紹
- 5.6 本章總結和參考資料說明
- 5.6.1 本章總結
- 5.6.2 參考資料說明
- 第6章 深入理解Wi-Fi Simple Configuration
- 6.1 概述
- 6.2 WSC基礎知識
- 6.2.1 WSC應用場景
- 6.2.2 WSC核心組件及接口
- 6.3 Registration Protocol詳解
- 6.3.1 WSC IE和Attribute介紹
- 6.3.2 802.11管理幀WSC IE設置
- 6.3.3 EAP-WSC介紹
- 6.4 WSC代碼分析
- 6.4.1 Settings中的WSC處理
- 6.4.2 WifiStateMachine的處理
- 6.4.3 wpa_supplicant中的WSC處理
- 6.4.4 EAP-WSC處理流程分析
- 6.5 本章總結和參考資料說明
- 6.5.1 本章總結
- 6.5.2 參考資料說明
- 第7章 深入理解Wi-Fi P2P
- 7.1 概述
- 7.2 P2P基礎知識
- 7.2.1 P2P架構
- 7.2.2 P2P Discovery技術
- 7.2.3 P2P工作流程
- 7.3 WifiP2pSettings和WifiP2pService介紹
- 7.3.1 WifiP2pSettings工作流程
- 7.3.2 WifiP2pService工作流程
- 7.4 wpa_supplicant中的P2P
- 7.4.1 P2P模塊初始化
- 7.4.2 P2P Device Discovery流程分析
- 7.4.3 Provision Discovery流程分析
- 7.4.4 GO Negotiation流程分析
- 7.5 本章總結和參考資料說明
- 7.5.1 本章總結
- 7.5.2 參考資料說明
- 第8章 深入理解NFC
- 8.1 概述
- 8.2 NFC基礎知識
- 8.2.1 NFC概述
- 8.2.2 NFC R/W運行模式
- 8.2.3 NFC P2P運行模式
- 8.2.4 NFC CE運行模式
- 8.2.5 NCI原理
- 8.2.6 NFC相關規范
- 8.3 Android中的NFC
- 8.3.1 NFC應用示例
- 8.3.2 NFC系統模塊
- 8.4 NFC HAL層討論
- 8.5 本章總結和參考資料說明
- 8.5.1 本章總結
- 8.5.2 參考資料說明
- 第9章 深入理解GPS
- 9.1 概述
- 9.2 GPS基礎知識
- 9.2.1 衛星導航基本原理
- 9.2.2 GPS系統組成及原理
- 9.2.3 OMA-SUPL協議
- 9.3 Android中的位置管理
- 9.3.1 LocationManager架構
- 9.3.2 LocationManager應用示例
- 9.3.3 LocationManager系統模塊
- 9.4 本章總結和參考資料說明
- 9.4.1 本章總結
- 9.4.2 參考資料說明
- 附錄