Add NetworkManagement support for fwmark routes

Add NetworkManagementService binds for netd's fwmark routes

Change-Id: I55cf6b198d56f1fb0d20818ddf176a0f779a33b6
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 30885856..51c367a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -368,6 +368,26 @@
     void clearMarkedForwarding(String iface);
 
     /**
+     * Get the SO_MARK associated with routing packets for user {@code uid}
+     */
+    int getMarkForUid(int uid);
+
+    /**
+     * Get the SO_MARK associated with protecting packets from VPN routing rules
+     */
+    int getMarkForProtect();
+
+    /**
+     * Route all traffic in {@code route} to {@code iface} setup for marked forwarding
+     */
+    void setMarkedForwardingRoute(String iface, in RouteInfo route);
+
+    /**
+     * Clear routes set by {@link setMarkedForwardingRoute}
+     */
+    void clearMarkedForwardingRoute(String iface, in RouteInfo route);
+
+    /**
      * Set a process (pid) to use the name servers associated with the specified interface.
      */
     void setDnsInterfaceForPid(String iface, int pid);
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 6f740cd0..c3a43bb 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -32,6 +32,7 @@
 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
+import static com.android.server.NetworkManagementService.NetdResponseCode.GetMarkResult;
 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
 
 import android.content.Context;
@@ -127,6 +128,7 @@
         public static final int TetheringStatsResult      = 221;
         public static final int DnsProxyQueryResult       = 222;
         public static final int ClatdStatusResult         = 223;
+        public static final int GetMarkResult             = 225;
 
         public static final int InterfaceChange           = 600;
         public static final int BandwidthControl          = 601;
@@ -1382,7 +1384,7 @@
     public void setUidRangeRoute(String iface, int uid_start, int uid_end) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("interface", "route",
+            mConnector.execute("interface", "fwmark",
                     "uid", "add", iface, uid_start, uid_end);
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
@@ -1393,7 +1395,7 @@
     public void clearUidRangeRoute(String iface, int uid_start, int uid_end) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("interface", "route",
+            mConnector.execute("interface", "fwmark",
                     "uid", "remove", iface, uid_start, uid_end);
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
@@ -1404,7 +1406,7 @@
     public void setMarkedForwarding(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("interface", "route", "fwmark", "add", iface);
+            mConnector.execute("interface", "fwmark", "rule", "add", iface);
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
@@ -1414,7 +1416,57 @@
     public void clearMarkedForwarding(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("interface", "route", "fwmark", "remove", iface);
+            mConnector.execute("interface", "fwmark", "rule", "remove", iface);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public int getMarkForUid(int uid) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("interface", "fwmark", "get", "mark", uid);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+        event.checkCode(GetMarkResult);
+        return Integer.parseInt(event.getMessage());
+    }
+
+    @Override
+    public int getMarkForProtect() {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("interface", "fwmark", "get", "protect");
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+        event.checkCode(GetMarkResult);
+        return Integer.parseInt(event.getMessage());
+    }
+
+    @Override
+    public void setMarkedForwardingRoute(String iface, RouteInfo route) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        try {
+            LinkAddress dest = route.getDestination();
+            mConnector.execute("interface", "fwmark", "route", "add", iface,
+                    dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength());
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void clearMarkedForwardingRoute(String iface, RouteInfo route) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        try {
+            LinkAddress dest = route.getDestination();
+            mConnector.execute("interface", "fwmark", "route", "remove", iface,
+                    dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength());
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }