【Android】(二) Netd初始化

初始化操作

//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 中定义的方法,从而与硬件进行交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值