NetworkManagementService.java revision 276642baf11e05700ef24447dc4271f16ce69b50
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 19b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkeyimport static android.Manifest.permission.ACCESS_NETWORK_STATE; 20b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkeyimport static android.Manifest.permission.CHANGE_NETWORK_STATE; 21af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkeyimport static android.Manifest.permission.CHANGE_WIFI_STATE; 2247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport static android.Manifest.permission.DUMP; 23350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY; 24af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkeyimport static android.Manifest.permission.SHUTDOWN; 25b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT; 261b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE; 271b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL; 28ae2c1810839430c84e4a1172580d9c4b18f568caJeff Sharkeyimport static android.net.TrafficStats.UID_TETHERING; 29350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_ENABLED; 30a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 311b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 32873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Context; 334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehatimport android.net.INetworkManagementEventObserver; 34eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.InterfaceConfiguration; 35ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.LinkAddress; 36eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.NetworkStats; 37ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.NetworkUtils; 3859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport android.net.RouteInfo; 399ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration; 409ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration.KeyMgmt; 41eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.os.Binder; 42873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService; 439a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.SystemClock; 4462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissenimport android.os.SystemProperties; 45350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport android.provider.Settings; 469ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.util.Log; 478a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 48b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.util.SparseBooleanArray; 49873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 501059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport com.android.internal.net.NetworkStatsFactory; 51b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport com.google.android.collect.Sets; 524414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 5359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.BufferedReader; 5459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.DataInputStream; 55873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File; 5647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.FileDescriptor; 579a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.FileInputStream; 589a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.IOException; 599a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.InputStreamReader; 6047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.PrintWriter; 6159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.net.Inet4Address; 62eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.net.InetAddress; 633b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.InterfaceAddress; 643b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.NetworkInterface; 653b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.SocketException; 66eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.ArrayList; 673b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.util.Collection; 68b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.HashSet; 69eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.NoSuchElementException; 70eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.StringTokenizer; 71e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwaltimport java.util.concurrent.CountDownLatch; 72873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 73873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/** 74873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide 75873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 768e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeypublic class NetworkManagementService extends INetworkManagementService.Stub 778e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey implements Watchdog.Monitor { 78eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey private static final String TAG = "NetworkManagementService"; 79cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn private static final boolean DBG = false; 80305bcbf0c961840c4505770d084a1caacc074dbbKenny Root private static final String NETD_TAG = "NetdConnector"; 81305bcbf0c961840c4505770d084a1caacc074dbbKenny Root 8259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private static final int ADD = 1; 8359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private static final int REMOVE = 2; 8459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 853b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt private static final String DEFAULT = "default"; 863b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt private static final String SECONDARY = "secondary"; 873b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt 888e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey /** 898e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey * Name representing {@link #setGlobalAlert(long)} limit when delivered to 908e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey * {@link INetworkManagementEventObserver#limitReached(String, String)}. 918e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey */ 928e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; 938e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey 94873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdResponseCode { 9512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* Keep in sync with system/netd/ResponseCode.h */ 96873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int InterfaceListResult = 110; 97873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherInterfaceListResult = 111; 98873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherDnsFwdTgtListResult = 112; 9972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public static final int TtyListResult = 113; 100873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 101873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherStatusResult = 210; 102873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int IpFwdStatusResult = 211; 103ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public static final int InterfaceGetCfgResult = 213; 104e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int SoftapStatusResult = 214; 10591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceRxCounterResult = 216; 10691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceTxCounterResult = 217; 10791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceRxThrottleResult = 218; 10891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceTxThrottleResult = 219; 109cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey public static final int QuotaCounterResult = 220; 110cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey public static final int TetheringStatsResult = 221; 111e325392c257a5460de6327420c81729f4e687881Robert Greenwalt 112e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int InterfaceChange = 600; 11312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall public static final int BandwidthControl = 601; 114873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 115873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 116873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 117873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Binder context for this service 118873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 119873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private Context mContext; 120873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 121873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 122873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * connector object for communicating with netd 123873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 124873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private NativeDaemonConnector mConnector; 125873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 126e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt private Thread mThread; 127e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt private final CountDownLatch mConnectedSignal = new CountDownLatch(1); 128e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 12941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: replace with RemoteCallbackList 1304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private ArrayList<INetworkManagementEventObserver> mObservers; 1314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory(); 1331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey 13441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private Object mQuotaLock = new Object(); 135b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** Set of interfaces with active quotas. */ 13641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet(); 13741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Set of interfaces with active alerts. */ 13841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<String> mActiveAlertIfaces = Sets.newHashSet(); 139b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** Set of UIDs with active reject rules. */ 140b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); 141b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 142fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey private volatile boolean mBandwidthControlEnabled; 143350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 144873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 145873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Constructs a new NetworkManagementService instance 146873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 147873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @param context Binder context for this service 148873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 1491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey private NetworkManagementService(Context context) { 150873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext = context; 1514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers = new ArrayList<INetworkManagementEventObserver>(); 1524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 15362dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 15462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen return; 15562dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen } 15662dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen 157873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector = new NativeDaemonConnector( 158305bcbf0c961840c4505770d084a1caacc074dbbKenny Root new NetdCallbackReceiver(), "netd", 10, NETD_TAG); 159e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt mThread = new Thread(mConnector, NETD_TAG); 160fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey 161fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey // Add ourself to the Watchdog monitors. 162fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey Watchdog.getInstance().addMonitor(this); 163e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt } 164e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 165e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt public static NetworkManagementService create(Context context) throws InterruptedException { 1661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey NetworkManagementService service = new NetworkManagementService(context); 167e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 168e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt service.mThread.start(); 169e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Awaiting socket connection"); 170e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt service.mConnectedSignal.await(); 171e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Connected"); 172e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt return service; 173873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 174873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 175350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey public void systemReady() { 176350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // only enable bandwidth control when support exists, and requested by 177350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // system setting. 178350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 179350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final boolean shouldEnable = 18005355c3eb69ef2cd8d08260be059be006a2883b9Jeff Sharkey Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0; 181350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 182350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (hasKernelSupport && shouldEnable) { 183350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey Slog.d(TAG, "enabling bandwidth control"); 184350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey try { 185350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mConnector.doCommand("bandwidth enable"); 186350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mBandwidthControlEnabled = true; 187350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } catch (NativeDaemonConnectorException e) { 1881059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey Log.wtf(TAG, "problem enabling bandwidth controls", e); 189350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 190350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } else { 191350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey Slog.d(TAG, "not enabling bandwidth control"); 192350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 19362a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey 194a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 195350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 196350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 197af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 1984d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void registerObserver(INetworkManagementEventObserver obs) { 1998a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Registering observer"); 2004d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.add(obs); 2014d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2024d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 203af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 2044d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void unregisterObserver(INetworkManagementEventObserver obs) { 2058a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Unregistering observer"); 2064d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.remove(mObservers.indexOf(obs)); 2074d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2084d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2094d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2106143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen * Notify our observers of an interface status change 2114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2126143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen private void notifyInterfaceStatusChanged(String iface, boolean up) { 2134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2144d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2156143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen obs.interfaceStatusChanged(iface, up); 2166143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } catch (Exception ex) { 2176143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen Slog.w(TAG, "Observer notifier failed", ex); 2186143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2196143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2206143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2216143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen 2226143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen /** 223f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen * Notify our observers of an interface link state change 2246143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen * (typically, an Ethernet cable has been plugged-in or unplugged). 2256143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen */ 2266143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 2276143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen for (INetworkManagementEventObserver obs : mObservers) { 2286143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen try { 2296143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen obs.interfaceLinkStateChanged(iface, up); 2304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2318a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface addition. 2384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceAdded(String iface) { 2404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceAdded(iface); 2434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2448a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2484d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2504d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface removal. 2514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceRemoved(String iface) { 25389b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey // netd already clears out quota and alerts for removed ifaces; update 25489b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey // our sanity-checking state. 25589b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey mActiveAlertIfaces.remove(iface); 25689b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey mActiveQuotaIfaces.remove(iface); 25789b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey 2584d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2594d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2604d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceRemoved(iface); 2614d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2628a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2634d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2644d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2654d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2664d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 267e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt /** 26812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Notify our observers of a limit reached. 26912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 27012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall private void notifyLimitReached(String limitName, String iface) { 27112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall for (INetworkManagementEventObserver obs : mObservers) { 27212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall try { 27312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall obs.limitReached(limitName, iface); 27412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } catch (Exception ex) { 27512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall Slog.w(TAG, "Observer notifier failed", ex); 27612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 27712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 27812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 27912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall 28012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /** 281e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt * Let us know the daemon is connected 282e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt */ 283fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey protected void onDaemonConnected() { 284e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "onConnected"); 285e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt mConnectedSignal.countDown(); 286e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt } 287e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 2884d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 289873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 290873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // Netd Callback handling 291873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 292873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 293873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 294fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey /** {@inheritDoc} */ 295873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void onDaemonConnected() { 296fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey NetworkManagementService.this.onDaemonConnected(); 297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 298fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey 299fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey /** {@inheritDoc} */ 300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean onEvent(int code, String raw, String[] cooked) { 30112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall switch (code) { 30212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall case NetdResponseCode.InterfaceChange: 30312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* 30412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * a network interface change occured 30512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Format: "NNN Iface added <name>" 30612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface removed <name>" 30712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface changed <name> <up/down>" 30812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface linkstatus <name> <up/down>" 30912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 31012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked.length < 4 || !cooked[1].equals("Iface")) { 31112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 31212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 31312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 31412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked[2].equals("added")) { 31512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceAdded(cooked[3]); 31612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 31712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("removed")) { 31812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceRemoved(cooked[3]); 31912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 32012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("changed") && cooked.length == 5) { 32112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 32212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 32312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 32412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 32512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 32612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 327e325392c257a5460de6327420c81729f4e687881Robert Greenwalt throw new IllegalStateException( 328e325392c257a5460de6327420c81729f4e687881Robert Greenwalt String.format("Invalid event from daemon (%s)", raw)); 32912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall // break; 33012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall case NetdResponseCode.BandwidthControl: 33112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* 33212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Bandwidth control needs some attention 33312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Format: "NNN limit alert <alertName> <ifaceName>" 33412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 33512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked.length < 5 || !cooked[1].equals("limit")) { 33612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 33712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 33812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 33912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked[2].equals("alert")) { 34012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyLimitReached(cooked[3], cooked[4]); 34112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 34212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 34312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 34412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 34512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall // break; 34612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall default: break; 347e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } 348e325392c257a5460de6327420c81729f4e687881Robert Greenwalt return false; 349873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 350873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 351873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 352ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 353873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 354873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // INetworkManagementService members 355873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 356873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 357af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 358af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public String[] listInterfaces() { 359af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 360a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 361a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult); 362a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 363276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 364a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 365ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 366ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 367af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 368af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public InterfaceConfiguration getInterfaceConfig(String iface) { 369b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 370a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 371a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 372a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("interface getcfg " + iface).get(0); 373a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 374276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 375a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 3768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, String.format("rsp <%s>", rsp)); 377ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 3782d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz [flag1 flag2 flag3] 379ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat StringTokenizer st = new StringTokenizer(rsp); 380ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 381a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root InterfaceConfiguration cfg; 382ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 383a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 384a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root int code = Integer.parseInt(st.nextToken(" ")); 385a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (code != NetdResponseCode.InterfaceGetCfgResult) { 386a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 387a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Expected code %d, but got %d", 388a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root NetdResponseCode.InterfaceGetCfgResult, code)); 389a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 390a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NumberFormatException nfe) { 391ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new IllegalStateException( 392a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Invalid response from daemon (%s)", rsp)); 393ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 394ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 395a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root cfg = new InterfaceConfiguration(); 396ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey cfg.setHardwareAddress(st.nextToken(" ")); 397ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt InetAddress addr = null; 3982d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt int prefixLength = 0; 399a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 400e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt addr = NetworkUtils.numericToInetAddress(st.nextToken(" ")); 401e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException iae) { 402e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt Slog.e(TAG, "Failed to parse ipaddr", iae); 403a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 404ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 405a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 4062d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt prefixLength = Integer.parseInt(st.nextToken(" ")); 4072d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt } catch (NumberFormatException nfe) { 4082d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt Slog.e(TAG, "Failed to parse prefixLength", nfe); 409a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 41004808c294027f8bc318643a94c85a999257d7f52Robert Greenwalt 411ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 412ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey while (st.hasMoreTokens()) { 413ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey cfg.setFlag(st.nextToken()); 414ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey } 415a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NoSuchElementException nsee) { 416a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 417a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Invalid response from daemon (%s)", rsp)); 418ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 419ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey Slog.d(TAG, String.format("flags <%s>", cfg.getFlags())); 420ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return cfg; 421ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 422ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 423af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 424af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 425b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 426ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey LinkAddress linkAddr = cfg.getLinkAddress(); 4272d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt if (linkAddr == null || linkAddr.getAddress() == null) { 4282d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt throw new IllegalStateException("Null LinkAddress given"); 429ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt } 4302d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt String cmd = String.format("interface setcfg %s %s %d %s", iface, 4312d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt linkAddr.getAddress().getHostAddress(), 4322d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt linkAddr.getNetworkPrefixLength(), 433ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey cfg.getFlags()); 434a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 435a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 436a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 437276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 438a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 439873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 440873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 441af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 442af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setInterfaceDown(String iface) { 443b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 44431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 445ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey ifcg.setInterfaceDown(); 44631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey setInterfaceConfig(iface, ifcg); 4477244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4487244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff 449af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 450af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setInterfaceUp(String iface) { 451b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 45231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 453ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey ifcg.setInterfaceUp(); 45431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey setInterfaceConfig(iface, ifcg); 4557244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4567244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff 457af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 458af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 459b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 4607329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff String cmd = String.format("interface ipv6privacyextensions %s %s", iface, 4617329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff enable ? "enable" : "disable"); 4627329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff try { 4637329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff mConnector.doCommand(cmd); 4647329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff } catch (NativeDaemonConnectorException e) { 465276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 4667329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff } 4677329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff } 4687329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff 469f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 470f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff IPv6 addresses on interface down, but we need to do full clean up here */ 471af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 472af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void clearInterfaceAddresses(String iface) { 473b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 474b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey String cmd = String.format("interface clearaddrs %s", iface); 475f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff try { 476f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff mConnector.doCommand(cmd); 477f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } catch (NativeDaemonConnectorException e) { 478276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 479f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } 480f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } 481f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff 482af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 483af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void enableIpv6(String iface) { 484af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 4857960d9f888e31602e17b8856c77a3826bf8c841erepo sync try { 4867960d9f888e31602e17b8856c77a3826bf8c841erepo sync mConnector.doCommand(String.format("interface ipv6 %s enable", iface)); 4877960d9f888e31602e17b8856c77a3826bf8c841erepo sync } catch (NativeDaemonConnectorException e) { 488276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 4897960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 4907960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 4917960d9f888e31602e17b8856c77a3826bf8c841erepo sync 492af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 493af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void disableIpv6(String iface) { 494af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 4957960d9f888e31602e17b8856c77a3826bf8c841erepo sync try { 4967960d9f888e31602e17b8856c77a3826bf8c841erepo sync mConnector.doCommand(String.format("interface ipv6 %s disable", iface)); 4977960d9f888e31602e17b8856c77a3826bf8c841erepo sync } catch (NativeDaemonConnectorException e) { 498276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 4997960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 5007960d9f888e31602e17b8856c77a3826bf8c841erepo sync } 5017960d9f888e31602e17b8856c77a3826bf8c841erepo sync 502af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 50359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public void addRoute(String interfaceName, RouteInfo route) { 504b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 5053b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt modifyRoute(interfaceName, ADD, route, DEFAULT); 50659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 50759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 508af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 50959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public void removeRoute(String interfaceName, RouteInfo route) { 510b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 5113b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt modifyRoute(interfaceName, REMOVE, route, DEFAULT); 5123b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt } 5133b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt 514af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 5153b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt public void addSecondaryRoute(String interfaceName, RouteInfo route) { 5163b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 5173b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt modifyRoute(interfaceName, ADD, route, SECONDARY); 5183b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt } 5193b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt 520af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 5213b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt public void removeSecondaryRoute(String interfaceName, RouteInfo route) { 5223b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 5233b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt modifyRoute(interfaceName, REMOVE, route, SECONDARY); 52459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 52559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 5263b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt private void modifyRoute(String interfaceName, int action, RouteInfo route, String type) { 52759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<String> rsp; 52859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 52959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt StringBuilder cmd; 53059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 53159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt switch (action) { 53259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt case ADD: 53359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt { 5343b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt cmd = new StringBuilder("interface route add " + interfaceName + " " + type); 53559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt break; 53659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 53759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt case REMOVE: 53859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt { 5393b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt cmd = new StringBuilder("interface route remove " + interfaceName + " " + type); 54059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt break; 54159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 54259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt default: 54359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt throw new IllegalStateException("Unknown action type " + action); 54459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 54559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 54659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // create triplet: dest-ip-addr prefixlength gateway-ip-addr 54759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress la = route.getDestination(); 54859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 54959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(la.getAddress().getHostAddress()); 55059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 55159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(la.getNetworkPrefixLength()); 55259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 55359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (route.getGateway() == null) { 55459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (la.getAddress() instanceof Inet4Address) { 55559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append("0.0.0.0"); 55659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } else { 55759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append ("::0"); 55859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 55959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } else { 56059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(route.getGateway().getHostAddress()); 56159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 56259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 56359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt rsp = mConnector.doCommand(cmd.toString()); 56459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (NativeDaemonConnectorException e) { 565276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 56659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 56759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 568c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville if (DBG) { 569c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville for (String line : rsp) { 570c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville Log.v(TAG, "add route response is " + line); 571c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville } 57259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 57359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 57459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 57559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private ArrayList<String> readRouteList(String filename) { 57659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt FileInputStream fstream = null; 57759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<String> list = new ArrayList<String>(); 57859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 57959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 58059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt fstream = new FileInputStream(filename); 58159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt DataInputStream in = new DataInputStream(fstream); 58259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt BufferedReader br = new BufferedReader(new InputStreamReader(in)); 58359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String s; 58459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 58559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // throw away the title line 58659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 58759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt while (((s = br.readLine()) != null) && (s.length() != 0)) { 58859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt list.add(s); 58959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 59059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (IOException ex) { 59159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // return current list, possibly empty 59259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } finally { 59359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fstream != null) { 59459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 59559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt fstream.close(); 59659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (IOException ex) {} 59759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 59859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 59959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 60059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt return list; 60159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 60259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 603af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 60459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public RouteInfo[] getRoutes(String interfaceName) { 605b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 60659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 60759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 60859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // v4 routes listed as: 60959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 61059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt for (String s : readRouteList("/proc/net/route")) { 61159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String[] fields = s.split("\t"); 61259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 61359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fields.length > 7) { 61459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String iface = fields[0]; 61559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 61659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (interfaceName.equals(iface)) { 61759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String dest = fields[1]; 61859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String gate = fields[2]; 61959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String flags = fields[3]; // future use? 62059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String mask = fields[7]; 62159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 62259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a hex string, ex: 0014A8C0 62359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress destAddr = 62459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 62559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt int prefixLength = 62659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.netmaskIntToPrefixLength( 62759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt (int)Long.parseLong(mask, 16)); 62859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 62959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 63059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a hex string, ex 0014A8C0 63159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress gatewayAddr = 63259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 63359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 63459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 63559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt routes.add(route); 63659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (Exception e) { 63759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt Log.e(TAG, "Error parsing route " + s + " : " + e); 63859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt continue; 63959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 64059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 64159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 64259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 64359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 64459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // v6 routes listed as: 64559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 64659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt for (String s : readRouteList("/proc/net/ipv6_route")) { 64759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String[]fields = s.split("\\s+"); 64859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fields.length > 9) { 64959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String iface = fields[9].trim(); 65059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (interfaceName.equals(iface)) { 65159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String dest = fields[0]; 65259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String prefix = fields[1]; 65359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String gate = fields[4]; 65459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 65559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 65659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // prefix length stored as a hex string, ex 40 65759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt int prefixLength = Integer.parseInt(prefix, 16); 65859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 65959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a 32 char hex string 66059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // ex fe800000000000000000000000000000 66159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 66259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 66359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 66459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 66559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 66659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt RouteInfo route = new RouteInfo(linkAddress, gateAddr); 66759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt routes.add(route); 66859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (Exception e) { 66959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt Log.e(TAG, "Error parsing route " + s + " : " + e); 67059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt continue; 67159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 67259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 67359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 67459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 67559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt return (RouteInfo[]) routes.toArray(new RouteInfo[0]); 67659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 67759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 678af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 679873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void shutdown() { 680af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey // TODO: remove from aidl if nobody calls externally 681af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 682873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 6838a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Shutting down"); 684873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 685873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 686af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 687873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean getIpForwardingEnabled() throws IllegalStateException{ 688af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 689873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 690a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root ArrayList<String> rsp; 691a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 692a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("ipfwd status"); 693a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 694276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 695a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 696873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 697873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 698a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = line.split(" "); 699a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 3) { 700a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Malformed response from native daemon: " + line); 701a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return false; 702a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 703a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 704873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 705873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.IpFwdStatusResult) { 706873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 211 Forwarding <enabled/disabled> 707a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return "enabled".equals(tok[2]); 708873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 709873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 710873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 711873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 712873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 713873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 714873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 715af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 716af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setIpForwardingEnabled(boolean enable) { 717af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 71831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey try { 71931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis"))); 72031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } catch (NativeDaemonConnectorException e) { 721276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 72231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 723873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 724873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 725af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 726af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void startTethering(String[] dhcpRange) { 727af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 728bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt // cmd is "tether start first_start first_stop second_start second_stop ..." 729bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt // an odd number of addrs will fail 730bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt String cmd = "tether start"; 731bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt for (String d : dhcpRange) { 732bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt cmd += " " + d; 733bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt } 734a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 735a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 736a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 737a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 738276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 739a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 740873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 741873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 742af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 743af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void stopTethering() { 744af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 745a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 746a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether stop"); 747a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 748276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 749a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 750873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 751873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 752af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 753af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public boolean isTetheringStarted() { 754af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 755873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 756a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root ArrayList<String> rsp; 757a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 758a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("tether status"); 759a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 760276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 761a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 762873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 763873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 764a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = line.split(" "); 765a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 3) { 766a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Malformed response for tether status: " + line); 767a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 768873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 769873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.TetherStatusResult) { 770873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // XXX: Tethering services <started/stopped> <TBD>... 771a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return "started".equals(tok[2]); 772873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 773873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 774873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 775873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 776873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 777873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 778873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 779af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 780af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void tetherInterface(String iface) { 781af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 782a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 783a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether interface add " + iface); 784a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 785276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 786a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 787873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 788873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 789af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 790873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void untetherInterface(String iface) { 791af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 792a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 793a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether interface remove " + iface); 794a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 795276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 796a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 797873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 798873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 799af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 800af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public String[] listTetheredInterfaces() { 801af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 802a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 803a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand( 804a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "tether interface list", NetdResponseCode.TetherInterfaceListResult); 805a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 806276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 807a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 808873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 809873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 810af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 811af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setDnsForwarders(String[] dns) { 812af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 813873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat try { 814d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String cmd = "tether dns set"; 815873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String s : dns) { 816e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt cmd += " " + NetworkUtils.numericToInetAddress(s).getHostAddress(); 817873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 818a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 819a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 820a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 821276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 822a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 823e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException e) { 824873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Error resolving dns name", e); 825873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 826873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 827873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 828af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 829af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public String[] getDnsForwarders() { 830af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 831a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 832a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand( 833a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult); 834a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 835276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 836a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 837873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 838873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 8393b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt private void modifyNat(String cmd, String internalInterface, String externalInterface) 8403b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt throws SocketException { 8413b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt cmd = String.format("nat %s %s %s", cmd, internalInterface, externalInterface); 8423b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt 8433b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt NetworkInterface internalNetworkInterface = 8443b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt NetworkInterface.getByName(internalInterface); 845e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt if (internalNetworkInterface == null) { 846e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt cmd += " 0"; 847e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt } else { 848e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt Collection<InterfaceAddress>interfaceAddresses = 849e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt internalNetworkInterface.getInterfaceAddresses(); 850e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt cmd += " " + interfaceAddresses.size(); 851e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt for (InterfaceAddress ia : interfaceAddresses) { 852e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(), 853e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt ia.getNetworkPrefixLength()); 854e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength(); 855e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt } 8563b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt } 8573b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt 85831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey try { 85931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mConnector.doCommand(cmd); 86031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } catch (NativeDaemonConnectorException e) { 861276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 86231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 8633b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt } 8643b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt 865af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 866af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void enableNat(String internalInterface, String externalInterface) { 867af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 8683b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt if (DBG) Log.d(TAG, "enableNat(" + internalInterface + ", " + externalInterface + ")"); 869a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 8703b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt modifyNat("enable", internalInterface, externalInterface); 8713b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt } catch (Exception e) { 8723b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt Log.e(TAG, "enableNat got Exception " + e.toString()); 873a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 874a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for enabling NAT interface"); 875a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 876873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 877873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 878af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 879af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void disableNat(String internalInterface, String externalInterface) { 880af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 8813b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt if (DBG) Log.d(TAG, "disableNat(" + internalInterface + ", " + externalInterface + ")"); 882a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 8833b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt modifyNat("disable", internalInterface, externalInterface); 8843b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt } catch (Exception e) { 8853b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt Log.e(TAG, "disableNat got Exception " + e.toString()); 886a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 887a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for disabling NAT interface"); 888a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 889873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 89072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 891af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 892af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public String[] listTtys() { 893af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 894a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 895a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult); 896a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 897276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 898a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 89972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 90072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 901af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 902af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void attachPppd( 903af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 904af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 90572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat try { 906d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty, 907e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 908e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 909e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 910e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress())); 911e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException e) { 91272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat throw new IllegalStateException("Error resolving addr", e); 913a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 914276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 91572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 91672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 91772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 918af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 919af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void detachPppd(String tty) { 920af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 921a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 922a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("pppd detach %s", tty)); 923a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 924276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 925a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 92672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 927ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt 928af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 929af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void startAccessPoint( 930af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey WifiConfiguration wifiConfig, String wlanIface, String softapIface) { 931af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 932af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG); 933a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 934cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff wifiFirmwareReload(wlanIface, "AP"); 935a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap start " + wlanIface)); 936a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (wifiConfig == null) { 937a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); 938a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } else { 939a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root /** 940a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8] 941a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv1 - wlan interface 942a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv2 - softap interface 943a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv3 - SSID 944a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv4 - Security 945a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv5 - Key 946a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv6 - Channel 947a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv7 - Preamble 948a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv8 - Max SCB 949a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root */ 950ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff String str = String.format("softap set " + wlanIface + " " + softapIface + 951ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff " %s %s %s", convertQuotedString(wifiConfig.SSID), 952ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff getSecurityType(wifiConfig), 953ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff convertQuotedString(wifiConfig.preSharedKey)); 954a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(str); 955a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 956a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap startap")); 957a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 958276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 959a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 9605321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff } 9615321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff 962a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff private String convertQuotedString(String s) { 9637baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff if (s == null) { 9647baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff return s; 9657baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff } 9667baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff /* Replace \ with \\, then " with \" and add quotes at end */ 9677baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"'; 968a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff } 969a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff 970ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff private String getSecurityType(WifiConfiguration wifiConfig) { 971ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff switch (wifiConfig.getAuthType()) { 972ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff case KeyMgmt.WPA_PSK: 973ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "wpa-psk"; 974ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff case KeyMgmt.WPA2_PSK: 975ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "wpa2-psk"; 976ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff default: 977ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "open"; 978ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff } 979ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff } 980ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff 981cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff /* @param mode can be "AP", "STA" or "P2P" */ 982af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 983af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void wifiFirmwareReload(String wlanIface, String mode) { 984af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 985af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG); 986cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff try { 987cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff mConnector.doCommand(String.format("softap fwreload " + wlanIface + " " + mode)); 988cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } catch (NativeDaemonConnectorException e) { 989276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 990cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } 991cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } 992cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff 993af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 994af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void stopAccessPoint(String wlanIface) { 995af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 996af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG); 997a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 998a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("softap stopap"); 99923eb297c771bd996fe8559178feb1a07be43ad72Irfan Sheriff mConnector.doCommand("softap stop " + wlanIface); 1000cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff wifiFirmwareReload(wlanIface, "STA"); 1001a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1002276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1003a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 10045321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff } 10055321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff 1006af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 1007af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) { 1008af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 1009af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG); 1010a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1011a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (wifiConfig == null) { 1012a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); 1013a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } else { 1014a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String str = String.format("softap set " + wlanIface + " " + softapIface 1015a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root + " %s %s %s", convertQuotedString(wifiConfig.SSID), 1016ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff getSecurityType(wifiConfig), 1017a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root convertQuotedString(wifiConfig.preSharedKey)); 1018a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(str); 1019a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1020a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1021276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1022c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff } 1023c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff } 102491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 102591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat private long getInterfaceCounter(String iface, boolean rx) { 1026af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 102791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 1028a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 1029a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1030a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand( 1031a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0); 1032a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e1) { 1033a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Error communicating with native daemon", e1); 1034a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1035a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1036a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 1037a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = rsp.split(" "); 1038a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 2) { 1039a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, String.format("Malformed response for reading %s interface", 1040a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root (rx ? "rx" : "tx"))); 1041a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1042a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1043a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 104491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat int code; 104591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 104691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat code = Integer.parseInt(tok[0]); 104791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (NumberFormatException nfe) { 104891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Error parsing code %s", tok[0])); 104991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 105091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 105191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat if ((rx && code != NetdResponseCode.InterfaceRxCounterResult) || ( 105291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat !rx && code != NetdResponseCode.InterfaceTxCounterResult)) { 105391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Unexpected response code %d", code)); 105491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 105591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 105691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return Long.parseLong(tok[1]); 105791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (Exception e) { 105891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format( 105991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat "Failed to read interface %s counters", (rx ? "rx" : "tx")), e); 106091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 106191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 106291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 106391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1064eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 10659a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats getNetworkStatsSummary() { 1066af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 10671059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey return mStatsFactory.readNetworkStatsSummary(); 106891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 106991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1070eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 10719a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats getNetworkStatsDetail() { 1072af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 10731059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey return mStatsFactory.readNetworkStatsDetail(UID_ALL); 107491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 107591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1076eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 107741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setInterfaceQuota(String iface, long quotaBytes) { 1078b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1079b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1080350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1081350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1082350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1083350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 108441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 108541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (mActiveQuotaIfaces.contains(iface)) { 108641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("iface " + iface + " already has quota"); 1087b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1088b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1089b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 109041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes); 1091b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1092b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 109341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support quota shared across interfaces 1094b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 109541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveQuotaIfaces.add(iface); 1096b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1097276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1098b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 109950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 110050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 110150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 110250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma @Override 1103b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey public void removeInterfaceQuota(String iface) { 1104b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1105b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1106350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1107350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1108350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1109350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 111041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 111141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveQuotaIfaces.contains(iface)) { 1112b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: eventually consider throwing 1113b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey return; 1114b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1115b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1116b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 1117b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append("bandwidth removeiquota ").append(iface); 1118b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 111938ddeaa67e52810da5db42895edb74b79111ec53Jeff Sharkey mActiveQuotaIfaces.remove(iface); 112038ddeaa67e52810da5db42895edb74b79111ec53Jeff Sharkey mActiveAlertIfaces.remove(iface); 112138ddeaa67e52810da5db42895edb74b79111ec53Jeff Sharkey 1122b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 112341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support quota shared across interfaces 1124b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 1125b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1126276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1127b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1128b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1129b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1130b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1131b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey @Override 113241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setInterfaceAlert(String iface, long alertBytes) { 113341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 113441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 113541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 113641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 113741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 113841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 113941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // quick sanity check 114041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveQuotaIfaces.contains(iface)) { 114141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("setting alert requires existing quota on iface"); 114241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 114341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 114441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 114541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (mActiveAlertIfaces.contains(iface)) { 114641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("iface " + iface + " already has alert"); 114741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 114841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 114941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 115041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setinterfacealert ").append(iface).append(" ").append( 115141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey alertBytes); 115241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 115341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 115441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support alert shared across interfaces 115541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 115641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.add(iface); 115741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 1158276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 115941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 116041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 116141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 116241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 116341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 116441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void removeInterfaceAlert(String iface) { 116541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 116641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 116741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 116841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 116941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 117041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 117141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 117241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveAlertIfaces.contains(iface)) { 117341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually consider throwing 117441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return; 117541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 117641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 117741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 117841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth removeinterfacealert ").append(iface); 117941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 118041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 118141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support alert shared across interfaces 118241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 118341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.remove(iface); 118441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 1185276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 118641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 118741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 118841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 118941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 119041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 119141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setGlobalAlert(long alertBytes) { 119241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 119341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 119441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 119541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 119641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 119741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 119841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 119941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setglobalalert ").append(alertBytes); 120041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 120141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 120241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 120341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 1204276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 120541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 120641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 120741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 120841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 1209b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1210b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1211b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1212350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1213350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1214350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1215350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 1216b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey synchronized (mUidRejectOnQuota) { 1217b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1218b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1219b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: eventually consider throwing 1220b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey return; 1221b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1222b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1223b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 1224b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append("bandwidth"); 1225b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (rejectOnQuotaInterfaces) { 1226b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" addnaughtyapps"); 1227b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } else { 1228b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" removenaughtyapps"); 1229b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1230b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" ").append(uid); 1231b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1232b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 1233b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 1234b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (rejectOnQuotaInterfaces) { 1235b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mUidRejectOnQuota.put(uid, true); 1236b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } else { 1237b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mUidRejectOnQuota.delete(uid); 1238b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1239b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1240276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1241b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 124250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 124350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 124450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 124563d27a9233fed934340231f438493746084a681dJeff Sharkey @Override 124663d27a9233fed934340231f438493746084a681dJeff Sharkey public boolean isBandwidthControlEnabled() { 124763d27a9233fed934340231f438493746084a681dJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 124863d27a9233fed934340231f438493746084a681dJeff Sharkey return mBandwidthControlEnabled; 124963d27a9233fed934340231f438493746084a681dJeff Sharkey } 125063d27a9233fed934340231f438493746084a681dJeff Sharkey 125163d27a9233fed934340231f438493746084a681dJeff Sharkey @Override 1252eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey public NetworkStats getNetworkStatsUidDetail(int uid) { 1253eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey if (Binder.getCallingUid() != uid) { 1254af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 1255eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 12561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey return mStatsFactory.readNetworkStatsDetail(uid); 1257eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 1258eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 1259cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey @Override 1260cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey public NetworkStats getNetworkStatsTethering(String[] ifacePairs) { 1261af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 1262cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1263cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (ifacePairs.length % 2 != 0) { 1264cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalArgumentException( 1265cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "unexpected ifacePairs; length=" + ifacePairs.length); 1266cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1267cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1268cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1269cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey for (int i = 0; i < ifacePairs.length; i += 2) { 1270cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String ifaceIn = ifacePairs[i]; 1271cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String ifaceOut = ifacePairs[i + 1]; 1272cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (ifaceIn != null && ifaceOut != null) { 1273cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut)); 1274cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1275cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1276cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey return stats; 1277cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1278cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1279cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) { 1280cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final StringBuilder command = new StringBuilder(); 1281cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut); 1282cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1283cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String rsp; 1284cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey try { 1285cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey rsp = mConnector.doCommand(command.toString()).get(0); 1286cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } catch (NativeDaemonConnectorException e) { 1287276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1288cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1289cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1290cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final String[] tok = rsp.split(" "); 1291cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey /* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */ 1292cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (tok.length != 7) { 1293cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException("Native daemon returned unexpected result: " + rsp); 1294cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1295cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1296cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final int code; 1297cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey try { 1298cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey code = Integer.parseInt(tok[0]); 1299cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } catch (NumberFormatException e) { 1300cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException( 1301cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut); 1302cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1303cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey if (code != NetdResponseCode.TetheringStatsResult) { 1304cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException( 1305cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut); 1306cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1307cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1308cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey try { 1309cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry(); 1310cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.iface = ifaceIn; 1311905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey entry.uid = UID_TETHERING; 1312cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.set = SET_DEFAULT; 1313cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.tag = TAG_NONE; 1314cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.rxBytes = Long.parseLong(tok[3]); 1315cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.rxPackets = Long.parseLong(tok[4]); 1316cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.txBytes = Long.parseLong(tok[5]); 1317cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey entry.txPackets = Long.parseLong(tok[6]); 1318cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey return entry; 1319cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } catch (NumberFormatException e) { 1320cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey throw new IllegalStateException( 1321cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e); 1322cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1323cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey } 1324cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey 1325af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 1326f0db6e1853e929ae3b65501c31ee57c4dfbc767cSan Mehat public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) { 1327af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 1328a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1329a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format( 1330a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "interface setthrottle %s %d %d", iface, rxKbps, txKbps)); 1331a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1332276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1333a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 133491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 133591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 133691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat private int getInterfaceThrottle(String iface, boolean rx) { 1337af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 133891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 1339a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 1340a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1341a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand( 1342a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("interface getthrottle %s %s", iface, 1343a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root (rx ? "rx" : "tx"))).get(0); 1344a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1345276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 1346a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1347a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 1348a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = rsp.split(" "); 1349a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 2) { 1350a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Malformed response to getthrottle command"); 1351a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1352a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1353a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 135491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat int code; 135591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 135691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat code = Integer.parseInt(tok[0]); 135791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (NumberFormatException nfe) { 135891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Error parsing code %s", tok[0])); 135991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 136091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 136191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat if ((rx && code != NetdResponseCode.InterfaceRxThrottleResult) || ( 136291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat !rx && code != NetdResponseCode.InterfaceTxThrottleResult)) { 136391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Unexpected response code %d", code)); 136491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 136591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 136691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return Integer.parseInt(tok[1]); 136791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (Exception e) { 136891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format( 136991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat "Failed to read interface %s throttle value", (rx ? "rx" : "tx")), e); 137091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 137191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 137291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 137391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1374af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 137591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public int getInterfaceRxThrottle(String iface) { 137691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return getInterfaceThrottle(iface, true); 137791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 137891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1379af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 138091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public int getInterfaceTxThrottle(String iface) { 138191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return getInterfaceThrottle(iface, false); 138291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 13839a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 1384af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 1385af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setDefaultInterfaceForDns(String iface) { 1386af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 13877475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 13887475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver setdefaultif " + iface; 13897475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 13907475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 13917475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 1392276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 13937475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13947475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 13957475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 1396af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 1397af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void setDnsServersForInterface(String iface, String[] servers) { 1398af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 13997475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 14007475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver setifdns " + iface; 14017475c0cea622f126af966c3b5b9741f547e83450Mattias Falk for (String s : servers) { 1402572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt InetAddress a = NetworkUtils.numericToInetAddress(s); 1403572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt if (a.isAnyLocalAddress() == false) { 1404572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt cmd += " " + a.getHostAddress(); 14057475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14067475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14077475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 1408572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt } catch (IllegalArgumentException e) { 1409572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt throw new IllegalStateException("Error setting dnsn for interface", e); 14107475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 1411276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 14127475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14137475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14147475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 1415af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 1416af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void flushDefaultDnsCache() { 1417af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 14187475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 14197475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver flushdefaultif"; 14207475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 14217475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 14227475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 1423276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 14247475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14257475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14267475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 1427af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey @Override 1428af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey public void flushInterfaceDnsCache(String iface) { 1429af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); 14307475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 14317475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver flushif " + iface; 14327475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 14337475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 14347475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 1435276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey throw e.rethrowAsParcelableException(); 14367475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 14377475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 1438fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey 1439fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey /** {@inheritDoc} */ 1440fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey public void monitor() { 1441fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey if (mConnector != null) { 1442fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey mConnector.monitor(); 1443fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey } 1444fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey } 144547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 144647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey @Override 144747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 144847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey mContext.enforceCallingOrSelfPermission(DUMP, TAG); 144947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 145047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 145147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 145247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey synchronized (mQuotaLock) { 145347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("Active quota ifaces: "); pw.println(mActiveQuotaIfaces.toString()); 145447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("Active alert ifaces: "); pw.println(mActiveAlertIfaces.toString()); 145547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 145647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey 145747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey synchronized (mUidRejectOnQuota) { 145847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print("UID reject on quota ifaces: ["); 145947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey final int size = mUidRejectOnQuota.size(); 146047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey for (int i = 0; i < size; i++) { 146147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.print(mUidRejectOnQuota.keyAt(i)); 146247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey if (i < size - 1) pw.print(","); 146347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 146447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey pw.println("]"); 146547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 146647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey } 1467873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat} 1468