blob: a4abddb461374e0adbbe089860abe8135dc24729 [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;
San Mehat72759df2010-01-19 13:50:37 -080055 public static final int TtyListResult = 113;
San Mehat873f2142010-01-14 10:25:07 -080056
57 public static final int TetherStatusResult = 210;
58 public static final int IpFwdStatusResult = 211;
59 }
60
61 /**
62 * Binder context for this service
63 */
64 private Context mContext;
65
66 /**
67 * connector object for communicating with netd
68 */
69 private NativeDaemonConnector mConnector;
70
71 /**
72 * Constructs a new NetworkManagementService instance
73 *
74 * @param context Binder context for this service
75 */
76 private NetworkManagementService(Context context) {
77 mContext = context;
78
79 mConnector = new NativeDaemonConnector(
80 new NetdCallbackReceiver(), "netd", 10, "NetdConnector");
81 Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
82 thread.start();
83 }
84
85 //
86 // Netd Callback handling
87 //
88
89 class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
90 public void onDaemonConnected() {
91 new Thread() {
92 public void run() {
93 // XXX: Run some tests
94 }
95 }.start();
96 }
97 public boolean onEvent(int code, String raw, String[] cooked) {
98 return false;
99 }
100 }
101
102 //
103 // INetworkManagementService members
104 //
105
106 public String[] listInterfaces() throws IllegalStateException {
107 mContext.enforceCallingOrSelfPermission(
108 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
109
San Mehat72759df2010-01-19 13:50:37 -0800110 return mConnector.doListCommand("list_interfaces", NetdResponseCode.InterfaceListResult);
San Mehat873f2142010-01-14 10:25:07 -0800111 }
112
113 public void shutdown() {
114 if (mContext.checkCallingOrSelfPermission(
115 android.Manifest.permission.SHUTDOWN)
116 != PackageManager.PERMISSION_GRANTED) {
117 throw new SecurityException("Requires SHUTDOWN permission");
118 }
119
120 Log.d(TAG, "Shutting down");
121 }
122
123 public boolean getIpForwardingEnabled() throws IllegalStateException{
124 mContext.enforceCallingOrSelfPermission(
125 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
126
127 ArrayList<String> rsp = mConnector.doCommand("ipfwd status");
128
129 for (String line : rsp) {
130 String []tok = line.split(" ");
131 int code = Integer.parseInt(tok[0]);
132 if (code == NetdResponseCode.IpFwdStatusResult) {
133 // 211 Forwarding <enabled/disabled>
134 if (tok.length !=2) {
135 throw new IllegalStateException(
136 String.format("Malformatted list entry '%s'", line));
137 }
138 if (tok[2].equals("enabled"))
139 return true;
140 return false;
141 } else {
142 throw new IllegalStateException(String.format("Unexpected response code %d", code));
143 }
144 }
145 throw new IllegalStateException("Got an empty response");
146 }
147
148 public void setIpForwardingEnabled(boolean enable) throws IllegalStateException {
149 mContext.enforceCallingOrSelfPermission(
150 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
151 mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
152 }
153
154 public void startTethering(String dhcpRangeStart, String dhcpRangeEnd)
155 throws IllegalStateException {
156 mContext.enforceCallingOrSelfPermission(
157 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
158 mConnector.doCommand(String.format("tether start %s %s", dhcpRangeStart, dhcpRangeEnd));
159 }
160
161 public void stopTethering() throws IllegalStateException {
162 mContext.enforceCallingOrSelfPermission(
163 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
164 mConnector.doCommand("tether stop");
165 }
166
167 public boolean isTetheringStarted() throws IllegalStateException {
168 mContext.enforceCallingOrSelfPermission(
169 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
170
171 ArrayList<String> rsp = mConnector.doCommand("tether status");
172
173 for (String line : rsp) {
174 String []tok = line.split(" ");
175 int code = Integer.parseInt(tok[0]);
176 if (code == NetdResponseCode.TetherStatusResult) {
177 // XXX: Tethering services <started/stopped> <TBD>...
178 if (tok[2].equals("started"))
179 return true;
180 return false;
181 } else {
182 throw new IllegalStateException(String.format("Unexpected response code %d", code));
183 }
184 }
185 throw new IllegalStateException("Got an empty response");
186 }
187
188 public void tetherInterface(String iface) throws IllegalStateException {
189 mContext.enforceCallingOrSelfPermission(
190 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
191 mConnector.doCommand("tether interface add " + iface);
192 }
193
194 public void untetherInterface(String iface) {
195 mContext.enforceCallingOrSelfPermission(
196 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
197 mConnector.doCommand("tether interface remove " + iface);
198 }
199
200 public String[] listTetheredInterfaces() throws IllegalStateException {
201 mContext.enforceCallingOrSelfPermission(
202 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
San Mehat72759df2010-01-19 13:50:37 -0800203 return mConnector.doListCommand(
204 "tether interface list", NetdResponseCode.TetherInterfaceListResult);
San Mehat873f2142010-01-14 10:25:07 -0800205 }
206
207 public void setDnsForwarders(String[] dns) throws IllegalStateException {
208 mContext.enforceCallingOrSelfPermission(
209 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
210 try {
211 String cmd = "tether dns set ";
212 for (String s : dns) {
213 cmd += InetAddress.getByName(s).toString() + " ";
214 }
215 mConnector.doCommand(cmd);
216 } catch (UnknownHostException e) {
217 throw new IllegalStateException("Error resolving dns name", e);
218 }
219 }
220
221 public String[] getDnsForwarders() throws IllegalStateException {
222 mContext.enforceCallingOrSelfPermission(
223 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
San Mehat72759df2010-01-19 13:50:37 -0800224 return mConnector.doListCommand(
225 "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
San Mehat873f2142010-01-14 10:25:07 -0800226 }
227
228 public void enableNat(String internalInterface, String externalInterface)
229 throws IllegalStateException {
230 mContext.enforceCallingOrSelfPermission(
231 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
232 mConnector.doCommand(
233 String.format("nat enable %s %s", internalInterface, externalInterface));
234 }
235
236 public void disableNat(String internalInterface, String externalInterface)
237 throws IllegalStateException {
238 mContext.enforceCallingOrSelfPermission(
239 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
240 mConnector.doCommand(
241 String.format("nat disable %s %s", internalInterface, externalInterface));
242 }
San Mehat72759df2010-01-19 13:50:37 -0800243
244 public String[] listTtys() throws IllegalStateException {
245 mContext.enforceCallingOrSelfPermission(
246 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
247 return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
248 }
249
250 public void attachPppd(String tty, String localAddr, String remoteAddr)
251 throws IllegalStateException {
252 try {
253 mContext.enforceCallingOrSelfPermission(
254 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
255 mConnector.doCommand(String.format("pppd attach %s %s %s", tty,
256 InetAddress.getByName(localAddr).toString(),
257 InetAddress.getByName(localAddr).toString()));
258 } catch (UnknownHostException e) {
259 throw new IllegalStateException("Error resolving addr", e);
260 }
261 }
262
263 public void detachPppd(String tty) throws IllegalStateException {
264 mContext.enforceCallingOrSelfPermission(
265 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
266 mConnector.doCommand(String.format("pppd detach %s", tty));
267 }
San Mehat873f2142010-01-14 10:25:07 -0800268}
269