Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4e0c0cb authored by Sreeram Ramachandran's avatar Sreeram Ramachandran
Browse files

Allow VPNs to add/remove link addresses dynamically.

Bug: 15409819
Change-Id: If91fc6891d7ce04060362c6cde8c57462394c4e8
parent 4789e41a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -163,4 +163,7 @@ interface IConnectivityManager
    void releaseNetworkRequest(in NetworkRequest networkRequest);

    int getRestoreDefaultNetworkDelay(int networkType);

    boolean addVpnAddress(String address, int prefixLength);
    boolean removeVpnAddress(String address, int prefixLength);
}
+32 −24
Original line number Diff line number Diff line
@@ -212,8 +212,12 @@ public class VpnService extends Service {
     * @see Builder#addAddress
     */
    public boolean addAddress(InetAddress address, int prefixLength) {
        // TODO
        return true;
        check(address, prefixLength);
        try {
            return getService().addVpnAddress(address.getHostAddress(), prefixLength);
        } catch (RemoteException e) {
            throw new IllegalStateException(e);
        }
    }

    /**
@@ -236,8 +240,12 @@ public class VpnService extends Service {
     * @return {@code true} on success.
     */
    public boolean removeAddress(InetAddress address, int prefixLength) {
        // TODO
        return true;
        check(address, prefixLength);
        try {
            return getService().removeVpnAddress(address.getHostAddress(), prefixLength);
        } catch (RemoteException e) {
            throw new IllegalStateException(e);
        }
    }

    /**
@@ -285,6 +293,26 @@ public class VpnService extends Service {
        }
    }

    /**
     * Private method to validate address and prefixLength.
     */
    private static void check(InetAddress address, int prefixLength) {
        if (address.isLoopbackAddress()) {
            throw new IllegalArgumentException("Bad address");
        }
        if (address instanceof Inet4Address) {
            if (prefixLength < 0 || prefixLength > 32) {
                throw new IllegalArgumentException("Bad prefixLength");
            }
        } else if (address instanceof Inet6Address) {
            if (prefixLength < 0 || prefixLength > 128) {
                throw new IllegalArgumentException("Bad prefixLength");
            }
        } else {
            throw new IllegalArgumentException("Unsupported family");
        }
    }

    /**
     * Helper class to create a VPN interface. This class should be always
     * used within the scope of the outer {@link VpnService}.
@@ -336,26 +364,6 @@ public class VpnService extends Service {
            return this;
        }

        /**
         * Private method to validate address and prefixLength.
         */
        private void check(InetAddress address, int prefixLength) {
            if (address.isLoopbackAddress()) {
                throw new IllegalArgumentException("Bad address");
            }
            if (address instanceof Inet4Address) {
                if (prefixLength < 0 || prefixLength > 32) {
                    throw new IllegalArgumentException("Bad prefixLength");
                }
            } else if (address instanceof Inet6Address) {
                if (prefixLength < 0 || prefixLength > 128) {
                    throw new IllegalArgumentException("Bad prefixLength");
                }
            } else {
                throw new IllegalArgumentException("Unsupported family");
            }
        }

        /**
         * Add a network address to the VPN interface. Both IPv4 and IPv6
         * addresses are supported. At least one address must be set before
+18 −0
Original line number Diff line number Diff line
@@ -5351,4 +5351,22 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        }
        return new NetworkCapabilities();
    }

    @Override
    public boolean addVpnAddress(String address, int prefixLength) {
        throwIfLockdownEnabled();
        int user = UserHandle.getUserId(Binder.getCallingUid());
        synchronized (mVpns) {
            return mVpns.get(user).addAddress(address, prefixLength);
        }
    }

    @Override
    public boolean removeVpnAddress(String address, int prefixLength) {
        throwIfLockdownEnabled();
        int user = UserHandle.getUserId(Binder.getCallingUid());
        synchronized (mVpns) {
            return mVpns.get(user).removeAddress(address, prefixLength);
        }
    }
}
+44 −1
Original line number Diff line number Diff line
@@ -83,8 +83,9 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -754,11 +755,53 @@ public class Vpn {
        }
    }

    public synchronized boolean addAddress(String address, int prefixLength) {
        if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) {
            return false;
        }
        boolean success = jniAddAddress(mInterface, address, prefixLength);
        if (success && (!mAllowIPv4 || !mAllowIPv6)) {
            try {
                InetAddress inetAddress = InetAddress.parseNumericAddress(address);
                if ((inetAddress instanceof Inet4Address) && !mAllowIPv4) {
                    mAllowIPv4 = true;
                    mNetworkAgent.unblockAddressFamily(AF_INET);
                } else if ((inetAddress instanceof Inet6Address) && !mAllowIPv6) {
                    mAllowIPv6 = true;
                    mNetworkAgent.unblockAddressFamily(AF_INET6);
                }
            } catch (IllegalArgumentException e) {
                // ignore
            }
        }
        // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService
        // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set
        // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect())
        // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()).
        // TODO: Maybe fix this.
        return success;
    }

    public synchronized boolean removeAddress(String address, int prefixLength) {
        if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) {
            return false;
        }
        boolean success = jniDelAddress(mInterface, address, prefixLength);
        // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService
        // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set
        // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect())
        // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()).
        // TODO: Maybe fix this.
        return success;
    }

    private native int jniCreate(int mtu);
    private native String jniGetName(int tun);
    private native int jniSetAddresses(String interfaze, String addresses);
    private native void jniReset(String interfaze);
    private native int jniCheck(String interfaze);
    private native boolean jniAddAddress(String interfaze, String address, int prefixLen);
    private native boolean jniDelAddress(String interfaze, String address, int prefixLen);

    private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
        for (RouteInfo route : prop.getAllRoutes()) {
+2 −1
Original line number Diff line number Diff line
@@ -61,5 +61,6 @@ LOCAL_SHARED_LIBRARIES += \
    libusbhost \
    libsuspend \
    libEGL \
    libGLESv2
    libGLESv2 \
    libnetutils \
Loading