iptables 命令的使用主要是记录一下这样的流程,从java层到C/C++的整个过程
android 是基于linux,因此网络相关重要功能都是通过iptables实现
(1)bandwidth
1.设置流向使用提醒阈值(alert),超过后会发出提醒。
2.设置流量使用上限(quota),超过后自动禁止流量使用,无法访问网。
3.限制某个应用后台使用流量
(2)firewall:防火墙
这部分主要是存在于netd模块中实现的
- netd/
- └── server
- ├── CommandListener.cpp //接收framework曾下发的cmd,初始iptables链
- ├── CommandListener.h
- ├── BandwidthController.cpp //bandwidth
- ├── BandwidthController.h
- ├── FirewallController.cpp //firewall
- ├── FirewallController.h
- ├── IdletimerController.cpp //idletimer
- ├── IdletimerController.h
- ├── NatController.cpp //nat
- ├── NatController.h
- ├── NetlinkHandler.cpp //接收netlink事件
- └── NetlinkHandler.h
CommandListener.cpp文件主要是接受framework层,下发的cmd命令,防火墙的命令主要是由FirewallCmd来接收参数
//参数argv[1]是上下层的标记,argc就是传递参数的数量int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,char **argv) { if (argc < 2) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false); return 0; } if (!strcmp(argv[1], "enable")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall enable <whitelist|blacklist>", false); return 0; } FirewallType firewallType = parseFirewallType(argv[2]); int res = sFirewallCtrl->enableFirewall(firewallType); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "disable")) { int res = sFirewallCtrl->disableFirewall(); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "is_enabled")) { int res = sFirewallCtrl->isFirewallEnabled(); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "set_interface_rule")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false); return 0; } const char* iface = argv[2]; FirewallRule rule = parseRule(argv[3]); int res = sFirewallCtrl->setInterfaceRule(iface, rule); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "set_egress_source_rule")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>", false); return 0; } const char* addr = argv[2]; FirewallRule rule = parseRule(argv[3]); int res = sFirewallCtrl->setEgressSourceRule(addr, rule); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "set_egress_dest_rule")) { if (argc != 5) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>", false); return 0; } const char* addr = argv[2]; int port = atoi(argv[3]); FirewallRule rule = parseRule(argv[4]); int res = 0; res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule); res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "set_uid_rule")) { if (argc != 5) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>", false); return 0; } ChildChain childChain = parseChildChain(argv[2]); if (childChain == INVALID_CHAIN) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid chain name. Valid names are: <dozable|standby|none>", false); return 0; } int uid = atoi(argv[3]); FirewallRule rule = parseRule(argv[4]); int res = sFirewallCtrl->setUidRule(childChain, uid, rule); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "enable_chain")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall enable_chain <dozable|standby>", false); return 0; } ChildChain childChain = parseChildChain(argv[2]); int res = sFirewallCtrl->enableChildChains(childChain, true); return sendGenericOkFail(cli, res); } if (!strcmp(argv[1], "disable_chain")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall disable_chain <dozable|standby>", false); return 0; } ChildChain childChain = parseChildChain(argv[2]); int res = sFirewallCtrl->enableChildChains(childChain, false); return sendGenericOkFail(cli, res); } cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false); return 0;}
在FirewallController.cpp中实现功能
Framework中
NetworkManagementService.java用于管理网络 NativeDaemonConnector创建socket用于与底层进行通信mConnector.execute(
"interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable"));
参数的个数就是argc,并且存放在argv数组中