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

Commit 4e0421a5 authored by Paul Jensen's avatar Paul Jensen Committed by android-build-merger
Browse files

Have ConnectivityService install packet filters when possible am: 578a76e7 am: 978c80b4

am: 171160a3

* commit '171160a3':
  Have ConnectivityService install packet filters when possible
parents 146dd3ad 171160a3
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -200,6 +200,14 @@ public abstract class NetworkAgent extends Handler {
     */
    public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;

    /**
     * Sent by ConnectivityService to the NetworkAgent to install an APF program in the network
     * chipset for use to filter packets.
     *
     * obj = byte[] containing the APF program bytecode.
     */
    public static final int CMD_PUSH_APF_PROGRAM = BASE + 16;

    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
            NetworkCapabilities nc, LinkProperties lp, int score) {
        this(looper, context, logTag, ni, nc, lp, score, null);
@@ -319,6 +327,10 @@ public abstract class NetworkAgent extends Handler {
                preventAutomaticReconnect();
                break;
            }
            case CMD_PUSH_APF_PROGRAM: {
                installPacketFilter((byte[]) msg.obj);
                break;
            }
        }
    }

@@ -494,6 +506,15 @@ public abstract class NetworkAgent extends Handler {
    protected void preventAutomaticReconnect() {
    }

    /**
     * Install a packet filter.
     * @param filter an APF program to filter incoming packets.
     * @return {@code true} if filter successfully installed, {@code false} otherwise.
     */
    protected boolean installPacketFilter(byte[] filter) {
        return false;
    }

    protected void log(String s) {
        Log.d(LOG_TAG, "NetworkAgent: " + s);
    }
+25 −0
Original line number Diff line number Diff line
@@ -56,6 +56,22 @@ public class NetworkMisc implements Parcelable {
     */
    public String subscriberId;

    /**
     * Version of APF instruction set supported for packet filtering. 0 indicates no support for
     * packet filtering using APF programs.
     */
    public int apfVersionSupported;

    /**
     * Maximum size of APF program allowed.
     */
    public int maximumApfProgramSize;

    /**
     * Format of packets passed to APF filter. Should be one of ARPHRD_*
     */
    public int apfPacketFormat;

    public NetworkMisc() {
    }

@@ -65,6 +81,9 @@ public class NetworkMisc implements Parcelable {
            explicitlySelected = nm.explicitlySelected;
            acceptUnvalidated = nm.acceptUnvalidated;
            subscriberId = nm.subscriberId;
            apfVersionSupported = nm.apfVersionSupported;
            maximumApfProgramSize = nm.maximumApfProgramSize;
            apfPacketFormat = nm.apfPacketFormat;
        }
    }

@@ -79,6 +98,9 @@ public class NetworkMisc implements Parcelable {
        out.writeInt(explicitlySelected ? 1 : 0);
        out.writeInt(acceptUnvalidated ? 1 : 0);
        out.writeString(subscriberId);
        out.writeInt(apfVersionSupported);
        out.writeInt(maximumApfProgramSize);
        out.writeInt(apfPacketFormat);
    }

    public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -89,6 +111,9 @@ public class NetworkMisc implements Parcelable {
            networkMisc.explicitlySelected = in.readInt() != 0;
            networkMisc.acceptUnvalidated = in.readInt() != 0;
            networkMisc.subscriberId = in.readString();
            networkMisc.apfVersionSupported = in.readInt();
            networkMisc.maximumApfProgramSize = in.readInt();
            networkMisc.apfPacketFormat = in.readInt();
            return networkMisc;
        }

+7 −0
Original line number Diff line number Diff line
@@ -61,6 +61,13 @@ public class NetworkUtils {
     */
    public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;

    /**
     * Attaches a socket filter that accepts ICMP6 router advertisement packets to the given socket.
     * @param fd the socket's {@link FileDescriptor}.
     * @param packetType the hardware address type, one of ARPHRD_*.
     */
    public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;

    /**
     * Binds the current process to the network designated by {@code netId}.  All sockets created
     * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
+44 −2
Original line number Diff line number Diff line
@@ -26,10 +26,13 @@
#include <net/if.h>
#include <linux/filter.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/if_ether.h>
#include <netinet/icmp6.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <cutils/properties.h>

@@ -64,7 +67,6 @@ static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,

static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
{
    int fd = jniGetFDFromFileDescriptor(env, javaFd);
    uint32_t ip_offset = sizeof(ether_header);
    uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
    uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
@@ -94,6 +96,45 @@ static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobje
        filter_code,
    };

    int fd = jniGetFDFromFileDescriptor(env, javaFd);
    if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
        jniThrowExceptionFmt(env, "java/net/SocketException",
                "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
    }
}

static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject javaFd,
        jint hardwareAddressType)
{
    if (hardwareAddressType != ARPHRD_ETHER) {
        jniThrowExceptionFmt(env, "java/net/SocketException",
                "attachRaFilter only supports ARPHRD_ETHER");
        return;
    }

    uint32_t ipv6_offset = sizeof(ether_header);
    uint32_t ipv6_next_header_offset = ipv6_offset + offsetof(ip6_hdr, ip6_nxt);
    uint32_t icmp6_offset = ipv6_offset + sizeof(ip6_hdr);
    uint32_t icmp6_type_offset = icmp6_offset + offsetof(icmp6_hdr, icmp6_type);
    struct sock_filter filter_code[] = {
        // Check IPv6 Next Header is ICMPv6.
        BPF_STMT(BPF_LD  | BPF_B   | BPF_ABS,  ipv6_next_header_offset),
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    IPPROTO_ICMPV6, 0, 3),

        // Check ICMPv6 type is Router Advertisement.
        BPF_STMT(BPF_LD  | BPF_B   | BPF_ABS,  icmp6_type_offset),
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    ND_ROUTER_ADVERT, 0, 1),

        // Accept or reject.
        BPF_STMT(BPF_RET | BPF_K,              0xffff),
        BPF_STMT(BPF_RET | BPF_K,              0)
    };
    struct sock_fprog filter = {
        sizeof(filter_code) / sizeof(filter_code[0]),
        filter_code,
    };

    int fd = jniGetFDFromFileDescriptor(env, javaFd);
    if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
        jniThrowExceptionFmt(env, "java/net/SocketException",
                "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
@@ -148,6 +189,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = {
    { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
    { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
    { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
    { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
};

int register_android_net_NetworkUtils(JNIEnv* env)
+29 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.PacManager;
import com.android.server.connectivity.PermissionMonitor;
import com.android.server.connectivity.ApfFilter;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
@@ -353,6 +354,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
     */
    private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;

    /**
     * used to push APF program to NetworkAgent
     * replyTo = NetworkAgent message handler
     * obj = byte[] of APF program
     */
    private static final int EVENT_PUSH_APF_PROGRAM_TO_NETWORK = 32;

    /** Handler thread used for both of the handlers below. */
    @VisibleForTesting
    protected final HandlerThread mHandlerThread;
@@ -2193,6 +2201,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            mKeepaliveTracker.handleStopAllKeepalives(nai,
                    ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
            nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
            if (nai.apfFilter != null) nai.apfFilter.shutdown();
            mNetworkAgentInfos.remove(msg.replyTo);
            updateClat(null, nai.linkProperties, nai);
            synchronized (mNetworkForNetId) {
@@ -2407,6 +2416,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
                accept ? 1 : 0, always ? 1: 0, network));
    }

    public void pushApfProgramToNetwork(NetworkAgentInfo nai, byte[] program) {
        enforceConnectivityInternalPermission();
        Message msg = mHandler.obtainMessage(EVENT_PUSH_APF_PROGRAM_TO_NETWORK, program);
        msg.replyTo = nai.messenger;
        mHandler.sendMessage(msg);
    }

    private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
        if (DBG) log("handleSetAcceptUnvalidated network=" + network +
                " accept=" + accept + " always=" + always);
@@ -2556,6 +2572,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    handleMobileDataAlwaysOn();
                    break;
                }
                case EVENT_PUSH_APF_PROGRAM_TO_NETWORK: {
                    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
                    if (nai == null) {
                        loge("EVENT_PUSH_APF_PROGRAM_TO_NETWORK from unknown NetworkAgent");
                    } else {
                         nai.asyncChannel.sendMessage(NetworkAgent.CMD_PUSH_APF_PROGRAM,
                                 (byte[]) msg.obj);
                    }
                    break;
                }
                // Sent by KeepaliveTracker to process an app request on the state machine thread.
                case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
                    mKeepaliveTracker.handleStartKeepalive(msg);
@@ -4071,6 +4097,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
        if (networkAgent.clatd != null) {
            networkAgent.clatd.fixupLinkProperties(oldLp);
        }
        if (networkAgent.apfFilter != null) {
            networkAgent.apfFilter.updateFilter();
        }

        updateInterfaces(newLp, oldLp, netId);
        updateMtu(newLp, oldLp);
Loading