NetworkManagementService.java revision d0e18ffb82b59d38aeaf0e552f48e734202719ab
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; 62873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 63873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 64873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 65873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Binder context for this service 66873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 67873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private Context mContext; 68873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 69873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 70873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * connector object for communicating with netd 71873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 72873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private NativeDaemonConnector mConnector; 73873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 744d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private ArrayList<INetworkManagementEventObserver> mObservers; 754d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 76873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 77873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Constructs a new NetworkManagementService instance 78873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 79873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @param context Binder context for this service 80873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 81d1df8ac6d076ef15ba8857211da2e447b6505fb3San Mehat public NetworkManagementService(Context context) { 82873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext = context; 83873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 844d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers = new ArrayList<INetworkManagementEventObserver>(); 854d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 86873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector = new NativeDaemonConnector( 87873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat new NetdCallbackReceiver(), "netd", 10, "NetdConnector"); 88873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName()); 89873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat thread.start(); 90873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 91873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 924d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void registerObserver(INetworkManagementEventObserver obs) { 934d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.d(TAG, "Registering observer"); 944d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.add(obs); 954d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 964d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 974d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void unregisterObserver(INetworkManagementEventObserver obs) { 984d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.d(TAG, "Unregistering observer"); 994d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.remove(mObservers.indexOf(obs)); 1004d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1014d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1024d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 1034d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface link status change 1044d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 1054d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceLinkStatusChanged(String iface, boolean link) { 1064d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 1074d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 1084d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceLinkStatusChanged(iface, link); 1094d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 1104d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.w(TAG, "Observer notifier failed", ex); 1114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1124d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1144d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1154d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 1164d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface addition. 1174d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 1184d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceAdded(String iface) { 1194d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 1204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 1214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceAdded(iface); 1224d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 1234d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.w(TAG, "Observer notifier failed", ex); 1244d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1254d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1264d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1274d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 1294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface removal. 1304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 1314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceRemoved(String iface) { 1324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 1334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 1344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceRemoved(iface); 1354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 1364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat Log.w(TAG, "Observer notifier failed", ex); 1374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 1404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 1414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 142873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 143873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // Netd Callback handling 144873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 145873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 146873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 147873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void onDaemonConnected() { 148873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat new Thread() { 149873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void run() { 150873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // XXX: Run some tests 151873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 152873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat }.start(); 153873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 154873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean onEvent(int code, String raw, String[] cooked) { 155873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return false; 156873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 157873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 158873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 159ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat private static int stringToIpAddr(String addrString) throws UnknownHostException { 160ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 161ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String[] parts = addrString.split("\\."); 162ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat if (parts.length != 4) { 163ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new UnknownHostException(addrString); 164ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 165ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 166ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int a = Integer.parseInt(parts[0]) ; 167ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int b = Integer.parseInt(parts[1]) << 8; 168ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int c = Integer.parseInt(parts[2]) << 16; 169ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int d = Integer.parseInt(parts[3]) << 24; 170ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 171ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return a | b | c | d; 172ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (NumberFormatException ex) { 173ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new UnknownHostException(addrString); 174ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 175ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 176ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 177ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public static String intToIpString(int i) { 178ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return ((i >> 24 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >> 8 ) & 0xFF) + "." + 179ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat (i & 0xFF); 180ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 181ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 182873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 183873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // INetworkManagementService members 184873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 185873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 186873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listInterfaces() throws IllegalStateException { 187873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 188873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 189873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 190ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult); 191ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 192ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 193ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException { 194ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String rsp = mConnector.doCommand("interface getcfg " + iface).get(0); 195ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.d(TAG, String.format("rsp <%s>", rsp)); 196ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 197ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz.zzz.zzz.zzz [flag1 flag2 flag3] 198ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat StringTokenizer st = new StringTokenizer(rsp); 199ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 200ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 201ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat int code = Integer.parseInt(st.nextToken(" ")); 202ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat if (code != NetdResponseCode.InterfaceGetCfgResult) { 203ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new IllegalStateException( 204ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String.format("Expected code %d, but got %d", 205ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat NetdResponseCode.InterfaceGetCfgResult, code)); 206ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 207ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (NumberFormatException nfe) { 208ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new IllegalStateException( 209ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String.format("Invalid response from daemon (%s)", rsp)); 210ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 211ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 212ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat InterfaceConfiguration cfg = new InterfaceConfiguration(); 213ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.hwAddr = st.nextToken(" "); 214ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 215ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.ipAddr = stringToIpAddr(st.nextToken(" ")); 216ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (UnknownHostException uhe) { 217ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.e(TAG, "Failed to parse ipaddr", uhe); 218ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.ipAddr = 0; 219ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 220ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 221ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 222ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.netmask = stringToIpAddr(st.nextToken(" ")); 223ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } catch (UnknownHostException uhe) { 224ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.e(TAG, "Failed to parse netmask", uhe); 225ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.netmask = 0; 226ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 227ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat cfg.interfaceFlags = st.nextToken("]"); 228ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat Log.d(TAG, String.format("flags <%s>", cfg.interfaceFlags)); 229ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return cfg; 230ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 231ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 232ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public void setInterfaceConfig( 233ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String iface, InterfaceConfiguration cfg) throws IllegalStateException { 234ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String cmd = String.format("interface setcfg %s %s %s", iface, 235ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags); 236ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat mConnector.doCommand(cmd); 237873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 238873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 239873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void shutdown() { 240873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (mContext.checkCallingOrSelfPermission( 241873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.SHUTDOWN) 242873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat != PackageManager.PERMISSION_GRANTED) { 243873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new SecurityException("Requires SHUTDOWN permission"); 244873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 245873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 246873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat Log.d(TAG, "Shutting down"); 247873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 248873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 249873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean getIpForwardingEnabled() throws IllegalStateException{ 250873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 251873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 252873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 253873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat ArrayList<String> rsp = mConnector.doCommand("ipfwd status"); 254873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 255873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 256873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String []tok = line.split(" "); 257873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 258873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.IpFwdStatusResult) { 259873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 211 Forwarding <enabled/disabled> 260873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (tok.length !=2) { 261873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException( 262873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String.format("Malformatted list entry '%s'", line)); 263873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 264873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (tok[2].equals("enabled")) 265873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return true; 266873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return false; 267873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 268873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 269873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 270873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 271873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 272873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 273873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 274873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setIpForwardingEnabled(boolean enable) throws IllegalStateException { 275873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 276873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 277873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis"))); 278873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 279873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 280873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void startTethering(String dhcpRangeStart, String dhcpRangeEnd) 281873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 282873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 283873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 284873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(String.format("tether start %s %s", dhcpRangeStart, dhcpRangeEnd)); 285873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 286873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 287873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void stopTethering() throws IllegalStateException { 288873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 289873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 290873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand("tether stop"); 291873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 292873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 293873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean isTetheringStarted() throws IllegalStateException { 294873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 295873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 296873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat ArrayList<String> rsp = mConnector.doCommand("tether status"); 298873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 299873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String []tok = line.split(" "); 301873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 302873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.TetherStatusResult) { 303873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // XXX: Tethering services <started/stopped> <TBD>... 304873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (tok[2].equals("started")) 305873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return true; 306873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat return false; 307873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 308873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 309873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 310873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 311873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 312873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 313873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 314873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void tetherInterface(String iface) throws IllegalStateException { 315873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 316873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 317873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand("tether interface add " + iface); 318873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 319873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 320873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void untetherInterface(String iface) { 321873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 322873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 323873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand("tether interface remove " + iface); 324873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 325873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 326873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listTetheredInterfaces() throws IllegalStateException { 327873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 328873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 32972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat return mConnector.doListCommand( 33072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat "tether interface list", NetdResponseCode.TetherInterfaceListResult); 331873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 332873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 333873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setDnsForwarders(String[] dns) throws IllegalStateException { 334873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 335873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 336873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat try { 337d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String cmd = "tether dns set"; 338873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String s : dns) { 339d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt cmd += " " + InetAddress.getByName(s).getHostAddress(); 340873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 341873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(cmd); 342873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } catch (UnknownHostException e) { 343873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Error resolving dns name", e); 344873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 345873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 346873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 347873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] getDnsForwarders() throws IllegalStateException { 348873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 349873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 35072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat return mConnector.doListCommand( 35172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult); 352873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 353873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 354873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void enableNat(String internalInterface, String externalInterface) 355873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 356873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 357873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 358873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand( 359873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String.format("nat enable %s %s", internalInterface, externalInterface)); 360873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 361873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 362873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void disableNat(String internalInterface, String externalInterface) 363873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 364873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 365873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 366873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand( 367873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat String.format("nat disable %s %s", internalInterface, externalInterface)); 368873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 36972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 37072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public String[] listTtys() throws IllegalStateException { 37172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 37272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 37372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult); 37472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 37572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 376d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr, 377d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String dns2Addr) throws IllegalStateException { 37872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat try { 37972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 38072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 381d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty, 382d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(localAddr).getHostAddress(), 383d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(remoteAddr).getHostAddress(), 384d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(dns1Addr).getHostAddress(), 385d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt InetAddress.getByName(dns2Addr).getHostAddress())); 38672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } catch (UnknownHostException e) { 38772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat throw new IllegalStateException("Error resolving addr", e); 38872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 38972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 39072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 39172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public void detachPppd(String tty) throws IllegalStateException { 39272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 39372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 39472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mConnector.doCommand(String.format("pppd detach %s", tty)); 39572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 396873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat} 397