最近做车载项目,有个需求是设置域名白名单,整体思路是增加一个接口,然后上层应用通过接口传域名到netd中,然后netd在进行DNS学习,最后将学习后的IP地址传到防火墙进行流量控制。这里就必须先讲一下netd相关知识。
Netd是Android系统中专门负责网络管理和控制的后台daemon程序,其功能主要分三大块:
Netd位于Framework层和Kernel层之间,它是Android系统中网络相关消息和命令转发及处理的中枢模块,Netd的工作流程可分成两部分:
启动(代码位于/system/core/rootdir下的init.rc):
==========================================================================================
start netd
==========================================================================================
配置(代码位于/system/netd/server/netd.rc):
==========================================================================================
service netd /system/bin/netd
class main
capabilities CHOWN DAC_OVERRIDE DAC_READ_SEARCH FOWNER IPC_LOCK KILL NET_ADMIN NET_BIND_SERVICE NET_RAW SETUID SETGID
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet
onrestart restart zygote
onrestart restart zygote_secondary
# b/121354779: netd itself is not updatable, but on startup it dlopen()s the resolver library
# from the DNS resolver APEX. Mark it as updatable so init won't start it until all APEX
# packages are ready.
updatable
==========================================================================================
可以看到启动了三个Socket,分别是dnsproxyd、mdns和fwmarkd
typedef void (*dns_resolve_result_callback)(const char* address, const char* ip);
- void dnsResolverResultCallback(const char* address, const char* ip) {
- gLog.info("dnsResolverResultCallback addres = %s, ip = %s", address, ip);
- gCtls->checkDnsResultWithWhiteList(address, ip);
- }
-
- bool initDnsResolver() {
- ResolverNetdCallbacks callbacks = {
- .check_calling_permission = &checkCallingPermissionCallback,
- .get_network_context = &getNetworkContextCallback,
- .log = &logCallback,
- .tagSocket = &tagSocketCallback,
- .evaluate_domain_name = &evaluateDomainNameCallback,
- .dns_resolve_result_callback = &dnsResolverResultCallback,
- };
- return resolv_init(&callbacks);
- }
- bool resolv_init(const ResolverNetdCallbacks* callbacks) {
- ……
- gResNetdCallbacks.dns_resolve_result_callback = callbacks->dns_resolve_result_callback;
- ……
- }
- void DnsProxyListener::GetAddrInfoHandler::run() {
- ……
- if(gResNetdCallbacks.dns_resolve_result_callback != nullptr) {
- struct sockaddr_in sinOriginal = *(struct sockaddr_in*) ai->ai_addr;
- char buf[INET6_ADDRSTRLEN]; // big enough for either IPv4 or IPv6
- inet_ntop(AF_INET, &sinOriginal.sin_addr.s_addr, buf, sizeof(buf));
- gResNetdCallbacks.dns_resolve_result_callback(mHost, buf);
- }
- ……
- }
cd ~/aosp //具体的源码根目录
source build/envsetup.sh //用于初始化环境变量
mmm development/tools/idegen/ //生成文件out/host/linux-x86/framework/idegen.jar
./development/tools/idegen/idegen.sh//源码根目录生成文件android.ipr(工程相关设置), android.iml(模块相关配置)
adb shell service call dnsresolver 10 i32 1
VERBOSE 0
DEBUG 1
INFO 2
WARNING 3
ERROR 4