简介
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
网友评论