標籤:android
Android DNS 代碼都在bionic/libc/netbsd中
(雖然netbsd 是個廢棄的項目,但dns功能部分代碼被 Android用上了)
netbsd 代碼晦澀難懂,只有一邊寫程式,一邊打log驗證
照抄了一個簡單程式, 在android 下面用 mmm 編譯可以得到 py_getaddr 可執行檔, 用adb 登陸到 devices 再到 system/bin 下去執行
[email protected]:~/njb/getaddr$ cat py_getaddr.c #include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <string.h>int main(int argc, char **argv){if (argc != 2) {fprintf(stderr, "Usage: %s hostname\n",argv[1]);exit(1); }struct addrinfo *answer, hint, *curr;char ipstr[16]; bzero(&hint, sizeof(hint));hint.ai_family = AF_INET;hint.ai_socktype = SOCK_STREAM;int ret = getaddrinfo(argv[1], NULL, &hint, &answer);if (ret != 0) {fprintf(stderr,"getaddrinfo: &s\n",gai_strerror(ret));exit(1);}for (curr = answer; curr != NULL; curr = curr->ai_next) {inet_ntop(AF_INET,&(((struct sockaddr_in *)(curr->ai_addr))->sin_addr),ipstr, 16);printf("%s\n", ipstr);}freeaddrinfo(answer);exit(0);}
cat Android.mk LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:= py_getaddr.cLOCAL_MODULE := py_getaddrLOCAL_STATIC_LIBRARIES := libcutils libcinclude $(BUILD_EXECUTABLE)
到運行 py_getadd sohu.com 的時候, 調用過程如下
_files_getaddrinfo 是讀取/system/etc/hosts 檢索
_dns_getaddrinfo 是訪問dns server
在訪問構造 dns 訪問的時候,如何找到 dns server, 原來在 __res_get_state 調用返回 __res_state (這個複雜的結構定義在 bionic/libc/private/resolv_private.h#__res_state )
在調用過程中 __res_vinit 使用了系統設定的 8.8.8.8 nameserver (jeallybean 代碼在bionic/libc/netbsd/resolv/res_init.c#339)
之後res_queryN 用 res_nmkquery 構造dns 查詢,並用 res_nsend 發送查詢,並得到返回結果。
運行程式和 log 的列印結果如下:
py_getaddr sohu.com
======================= _files_getaddrinfo
======================= _dns_getaddrinfo
=========== getaddrinfo cp 8.8.8.8, subf 53
================ res_searchN sohu.com
================ res_querydomainN name sohu.com, domain (null)
================ res_queryN sohu.com
;; res_nmkquery(QUERY, sohu.com, IN, A)
================getanswer sohu.com
220.181.90.240
123.125.116.19
Android DNS 程式碼分析