blob: bcb1aa24930d544cfe4ab572b2af64106facf50d [file] [log] [blame]
San Mehat873f2142010-01-14 10:25:07 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkey47eb1022011-08-25 17:48:52 -070019import static android.Manifest.permission.DUMP;
Jeff Sharkey350083e2011-06-29 10:45:16 -070020import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070021import static android.net.NetworkStats.SET_DEFAULT;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070022import static android.net.NetworkStats.TAG_NONE;
23import static android.net.NetworkStats.UID_ALL;
Jeff Sharkeyae2c1812011-10-04 13:11:40 -070024import static android.net.TrafficStats.UID_TETHERING;
Jeff Sharkey350083e2011-06-29 10:45:16 -070025import static android.provider.Settings.Secure.NETSTATS_ENABLED;
Jeff Sharkeya63ba592011-07-19 23:47:12 -070026import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070027
San Mehat873f2142010-01-14 10:25:07 -080028import android.content.Context;
San Mehat873f2142010-01-14 10:25:07 -080029import android.content.pm.PackageManager;
San Mehat4d02d002010-01-22 16:07:46 -080030import android.net.INetworkManagementEventObserver;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070031import android.net.InterfaceConfiguration;
Robert Greenwalted126402011-01-28 15:34:55 -080032import android.net.LinkAddress;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070033import android.net.NetworkStats;
Robert Greenwalted126402011-01-28 15:34:55 -080034import android.net.NetworkUtils;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070035import android.net.RouteInfo;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080036import android.net.wifi.WifiConfiguration;
37import android.net.wifi.WifiConfiguration.KeyMgmt;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070038import android.os.Binder;
San Mehat873f2142010-01-14 10:25:07 -080039import android.os.INetworkManagementService;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070040import android.os.SystemClock;
Marco Nelissen62dbb222010-02-18 10:56:30 -080041import android.os.SystemProperties;
Jeff Sharkey350083e2011-06-29 10:45:16 -070042import android.provider.Settings;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080043import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080044import android.util.Slog;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070045import android.util.SparseBooleanArray;
San Mehat873f2142010-01-14 10:25:07 -080046
Jeff Sharkey1059c3c2011-10-04 16:54:49 -070047import com.android.internal.net.NetworkStatsFactory;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070048import com.google.android.collect.Sets;
Jeff Sharkey4414cea2011-06-24 17:05:24 -070049
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070050import java.io.BufferedReader;
51import java.io.DataInputStream;
San Mehat873f2142010-01-14 10:25:07 -080052import java.io.File;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070053import java.io.FileDescriptor;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070054import java.io.FileInputStream;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070055import java.io.IOException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070056import java.io.InputStreamReader;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070057import java.io.PrintWriter;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070058import java.net.Inet4Address;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070059import java.net.InetAddress;
60import java.util.ArrayList;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070061import java.util.HashSet;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070062import java.util.NoSuchElementException;
63import java.util.StringTokenizer;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -070064import java.util.concurrent.CountDownLatch;
San Mehat873f2142010-01-14 10:25:07 -080065
66/**
67 * @hide
68 */
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070069public class NetworkManagementService extends INetworkManagementService.Stub
70 implements Watchdog.Monitor {
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070071 private static final String TAG = "NetworkManagementService";
Dianne Hackborncef65ee2010-09-30 18:27:22 -070072 private static final boolean DBG = false;
Kenny Root305bcbf2010-09-03 07:56:38 -070073 private static final String NETD_TAG = "NetdConnector";
74
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070075 private static final int ADD = 1;
76 private static final int REMOVE = 2;
77
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070078 /**
79 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
80 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
81 */
82 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
83
San Mehat873f2142010-01-14 10:25:07 -080084 class NetdResponseCode {
JP Abgrall12b933d2011-07-14 18:09:22 -070085 /* Keep in sync with system/netd/ResponseCode.h */
San Mehat873f2142010-01-14 10:25:07 -080086 public static final int InterfaceListResult = 110;
87 public static final int TetherInterfaceListResult = 111;
88 public static final int TetherDnsFwdTgtListResult = 112;
San Mehat72759df2010-01-19 13:50:37 -080089 public static final int TtyListResult = 113;
San Mehat873f2142010-01-14 10:25:07 -080090
91 public static final int TetherStatusResult = 210;
92 public static final int IpFwdStatusResult = 211;
San Mehated4fc8a2010-01-22 12:28:36 -080093 public static final int InterfaceGetCfgResult = 213;
Robert Greenwalte3253922010-02-18 09:23:25 -080094 public static final int SoftapStatusResult = 214;
San Mehat91cac642010-03-31 14:31:36 -070095 public static final int InterfaceRxCounterResult = 216;
96 public static final int InterfaceTxCounterResult = 217;
97 public static final int InterfaceRxThrottleResult = 218;
98 public static final int InterfaceTxThrottleResult = 219;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070099 public static final int QuotaCounterResult = 220;
100 public static final int TetheringStatsResult = 221;
Robert Greenwalte3253922010-02-18 09:23:25 -0800101
102 public static final int InterfaceChange = 600;
JP Abgrall12b933d2011-07-14 18:09:22 -0700103 public static final int BandwidthControl = 601;
San Mehat873f2142010-01-14 10:25:07 -0800104 }
105
106 /**
107 * Binder context for this service
108 */
109 private Context mContext;
110
111 /**
112 * connector object for communicating with netd
113 */
114 private NativeDaemonConnector mConnector;
115
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700116 private Thread mThread;
117 private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
118
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700119 // TODO: replace with RemoteCallbackList
San Mehat4d02d002010-01-22 16:07:46 -0800120 private ArrayList<INetworkManagementEventObserver> mObservers;
121
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700122 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
123
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700124 private Object mQuotaLock = new Object();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700125 /** Set of interfaces with active quotas. */
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700126 private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet();
127 /** Set of interfaces with active alerts. */
128 private HashSet<String> mActiveAlertIfaces = Sets.newHashSet();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700129 /** Set of UIDs with active reject rules. */
130 private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
131
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700132 private volatile boolean mBandwidthControlEnabled;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700133
San Mehat873f2142010-01-14 10:25:07 -0800134 /**
135 * Constructs a new NetworkManagementService instance
136 *
137 * @param context Binder context for this service
138 */
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700139 private NetworkManagementService(Context context) {
San Mehat873f2142010-01-14 10:25:07 -0800140 mContext = context;
San Mehat4d02d002010-01-22 16:07:46 -0800141 mObservers = new ArrayList<INetworkManagementEventObserver>();
142
Marco Nelissen62dbb222010-02-18 10:56:30 -0800143 if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
144 return;
145 }
146
San Mehat873f2142010-01-14 10:25:07 -0800147 mConnector = new NativeDaemonConnector(
Kenny Root305bcbf2010-09-03 07:56:38 -0700148 new NetdCallbackReceiver(), "netd", 10, NETD_TAG);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700149 mThread = new Thread(mConnector, NETD_TAG);
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700150
151 // Add ourself to the Watchdog monitors.
152 Watchdog.getInstance().addMonitor(this);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700153 }
154
155 public static NetworkManagementService create(Context context) throws InterruptedException {
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700156 NetworkManagementService service = new NetworkManagementService(context);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700157 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
158 service.mThread.start();
159 if (DBG) Slog.d(TAG, "Awaiting socket connection");
160 service.mConnectedSignal.await();
161 if (DBG) Slog.d(TAG, "Connected");
162 return service;
San Mehat873f2142010-01-14 10:25:07 -0800163 }
164
Jeff Sharkey350083e2011-06-29 10:45:16 -0700165 public void systemReady() {
Jeff Sharkey350083e2011-06-29 10:45:16 -0700166 // only enable bandwidth control when support exists, and requested by
167 // system setting.
Jeff Sharkey350083e2011-06-29 10:45:16 -0700168 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
169 final boolean shouldEnable =
Jeff Sharkey05355c32011-08-09 14:44:19 -0700170 Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700171
Jeff Sharkey350083e2011-06-29 10:45:16 -0700172 if (hasKernelSupport && shouldEnable) {
173 Slog.d(TAG, "enabling bandwidth control");
174 try {
175 mConnector.doCommand("bandwidth enable");
176 mBandwidthControlEnabled = true;
177 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700178 Log.wtf(TAG, "problem enabling bandwidth controls", e);
Jeff Sharkey350083e2011-06-29 10:45:16 -0700179 }
180 } else {
181 Slog.d(TAG, "not enabling bandwidth control");
182 }
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -0700183
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700184 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
Jeff Sharkey350083e2011-06-29 10:45:16 -0700185 }
186
San Mehat4d02d002010-01-22 16:07:46 -0800187 public void registerObserver(INetworkManagementEventObserver obs) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800188 Slog.d(TAG, "Registering observer");
San Mehat4d02d002010-01-22 16:07:46 -0800189 mObservers.add(obs);
190 }
191
192 public void unregisterObserver(INetworkManagementEventObserver obs) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800193 Slog.d(TAG, "Unregistering observer");
San Mehat4d02d002010-01-22 16:07:46 -0800194 mObservers.remove(mObservers.indexOf(obs));
195 }
196
197 /**
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700198 * Notify our observers of an interface status change
San Mehat4d02d002010-01-22 16:07:46 -0800199 */
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700200 private void notifyInterfaceStatusChanged(String iface, boolean up) {
San Mehat4d02d002010-01-22 16:07:46 -0800201 for (INetworkManagementEventObserver obs : mObservers) {
202 try {
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700203 obs.interfaceStatusChanged(iface, up);
204 } catch (Exception ex) {
205 Slog.w(TAG, "Observer notifier failed", ex);
206 }
207 }
208 }
209
210 /**
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700211 * Notify our observers of an interface link state change
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700212 * (typically, an Ethernet cable has been plugged-in or unplugged).
213 */
214 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
215 for (INetworkManagementEventObserver obs : mObservers) {
216 try {
217 obs.interfaceLinkStateChanged(iface, up);
San Mehat4d02d002010-01-22 16:07:46 -0800218 } catch (Exception ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800219 Slog.w(TAG, "Observer notifier failed", ex);
San Mehat4d02d002010-01-22 16:07:46 -0800220 }
221 }
222 }
223
224 /**
225 * Notify our observers of an interface addition.
226 */
227 private void notifyInterfaceAdded(String iface) {
228 for (INetworkManagementEventObserver obs : mObservers) {
229 try {
230 obs.interfaceAdded(iface);
231 } catch (Exception ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800232 Slog.w(TAG, "Observer notifier failed", ex);
San Mehat4d02d002010-01-22 16:07:46 -0800233 }
234 }
235 }
236
237 /**
238 * Notify our observers of an interface removal.
239 */
240 private void notifyInterfaceRemoved(String iface) {
Jeff Sharkey89b8a212011-10-11 11:58:11 -0700241 // netd already clears out quota and alerts for removed ifaces; update
242 // our sanity-checking state.
243 mActiveAlertIfaces.remove(iface);
244 mActiveQuotaIfaces.remove(iface);
245
San Mehat4d02d002010-01-22 16:07:46 -0800246 for (INetworkManagementEventObserver obs : mObservers) {
247 try {
248 obs.interfaceRemoved(iface);
249 } catch (Exception ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800250 Slog.w(TAG, "Observer notifier failed", ex);
San Mehat4d02d002010-01-22 16:07:46 -0800251 }
252 }
253 }
254
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700255 /**
JP Abgrall12b933d2011-07-14 18:09:22 -0700256 * Notify our observers of a limit reached.
257 */
258 private void notifyLimitReached(String limitName, String iface) {
259 for (INetworkManagementEventObserver obs : mObservers) {
260 try {
261 obs.limitReached(limitName, iface);
JP Abgrall12b933d2011-07-14 18:09:22 -0700262 } catch (Exception ex) {
263 Slog.w(TAG, "Observer notifier failed", ex);
264 }
265 }
266 }
267
268 /**
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700269 * Let us know the daemon is connected
270 */
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700271 protected void onDaemonConnected() {
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700272 if (DBG) Slog.d(TAG, "onConnected");
273 mConnectedSignal.countDown();
274 }
275
San Mehat4d02d002010-01-22 16:07:46 -0800276
San Mehat873f2142010-01-14 10:25:07 -0800277 //
278 // Netd Callback handling
279 //
280
281 class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700282 /** {@inheritDoc} */
San Mehat873f2142010-01-14 10:25:07 -0800283 public void onDaemonConnected() {
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700284 NetworkManagementService.this.onDaemonConnected();
San Mehat873f2142010-01-14 10:25:07 -0800285 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700286
287 /** {@inheritDoc} */
San Mehat873f2142010-01-14 10:25:07 -0800288 public boolean onEvent(int code, String raw, String[] cooked) {
JP Abgrall12b933d2011-07-14 18:09:22 -0700289 switch (code) {
290 case NetdResponseCode.InterfaceChange:
291 /*
292 * a network interface change occured
293 * Format: "NNN Iface added <name>"
294 * "NNN Iface removed <name>"
295 * "NNN Iface changed <name> <up/down>"
296 * "NNN Iface linkstatus <name> <up/down>"
297 */
298 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
299 throw new IllegalStateException(
300 String.format("Invalid event from daemon (%s)", raw));
301 }
302 if (cooked[2].equals("added")) {
303 notifyInterfaceAdded(cooked[3]);
304 return true;
305 } else if (cooked[2].equals("removed")) {
306 notifyInterfaceRemoved(cooked[3]);
307 return true;
308 } else if (cooked[2].equals("changed") && cooked.length == 5) {
309 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
310 return true;
311 } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
312 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
313 return true;
314 }
Robert Greenwalte3253922010-02-18 09:23:25 -0800315 throw new IllegalStateException(
316 String.format("Invalid event from daemon (%s)", raw));
JP Abgrall12b933d2011-07-14 18:09:22 -0700317 // break;
318 case NetdResponseCode.BandwidthControl:
319 /*
320 * Bandwidth control needs some attention
321 * Format: "NNN limit alert <alertName> <ifaceName>"
322 */
323 if (cooked.length < 5 || !cooked[1].equals("limit")) {
324 throw new IllegalStateException(
325 String.format("Invalid event from daemon (%s)", raw));
326 }
327 if (cooked[2].equals("alert")) {
328 notifyLimitReached(cooked[3], cooked[4]);
329 return true;
330 }
331 throw new IllegalStateException(
332 String.format("Invalid event from daemon (%s)", raw));
333 // break;
334 default: break;
Robert Greenwalte3253922010-02-18 09:23:25 -0800335 }
336 return false;
San Mehat873f2142010-01-14 10:25:07 -0800337 }
338 }
339
San Mehated4fc8a2010-01-22 12:28:36 -0800340
San Mehat873f2142010-01-14 10:25:07 -0800341 //
342 // INetworkManagementService members
343 //
344
345 public String[] listInterfaces() throws IllegalStateException {
346 mContext.enforceCallingOrSelfPermission(
347 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
348
Kenny Roota80ce062010-06-01 13:23:53 -0700349 try {
350 return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult);
351 } catch (NativeDaemonConnectorException e) {
352 throw new IllegalStateException(
353 "Cannot communicate with native daemon to list interfaces");
354 }
San Mehated4fc8a2010-01-22 12:28:36 -0800355 }
356
357 public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException {
Kenny Roota80ce062010-06-01 13:23:53 -0700358 String rsp;
359 try {
360 rsp = mConnector.doCommand("interface getcfg " + iface).get(0);
361 } catch (NativeDaemonConnectorException e) {
362 throw new IllegalStateException(
363 "Cannot communicate with native daemon to get interface config");
364 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800365 Slog.d(TAG, String.format("rsp <%s>", rsp));
San Mehated4fc8a2010-01-22 12:28:36 -0800366
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800367 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz [flag1 flag2 flag3]
San Mehated4fc8a2010-01-22 12:28:36 -0800368 StringTokenizer st = new StringTokenizer(rsp);
369
Kenny Roota80ce062010-06-01 13:23:53 -0700370 InterfaceConfiguration cfg;
San Mehated4fc8a2010-01-22 12:28:36 -0800371 try {
Kenny Roota80ce062010-06-01 13:23:53 -0700372 try {
373 int code = Integer.parseInt(st.nextToken(" "));
374 if (code != NetdResponseCode.InterfaceGetCfgResult) {
375 throw new IllegalStateException(
376 String.format("Expected code %d, but got %d",
377 NetdResponseCode.InterfaceGetCfgResult, code));
378 }
379 } catch (NumberFormatException nfe) {
San Mehated4fc8a2010-01-22 12:28:36 -0800380 throw new IllegalStateException(
Kenny Roota80ce062010-06-01 13:23:53 -0700381 String.format("Invalid response from daemon (%s)", rsp));
San Mehated4fc8a2010-01-22 12:28:36 -0800382 }
Kenny Roota80ce062010-06-01 13:23:53 -0700383
384 cfg = new InterfaceConfiguration();
385 cfg.hwAddr = st.nextToken(" ");
Robert Greenwalted126402011-01-28 15:34:55 -0800386 InetAddress addr = null;
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800387 int prefixLength = 0;
Kenny Roota80ce062010-06-01 13:23:53 -0700388 try {
Robert Greenwalte5903732011-02-22 16:00:42 -0800389 addr = NetworkUtils.numericToInetAddress(st.nextToken(" "));
390 } catch (IllegalArgumentException iae) {
391 Slog.e(TAG, "Failed to parse ipaddr", iae);
Kenny Roota80ce062010-06-01 13:23:53 -0700392 }
393
394 try {
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800395 prefixLength = Integer.parseInt(st.nextToken(" "));
396 } catch (NumberFormatException nfe) {
397 Slog.e(TAG, "Failed to parse prefixLength", nfe);
Kenny Roota80ce062010-06-01 13:23:53 -0700398 }
Robert Greenwalt04808c22010-12-13 17:01:41 -0800399
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800400 cfg.addr = new LinkAddress(addr, prefixLength);
Kenny Roota80ce062010-06-01 13:23:53 -0700401 cfg.interfaceFlags = st.nextToken("]").trim() +"]";
402 } catch (NoSuchElementException nsee) {
San Mehated4fc8a2010-01-22 12:28:36 -0800403 throw new IllegalStateException(
404 String.format("Invalid response from daemon (%s)", rsp));
405 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800406 Slog.d(TAG, String.format("flags <%s>", cfg.interfaceFlags));
San Mehated4fc8a2010-01-22 12:28:36 -0800407 return cfg;
408 }
409
410 public void setInterfaceConfig(
411 String iface, InterfaceConfiguration cfg) throws IllegalStateException {
Robert Greenwalted126402011-01-28 15:34:55 -0800412 LinkAddress linkAddr = cfg.addr;
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800413 if (linkAddr == null || linkAddr.getAddress() == null) {
414 throw new IllegalStateException("Null LinkAddress given");
Robert Greenwalted126402011-01-28 15:34:55 -0800415 }
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800416 String cmd = String.format("interface setcfg %s %s %d %s", iface,
417 linkAddr.getAddress().getHostAddress(),
418 linkAddr.getNetworkPrefixLength(),
419 cfg.interfaceFlags);
Kenny Roota80ce062010-06-01 13:23:53 -0700420 try {
421 mConnector.doCommand(cmd);
422 } catch (NativeDaemonConnectorException e) {
423 throw new IllegalStateException(
Robert Greenwalt81d5ad52010-12-16 11:27:38 -0800424 "Unable to communicate with native daemon to interface setcfg - " + e);
Kenny Roota80ce062010-06-01 13:23:53 -0700425 }
San Mehat873f2142010-01-14 10:25:07 -0800426 }
427
Irfan Sheriff7244c972011-08-05 20:40:45 -0700428 public void setInterfaceDown(String iface) throws IllegalStateException {
429 try {
430 InterfaceConfiguration ifcg = getInterfaceConfig(iface);
431 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
432 setInterfaceConfig(iface, ifcg);
433 } catch (NativeDaemonConnectorException e) {
434 throw new IllegalStateException(
435 "Unable to communicate with native daemon for interface down - " + e);
436 }
437 }
438
439 public void setInterfaceUp(String iface) throws IllegalStateException {
440 try {
441 InterfaceConfiguration ifcg = getInterfaceConfig(iface);
442 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
443 setInterfaceConfig(iface, ifcg);
444 } catch (NativeDaemonConnectorException e) {
445 throw new IllegalStateException(
446 "Unable to communicate with native daemon for interface up - " + e);
447 }
448 }
449
Irfan Sheriff73293612011-09-14 12:31:56 -0700450 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)
451 throws IllegalStateException {
452 String cmd = String.format("interface ipv6privacyextensions %s %s", iface,
453 enable ? "enable" : "disable");
454 try {
455 mConnector.doCommand(cmd);
456 } catch (NativeDaemonConnectorException e) {
457 throw new IllegalStateException(
458 "Unable to communicate with native daemon to set ipv6privacyextensions - " + e);
459 }
460 }
461
462
463
Irfan Sherifff5600612011-06-16 10:26:28 -0700464 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
465 IPv6 addresses on interface down, but we need to do full clean up here */
466 public void clearInterfaceAddresses(String iface) throws IllegalStateException {
467 String cmd = String.format("interface clearaddrs %s", iface);
468 try {
469 mConnector.doCommand(cmd);
470 } catch (NativeDaemonConnectorException e) {
471 throw new IllegalStateException(
472 "Unable to communicate with native daemon to interface clearallips - " + e);
473 }
474 }
475
repo sync7960d9f2011-09-29 12:40:02 -0700476 public void enableIpv6(String iface) throws IllegalStateException {
477 mContext.enforceCallingOrSelfPermission(
478 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
479 try {
480 mConnector.doCommand(String.format("interface ipv6 %s enable", iface));
481 } catch (NativeDaemonConnectorException e) {
482 throw new IllegalStateException(
483 "Unable to communicate to native daemon for enabling ipv6");
484 }
485 }
486
487 public void disableIpv6(String iface) throws IllegalStateException {
488 mContext.enforceCallingOrSelfPermission(
489 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
490 try {
491 mConnector.doCommand(String.format("interface ipv6 %s disable", iface));
492 } catch (NativeDaemonConnectorException e) {
493 throw new IllegalStateException(
494 "Unable to communicate to native daemon for disabling ipv6");
495 }
496 }
497
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700498 public void addRoute(String interfaceName, RouteInfo route) {
499 modifyRoute(interfaceName, ADD, route);
500 }
501
502 public void removeRoute(String interfaceName, RouteInfo route) {
503 modifyRoute(interfaceName, REMOVE, route);
504 }
505
506 private void modifyRoute(String interfaceName, int action, RouteInfo route) {
507 ArrayList<String> rsp;
508
509 StringBuilder cmd;
510
511 switch (action) {
512 case ADD:
513 {
514 cmd = new StringBuilder("interface route add " + interfaceName);
515 break;
516 }
517 case REMOVE:
518 {
519 cmd = new StringBuilder("interface route remove " + interfaceName);
520 break;
521 }
522 default:
523 throw new IllegalStateException("Unknown action type " + action);
524 }
525
526 // create triplet: dest-ip-addr prefixlength gateway-ip-addr
527 LinkAddress la = route.getDestination();
528 cmd.append(' ');
529 cmd.append(la.getAddress().getHostAddress());
530 cmd.append(' ');
531 cmd.append(la.getNetworkPrefixLength());
532 cmd.append(' ');
533 if (route.getGateway() == null) {
534 if (la.getAddress() instanceof Inet4Address) {
535 cmd.append("0.0.0.0");
536 } else {
537 cmd.append ("::0");
538 }
539 } else {
540 cmd.append(route.getGateway().getHostAddress());
541 }
542 try {
543 rsp = mConnector.doCommand(cmd.toString());
544 } catch (NativeDaemonConnectorException e) {
545 throw new IllegalStateException(
546 "Unable to communicate with native dameon to add routes - "
547 + e);
548 }
549
Wink Savillec9acde92011-09-21 11:05:43 -0700550 if (DBG) {
551 for (String line : rsp) {
552 Log.v(TAG, "add route response is " + line);
553 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700554 }
555 }
556
557 private ArrayList<String> readRouteList(String filename) {
558 FileInputStream fstream = null;
559 ArrayList<String> list = new ArrayList<String>();
560
561 try {
562 fstream = new FileInputStream(filename);
563 DataInputStream in = new DataInputStream(fstream);
564 BufferedReader br = new BufferedReader(new InputStreamReader(in));
565 String s;
566
567 // throw away the title line
568
569 while (((s = br.readLine()) != null) && (s.length() != 0)) {
570 list.add(s);
571 }
572 } catch (IOException ex) {
573 // return current list, possibly empty
574 } finally {
575 if (fstream != null) {
576 try {
577 fstream.close();
578 } catch (IOException ex) {}
579 }
580 }
581
582 return list;
583 }
584
585 public RouteInfo[] getRoutes(String interfaceName) {
586 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
587
588 // v4 routes listed as:
589 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT
590 for (String s : readRouteList("/proc/net/route")) {
591 String[] fields = s.split("\t");
592
593 if (fields.length > 7) {
594 String iface = fields[0];
595
596 if (interfaceName.equals(iface)) {
597 String dest = fields[1];
598 String gate = fields[2];
599 String flags = fields[3]; // future use?
600 String mask = fields[7];
601 try {
602 // address stored as a hex string, ex: 0014A8C0
603 InetAddress destAddr =
604 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16));
605 int prefixLength =
606 NetworkUtils.netmaskIntToPrefixLength(
607 (int)Long.parseLong(mask, 16));
608 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
609
610 // address stored as a hex string, ex 0014A8C0
611 InetAddress gatewayAddr =
612 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16));
613
614 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr);
615 routes.add(route);
616 } catch (Exception e) {
617 Log.e(TAG, "Error parsing route " + s + " : " + e);
618 continue;
619 }
620 }
621 }
622 }
623
624 // v6 routes listed as:
625 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface
626 for (String s : readRouteList("/proc/net/ipv6_route")) {
627 String[]fields = s.split("\\s+");
628 if (fields.length > 9) {
629 String iface = fields[9].trim();
630 if (interfaceName.equals(iface)) {
631 String dest = fields[0];
632 String prefix = fields[1];
633 String gate = fields[4];
634
635 try {
636 // prefix length stored as a hex string, ex 40
637 int prefixLength = Integer.parseInt(prefix, 16);
638
639 // address stored as a 32 char hex string
640 // ex fe800000000000000000000000000000
641 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest);
642 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
643
644 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate);
645
646 RouteInfo route = new RouteInfo(linkAddress, gateAddr);
647 routes.add(route);
648 } catch (Exception e) {
649 Log.e(TAG, "Error parsing route " + s + " : " + e);
650 continue;
651 }
652 }
653 }
654 }
655 return (RouteInfo[]) routes.toArray(new RouteInfo[0]);
656 }
657
San Mehat873f2142010-01-14 10:25:07 -0800658 public void shutdown() {
659 if (mContext.checkCallingOrSelfPermission(
660 android.Manifest.permission.SHUTDOWN)
661 != PackageManager.PERMISSION_GRANTED) {
662 throw new SecurityException("Requires SHUTDOWN permission");
663 }
664
Joe Onorato8a9b2202010-02-26 18:56:32 -0800665 Slog.d(TAG, "Shutting down");
San Mehat873f2142010-01-14 10:25:07 -0800666 }
667
668 public boolean getIpForwardingEnabled() throws IllegalStateException{
669 mContext.enforceCallingOrSelfPermission(
670 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
671
Kenny Roota80ce062010-06-01 13:23:53 -0700672 ArrayList<String> rsp;
673 try {
674 rsp = mConnector.doCommand("ipfwd status");
675 } catch (NativeDaemonConnectorException e) {
676 throw new IllegalStateException(
677 "Unable to communicate with native daemon to ipfwd status");
678 }
San Mehat873f2142010-01-14 10:25:07 -0800679
680 for (String line : rsp) {
Kenny Roota80ce062010-06-01 13:23:53 -0700681 String[] tok = line.split(" ");
682 if (tok.length < 3) {
683 Slog.e(TAG, "Malformed response from native daemon: " + line);
684 return false;
685 }
686
San Mehat873f2142010-01-14 10:25:07 -0800687 int code = Integer.parseInt(tok[0]);
688 if (code == NetdResponseCode.IpFwdStatusResult) {
689 // 211 Forwarding <enabled/disabled>
Kenny Roota80ce062010-06-01 13:23:53 -0700690 return "enabled".equals(tok[2]);
San Mehat873f2142010-01-14 10:25:07 -0800691 } else {
692 throw new IllegalStateException(String.format("Unexpected response code %d", code));
693 }
694 }
695 throw new IllegalStateException("Got an empty response");
696 }
697
698 public void setIpForwardingEnabled(boolean enable) throws IllegalStateException {
699 mContext.enforceCallingOrSelfPermission(
700 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
701 mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
702 }
703
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700704 public void startTethering(String[] dhcpRange)
San Mehat873f2142010-01-14 10:25:07 -0800705 throws IllegalStateException {
706 mContext.enforceCallingOrSelfPermission(
707 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700708 // cmd is "tether start first_start first_stop second_start second_stop ..."
709 // an odd number of addrs will fail
710 String cmd = "tether start";
711 for (String d : dhcpRange) {
712 cmd += " " + d;
713 }
Kenny Roota80ce062010-06-01 13:23:53 -0700714
715 try {
716 mConnector.doCommand(cmd);
717 } catch (NativeDaemonConnectorException e) {
718 throw new IllegalStateException("Unable to communicate to native daemon");
719 }
San Mehat873f2142010-01-14 10:25:07 -0800720 }
721
722 public void stopTethering() throws IllegalStateException {
723 mContext.enforceCallingOrSelfPermission(
724 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700725 try {
726 mConnector.doCommand("tether stop");
727 } catch (NativeDaemonConnectorException e) {
728 throw new IllegalStateException("Unable to communicate to native daemon to stop tether");
729 }
San Mehat873f2142010-01-14 10:25:07 -0800730 }
731
732 public boolean isTetheringStarted() throws IllegalStateException {
733 mContext.enforceCallingOrSelfPermission(
734 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
735
Kenny Roota80ce062010-06-01 13:23:53 -0700736 ArrayList<String> rsp;
737 try {
738 rsp = mConnector.doCommand("tether status");
739 } catch (NativeDaemonConnectorException e) {
740 throw new IllegalStateException(
741 "Unable to communicate to native daemon to get tether status");
742 }
San Mehat873f2142010-01-14 10:25:07 -0800743
744 for (String line : rsp) {
Kenny Roota80ce062010-06-01 13:23:53 -0700745 String[] tok = line.split(" ");
746 if (tok.length < 3) {
747 throw new IllegalStateException("Malformed response for tether status: " + line);
748 }
San Mehat873f2142010-01-14 10:25:07 -0800749 int code = Integer.parseInt(tok[0]);
750 if (code == NetdResponseCode.TetherStatusResult) {
751 // XXX: Tethering services <started/stopped> <TBD>...
Kenny Roota80ce062010-06-01 13:23:53 -0700752 return "started".equals(tok[2]);
San Mehat873f2142010-01-14 10:25:07 -0800753 } else {
754 throw new IllegalStateException(String.format("Unexpected response code %d", code));
755 }
756 }
757 throw new IllegalStateException("Got an empty response");
758 }
759
760 public void tetherInterface(String iface) throws IllegalStateException {
761 mContext.enforceCallingOrSelfPermission(
762 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700763 try {
764 mConnector.doCommand("tether interface add " + iface);
765 } catch (NativeDaemonConnectorException e) {
766 throw new IllegalStateException(
767 "Unable to communicate to native daemon for adding tether interface");
768 }
San Mehat873f2142010-01-14 10:25:07 -0800769 }
770
771 public void untetherInterface(String iface) {
772 mContext.enforceCallingOrSelfPermission(
773 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700774 try {
775 mConnector.doCommand("tether interface remove " + iface);
776 } catch (NativeDaemonConnectorException e) {
777 throw new IllegalStateException(
778 "Unable to communicate to native daemon for removing tether interface");
779 }
San Mehat873f2142010-01-14 10:25:07 -0800780 }
781
782 public String[] listTetheredInterfaces() throws IllegalStateException {
783 mContext.enforceCallingOrSelfPermission(
784 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700785 try {
786 return mConnector.doListCommand(
787 "tether interface list", NetdResponseCode.TetherInterfaceListResult);
788 } catch (NativeDaemonConnectorException e) {
789 throw new IllegalStateException(
790 "Unable to communicate to native daemon for listing tether interfaces");
791 }
San Mehat873f2142010-01-14 10:25:07 -0800792 }
793
794 public void setDnsForwarders(String[] dns) throws IllegalStateException {
795 mContext.enforceCallingOrSelfPermission(
796 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
797 try {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800798 String cmd = "tether dns set";
San Mehat873f2142010-01-14 10:25:07 -0800799 for (String s : dns) {
Robert Greenwalte5903732011-02-22 16:00:42 -0800800 cmd += " " + NetworkUtils.numericToInetAddress(s).getHostAddress();
San Mehat873f2142010-01-14 10:25:07 -0800801 }
Kenny Roota80ce062010-06-01 13:23:53 -0700802 try {
803 mConnector.doCommand(cmd);
804 } catch (NativeDaemonConnectorException e) {
805 throw new IllegalStateException(
806 "Unable to communicate to native daemon for setting tether dns");
807 }
Robert Greenwalte5903732011-02-22 16:00:42 -0800808 } catch (IllegalArgumentException e) {
San Mehat873f2142010-01-14 10:25:07 -0800809 throw new IllegalStateException("Error resolving dns name", e);
810 }
811 }
812
813 public String[] getDnsForwarders() throws IllegalStateException {
814 mContext.enforceCallingOrSelfPermission(
815 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700816 try {
817 return mConnector.doListCommand(
818 "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
819 } catch (NativeDaemonConnectorException e) {
820 throw new IllegalStateException(
821 "Unable to communicate to native daemon for listing tether dns");
822 }
San Mehat873f2142010-01-14 10:25:07 -0800823 }
824
825 public void enableNat(String internalInterface, String externalInterface)
826 throws IllegalStateException {
827 mContext.enforceCallingOrSelfPermission(
828 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700829 try {
830 mConnector.doCommand(
831 String.format("nat enable %s %s", internalInterface, externalInterface));
832 } catch (NativeDaemonConnectorException e) {
833 throw new IllegalStateException(
834 "Unable to communicate to native daemon for enabling NAT interface");
835 }
San Mehat873f2142010-01-14 10:25:07 -0800836 }
837
838 public void disableNat(String internalInterface, String externalInterface)
839 throws IllegalStateException {
840 mContext.enforceCallingOrSelfPermission(
841 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700842 try {
843 mConnector.doCommand(
844 String.format("nat disable %s %s", internalInterface, externalInterface));
845 } catch (NativeDaemonConnectorException e) {
846 throw new IllegalStateException(
847 "Unable to communicate to native daemon for disabling NAT interface");
848 }
San Mehat873f2142010-01-14 10:25:07 -0800849 }
San Mehat72759df2010-01-19 13:50:37 -0800850
851 public String[] listTtys() throws IllegalStateException {
852 mContext.enforceCallingOrSelfPermission(
853 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700854 try {
855 return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
856 } catch (NativeDaemonConnectorException e) {
857 throw new IllegalStateException(
858 "Unable to communicate to native daemon for listing TTYs");
859 }
San Mehat72759df2010-01-19 13:50:37 -0800860 }
861
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800862 public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr,
863 String dns2Addr) throws IllegalStateException {
San Mehat72759df2010-01-19 13:50:37 -0800864 try {
865 mContext.enforceCallingOrSelfPermission(
866 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800867 mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty,
Robert Greenwalte5903732011-02-22 16:00:42 -0800868 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
869 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
870 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
871 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()));
872 } catch (IllegalArgumentException e) {
San Mehat72759df2010-01-19 13:50:37 -0800873 throw new IllegalStateException("Error resolving addr", e);
Kenny Roota80ce062010-06-01 13:23:53 -0700874 } catch (NativeDaemonConnectorException e) {
875 throw new IllegalStateException("Error communicating to native daemon to attach pppd", e);
San Mehat72759df2010-01-19 13:50:37 -0800876 }
877 }
878
879 public void detachPppd(String tty) throws IllegalStateException {
880 mContext.enforceCallingOrSelfPermission(
881 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700882 try {
883 mConnector.doCommand(String.format("pppd detach %s", tty));
884 } catch (NativeDaemonConnectorException e) {
885 throw new IllegalStateException("Error communicating to native daemon to detach pppd", e);
886 }
San Mehat72759df2010-01-19 13:50:37 -0800887 }
Robert Greenwaltce1200d2010-02-18 11:25:54 -0800888
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700889 public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800890 throws IllegalStateException {
891 mContext.enforceCallingOrSelfPermission(
892 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
893 mContext.enforceCallingOrSelfPermission(
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700894 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700895 try {
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700896 wifiFirmwareReload(wlanIface, "AP");
Kenny Roota80ce062010-06-01 13:23:53 -0700897 mConnector.doCommand(String.format("softap start " + wlanIface));
898 if (wifiConfig == null) {
899 mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
900 } else {
901 /**
902 * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8]
903 * argv1 - wlan interface
904 * argv2 - softap interface
905 * argv3 - SSID
906 * argv4 - Security
907 * argv5 - Key
908 * argv6 - Channel
909 * argv7 - Preamble
910 * argv8 - Max SCB
911 */
Irfan Sheriffec8d23a2011-02-16 17:00:33 -0800912 String str = String.format("softap set " + wlanIface + " " + softapIface +
913 " %s %s %s", convertQuotedString(wifiConfig.SSID),
914 getSecurityType(wifiConfig),
915 convertQuotedString(wifiConfig.preSharedKey));
Kenny Roota80ce062010-06-01 13:23:53 -0700916 mConnector.doCommand(str);
917 }
918 mConnector.doCommand(String.format("softap startap"));
919 } catch (NativeDaemonConnectorException e) {
920 throw new IllegalStateException("Error communicating to native daemon to start softap", e);
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800921 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800922 }
923
Irfan Sheriffa6e559e2010-05-24 14:55:42 -0700924 private String convertQuotedString(String s) {
Irfan Sheriff7baec0f2010-05-26 17:16:47 -0700925 if (s == null) {
926 return s;
927 }
928 /* Replace \ with \\, then " with \" and add quotes at end */
929 return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"';
Irfan Sheriffa6e559e2010-05-24 14:55:42 -0700930 }
931
Irfan Sheriffec8d23a2011-02-16 17:00:33 -0800932 private String getSecurityType(WifiConfiguration wifiConfig) {
933 switch (wifiConfig.getAuthType()) {
934 case KeyMgmt.WPA_PSK:
935 return "wpa-psk";
936 case KeyMgmt.WPA2_PSK:
937 return "wpa2-psk";
938 default:
939 return "open";
940 }
941 }
942
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700943 /* @param mode can be "AP", "STA" or "P2P" */
944 public void wifiFirmwareReload(String wlanIface, String mode) throws IllegalStateException {
945 mContext.enforceCallingOrSelfPermission(
946 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
947 mContext.enforceCallingOrSelfPermission(
948 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
949
950 try {
951 mConnector.doCommand(String.format("softap fwreload " + wlanIface + " " + mode));
952 } catch (NativeDaemonConnectorException e) {
953 throw new IllegalStateException("Error communicating to native daemon ", e);
954 }
955 }
956
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700957 public void stopAccessPoint(String wlanIface) throws IllegalStateException {
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800958 mContext.enforceCallingOrSelfPermission(
959 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
960 mContext.enforceCallingOrSelfPermission(
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700961 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700962 try {
963 mConnector.doCommand("softap stopap");
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700964 mConnector.doCommand("softap stop " + wlanIface);
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700965 wifiFirmwareReload(wlanIface, "STA");
Kenny Roota80ce062010-06-01 13:23:53 -0700966 } catch (NativeDaemonConnectorException e) {
967 throw new IllegalStateException("Error communicating to native daemon to stop soft AP",
968 e);
969 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800970 }
971
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700972 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
973 throws IllegalStateException {
974 mContext.enforceCallingOrSelfPermission(
975 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
976 mContext.enforceCallingOrSelfPermission(
977 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700978 try {
979 if (wifiConfig == null) {
980 mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
981 } else {
982 String str = String.format("softap set " + wlanIface + " " + softapIface
983 + " %s %s %s", convertQuotedString(wifiConfig.SSID),
Irfan Sheriffec8d23a2011-02-16 17:00:33 -0800984 getSecurityType(wifiConfig),
Kenny Roota80ce062010-06-01 13:23:53 -0700985 convertQuotedString(wifiConfig.preSharedKey));
986 mConnector.doCommand(str);
987 }
988 } catch (NativeDaemonConnectorException e) {
989 throw new IllegalStateException("Error communicating to native daemon to set soft AP",
990 e);
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700991 }
992 }
San Mehat91cac642010-03-31 14:31:36 -0700993
994 private long getInterfaceCounter(String iface, boolean rx) {
995 mContext.enforceCallingOrSelfPermission(
996 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
997 try {
Kenny Roota80ce062010-06-01 13:23:53 -0700998 String rsp;
999 try {
1000 rsp = mConnector.doCommand(
1001 String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0);
1002 } catch (NativeDaemonConnectorException e1) {
1003 Slog.e(TAG, "Error communicating with native daemon", e1);
1004 return -1;
1005 }
1006
1007 String[] tok = rsp.split(" ");
1008 if (tok.length < 2) {
1009 Slog.e(TAG, String.format("Malformed response for reading %s interface",
1010 (rx ? "rx" : "tx")));
1011 return -1;
1012 }
1013
San Mehat91cac642010-03-31 14:31:36 -07001014 int code;
1015 try {
1016 code = Integer.parseInt(tok[0]);
1017 } catch (NumberFormatException nfe) {
1018 Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
1019 return -1;
1020 }
1021 if ((rx && code != NetdResponseCode.InterfaceRxCounterResult) || (
1022 !rx && code != NetdResponseCode.InterfaceTxCounterResult)) {
1023 Slog.e(TAG, String.format("Unexpected response code %d", code));
1024 return -1;
1025 }
1026 return Long.parseLong(tok[1]);
1027 } catch (Exception e) {
1028 Slog.e(TAG, String.format(
1029 "Failed to read interface %s counters", (rx ? "rx" : "tx")), e);
1030 }
1031 return -1;
1032 }
1033
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001034 @Override
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001035 public NetworkStats getNetworkStatsSummary() {
1036 mContext.enforceCallingOrSelfPermission(
1037 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001038 return mStatsFactory.readNetworkStatsSummary();
Jeff Sharkeyae2c1812011-10-04 13:11:40 -07001039 }
1040
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001041 @Override
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001042 public NetworkStats getNetworkStatsDetail() {
1043 mContext.enforceCallingOrSelfPermission(
1044 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001045 return mStatsFactory.readNetworkStatsDetail(UID_ALL);
San Mehat91cac642010-03-31 14:31:36 -07001046 }
1047
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001048 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001049 public void setInterfaceQuota(String iface, long quotaBytes) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001050 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1051
Jeff Sharkey350083e2011-06-29 10:45:16 -07001052 // silently discard when control disabled
1053 // TODO: eventually migrate to be always enabled
1054 if (!mBandwidthControlEnabled) return;
1055
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001056 synchronized (mQuotaLock) {
1057 if (mActiveQuotaIfaces.contains(iface)) {
1058 throw new IllegalStateException("iface " + iface + " already has quota");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001059 }
1060
1061 final StringBuilder command = new StringBuilder();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001062 command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001063
1064 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001065 // TODO: support quota shared across interfaces
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001066 mConnector.doCommand(command.toString());
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001067 mActiveQuotaIfaces.add(iface);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001068 } catch (NativeDaemonConnectorException e) {
1069 throw new IllegalStateException("Error communicating to native daemon", e);
1070 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001071 }
1072 }
1073
1074 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001075 public void removeInterfaceQuota(String iface) {
1076 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1077
Jeff Sharkey350083e2011-06-29 10:45:16 -07001078 // silently discard when control disabled
1079 // TODO: eventually migrate to be always enabled
1080 if (!mBandwidthControlEnabled) return;
1081
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001082 synchronized (mQuotaLock) {
1083 if (!mActiveQuotaIfaces.contains(iface)) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001084 // TODO: eventually consider throwing
1085 return;
1086 }
1087
1088 final StringBuilder command = new StringBuilder();
1089 command.append("bandwidth removeiquota ").append(iface);
1090
1091 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001092 // TODO: support quota shared across interfaces
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001093 mConnector.doCommand(command.toString());
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001094 mActiveQuotaIfaces.remove(iface);
1095 mActiveAlertIfaces.remove(iface);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001096 } catch (NativeDaemonConnectorException e) {
1097 throw new IllegalStateException("Error communicating to native daemon", e);
1098 }
1099 }
1100 }
1101
1102 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001103 public void setInterfaceAlert(String iface, long alertBytes) {
1104 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1105
1106 // silently discard when control disabled
1107 // TODO: eventually migrate to be always enabled
1108 if (!mBandwidthControlEnabled) return;
1109
1110 // quick sanity check
1111 if (!mActiveQuotaIfaces.contains(iface)) {
1112 throw new IllegalStateException("setting alert requires existing quota on iface");
1113 }
1114
1115 synchronized (mQuotaLock) {
1116 if (mActiveAlertIfaces.contains(iface)) {
1117 throw new IllegalStateException("iface " + iface + " already has alert");
1118 }
1119
1120 final StringBuilder command = new StringBuilder();
1121 command.append("bandwidth setinterfacealert ").append(iface).append(" ").append(
1122 alertBytes);
1123
1124 try {
1125 // TODO: support alert shared across interfaces
1126 mConnector.doCommand(command.toString());
1127 mActiveAlertIfaces.add(iface);
1128 } catch (NativeDaemonConnectorException e) {
1129 throw new IllegalStateException("Error communicating to native daemon", e);
1130 }
1131 }
1132 }
1133
1134 @Override
1135 public void removeInterfaceAlert(String iface) {
1136 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1137
1138 // silently discard when control disabled
1139 // TODO: eventually migrate to be always enabled
1140 if (!mBandwidthControlEnabled) return;
1141
1142 synchronized (mQuotaLock) {
1143 if (!mActiveAlertIfaces.contains(iface)) {
1144 // TODO: eventually consider throwing
1145 return;
1146 }
1147
1148 final StringBuilder command = new StringBuilder();
1149 command.append("bandwidth removeinterfacealert ").append(iface);
1150
1151 try {
1152 // TODO: support alert shared across interfaces
1153 mConnector.doCommand(command.toString());
1154 mActiveAlertIfaces.remove(iface);
1155 } catch (NativeDaemonConnectorException e) {
1156 throw new IllegalStateException("Error communicating to native daemon", e);
1157 }
1158 }
1159 }
1160
1161 @Override
1162 public void setGlobalAlert(long alertBytes) {
1163 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1164
1165 // silently discard when control disabled
1166 // TODO: eventually migrate to be always enabled
1167 if (!mBandwidthControlEnabled) return;
1168
1169 final StringBuilder command = new StringBuilder();
1170 command.append("bandwidth setglobalalert ").append(alertBytes);
1171
1172 try {
1173 mConnector.doCommand(command.toString());
1174 } catch (NativeDaemonConnectorException e) {
1175 throw new IllegalStateException("Error communicating to native daemon", e);
1176 }
1177 }
1178
1179 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001180 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
1181 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1182
Jeff Sharkey350083e2011-06-29 10:45:16 -07001183 // silently discard when control disabled
1184 // TODO: eventually migrate to be always enabled
1185 if (!mBandwidthControlEnabled) return;
1186
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001187 synchronized (mUidRejectOnQuota) {
1188 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
1189 if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
1190 // TODO: eventually consider throwing
1191 return;
1192 }
1193
1194 final StringBuilder command = new StringBuilder();
1195 command.append("bandwidth");
1196 if (rejectOnQuotaInterfaces) {
1197 command.append(" addnaughtyapps");
1198 } else {
1199 command.append(" removenaughtyapps");
1200 }
1201 command.append(" ").append(uid);
1202
1203 try {
1204 mConnector.doCommand(command.toString());
1205 if (rejectOnQuotaInterfaces) {
1206 mUidRejectOnQuota.put(uid, true);
1207 } else {
1208 mUidRejectOnQuota.delete(uid);
1209 }
1210 } catch (NativeDaemonConnectorException e) {
1211 throw new IllegalStateException("Error communicating to native daemon", e);
1212 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001213 }
1214 }
1215
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001216 @Override
1217 public boolean isBandwidthControlEnabled() {
1218 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1219 return mBandwidthControlEnabled;
1220 }
1221
1222 @Override
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001223 public NetworkStats getNetworkStatsUidDetail(int uid) {
1224 if (Binder.getCallingUid() != uid) {
1225 mContext.enforceCallingOrSelfPermission(
1226 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
1227 }
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001228 return mStatsFactory.readNetworkStatsDetail(uid);
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001229 }
1230
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001231 @Override
1232 public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
1233 mContext.enforceCallingOrSelfPermission(
1234 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
1235
1236 if (ifacePairs.length % 2 != 0) {
1237 throw new IllegalArgumentException(
1238 "unexpected ifacePairs; length=" + ifacePairs.length);
1239 }
1240
1241 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1242 for (int i = 0; i < ifacePairs.length; i += 2) {
1243 final String ifaceIn = ifacePairs[i];
1244 final String ifaceOut = ifacePairs[i + 1];
1245 if (ifaceIn != null && ifaceOut != null) {
1246 stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
1247 }
1248 }
1249 return stats;
1250 }
1251
1252 private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
1253 final StringBuilder command = new StringBuilder();
1254 command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut);
1255
1256 final String rsp;
1257 try {
1258 rsp = mConnector.doCommand(command.toString()).get(0);
1259 } catch (NativeDaemonConnectorException e) {
1260 throw new IllegalStateException("Error communicating to native daemon", e);
1261 }
1262
1263 final String[] tok = rsp.split(" ");
1264 /* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */
1265 if (tok.length != 7) {
1266 throw new IllegalStateException("Native daemon returned unexpected result: " + rsp);
1267 }
1268
1269 final int code;
1270 try {
1271 code = Integer.parseInt(tok[0]);
1272 } catch (NumberFormatException e) {
1273 throw new IllegalStateException(
1274 "Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut);
1275 }
1276 if (code != NetdResponseCode.TetheringStatsResult) {
1277 throw new IllegalStateException(
1278 "Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut);
1279 }
1280
1281 try {
1282 final NetworkStats.Entry entry = new NetworkStats.Entry();
1283 entry.iface = ifaceIn;
Jeff Sharkey905b5892011-09-30 15:19:49 -07001284 entry.uid = UID_TETHERING;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001285 entry.set = SET_DEFAULT;
1286 entry.tag = TAG_NONE;
1287 entry.rxBytes = Long.parseLong(tok[3]);
1288 entry.rxPackets = Long.parseLong(tok[4]);
1289 entry.txBytes = Long.parseLong(tok[5]);
1290 entry.txPackets = Long.parseLong(tok[6]);
1291 return entry;
1292 } catch (NumberFormatException e) {
1293 throw new IllegalStateException(
1294 "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
1295 }
1296 }
1297
San Mehatf0db6e12010-04-07 15:22:10 -07001298 public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
San Mehat91cac642010-03-31 14:31:36 -07001299 mContext.enforceCallingOrSelfPermission(
1300 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -07001301 try {
1302 mConnector.doCommand(String.format(
1303 "interface setthrottle %s %d %d", iface, rxKbps, txKbps));
1304 } catch (NativeDaemonConnectorException e) {
1305 Slog.e(TAG, "Error communicating with native daemon to set throttle", e);
1306 }
San Mehat91cac642010-03-31 14:31:36 -07001307 }
1308
1309 private int getInterfaceThrottle(String iface, boolean rx) {
1310 mContext.enforceCallingOrSelfPermission(
1311 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
1312 try {
Kenny Roota80ce062010-06-01 13:23:53 -07001313 String rsp;
1314 try {
1315 rsp = mConnector.doCommand(
1316 String.format("interface getthrottle %s %s", iface,
1317 (rx ? "rx" : "tx"))).get(0);
1318 } catch (NativeDaemonConnectorException e) {
1319 Slog.e(TAG, "Error communicating with native daemon to getthrottle", e);
1320 return -1;
1321 }
1322
1323 String[] tok = rsp.split(" ");
1324 if (tok.length < 2) {
1325 Slog.e(TAG, "Malformed response to getthrottle command");
1326 return -1;
1327 }
1328
San Mehat91cac642010-03-31 14:31:36 -07001329 int code;
1330 try {
1331 code = Integer.parseInt(tok[0]);
1332 } catch (NumberFormatException nfe) {
1333 Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
1334 return -1;
1335 }
1336 if ((rx && code != NetdResponseCode.InterfaceRxThrottleResult) || (
1337 !rx && code != NetdResponseCode.InterfaceTxThrottleResult)) {
1338 Slog.e(TAG, String.format("Unexpected response code %d", code));
1339 return -1;
1340 }
1341 return Integer.parseInt(tok[1]);
1342 } catch (Exception e) {
1343 Slog.e(TAG, String.format(
1344 "Failed to read interface %s throttle value", (rx ? "rx" : "tx")), e);
1345 }
1346 return -1;
1347 }
1348
1349 public int getInterfaceRxThrottle(String iface) {
1350 return getInterfaceThrottle(iface, true);
1351 }
1352
1353 public int getInterfaceTxThrottle(String iface) {
1354 return getInterfaceThrottle(iface, false);
1355 }
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001356
Mattias Falk7475c0c2011-04-04 16:10:36 +02001357 public void setDefaultInterfaceForDns(String iface) throws IllegalStateException {
1358 mContext.enforceCallingOrSelfPermission(
1359 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
1360 try {
1361 String cmd = "resolver setdefaultif " + iface;
1362
1363 mConnector.doCommand(cmd);
1364 } catch (NativeDaemonConnectorException e) {
1365 throw new IllegalStateException(
1366 "Error communicating with native daemon to set default interface", e);
1367 }
1368 }
1369
1370 public void setDnsServersForInterface(String iface, String[] servers)
1371 throws IllegalStateException {
1372 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE,
1373 "NetworkManagementService");
1374 try {
1375 String cmd = "resolver setifdns " + iface;
1376 for (String s : servers) {
Robert Greenwalt572b7042011-07-25 17:00:13 -07001377 InetAddress a = NetworkUtils.numericToInetAddress(s);
1378 if (a.isAnyLocalAddress() == false) {
1379 cmd += " " + a.getHostAddress();
Mattias Falk7475c0c2011-04-04 16:10:36 +02001380 }
1381 }
Mattias Falk7475c0c2011-04-04 16:10:36 +02001382 mConnector.doCommand(cmd);
Robert Greenwalt572b7042011-07-25 17:00:13 -07001383 } catch (IllegalArgumentException e) {
1384 throw new IllegalStateException("Error setting dnsn for interface", e);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001385 } catch (NativeDaemonConnectorException e) {
1386 throw new IllegalStateException(
Robert Greenwalt572b7042011-07-25 17:00:13 -07001387 "Error communicating with native daemon to set dns for interface", e);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001388 }
1389 }
1390
1391 public void flushDefaultDnsCache() throws IllegalStateException {
1392 mContext.enforceCallingOrSelfPermission(
1393 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
1394 try {
1395 String cmd = "resolver flushdefaultif";
1396
1397 mConnector.doCommand(cmd);
1398 } catch (NativeDaemonConnectorException e) {
1399 throw new IllegalStateException(
1400 "Error communicating with native deamon to flush default interface", e);
1401 }
1402 }
1403
1404 public void flushInterfaceDnsCache(String iface) throws IllegalStateException {
1405 mContext.enforceCallingOrSelfPermission(
1406 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
1407 try {
1408 String cmd = "resolver flushif " + iface;
1409
1410 mConnector.doCommand(cmd);
1411 } catch (NativeDaemonConnectorException e) {
1412 throw new IllegalStateException(
Robert Greenwalt572b7042011-07-25 17:00:13 -07001413 "Error communicating with native daemon to flush interface " + iface, e);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001414 }
1415 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07001416
1417 /** {@inheritDoc} */
1418 public void monitor() {
1419 if (mConnector != null) {
1420 mConnector.monitor();
1421 }
1422 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001423
1424 @Override
1425 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1426 mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1427
1428 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
1429
1430 synchronized (mQuotaLock) {
1431 pw.print("Active quota ifaces: "); pw.println(mActiveQuotaIfaces.toString());
1432 pw.print("Active alert ifaces: "); pw.println(mActiveAlertIfaces.toString());
1433 }
1434
1435 synchronized (mUidRejectOnQuota) {
1436 pw.print("UID reject on quota ifaces: [");
1437 final int size = mUidRejectOnQuota.size();
1438 for (int i = 0; i < size; i++) {
1439 pw.print(mUidRejectOnQuota.keyAt(i));
1440 if (i < size - 1) pw.print(",");
1441 }
1442 pw.println("]");
1443 }
1444 }
San Mehat873f2142010-01-14 10:25:07 -08001445}