Netd是Android系统中专门负责网络管理和控制的后台daemon程序,其功能主要分三部分。
Netd的工作流程和Vold类似,其工作可分为两部分
Netd启动时将创建三个TCP 监听socket,其名称分别为netd、dnsproxyd和mdns
Netd的main 函数非常简单,主要是创建几个重要成员并启动相应的工作,这四个重要成员分别如下:
NetlinkManager(以后简称NM)主要负责接收并解析来自Kernel的UEvent消息。其核心代码在start函数中
NM的start函数主要是向kernel注册三个用于接受UEvent事件的socket,这三个UEvent分别对应于以下内容
NETLINK_KOBJECT_UEVENT:代表kobject事件,由于这些事件包含的信息由ASCII字符串表达,故上述代码中使用NETLINK_FOMRAT_ASCII。它表示将采用字符串解析的方法去解析接收到的UEvent消息。kobject一般用来通知内核中某个模块的加载或卸载。对于NM来说,其关注的是/sys/class/net下相应模块的加载或卸载消息
NETLINK_ROUTE:代表kernel中routing或link改变时对应的消息。NETLINK_ROUTE包含很多子项,上述代码中使用了RTMGRP_LINK项。二者结合起来使用,表示NM希望收到网络链路断开或接通时对应的UEvent消息。由于对应UEvent消息内部封装了nlmsghdr等相关结构体,故上述代码使用了NETLINK_FORMAT_BINARY来指示解析UEvent消息时将使用二进制的解析方法
NETLINK_NFLOG:和带宽控制有关。Netd中的带宽控制可以设置一个预警值,当网络数据超过一定字节数就会触发Kernel发送一个警告。该功能属于iptables的扩展项。NETLINK_NFLOG相关socket的设置并非所有Kernel版本都支持。同时,NFLOG_QUOTA_GROUP的值是直接定义在Netlinkmanager.cpp中的,而非和其他类似系统定义一样定义在系统头文件中,这也表明NFLOG_QUOTA_GROUP的功能比较新
NetlinkHandler和 CommandListener均间接从SocketListener排成。其中,NetlinkHandler收到的socket消息将通过onEvent回调处理
NetlinkManager分别注册了三个用于接受UEvent的socket,其对应的NetlinkHandler分别是mUeventHandler、mRuoteHandler和mQuotaHandler
NetlinkHandler接收到的UEvent消息会转换成一个NetlinkEvent对象。NetlinkEvent对象封装了对UEvent消息的解析方法。对于NETLINK_FOMRAT_ASCII类型,其parseAsciiNetlinkMessage函数会被调用,而对于NETLINK_FOMRAT_BINARY类型,其parseBinaryNetlinkMessage函数会被调用
NM处理流程的输入为一个解析后的NetlinkEvent对象。NM完成相应工作后,其处理结果将经由mBroadcaster对象传递给Framework层的接收者,也就是NetworkManagementService
CommandListener从FrameworkListener派生,而FrameworkListener内部有一个数组mCommands,用于存储注册到FrameworkListener中的命令处理对象
Netd中第二个重要成员是CommandListener(以后简称CL),其主要作用是接收来自Framework层NetworkManageService的命令。从角色来看,CL仅是一个Listener。它在收到命令后,只是将它们转交给对应的命令处理对象去处理。CL内部定义了许多命令,而这些命令都有较深的背景知识。
CL定义了11个和网络相关的Command类。这些类均从NetdCommand派生(注意,为保持绘图简洁,这11个Command的派生关系由1个派生箭头表达)。CL还定义了10个控制类,这些控制类将和命令类共同完成相应的命令处理工作。
1 Android DNS 简介
DNS(Domain Name System,域名系统)主要作用是在域名和IP地址之间建立一种映射。简单来说,DNS的功能类似于电话簿,它可将人名映射到相应的电话号码。在DNS中,人名就是域名,电话号码就是IP地址。域名系统的管理由DNS服务器来完成。全球范围内的DNS服务器共同构成了一个分布式的域名-IP数据库。
对软件开发者来说,常用的域名解析socket API 有两个
2 getaddrinfo 函数分析
Android平台中的getaddrinfo会调用其定制的android_getaddrinfo_proxy函数完成一些特殊操作
3 DnsProxyListener 命令 简称(DPL)
GetAddrInfoHandler最终的处理还是交由Bionic C的getaddrinfo函数来完成。根据前文所述,由于Netd进程设置了ANDROID_DNS_MODE环境变量,故Netd调用的getaddrinfo将走正常的流程。这个正常流程就是Netd进程将向指定的DNS服务器发起请求以解析域名。
MDnsSd是Multicast DNS Service Discovery的简称
MDnsSdListener对应的Framework层服务为NsdService(Nsd为Network ServiceDiscovery的缩写),它是Android 4.1新增的一个Framework层Service
iptables 命令
iptables是Linux系统中最重要的网络管控工具。它与Kernel中的netflter模块配合工作,其主要功能是为netfilter设置一些过滤(flter)或网络地址转换(NAT)的规则。当Kernel收到网络数据包后,将会依据iptables设置的规则进行相应的操作。举个最简单的例子,可以利用iptables设置这样一条防火墙规则:丢弃来自IP地址为192.168.1.108的所有数据包。
tc命令
TC是Traffic Control的缩写。在Linux系统中,流量控制是通过建立数据包队列(Queue),并控制各个队列中数据包的发送方式来实现的
ip命令
ip命令是Linux系统中另一个强大的网络管理工具,主要功能如下。
InterfaceCmd用来管理和控制系统中的网络设备,其支持较多的控制选项。另外,InterfaceCmd除了和控制对象InterfaceController交互外,还会和ThrottleController、SecondaryTableController交互。
(1)TTY和 ptmx编程
TTY是Linux系统(更确切地说是UNIX)中终端设备的统称,该词源于TeleTYpewriter(电传打字机),是一个通过串行线用打印机键盘通过阅读和发送信息的设备。不过随着计算机技术的发展,这类设备早就被键盘和显示器替代了。
(2)PPP 和 pppd
PPP(Point-to-Point Protocol,点对点协议)是为在同等单元之间传输数据包这样的简单链路设计的链路层协议。这种链路提供全双工操作,并按照顺序传递数据包。设计目的主要是通过拨号或专线方式建立点对点连接发送数据,使其成为各种主机、网桥和路由器之间简单连接的一种共通的解决方案。
BandwidthControlCmd 命令
bwcc用于Android系统中的带宽控制。目前4.2系统中的带宽控制可针对设备、某个应用。另外还可以设置预警值,当带宽使用超过该值时会收到相应的通知(见2.2.2节中的NETLINK_NFQLOG)。
和流量控制类似,带宽控制的实现也是利用iptables。它利用了iptables中扩展模块libxt_quota2的功能,属于iptables的高级用法。这些内容对于非从事网络管理专业工作的人来说难度相当大。考虑到这个因素,本节将把bwcc当做一个黑盒,仅介绍其提供的各项功能。想深入研究的读者可在此基础上结合参考资料进一步了解。
IdletimerControlCmd命令
icc利用了iptables另一个扩展模块libxt_idletimer,其对应的iptables命令格式如下。
NAT分为两种,分别是源NAT(SNAT)和目的NAT(DNAT),顾名思义,SNAT就是改变转发数据包的源地址,DNAT就是改变转发数据包的目的地址。Linux系统上的NAT操作是通过iptables的nat表来完成,该表有三条默认Chain,它们分别如下。
TetherCmd和SoftapCmd命令都和手机中一项名为绑定(Tether)的功能相关。简单来说,绑定功能即把手机当成Modem用。智能手机一般都有多种连接网络的方式,例如使用Wi-Fi或
3G。在某些环境下如高铁列车上,差旅人士只要把手机接到笔记本上,然后开启3G和Tether,笔记本就可以利用手机上网了(在智能机普及前,类似的场景中就需要使用3G上网卡)。
ResolverCmd和Android系统中DNS的实现有关,用于给不同NIC设备配置不同的DNS。其主要支持四个选项。
根据前文所述,NetworkManagementService(以后简称NMService)将通过“netd”socket和Netd交互