美文网首页
Android之网络-NetworkManagementServ

Android之网络-NetworkManagementServ

作者: 锄禾豆 | 来源:发表于2022-01-21 12:49 被阅读0次

简介

NetworkManagementService主要设置防火墙(Firewall)、带宽控制、网络设备绑定(Tether)等业务,实现方式主要通过binder调用netd。

代码路径

frameworks/base/services/core/java/com/android/server/NetworkManagementService.java
system/netd
注:
10.0

adb查询

adb shell dumpsys network_management

一、network_management服务启动
1.SystemServer::SystemServer:run --> startOtherServices

    private void startOtherServices() {
        ···
        NetworkManagementService networkManagement = null;
        ···
        traceBeginAndSlog("StartNetworkManagementService");
        try {
            networkManagement = NetworkManagementService.create(context);
            ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);//注册服务到ServiceManager,供其他进程使用
        } catch (Throwable e) {
            reportWtf("starting NetworkManagement Service", e);
        }
        traceEnd();
        ···
        final NetworkManagementService networkManagementF = networkManagement;
        ···
        mActivityManagerService.systemReady(() -> {
            ···
            try {
                if (networkManagementF != null) {
                    networkManagementF.systemReady();
                }
            } catch (Throwable e) {
                reportWtf("making Network Managment Service ready", e);
            }
            ···
        }
    }

2.具体分析NetworkManagementService
1)初始化NetworkManagementService对象

    static NetworkManagementService create(Context context, SystemServices services)
            throws InterruptedException {
        final NetworkManagementService service =
                new NetworkManagementService(context, services);
        service.connectNativeNetdService();
        return service;
    }

    private void connectNativeNetdService() {
        mNetdService = mServices.getNetd();//初始化nNetdService服务
        try {
            mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
        } catch (RemoteException | ServiceSpecificException e) {
            Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e);
        }
    }
    
    static class SystemServices {
        ···
        public INetd getNetd() {
            return NetdService.get();
        }
    }

NetworkManagementService初始化的过程主要初始化mNetService.
重点介绍NetService.get()

NetService

    private static final long BASE_TIMEOUT_MS = 100;
    private static final long MAX_TIMEOUT_MS = 1000;

    public static INetd get() {
        return get(-1);
    }

    public static INetd get(long maxTimeoutMs) {
        if (maxTimeoutMs == 0) return getInstance();

        final long stop = (maxTimeoutMs > 0)
                ? SystemClock.elapsedRealtime() + maxTimeoutMs
                : Long.MAX_VALUE;

        long timeoutMs = 0;
        while (true) {
            final INetd netdInstance = getInstance();//获取INet对象
            if (netdInstance != null) {
                return netdInstance;
            }

            final long remaining = stop - SystemClock.elapsedRealtime();
            if (remaining <= 0) break;

            // No netdInstance was received; sleep and retry.
            timeoutMs = Math.min(timeoutMs + BASE_TIMEOUT_MS, MAX_TIMEOUT_MS);
            timeoutMs = Math.min(timeoutMs, remaining);//最大的超时就是1秒种
            try {
                Thread.sleep(timeoutMs);
            } catch (InterruptedException e) {}
        }
        return null;
    }
    
    public static INetd getInstance() {
        // NOTE: ServiceManager does no caching for the netd service,
        // because netd is not one of the defined common services.
        final INetd netdInstance = INetd.Stub.asInterface(
                ServiceManager.getService(Context.NETD_SERVICE));
        if (netdInstance == null) {
            Log.w(TAG, "WARNING: returning null INetd instance.");
        }
        return netdInstance;
    }

NetService获取了netd服务
3.案例分析限制app上网的接口调用:setFirewallUidRule
1)NetworkManagementService.setFirewallUidRule

    public void setFirewallUidRule(int chain, int uid, int rule) {
        //这里要求只有uid = 1000(Process.SYSTEM_UID)的才有设置权限
        enforceSystemUid();
        synchronized(this.mQuotaLock) {
            this.setFirewallUidRuleLocked(chain, uid, rule);
        }
    }
    
    private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
        if (updateFirewallUidRuleLocked(chain, uid, rule)) {//更新规则
            final int ruleType = getFirewallRuleType(chain, rule);
            try {
                //调用mNetService控制网络
                mNetdService.firewallSetUidRule(chain, uid, ruleType);
            } catch (RemoteException | ServiceSpecificException e) {
                throw new IllegalStateException(e);
            }
        }
    }

NetworkManagementService最后通过调用mNetdService来实现网络控制。也就是由
netd服务处理
2)netd服务进行firewallSetUidRule处理

NetdNativeService.cpp
binder::Status NetdNativeService::firewallSetUidRule(int32_t childChain, int32_t uid,
                                                     int32_t firewallRule) {
    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    auto chain = static_cast<ChildChain>(childChain);
    auto rule = static_cast<FirewallRule>(firewallRule);

    int res = gCtls->firewallCtrl.setUidRule(chain, uid, rule);
    return statusFromErrcode(res);
}
1.gCtrls为Controllers对象的指针
2.gCtrls->firewallCtrol就是FirewallController对象


FirewallController.cpp
int FirewallController::setUidRule(ChildChain chain, int uid, FirewallRule rule) {
    const char* op;
    const char* target;
    FirewallType firewallType = getFirewallType(chain);
    if (firewallType == WHITELIST) {
        target = "RETURN";
        // When adding, insert RETURN rules at the front, before the catch-all DROP at the end.
        op = (rule == ALLOW)? "-I" : "-D";
    } else { // BLACKLIST mode
        target = "DROP";
        // When adding, append DROP rules at the end, after the RETURN rule that matches TCP RSTs.
        op = (rule == DENY)? "-A" : "-D";
    }

    std::vector<std::string> chainNames;
    switch(chain) {
        case DOZABLE:
            chainNames = { LOCAL_DOZABLE };
            break;
        case STANDBY:
            chainNames = { LOCAL_STANDBY };
            break;
        case POWERSAVE:
            chainNames = { LOCAL_POWERSAVE };
            break;
        case NONE:
            chainNames = { LOCAL_INPUT, LOCAL_OUTPUT };
            break;
        default:
            ALOGW("Unknown child chain: %d", chain);
            return -EINVAL;
    }
    if (mUseBpfOwnerMatch != BpfLevel::NONE) {
        return gCtls->trafficCtrl.changeUidOwnerRule(chain, uid, rule, firewallType);
    }

    std::string command = "*filter\n";
    for (const std::string& chainName : chainNames) {
        StringAppendF(&command, "%s %s -m owner --uid-owner %d -j %s\n",
                      op, chainName.c_str(), uid, target);
    }
    StringAppendF(&command, "COMMIT\n");

    //调用iptables设置网络
    return (execIptablesRestore(V4V6, command) == 0) ? 0 : -EREMOTEIO;
}

netd设置网络的最终工具就是iptables。这里,我们也可以到/system/bin/iptables单独设置规则达到我们的期望。

二、参考学习

https://www.jianshu.com/p/5940ba4debf3
https://blog.csdn.net/GooHong/article/details/7937148
https://www.kancloud.cn/alex_wsc/android-wifi-nfc-gps/414019
https://python.iitter.com/other/71825.html

相关文章

网友评论

      本文标题:Android之网络-NetworkManagementServ

      本文链接:https://www.haomeiwen.com/subject/vuxshrtx.html