初始化操作
//system/netd/server/main.cpp
Stopwatch s;
gLog.info("netd 1.0 starting");
android::net::process::removePidFile(PID_FILE_PATH);
gLog.info("Pid file removed");
android::net::process::blockSigPipe();
gLog.info("SIGPIPE is blocked");
// Before we do anything that could fork, mark CLOEXEC the UNIX sockets that we get from init.
// FrameworkListener does this on initialization as well, but we only initialize these
// components after having initialized other subsystems that can fork.
for (const auto& sock :
{DNSPROXYLISTENER_SOCKET_NAME, FwmarkServer::SOCKET_NAME, MDnsSdListener::SOCKET_NAME}) {
setCloseOnExec(sock);
gLog.info("setCloseOnExec(%s)", sock);
}
// Make sure BPF programs are loaded before doing anything
android::bpf::waitForProgsLoaded();
gLog.info("BPF programs are loaded");
以上代码删除进程标识文件、阻止 SIGPIPE 信号、设置套接字的 CLOEXEC 属性以及等待 BPF 程序加载。这些操作旨在为程序的正常运行和安全性做准备。
构造 Controllers
NetworkController
:网络控制器,用于管理网络配置和连接。TetherController
:热点共享(Tethering)控制器,用于管理设备的网络共享功能。PppController
:PPP(Point-to-Point Protocol)控制器,用于管理通过 PPP 协议建立的网络连接。BandwidthController
:带宽控制器,用于管理网络带宽分配和流量限制。IdletimerController
:空闲定时器控制器,用于管理设备的空闲状态和定时功能。FirewallController
:防火墙控制器,用于管理网络防火墙规则。ClatdController
:CLAT(IPv6-to-IPv4 Translation)控制器,用于管理IPv6到IPv4的转换。StrictController
:Strict模式控制器,用于强制执行网络策略和规则。EventReporter
:事件报告控制器,用于记录和报告系统事件。IptablesRestoreController
:iptables恢复控制器,用于管理iptables规则的恢复和配置。WakeupController
:唤醒控制器,用于管理设备的唤醒事件。XfrmController
:XFRM(IPsec框架)控制器,用于管理IPsec安全传输。TrafficController
:流量控制器,用于管理流量控制和管理。TcpSocketMonitor
:TCP套接字监视器,用于监视和管理TCP套接字。
//system/netd/server/main.cpp
gCtls = new android::net::Controllers();
netd 进程的 main 函数中创建了 Controllers,并将其初始化。具体的构造及初始化见下文。
//system/netd/server/Controllers.cpp
Controllers::Controllers()
: clatdCtrl(&netCtrl),
wakeupCtrl(
[this](const WakeupController::ReportArgs& args) {
const auto listener = eventReporter.getNetdEventListener();
if (listener == nullptr) {
gLog.error("getNetdEventListener() returned nullptr. dropping wakeup event");
return;
}
String16 prefix = String16(args.prefix.c_str());
String16 srcIp = String16(args.srcIp.c_str());
String16 dstIp = String16(args.dstIp.c_str());
listener->onWakeupEvent(prefix, args.uid, args.ethertype, args.ipNextHeader,
args.dstHw, srcIp, dstIp, args.srcPort, args.dstPort,
args.timestampNs);
},
&iptablesRestoreCtrl) {
InterfaceController::initializeAll();
}
这是 Controllers 的构造函数。在构造函数之前,还进行的其他成员的初始化。
Controllers Init
//system/netd/server/main.cpp
gCtls->init();
//system/netd/server/Controller.cpp
void Controllers::init() {
initIptablesRules();
Stopwatch s;
clatdCtrl.init();
gLog.info("Initializing ClatdController: %" PRId64 "us", s.getTimeAndResetUs());
netdutils::Status tcStatus = trafficCtrl.start();
if (!isOk(tcStatus)) {
gLog.error("Failed to start trafficcontroller: (%s)", toString(tcStatus).c_str());
gLog.error("CRITICAL: sleeping 60 seconds, netd exiting with failure, crash loop likely!");
// The expected reason we get here is a major kernel or other code bug, as such
// the probability that things will succeed on restart of netd is pretty small.
// So, let's wait a minute to at least try to limit the log spam a little bit.
sleep(60);
exit(1);
}
gLog.info("Initializing traffic control: %" PRId64 "us", s.getTimeAndResetUs());
bandwidthCtrl.enableBandwidthControl();
gLog.info("Enabling bandwidth control: %" PRId64 "us", s.getTimeAndResetUs());
if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
gLog.error("Failed to initialize RouteController (%s)", strerror(-ret));
}
gLog.info("Initializing RouteController: %" PRId64 "us", s.getTimeAndResetUs());
netdutils::Status xStatus = XfrmController::Init();
if (!isOk(xStatus)) {
gLog.error("Failed to initialize XfrmController (%s)", netdutils::toString(xStatus).c_str());
};
gLog.info("Initializing XfrmController: %" PRId64 "us", s.getTimeAndResetUs());
}
初始化 iptable rules
//system/netd/server/Controller.cpp
void Controllers::initIptablesRules() {
Stopwatch s;
initChildChains();
gLog.info("Creating child chains: %" PRId64 "us", s.getTimeAndResetUs());
// Let each module setup their child chains
setupOemIptablesHook();
gLog.info("Setting up OEM hooks: %" PRId64 "us", s.getTimeAndResetUs());
/* When enabled, DROPs all packets except those matching rules. */
firewallCtrl.setupIptablesHooks();
gLog.info("Setting up FirewallController hooks: %" PRId64 "us", s.getTimeAndResetUs());
/* Does DROPs in FORWARD by default */
tetherCtrl.setupIptablesHooks();
gLog.info("Setting up TetherController hooks: %" PRId64 "us", s.getTimeAndResetUs());
/*
* Does REJECT in INPUT, OUTPUT. Does counting also.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
bandwidthCtrl.setupIptablesHooks();
gLog.info("Setting up BandwidthController hooks: %" PRId64 "us", s.getTimeAndResetUs());
/*
* Counts in nat: PREROUTING, POSTROUTING.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
idletimerCtrl.setupIptablesHooks();
gLog.info("Setting up IdletimerController hooks: %" PRId64 "us", s.getTimeAndResetUs());
/*
* Add rules for detecting IPv6/IPv4 TCP/UDP connections with TLS/DTLS header
*/
strictCtrl.setupIptablesHooks();
gLog.info("Setting up StrictController hooks: %" PRId64 "us", s.getTimeAndResetUs());
}
initIptablesRules 中首先创建了一系列子链,源码如下:
http://aospxref.com/android-12.0.0_r3/xref/system/netd/server/Controllers.cpp#initChildChains
接着 Controllers::initIptablesRules 中初始化一系列不同控制器的 iptables 钩子,每个控制器都有其专用的 iptables 规则,用于实现特定的网络数据包处理和过滤功能。
enable BandwidthController
//system/netd/server/BandwidthController
int BandwidthController::enableBandwidthControl() {
/* Let's pretend we started from scratch ... */
mSharedQuotaIfaces.clear();
mQuotaIfaces.clear();
mGlobalAlertBytes = 0;
mSharedQuotaBytes = mSharedAlertBytes = 0;
flushCleanTables(false);
std::string commands = Join(getBasicAccountingCommands(), '\n');
return iptablesRestoreFunction(V4V6, commands, nullptr);
}
这段代码的主要功能是启用带宽控制。为了做到这一点,它首先对一些成员变量进行重置,然后通过执行iptables命令来实现必要的配置,清理一些 rule 并添加一些 rule。
init RouteController
//system/netd/server/RouteController.cpp
int RouteController::Init(unsigned localNetId) {
if (int ret = flushRules()) {
return ret;
}
if (int ret = addLegacyRouteRules()) {
return ret;
}
if (int ret = addLocalNetworkRules(localNetId)) {
return ret;
}
if (int ret = addUnreachableRule()) {
return ret;
}
// Don't complain if we can't add the dummy network, since not all devices support it.
configureDummyNetwork();
updateTableNamesFile();
return 0;
}
这段代码初始化了一个路由控制器,其中包括清空现有规则、添加传统路由规则、添加本地网络规则、添加不可达规则、配置虚拟网络以及更新表名文件等操作。
start other modules
start NetlinkManager
//system/netd/server/main.cpp
NetlinkManager *nm = NetlinkManager::Instance();
if (nm == nullptr) {
ALOGE("Unable to create NetlinkManager");
exit(1);
};
gLog.info("NetlinkManager instanced");
//...
if (nm->start()) {
ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));
exit(1);
}
获取到 NetlinkManager 单例,启动NetlinkManager。
//system/netd/server/NetlinkManager.cpp
int NetlinkManager::start() {
if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,
0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII, false)) == nullptr) {
return -1;
}
if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE,
RTMGRP_LINK |
RTMGRP_IPV4_IFADDR |
RTMGRP_IPV6_IFADDR |
RTMGRP_IPV6_ROUTE |
(1 << (RTNLGRP_ND_USEROPT - 1)),
NetlinkListener::NETLINK_FORMAT_BINARY, false)) == nullptr) {
return -1;
}
if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG,
NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY, false)) == nullptr) {
ALOGW("Unable to open qlog quota socket, check if xt_quota2 can send via UeventHandler");
// TODO: return -1 once the emulator gets a new kernel.
}
if ((mStrictHandler = setupSocket(&mStrictSock, NETLINK_NETFILTER,
0, NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST, true)) == nullptr) {
ALOGE("Unable to open strict socket");
// TODO: return -1 once the emulator gets a new kernel.
}
return 0;
}
监听 NETLINK_KOBJECT_UEVENT 类型的事件
监听 NETLINK_ROUTE 类型的事件,监听的事件包括 :
RTMGRP_LINK(链路状态变化)
RTMGRP_IPV4_IFADDR(IPv4 接口地址变化)
RTMGRP_IPV6_IFADDR(IPv6 接口地址变化)
RTMGRP_IPV6_ROUTE(IPv6 路由变化) 等
监听 NETLINK_NFLOG 类型的事件:
监听的是 NFLOG_QUOTA_GROUP 组的事件
监听 NETLINK_NETFILTER 类型的事件
创建相应的 Socket,以及相应时间的 Handler。setupSocket 源码如下:
http://aospxref.com/android-12.0.0_r3/xref/system/netd/server/NetlinkManager.cpp#setupSocket
init NFLogListener
//system/netd/server/main.cpp
std::unique_ptr<NFLogListener> logListener;
{
auto result = makeNFLogListener();
if (!isOk(result)) {
ALOGE("Unable to create NFLogListener: %s", toString(result).c_str());
exit(1);
}
logListener = std::move(result.value());
auto status = gCtls->wakeupCtrl.init(logListener.get());
if (!isOk(result)) {
gLog.error("Unable to init WakeupController: %s", toString(result).c_str());
// We can still continue without wakeup packet logging.
}
}
构造 NFLogListener,并在 WakeupController 内部构造一个 msgHandler。用 NFLogListener 订阅特定的网络日志组,并在收到网络日志消息时,用 msgHandler 解析消息中的属性,并将解析后的参数报告给 NetdEventListener 进行处理。详细代码见:
http://aospxref.com/android-12.0.0_r3/xref/system/netd/server/WakeupController.cpp#init
init Dns Resolver
//system/netd/server/main.cpp
// Set local DNS mode, to prevent bionic from proxying
// back to this service, recursively.
// TODO: Check if we could remove it since resolver cache no loger
// checks this environment variable after aosp/838050.
setenv("ANDROID_DNS_MODE", "local", 1);
// Note that only call initDnsResolver after gCtls initializing.
if (!initDnsResolver()) {
ALOGE("Unable to init resolver");
exit(1);
}
见Dns-Resolver
start MDnsSdListener
//system/netd/server/main.cpp
MDnsSdListener mdnsl;
if (mdnsl.startListener()) {
ALOGE("Unable to start MDnsSdListener (%s)", strerror(errno));
exit(1);
}
MDnsSdListener 继承自 FrameworkListener,FrameworkListener 继承自 SocketListener,所以跟DnsResolverProxy 类似,创建一个 Socket_Name = “mdnsd” 的本地套接字,监听来自上层的消息,收到消息以后根据 onDataAvailable 来进行相应的处理。
start FwmarkServer
//system/netd/server/main.cpp
FwmarkServer fwmarkServer(&gCtls->netCtrl, &gCtls->eventReporter, &gCtls->trafficCtrl);
if (fwmarkServer.startListener()) {
ALOGE("Unable to start FwmarkServer (%s)", strerror(errno));
exit(1);
}
MDnsSdListener 继承自 SocketListener,所以跟DnsResolverProxy 类似,创建一个 Socket_Name = “fwmarkd” 的本地套接字,监听来自上层的消息,收到消息以后根据 onDataAvailable 来进行相应的处理。
start NetdService
//system/netd/server/main.cpp
if ((ret = NetdNativeService::start()) != android::OK) {
ALOGE("Unable to start NetdNativeService: %d", ret);
exit(1);
}
//system/netd/server/NetdNativeService.cpp
status_t NetdNativeService::start() {
IPCThreadState::self()->disableBackgroundScheduling(true);
const status_t ret = BinderService<NetdNativeService>::publish();
if (ret != android::OK) {
return ret;
}
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
return android::OK;
}
禁止后台调度以确保在进行关键操作时不被中断,接着发布其 Binder 服务以供其他模块调用。启动 Binder 线程池,接受来自 Binder 服务调用者的请求。
start NetdHwService
//system/netd/server/main.cpp
sp<NetdHwService> mHwSvc(new NetdHwService());
if ((ret = mHwSvc->start()) != android::OK) {
ALOGE("Unable to start NetdHwService: %d", ret);
exit(1);
}
//system/netd/server/NetdHwService.cpp
status_t NetdHwService::start() {
IPCThreadState::self()->disableBackgroundScheduling(true);
// Usage of this HAL is anticipated to be thin; one thread should suffice.
configureRpcThreadpool(1, false /* callerWillNotJoin */);
// Register hardware service with ServiceManager.
return INetd::registerAsService();
}
启动 NetdHwService,并将其配置为一个硬件服务。通过注册到 ServiceManager,其他组件可以通过 Binder 机制访问和调用 NetdHwService 中定义的方法,从而与硬件进行交互。