Loading packages/NetworkStack/src/android/net/apf/ApfFilter.java +195 −12 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.system.OsConstants.ETH_P_ARP; import static android.system.OsConstants.ETH_P_IP; import static android.system.OsConstants.ETH_P_IPV6; import static android.system.OsConstants.IPPROTO_ICMPV6; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_RAW; Loading Loading @@ -56,6 +57,7 @@ import android.system.Os; import android.text.format.DateUtils; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -150,7 +152,9 @@ public class ApfFilter { DROPPED_IPV6_NON_ICMP_MULTICAST, DROPPED_802_3_FRAME, DROPPED_ETHERTYPE_BLACKLISTED, DROPPED_ARP_REPLY_SPA_NO_HOST; DROPPED_ARP_REPLY_SPA_NO_HOST, DROPPED_IPV4_KEEPALIVE_ACK, DROPPED_IPV6_KEEPALIVE_ACK; // Returns the negative byte offset from the end of the APF data segment for // a given counter. Loading Loading @@ -286,6 +290,7 @@ public class ApfFilter { private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16; private static final int IPV4_ANY_HOST_ADDRESS = 0; private static final int IPV4_BROADCAST_ADDRESS = -1; // 255.255.255.255 private static final int IPV4_HEADER_LEN = 20; // Without options // Traffic class and Flow label are not byte aligned. Luckily we // don't care about either value so we'll consider bytes 1-3 of the Loading @@ -306,6 +311,8 @@ public class ApfFilter { private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2; private static final int UDP_HEADER_LEN = 8; private static final int TCP_HEADER_SIZE_OFFSET = 12; private static final int DHCP_CLIENT_PORT = 68; // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28; Loading Loading @@ -789,7 +796,7 @@ public class ApfFilter { boolean isExpired() { // TODO: We may want to handle 0 lifetime RAs differently, if they are common. We'll // have to calculte the filter lifetime specially as a fraction of 0 is still 0. // have to calculate the filter lifetime specially as a fraction of 0 is still 0. return currentLifetime() <= 0; } Loading Loading @@ -848,11 +855,147 @@ public class ApfFilter { } } // A class to hold keepalive ack information. private abstract static class TcpKeepaliveAck { // Note that the offset starts from IP header. // These must be added ether header length when generating program. static final int IP_HEADER_OFFSET = 0; protected static class TcpKeepaliveAckData { public final byte[] srcAddress; public final int srcPort; public final byte[] dstAddress; public final int dstPort; public final int seq; public final int ack; // Create the characteristics of the ack packet from the sent keepalive packet. TcpKeepaliveAckData(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { srcAddress = sentKeepalivePacket.dstAddress; srcPort = sentKeepalivePacket.dstPort; dstAddress = sentKeepalivePacket.srcAddress; dstPort = sentKeepalivePacket.srcPort; seq = sentKeepalivePacket.ack; ack = sentKeepalivePacket.seq + 1; } } protected final TcpKeepaliveAckData mPacket; protected final byte[] mSrcDstAddr; TcpKeepaliveAck(final TcpKeepaliveAckData packet, final byte[] srcDstAddr) { mPacket = packet; mSrcDstAddr = srcDstAddr; } static byte[] concatArrays(final byte[]... arr) { int size = 0; for (byte[] a : arr) { size += a.length; } final byte[] result = new byte[size]; int offset = 0; for (byte[] a : arr) { System.arraycopy(a, 0, result, offset, a.length); offset += a.length; } return result; } public String toString() { return String.format("%s(%d) -> %s(%d), seq=%d, ack=%d", mPacket.srcAddress, mPacket.srcPort, mPacket.dstAddress, mPacket.dstPort, mPacket.seq, mPacket.ack); } // Append a filter for this keepalive ack to {@code gen}. // Jump to drop if it matches the keepalive ack. // Jump to the next filter if packet doesn't match the keepalive ack. abstract void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException; } private class TcpKeepaliveAckV4 extends TcpKeepaliveAck { private static final int IPV4_SRC_ADDR_OFFSET = IP_HEADER_OFFSET + 12; private static final int IPV4_TCP_SRC_PORT_OFFSET = 0; private static final int IPV4_TCP_DST_PORT_OFFSET = 2; private static final int IPV4_TCP_SEQ_OFFSET = 4; private static final int IPV4_TCP_ACK_OFFSET = 8; TcpKeepaliveAckV4(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { this(new TcpKeepaliveAckData(sentKeepalivePacket)); } TcpKeepaliveAckV4(final TcpKeepaliveAckData packet) { super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */); } @Override void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException { final String nextFilterLabel = "keepalive_ack" + getUniqueNumberLocked(); gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_TCP, nextFilterLabel); gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN + IPV4_SRC_ADDR_OFFSET); gen.addJumpIfBytesNotEqual(Register.R0, mSrcDstAddr, nextFilterLabel); // Pass the packet if it's not zero-sized : // Load the IP header size into R1 gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); // Load the TCP header size into R0 (it's indexed by R1) gen.addLoad8Indexed(Register.R0, ETH_HEADER_LEN + TCP_HEADER_SIZE_OFFSET); // Size offset is in the top nibble, but it must be multiplied by 4, and the two // top bits of the low nibble are guaranteed to be zeroes. Right-shift R0 by 2. gen.addRightShift(2); // R0 += R1 -> R0 contains TCP + IP headers lenght gen.addAddR1(); // Add the Ethernet header length to R0. gen.addLoadImmediate(Register.R1, ETH_HEADER_LEN); gen.addAddR1(); // Compare total length of headers to the size of the packet. gen.addLoadFromMemory(Register.R1, gen.PACKET_SIZE_MEMORY_SLOT); gen.addNeg(Register.R0); gen.addAddR1(); gen.addJumpIfR0NotEquals(0, nextFilterLabel); // Add IPv4 header length gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SRC_PORT_OFFSET); gen.addJumpIfR0NotEquals(mPacket.srcPort, nextFilterLabel); gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_DST_PORT_OFFSET); gen.addJumpIfR0NotEquals(mPacket.dstPort, nextFilterLabel); gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SEQ_OFFSET); gen.addJumpIfR0NotEquals(mPacket.seq, nextFilterLabel); gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_ACK_OFFSET); gen.addJumpIfR0NotEquals(mPacket.ack, nextFilterLabel); maybeSetupCounter(gen, Counter.DROPPED_IPV4_KEEPALIVE_ACK); gen.addJump(mCountAndDropLabel); gen.defineLabel(nextFilterLabel); } } private class TcpKeepaliveAckV6 extends TcpKeepaliveAck { TcpKeepaliveAckV6(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { this(new TcpKeepaliveAckData(sentKeepalivePacket)); } TcpKeepaliveAckV6(final TcpKeepaliveAckData packet) { super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */); } @Override void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException { throw new UnsupportedOperationException("IPv6 Keepalive is not supported yet"); } } // Maximum number of RAs to filter for. private static final int MAX_RAS = 10; @GuardedBy("this") private ArrayList<Ra> mRas = new ArrayList<Ra>(); private ArrayList<Ra> mRas = new ArrayList<>(); @GuardedBy("this") private SparseArray<TcpKeepaliveAck> mKeepaliveAcks = new SparseArray<>(); // There is always some marginal benefit to updating the installed APF program when an RA is // seen because we can extend the program's lifetime slightly, but there is some cost to Loading Loading @@ -981,6 +1124,8 @@ public class ApfFilter { // drop // if it's IPv4 broadcast: // drop // if keepalive ack // drop // pass if (mMulticastFilter) { Loading Loading @@ -1024,6 +1169,9 @@ public class ApfFilter { gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel); } // If any keepalive filters, generateKeepaliveFilter(gen); // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST); Loading @@ -1031,6 +1179,8 @@ public class ApfFilter { gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST); gen.addJump(mCountAndDropLabel); } else { generateKeepaliveFilter(gen); } // Otherwise, pass Loading @@ -1038,6 +1188,13 @@ public class ApfFilter { gen.addJump(mCountAndPassLabel); } private void generateKeepaliveFilter(ApfGenerator gen) throws IllegalInstructionException { // Drop IPv4 Keepalive acks for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i); if (ack instanceof TcpKeepaliveAckV4) ack.generateFilterLocked(gen); } } /** * Generate filter code to process IPv6 packets. Execution of this code ends in either the Loading @@ -1058,6 +1215,8 @@ public class ApfFilter { // drop // if it's ICMPv6 NA to ff02::1: // drop // if keepalive ack // drop gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET); Loading Loading @@ -1113,6 +1272,12 @@ public class ApfFilter { maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA); gen.addJump(mCountAndDropLabel); gen.defineLabel(skipUnsolicitedMulticastNALabel); // Drop IPv6 Keepalive acks for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i); if (ack instanceof TcpKeepaliveAckV6) ack.generateFilterLocked(gen); } } /** Loading Loading @@ -1491,16 +1656,23 @@ public class ApfFilter { } /** * Add keepalive packet filter. * Add keepalive ack packet filter. * This will add a filter to drop acks to the keepalive packet passed as an argument. * * @param slot The index used to access the filter. * @param pkt Parameters needed to compose the filter. * @param sentKeepalivePacket The attributes of the sent keepalive packet. */ public synchronized void addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) { // TODO: implement this. Log.e(TAG, "APF function is not implemented: addKeepalivePacketFilter(" + slot + ", " + pkt + ")"); public synchronized void addKeepalivePacketFilter(final int slot, final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { log("Adding keepalive ack(" + slot + ")"); if (null != mKeepaliveAcks.get(slot)) { throw new IllegalArgumentException("Keepalive slot " + slot + " is occupied"); } final int ipVersion = sentKeepalivePacket.srcAddress.length == 4 ? 4 : 6; mKeepaliveAcks.put(slot, (ipVersion == 4) ? new TcpKeepaliveAckV4(sentKeepalivePacket) : new TcpKeepaliveAckV6(sentKeepalivePacket)); installNewProgramLocked(); } /** Loading @@ -1509,8 +1681,8 @@ public class ApfFilter { * @param slot The index used to access the filter. */ public synchronized void removeKeepalivePacketFilter(int slot) { // TODO: implement this. Log.e(TAG, "APF function is not implemented: removeKeepalivePacketFilter(" + slot + ")"); mKeepaliveAcks.remove(slot); installNewProgramLocked(); } static public long counterValue(byte[] data, Counter counter) Loading Loading @@ -1565,6 +1737,17 @@ public class ApfFilter { } pw.decreaseIndent(); pw.println("Keepalive filter:"); pw.increaseIndent(); for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck keepaliveAck = mKeepaliveAcks.valueAt(i); pw.print("Slot "); pw.print(mKeepaliveAcks.keyAt(i)); pw.print(" : "); pw.println(keepaliveAck); } pw.decreaseIndent(); if (DBG) { pw.println("Last program:"); pw.increaseIndent(); Loading packages/NetworkStack/src/android/net/apf/ApfGenerator.java +2 −2 Original line number Diff line number Diff line Loading @@ -476,7 +476,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load 16-bits from the packet into * {@code register}. The offset of the loaded 16-bits from the begining of the packet is * {@code register}. The offset of the loaded 16-bits from the beginning of the packet is * the sum of {@code offset} and the value in register R1. */ public ApfGenerator addLoad16Indexed(Register register, int offset) { Loading @@ -488,7 +488,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load 32-bits from the packet into * {@code register}. The offset of the loaded 32-bits from the begining of the packet is * {@code register}. The offset of the loaded 32-bits from the beginning of the packet is * the sum of {@code offset} and the value in register R1. */ public ApfGenerator addLoad32Indexed(Register register, int offset) { Loading packages/NetworkStack/tests/src/android/net/apf/ApfTest.java +213 −2 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/NetworkStack/src/android/net/apf/ApfFilter.java +195 −12 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.system.OsConstants.ETH_P_ARP; import static android.system.OsConstants.ETH_P_IP; import static android.system.OsConstants.ETH_P_IPV6; import static android.system.OsConstants.IPPROTO_ICMPV6; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_RAW; Loading Loading @@ -56,6 +57,7 @@ import android.system.Os; import android.text.format.DateUtils; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -150,7 +152,9 @@ public class ApfFilter { DROPPED_IPV6_NON_ICMP_MULTICAST, DROPPED_802_3_FRAME, DROPPED_ETHERTYPE_BLACKLISTED, DROPPED_ARP_REPLY_SPA_NO_HOST; DROPPED_ARP_REPLY_SPA_NO_HOST, DROPPED_IPV4_KEEPALIVE_ACK, DROPPED_IPV6_KEEPALIVE_ACK; // Returns the negative byte offset from the end of the APF data segment for // a given counter. Loading Loading @@ -286,6 +290,7 @@ public class ApfFilter { private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16; private static final int IPV4_ANY_HOST_ADDRESS = 0; private static final int IPV4_BROADCAST_ADDRESS = -1; // 255.255.255.255 private static final int IPV4_HEADER_LEN = 20; // Without options // Traffic class and Flow label are not byte aligned. Luckily we // don't care about either value so we'll consider bytes 1-3 of the Loading @@ -306,6 +311,8 @@ public class ApfFilter { private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2; private static final int UDP_HEADER_LEN = 8; private static final int TCP_HEADER_SIZE_OFFSET = 12; private static final int DHCP_CLIENT_PORT = 68; // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28; Loading Loading @@ -789,7 +796,7 @@ public class ApfFilter { boolean isExpired() { // TODO: We may want to handle 0 lifetime RAs differently, if they are common. We'll // have to calculte the filter lifetime specially as a fraction of 0 is still 0. // have to calculate the filter lifetime specially as a fraction of 0 is still 0. return currentLifetime() <= 0; } Loading Loading @@ -848,11 +855,147 @@ public class ApfFilter { } } // A class to hold keepalive ack information. private abstract static class TcpKeepaliveAck { // Note that the offset starts from IP header. // These must be added ether header length when generating program. static final int IP_HEADER_OFFSET = 0; protected static class TcpKeepaliveAckData { public final byte[] srcAddress; public final int srcPort; public final byte[] dstAddress; public final int dstPort; public final int seq; public final int ack; // Create the characteristics of the ack packet from the sent keepalive packet. TcpKeepaliveAckData(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { srcAddress = sentKeepalivePacket.dstAddress; srcPort = sentKeepalivePacket.dstPort; dstAddress = sentKeepalivePacket.srcAddress; dstPort = sentKeepalivePacket.srcPort; seq = sentKeepalivePacket.ack; ack = sentKeepalivePacket.seq + 1; } } protected final TcpKeepaliveAckData mPacket; protected final byte[] mSrcDstAddr; TcpKeepaliveAck(final TcpKeepaliveAckData packet, final byte[] srcDstAddr) { mPacket = packet; mSrcDstAddr = srcDstAddr; } static byte[] concatArrays(final byte[]... arr) { int size = 0; for (byte[] a : arr) { size += a.length; } final byte[] result = new byte[size]; int offset = 0; for (byte[] a : arr) { System.arraycopy(a, 0, result, offset, a.length); offset += a.length; } return result; } public String toString() { return String.format("%s(%d) -> %s(%d), seq=%d, ack=%d", mPacket.srcAddress, mPacket.srcPort, mPacket.dstAddress, mPacket.dstPort, mPacket.seq, mPacket.ack); } // Append a filter for this keepalive ack to {@code gen}. // Jump to drop if it matches the keepalive ack. // Jump to the next filter if packet doesn't match the keepalive ack. abstract void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException; } private class TcpKeepaliveAckV4 extends TcpKeepaliveAck { private static final int IPV4_SRC_ADDR_OFFSET = IP_HEADER_OFFSET + 12; private static final int IPV4_TCP_SRC_PORT_OFFSET = 0; private static final int IPV4_TCP_DST_PORT_OFFSET = 2; private static final int IPV4_TCP_SEQ_OFFSET = 4; private static final int IPV4_TCP_ACK_OFFSET = 8; TcpKeepaliveAckV4(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { this(new TcpKeepaliveAckData(sentKeepalivePacket)); } TcpKeepaliveAckV4(final TcpKeepaliveAckData packet) { super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */); } @Override void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException { final String nextFilterLabel = "keepalive_ack" + getUniqueNumberLocked(); gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_TCP, nextFilterLabel); gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN + IPV4_SRC_ADDR_OFFSET); gen.addJumpIfBytesNotEqual(Register.R0, mSrcDstAddr, nextFilterLabel); // Pass the packet if it's not zero-sized : // Load the IP header size into R1 gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); // Load the TCP header size into R0 (it's indexed by R1) gen.addLoad8Indexed(Register.R0, ETH_HEADER_LEN + TCP_HEADER_SIZE_OFFSET); // Size offset is in the top nibble, but it must be multiplied by 4, and the two // top bits of the low nibble are guaranteed to be zeroes. Right-shift R0 by 2. gen.addRightShift(2); // R0 += R1 -> R0 contains TCP + IP headers lenght gen.addAddR1(); // Add the Ethernet header length to R0. gen.addLoadImmediate(Register.R1, ETH_HEADER_LEN); gen.addAddR1(); // Compare total length of headers to the size of the packet. gen.addLoadFromMemory(Register.R1, gen.PACKET_SIZE_MEMORY_SLOT); gen.addNeg(Register.R0); gen.addAddR1(); gen.addJumpIfR0NotEquals(0, nextFilterLabel); // Add IPv4 header length gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SRC_PORT_OFFSET); gen.addJumpIfR0NotEquals(mPacket.srcPort, nextFilterLabel); gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_DST_PORT_OFFSET); gen.addJumpIfR0NotEquals(mPacket.dstPort, nextFilterLabel); gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SEQ_OFFSET); gen.addJumpIfR0NotEquals(mPacket.seq, nextFilterLabel); gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_ACK_OFFSET); gen.addJumpIfR0NotEquals(mPacket.ack, nextFilterLabel); maybeSetupCounter(gen, Counter.DROPPED_IPV4_KEEPALIVE_ACK); gen.addJump(mCountAndDropLabel); gen.defineLabel(nextFilterLabel); } } private class TcpKeepaliveAckV6 extends TcpKeepaliveAck { TcpKeepaliveAckV6(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { this(new TcpKeepaliveAckData(sentKeepalivePacket)); } TcpKeepaliveAckV6(final TcpKeepaliveAckData packet) { super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */); } @Override void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException { throw new UnsupportedOperationException("IPv6 Keepalive is not supported yet"); } } // Maximum number of RAs to filter for. private static final int MAX_RAS = 10; @GuardedBy("this") private ArrayList<Ra> mRas = new ArrayList<Ra>(); private ArrayList<Ra> mRas = new ArrayList<>(); @GuardedBy("this") private SparseArray<TcpKeepaliveAck> mKeepaliveAcks = new SparseArray<>(); // There is always some marginal benefit to updating the installed APF program when an RA is // seen because we can extend the program's lifetime slightly, but there is some cost to Loading Loading @@ -981,6 +1124,8 @@ public class ApfFilter { // drop // if it's IPv4 broadcast: // drop // if keepalive ack // drop // pass if (mMulticastFilter) { Loading Loading @@ -1024,6 +1169,9 @@ public class ApfFilter { gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel); } // If any keepalive filters, generateKeepaliveFilter(gen); // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST); Loading @@ -1031,6 +1179,8 @@ public class ApfFilter { gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel); maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST); gen.addJump(mCountAndDropLabel); } else { generateKeepaliveFilter(gen); } // Otherwise, pass Loading @@ -1038,6 +1188,13 @@ public class ApfFilter { gen.addJump(mCountAndPassLabel); } private void generateKeepaliveFilter(ApfGenerator gen) throws IllegalInstructionException { // Drop IPv4 Keepalive acks for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i); if (ack instanceof TcpKeepaliveAckV4) ack.generateFilterLocked(gen); } } /** * Generate filter code to process IPv6 packets. Execution of this code ends in either the Loading @@ -1058,6 +1215,8 @@ public class ApfFilter { // drop // if it's ICMPv6 NA to ff02::1: // drop // if keepalive ack // drop gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET); Loading Loading @@ -1113,6 +1272,12 @@ public class ApfFilter { maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA); gen.addJump(mCountAndDropLabel); gen.defineLabel(skipUnsolicitedMulticastNALabel); // Drop IPv6 Keepalive acks for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i); if (ack instanceof TcpKeepaliveAckV6) ack.generateFilterLocked(gen); } } /** Loading Loading @@ -1491,16 +1656,23 @@ public class ApfFilter { } /** * Add keepalive packet filter. * Add keepalive ack packet filter. * This will add a filter to drop acks to the keepalive packet passed as an argument. * * @param slot The index used to access the filter. * @param pkt Parameters needed to compose the filter. * @param sentKeepalivePacket The attributes of the sent keepalive packet. */ public synchronized void addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) { // TODO: implement this. Log.e(TAG, "APF function is not implemented: addKeepalivePacketFilter(" + slot + ", " + pkt + ")"); public synchronized void addKeepalivePacketFilter(final int slot, final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { log("Adding keepalive ack(" + slot + ")"); if (null != mKeepaliveAcks.get(slot)) { throw new IllegalArgumentException("Keepalive slot " + slot + " is occupied"); } final int ipVersion = sentKeepalivePacket.srcAddress.length == 4 ? 4 : 6; mKeepaliveAcks.put(slot, (ipVersion == 4) ? new TcpKeepaliveAckV4(sentKeepalivePacket) : new TcpKeepaliveAckV6(sentKeepalivePacket)); installNewProgramLocked(); } /** Loading @@ -1509,8 +1681,8 @@ public class ApfFilter { * @param slot The index used to access the filter. */ public synchronized void removeKeepalivePacketFilter(int slot) { // TODO: implement this. Log.e(TAG, "APF function is not implemented: removeKeepalivePacketFilter(" + slot + ")"); mKeepaliveAcks.remove(slot); installNewProgramLocked(); } static public long counterValue(byte[] data, Counter counter) Loading Loading @@ -1565,6 +1737,17 @@ public class ApfFilter { } pw.decreaseIndent(); pw.println("Keepalive filter:"); pw.increaseIndent(); for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck keepaliveAck = mKeepaliveAcks.valueAt(i); pw.print("Slot "); pw.print(mKeepaliveAcks.keyAt(i)); pw.print(" : "); pw.println(keepaliveAck); } pw.decreaseIndent(); if (DBG) { pw.println("Last program:"); pw.increaseIndent(); Loading
packages/NetworkStack/src/android/net/apf/ApfGenerator.java +2 −2 Original line number Diff line number Diff line Loading @@ -476,7 +476,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load 16-bits from the packet into * {@code register}. The offset of the loaded 16-bits from the begining of the packet is * {@code register}. The offset of the loaded 16-bits from the beginning of the packet is * the sum of {@code offset} and the value in register R1. */ public ApfGenerator addLoad16Indexed(Register register, int offset) { Loading @@ -488,7 +488,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load 32-bits from the packet into * {@code register}. The offset of the loaded 32-bits from the begining of the packet is * {@code register}. The offset of the loaded 32-bits from the beginning of the packet is * the sum of {@code offset} and the value in register R1. */ public ApfGenerator addLoad32Indexed(Register register, int offset) { Loading
packages/NetworkStack/tests/src/android/net/apf/ApfTest.java +213 −2 File changed.Preview size limit exceeded, changes collapsed. Show changes