2.3.2 CommandListener构造函数和测试工具ndc

本节将介绍CL的构造函数以及Netd的测试工具ndc。

1.CL构造函数

在前文的2.2.3节中已经介绍了CL构造函数的前半部分,下面接着介绍CL构造函数的后半部分,代码如下所示。

[—>CommandListener::CommandListener构造函数]

  1. CommandListener::CommandListener() :
  2. FrameworkListener("netd", true) {
  3. ......// 创建命令和命令控制对象
  4.  
  5. // 初始化iptables中的各个Table及相应Chain和Rules
  6. // createChildChains第一个参数用于指明针对IPv4还是IPv6
  7. createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
  8. createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
  9. createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
  10. createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
  11. createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
  12. createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
  13. createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
  14.  
  15. // 4.2以后,Netd允许OEM厂商可自定义一些规则
  16. // 这些规则在/system/bin/oem-iptables-init.sh文件中保存
  17. setupOemIptablesHook();
  18. // 初始化iptables中的一些chain,以及初始化路由表
  19. sFirewallCtrl->setupIptablesHooks();
  20. sNatCtrl->setupIptablesHooks();
  21. sBandwidthCtrl->setupIptablesHooks();
  22. sIdletimerCtrl->setupIptablesHooks();
  23. // 初始时,Netd将禁止带宽控制功能
  24. sBandwidthCtrl->enableBandwidthControl(false);

由上述代码可知,CL构造函数的后半部分工作主要是利用iptables等工具创建较多的Chain和Rule,以及对某些命令控制对象进行初始化。

本节将重点关注iptables执行后的效果。图2-13所示为CL构造后,iptable中filter表内所创建的Chain和Rule。

图2-13中列出的是filter表中部分Chain的截图,其中,target是目标名,prot是protocol之意,opt是选项,source和destination分别表示数据包的源和目标地址。

·bw_INPUT、bw_OUTPUT和bw_FORWARD Chain用于带宽(Bandwidth)控制。

·fw_INPUT、fw_OUTPUT和fw_FORWARD用于防火墙(Firewall)控制。

·natctrl_FORWARD用于网络地址转换(NAT)控制。

·oem_fwd、oem_out用于OEM厂商自定义的控制。

2.3.2 CommandListener构造函数和测试工具ndc - 图1

图2-13 CL创建后filter表的内容

2.ndc测试工具

ndc是Android为Netd提供的一个测试工具。其主要功能有:

·监视Netd中发生的事情。

·支持通过命令行发送命令给Netd去执行。

相信读者很轻松就能想到ndc的实现原理,其实它就是连接上位于netd进程中的"netd"监听socket,然后从Netd接收信息或发送命令给Netd。

图2-14为使用ndc monitor选项监控Galaxy Note 2打开Wi-Fi功能时得到的输出。

2.3.2 CommandListener构造函数和测试工具ndc - 图2

图2-14 ndc monitor执行结果

利用ndc来监视Netd的工作状况是一个简单高效的方法。另外,还可利用ndc来测试CommandListener中所支持的各种命令。这对于网络相关模块的HAL层开发者来说无疑是一个很大的帮助。为了方便读者理解,本节下文也将利用ndc来展示命令执行的结果。

在正式介绍CL中的命令对象之前,先介绍这些命令对象处理的通用流程。

如图2-4所示,命令对象的真正控制函数是runCommand,而绝大部分命令的runCommand函数都有类似如下的代码结构(此处以InterfaceCmd为例)。

[—>CommandListener.cpp::InterfaceCmd:runCommand]

  1. int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
  2. int argc, char **argv) {
  3. if (argc < 2) {// 先做参数检查
  4. cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
  5. return 0;
  6. }
  7. // 然后分别处理自己支持的各种命令选项
  8. if (!strcmp(argv[1], "list")) {
  9. ......// 处理"list"选项
  10. } else if (!strcmp(argv[1], "readrxcounter")) {
  11. ......// 处理"readrxcounter"选项
  12. }
  13. ......// 处理其他选项
  14. }

由上述InteraceCmd的处理函数可知,runCommand的处理流程如下。

1)首先参数检查,一般是检查参数个数是否正确。

2)然后根据不同的选项进行对应的处理。

提示 接下来分析CL中各个命令,由于其中涉及较多的知识,因此单独增加“背景知识介绍”小节以帮助读者更好地理解它们。