• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server;
18 
19 import static android.net.dhcp.IDhcpServer.STATUS_INVALID_ARGUMENT;
20 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
21 import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
22 
23 import static com.android.server.util.PermissionUtil.checkDumpPermission;
24 import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission;
25 
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.app.Service;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.net.ConnectivityManager;
32 import android.net.IIpMemoryStore;
33 import android.net.IIpMemoryStoreCallbacks;
34 import android.net.INetd;
35 import android.net.INetworkMonitor;
36 import android.net.INetworkMonitorCallbacks;
37 import android.net.INetworkStackConnector;
38 import android.net.LinkProperties;
39 import android.net.Network;
40 import android.net.NetworkCapabilities;
41 import android.net.PrivateDnsConfigParcel;
42 import android.net.dhcp.DhcpServer;
43 import android.net.dhcp.DhcpServingParams;
44 import android.net.dhcp.DhcpServingParamsParcel;
45 import android.net.dhcp.IDhcpServerCallbacks;
46 import android.net.ip.IIpClientCallbacks;
47 import android.net.ip.IpClient;
48 import android.net.shared.PrivateDnsConfig;
49 import android.net.util.SharedLog;
50 import android.os.IBinder;
51 import android.os.RemoteException;
52 import android.util.ArraySet;
53 
54 import com.android.internal.annotations.GuardedBy;
55 import com.android.internal.util.IndentingPrintWriter;
56 import com.android.server.connectivity.NetworkMonitor;
57 import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService;
58 
59 import java.io.FileDescriptor;
60 import java.io.PrintWriter;
61 import java.lang.ref.WeakReference;
62 import java.util.ArrayDeque;
63 import java.util.ArrayList;
64 import java.util.HashSet;
65 import java.util.Iterator;
66 
67 /**
68  * Android service used to start the network stack when bound to via an intent.
69  *
70  * <p>The service returns a binder for the system server to communicate with the network stack.
71  */
72 public class NetworkStackService extends Service {
73     private static final String TAG = NetworkStackService.class.getSimpleName();
74     private static NetworkStackConnector sConnector;
75 
76     /**
77      * Create a binder connector for the system server to communicate with the network stack.
78      *
79      * <p>On platforms where the network stack runs in the system server process, this method may
80      * be called directly instead of obtaining the connector by binding to the service.
81      */
makeConnector(Context context)82     public static synchronized IBinder makeConnector(Context context) {
83         if (sConnector == null) {
84             sConnector = new NetworkStackConnector(context);
85         }
86         return sConnector;
87     }
88 
89     @NonNull
90     @Override
onBind(Intent intent)91     public IBinder onBind(Intent intent) {
92         return makeConnector(this);
93     }
94 
95     /**
96      * An interface for internal clients of the network stack service that can return
97      * or create inline instances of the service it manages.
98      */
99     public interface NetworkStackServiceManager {
100         /**
101          * Get an instance of the IpMemoryStoreService.
102          */
getIpMemoryStoreService()103         IIpMemoryStore getIpMemoryStoreService();
104     }
105 
106     private static class NetworkStackConnector extends INetworkStackConnector.Stub
107             implements NetworkStackServiceManager {
108         private static final int NUM_VALIDATION_LOG_LINES = 20;
109         private final Context mContext;
110         private final INetd mNetd;
111         private final NetworkObserverRegistry mObserverRegistry;
112         private final ConnectivityManager mCm;
113         @GuardedBy("mIpClients")
114         private final ArrayList<WeakReference<IpClient>> mIpClients = new ArrayList<>();
115         private final IpMemoryStoreService mIpMemoryStoreService;
116 
117         private static final int MAX_VALIDATION_LOGS = 10;
118         @GuardedBy("mValidationLogs")
119         private final ArrayDeque<SharedLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS);
120 
121         private static final String DUMPSYS_ARG_VERSION = "version";
122 
123         /** Version of the framework AIDL interfaces observed. Should hold only one value. */
124         @GuardedBy("mFrameworkAidlVersions")
125         private final ArraySet<Integer> mFrameworkAidlVersions = new ArraySet<>(1);
126         private final int mNetdAidlVersion;
127 
addValidationLogs(Network network, String name)128         private SharedLog addValidationLogs(Network network, String name) {
129             final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name);
130             synchronized (mValidationLogs) {
131                 while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
132                     mValidationLogs.removeLast();
133                 }
134                 mValidationLogs.addFirst(log);
135             }
136             return log;
137         }
138 
NetworkStackConnector(Context context)139         NetworkStackConnector(Context context) {
140             mContext = context;
141             mNetd = INetd.Stub.asInterface(
142                     (IBinder) context.getSystemService(Context.NETD_SERVICE));
143             mObserverRegistry = new NetworkObserverRegistry();
144             mCm = context.getSystemService(ConnectivityManager.class);
145             mIpMemoryStoreService = new IpMemoryStoreService(context);
146 
147             int netdVersion;
148             try {
149                 netdVersion = mNetd.getInterfaceVersion();
150             } catch (RemoteException e) {
151                 mLog.e("Error obtaining INetd version", e);
152                 netdVersion = -1;
153             }
154             mNetdAidlVersion = netdVersion;
155 
156             try {
157                 mObserverRegistry.register(mNetd);
158             } catch (RemoteException e) {
159                 mLog.e("Error registering observer on Netd", e);
160             }
161         }
162 
updateSystemAidlVersion(final int version)163         private void updateSystemAidlVersion(final int version) {
164             synchronized (mFrameworkAidlVersions) {
165                 mFrameworkAidlVersions.add(version);
166             }
167         }
168 
169         @NonNull
170         private final SharedLog mLog = new SharedLog(TAG);
171 
172         @Override
makeDhcpServer(@onNull String ifName, @NonNull DhcpServingParamsParcel params, @NonNull IDhcpServerCallbacks cb)173         public void makeDhcpServer(@NonNull String ifName, @NonNull DhcpServingParamsParcel params,
174                 @NonNull IDhcpServerCallbacks cb) throws RemoteException {
175             checkNetworkStackCallingPermission();
176             updateSystemAidlVersion(cb.getInterfaceVersion());
177             final DhcpServer server;
178             try {
179                 server = new DhcpServer(
180                         ifName,
181                         DhcpServingParams.fromParcelableObject(params),
182                         mLog.forSubComponent(ifName + ".DHCP"));
183             } catch (DhcpServingParams.InvalidParameterException e) {
184                 mLog.e("Invalid DhcpServingParams", e);
185                 cb.onDhcpServerCreated(STATUS_INVALID_ARGUMENT, null);
186                 return;
187             } catch (Exception e) {
188                 mLog.e("Unknown error starting DhcpServer", e);
189                 cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
190                 return;
191             }
192             cb.onDhcpServerCreated(STATUS_SUCCESS, server);
193         }
194 
195         @Override
makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)196         public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)
197                 throws RemoteException {
198             checkNetworkStackCallingPermission();
199             updateSystemAidlVersion(cb.getInterfaceVersion());
200             final SharedLog log = addValidationLogs(network, name);
201             final NetworkMonitor nm = new NetworkMonitor(mContext, cb, network, log);
202             cb.onNetworkMonitorCreated(new NetworkMonitorImpl(nm));
203         }
204 
205         @Override
makeIpClient(String ifName, IIpClientCallbacks cb)206         public void makeIpClient(String ifName, IIpClientCallbacks cb) throws RemoteException {
207             checkNetworkStackCallingPermission();
208             updateSystemAidlVersion(cb.getInterfaceVersion());
209             final IpClient ipClient = new IpClient(mContext, ifName, cb, mObserverRegistry, this);
210 
211             synchronized (mIpClients) {
212                 final Iterator<WeakReference<IpClient>> it = mIpClients.iterator();
213                 while (it.hasNext()) {
214                     final IpClient ipc = it.next().get();
215                     if (ipc == null) {
216                         it.remove();
217                     }
218                 }
219                 mIpClients.add(new WeakReference<>(ipClient));
220             }
221 
222             cb.onIpClientCreated(ipClient.makeConnector());
223         }
224 
225         @Override
getIpMemoryStoreService()226         public IIpMemoryStore getIpMemoryStoreService() {
227             return mIpMemoryStoreService;
228         }
229 
230         @Override
fetchIpMemoryStore(@onNull final IIpMemoryStoreCallbacks cb)231         public void fetchIpMemoryStore(@NonNull final IIpMemoryStoreCallbacks cb)
232                 throws RemoteException {
233             checkNetworkStackCallingPermission();
234             updateSystemAidlVersion(cb.getInterfaceVersion());
235             cb.onIpMemoryStoreFetched(mIpMemoryStoreService);
236         }
237 
238         @Override
dump(@onNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args)239         protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
240                 @Nullable String[] args) {
241             checkDumpPermission();
242 
243             final IndentingPrintWriter pw = new IndentingPrintWriter(fout, "  ");
244             pw.println("NetworkStack version:");
245             dumpVersion(pw);
246             pw.println();
247 
248             if (args != null && args.length >= 1 && DUMPSYS_ARG_VERSION.equals(args[0])) {
249                 return;
250             }
251 
252             pw.println("NetworkStack logs:");
253             mLog.dump(fd, pw, args);
254 
255             // Dump full IpClient logs for non-GCed clients
256             pw.println();
257             pw.println("Recently active IpClient logs:");
258             final ArrayList<IpClient> ipClients = new ArrayList<>();
259             final HashSet<String> dumpedIpClientIfaces = new HashSet<>();
260             synchronized (mIpClients) {
261                 for (WeakReference<IpClient> ipcRef : mIpClients) {
262                     final IpClient ipc = ipcRef.get();
263                     if (ipc != null) {
264                         ipClients.add(ipc);
265                     }
266                 }
267             }
268 
269             for (IpClient ipc : ipClients) {
270                 pw.println(ipc.getName());
271                 pw.increaseIndent();
272                 ipc.dump(fd, pw, args);
273                 pw.decreaseIndent();
274                 dumpedIpClientIfaces.add(ipc.getInterfaceName());
275             }
276 
277             // State machine and connectivity metrics logs are kept for GCed IpClients
278             pw.println();
279             pw.println("Other IpClient logs:");
280             IpClient.dumpAllLogs(fout, dumpedIpClientIfaces);
281 
282             pw.println();
283             pw.println("Validation logs (most recent first):");
284             synchronized (mValidationLogs) {
285                 for (SharedLog p : mValidationLogs) {
286                     pw.println(p.getTag());
287                     pw.increaseIndent();
288                     p.dump(fd, pw, args);
289                     pw.decreaseIndent();
290                 }
291             }
292         }
293 
294         /**
295          * Dump version information of the module and detected system version.
296          */
dumpVersion(@onNull PrintWriter fout)297         private void dumpVersion(@NonNull PrintWriter fout) {
298             fout.println("NetworkStackConnector: " + this.VERSION);
299             synchronized (mFrameworkAidlVersions) {
300                 fout.println("SystemServer: " + mFrameworkAidlVersions);
301             }
302             fout.println("Netd: " + mNetdAidlVersion);
303         }
304 
305         @Override
getInterfaceVersion()306         public int getInterfaceVersion() {
307             return this.VERSION;
308         }
309     }
310 
311     private static class NetworkMonitorImpl extends INetworkMonitor.Stub {
312         private final NetworkMonitor mNm;
313 
NetworkMonitorImpl(NetworkMonitor nm)314         NetworkMonitorImpl(NetworkMonitor nm) {
315             mNm = nm;
316         }
317 
318         @Override
start()319         public void start() {
320             checkNetworkStackCallingPermission();
321             mNm.start();
322         }
323 
324         @Override
launchCaptivePortalApp()325         public void launchCaptivePortalApp() {
326             checkNetworkStackCallingPermission();
327             mNm.launchCaptivePortalApp();
328         }
329 
330         @Override
notifyCaptivePortalAppFinished(int response)331         public void notifyCaptivePortalAppFinished(int response) {
332             checkNetworkStackCallingPermission();
333             mNm.notifyCaptivePortalAppFinished(response);
334         }
335 
336         @Override
setAcceptPartialConnectivity()337         public void setAcceptPartialConnectivity() {
338             checkNetworkStackCallingPermission();
339             mNm.setAcceptPartialConnectivity();
340         }
341 
342         @Override
forceReevaluation(int uid)343         public void forceReevaluation(int uid) {
344             checkNetworkStackCallingPermission();
345             mNm.forceReevaluation(uid);
346         }
347 
348         @Override
notifyPrivateDnsChanged(PrivateDnsConfigParcel config)349         public void notifyPrivateDnsChanged(PrivateDnsConfigParcel config) {
350             checkNetworkStackCallingPermission();
351             mNm.notifyPrivateDnsSettingsChanged(PrivateDnsConfig.fromParcel(config));
352         }
353 
354         @Override
notifyDnsResponse(int returnCode)355         public void notifyDnsResponse(int returnCode) {
356             checkNetworkStackCallingPermission();
357             mNm.notifyDnsResponse(returnCode);
358         }
359 
360         @Override
notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc)361         public void notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc) {
362             checkNetworkStackCallingPermission();
363             mNm.notifyNetworkConnected(lp, nc);
364         }
365 
366         @Override
notifyNetworkDisconnected()367         public void notifyNetworkDisconnected() {
368             checkNetworkStackCallingPermission();
369             mNm.notifyNetworkDisconnected();
370         }
371 
372         @Override
notifyLinkPropertiesChanged(LinkProperties lp)373         public void notifyLinkPropertiesChanged(LinkProperties lp) {
374             checkNetworkStackCallingPermission();
375             mNm.notifyLinkPropertiesChanged(lp);
376         }
377 
378         @Override
notifyNetworkCapabilitiesChanged(NetworkCapabilities nc)379         public void notifyNetworkCapabilitiesChanged(NetworkCapabilities nc) {
380             checkNetworkStackCallingPermission();
381             mNm.notifyNetworkCapabilitiesChanged(nc);
382         }
383 
384         @Override
getInterfaceVersion()385         public int getInterfaceVersion() {
386             return this.VERSION;
387         }
388     }
389 }
390