diff options
Diffstat (limited to 'services/java/com/android/server/NetworkManagementService.java')
-rw-r--r-- | services/java/com/android/server/NetworkManagementService.java | 169 |
1 files changed, 168 insertions, 1 deletions
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 44f5df2..0b4b958 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -28,6 +28,7 @@ import android.net.InterfaceConfiguration; import android.net.INetworkManagementEventObserver; import android.net.LinkAddress; import android.net.NetworkUtils; +import android.net.RouteInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.os.INetworkManagementService; @@ -43,11 +44,16 @@ import android.provider.Settings; import android.content.ContentResolver; import android.database.ContentObserver; +import java.io.BufferedReader; +import java.io.DataInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.IOException; import java.lang.IllegalStateException; - import java.net.InetAddress; +import java.net.Inet4Address; import java.net.UnknownHostException; import java.util.concurrent.CountDownLatch; @@ -60,6 +66,9 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static final boolean DBG = false; private static final String NETD_TAG = "NetdConnector"; + private static final int ADD = 1; + private static final int REMOVE = 2; + class NetdResponseCode { public static final int InterfaceListResult = 110; public static final int TetherInterfaceListResult = 111; @@ -309,6 +318,164 @@ class NetworkManagementService extends INetworkManagementService.Stub { } } + public void addRoute(String interfaceName, RouteInfo route) { + modifyRoute(interfaceName, ADD, route); + } + + public void removeRoute(String interfaceName, RouteInfo route) { + modifyRoute(interfaceName, REMOVE, route); + } + + private void modifyRoute(String interfaceName, int action, RouteInfo route) { + ArrayList<String> rsp; + + StringBuilder cmd; + + switch (action) { + case ADD: + { + cmd = new StringBuilder("interface route add " + interfaceName); + break; + } + case REMOVE: + { + cmd = new StringBuilder("interface route remove " + interfaceName); + break; + } + default: + throw new IllegalStateException("Unknown action type " + action); + } + + // create triplet: dest-ip-addr prefixlength gateway-ip-addr + LinkAddress la = route.getDestination(); + cmd.append(' '); + cmd.append(la.getAddress().getHostAddress()); + cmd.append(' '); + cmd.append(la.getNetworkPrefixLength()); + cmd.append(' '); + if (route.getGateway() == null) { + if (la.getAddress() instanceof Inet4Address) { + cmd.append("0.0.0.0"); + } else { + cmd.append ("::0"); + } + } else { + cmd.append(route.getGateway().getHostAddress()); + } + try { + rsp = mConnector.doCommand(cmd.toString()); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate with native dameon to add routes - " + + e); + } + + for (String line : rsp) { + Log.v(TAG, "add route response is " + line); + } + } + + private ArrayList<String> readRouteList(String filename) { + FileInputStream fstream = null; + ArrayList<String> list = new ArrayList<String>(); + + try { + fstream = new FileInputStream(filename); + DataInputStream in = new DataInputStream(fstream); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + String s; + + // throw away the title line + + while (((s = br.readLine()) != null) && (s.length() != 0)) { + list.add(s); + } + } catch (IOException ex) { + // return current list, possibly empty + } finally { + if (fstream != null) { + try { + fstream.close(); + } catch (IOException ex) {} + } + } + + return list; + } + + public RouteInfo[] getRoutes(String interfaceName) { + ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); + + // v4 routes listed as: + // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT + for (String s : readRouteList("/proc/net/route")) { + String[] fields = s.split("\t"); + + if (fields.length > 7) { + String iface = fields[0]; + + if (interfaceName.equals(iface)) { + String dest = fields[1]; + String gate = fields[2]; + String flags = fields[3]; // future use? + String mask = fields[7]; + try { + // address stored as a hex string, ex: 0014A8C0 + InetAddress destAddr = + NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); + int prefixLength = + NetworkUtils.netmaskIntToPrefixLength( + (int)Long.parseLong(mask, 16)); + LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); + + // address stored as a hex string, ex 0014A8C0 + InetAddress gatewayAddr = + NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); + + RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); + routes.add(route); + } catch (Exception e) { + Log.e(TAG, "Error parsing route " + s + " : " + e); + continue; + } + } + } + } + + // v6 routes listed as: + // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface + for (String s : readRouteList("/proc/net/ipv6_route")) { + String[]fields = s.split("\\s+"); + if (fields.length > 9) { + String iface = fields[9].trim(); + if (interfaceName.equals(iface)) { + String dest = fields[0]; + String prefix = fields[1]; + String gate = fields[4]; + + try { + // prefix length stored as a hex string, ex 40 + int prefixLength = Integer.parseInt(prefix, 16); + + // address stored as a 32 char hex string + // ex fe800000000000000000000000000000 + InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); + LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); + + InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); + + RouteInfo route = new RouteInfo(linkAddress, gateAddr); + routes.add(route); + } catch (Exception e) { + Log.e(TAG, "Error parsing route " + s + " : " + e); + continue; + } + } + } + } + return (RouteInfo[]) routes.toArray(new RouteInfo[0]); + } + public void shutdown() { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SHUTDOWN) |