Loading src/android/net/apf/ApfFilter.java +6 −5 Original line number Diff line number Diff line Loading @@ -514,9 +514,9 @@ public class ApfFilter { public final Type type; /** Offset into the packet at which this section begins. */ public final int start; /** Length of this section. */ /** Length of this section in bytes. */ public final int length; /** If this is a lifetime, the ICMP option that the defined it. 0 for router lifetime. */ /** If this is a lifetime, the ICMP option that defined it. 0 for router lifetime. */ public final int option; /** If this is a lifetime, the lifetime value. */ public final long lifetime; Loading Loading @@ -785,8 +785,9 @@ public class ApfFilter { addLifetimeSection(ICMP6_RA_ROUTER_LIFETIME_LEN, 0, routerLifetime); builder.updateRouterLifetime(routerLifetime); // Ensures that the RA is not truncated. mPacket.position(ICMP6_RA_OPTION_OFFSET); // Add remaining fields (reachable time and retransmission timer) to match section. addMatchUntil(ICMP6_RA_OPTION_OFFSET); while (mPacket.hasRemaining()) { final int position = mPacket.position(); final int optionType = getUint8(mPacket, position); Loading @@ -797,7 +798,7 @@ public class ApfFilter { mPrefixOptionOffsets.add(position); // Parse valid lifetime addMatchSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN); addMatchSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET); lifetime = getUint32(mPacket, mPacket.position()); addLifetimeSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN, ICMP6_PREFIX_OPTION_TYPE, lifetime); Loading tests/unit/src/android/net/apf/ApfTest.java +76 −11 Original line number Diff line number Diff line Loading @@ -1056,10 +1056,14 @@ public class ApfTest { private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; private static final int ICMP6_RA_HEADER_LEN = 16; private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6; private static final int ICMP6_RA_CHECKSUM_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 2; private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6; private static final int ICMP6_RA_REACHABLE_TIME_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 8; private static final int ICMP6_RA_RETRANSMISSION_TIMER_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 12; private static final int ICMP6_RA_OPTION_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; Loading Loading @@ -2000,6 +2004,25 @@ public class ApfTest { ipClientCallback.assertNoProgramUpdate(); } private ByteBuffer makeBaseRaPacket() { ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); final int ROUTER_LIFETIME = 1000; final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN; // IPv6, traffic class = 0, flow label = 0x12345 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6); basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, VERSION_TRAFFIC_CLASS_FLOW_LABEL); basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6); basePacket.put(ICMP6_TYPE_OFFSET, (byte) ICMP6_ROUTER_ADVERTISEMENT); basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short) ROUTER_LIFETIME); basePacket.position(IPV6_DEST_ADDR_OFFSET); basePacket.put(IPV6_ALL_NODES_ADDRESS); return basePacket; } @Test public void testApfFilterRa() throws Exception { MockIpClientCallback ipClientCallback = new MockIpClientCallback(); Loading @@ -2021,15 +2044,7 @@ public class ApfTest { final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; // Verify RA is passed the first time ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, VERSION_TRAFFIC_CLASS_FLOW_LABEL); basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT); basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME); basePacket.position(IPV6_DEST_ADDR_OFFSET); basePacket.put(IPV6_ALL_NODES_ADDRESS); ByteBuffer basePacket = makeBaseRaPacket(); assertPass(program, basePacket.array()); verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME); Loading Loading @@ -2083,6 +2098,16 @@ public class ApfTest { verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME); verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1)); // Check that RIOs differing only in the first 4 bytes are different. ByteBuffer similarRouteInfoOptionPacket = ByteBuffer.wrap( new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]); basePacket.clear(); similarRouteInfoOptionPacket.put(basePacket); addRioOption(similarRouteInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/64"); // Packet should be passed because it is different. program = ipClientCallback.getApfProgram(); assertPass(program, similarRouteInfoOptionPacket.array()); ByteBuffer dnsslOptionPacket = ByteBuffer.wrap( new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); basePacket.clear(); Loading Loading @@ -2111,6 +2136,46 @@ public class ApfTest { apfFilter.shutdown(); } @Test public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception { final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); byte[] program = ipClientCallback.getApfProgram(); final int RA_REACHABLE_TIME = 1800; final int RA_RETRANSMISSION_TIMER = 1234; // Create an Ra packet without options // Reachable time = 1800, retransmission timer = 1234 ByteBuffer raPacket = makeBaseRaPacket(); raPacket.position(ICMP6_RA_REACHABLE_TIME_OFFSET); raPacket.putInt(RA_REACHABLE_TIME); raPacket.putInt(RA_RETRANSMISSION_TIMER); // First RA passes filter assertPass(program, raPacket.array()); // Assume apf is shown the given RA, it generates program to filter it. ipClientCallback.resetApfProgramWait(); apfFilter.pretendPacketReceived(raPacket.array()); program = ipClientCallback.getApfProgram(); assertDrop(program, raPacket.array()); // A packet with different reachable time should be passed. // Reachable time = 2300, retransmission timer = 1234 raPacket.clear(); raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME + 500); assertPass(program, raPacket.array()); // A packet with different retransmission timer should be passed. // Reachable time = 1800, retransmission timer = 2234 raPacket.clear(); raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME); raPacket.putInt(ICMP6_RA_RETRANSMISSION_TIMER_OFFSET, RA_RETRANSMISSION_TIMER + 1000); assertPass(program, raPacket.array()); } /** * Stage a file for testing, i.e. make it native accessible. Given a resource ID, * copy that resource into the app's data directory and return the path to it. Loading Loading
src/android/net/apf/ApfFilter.java +6 −5 Original line number Diff line number Diff line Loading @@ -514,9 +514,9 @@ public class ApfFilter { public final Type type; /** Offset into the packet at which this section begins. */ public final int start; /** Length of this section. */ /** Length of this section in bytes. */ public final int length; /** If this is a lifetime, the ICMP option that the defined it. 0 for router lifetime. */ /** If this is a lifetime, the ICMP option that defined it. 0 for router lifetime. */ public final int option; /** If this is a lifetime, the lifetime value. */ public final long lifetime; Loading Loading @@ -785,8 +785,9 @@ public class ApfFilter { addLifetimeSection(ICMP6_RA_ROUTER_LIFETIME_LEN, 0, routerLifetime); builder.updateRouterLifetime(routerLifetime); // Ensures that the RA is not truncated. mPacket.position(ICMP6_RA_OPTION_OFFSET); // Add remaining fields (reachable time and retransmission timer) to match section. addMatchUntil(ICMP6_RA_OPTION_OFFSET); while (mPacket.hasRemaining()) { final int position = mPacket.position(); final int optionType = getUint8(mPacket, position); Loading @@ -797,7 +798,7 @@ public class ApfFilter { mPrefixOptionOffsets.add(position); // Parse valid lifetime addMatchSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN); addMatchSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET); lifetime = getUint32(mPacket, mPacket.position()); addLifetimeSection(ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN, ICMP6_PREFIX_OPTION_TYPE, lifetime); Loading
tests/unit/src/android/net/apf/ApfTest.java +76 −11 Original line number Diff line number Diff line Loading @@ -1056,10 +1056,14 @@ public class ApfTest { private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; private static final int ICMP6_RA_HEADER_LEN = 16; private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6; private static final int ICMP6_RA_CHECKSUM_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 2; private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6; private static final int ICMP6_RA_REACHABLE_TIME_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 8; private static final int ICMP6_RA_RETRANSMISSION_TIMER_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + 12; private static final int ICMP6_RA_OPTION_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; Loading Loading @@ -2000,6 +2004,25 @@ public class ApfTest { ipClientCallback.assertNoProgramUpdate(); } private ByteBuffer makeBaseRaPacket() { ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); final int ROUTER_LIFETIME = 1000; final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN; // IPv6, traffic class = 0, flow label = 0x12345 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6); basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, VERSION_TRAFFIC_CLASS_FLOW_LABEL); basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6); basePacket.put(ICMP6_TYPE_OFFSET, (byte) ICMP6_ROUTER_ADVERTISEMENT); basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short) ROUTER_LIFETIME); basePacket.position(IPV6_DEST_ADDR_OFFSET); basePacket.put(IPV6_ALL_NODES_ADDRESS); return basePacket; } @Test public void testApfFilterRa() throws Exception { MockIpClientCallback ipClientCallback = new MockIpClientCallback(); Loading @@ -2021,15 +2044,7 @@ public class ApfTest { final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; // Verify RA is passed the first time ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, VERSION_TRAFFIC_CLASS_FLOW_LABEL); basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT); basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME); basePacket.position(IPV6_DEST_ADDR_OFFSET); basePacket.put(IPV6_ALL_NODES_ADDRESS); ByteBuffer basePacket = makeBaseRaPacket(); assertPass(program, basePacket.array()); verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME); Loading Loading @@ -2083,6 +2098,16 @@ public class ApfTest { verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME); verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1)); // Check that RIOs differing only in the first 4 bytes are different. ByteBuffer similarRouteInfoOptionPacket = ByteBuffer.wrap( new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]); basePacket.clear(); similarRouteInfoOptionPacket.put(basePacket); addRioOption(similarRouteInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/64"); // Packet should be passed because it is different. program = ipClientCallback.getApfProgram(); assertPass(program, similarRouteInfoOptionPacket.array()); ByteBuffer dnsslOptionPacket = ByteBuffer.wrap( new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); basePacket.clear(); Loading Loading @@ -2111,6 +2136,46 @@ public class ApfTest { apfFilter.shutdown(); } @Test public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception { final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration config = getDefaultConfig(); config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); byte[] program = ipClientCallback.getApfProgram(); final int RA_REACHABLE_TIME = 1800; final int RA_RETRANSMISSION_TIMER = 1234; // Create an Ra packet without options // Reachable time = 1800, retransmission timer = 1234 ByteBuffer raPacket = makeBaseRaPacket(); raPacket.position(ICMP6_RA_REACHABLE_TIME_OFFSET); raPacket.putInt(RA_REACHABLE_TIME); raPacket.putInt(RA_RETRANSMISSION_TIMER); // First RA passes filter assertPass(program, raPacket.array()); // Assume apf is shown the given RA, it generates program to filter it. ipClientCallback.resetApfProgramWait(); apfFilter.pretendPacketReceived(raPacket.array()); program = ipClientCallback.getApfProgram(); assertDrop(program, raPacket.array()); // A packet with different reachable time should be passed. // Reachable time = 2300, retransmission timer = 1234 raPacket.clear(); raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME + 500); assertPass(program, raPacket.array()); // A packet with different retransmission timer should be passed. // Reachable time = 1800, retransmission timer = 2234 raPacket.clear(); raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME); raPacket.putInt(ICMP6_RA_RETRANSMISSION_TIMER_OFFSET, RA_RETRANSMISSION_TIMER + 1000); assertPass(program, raPacket.array()); } /** * Stage a file for testing, i.e. make it native accessible. Given a resource ID, * copy that resource into the app's data directory and return the path to it. Loading