NetworkManagementService.java revision 89b8a2161ab6ad0211df305da1eebd6227a217e6
1873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/* 2873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Copyright (C) 2007 The Android Open Source Project 3873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 4873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * you may not use this file except in compliance with the License. 6873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * You may obtain a copy of the License at 7873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 8873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 10873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Unless required by applicable law or agreed to in writing, software 11873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * See the License for the specific language governing permissions and 14873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * limitations under the License. 15873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 16873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 17873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatpackage com.android.server; 18873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 1947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport static android.Manifest.permission.DUMP; 20350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY; 21b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT; 221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE; 231b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL; 24ae2c1810839430c84e4a1172580d9c4b18f568caJeff Sharkeyimport static android.net.TrafficStats.UID_TETHERING; 25350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_ENABLED; 26a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 271b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 28873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Context; 29873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.pm.PackageManager; 304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehatimport android.net.INetworkManagementEventObserver; 31eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.InterfaceConfiguration; 32ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.LinkAddress; 33eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.NetworkStats; 34ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.NetworkUtils; 3559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport android.net.RouteInfo; 369ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration; 379ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration.KeyMgmt; 38eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.os.Binder; 39873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService; 409a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.SystemClock; 4162dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissenimport android.os.SystemProperties; 42350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport android.provider.Settings; 439ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.util.Log; 448a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 45b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.util.SparseBooleanArray; 46873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 471059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport com.android.internal.net.NetworkStatsFactory; 48b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport com.google.android.collect.Sets; 494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 5059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.BufferedReader; 5159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.DataInputStream; 52873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File; 5347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.FileDescriptor; 549a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.FileInputStream; 559a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.IOException; 569a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.InputStreamReader; 5747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.PrintWriter; 5859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.net.Inet4Address; 59eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.net.InetAddress; 60eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.ArrayList; 61b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.HashSet; 62eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.NoSuchElementException; 63eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.StringTokenizer; 64e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwaltimport java.util.concurrent.CountDownLatch; 65873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 66873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/** 67873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide 68873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 698e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeypublic class NetworkManagementService extends INetworkManagementService.Stub 708e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey implements Watchdog.Monitor { 71eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey private static final String TAG = "NetworkManagementService"; 72cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn private static final boolean DBG = false; 73305bcbf0c961840c4505770d084a1caacc074dbbKenny Root private static final String NETD_TAG = "NetdConnector"; 74305bcbf0c961840c4505770d084a1caacc074dbbKenny Root 7559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private static final int ADD = 1; 7659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private static final int REMOVE = 2; 7759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 788e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey /** 798e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey * Name representing {@link #setGlobalAlert(long)} limit when delivered to 808e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey * {@link INetworkManagementEventObserver#limitReached(String, String)}. 818e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey */ 828e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; 838e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey 84873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdResponseCode { 8512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* Keep in sync with system/netd/ResponseCode.h */ 86873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int InterfaceListResult = 110; 87873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherInterfaceListResult = 111; 88873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherDnsFwdTgtListResult = 112; 8972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public static final int TtyListResult = 113; 90873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 91873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherStatusResult = 210; 92873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int IpFwdStatusResult = 211; 93ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public static final int InterfaceGetCfgResult = 213; 94e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int SoftapStatusResult = 214; 9591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceRxCounterResult = 216; 9691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceTxCounterResult = 217; 9791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceRxThrottleResult = 218; 9891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceTxThrottleResult = 219; 99cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey public static final int QuotaCounterResult = 220; 100cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey public static final int TetheringStatsResult = 221; 101e325392c257a5460de6327420c81729f4e687881Robert Greenwalt 102e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int InterfaceChange = 600; 10312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall public static final int BandwidthControl = 601; 104873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 105873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 106873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 107873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Binder context for this service 108873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 109873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private Context mContext; 110873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 111873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 112873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * connector object for communicating with netd 113873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 114873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private NativeDaemonConnector mConnector; 115873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 116e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt private Thread mThread; 117e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt private final CountDownLatch mConnectedSignal = new CountDownLatch(1); 118e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 11941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: replace with RemoteCallbackList 1204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private ArrayList<INetworkManagementEventObserver> mObservers; 1214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1221059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory(); 1231059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey 12441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private Object mQuotaLock = new Object(); 125b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** Set of interfaces with active quotas. */ 12641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet(); 12741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Set of interfaces with active alerts. */ 12841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<String> mActiveAlertIfaces = Sets.newHashSet(); 129b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** Set of UIDs with active reject rules. */ 130b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); 131b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 132fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey private volatile boolean mBandwidthControlEnabled; 133350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 134873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 135873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Constructs a new NetworkManagementService instance 136873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 137873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @param context Binder context for this service 138873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 1391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey private NetworkManagementService(Context context) { 140873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext = context; 1414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers = new ArrayList<INetworkManagementEventObserver>(); 1424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 14362dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 14462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen return; 14562dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen } 14662dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen 147873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector = new NativeDaemonConnector( 148305bcbf0c961840c4505770d084a1caacc074dbbKenny Root new NetdCallbackReceiver(), "netd", 10, NETD_TAG); 149e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt mThread = new Thread(mConnector, NETD_TAG); 150fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey 151fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey // Add ourself to the Watchdog monitors. 152fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey Watchdog.getInstance().addMonitor(this); 153e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt } 154e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 155e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt public static NetworkManagementService create(Context context) throws InterruptedException { 1561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey NetworkManagementService service = new NetworkManagementService(context); 157e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 158e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt service.mThread.start(); 159e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Awaiting socket connection"); 160e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt service.mConnectedSignal.await(); 161e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Connected"); 162e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt return service; 163873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 164873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 165350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey public void systemReady() { 166350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // only enable bandwidth control when support exists, and requested by 167350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // system setting. 168350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 169350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final boolean shouldEnable = 17005355c3eb69ef2cd8d08260be059be006a2883b9Jeff Sharkey Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0; 171350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 172350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (hasKernelSupport && shouldEnable) { 173350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey Slog.d(TAG, "enabling bandwidth control"); 174350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey try { 175350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mConnector.doCommand("bandwidth enable"); 176350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mBandwidthControlEnabled = true; 177350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } catch (NativeDaemonConnectorException e) { 1781059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey Log.wtf(TAG, "problem enabling bandwidth controls", e); 179350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 180350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } else { 181350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey Slog.d(TAG, "not enabling bandwidth control"); 182350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 18362a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey 184a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 185350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 186350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 1874d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void registerObserver(INetworkManagementEventObserver obs) { 1888a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Registering observer"); 1894d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.add(obs); 1904d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1914d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1924d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void unregisterObserver(INetworkManagementEventObserver obs) { 1938a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Unregistering observer"); 1944d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.remove(mObservers.indexOf(obs)); 1954d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1964d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1974d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 1986143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen * Notify our observers of an interface status change 1994d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2006143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen private void notifyInterfaceStatusChanged(String iface, boolean up) { 2014d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2024d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2036143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen obs.interfaceStatusChanged(iface, up); 2046143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } catch (Exception ex) { 2056143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen Slog.w(TAG, "Observer notifier failed", ex); 2066143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2076143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2086143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2096143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen 2106143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen /** 211f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen * Notify our observers of an interface link state change 2126143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen * (typically, an Ethernet cable has been plugged-in or unplugged). 2136143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen */ 2146143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 2156143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen for (INetworkManagementEventObserver obs : mObservers) { 2166143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen try { 2176143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen obs.interfaceLinkStateChanged(iface, up); 2184d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2198a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2224d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2234d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2244d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2254d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface addition. 2264d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2274d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceAdded(String iface) { 2284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceAdded(iface); 2314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2328a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface removal. 2394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceRemoved(String iface) { 24189b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey // netd already clears out quota and alerts for removed ifaces; update 24289b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey // our sanity-checking state. 24389b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey mActiveAlertIfaces.remove(iface); 24489b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey mActiveQuotaIfaces.remove(iface); 24589b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey 2464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2484d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceRemoved(iface); 2494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2508a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2534d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2544d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 255e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt /** 25612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Notify our observers of a limit reached. 25712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 25812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall private void notifyLimitReached(String limitName, String iface) { 25912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall for (INetworkManagementEventObserver obs : mObservers) { 26012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall try { 26112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall obs.limitReached(limitName, iface); 26212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } catch (Exception ex) { 26312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall Slog.w(TAG, "Observer notifier failed", ex); 26412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 26512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 26612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 26712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall 26812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /** 269e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt * Let us know the daemon is connected 270e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt */ 271fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey protected void onDaemonConnected() { 272e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "onConnected"); 273e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt mConnectedSignal.countDown(); 274e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt } 275e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 2764d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 277873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 278873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // Netd Callback handling 279873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 280873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 281873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 282fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey /** {@inheritDoc} */ 283873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void onDaemonConnected() { 284fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey NetworkManagementService.this.onDaemonConnected(); 285873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 286fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey 287fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey /** {@inheritDoc} */ 288873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean onEvent(int code, String raw, String[] cooked) { 28912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall switch (code) { 29012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall case NetdResponseCode.InterfaceChange: 29112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* 29212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * a network interface change occured 29312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Format: "NNN Iface added <name>" 29412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface removed <name>" 29512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface changed <name> <up/down>" 29612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface linkstatus <name> <up/down>" 29712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 29812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked.length < 4 || !cooked[1].equals("Iface")) { 29912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 30012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 30112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 30212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked[2].equals("added")) { 30312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceAdded(cooked[3]); 30412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 30512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("removed")) { 30612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceRemoved(cooked[3]); 30712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 30812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("changed") && cooked.length == 5) { 30912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 31012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 31112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 31212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 31312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 31412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 315e325392c257a5460de6327420c81729f4e687881Robert Greenwalt throw new IllegalStateException( 316e325392c257a5460de6327420c81729f4e687881Robert Greenwalt String.format("Invalid event from daemon (%s)", raw)); 31712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall // break; 31812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall case NetdResponseCode.BandwidthControl: 31912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* 32012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Bandwidth control needs some attention 32112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Format: "NNN limit alert <alertName> <ifaceName>" 32212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 32312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked.length < 5 || !cooked[1].equals("limit")) { 32412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 32512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 32612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 32712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked[2].equals("alert")) { 32812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyLimitReached(cooked[3], cooked[4]); 32912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 33012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 33112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 33212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 33312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall // break; 33412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall default: break; 335e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } 336e325392c257a5460de6327420c81729f4e687881Robert Greenwalt return false; 337873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 338873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 339873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 340ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 341873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 342873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // INetworkManagementService members 343873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 344873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 345873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listInterfaces() throws IllegalStateException { 346873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 347873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 348873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 349a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 350a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult); 351a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 352a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 353a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Cannot communicate with native daemon to list interfaces"); 354a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 355ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 356ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 357ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException { 358a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 359a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 360a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("interface getcfg " + iface).get(0); 361a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 362a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 363a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Cannot communicate with native daemon to get interface config"); 364a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 3658a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, String.format("rsp <%s>", rsp)); 366ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 3672d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz [flag1 flag2 flag3] 368ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat StringTokenizer st = new StringTokenizer(rsp); 369ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 370a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root InterfaceConfiguration cfg; 371ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 372a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 373a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root int code = Integer.parseInt(st.nextToken(" ")); 374a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (code != NetdResponseCode.InterfaceGetCfgResult) { 375a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 376a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Expected code %d, but got %d", 377a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root NetdResponseCode.InterfaceGetCfgResult, code)); 378a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 379a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NumberFormatException nfe) { 380ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new IllegalStateException( 381a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Invalid response from daemon (%s)", rsp)); 382ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 383ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 384a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root cfg = new InterfaceConfiguration(); 385a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root cfg.hwAddr = st.nextToken(" "); 386ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt InetAddress addr = null; 3872d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt int prefixLength = 0; 388a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 389e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt addr = NetworkUtils.numericToInetAddress(st.nextToken(" ")); 390e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException iae) { 391e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt Slog.e(TAG, "Failed to parse ipaddr", iae); 392a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 393ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 394a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 3952d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt prefixLength = Integer.parseInt(st.nextToken(" ")); 3962d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt } catch (NumberFormatException nfe) { 3972d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt Slog.e(TAG, "Failed to parse prefixLength", nfe); 398a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 39904808c294027f8bc318643a94c85a999257d7f52Robert Greenwalt 4002d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt cfg.addr = new LinkAddress(addr, prefixLength); 401a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root cfg.interfaceFlags = st.nextToken("]").trim() +"]"; 402a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NoSuchElementException nsee) { 403a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 404a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Invalid response from daemon (%s)", rsp)); 405ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 4068a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, String.format("flags <%s>", cfg.interfaceFlags)); 407ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return cfg; 408ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 409ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 410ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public void setInterfaceConfig( 411ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String iface, InterfaceConfiguration cfg) throws IllegalStateException { 412ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt LinkAddress linkAddr = cfg.addr; 4132d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt if (linkAddr == null || linkAddr.getAddress() == null) { 4142d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt throw new IllegalStateException("Null LinkAddress given"); 415ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt } 4162d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt String cmd = String.format("interface setcfg %s %s %d %s", iface, 4172d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt linkAddr.getAddress().getHostAddress(), 4182d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt linkAddr.getNetworkPrefixLength(), 4192d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt cfg.interfaceFlags); 420a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 421a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 422a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 423a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 42481d5ad515a9379432b2907aa9bcc830303202c84Robert Greenwalt "Unable to communicate with native daemon to interface setcfg - " + e); 425a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 426873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 427873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 4287244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff public void setInterfaceDown(String iface) throws IllegalStateException { 4297244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff try { 4307244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff InterfaceConfiguration ifcg = getInterfaceConfig(iface); 4317244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); 4327244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff setInterfaceConfig(iface, ifcg); 4337244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } catch (NativeDaemonConnectorException e) { 4347244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff throw new IllegalStateException( 4357244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff "Unable to communicate with native daemon for interface down - " + e); 4367244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4377244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4387244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff 4397244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff public void setInterfaceUp(String iface) throws IllegalStateException { 4407244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff try { 4417244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff InterfaceConfiguration ifcg = getInterfaceConfig(iface); 4427244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); 4437244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff setInterfaceConfig(iface, ifcg); 4447244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } catch (NativeDaemonConnectorException e) { 4457244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff throw new IllegalStateException( 4467244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff "Unable to communicate with native daemon for interface up - " + e); 4477244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4487244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4497244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff 4507329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) 4517329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff throws IllegalStateException { 4527329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff String cmd = String.format("interface ipv6privacyextensions %s %s", iface, 4537329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff enable ? "enable" : "disable"); 4547329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff try { 4557329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff mConnector.doCommand(cmd); 4567329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff } catch (NativeDaemonConnectorException e) { 4577329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff throw new IllegalStateException( 4587329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff "Unable to communicate with native daemon to set ipv6privacyextensions - " + e); 4597329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff } 4607329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff } 4617329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff 4627329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff 4637329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff 464f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 465f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff IPv6 addresses on interface down, but we need to do full clean up here */ 466f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff public void clearInterfaceAddresses(String iface) throws IllegalStateException { 467f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff String cmd = String.format("interface clearaddrs %s", iface); 468f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff try { 469f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff mConnector.doCommand(cmd); 470f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } catch (NativeDaemonConnectorException e) { 471f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff throw new IllegalStateException( 472f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff "Unable to communicate with native daemon to interface clearallips - " + e); 473f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } 474f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } 475f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff 4767960d9f888e31602e17b8856c77a3826bf8c841erepo sync public void enableIpv6(String iface) throws IllegalStateException { 4777960d9f888e31602e17b8856c77a3826bf8c841erepo sync mContext.enforceCallingOrSelfPermission( 4787960d9f888e31602e17b8856c77a3826bf8c841erepo sync android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 4797960d9f888e31602e17b8856c77a3826bf8c841erepo sync try { 4807960d9f888e31602e17b8856c77a3826bf8c841erepo sync mConnector.doCommand(String.format("interface ipv6 %s enable", iface)); 4817960d9f888e31602e17b8856c77a3826bf8c841erepo sync } catch (NativeDaemonConnectorException e) { 4827960d9f888e31602e17b8856c77a3826bf8c841erepo sync throw new IllegalStateException( 4837960d9f888e31602e17b8856c77a3826bf8c841erepo sync "Unable to communicate to native daemon for enabling ipv6"); 4847960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 4857960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 4867960d9f888e31602e17b8856c77a3826bf8c841erepo sync 4877960d9f888e31602e17b8856c77a3826bf8c841erepo sync public void disableIpv6(String iface) throws IllegalStateException { 4887960d9f888e31602e17b8856c77a3826bf8c841erepo sync mContext.enforceCallingOrSelfPermission( 4897960d9f888e31602e17b8856c77a3826bf8c841erepo sync android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 4907960d9f888e31602e17b8856c77a3826bf8c841erepo sync try { 4917960d9f888e31602e17b8856c77a3826bf8c841erepo sync mConnector.doCommand(String.format("interface ipv6 %s disable", iface)); 4927960d9f888e31602e17b8856c77a3826bf8c841erepo sync } catch (NativeDaemonConnectorException e) { 4937960d9f888e31602e17b8856c77a3826bf8c841erepo sync throw new IllegalStateException( 4947960d9f888e31602e17b8856c77a3826bf8c841erepo sync "Unable to communicate to native daemon for disabling ipv6"); 4957960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 4967960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 4977960d9f888e31602e17b8856c77a3826bf8c841erepo sync 49859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public void addRoute(String interfaceName, RouteInfo route) { 49959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt modifyRoute(interfaceName, ADD, route); 50059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 50159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 50259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public void removeRoute(String interfaceName, RouteInfo route) { 50359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt modifyRoute(interfaceName, REMOVE, route); 50459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 50559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 50659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private void modifyRoute(String interfaceName, int action, RouteInfo route) { 50759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<String> rsp; 50859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 50959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt StringBuilder cmd; 51059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 51159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt switch (action) { 51259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt case ADD: 51359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt { 51459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd = new StringBuilder("interface route add " + interfaceName); 51559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt break; 51659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 51759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt case REMOVE: 51859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt { 51959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd = new StringBuilder("interface route remove " + interfaceName); 52059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt break; 52159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 52259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt default: 52359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt throw new IllegalStateException("Unknown action type " + action); 52459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 52559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 52659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // create triplet: dest-ip-addr prefixlength gateway-ip-addr 52759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress la = route.getDestination(); 52859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 52959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(la.getAddress().getHostAddress()); 53059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 53159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(la.getNetworkPrefixLength()); 53259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 53359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (route.getGateway() == null) { 53459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (la.getAddress() instanceof Inet4Address) { 53559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append("0.0.0.0"); 53659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } else { 53759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append ("::0"); 53859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 53959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } else { 54059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(route.getGateway().getHostAddress()); 54159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 54259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 54359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt rsp = mConnector.doCommand(cmd.toString()); 54459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (NativeDaemonConnectorException e) { 54559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt throw new IllegalStateException( 54659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt "Unable to communicate with native dameon to add routes - " 54759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt + e); 54859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 54959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 550c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville if (DBG) { 551c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville for (String line : rsp) { 552c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville Log.v(TAG, "add route response is " + line); 553c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville } 55459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 55559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 55659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 55759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private ArrayList<String> readRouteList(String filename) { 55859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt FileInputStream fstream = null; 55959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<String> list = new ArrayList<String>(); 56059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 56159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 56259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt fstream = new FileInputStream(filename); 56359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt DataInputStream in = new DataInputStream(fstream); 56459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt BufferedReader br = new BufferedReader(new InputStreamReader(in)); 56559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String s; 56659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 56759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // throw away the title line 56859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 56959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt while (((s = br.readLine()) != null) && (s.length() != 0)) { 57059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt list.add(s); 57159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 57259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (IOException ex) { 57359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // return current list, possibly empty 57459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } finally { 57559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fstream != null) { 57659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 57759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt fstream.close(); 57859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (IOException ex) {} 57959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 58059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 58159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 58259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt return list; 58359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 58459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 58559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public RouteInfo[] getRoutes(String interfaceName) { 58659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 58759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 58859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // v4 routes listed as: 58959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 59059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt for (String s : readRouteList("/proc/net/route")) { 59159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String[] fields = s.split("\t"); 59259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 59359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fields.length > 7) { 59459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String iface = fields[0]; 59559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 59659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (interfaceName.equals(iface)) { 59759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String dest = fields[1]; 59859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String gate = fields[2]; 59959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String flags = fields[3]; // future use? 60059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String mask = fields[7]; 60159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 60259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a hex string, ex: 0014A8C0 60359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress destAddr = 60459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 60559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt int prefixLength = 60659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.netmaskIntToPrefixLength( 60759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt (int)Long.parseLong(mask, 16)); 60859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 60959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 61059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a hex string, ex 0014A8C0 61159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress gatewayAddr = 61259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 61359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 61459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 61559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt routes.add(route); 61659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (Exception e) { 61759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt Log.e(TAG, "Error parsing route " + s + " : " + e); 61859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt continue; 61959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 62059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 62159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 62259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 62359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 62459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // v6 routes listed as: 62559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 62659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt for (String s : readRouteList("/proc/net/ipv6_route")) { 62759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String[]fields = s.split("\\s+"); 62859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fields.length > 9) { 62959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String iface = fields[9].trim(); 63059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (interfaceName.equals(iface)) { 63159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String dest = fields[0]; 63259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String prefix = fields[1]; 63359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String gate = fields[4]; 63459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 63559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 63659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // prefix length stored as a hex string, ex 40 63759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt int prefixLength = Integer.parseInt(prefix, 16); 63859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 63959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a 32 char hex string 64059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // ex fe800000000000000000000000000000 64159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 64259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 64359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 64459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 64559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 64659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt RouteInfo route = new RouteInfo(linkAddress, gateAddr); 64759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt routes.add(route); 64859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (Exception e) { 64959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt Log.e(TAG, "Error parsing route " + s + " : " + e); 65059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt continue; 65159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 65259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 65359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 65459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 65559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt return (RouteInfo[]) routes.toArray(new RouteInfo[0]); 65659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 65759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 658873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void shutdown() { 659873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (mContext.checkCallingOrSelfPermission( 660873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.SHUTDOWN) 661873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat != PackageManager.PERMISSION_GRANTED) { 662873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new SecurityException("Requires SHUTDOWN permission"); 663873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 664873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 6658a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Shutting down"); 666873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 667873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 668873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean getIpForwardingEnabled() throws IllegalStateException{ 669873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 670873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 671873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 672a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root ArrayList<String> rsp; 673a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 674a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("ipfwd status"); 675a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 676a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 677a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate with native daemon to ipfwd status"); 678a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 679873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 680873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 681a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = line.split(" "); 682a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 3) { 683a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Malformed response from native daemon: " + line); 684a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return false; 685a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 686a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 687873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 688873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.IpFwdStatusResult) { 689873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 211 Forwarding <enabled/disabled> 690a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return "enabled".equals(tok[2]); 691873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 692873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 693873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 694873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 695873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 696873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 697873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 698873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setIpForwardingEnabled(boolean enable) throws IllegalStateException { 699873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 700873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 701873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis"))); 702873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 703873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 704bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt public void startTethering(String[] dhcpRange) 705873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 706873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 707873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 708bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt // cmd is "tether start first_start first_stop second_start second_stop ..." 709bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt // an odd number of addrs will fail 710bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt String cmd = "tether start"; 711bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt for (String d : dhcpRange) { 712bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt cmd += " " + d; 713bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt } 714a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 715a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 716a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 717a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 718a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Unable to communicate to native daemon"); 719a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 720873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 721873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 722873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void stopTethering() throws IllegalStateException { 723873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 724873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 725a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 726a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether stop"); 727a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 728a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Unable to communicate to native daemon to stop tether"); 729a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 730873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 731873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 732873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean isTetheringStarted() throws IllegalStateException { 733873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 734873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 735873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 736a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root ArrayList<String> rsp; 737a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 738a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("tether status"); 739a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 740a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 741a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon to get tether status"); 742a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 743873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 744873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 745a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = line.split(" "); 746a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 3) { 747a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Malformed response for tether status: " + line); 748a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 749873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 750873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.TetherStatusResult) { 751873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // XXX: Tethering services <started/stopped> <TBD>... 752a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return "started".equals(tok[2]); 753873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 754873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 755873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 756873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 757873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 758873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 759873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 760873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void tetherInterface(String iface) throws IllegalStateException { 761873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 762873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 763a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 764a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether interface add " + iface); 765a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 766a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 767a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for adding tether interface"); 768a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 769873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 770873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 771873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void untetherInterface(String iface) { 772873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 773873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 774a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 775a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether interface remove " + iface); 776a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 777a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 778a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for removing tether interface"); 779a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 780873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 781873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 782873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listTetheredInterfaces() throws IllegalStateException { 783873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 784873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 785a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 786a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand( 787a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "tether interface list", NetdResponseCode.TetherInterfaceListResult); 788a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 789a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 790a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for listing tether interfaces"); 791a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 792873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 793873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 794873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setDnsForwarders(String[] dns) throws IllegalStateException { 795873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 796873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 797873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat try { 798d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String cmd = "tether dns set"; 799873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String s : dns) { 800e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt cmd += " " + NetworkUtils.numericToInetAddress(s).getHostAddress(); 801873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 802a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 803a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 804a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 805a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 806a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for setting tether dns"); 807a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 808e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException e) { 809873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Error resolving dns name", e); 810873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 811873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 812873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 813873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] getDnsForwarders() throws IllegalStateException { 814873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 815873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 816a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 817a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand( 818a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult); 819a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 820a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 821a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for listing tether dns"); 822a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 823873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 824873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 825873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void enableNat(String internalInterface, String externalInterface) 826873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 827873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 828873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 829a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 830a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand( 831a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("nat enable %s %s", internalInterface, externalInterface)); 832a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 833a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 834a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for enabling NAT interface"); 835a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 836873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 837873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 838873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void disableNat(String internalInterface, String externalInterface) 839873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 840873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 841873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 842a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 843a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand( 844a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("nat disable %s %s", internalInterface, externalInterface)); 845a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 846a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 847a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for disabling NAT interface"); 848a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 849873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 85072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 85172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public String[] listTtys() throws IllegalStateException { 85272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 85372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 854a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 855a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult); 856a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 857a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 858a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for listing TTYs"); 859a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 86072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 86172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 862d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr, 863d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String dns2Addr) throws IllegalStateException { 86472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat try { 86572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 86672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 867d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty, 868e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 869e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 870e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 871e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress())); 872e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException e) { 87372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat throw new IllegalStateException("Error resolving addr", e); 874a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 875a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to attach pppd", e); 87672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 87772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 87872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 87972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public void detachPppd(String tty) throws IllegalStateException { 88072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 88172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 882a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 883a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("pppd detach %s", tty)); 884a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 885a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to detach pppd", e); 886a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 88772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 888ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt 889c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) 8905321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff throws IllegalStateException { 8915321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 8925321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 8935321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 894c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 895a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 896cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff wifiFirmwareReload(wlanIface, "AP"); 897a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap start " + wlanIface)); 898a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (wifiConfig == null) { 899a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); 900a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } else { 901a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root /** 902a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8] 903a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv1 - wlan interface 904a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv2 - softap interface 905a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv3 - SSID 906a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv4 - Security 907a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv5 - Key 908a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv6 - Channel 909a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv7 - Preamble 910a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv8 - Max SCB 911a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root */ 912ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff String str = String.format("softap set " + wlanIface + " " + softapIface + 913ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff " %s %s %s", convertQuotedString(wifiConfig.SSID), 914ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff getSecurityType(wifiConfig), 915ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff convertQuotedString(wifiConfig.preSharedKey)); 916a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(str); 917a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 918a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap startap")); 919a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 920a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to start softap", e); 921a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 9225321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff } 9235321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff 924a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff private String convertQuotedString(String s) { 9257baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff if (s == null) { 9267baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff return s; 9277baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff } 9287baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff /* Replace \ with \\, then " with \" and add quotes at end */ 9297baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"'; 930a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff } 931a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff 932ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff private String getSecurityType(WifiConfiguration wifiConfig) { 933ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff switch (wifiConfig.getAuthType()) { 934ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff case KeyMgmt.WPA_PSK: 935ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "wpa-psk"; 936ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff case KeyMgmt.WPA2_PSK: 937ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "wpa2-psk"; 938ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff default: 939ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "open"; 940ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff } 941ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff } 942ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff 943cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff /* @param mode can be "AP", "STA" or "P2P" */ 944cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff public void wifiFirmwareReload(String wlanIface, String mode) throws IllegalStateException { 945cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff mContext.enforceCallingOrSelfPermission( 946cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 947cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff mContext.enforceCallingOrSelfPermission( 948cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 949cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff 950cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff try { 951cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff mConnector.doCommand(String.format("softap fwreload " + wlanIface + " " + mode)); 952cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } catch (NativeDaemonConnectorException e) { 953cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff throw new IllegalStateException("Error communicating to native daemon ", e); 954cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } 955cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } 956cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff 95723eb297c771bd996fe8559178feb1a07be43ad72Irfan Sheriff public void stopAccessPoint(String wlanIface) throws IllegalStateException { 9585321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 9595321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 9605321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 961c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 962a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 963a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("softap stopap"); 96423eb297c771bd996fe8559178feb1a07be43ad72Irfan Sheriff mConnector.doCommand("softap stop " + wlanIface); 965cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff wifiFirmwareReload(wlanIface, "STA"); 966a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 967a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to stop soft AP", 968a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root e); 969a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 9705321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff } 9715321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff 972c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) 973c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff throws IllegalStateException { 974c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff mContext.enforceCallingOrSelfPermission( 975c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 976c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff mContext.enforceCallingOrSelfPermission( 977c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 978a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 979a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (wifiConfig == null) { 980a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); 981a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } else { 982a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String str = String.format("softap set " + wlanIface + " " + softapIface 983a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root + " %s %s %s", convertQuotedString(wifiConfig.SSID), 984ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff getSecurityType(wifiConfig), 985a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root convertQuotedString(wifiConfig.preSharedKey)); 986a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(str); 987a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 988a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 989a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to set soft AP", 990a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root e); 991c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff } 992c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff } 99391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 99491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat private long getInterfaceCounter(String iface, boolean rx) { 99591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat mContext.enforceCallingOrSelfPermission( 99691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 99791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 998a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 999a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1000a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand( 1001a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0); 1002a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e1) { 1003a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Error communicating with native daemon", e1); 1004a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1005a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1006a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 1007a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = rsp.split(" "); 1008a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 2) { 1009a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, String.format("Malformed response for reading %s interface", 1010a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root (rx ? "rx" : "tx"))); 1011a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1012a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1013a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 101491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat int code; 101591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 101691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat code = Integer.parseInt(tok[0]); 101791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (NumberFormatException nfe) { 101891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Error parsing code %s", tok[0])); 101991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 102091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 102191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat if ((rx && code != NetdResponseCode.InterfaceRxCounterResult) || ( 102291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat !rx && code != NetdResponseCode.InterfaceTxCounterResult)) { 102391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Unexpected response code %d", code)); 102491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 102591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 102691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return Long.parseLong(tok[1]); 102791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (Exception e) { 102891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format( 102991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat "Failed to read interface %s counters", (rx ? "rx" : "tx")), e); 103091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 103191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 103291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 103391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1034eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 10359a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats getNetworkStatsSummary() { 10369a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey mContext.enforceCallingOrSelfPermission( 10379a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 10381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey return mStatsFactory.readNetworkStatsSummary(); 103991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 104091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1041eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 10429a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats getNetworkStatsDetail() { 10439a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey mContext.enforceCallingOrSelfPermission( 10449a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 10451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey return mStatsFactory.readNetworkStatsDetail(UID_ALL); 104691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 104791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1048eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 104941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setInterfaceQuota(String iface, long quotaBytes) { 1050b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1051b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1052350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1053350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1054350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1055350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 105641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 105741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (mActiveQuotaIfaces.contains(iface)) { 105841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("iface " + iface + " already has quota"); 1059b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1060b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1061b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 106241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes); 1063b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1064b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 106541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support quota shared across interfaces 1066b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 106741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveQuotaIfaces.add(iface); 1068b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1069b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 1070b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 107150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 107250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 107350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 107450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma @Override 1075b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey public void removeInterfaceQuota(String iface) { 1076b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1077b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1078350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1079350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1080350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1081350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 108241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 108341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveQuotaIfaces.contains(iface)) { 1084b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: eventually consider throwing 1085b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey return; 1086b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1087b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1088b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 1089b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append("bandwidth removeiquota ").append(iface); 1090b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1091b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 109241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support quota shared across interfaces 1093b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 109441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveQuotaIfaces.remove(iface); 109541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.remove(iface); 1096b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1097b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 1098b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1099b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1100b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1101b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1102b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey @Override 110341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setInterfaceAlert(String iface, long alertBytes) { 110441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 110541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 110641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 110741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 110841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 110941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 111041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // quick sanity check 111141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveQuotaIfaces.contains(iface)) { 111241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("setting alert requires existing quota on iface"); 111341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 111441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 111541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 111641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (mActiveAlertIfaces.contains(iface)) { 111741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("iface " + iface + " already has alert"); 111841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 111941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 112041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 112141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setinterfacealert ").append(iface).append(" ").append( 112241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey alertBytes); 112341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 112441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 112541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support alert shared across interfaces 112641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 112741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.add(iface); 112841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 112941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 113041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 113141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 113241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 113341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 113441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 113541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void removeInterfaceAlert(String iface) { 113641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 113741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 113841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 113941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 114041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 114141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 114241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 114341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveAlertIfaces.contains(iface)) { 114441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually consider throwing 114541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return; 114641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 114741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 114841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 114941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth removeinterfacealert ").append(iface); 115041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 115141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 115241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support alert shared across interfaces 115341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 115441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.remove(iface); 115541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 115641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 115741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 115841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 115941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 116041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 116141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 116241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setGlobalAlert(long alertBytes) { 116341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 116441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 116541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 116641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 116741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 116841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 116941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 117041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setglobalalert ").append(alertBytes); 117141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 117241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 117341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 117441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 117541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 117641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 117741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 117841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 117941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 1180b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1181b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1182b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1183350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1184350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1185350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1186350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 1187b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey synchronized (mUidRejectOnQuota) { 1188b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1189b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1190b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: eventually consider throwing 1191b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey return; 1192b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1193b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1194b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 1195b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append("bandwidth"); 1196b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (rejectOnQuotaInterfaces) { 1197b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" addnaughtyapps"); 1198b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } else { 1199b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" removenaughtyapps"); 1200b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1201b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" ").append(uid); 1202b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1203b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 1204b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 1205b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (rejectOnQuotaInterfaces) { 1206b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mUidRejectOnQuota.put(uid, true); 1207b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } else { 1208b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mUidRejectOnQuota.delete(uid); 1209b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1210b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1211b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 1212b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 121350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 121450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 121550fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 121663d27a9233fed934340231f438493746084a681dJeff Sharkey @Override 121763d27a9233fed934340231f438493746084a681dJeff Sharkey public boolean isBandwidthControlEnabled() { 121863d27a9233fed934340231f438493746084a681dJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 121963d27a9233fed934340231f438493746084a681dJeff Sharkey return mBandwidthControlEnabled; 122063d27a9233fed934340231f438493746084a681dJeff Sharkey } 122163d27a9233fed934340231f438493746084a681dJeff Sharkey 122263d27a9233fed934340231f438493746084a681dJeff Sharkey @Override 1223eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey public NetworkStats getNetworkStatsUidDetail(int uid) { 1224eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey if (Binder.getCallingUid() != uid) { 1225eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey mContext.enforceCallingOrSelfPermission( 1226eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 1227eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 12281059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey return mStatsFactory.readNetworkStatsDetail(uid); 1229eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 1230eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 1231cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey @Override 1232cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey public NetworkStats getNetworkStatsTethering(String[] ifacePairs) { 1233cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey mContext.enforceCallingOrSelfPermission( 1234cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 1235cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1236cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (ifacePairs.length % 2 != 0) { 1237cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalArgumentException( 1238cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "unexpected ifacePairs; length=" + ifacePairs.length); 1239cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1240cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1241cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1242cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey for (int i = 0; i < ifacePairs.length; i += 2) { 1243cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String ifaceIn = ifacePairs[i]; 1244cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String ifaceOut = ifacePairs[i + 1]; 1245cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (ifaceIn != null && ifaceOut != null) { 1246cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut)); 1247cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1248cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1249cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey return stats; 1250cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1251cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1252cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) { 1253cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final StringBuilder command = new StringBuilder(); 1254cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut); 1255cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1256cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String rsp; 1257cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey try { 1258cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey rsp = mConnector.doCommand(command.toString()).get(0); 1259cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } catch (NativeDaemonConnectorException e) { 1260cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 1261cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1262cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1263cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String[] tok = rsp.split(" "); 1264cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey /* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */ 1265cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (tok.length != 7) { 1266cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException("Native daemon returned unexpected result: " + rsp); 1267cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1268cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1269cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final int code; 1270cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey try { 1271cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey code = Integer.parseInt(tok[0]); 1272cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } catch (NumberFormatException e) { 1273cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException( 1274cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut); 1275cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1276cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (code != NetdResponseCode.TetheringStatsResult) { 1277cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException( 1278cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut); 1279cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1280cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1281cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey try { 1282cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry(); 1283cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.iface = ifaceIn; 1284905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.uid = UID_TETHERING; 1285cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.set = SET_DEFAULT; 1286cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.tag = TAG_NONE; 1287cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.rxBytes = Long.parseLong(tok[3]); 1288cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.rxPackets = Long.parseLong(tok[4]); 1289cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.txBytes = Long.parseLong(tok[5]); 1290cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.txPackets = Long.parseLong(tok[6]); 1291cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey return entry; 1292cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } catch (NumberFormatException e) { 1293cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException( 1294cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e); 1295cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1296cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1297cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1298f0db6e1853e929ae3b65501c31ee57c4dfbc767cSan Mehat public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) { 129991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat mContext.enforceCallingOrSelfPermission( 130091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 1301a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1302a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format( 1303a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "interface setthrottle %s %d %d", iface, rxKbps, txKbps)); 1304a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1305a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Error communicating with native daemon to set throttle", e); 1306a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 130791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 130891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 130991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat private int getInterfaceThrottle(String iface, boolean rx) { 131091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat mContext.enforceCallingOrSelfPermission( 131191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 131291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 1313a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 1314a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1315a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand( 1316a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("interface getthrottle %s %s", iface, 1317a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root (rx ? "rx" : "tx"))).get(0); 1318a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1319a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Error communicating with native daemon to getthrottle", e); 1320a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1321a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1322a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 1323a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = rsp.split(" "); 1324a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 2) { 1325a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Malformed response to getthrottle command"); 1326a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1327a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1328a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 132991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat int code; 133091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 133191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat code = Integer.parseInt(tok[0]); 133291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (NumberFormatException nfe) { 133391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Error parsing code %s", tok[0])); 133491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 133591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 133691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat if ((rx && code != NetdResponseCode.InterfaceRxThrottleResult) || ( 133791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat !rx && code != NetdResponseCode.InterfaceTxThrottleResult)) { 133891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Unexpected response code %d", code)); 133991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 134091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 134191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return Integer.parseInt(tok[1]); 134291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (Exception e) { 134391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format( 134491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat "Failed to read interface %s throttle value", (rx ? "rx" : "tx")), e); 134591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 134691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 134791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 134891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 134991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public int getInterfaceRxThrottle(String iface) { 135091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return getInterfaceThrottle(iface, true); 135191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 135291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 135391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public int getInterfaceTxThrottle(String iface) { 135491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return getInterfaceThrottle(iface, false); 135591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 13569a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 13577475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void setDefaultInterfaceForDns(String iface) throws IllegalStateException { 13587475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission( 13597475c0cea622f126af966c3b5b9741f547e83450Mattias Falk android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 13607475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 13617475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver setdefaultif " + iface; 13627475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 13637475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 13647475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 13657475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 13667475c0cea622f126af966c3b5b9741f547e83450Mattias Falk "Error communicating with native daemon to set default interface", e); 13677475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13687475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13697475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 13707475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void setDnsServersForInterface(String iface, String[] servers) 13717475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throws IllegalStateException { 13727475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE, 13737475c0cea622f126af966c3b5b9741f547e83450Mattias Falk "NetworkManagementService"); 13747475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 13757475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver setifdns " + iface; 13767475c0cea622f126af966c3b5b9741f547e83450Mattias Falk for (String s : servers) { 1377572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt InetAddress a = NetworkUtils.numericToInetAddress(s); 1378572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt if (a.isAnyLocalAddress() == false) { 1379572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt cmd += " " + a.getHostAddress(); 13807475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13817475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13827475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 1383572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt } catch (IllegalArgumentException e) { 1384572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt throw new IllegalStateException("Error setting dnsn for interface", e); 13857475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 13867475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 1387572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt "Error communicating with native daemon to set dns for interface", e); 13887475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13897475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13907475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 13917475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void flushDefaultDnsCache() throws IllegalStateException { 13927475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission( 13937475c0cea622f126af966c3b5b9741f547e83450Mattias Falk android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 13947475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 13957475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver flushdefaultif"; 13967475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 13977475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 13987475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 13997475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 14007475c0cea622f126af966c3b5b9741f547e83450Mattias Falk "Error communicating with native deamon to flush default interface", e); 14017475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14027475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14037475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 14047475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void flushInterfaceDnsCache(String iface) throws IllegalStateException { 14057475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission( 14067475c0cea622f126af966c3b5b9741f547e83450Mattias Falk android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 14077475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 14087475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver flushif " + iface; 14097475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 14107475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 14117475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 14127475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 1413572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt "Error communicating with native daemon to flush interface " + iface, e); 14147475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14157475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 1416fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey 1417fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey /** {@inheritDoc} */ 1418fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey public void monitor() { 1419fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey if (mConnector != null) { 1420fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey mConnector.monitor(); 1421fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey } 1422fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey } 142347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 142447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey @Override 142547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 142647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey mContext.enforceCallingOrSelfPermission(DUMP, TAG); 142747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 142847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 142947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 143047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey synchronized (mQuotaLock) { 143147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("Active quota ifaces: "); pw.println(mActiveQuotaIfaces.toString()); 143247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("Active alert ifaces: "); pw.println(mActiveAlertIfaces.toString()); 143347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 143447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 143547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey synchronized (mUidRejectOnQuota) { 143647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("UID reject on quota ifaces: ["); 143747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey final int size = mUidRejectOnQuota.size(); 143847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey for (int i = 0; i < size; i++) { 143947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print(mUidRejectOnQuota.keyAt(i)); 144047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (i < size - 1) pw.print(","); 144147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 144247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.println("]"); 144347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 144447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 1445873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat} 1446