NetworkManagementService.java revision 42065ac64cba166dc0fe602957ea8fe80bf406e2
1/* 2 * Copyright (C) 2007 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 17package com.android.server; 18 19import static android.Manifest.permission.CHANGE_NETWORK_STATE; 20import static android.Manifest.permission.CONNECTIVITY_INTERNAL; 21import static android.Manifest.permission.DUMP; 22import static android.Manifest.permission.SHUTDOWN; 23import static android.net.NetworkStats.SET_DEFAULT; 24import static android.net.NetworkStats.TAG_ALL; 25import static android.net.NetworkStats.TAG_NONE; 26import static android.net.NetworkStats.UID_ALL; 27import static android.net.TrafficStats.UID_TETHERING; 28import static android.system.OsConstants.AF_INET; 29import static android.system.OsConstants.AF_INET6; 30import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult; 31import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult; 32import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult; 33import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult; 34import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult; 35import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult; 36import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult; 37import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult; 38import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult; 39import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 40 41import android.content.Context; 42import android.net.ConnectivityManager; 43import android.net.INetworkManagementEventObserver; 44import android.net.InterfaceConfiguration; 45import android.net.IpPrefix; 46import android.net.LinkAddress; 47import android.net.NetworkStats; 48import android.net.NetworkUtils; 49import android.net.RouteInfo; 50import android.net.UidRange; 51import android.net.wifi.WifiConfiguration; 52import android.net.wifi.WifiConfiguration.KeyMgmt; 53import android.os.BatteryStats; 54import android.os.Binder; 55import android.os.Handler; 56import android.os.INetworkActivityListener; 57import android.os.INetworkManagementService; 58import android.os.PowerManager; 59import android.os.Process; 60import android.os.RemoteCallbackList; 61import android.os.RemoteException; 62import android.os.ServiceManager; 63import android.os.SystemClock; 64import android.os.SystemProperties; 65import android.telephony.DataConnectionRealTimeInfo; 66import android.telephony.PhoneStateListener; 67import android.telephony.SubscriptionManager; 68import android.telephony.TelephonyManager; 69import android.util.Log; 70import android.util.Slog; 71import android.util.SparseBooleanArray; 72 73import com.android.internal.app.IBatteryStats; 74import com.android.internal.net.NetworkStatsFactory; 75import com.android.internal.util.Preconditions; 76import com.android.server.NativeDaemonConnector.Command; 77import com.android.server.NativeDaemonConnector.SensitiveArg; 78import com.android.server.net.LockdownVpnTracker; 79import com.google.android.collect.Maps; 80 81import java.io.BufferedReader; 82import java.io.DataInputStream; 83import java.io.File; 84import java.io.FileDescriptor; 85import java.io.FileInputStream; 86import java.io.IOException; 87import java.io.InputStreamReader; 88import java.io.PrintWriter; 89import java.net.Inet4Address; 90import java.net.Inet6Address; 91import java.net.InetAddress; 92import java.net.InterfaceAddress; 93import java.net.NetworkInterface; 94import java.net.SocketException; 95import java.util.ArrayList; 96import java.util.Arrays; 97import java.util.HashMap; 98import java.util.List; 99import java.util.Map; 100import java.util.NoSuchElementException; 101import java.util.StringTokenizer; 102import java.util.concurrent.CountDownLatch; 103 104/** 105 * @hide 106 */ 107public class NetworkManagementService extends INetworkManagementService.Stub 108 implements Watchdog.Monitor { 109 private static final String TAG = "NetworkManagementService"; 110 private static final boolean DBG = false; 111 private static final String NETD_TAG = "NetdConnector"; 112 private static final String NETD_SOCKET_NAME = "netd"; 113 114 private static final int MAX_UID_RANGES_PER_COMMAND = 10; 115 116 /** 117 * Name representing {@link #setGlobalAlert(long)} limit when delivered to 118 * {@link INetworkManagementEventObserver#limitReached(String, String)}. 119 */ 120 public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; 121 122 class NetdResponseCode { 123 /* Keep in sync with system/netd/server/ResponseCode.h */ 124 public static final int InterfaceListResult = 110; 125 public static final int TetherInterfaceListResult = 111; 126 public static final int TetherDnsFwdTgtListResult = 112; 127 public static final int TtyListResult = 113; 128 public static final int TetheringStatsListResult = 114; 129 130 public static final int TetherStatusResult = 210; 131 public static final int IpFwdStatusResult = 211; 132 public static final int InterfaceGetCfgResult = 213; 133 public static final int SoftapStatusResult = 214; 134 public static final int InterfaceRxCounterResult = 216; 135 public static final int InterfaceTxCounterResult = 217; 136 public static final int QuotaCounterResult = 220; 137 public static final int TetheringStatsResult = 221; 138 public static final int DnsProxyQueryResult = 222; 139 public static final int ClatdStatusResult = 223; 140 141 public static final int InterfaceChange = 600; 142 public static final int BandwidthControl = 601; 143 public static final int InterfaceClassActivity = 613; 144 public static final int InterfaceAddressChange = 614; 145 public static final int InterfaceDnsServerInfo = 615; 146 public static final int RouteChange = 616; 147 } 148 149 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1; 150 151 /** 152 * Binder context for this service 153 */ 154 private final Context mContext; 155 156 /** 157 * connector object for communicating with netd 158 */ 159 private final NativeDaemonConnector mConnector; 160 161 private final Handler mFgHandler; 162 private final Handler mDaemonHandler; 163 private final PhoneStateListener mPhoneStateListener; 164 165 private IBatteryStats mBatteryStats; 166 167 private final Thread mThread; 168 private CountDownLatch mConnectedSignal = new CountDownLatch(1); 169 170 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = 171 new RemoteCallbackList<INetworkManagementEventObserver>(); 172 173 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory(); 174 175 private Object mQuotaLock = new Object(); 176 /** Set of interfaces with active quotas. */ 177 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap(); 178 /** Set of interfaces with active alerts. */ 179 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap(); 180 /** Set of UIDs with active reject rules. */ 181 private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); 182 183 private Object mIdleTimerLock = new Object(); 184 /** Set of interfaces with active idle timers. */ 185 private static class IdleTimerParams { 186 public final int timeout; 187 public final int type; 188 public int networkCount; 189 190 IdleTimerParams(int timeout, int type) { 191 this.timeout = timeout; 192 this.type = type; 193 this.networkCount = 1; 194 } 195 } 196 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap(); 197 198 private volatile boolean mBandwidthControlEnabled; 199 private volatile boolean mFirewallEnabled; 200 201 private boolean mMobileActivityFromRadio = false; 202 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; 203 204 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners = 205 new RemoteCallbackList<INetworkActivityListener>(); 206 private boolean mNetworkActive; 207 208 /** 209 * Constructs a new NetworkManagementService instance 210 * 211 * @param context Binder context for this service 212 */ 213 private NetworkManagementService(Context context, String socket) { 214 mContext = context; 215 216 // make sure this is on the same looper as our NativeDaemonConnector for sync purposes 217 mFgHandler = new Handler(FgThread.get().getLooper()); 218 219 if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 220 mConnector = null; 221 mThread = null; 222 mDaemonHandler = null; 223 mPhoneStateListener = null; 224 return; 225 } 226 227 // Don't need this wake lock, since we now have a time stamp for when 228 // the network actually went inactive. (It might be nice to still do this, 229 // but I don't want to do it through the power manager because that pollutes the 230 // battery stats history with pointless noise.) 231 //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 232 PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG); 233 234 mConnector = new NativeDaemonConnector( 235 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl, 236 FgThread.get().getLooper()); 237 mThread = new Thread(mConnector, NETD_TAG); 238 239 mDaemonHandler = new Handler(FgThread.get().getLooper()); 240 241 mPhoneStateListener = new PhoneStateListener(SubscriptionManager.DEFAULT_SUB_ID, 242 mDaemonHandler.getLooper()) { 243 @Override 244 public void onDataConnectionRealTimeInfoChanged( 245 DataConnectionRealTimeInfo dcRtInfo) { 246 if (DBG) Slog.d(TAG, "onDataConnectionRealTimeInfoChanged: " + dcRtInfo); 247 notifyInterfaceClassActivity(ConnectivityManager.TYPE_MOBILE, 248 dcRtInfo.getDcPowerState(), dcRtInfo.getTime(), true); 249 } 250 }; 251 TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 252 if (tm != null) { 253 tm.listen(mPhoneStateListener, 254 PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO); 255 } 256 257 // Add ourself to the Watchdog monitors. 258 Watchdog.getInstance().addMonitor(this); 259 } 260 261 static NetworkManagementService create(Context context, 262 String socket) throws InterruptedException { 263 final NetworkManagementService service = new NetworkManagementService(context, socket); 264 final CountDownLatch connectedSignal = service.mConnectedSignal; 265 if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 266 service.mThread.start(); 267 if (DBG) Slog.d(TAG, "Awaiting socket connection"); 268 connectedSignal.await(); 269 if (DBG) Slog.d(TAG, "Connected"); 270 return service; 271 } 272 273 public static NetworkManagementService create(Context context) throws InterruptedException { 274 return create(context, NETD_SOCKET_NAME); 275 } 276 277 public void systemReady() { 278 prepareNativeDaemon(); 279 if (DBG) Slog.d(TAG, "Prepared"); 280 } 281 282 private IBatteryStats getBatteryStats() { 283 synchronized (this) { 284 if (mBatteryStats != null) { 285 return mBatteryStats; 286 } 287 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( 288 BatteryStats.SERVICE_NAME)); 289 return mBatteryStats; 290 } 291 } 292 293 @Override 294 public void registerObserver(INetworkManagementEventObserver observer) { 295 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 296 mObservers.register(observer); 297 } 298 299 @Override 300 public void unregisterObserver(INetworkManagementEventObserver observer) { 301 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 302 mObservers.unregister(observer); 303 } 304 305 /** 306 * Notify our observers of an interface status change 307 */ 308 private void notifyInterfaceStatusChanged(String iface, boolean up) { 309 final int length = mObservers.beginBroadcast(); 310 try { 311 for (int i = 0; i < length; i++) { 312 try { 313 mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up); 314 } catch (RemoteException e) { 315 } catch (RuntimeException e) { 316 } 317 } 318 } finally { 319 mObservers.finishBroadcast(); 320 } 321 } 322 323 /** 324 * Notify our observers of an interface link state change 325 * (typically, an Ethernet cable has been plugged-in or unplugged). 326 */ 327 private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 328 final int length = mObservers.beginBroadcast(); 329 try { 330 for (int i = 0; i < length; i++) { 331 try { 332 mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up); 333 } catch (RemoteException e) { 334 } catch (RuntimeException e) { 335 } 336 } 337 } finally { 338 mObservers.finishBroadcast(); 339 } 340 } 341 342 /** 343 * Notify our observers of an interface addition. 344 */ 345 private void notifyInterfaceAdded(String iface) { 346 final int length = mObservers.beginBroadcast(); 347 try { 348 for (int i = 0; i < length; i++) { 349 try { 350 mObservers.getBroadcastItem(i).interfaceAdded(iface); 351 } catch (RemoteException e) { 352 } catch (RuntimeException e) { 353 } 354 } 355 } finally { 356 mObservers.finishBroadcast(); 357 } 358 } 359 360 /** 361 * Notify our observers of an interface removal. 362 */ 363 private void notifyInterfaceRemoved(String iface) { 364 // netd already clears out quota and alerts for removed ifaces; update 365 // our sanity-checking state. 366 mActiveAlerts.remove(iface); 367 mActiveQuotas.remove(iface); 368 369 final int length = mObservers.beginBroadcast(); 370 try { 371 for (int i = 0; i < length; i++) { 372 try { 373 mObservers.getBroadcastItem(i).interfaceRemoved(iface); 374 } catch (RemoteException e) { 375 } catch (RuntimeException e) { 376 } 377 } 378 } finally { 379 mObservers.finishBroadcast(); 380 } 381 } 382 383 /** 384 * Notify our observers of a limit reached. 385 */ 386 private void notifyLimitReached(String limitName, String iface) { 387 final int length = mObservers.beginBroadcast(); 388 try { 389 for (int i = 0; i < length; i++) { 390 try { 391 mObservers.getBroadcastItem(i).limitReached(limitName, iface); 392 } catch (RemoteException e) { 393 } catch (RuntimeException e) { 394 } 395 } 396 } finally { 397 mObservers.finishBroadcast(); 398 } 399 } 400 401 /** 402 * Notify our observers of a change in the data activity state of the interface 403 */ 404 private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos, 405 boolean fromRadio) { 406 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type); 407 if (isMobile) { 408 if (!fromRadio) { 409 if (mMobileActivityFromRadio) { 410 // If this call is not coming from a report from the radio itself, but we 411 // have previously received reports from the radio, then we will take the 412 // power state to just be whatever the radio last reported. 413 powerState = mLastPowerStateFromRadio; 414 } 415 } else { 416 mMobileActivityFromRadio = true; 417 } 418 if (mLastPowerStateFromRadio != powerState) { 419 mLastPowerStateFromRadio = powerState; 420 try { 421 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos); 422 } catch (RemoteException e) { 423 } 424 } 425 } 426 427 boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM 428 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; 429 430 if (!isMobile || fromRadio || !mMobileActivityFromRadio) { 431 // Report the change in data activity. We don't do this if this is a change 432 // on the mobile network, that is not coming from the radio itself, and we 433 // have previously seen change reports from the radio. In that case only 434 // the radio is the authority for the current state. 435 final int length = mObservers.beginBroadcast(); 436 try { 437 for (int i = 0; i < length; i++) { 438 try { 439 mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged( 440 Integer.toString(type), isActive, tsNanos); 441 } catch (RemoteException e) { 442 } catch (RuntimeException e) { 443 } 444 } 445 } finally { 446 mObservers.finishBroadcast(); 447 } 448 } 449 450 boolean report = false; 451 synchronized (mIdleTimerLock) { 452 if (mActiveIdleTimers.isEmpty()) { 453 // If there are no idle timers, we are not monitoring activity, so we 454 // are always considered active. 455 isActive = true; 456 } 457 if (mNetworkActive != isActive) { 458 mNetworkActive = isActive; 459 report = isActive; 460 } 461 } 462 if (report) { 463 reportNetworkActive(); 464 } 465 } 466 467 /** 468 * Prepare native daemon once connected, enabling modules and pushing any 469 * existing in-memory rules. 470 */ 471 private void prepareNativeDaemon() { 472 mBandwidthControlEnabled = false; 473 474 // only enable bandwidth control when support exists 475 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 476 if (hasKernelSupport) { 477 Slog.d(TAG, "enabling bandwidth control"); 478 try { 479 mConnector.execute("bandwidth", "enable"); 480 mBandwidthControlEnabled = true; 481 } catch (NativeDaemonConnectorException e) { 482 Log.wtf(TAG, "problem enabling bandwidth controls", e); 483 } 484 } else { 485 Slog.d(TAG, "not enabling bandwidth control"); 486 } 487 488 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 489 490 if (mBandwidthControlEnabled) { 491 try { 492 getBatteryStats().noteNetworkStatsEnabled(); 493 } catch (RemoteException e) { 494 } 495 } 496 497 // push any existing quota or UID rules 498 synchronized (mQuotaLock) { 499 int size = mActiveQuotas.size(); 500 if (size > 0) { 501 Slog.d(TAG, "pushing " + size + " active quota rules"); 502 final HashMap<String, Long> activeQuotas = mActiveQuotas; 503 mActiveQuotas = Maps.newHashMap(); 504 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) { 505 setInterfaceQuota(entry.getKey(), entry.getValue()); 506 } 507 } 508 509 size = mActiveAlerts.size(); 510 if (size > 0) { 511 Slog.d(TAG, "pushing " + size + " active alert rules"); 512 final HashMap<String, Long> activeAlerts = mActiveAlerts; 513 mActiveAlerts = Maps.newHashMap(); 514 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) { 515 setInterfaceAlert(entry.getKey(), entry.getValue()); 516 } 517 } 518 519 size = mUidRejectOnQuota.size(); 520 if (size > 0) { 521 Slog.d(TAG, "pushing " + size + " active uid rules"); 522 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota; 523 mUidRejectOnQuota = new SparseBooleanArray(); 524 for (int i = 0; i < uidRejectOnQuota.size(); i++) { 525 setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i)); 526 } 527 } 528 } 529 530 // TODO: Push any existing firewall state 531 setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); 532 } 533 534 /** 535 * Notify our observers of a new or updated interface address. 536 */ 537 private void notifyAddressUpdated(String iface, LinkAddress address) { 538 final int length = mObservers.beginBroadcast(); 539 try { 540 for (int i = 0; i < length; i++) { 541 try { 542 mObservers.getBroadcastItem(i).addressUpdated(iface, address); 543 } catch (RemoteException e) { 544 } catch (RuntimeException e) { 545 } 546 } 547 } finally { 548 mObservers.finishBroadcast(); 549 } 550 } 551 552 /** 553 * Notify our observers of a deleted interface address. 554 */ 555 private void notifyAddressRemoved(String iface, LinkAddress address) { 556 final int length = mObservers.beginBroadcast(); 557 try { 558 for (int i = 0; i < length; i++) { 559 try { 560 mObservers.getBroadcastItem(i).addressRemoved(iface, address); 561 } catch (RemoteException e) { 562 } catch (RuntimeException e) { 563 } 564 } 565 } finally { 566 mObservers.finishBroadcast(); 567 } 568 } 569 570 /** 571 * Notify our observers of DNS server information received. 572 */ 573 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) { 574 final int length = mObservers.beginBroadcast(); 575 try { 576 for (int i = 0; i < length; i++) { 577 try { 578 mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime, 579 addresses); 580 } catch (RemoteException e) { 581 } catch (RuntimeException e) { 582 } 583 } 584 } finally { 585 mObservers.finishBroadcast(); 586 } 587 } 588 589 /** 590 * Notify our observers of a route change. 591 */ 592 private void notifyRouteChange(String action, RouteInfo route) { 593 final int length = mObservers.beginBroadcast(); 594 try { 595 for (int i = 0; i < length; i++) { 596 try { 597 if (action.equals("updated")) { 598 mObservers.getBroadcastItem(i).routeUpdated(route); 599 } else { 600 mObservers.getBroadcastItem(i).routeRemoved(route); 601 } 602 } catch (RemoteException e) { 603 } catch (RuntimeException e) { 604 } 605 } 606 } finally { 607 mObservers.finishBroadcast(); 608 } 609 } 610 611 // 612 // Netd Callback handling 613 // 614 615 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 616 @Override 617 public void onDaemonConnected() { 618 // event is dispatched from internal NDC thread, so we prepare the 619 // daemon back on main thread. 620 if (mConnectedSignal != null) { 621 mConnectedSignal.countDown(); 622 mConnectedSignal = null; 623 } else { 624 mFgHandler.post(new Runnable() { 625 @Override 626 public void run() { 627 prepareNativeDaemon(); 628 } 629 }); 630 } 631 } 632 633 @Override 634 public boolean onCheckHoldWakeLock(int code) { 635 return code == NetdResponseCode.InterfaceClassActivity; 636 } 637 638 @Override 639 public boolean onEvent(int code, String raw, String[] cooked) { 640 String errorMessage = String.format("Invalid event from daemon (%s)", raw); 641 switch (code) { 642 case NetdResponseCode.InterfaceChange: 643 /* 644 * a network interface change occured 645 * Format: "NNN Iface added <name>" 646 * "NNN Iface removed <name>" 647 * "NNN Iface changed <name> <up/down>" 648 * "NNN Iface linkstatus <name> <up/down>" 649 */ 650 if (cooked.length < 4 || !cooked[1].equals("Iface")) { 651 throw new IllegalStateException(errorMessage); 652 } 653 if (cooked[2].equals("added")) { 654 notifyInterfaceAdded(cooked[3]); 655 return true; 656 } else if (cooked[2].equals("removed")) { 657 notifyInterfaceRemoved(cooked[3]); 658 return true; 659 } else if (cooked[2].equals("changed") && cooked.length == 5) { 660 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 661 return true; 662 } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 663 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 664 return true; 665 } 666 throw new IllegalStateException(errorMessage); 667 // break; 668 case NetdResponseCode.BandwidthControl: 669 /* 670 * Bandwidth control needs some attention 671 * Format: "NNN limit alert <alertName> <ifaceName>" 672 */ 673 if (cooked.length < 5 || !cooked[1].equals("limit")) { 674 throw new IllegalStateException(errorMessage); 675 } 676 if (cooked[2].equals("alert")) { 677 notifyLimitReached(cooked[3], cooked[4]); 678 return true; 679 } 680 throw new IllegalStateException(errorMessage); 681 // break; 682 case NetdResponseCode.InterfaceClassActivity: 683 /* 684 * An network interface class state changed (active/idle) 685 * Format: "NNN IfaceClass <active/idle> <label>" 686 */ 687 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) { 688 throw new IllegalStateException(errorMessage); 689 } 690 long timestampNanos = 0; 691 if (cooked.length == 5) { 692 try { 693 timestampNanos = Long.parseLong(cooked[4]); 694 } catch(NumberFormatException ne) {} 695 } else { 696 timestampNanos = SystemClock.elapsedRealtimeNanos(); 697 } 698 boolean isActive = cooked[2].equals("active"); 699 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), 700 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH 701 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, timestampNanos, false); 702 return true; 703 // break; 704 case NetdResponseCode.InterfaceAddressChange: 705 /* 706 * A network address change occurred 707 * Format: "NNN Address updated <addr> <iface> <flags> <scope>" 708 * "NNN Address removed <addr> <iface> <flags> <scope>" 709 */ 710 if (cooked.length < 7 || !cooked[1].equals("Address")) { 711 throw new IllegalStateException(errorMessage); 712 } 713 714 String iface = cooked[4]; 715 LinkAddress address; 716 try { 717 int flags = Integer.parseInt(cooked[5]); 718 int scope = Integer.parseInt(cooked[6]); 719 address = new LinkAddress(cooked[3], flags, scope); 720 } catch(NumberFormatException e) { // Non-numeric lifetime or scope. 721 throw new IllegalStateException(errorMessage, e); 722 } catch(IllegalArgumentException e) { // Malformed/invalid IP address. 723 throw new IllegalStateException(errorMessage, e); 724 } 725 726 if (cooked[2].equals("updated")) { 727 notifyAddressUpdated(iface, address); 728 } else { 729 notifyAddressRemoved(iface, address); 730 } 731 return true; 732 // break; 733 case NetdResponseCode.InterfaceDnsServerInfo: 734 /* 735 * Information about available DNS servers has been received. 736 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>" 737 */ 738 long lifetime; // Actually a 32-bit unsigned integer. 739 740 if (cooked.length == 6 && 741 cooked[1].equals("DnsInfo") && 742 cooked[2].equals("servers")) { 743 try { 744 lifetime = Long.parseLong(cooked[4]); 745 } catch (NumberFormatException e) { 746 throw new IllegalStateException(errorMessage); 747 } 748 String[] servers = cooked[5].split(","); 749 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers); 750 } 751 return true; 752 // break; 753 case NetdResponseCode.RouteChange: 754 /* 755 * A route has been updated or removed. 756 * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]" 757 */ 758 if (!cooked[1].equals("Route") || cooked.length < 6) { 759 throw new IllegalStateException(errorMessage); 760 } 761 762 String via = null; 763 String dev = null; 764 boolean valid = true; 765 for (int i = 4; (i + 1) < cooked.length && valid; i += 2) { 766 if (cooked[i].equals("dev")) { 767 if (dev == null) { 768 dev = cooked[i+1]; 769 } else { 770 valid = false; // Duplicate interface. 771 } 772 } else if (cooked[i].equals("via")) { 773 if (via == null) { 774 via = cooked[i+1]; 775 } else { 776 valid = false; // Duplicate gateway. 777 } 778 } else { 779 valid = false; // Unknown syntax. 780 } 781 } 782 if (valid) { 783 try { 784 // InetAddress.parseNumericAddress(null) inexplicably returns ::1. 785 InetAddress gateway = null; 786 if (via != null) gateway = InetAddress.parseNumericAddress(via); 787 RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev); 788 notifyRouteChange(cooked[2], route); 789 return true; 790 } catch (IllegalArgumentException e) {} 791 } 792 throw new IllegalStateException(errorMessage); 793 // break; 794 default: break; 795 } 796 return false; 797 } 798 } 799 800 801 // 802 // INetworkManagementService members 803 // 804 805 @Override 806 public String[] listInterfaces() { 807 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 808 try { 809 return NativeDaemonEvent.filterMessageList( 810 mConnector.executeForList("interface", "list"), InterfaceListResult); 811 } catch (NativeDaemonConnectorException e) { 812 throw e.rethrowAsParcelableException(); 813 } 814 } 815 816 @Override 817 public InterfaceConfiguration getInterfaceConfig(String iface) { 818 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 819 820 final NativeDaemonEvent event; 821 try { 822 event = mConnector.execute("interface", "getcfg", iface); 823 } catch (NativeDaemonConnectorException e) { 824 throw e.rethrowAsParcelableException(); 825 } 826 827 event.checkCode(InterfaceGetCfgResult); 828 829 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3 830 final StringTokenizer st = new StringTokenizer(event.getMessage()); 831 832 InterfaceConfiguration cfg; 833 try { 834 cfg = new InterfaceConfiguration(); 835 cfg.setHardwareAddress(st.nextToken(" ")); 836 InetAddress addr = null; 837 int prefixLength = 0; 838 try { 839 addr = NetworkUtils.numericToInetAddress(st.nextToken()); 840 } catch (IllegalArgumentException iae) { 841 Slog.e(TAG, "Failed to parse ipaddr", iae); 842 } 843 844 try { 845 prefixLength = Integer.parseInt(st.nextToken()); 846 } catch (NumberFormatException nfe) { 847 Slog.e(TAG, "Failed to parse prefixLength", nfe); 848 } 849 850 cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 851 while (st.hasMoreTokens()) { 852 cfg.setFlag(st.nextToken()); 853 } 854 } catch (NoSuchElementException nsee) { 855 throw new IllegalStateException("Invalid response from daemon: " + event); 856 } 857 return cfg; 858 } 859 860 @Override 861 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 862 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 863 LinkAddress linkAddr = cfg.getLinkAddress(); 864 if (linkAddr == null || linkAddr.getAddress() == null) { 865 throw new IllegalStateException("Null LinkAddress given"); 866 } 867 868 final Command cmd = new Command("interface", "setcfg", iface, 869 linkAddr.getAddress().getHostAddress(), 870 linkAddr.getPrefixLength()); 871 for (String flag : cfg.getFlags()) { 872 cmd.appendArg(flag); 873 } 874 875 try { 876 mConnector.execute(cmd); 877 } catch (NativeDaemonConnectorException e) { 878 throw e.rethrowAsParcelableException(); 879 } 880 } 881 882 @Override 883 public void setInterfaceDown(String iface) { 884 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 885 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 886 ifcg.setInterfaceDown(); 887 setInterfaceConfig(iface, ifcg); 888 } 889 890 @Override 891 public void setInterfaceUp(String iface) { 892 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 893 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 894 ifcg.setInterfaceUp(); 895 setInterfaceConfig(iface, ifcg); 896 } 897 898 @Override 899 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 900 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 901 try { 902 mConnector.execute( 903 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable"); 904 } catch (NativeDaemonConnectorException e) { 905 throw e.rethrowAsParcelableException(); 906 } 907 } 908 909 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 910 IPv6 addresses on interface down, but we need to do full clean up here */ 911 @Override 912 public void clearInterfaceAddresses(String iface) { 913 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 914 try { 915 mConnector.execute("interface", "clearaddrs", iface); 916 } catch (NativeDaemonConnectorException e) { 917 throw e.rethrowAsParcelableException(); 918 } 919 } 920 921 @Override 922 public void enableIpv6(String iface) { 923 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 924 try { 925 mConnector.execute("interface", "ipv6", iface, "enable"); 926 } catch (NativeDaemonConnectorException e) { 927 throw e.rethrowAsParcelableException(); 928 } 929 } 930 931 @Override 932 public void disableIpv6(String iface) { 933 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 934 try { 935 mConnector.execute("interface", "ipv6", iface, "disable"); 936 } catch (NativeDaemonConnectorException e) { 937 throw e.rethrowAsParcelableException(); 938 } 939 } 940 941 @Override 942 public void addRoute(int netId, RouteInfo route) { 943 modifyRoute("add", "" + netId, route); 944 } 945 946 @Override 947 public void removeRoute(int netId, RouteInfo route) { 948 modifyRoute("remove", "" + netId, route); 949 } 950 951 private void modifyRoute(String action, String netId, RouteInfo route) { 952 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 953 954 final Command cmd = new Command("network", "route", action, netId); 955 956 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 957 final LinkAddress la = route.getDestinationLinkAddress(); 958 cmd.appendArg(route.getInterface()); 959 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); 960 if (route.hasGateway()) { 961 cmd.appendArg(route.getGateway().getHostAddress()); 962 } 963 964 try { 965 mConnector.execute(cmd); 966 } catch (NativeDaemonConnectorException e) { 967 throw e.rethrowAsParcelableException(); 968 } 969 } 970 971 private ArrayList<String> readRouteList(String filename) { 972 FileInputStream fstream = null; 973 ArrayList<String> list = new ArrayList<String>(); 974 975 try { 976 fstream = new FileInputStream(filename); 977 DataInputStream in = new DataInputStream(fstream); 978 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 979 String s; 980 981 // throw away the title line 982 983 while (((s = br.readLine()) != null) && (s.length() != 0)) { 984 list.add(s); 985 } 986 } catch (IOException ex) { 987 // return current list, possibly empty 988 } finally { 989 if (fstream != null) { 990 try { 991 fstream.close(); 992 } catch (IOException ex) {} 993 } 994 } 995 996 return list; 997 } 998 999 @Override 1000 public RouteInfo[] getRoutes(String interfaceName) { 1001 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1002 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 1003 1004 // v4 routes listed as: 1005 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 1006 for (String s : readRouteList("/proc/net/route")) { 1007 String[] fields = s.split("\t"); 1008 1009 if (fields.length > 7) { 1010 String iface = fields[0]; 1011 1012 if (interfaceName.equals(iface)) { 1013 String dest = fields[1]; 1014 String gate = fields[2]; 1015 String flags = fields[3]; // future use? 1016 String mask = fields[7]; 1017 try { 1018 // address stored as a hex string, ex: 0014A8C0 1019 InetAddress destAddr = 1020 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 1021 int prefixLength = 1022 NetworkUtils.netmaskIntToPrefixLength( 1023 (int)Long.parseLong(mask, 16)); 1024 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 1025 1026 // address stored as a hex string, ex 0014A8C0 1027 InetAddress gatewayAddr = 1028 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 1029 1030 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 1031 routes.add(route); 1032 } catch (Exception e) { 1033 Log.e(TAG, "Error parsing route " + s + " : " + e); 1034 continue; 1035 } 1036 } 1037 } 1038 } 1039 1040 // v6 routes listed as: 1041 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 1042 for (String s : readRouteList("/proc/net/ipv6_route")) { 1043 String[]fields = s.split("\\s+"); 1044 if (fields.length > 9) { 1045 String iface = fields[9].trim(); 1046 if (interfaceName.equals(iface)) { 1047 String dest = fields[0]; 1048 String prefix = fields[1]; 1049 String gate = fields[4]; 1050 1051 try { 1052 // prefix length stored as a hex string, ex 40 1053 int prefixLength = Integer.parseInt(prefix, 16); 1054 1055 // address stored as a 32 char hex string 1056 // ex fe800000000000000000000000000000 1057 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 1058 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 1059 1060 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 1061 1062 RouteInfo route = new RouteInfo(linkAddress, gateAddr); 1063 routes.add(route); 1064 } catch (Exception e) { 1065 Log.e(TAG, "Error parsing route " + s + " : " + e); 1066 continue; 1067 } 1068 } 1069 } 1070 } 1071 return routes.toArray(new RouteInfo[routes.size()]); 1072 } 1073 1074 @Override 1075 public void setMtu(String iface, int mtu) { 1076 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1077 1078 final NativeDaemonEvent event; 1079 try { 1080 event = mConnector.execute("interface", "setmtu", iface, mtu); 1081 } catch (NativeDaemonConnectorException e) { 1082 throw e.rethrowAsParcelableException(); 1083 } 1084 } 1085 1086 @Override 1087 public void shutdown() { 1088 // TODO: remove from aidl if nobody calls externally 1089 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 1090 1091 Slog.d(TAG, "Shutting down"); 1092 } 1093 1094 @Override 1095 public boolean getIpForwardingEnabled() throws IllegalStateException{ 1096 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1097 1098 final NativeDaemonEvent event; 1099 try { 1100 event = mConnector.execute("ipfwd", "status"); 1101 } catch (NativeDaemonConnectorException e) { 1102 throw e.rethrowAsParcelableException(); 1103 } 1104 1105 // 211 Forwarding enabled 1106 event.checkCode(IpFwdStatusResult); 1107 return event.getMessage().endsWith("enabled"); 1108 } 1109 1110 @Override 1111 public void setIpForwardingEnabled(boolean enable) { 1112 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1113 try { 1114 mConnector.execute("ipfwd", enable ? "enable" : "disable"); 1115 } catch (NativeDaemonConnectorException e) { 1116 throw e.rethrowAsParcelableException(); 1117 } 1118 } 1119 1120 @Override 1121 public void startTethering(String[] dhcpRange) { 1122 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1123 // cmd is "tether start first_start first_stop second_start second_stop ..." 1124 // an odd number of addrs will fail 1125 1126 final Command cmd = new Command("tether", "start"); 1127 for (String d : dhcpRange) { 1128 cmd.appendArg(d); 1129 } 1130 1131 try { 1132 mConnector.execute(cmd); 1133 } catch (NativeDaemonConnectorException e) { 1134 throw e.rethrowAsParcelableException(); 1135 } 1136 } 1137 1138 @Override 1139 public void stopTethering() { 1140 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1141 try { 1142 mConnector.execute("tether", "stop"); 1143 } catch (NativeDaemonConnectorException e) { 1144 throw e.rethrowAsParcelableException(); 1145 } 1146 } 1147 1148 @Override 1149 public boolean isTetheringStarted() { 1150 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1151 1152 final NativeDaemonEvent event; 1153 try { 1154 event = mConnector.execute("tether", "status"); 1155 } catch (NativeDaemonConnectorException e) { 1156 throw e.rethrowAsParcelableException(); 1157 } 1158 1159 // 210 Tethering services started 1160 event.checkCode(TetherStatusResult); 1161 return event.getMessage().endsWith("started"); 1162 } 1163 1164 @Override 1165 public void tetherInterface(String iface) { 1166 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1167 try { 1168 mConnector.execute("tether", "interface", "add", iface); 1169 } catch (NativeDaemonConnectorException e) { 1170 throw e.rethrowAsParcelableException(); 1171 } 1172 List<RouteInfo> routes = new ArrayList<RouteInfo>(); 1173 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it 1174 // suitable to use as a route destination. 1175 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface)); 1176 addInterfaceToLocalNetwork(iface, routes); 1177 } 1178 1179 @Override 1180 public void untetherInterface(String iface) { 1181 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1182 try { 1183 mConnector.execute("tether", "interface", "remove", iface); 1184 } catch (NativeDaemonConnectorException e) { 1185 throw e.rethrowAsParcelableException(); 1186 } 1187 removeInterfaceFromLocalNetwork(iface); 1188 } 1189 1190 @Override 1191 public String[] listTetheredInterfaces() { 1192 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1193 try { 1194 return NativeDaemonEvent.filterMessageList( 1195 mConnector.executeForList("tether", "interface", "list"), 1196 TetherInterfaceListResult); 1197 } catch (NativeDaemonConnectorException e) { 1198 throw e.rethrowAsParcelableException(); 1199 } 1200 } 1201 1202 @Override 1203 public void setDnsForwarders(String[] dns) { 1204 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1205 1206 final Command cmd = new Command("tether", "dns", "set"); 1207 for (String s : dns) { 1208 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 1209 } 1210 1211 try { 1212 mConnector.execute(cmd); 1213 } catch (NativeDaemonConnectorException e) { 1214 throw e.rethrowAsParcelableException(); 1215 } 1216 } 1217 1218 @Override 1219 public String[] getDnsForwarders() { 1220 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1221 try { 1222 return NativeDaemonEvent.filterMessageList( 1223 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 1224 } catch (NativeDaemonConnectorException e) { 1225 throw e.rethrowAsParcelableException(); 1226 } 1227 } 1228 1229 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 1230 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); 1231 for (InterfaceAddress ia : addresses) { 1232 if (!ia.getAddress().isLinkLocalAddress()) 1233 filtered.add(ia); 1234 } 1235 return filtered; 1236 } 1237 1238 private void modifyNat(String action, String internalInterface, String externalInterface) 1239 throws SocketException { 1240 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 1241 1242 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 1243 internalInterface); 1244 if (internalNetworkInterface == null) { 1245 cmd.appendArg("0"); 1246 } else { 1247 // Don't touch link-local routes, as link-local addresses aren't routable, 1248 // kernel creates link-local routes on all interfaces automatically 1249 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( 1250 internalNetworkInterface.getInterfaceAddresses()); 1251 cmd.appendArg(interfaceAddresses.size()); 1252 for (InterfaceAddress ia : interfaceAddresses) { 1253 InetAddress addr = NetworkUtils.getNetworkPart( 1254 ia.getAddress(), ia.getNetworkPrefixLength()); 1255 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 1256 } 1257 } 1258 1259 try { 1260 mConnector.execute(cmd); 1261 } catch (NativeDaemonConnectorException e) { 1262 throw e.rethrowAsParcelableException(); 1263 } 1264 } 1265 1266 @Override 1267 public void enableNat(String internalInterface, String externalInterface) { 1268 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1269 try { 1270 modifyNat("enable", internalInterface, externalInterface); 1271 } catch (SocketException e) { 1272 throw new IllegalStateException(e); 1273 } 1274 } 1275 1276 @Override 1277 public void disableNat(String internalInterface, String externalInterface) { 1278 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1279 try { 1280 modifyNat("disable", internalInterface, externalInterface); 1281 } catch (SocketException e) { 1282 throw new IllegalStateException(e); 1283 } 1284 } 1285 1286 @Override 1287 public String[] listTtys() { 1288 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1289 try { 1290 return NativeDaemonEvent.filterMessageList( 1291 mConnector.executeForList("list_ttys"), TtyListResult); 1292 } catch (NativeDaemonConnectorException e) { 1293 throw e.rethrowAsParcelableException(); 1294 } 1295 } 1296 1297 @Override 1298 public void attachPppd( 1299 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 1300 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1301 try { 1302 mConnector.execute("pppd", "attach", tty, 1303 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 1304 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 1305 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 1306 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 1307 } catch (NativeDaemonConnectorException e) { 1308 throw e.rethrowAsParcelableException(); 1309 } 1310 } 1311 1312 @Override 1313 public void detachPppd(String tty) { 1314 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1315 try { 1316 mConnector.execute("pppd", "detach", tty); 1317 } catch (NativeDaemonConnectorException e) { 1318 throw e.rethrowAsParcelableException(); 1319 } 1320 } 1321 1322 @Override 1323 public void startAccessPoint( 1324 WifiConfiguration wifiConfig, String wlanIface) { 1325 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1326 try { 1327 wifiFirmwareReload(wlanIface, "AP"); 1328 if (wifiConfig == null) { 1329 mConnector.execute("softap", "set", wlanIface); 1330 } else { 1331 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1332 "broadcast", "6", getSecurityType(wifiConfig), 1333 new SensitiveArg(wifiConfig.preSharedKey)); 1334 } 1335 mConnector.execute("softap", "startap"); 1336 } catch (NativeDaemonConnectorException e) { 1337 throw e.rethrowAsParcelableException(); 1338 } 1339 } 1340 1341 private static String getSecurityType(WifiConfiguration wifiConfig) { 1342 switch (wifiConfig.getAuthType()) { 1343 case KeyMgmt.WPA_PSK: 1344 return "wpa-psk"; 1345 case KeyMgmt.WPA2_PSK: 1346 return "wpa2-psk"; 1347 default: 1348 return "open"; 1349 } 1350 } 1351 1352 /* @param mode can be "AP", "STA" or "P2P" */ 1353 @Override 1354 public void wifiFirmwareReload(String wlanIface, String mode) { 1355 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1356 try { 1357 mConnector.execute("softap", "fwreload", wlanIface, mode); 1358 } catch (NativeDaemonConnectorException e) { 1359 throw e.rethrowAsParcelableException(); 1360 } 1361 } 1362 1363 @Override 1364 public void stopAccessPoint(String wlanIface) { 1365 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1366 try { 1367 mConnector.execute("softap", "stopap"); 1368 wifiFirmwareReload(wlanIface, "STA"); 1369 } catch (NativeDaemonConnectorException e) { 1370 throw e.rethrowAsParcelableException(); 1371 } 1372 } 1373 1374 @Override 1375 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1376 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1377 try { 1378 if (wifiConfig == null) { 1379 mConnector.execute("softap", "set", wlanIface); 1380 } else { 1381 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1382 "broadcast", "6", getSecurityType(wifiConfig), 1383 new SensitiveArg(wifiConfig.preSharedKey)); 1384 } 1385 } catch (NativeDaemonConnectorException e) { 1386 throw e.rethrowAsParcelableException(); 1387 } 1388 } 1389 1390 @Override 1391 public void addIdleTimer(String iface, int timeout, final int type) { 1392 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1393 1394 if (DBG) Slog.d(TAG, "Adding idletimer"); 1395 1396 synchronized (mIdleTimerLock) { 1397 IdleTimerParams params = mActiveIdleTimers.get(iface); 1398 if (params != null) { 1399 // the interface already has idletimer, update network count 1400 params.networkCount++; 1401 return; 1402 } 1403 1404 try { 1405 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), 1406 Integer.toString(type)); 1407 } catch (NativeDaemonConnectorException e) { 1408 throw e.rethrowAsParcelableException(); 1409 } 1410 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); 1411 1412 // Networks start up. 1413 if (ConnectivityManager.isNetworkTypeMobile(type)) { 1414 mNetworkActive = false; 1415 } 1416 mDaemonHandler.post(new Runnable() { 1417 @Override public void run() { 1418 notifyInterfaceClassActivity(type, 1419 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 1420 SystemClock.elapsedRealtimeNanos(), false); 1421 } 1422 }); 1423 } 1424 } 1425 1426 @Override 1427 public void removeIdleTimer(String iface) { 1428 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1429 1430 if (DBG) Slog.d(TAG, "Removing idletimer"); 1431 1432 synchronized (mIdleTimerLock) { 1433 final IdleTimerParams params = mActiveIdleTimers.get(iface); 1434 if (params == null || --(params.networkCount) > 0) { 1435 return; 1436 } 1437 1438 try { 1439 mConnector.execute("idletimer", "remove", iface, 1440 Integer.toString(params.timeout), Integer.toString(params.type)); 1441 } catch (NativeDaemonConnectorException e) { 1442 throw e.rethrowAsParcelableException(); 1443 } 1444 mActiveIdleTimers.remove(iface); 1445 mDaemonHandler.post(new Runnable() { 1446 @Override public void run() { 1447 notifyInterfaceClassActivity(params.type, 1448 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, 1449 SystemClock.elapsedRealtimeNanos(), false); 1450 } 1451 }); 1452 } 1453 } 1454 1455 @Override 1456 public NetworkStats getNetworkStatsSummaryDev() { 1457 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1458 try { 1459 return mStatsFactory.readNetworkStatsSummaryDev(); 1460 } catch (IOException e) { 1461 throw new IllegalStateException(e); 1462 } 1463 } 1464 1465 @Override 1466 public NetworkStats getNetworkStatsSummaryXt() { 1467 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1468 try { 1469 return mStatsFactory.readNetworkStatsSummaryXt(); 1470 } catch (IOException e) { 1471 throw new IllegalStateException(e); 1472 } 1473 } 1474 1475 @Override 1476 public NetworkStats getNetworkStatsDetail() { 1477 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1478 try { 1479 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); 1480 } catch (IOException e) { 1481 throw new IllegalStateException(e); 1482 } 1483 } 1484 1485 @Override 1486 public void setInterfaceQuota(String iface, long quotaBytes) { 1487 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1488 1489 // silently discard when control disabled 1490 // TODO: eventually migrate to be always enabled 1491 if (!mBandwidthControlEnabled) return; 1492 1493 synchronized (mQuotaLock) { 1494 if (mActiveQuotas.containsKey(iface)) { 1495 throw new IllegalStateException("iface " + iface + " already has quota"); 1496 } 1497 1498 try { 1499 // TODO: support quota shared across interfaces 1500 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1501 mActiveQuotas.put(iface, quotaBytes); 1502 } catch (NativeDaemonConnectorException e) { 1503 throw e.rethrowAsParcelableException(); 1504 } 1505 } 1506 } 1507 1508 @Override 1509 public void removeInterfaceQuota(String iface) { 1510 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1511 1512 // silently discard when control disabled 1513 // TODO: eventually migrate to be always enabled 1514 if (!mBandwidthControlEnabled) return; 1515 1516 synchronized (mQuotaLock) { 1517 if (!mActiveQuotas.containsKey(iface)) { 1518 // TODO: eventually consider throwing 1519 return; 1520 } 1521 1522 mActiveQuotas.remove(iface); 1523 mActiveAlerts.remove(iface); 1524 1525 try { 1526 // TODO: support quota shared across interfaces 1527 mConnector.execute("bandwidth", "removeiquota", iface); 1528 } catch (NativeDaemonConnectorException e) { 1529 throw e.rethrowAsParcelableException(); 1530 } 1531 } 1532 } 1533 1534 @Override 1535 public void setInterfaceAlert(String iface, long alertBytes) { 1536 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1537 1538 // silently discard when control disabled 1539 // TODO: eventually migrate to be always enabled 1540 if (!mBandwidthControlEnabled) return; 1541 1542 // quick sanity check 1543 if (!mActiveQuotas.containsKey(iface)) { 1544 throw new IllegalStateException("setting alert requires existing quota on iface"); 1545 } 1546 1547 synchronized (mQuotaLock) { 1548 if (mActiveAlerts.containsKey(iface)) { 1549 throw new IllegalStateException("iface " + iface + " already has alert"); 1550 } 1551 1552 try { 1553 // TODO: support alert shared across interfaces 1554 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1555 mActiveAlerts.put(iface, alertBytes); 1556 } catch (NativeDaemonConnectorException e) { 1557 throw e.rethrowAsParcelableException(); 1558 } 1559 } 1560 } 1561 1562 @Override 1563 public void removeInterfaceAlert(String iface) { 1564 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1565 1566 // silently discard when control disabled 1567 // TODO: eventually migrate to be always enabled 1568 if (!mBandwidthControlEnabled) return; 1569 1570 synchronized (mQuotaLock) { 1571 if (!mActiveAlerts.containsKey(iface)) { 1572 // TODO: eventually consider throwing 1573 return; 1574 } 1575 1576 try { 1577 // TODO: support alert shared across interfaces 1578 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1579 mActiveAlerts.remove(iface); 1580 } catch (NativeDaemonConnectorException e) { 1581 throw e.rethrowAsParcelableException(); 1582 } 1583 } 1584 } 1585 1586 @Override 1587 public void setGlobalAlert(long alertBytes) { 1588 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1589 1590 // silently discard when control disabled 1591 // TODO: eventually migrate to be always enabled 1592 if (!mBandwidthControlEnabled) return; 1593 1594 try { 1595 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1596 } catch (NativeDaemonConnectorException e) { 1597 throw e.rethrowAsParcelableException(); 1598 } 1599 } 1600 1601 @Override 1602 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1603 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1604 1605 // silently discard when control disabled 1606 // TODO: eventually migrate to be always enabled 1607 if (!mBandwidthControlEnabled) return; 1608 1609 synchronized (mQuotaLock) { 1610 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1611 if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1612 // TODO: eventually consider throwing 1613 return; 1614 } 1615 1616 try { 1617 mConnector.execute("bandwidth", 1618 rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid); 1619 if (rejectOnQuotaInterfaces) { 1620 mUidRejectOnQuota.put(uid, true); 1621 } else { 1622 mUidRejectOnQuota.delete(uid); 1623 } 1624 } catch (NativeDaemonConnectorException e) { 1625 throw e.rethrowAsParcelableException(); 1626 } 1627 } 1628 } 1629 1630 @Override 1631 public boolean isBandwidthControlEnabled() { 1632 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1633 return mBandwidthControlEnabled; 1634 } 1635 1636 @Override 1637 public NetworkStats getNetworkStatsUidDetail(int uid) { 1638 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1639 try { 1640 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1641 } catch (IOException e) { 1642 throw new IllegalStateException(e); 1643 } 1644 } 1645 1646 @Override 1647 public NetworkStats getNetworkStatsTethering() { 1648 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1649 1650 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1651 try { 1652 final NativeDaemonEvent[] events = mConnector.executeForList( 1653 "bandwidth", "gettetherstats"); 1654 for (NativeDaemonEvent event : events) { 1655 if (event.getCode() != TetheringStatsListResult) continue; 1656 1657 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1658 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1659 try { 1660 final String ifaceIn = tok.nextToken(); 1661 final String ifaceOut = tok.nextToken(); 1662 1663 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1664 entry.iface = ifaceOut; 1665 entry.uid = UID_TETHERING; 1666 entry.set = SET_DEFAULT; 1667 entry.tag = TAG_NONE; 1668 entry.rxBytes = Long.parseLong(tok.nextToken()); 1669 entry.rxPackets = Long.parseLong(tok.nextToken()); 1670 entry.txBytes = Long.parseLong(tok.nextToken()); 1671 entry.txPackets = Long.parseLong(tok.nextToken()); 1672 stats.combineValues(entry); 1673 } catch (NoSuchElementException e) { 1674 throw new IllegalStateException("problem parsing tethering stats: " + event); 1675 } catch (NumberFormatException e) { 1676 throw new IllegalStateException("problem parsing tethering stats: " + event); 1677 } 1678 } 1679 } catch (NativeDaemonConnectorException e) { 1680 throw e.rethrowAsParcelableException(); 1681 } 1682 return stats; 1683 } 1684 1685 @Override 1686 public void setDnsServersForNetwork(int netId, String[] servers, String domains) { 1687 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1688 1689 final Command cmd = new Command("resolver", "setnetdns", netId, 1690 (domains == null ? "" : domains)); 1691 1692 for (String s : servers) { 1693 InetAddress a = NetworkUtils.numericToInetAddress(s); 1694 if (a.isAnyLocalAddress() == false) { 1695 cmd.appendArg(a.getHostAddress()); 1696 } 1697 } 1698 1699 try { 1700 mConnector.execute(cmd); 1701 } catch (NativeDaemonConnectorException e) { 1702 throw e.rethrowAsParcelableException(); 1703 } 1704 } 1705 1706 @Override 1707 public void addVpnUidRanges(int netId, UidRange[] ranges) { 1708 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1709 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 1710 argv[0] = "users"; 1711 argv[1] = "add"; 1712 argv[2] = netId; 1713 int argc = 3; 1714 // Avoid overly long commands by limiting number of UID ranges per command. 1715 for (int i = 0; i < ranges.length; i++) { 1716 argv[argc++] = ranges[i].toString(); 1717 if (i == (ranges.length - 1) || argc == argv.length) { 1718 try { 1719 mConnector.execute("network", Arrays.copyOf(argv, argc)); 1720 } catch (NativeDaemonConnectorException e) { 1721 throw e.rethrowAsParcelableException(); 1722 } 1723 argc = 3; 1724 } 1725 } 1726 } 1727 1728 @Override 1729 public void removeVpnUidRanges(int netId, UidRange[] ranges) { 1730 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1731 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 1732 argv[0] = "users"; 1733 argv[1] = "remove"; 1734 argv[2] = netId; 1735 int argc = 3; 1736 // Avoid overly long commands by limiting number of UID ranges per command. 1737 for (int i = 0; i < ranges.length; i++) { 1738 argv[argc++] = ranges[i].toString(); 1739 if (i == (ranges.length - 1) || argc == argv.length) { 1740 try { 1741 mConnector.execute("network", Arrays.copyOf(argv, argc)); 1742 } catch (NativeDaemonConnectorException e) { 1743 throw e.rethrowAsParcelableException(); 1744 } 1745 argc = 3; 1746 } 1747 } 1748 } 1749 1750 @Override 1751 public void setFirewallEnabled(boolean enabled) { 1752 enforceSystemUid(); 1753 try { 1754 mConnector.execute("firewall", enabled ? "enable" : "disable"); 1755 mFirewallEnabled = enabled; 1756 } catch (NativeDaemonConnectorException e) { 1757 throw e.rethrowAsParcelableException(); 1758 } 1759 } 1760 1761 @Override 1762 public boolean isFirewallEnabled() { 1763 enforceSystemUid(); 1764 return mFirewallEnabled; 1765 } 1766 1767 @Override 1768 public void setFirewallInterfaceRule(String iface, boolean allow) { 1769 enforceSystemUid(); 1770 Preconditions.checkState(mFirewallEnabled); 1771 final String rule = allow ? "allow" : "deny"; 1772 try { 1773 mConnector.execute("firewall", "set_interface_rule", iface, rule); 1774 } catch (NativeDaemonConnectorException e) { 1775 throw e.rethrowAsParcelableException(); 1776 } 1777 } 1778 1779 @Override 1780 public void setFirewallEgressSourceRule(String addr, boolean allow) { 1781 enforceSystemUid(); 1782 Preconditions.checkState(mFirewallEnabled); 1783 final String rule = allow ? "allow" : "deny"; 1784 try { 1785 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 1786 } catch (NativeDaemonConnectorException e) { 1787 throw e.rethrowAsParcelableException(); 1788 } 1789 } 1790 1791 @Override 1792 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 1793 enforceSystemUid(); 1794 Preconditions.checkState(mFirewallEnabled); 1795 final String rule = allow ? "allow" : "deny"; 1796 try { 1797 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 1798 } catch (NativeDaemonConnectorException e) { 1799 throw e.rethrowAsParcelableException(); 1800 } 1801 } 1802 1803 @Override 1804 public void setFirewallUidRule(int uid, boolean allow) { 1805 enforceSystemUid(); 1806 Preconditions.checkState(mFirewallEnabled); 1807 final String rule = allow ? "allow" : "deny"; 1808 try { 1809 mConnector.execute("firewall", "set_uid_rule", uid, rule); 1810 } catch (NativeDaemonConnectorException e) { 1811 throw e.rethrowAsParcelableException(); 1812 } 1813 } 1814 1815 private static void enforceSystemUid() { 1816 final int uid = Binder.getCallingUid(); 1817 if (uid != Process.SYSTEM_UID) { 1818 throw new SecurityException("Only available to AID_SYSTEM"); 1819 } 1820 } 1821 1822 @Override 1823 public void startClatd(String interfaceName) throws IllegalStateException { 1824 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1825 1826 try { 1827 mConnector.execute("clatd", "start", interfaceName); 1828 } catch (NativeDaemonConnectorException e) { 1829 throw e.rethrowAsParcelableException(); 1830 } 1831 } 1832 1833 @Override 1834 public void stopClatd() throws IllegalStateException { 1835 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1836 1837 try { 1838 mConnector.execute("clatd", "stop"); 1839 } catch (NativeDaemonConnectorException e) { 1840 throw e.rethrowAsParcelableException(); 1841 } 1842 } 1843 1844 @Override 1845 public boolean isClatdStarted() { 1846 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1847 1848 final NativeDaemonEvent event; 1849 try { 1850 event = mConnector.execute("clatd", "status"); 1851 } catch (NativeDaemonConnectorException e) { 1852 throw e.rethrowAsParcelableException(); 1853 } 1854 1855 event.checkCode(ClatdStatusResult); 1856 return event.getMessage().endsWith("started"); 1857 } 1858 1859 @Override 1860 public void registerNetworkActivityListener(INetworkActivityListener listener) { 1861 mNetworkActivityListeners.register(listener); 1862 } 1863 1864 @Override 1865 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 1866 mNetworkActivityListeners.unregister(listener); 1867 } 1868 1869 @Override 1870 public boolean isNetworkActive() { 1871 synchronized (mNetworkActivityListeners) { 1872 return mNetworkActive || mActiveIdleTimers.isEmpty(); 1873 } 1874 } 1875 1876 private void reportNetworkActive() { 1877 final int length = mNetworkActivityListeners.beginBroadcast(); 1878 try { 1879 for (int i = 0; i < length; i++) { 1880 try { 1881 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 1882 } catch (RemoteException e) { 1883 } catch (RuntimeException e) { 1884 } 1885 } 1886 } finally { 1887 mNetworkActivityListeners.finishBroadcast(); 1888 } 1889 } 1890 1891 /** {@inheritDoc} */ 1892 @Override 1893 public void monitor() { 1894 if (mConnector != null) { 1895 mConnector.monitor(); 1896 } 1897 } 1898 1899 @Override 1900 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1901 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1902 1903 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 1904 mConnector.dump(fd, pw, args); 1905 pw.println(); 1906 1907 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 1908 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); 1909 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); 1910 pw.print("mNetworkActive="); pw.println(mNetworkActive); 1911 1912 synchronized (mQuotaLock) { 1913 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 1914 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 1915 } 1916 1917 synchronized (mUidRejectOnQuota) { 1918 pw.print("UID reject on quota ifaces: ["); 1919 final int size = mUidRejectOnQuota.size(); 1920 for (int i = 0; i < size; i++) { 1921 pw.print(mUidRejectOnQuota.keyAt(i)); 1922 if (i < size - 1) pw.print(","); 1923 } 1924 pw.println("]"); 1925 } 1926 1927 synchronized (mIdleTimerLock) { 1928 pw.println("Idle timers:"); 1929 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 1930 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 1931 IdleTimerParams params = ent.getValue(); 1932 pw.print(" timeout="); pw.print(params.timeout); 1933 pw.print(" type="); pw.print(params.type); 1934 pw.print(" networkCount="); pw.println(params.networkCount); 1935 } 1936 } 1937 1938 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 1939 } 1940 1941 @Override 1942 public void createPhysicalNetwork(int netId) { 1943 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1944 1945 try { 1946 mConnector.execute("network", "create", netId); 1947 } catch (NativeDaemonConnectorException e) { 1948 throw e.rethrowAsParcelableException(); 1949 } 1950 } 1951 1952 @Override 1953 public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) { 1954 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1955 1956 try { 1957 mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0", 1958 secure ? "1" : "0"); 1959 } catch (NativeDaemonConnectorException e) { 1960 throw e.rethrowAsParcelableException(); 1961 } 1962 } 1963 1964 @Override 1965 public void removeNetwork(int netId) { 1966 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1967 1968 try { 1969 mConnector.execute("network", "destroy", netId); 1970 } catch (NativeDaemonConnectorException e) { 1971 throw e.rethrowAsParcelableException(); 1972 } 1973 } 1974 1975 @Override 1976 public void addInterfaceToNetwork(String iface, int netId) { 1977 modifyInterfaceInNetwork("add", "" + netId, iface); 1978 } 1979 1980 @Override 1981 public void removeInterfaceFromNetwork(String iface, int netId) { 1982 modifyInterfaceInNetwork("remove", "" + netId, iface); 1983 } 1984 1985 private void modifyInterfaceInNetwork(String action, String netId, String iface) { 1986 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1987 try { 1988 mConnector.execute("network", "interface", action, netId, iface); 1989 } catch (NativeDaemonConnectorException e) { 1990 throw e.rethrowAsParcelableException(); 1991 } 1992 } 1993 1994 @Override 1995 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 1996 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1997 1998 final Command cmd = new Command("network", "route", "legacy", uid, "add", netId); 1999 2000 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 2001 final LinkAddress la = routeInfo.getDestinationLinkAddress(); 2002 cmd.appendArg(routeInfo.getInterface()); 2003 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); 2004 if (routeInfo.hasGateway()) { 2005 cmd.appendArg(routeInfo.getGateway().getHostAddress()); 2006 } 2007 2008 try { 2009 mConnector.execute(cmd); 2010 } catch (NativeDaemonConnectorException e) { 2011 throw e.rethrowAsParcelableException(); 2012 } 2013 } 2014 2015 @Override 2016 public void setDefaultNetId(int netId) { 2017 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2018 2019 try { 2020 mConnector.execute("network", "default", "set", netId); 2021 } catch (NativeDaemonConnectorException e) { 2022 throw e.rethrowAsParcelableException(); 2023 } 2024 } 2025 2026 @Override 2027 public void clearDefaultNetId() { 2028 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2029 2030 try { 2031 mConnector.execute("network", "default", "clear"); 2032 } catch (NativeDaemonConnectorException e) { 2033 throw e.rethrowAsParcelableException(); 2034 } 2035 } 2036 2037 @Override 2038 public void setPermission(boolean internal, boolean changeNetState, int[] uids) { 2039 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2040 2041 final Command cmd = new Command("network", "permission", "user", "set"); 2042 if (internal) cmd.appendArg(CONNECTIVITY_INTERNAL); 2043 if (changeNetState) cmd.appendArg(CHANGE_NETWORK_STATE); 2044 for (int i=0; i<uids.length; i++) { 2045 cmd.appendArg(uids[i]); 2046 } 2047 2048 try { 2049 mConnector.execute(cmd); 2050 } catch (NativeDaemonConnectorException e) { 2051 throw e.rethrowAsParcelableException(); 2052 } 2053 } 2054 2055 @Override 2056 public void clearPermission(int[] uids) { 2057 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2058 2059 final Command cmd = new Command("network", "permission", "user", "clear"); 2060 for (int i=0; i<uids.length; i++) { 2061 cmd.appendArg(uids[i]); 2062 } 2063 2064 try { 2065 mConnector.execute(cmd); 2066 } catch (NativeDaemonConnectorException e) { 2067 throw e.rethrowAsParcelableException(); 2068 } 2069 } 2070 2071 @Override 2072 public void allowProtect(int uid) { 2073 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2074 2075 try { 2076 mConnector.execute("network", "protect", "allow", uid); 2077 } catch (NativeDaemonConnectorException e) { 2078 throw e.rethrowAsParcelableException(); 2079 } 2080 } 2081 2082 @Override 2083 public void denyProtect(int uid) { 2084 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2085 2086 try { 2087 mConnector.execute("network", "protect", "deny", uid); 2088 } catch (NativeDaemonConnectorException e) { 2089 throw e.rethrowAsParcelableException(); 2090 } 2091 } 2092 2093 @Override 2094 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) { 2095 modifyInterfaceInNetwork("add", "local", iface); 2096 2097 for (RouteInfo route : routes) { 2098 if (!route.isDefaultRoute()) { 2099 modifyRoute("add", "local", route); 2100 } 2101 } 2102 } 2103 2104 @Override 2105 public void removeInterfaceFromLocalNetwork(String iface) { 2106 modifyInterfaceInNetwork("remove", "local", iface); 2107 } 2108 2109 @Override 2110 public void blockAddressFamily(int family, int netId, String iface) { 2111 modifyAddressFamily("add", family, netId, iface); 2112 } 2113 2114 @Override 2115 public void unblockAddressFamily(int family, int netId, String iface) { 2116 modifyAddressFamily("remove", family, netId, iface); 2117 } 2118 2119 private void modifyAddressFamily(String action, int family, int netId, String iface) { 2120 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2121 2122 final Command cmd = new Command("network", "route", action, netId, iface); 2123 2124 if (family == AF_INET) { 2125 cmd.appendArg(Inet4Address.ANY.getHostAddress() + "/0"); 2126 } else if (family == AF_INET6) { 2127 cmd.appendArg(Inet6Address.ANY.getHostAddress() + "/0"); 2128 } else { 2129 throw new IllegalStateException(family + " is neither " + AF_INET + " nor " + AF_INET6); 2130 } 2131 2132 cmd.appendArg("unreachable"); 2133 2134 try { 2135 mConnector.execute(cmd); 2136 } catch (NativeDaemonConnectorException e) { 2137 throw e.rethrowAsParcelableException(); 2138 } 2139 } 2140} 2141