blob: 97fa0cc229effcd8847c98cd97c0462b0f86a6fd [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
19import android.app.PendingIntent;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.res.Resources;
25import android.content.pm.PackageManager;
26import android.net.Uri;
27import android.os.INetworkManagementService;
28import android.os.Handler;
29import android.text.TextUtils;
30import android.util.Log;
31import java.util.ArrayList;
32
33import android.provider.Settings;
34import android.content.ContentResolver;
35import android.database.ContentObserver;
36
37import java.io.File;
38import java.io.FileReader;
39import java.lang.IllegalStateException;
40
41import java.net.InetAddress;
42import java.net.UnknownHostException;
43
44/**
45 * @hide
46 */
47class NetworkManagementService extends INetworkManagementService.Stub {
48
49 private static final String TAG = "NetworkManagmentService";
50
51 class NetdResponseCode {
52 public static final int InterfaceListResult = 110;
53 public static final int TetherInterfaceListResult = 111;
54 public static final int TetherDnsFwdTgtListResult = 112;
55
56 public static final int TetherStatusResult = 210;
57 public static final int IpFwdStatusResult = 211;
58 }
59
60 /**
61 * Binder context for this service
62 */
63 private Context mContext;
64
65 /**
66 * connector object for communicating with netd
67 */
68 private NativeDaemonConnector mConnector;
69
70 /**
71 * Constructs a new NetworkManagementService instance
72 *
73 * @param context Binder context for this service
74 */
75 private NetworkManagementService(Context context) {
76 mContext = context;
77
78 mConnector = new NativeDaemonConnector(
79 new NetdCallbackReceiver(), "netd", 10, "NetdConnector");
80 Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
81 thread.start();
82 }
83
84 //
85 // Netd Callback handling
86 //
87
88 class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
89 public void onDaemonConnected() {
90 new Thread() {
91 public void run() {
92 // XXX: Run some tests
93 }
94 }.start();
95 }
96 public boolean onEvent(int code, String raw, String[] cooked) {
97 return false;
98 }
99 }
100
101 //
102 // INetworkManagementService members
103 //
104
105 public String[] listInterfaces() throws IllegalStateException {
106 mContext.enforceCallingOrSelfPermission(
107 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
108
109 ArrayList<String> rsp = mConnector.doCommand("list_interfaces");
110
111 String[] rdata = new String[rsp.size()];
112 int idx = 0;
113
114 for (String line : rsp) {
115 String []tok = line.split(" ");
116 int code = Integer.parseInt(tok[0]);
117 if (code == NetdResponseCode.InterfaceListResult) {
118 if (tok.length !=2) {
119 throw new IllegalStateException(
120 String.format("Malformatted list entry '%s'", line));
121 }
122 rdata[idx++] = tok[1];
123 } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
124 return rdata;
125 } else {
126 throw new IllegalStateException(String.format("Unexpected response code %d", code));
127 }
128 }
129 throw new IllegalStateException("Got an empty response");
130 }
131
132 public void shutdown() {
133 if (mContext.checkCallingOrSelfPermission(
134 android.Manifest.permission.SHUTDOWN)
135 != PackageManager.PERMISSION_GRANTED) {
136 throw new SecurityException("Requires SHUTDOWN permission");
137 }
138
139 Log.d(TAG, "Shutting down");
140 }
141
142 public boolean getIpForwardingEnabled() throws IllegalStateException{
143 mContext.enforceCallingOrSelfPermission(
144 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
145
146 ArrayList<String> rsp = mConnector.doCommand("ipfwd status");
147
148 for (String line : rsp) {
149 String []tok = line.split(" ");
150 int code = Integer.parseInt(tok[0]);
151 if (code == NetdResponseCode.IpFwdStatusResult) {
152 // 211 Forwarding <enabled/disabled>
153 if (tok.length !=2) {
154 throw new IllegalStateException(
155 String.format("Malformatted list entry '%s'", line));
156 }
157 if (tok[2].equals("enabled"))
158 return true;
159 return false;
160 } else {
161 throw new IllegalStateException(String.format("Unexpected response code %d", code));
162 }
163 }
164 throw new IllegalStateException("Got an empty response");
165 }
166
167 public void setIpForwardingEnabled(boolean enable) throws IllegalStateException {
168 mContext.enforceCallingOrSelfPermission(
169 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
170 mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
171 }
172
173 public void startTethering(String dhcpRangeStart, String dhcpRangeEnd)
174 throws IllegalStateException {
175 mContext.enforceCallingOrSelfPermission(
176 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
177 mConnector.doCommand(String.format("tether start %s %s", dhcpRangeStart, dhcpRangeEnd));
178 }
179
180 public void stopTethering() throws IllegalStateException {
181 mContext.enforceCallingOrSelfPermission(
182 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
183 mConnector.doCommand("tether stop");
184 }
185
186 public boolean isTetheringStarted() throws IllegalStateException {
187 mContext.enforceCallingOrSelfPermission(
188 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
189
190 ArrayList<String> rsp = mConnector.doCommand("tether status");
191
192 for (String line : rsp) {
193 String []tok = line.split(" ");
194 int code = Integer.parseInt(tok[0]);
195 if (code == NetdResponseCode.TetherStatusResult) {
196 // XXX: Tethering services <started/stopped> <TBD>...
197 if (tok[2].equals("started"))
198 return true;
199 return false;
200 } else {
201 throw new IllegalStateException(String.format("Unexpected response code %d", code));
202 }
203 }
204 throw new IllegalStateException("Got an empty response");
205 }
206
207 public void tetherInterface(String iface) throws IllegalStateException {
208 mContext.enforceCallingOrSelfPermission(
209 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
210 mConnector.doCommand("tether interface add " + iface);
211 }
212
213 public void untetherInterface(String iface) {
214 mContext.enforceCallingOrSelfPermission(
215 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
216 mConnector.doCommand("tether interface remove " + iface);
217 }
218
219 public String[] listTetheredInterfaces() throws IllegalStateException {
220 mContext.enforceCallingOrSelfPermission(
221 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
222
223 ArrayList<String> rsp = mConnector.doCommand("tether interface list");
224
225 String[] rdata = new String[rsp.size()];
226 int idx = 0;
227
228 for (String line : rsp) {
229 String []tok = line.split(" ");
230 int code = Integer.parseInt(tok[0]);
231 if (code == NetdResponseCode.TetherInterfaceListResult) {
232 if (tok.length !=2) {
233 throw new IllegalStateException(
234 String.format("Malformatted list entry '%s'", line));
235 }
236 rdata[idx++] = tok[1];
237 } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
238 return rdata;
239 } else {
240 throw new IllegalStateException(String.format("Unexpected response code %d", code));
241 }
242 }
243 throw new IllegalStateException("Got an empty response");
244 }
245
246 public void setDnsForwarders(String[] dns) throws IllegalStateException {
247 mContext.enforceCallingOrSelfPermission(
248 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
249 try {
250 String cmd = "tether dns set ";
251 for (String s : dns) {
252 cmd += InetAddress.getByName(s).toString() + " ";
253 }
254 mConnector.doCommand(cmd);
255 } catch (UnknownHostException e) {
256 throw new IllegalStateException("Error resolving dns name", e);
257 }
258 }
259
260 public String[] getDnsForwarders() throws IllegalStateException {
261 mContext.enforceCallingOrSelfPermission(
262 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
263
264 ArrayList<String> rsp = mConnector.doCommand("tether dns list");
265
266 String[] rdata = new String[rsp.size()];
267 int idx = 0;
268
269 for (String line : rsp) {
270 String []tok = line.split(" ");
271 int code = Integer.parseInt(tok[0]);
272 if (code == NetdResponseCode.TetherDnsFwdTgtListResult) {
273 if (tok.length !=2) {
274 throw new IllegalStateException(
275 String.format("Malformatted list entry '%s'", line));
276 }
277 rdata[idx++] = tok[1];
278 } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
279 return rdata;
280 } else {
281 throw new IllegalStateException(String.format("Unexpected response code %d", code));
282 }
283 }
284 throw new IllegalStateException("Got an empty response");
285 }
286
287 public void enableNat(String internalInterface, String externalInterface)
288 throws IllegalStateException {
289 mContext.enforceCallingOrSelfPermission(
290 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
291 mConnector.doCommand(
292 String.format("nat enable %s %s", internalInterface, externalInterface));
293 }
294
295 public void disableNat(String internalInterface, String externalInterface)
296 throws IllegalStateException {
297 mContext.enforceCallingOrSelfPermission(
298 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
299 mConnector.doCommand(
300 String.format("nat disable %s %s", internalInterface, externalInterface));
301 }
302}
303