NetworkManagementService.java revision e325392c257a5460de6327420c81729f4e687881
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 19873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.app.PendingIntent; 20873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.BroadcastReceiver; 21873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Context; 22873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Intent; 23873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.IntentFilter; 24873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.res.Resources; 25873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.pm.PackageManager; 26873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.net.Uri; 27ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehatimport android.net.InterfaceConfiguration; 284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehatimport android.net.INetworkManagementEventObserver; 29873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService; 30873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.Handler; 31873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.text.TextUtils; 32873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.util.Log; 33873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.util.ArrayList; 34ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehatimport java.util.StringTokenizer; 35873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.provider.Settings; 36873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.ContentResolver; 37873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.database.ContentObserver; 38873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 39873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File; 40873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.FileReader; 41873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.lang.IllegalStateException; 42873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 43873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.net.InetAddress; 44873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.net.UnknownHostException; 45873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 46873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/** 47873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide 48873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 49873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatclass NetworkManagementService extends INetworkManagementService.Stub { 50873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 51873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private static final String TAG = "NetworkManagmentService"; 52873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 53873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdResponseCode { 54873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int InterfaceListResult = 110; 55873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherInterfaceListResult = 111; 56873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherDnsFwdTgtListResult = 112; 5772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public static final int TtyListResult = 113; 58873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 59873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherStatusResult = 210; 60873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int IpFwdStatusResult = 211; 61ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public static final int InterfaceGetCfgResult = 213; 62e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int SoftapStatusResult = 214; 63e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int UsbRNDISStatusResult = 215; 64e325392c257a5460de6327420c81729f4e687881Robert Greenwalt 65e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int InterfaceChange = 600; 66873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 67873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 68873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 69873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Binder context for this service 70873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 71873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private Context mContext; 72873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 73873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 74873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * connector object for communicating with netd 75873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 76873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private NativeDaemonConnector mConnector; 77873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 784d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private ArrayList<INetworkManagementEventObserver> mObservers; 794d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 80873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 81873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Constructs a new NetworkManagementService instance 82873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 83873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @param context Binder context for this service 84873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 85d1df8ac6d076ef15ba8857211da2e447b6505fb3San Mehat public NetworkManagementService(Context context) { 86873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext = context; 87873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 884d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers = new ArrayList<INetworkManagementEventObserver>(); 894d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 90873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector = new NativeDaemonConnector( 91873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat new NetdCallbackReceiver(), "netd", 10, "NetdConnector"); 92873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName()); 93873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat thread.start(); 94873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 95873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 964d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void registerObserver(INetworkManagementEventObserver obs) { 974d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.d(TAG, "Registering observer"); 984d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.add(obs); 994d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1004d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1014d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void unregisterObserver(INetworkManagementEventObserver obs) { 1024d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.d(TAG, "Unregistering observer"); 1034d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.remove(mObservers.indexOf(obs)); 1044d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1054d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1064d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 1074d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface link status change 1084d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 1094d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceLinkStatusChanged(String iface, boolean link) { 1104d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 1114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 1124d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceLinkStatusChanged(iface, link); 1134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 1144d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.w(TAG, "Observer notifier failed", ex); 1154d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1164d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1174d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1184d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1194d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 1204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface addition. 1214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 1224d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceAdded(String iface) { 1234d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 1244d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 1254d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceAdded(iface); 1264d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 1274d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.w(TAG, "Observer notifier failed", ex); 1284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 1334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface removal. 1344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 1354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceRemoved(String iface) { 1364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 1374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 1384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceRemoved(iface); 1394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 1404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.w(TAG, "Observer notifier failed", ex); 1414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1444d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 146873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 147873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // Netd Callback handling 148873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 149873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 150873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 151873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void onDaemonConnected() { 152873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat new Thread() { 153873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void run() { 154873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 155873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat }.start(); 156873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 157873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean onEvent(int code, String raw, String[] cooked) { 158e325392c257a5460de6327420c81729f4e687881Robert Greenwalt if (code == NetdResponseCode.InterfaceChange) { 159e325392c257a5460de6327420c81729f4e687881Robert Greenwalt /* 160e325392c257a5460de6327420c81729f4e687881Robert Greenwalt * a network interface change occured 161e325392c257a5460de6327420c81729f4e687881Robert Greenwalt * Format: "NNN Iface added <name>" 162e325392c257a5460de6327420c81729f4e687881Robert Greenwalt * "NNN Iface removed <name>" 163e325392c257a5460de6327420c81729f4e687881Robert Greenwalt * "NNN Iface changed <name> <up/down>" 164e325392c257a5460de6327420c81729f4e687881Robert Greenwalt */ 165e325392c257a5460de6327420c81729f4e687881Robert Greenwalt if (cooked.length < 4 || !cooked[1].equals("Iface")) { 166e325392c257a5460de6327420c81729f4e687881Robert Greenwalt throw new IllegalStateException( 167e325392c257a5460de6327420c81729f4e687881Robert Greenwalt String.format("Invalid event from daemon (%s)", raw)); 168e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } 169e325392c257a5460de6327420c81729f4e687881Robert Greenwalt if (cooked[2].equals("added")) { 170e325392c257a5460de6327420c81729f4e687881Robert Greenwalt notifyInterfaceAdded(cooked[3]); 171e325392c257a5460de6327420c81729f4e687881Robert Greenwalt return true; 172e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } else if (cooked[2].equals("removed")) { 173e325392c257a5460de6327420c81729f4e687881Robert Greenwalt notifyInterfaceRemoved(cooked[3]); 174e325392c257a5460de6327420c81729f4e687881Robert Greenwalt return true; 175e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } else if (cooked[2].equals("changed") && cooked.length == 5) { 176e325392c257a5460de6327420c81729f4e687881Robert Greenwalt notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up")); 177e325392c257a5460de6327420c81729f4e687881Robert Greenwalt return true; 178e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } 179e325392c257a5460de6327420c81729f4e687881Robert Greenwalt throw new IllegalStateException( 180e325392c257a5460de6327420c81729f4e687881Robert Greenwalt String.format("Invalid event from daemon (%s)", raw)); 181e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } 182e325392c257a5460de6327420c81729f4e687881Robert Greenwalt return false; 183873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 184873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 185873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 186ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat private static int stringToIpAddr(String addrString) throws UnknownHostException { 187ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 188ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String[] parts = addrString.split("\\."); 189ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat if (parts.length != 4) { 190ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new UnknownHostException(addrString); 191ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 192ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 193ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int a = Integer.parseInt(parts[0]) ; 194ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int b = Integer.parseInt(parts[1]) << 8; 195ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int c = Integer.parseInt(parts[2]) << 16; 196ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int d = Integer.parseInt(parts[3]) << 24; 197ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 198ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return a | b | c | d; 199ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (NumberFormatException ex) { 200ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new UnknownHostException(addrString); 201ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 202ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 203ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 204ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public static String intToIpString(int i) { 205ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return ((i >> 24 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >> 8 ) & 0xFF) + "." + 206ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat (i & 0xFF); 207ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 208ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 209873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 210873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // INetworkManagementService members 211873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 212873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 213873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listInterfaces() throws IllegalStateException { 214873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 215873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 216873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 217ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult); 218ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 219ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 220ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException { 221ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String rsp = mConnector.doCommand("interface getcfg " + iface).get(0); 222ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.d(TAG, String.format("rsp <%s>", rsp)); 223ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 224ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz.zzz.zzz.zzz [flag1 flag2 flag3] 225ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat StringTokenizer st = new StringTokenizer(rsp); 226ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 227ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 228ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int code = Integer.parseInt(st.nextToken(" ")); 229ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat if (code != NetdResponseCode.InterfaceGetCfgResult) { 230ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new IllegalStateException( 231ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String.format("Expected code %d, but got %d", 232ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat NetdResponseCode.InterfaceGetCfgResult, code)); 233ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 234ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (NumberFormatException nfe) { 235ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new IllegalStateException( 236ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String.format("Invalid response from daemon (%s)", rsp)); 237ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 238ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 239ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat InterfaceConfiguration cfg = new InterfaceConfiguration(); 240ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.hwAddr = st.nextToken(" "); 241ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 242ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.ipAddr = stringToIpAddr(st.nextToken(" ")); 243ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (UnknownHostException uhe) { 244ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.e(TAG, "Failed to parse ipaddr", uhe); 245ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.ipAddr = 0; 246ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 247ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 248ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 249ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.netmask = stringToIpAddr(st.nextToken(" ")); 250ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (UnknownHostException uhe) { 251ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.e(TAG, "Failed to parse netmask", uhe); 252ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.netmask = 0; 253ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 254ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.interfaceFlags = st.nextToken("]"); 255ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.d(TAG, String.format("flags <%s>", cfg.interfaceFlags)); 256ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return cfg; 257ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 258ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 259ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public void setInterfaceConfig( 260ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String iface, InterfaceConfiguration cfg) throws IllegalStateException { 261ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String cmd = String.format("interface setcfg %s %s %s", iface, 262ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags); 263ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat mConnector.doCommand(cmd); 264873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 265873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 266873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void shutdown() { 267873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (mContext.checkCallingOrSelfPermission( 268873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.SHUTDOWN) 269873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat != PackageManager.PERMISSION_GRANTED) { 270873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new SecurityException("Requires SHUTDOWN permission"); 271873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 272873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 273873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat Log.d(TAG, "Shutting down"); 274873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 275873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 276873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean getIpForwardingEnabled() throws IllegalStateException{ 277873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 278873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 279873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 280873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat ArrayList<String> rsp = mConnector.doCommand("ipfwd status"); 281873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 282873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 283873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String []tok = line.split(" "); 284873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 285873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.IpFwdStatusResult) { 286873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 211 Forwarding <enabled/disabled> 287873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (tok.length !=2) { 288873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException( 289873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String.format("Malformatted list entry '%s'", line)); 290873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 291873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (tok[2].equals("enabled")) 292873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return true; 293873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return false; 294873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 295873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 296873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 298873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 299873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 301873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setIpForwardingEnabled(boolean enable) throws IllegalStateException { 302873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 303873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 304873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis"))); 305873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 306873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 307873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void startTethering(String dhcpRangeStart, String dhcpRangeEnd) 308873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 309873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 310873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 311873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(String.format("tether start %s %s", dhcpRangeStart, dhcpRangeEnd)); 312873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 313873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 314873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void stopTethering() throws IllegalStateException { 315873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 316873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 317873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand("tether stop"); 318873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 319873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 320873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean isTetheringStarted() throws IllegalStateException { 321873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 322873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 323873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 324873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat ArrayList<String> rsp = mConnector.doCommand("tether status"); 325873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 326873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 327873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String []tok = line.split(" "); 328873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 329873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.TetherStatusResult) { 330873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // XXX: Tethering services <started/stopped> <TBD>... 331873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (tok[2].equals("started")) 332873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return true; 333873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return false; 334873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 335873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 336873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 337873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 338873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 339873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 340873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 341873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void tetherInterface(String iface) throws IllegalStateException { 342873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 343873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 344873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand("tether interface add " + iface); 345873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 346873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 347873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void untetherInterface(String iface) { 348873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 349873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 350873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand("tether interface remove " + iface); 351873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 352873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 353873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listTetheredInterfaces() throws IllegalStateException { 354873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 355873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 35672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat return mConnector.doListCommand( 35772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat "tether interface list", NetdResponseCode.TetherInterfaceListResult); 358873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 359873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 360873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setDnsForwarders(String[] dns) throws IllegalStateException { 361873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 362873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 363873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat try { 364d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String cmd = "tether dns set"; 365873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String s : dns) { 366d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt cmd += " " + InetAddress.getByName(s).getHostAddress(); 367873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 368873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(cmd); 369873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } catch (UnknownHostException e) { 370873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Error resolving dns name", e); 371873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 372873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 373873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 374873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] getDnsForwarders() throws IllegalStateException { 375873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 376873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 37772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat return mConnector.doListCommand( 37872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult); 379873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 380873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 381873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void enableNat(String internalInterface, String externalInterface) 382873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 383873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 384873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 385873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand( 386873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String.format("nat enable %s %s", internalInterface, externalInterface)); 387873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 388873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 389873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void disableNat(String internalInterface, String externalInterface) 390873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 391873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 392873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 393873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand( 394873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String.format("nat disable %s %s", internalInterface, externalInterface)); 395873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 39672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 39772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public String[] listTtys() throws IllegalStateException { 39872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 39972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 40072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult); 40172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 40272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 403d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr, 404d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String dns2Addr) throws IllegalStateException { 40572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat try { 40672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 40772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 408d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty, 409d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(localAddr).getHostAddress(), 410d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(remoteAddr).getHostAddress(), 411d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(dns1Addr).getHostAddress(), 412d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(dns2Addr).getHostAddress())); 41372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } catch (UnknownHostException e) { 41472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat throw new IllegalStateException("Error resolving addr", e); 41572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 41672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 41772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 41872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public void detachPppd(String tty) throws IllegalStateException { 41972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 42072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 42172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mConnector.doCommand(String.format("pppd detach %s", tty)); 42272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 423873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat} 424