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