1 /* 2 * Copyright (C) 2019 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 package android.net; 17 18 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; 19 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; 20 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; 21 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.content.Context; 25 import android.net.dhcp.DhcpServingParamsParcel; 26 import android.net.dhcp.IDhcpServerCallbacks; 27 import android.net.ip.IIpClientCallbacks; 28 import android.os.Binder; 29 import android.os.IBinder; 30 import android.os.Process; 31 import android.os.RemoteException; 32 import android.os.ServiceManager; 33 import android.os.UserHandle; 34 import android.util.Log; 35 import android.util.Slog; 36 37 import com.android.internal.annotations.GuardedBy; 38 import com.android.internal.annotations.VisibleForTesting; 39 40 import java.util.ArrayList; 41 42 /** 43 * Service used to communicate with the network stack, which is running in a separate module. 44 * @hide 45 */ 46 public class NetworkStackClient { 47 private static final String TAG = NetworkStackClient.class.getSimpleName(); 48 49 private static final int NETWORKSTACK_TIMEOUT_MS = 10_000; 50 51 private static NetworkStackClient sInstance; 52 53 @NonNull 54 private final Dependencies mDependencies; 55 56 @NonNull 57 @GuardedBy("mPendingNetStackRequests") 58 private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>(); 59 @Nullable 60 @GuardedBy("mPendingNetStackRequests") 61 private INetworkStackConnector mConnector; 62 63 private volatile boolean mWasSystemServerInitialized = false; 64 65 private interface NetworkStackCallback { onNetworkStackConnected(INetworkStackConnector connector)66 void onNetworkStackConnected(INetworkStackConnector connector); 67 } 68 69 @VisibleForTesting NetworkStackClient(@onNull Dependencies dependencies)70 protected NetworkStackClient(@NonNull Dependencies dependencies) { 71 mDependencies = dependencies; 72 } 73 NetworkStackClient()74 private NetworkStackClient() { 75 this(new DependenciesImpl()); 76 } 77 78 @VisibleForTesting 79 protected interface Dependencies { addToServiceManager(@onNull IBinder service)80 void addToServiceManager(@NonNull IBinder service); checkCallerUid()81 void checkCallerUid(); getConnectivityModuleConnector()82 ConnectivityModuleConnector getConnectivityModuleConnector(); 83 } 84 85 private static class DependenciesImpl implements Dependencies { 86 @Override addToServiceManager(@onNull IBinder service)87 public void addToServiceManager(@NonNull IBinder service) { 88 ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, 89 false /* allowIsolated */, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); 90 } 91 92 @Override checkCallerUid()93 public void checkCallerUid() { 94 final int caller = Binder.getCallingUid(); 95 // This is a client lib so "caller" is the current UID in most cases. The check is done 96 // here in the caller's process just to provide a nicer error message to clients; more 97 // generic checks are also done in NetworkStackService. 98 // See PermissionUtil in NetworkStack for the actual check on the service side - the 99 // checks here should be kept in sync with PermissionUtil. 100 if (caller != Process.SYSTEM_UID 101 && caller != Process.NETWORK_STACK_UID 102 && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) { 103 throw new SecurityException( 104 "Only the system server should try to bind to the network stack."); 105 } 106 } 107 108 @Override getConnectivityModuleConnector()109 public ConnectivityModuleConnector getConnectivityModuleConnector() { 110 return ConnectivityModuleConnector.getInstance(); 111 } 112 } 113 114 /** 115 * Get the NetworkStackClient singleton instance. 116 */ getInstance()117 public static synchronized NetworkStackClient getInstance() { 118 if (sInstance == null) { 119 sInstance = new NetworkStackClient(); 120 } 121 return sInstance; 122 } 123 124 /** 125 * Create a DHCP server according to the specified parameters. 126 * 127 * <p>The server will be returned asynchronously through the provided callbacks. 128 */ makeDhcpServer(final String ifName, final DhcpServingParamsParcel params, final IDhcpServerCallbacks cb)129 public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params, 130 final IDhcpServerCallbacks cb) { 131 requestConnector(connector -> { 132 try { 133 connector.makeDhcpServer(ifName, params, cb); 134 } catch (RemoteException e) { 135 e.rethrowFromSystemServer(); 136 } 137 }); 138 } 139 140 /** 141 * Create an IpClient on the specified interface. 142 * 143 * <p>The IpClient will be returned asynchronously through the provided callbacks. 144 */ makeIpClient(String ifName, IIpClientCallbacks cb)145 public void makeIpClient(String ifName, IIpClientCallbacks cb) { 146 requestConnector(connector -> { 147 try { 148 connector.makeIpClient(ifName, cb); 149 } catch (RemoteException e) { 150 e.rethrowFromSystemServer(); 151 } 152 }); 153 } 154 155 /** 156 * Create a NetworkMonitor. 157 * 158 * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks. 159 */ makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)160 public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) { 161 requestConnector(connector -> { 162 try { 163 connector.makeNetworkMonitor(network, name, cb); 164 } catch (RemoteException e) { 165 e.rethrowFromSystemServer(); 166 } 167 }); 168 } 169 170 /** 171 * Get an instance of the IpMemoryStore. 172 * 173 * <p>The IpMemoryStore will be returned asynchronously through the provided callbacks. 174 */ fetchIpMemoryStore(IIpMemoryStoreCallbacks cb)175 public void fetchIpMemoryStore(IIpMemoryStoreCallbacks cb) { 176 requestConnector(connector -> { 177 try { 178 connector.fetchIpMemoryStore(cb); 179 } catch (RemoteException e) { 180 e.rethrowFromSystemServer(); 181 } 182 }); 183 } 184 185 private class NetworkStackConnection implements 186 ConnectivityModuleConnector.ModuleServiceCallback { 187 @Override onModuleServiceConnected(IBinder service)188 public void onModuleServiceConnected(IBinder service) { 189 logi("Network stack service connected"); 190 registerNetworkStackService(service); 191 } 192 } 193 registerNetworkStackService(@onNull IBinder service)194 private void registerNetworkStackService(@NonNull IBinder service) { 195 final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service); 196 mDependencies.addToServiceManager(service); 197 log("Network stack service registered"); 198 199 final ArrayList<NetworkStackCallback> requests; 200 synchronized (mPendingNetStackRequests) { 201 requests = new ArrayList<>(mPendingNetStackRequests); 202 mPendingNetStackRequests.clear(); 203 mConnector = connector; 204 } 205 206 for (NetworkStackCallback r : requests) { 207 r.onNetworkStackConnected(connector); 208 } 209 } 210 211 /** 212 * Initialize the network stack. Should be called only once on device startup, before any 213 * client attempts to use the network stack. 214 */ init()215 public void init() { 216 log("Network stack init"); 217 mWasSystemServerInitialized = true; 218 } 219 220 /** 221 * Start the network stack. Should be called only once on device startup. 222 * 223 * <p>This method will start the network stack either in the network stack process, or inside 224 * the system server on devices that do not support the network stack module. The network stack 225 * connector will then be delivered asynchronously to clients that requested it before it was 226 * started. 227 */ start()228 public void start() { 229 mDependencies.getConnectivityModuleConnector().startModuleService( 230 INetworkStackConnector.class.getName(), PERMISSION_MAINLINE_NETWORK_STACK, 231 new NetworkStackConnection()); 232 log("Network stack service start requested"); 233 } 234 235 /** 236 * Log a debug message. 237 */ log(@onNull String message)238 private void log(@NonNull String message) { 239 Log.d(TAG, message); 240 } 241 logWtf(@onNull String message, @Nullable Throwable e)242 private void logWtf(@NonNull String message, @Nullable Throwable e) { 243 Slog.wtf(TAG, message); 244 Log.e(TAG, message, e); 245 } 246 loge(@onNull String message, @Nullable Throwable e)247 private void loge(@NonNull String message, @Nullable Throwable e) { 248 Log.e(TAG, message, e); 249 } 250 logi(@onNull String message)251 private void logi(@NonNull String message) { 252 Log.i(TAG, message); 253 } 254 255 /** 256 * For non-system server clients, get the connector registered by the system server. 257 */ getRemoteConnector()258 private INetworkStackConnector getRemoteConnector() { 259 // Block until the NetworkStack connector is registered in ServiceManager. 260 // <p>This is only useful for non-system processes that do not have a way to be notified of 261 // registration completion. Adding a callback system would be too heavy weight considering 262 // that the connector is registered on boot, so it is unlikely that a client would request 263 // it before it is registered. 264 // TODO: consider blocking boot on registration and simplify much of the logic in this class 265 IBinder connector; 266 try { 267 final long before = System.currentTimeMillis(); 268 while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) { 269 Thread.sleep(20); 270 if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) { 271 loge("Timeout waiting for NetworkStack connector", null); 272 return null; 273 } 274 } 275 } catch (InterruptedException e) { 276 loge("Error waiting for NetworkStack connector", e); 277 return null; 278 } 279 280 return INetworkStackConnector.Stub.asInterface(connector); 281 } 282 requestConnector(@onNull NetworkStackCallback request)283 private void requestConnector(@NonNull NetworkStackCallback request) { 284 mDependencies.checkCallerUid(); 285 286 if (!mWasSystemServerInitialized) { 287 // The network stack is not being started in this process, e.g. this process is not 288 // the system server. Get a remote connector registered by the system server. 289 final INetworkStackConnector connector = getRemoteConnector(); 290 synchronized (mPendingNetStackRequests) { 291 mConnector = connector; 292 } 293 request.onNetworkStackConnected(connector); 294 return; 295 } 296 297 final INetworkStackConnector connector; 298 synchronized (mPendingNetStackRequests) { 299 connector = mConnector; 300 if (connector == null) { 301 mPendingNetStackRequests.add(request); 302 return; 303 } 304 } 305 306 request.onNetworkStackConnected(connector); 307 } 308 } 309