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

Commit c6eb439f authored by Xiao Ma's avatar Xiao Ma Committed by Gerrit Code Review
Browse files

Merge "Support Neighbor Advertisement packet w/o TLLA option parsing."

parents b56816d5 11dbaed0
Loading
Loading
Loading
Loading
+12 −7
Original line number Original line Diff line number Diff line
@@ -17,13 +17,14 @@
package com.android.networkstack.packets;
package com.android.networkstack.packets;


import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_HEADER_MIN_LEN;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NA_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;


import android.net.MacAddress;
import android.net.MacAddress;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;


import com.android.net.module.util.Ipv6Utils;
import com.android.net.module.util.Ipv6Utils;
import com.android.net.module.util.Struct;
import com.android.net.module.util.Struct;
@@ -50,12 +51,12 @@ public class NeighborAdvertisement {
    public final Icmpv6Header icmpv6Hdr;
    public final Icmpv6Header icmpv6Hdr;
    @NonNull
    @NonNull
    public final NaHeader naHdr;
    public final NaHeader naHdr;
    @NonNull
    @Nullable
    public final LlaOption tlla;
    public final LlaOption tlla;


    public NeighborAdvertisement(@NonNull final EthernetHeader ethHdr,
    public NeighborAdvertisement(@NonNull final EthernetHeader ethHdr,
            @NonNull final Ipv6Header ipv6Hdr, @NonNull final Icmpv6Header icmpv6Hdr,
            @NonNull final Ipv6Header ipv6Hdr, @NonNull final Icmpv6Header icmpv6Hdr,
            @NonNull final NaHeader naHdr, @NonNull final LlaOption tlla) {
            @NonNull final NaHeader naHdr, @Nullable final LlaOption tlla) {
        this.ethHdr = ethHdr;
        this.ethHdr = ethHdr;
        this.ipv6Hdr = ipv6Hdr;
        this.ipv6Hdr = ipv6Hdr;
        this.icmpv6Hdr = icmpv6Hdr;
        this.icmpv6Hdr = icmpv6Hdr;
@@ -71,7 +72,7 @@ public class NeighborAdvertisement {
        final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
        final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
        final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.class);
        final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.class);
        final int naHeaderLen = Struct.getSize(NaHeader.class);
        final int naHeaderLen = Struct.getSize(NaHeader.class);
        final int tllaOptionLen = Struct.getSize(LlaOption.class);
        final int tllaOptionLen = (tlla == null) ? 0 : Struct.getSize(LlaOption.class);
        final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv6HeaderLen
        final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv6HeaderLen
                + icmpv6HeaderLen + naHeaderLen + tllaOptionLen);
                + icmpv6HeaderLen + naHeaderLen + tllaOptionLen);


@@ -79,7 +80,9 @@ public class NeighborAdvertisement {
        ipv6Hdr.writeToByteBuffer(packet);
        ipv6Hdr.writeToByteBuffer(packet);
        icmpv6Hdr.writeToByteBuffer(packet);
        icmpv6Hdr.writeToByteBuffer(packet);
        naHdr.writeToByteBuffer(packet);
        naHdr.writeToByteBuffer(packet);
        if (tlla != null) {
            tlla.writeToByteBuffer(packet);
            tlla.writeToByteBuffer(packet);
        }
        packet.flip();
        packet.flip();


        return packet;
        return packet;
@@ -100,7 +103,7 @@ public class NeighborAdvertisement {
     */
     */
    public static NeighborAdvertisement parse(@NonNull final byte[] recvbuf, final int length)
    public static NeighborAdvertisement parse(@NonNull final byte[] recvbuf, final int length)
            throws ParseException {
            throws ParseException {
        if (length < ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_MIN_LEN
        if (length < ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_NA_HEADER_LEN
                || recvbuf.length < length) {
                || recvbuf.length < length) {
            throw new ParseException("Invalid packet length: " + length);
            throw new ParseException("Invalid packet length: " + length);
        }
        }
@@ -111,7 +114,9 @@ public class NeighborAdvertisement {
        final Ipv6Header ipv6Hdr = Struct.parse(Ipv6Header.class, packet);
        final Ipv6Header ipv6Hdr = Struct.parse(Ipv6Header.class, packet);
        final Icmpv6Header icmpv6Hdr = Struct.parse(Icmpv6Header.class, packet);
        final Icmpv6Header icmpv6Hdr = Struct.parse(Icmpv6Header.class, packet);
        final NaHeader naHdr = Struct.parse(NaHeader.class, packet);
        final NaHeader naHdr = Struct.parse(NaHeader.class, packet);
        final LlaOption tlla = Struct.parse(LlaOption.class, packet);
        final LlaOption tlla = (packet.remaining() == 0)
                ? null
                : Struct.parse(LlaOption.class, packet);


        return new NeighborAdvertisement(ethHdr, ipv6Hdr, icmpv6Hdr, naHdr, tlla);
        return new NeighborAdvertisement(ethHdr, ipv6Hdr, icmpv6Hdr, naHdr, tlla);
    }
    }
+2 −4
Original line number Original line Diff line number Diff line
@@ -17,8 +17,8 @@
package com.android.networkstack.packets;
package com.android.networkstack.packets;


import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_HEADER_MIN_LEN;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NS_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;


import android.net.MacAddress;
import android.net.MacAddress;
@@ -43,8 +43,6 @@ import java.nio.ByteBuffer;
 * @hide
 * @hide
 */
 */
public class NeighborSolicitation {
public class NeighborSolicitation {
    private static final int NS_HEADER_LEN = Struct.getSize(NsHeader.class);

    @NonNull
    @NonNull
    public final EthernetHeader ethHdr;
    public final EthernetHeader ethHdr;
    @NonNull
    @NonNull
@@ -105,7 +103,7 @@ public class NeighborSolicitation {
     */
     */
    public static NeighborSolicitation parse(@NonNull final byte[] recvbuf, final int length)
    public static NeighborSolicitation parse(@NonNull final byte[] recvbuf, final int length)
            throws ParseException {
            throws ParseException {
        if (length < ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_MIN_LEN + NS_HEADER_LEN
        if (length < ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_NS_HEADER_LEN
                || recvbuf.length < length) {
                || recvbuf.length < length) {
            throw new ParseException("Invalid packet length: " + length);
            throw new ParseException("Invalid packet length: " + length);
        }
        }
+73 −10
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.networkstack.packets;
import static android.system.OsConstants.ETH_P_IPV6;
import static android.system.OsConstants.ETH_P_IPV6;
import static android.system.OsConstants.IPPROTO_ICMPV6;
import static android.system.OsConstants.IPPROTO_ICMPV6;


import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.MiscAsserts.assertThrows;
@@ -90,6 +91,41 @@ public final class NeighborAdvertisementTest {
        // Link-Layer address
        // Link-Layer address
        (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
        (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
    };
    };
    private static final byte[] TEST_GRATUITOUS_NA_WITHOUT_TLLA = new byte[] {
        // dst mac address
        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
        // src mac address
        (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
        // ether type
        (byte) 0x86, (byte) 0xdd,
        // version, priority and flow label
        (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        // length
        (byte) 0x00, (byte) 0x20,
        // next header
        (byte) 0x3a,
        // hop limit
        (byte) 0xff,
        // source address
        (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0xdf, (byte) 0xd9, (byte) 0x50, (byte) 0xa0,
        (byte) 0xcc, (byte) 0x7b, (byte) 0x7d, (byte) 0x6d,
        // destination address
        (byte) 0xff, (byte) 0x02, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
        // ICMP type, code, checksum
        (byte) 0x88, (byte) 0x00, (byte) 0x3a, (byte) 0x3c,
        // flags
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        // target address
        (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
        (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
        (byte) 0xc9, (byte) 0x28, (byte) 0x25, (byte) 0x0d,
        (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
    };
    private static final byte[] TEST_GRATUITOUS_NA_LESS_LENGTH = new byte[] {
    private static final byte[] TEST_GRATUITOUS_NA_LESS_LENGTH = new byte[] {
        // dst mac address
        // dst mac address
        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
@@ -115,6 +151,10 @@ public final class NeighborAdvertisementTest {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
        // ICMP type, code, checksum
        (byte) 0x88, (byte) 0x00, (byte) 0x3a, (byte) 0x3c,
        // flags
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
    };
    };
    private static final byte[] TEST_GRATUITOUS_NA_TRUNCATED = new byte[] {
    private static final byte[] TEST_GRATUITOUS_NA_TRUNCATED = new byte[] {
        // dst mac address
        // dst mac address
@@ -152,7 +192,7 @@ public final class NeighborAdvertisementTest {
        (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
        (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
        // TLLA option
        // TLLA option
        (byte) 0x02, (byte) 0x01,
        (byte) 0x02, (byte) 0x01,
        // Link-Layer address
        // truncatd Link-Layer address: 4bytes
        (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25,
        (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25,
    };
    };


@@ -165,11 +205,8 @@ public final class NeighborAdvertisementTest {
        assertArrayEquals(na.array(), TEST_GRATUITOUS_NA);
        assertArrayEquals(na.array(), TEST_GRATUITOUS_NA);
    }
    }


    @Test
    private void assertNeighborAdvertisement(final NeighborAdvertisement na,
    public void testGratuitousNa_parse() throws Exception {
            boolean hasTllaOption) {
        final NeighborAdvertisement na = NeighborAdvertisement.parse(TEST_GRATUITOUS_NA,
                TEST_GRATUITOUS_NA.length);

        assertArrayEquals(TEST_SOURCE_MAC_ADDR, na.ethHdr.srcMac.toByteArray());
        assertArrayEquals(TEST_SOURCE_MAC_ADDR, na.ethHdr.srcMac.toByteArray());
        assertArrayEquals(TEST_DST_MAC_ADDR, na.ethHdr.dstMac.toByteArray());
        assertArrayEquals(TEST_DST_MAC_ADDR, na.ethHdr.dstMac.toByteArray());
        assertEquals(ETH_P_IPV6, na.ethHdr.etherType);
        assertEquals(ETH_P_IPV6, na.ethHdr.etherType);
@@ -181,19 +218,45 @@ public final class NeighborAdvertisementTest {
        assertEquals(0, na.icmpv6Hdr.code);
        assertEquals(0, na.icmpv6Hdr.code);
        assertEquals(0, na.naHdr.flags);
        assertEquals(0, na.naHdr.flags);
        assertEquals(TEST_TARGET_ADDR, na.naHdr.target);
        assertEquals(TEST_TARGET_ADDR, na.naHdr.target);
        assertEquals(2, na.tlla.type);
        if (hasTllaOption) {
            assertEquals(ICMPV6_ND_OPTION_TLLA, na.tlla.type);
            assertEquals(1, na.tlla.length);
            assertEquals(1, na.tlla.length);
            assertArrayEquals(TEST_SOURCE_MAC_ADDR, na.tlla.linkLayerAddress.toByteArray());
            assertArrayEquals(TEST_SOURCE_MAC_ADDR, na.tlla.linkLayerAddress.toByteArray());
        }
    }

    @Test
    public void testGratuitousNa_parse() throws Exception {
        final NeighborAdvertisement na = NeighborAdvertisement.parse(TEST_GRATUITOUS_NA,
                TEST_GRATUITOUS_NA.length);


        assertNeighborAdvertisement(na, true /* hasTllaOption */);
        assertArrayEquals(TEST_GRATUITOUS_NA, na.toByteBuffer().array());
        assertArrayEquals(TEST_GRATUITOUS_NA, na.toByteBuffer().array());
    }
    }


    @Test
    @Test
    public void testGratuitousNa_invalidByteBufferParameters() throws Exception {
    public void testGratuitousNa_parseWithoutTllaOption() throws Exception {
        final NeighborAdvertisement na =
                NeighborAdvertisement.parse(TEST_GRATUITOUS_NA_WITHOUT_TLLA,
                        TEST_GRATUITOUS_NA_WITHOUT_TLLA.length);

        assertNeighborAdvertisement(na, false /* hasTllaOption */);
        assertArrayEquals(TEST_GRATUITOUS_NA_WITHOUT_TLLA, na.toByteBuffer().array());
    }

    @Test
    public void testGratuitousNa_zeroPacketLength() throws Exception {
        assertThrows(NeighborAdvertisement.ParseException.class,
        assertThrows(NeighborAdvertisement.ParseException.class,
                () -> NeighborAdvertisement.parse(TEST_GRATUITOUS_NA, 0));
                () -> NeighborAdvertisement.parse(TEST_GRATUITOUS_NA, 0));
    }
    }


    @Test
    public void testGratuitousNa_invalidByteBufferLength() throws Exception {
        assertThrows(NeighborAdvertisement.ParseException.class,
                () -> NeighborAdvertisement.parse(TEST_GRATUITOUS_NA_TRUNCATED,
                                                  TEST_GRATUITOUS_NA.length));
    }

    @Test
    @Test
    public void testGratuitousNa_lessPacketLength() throws Exception {
    public void testGratuitousNa_lessPacketLength() throws Exception {
        assertThrows(NeighborAdvertisement.ParseException.class,
        assertThrows(NeighborAdvertisement.ParseException.class,
+4 −1
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.networkstack.packets;
import static android.system.OsConstants.ETH_P_IPV6;
import static android.system.OsConstants.ETH_P_IPV6;
import static android.system.OsConstants.IPPROTO_ICMPV6;
import static android.system.OsConstants.IPPROTO_ICMPV6;


import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.MiscAsserts.assertThrows;


@@ -193,7 +194,7 @@ public final class NeighborSolicitationTest {
        (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
        (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
        // slla option
        // slla option
        (byte) 0x01, (byte) 0x01,
        (byte) 0x01, (byte) 0x01,
        // link-layer address
        // truncatd link-layer address: 4bytes
        (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02,
        (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02,
    };
    };


@@ -218,6 +219,8 @@ public final class NeighborSolicitationTest {
        assertEquals(0, ns.icmpv6Hdr.code);
        assertEquals(0, ns.icmpv6Hdr.code);
        assertEquals(TEST_TARGET_ADDR, ns.nsHdr.target);
        assertEquals(TEST_TARGET_ADDR, ns.nsHdr.target);
        if (hasSllaOption) {
        if (hasSllaOption) {
            assertEquals(ICMPV6_ND_OPTION_SLLA, ns.slla.type);
            assertEquals(1, ns.slla.length);
            assertEquals(MacAddress.fromBytes(TEST_SOURCE_MAC_ADDR), ns.slla.linkLayerAddress);
            assertEquals(MacAddress.fromBytes(TEST_SOURCE_MAC_ADDR), ns.slla.linkLayerAddress);
        }
        }
    }
    }