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

Commit 8e37fa17 authored by Xiao Ma's avatar Xiao Ma Committed by Automerger Merge Worker
Browse files

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

Merge "Support Neighbor Advertisement packet w/o TLLA option parsing." am: c6eb439f am: a73d636c am: e5b4fbaf

Original change: https://android-review.googlesource.com/c/platform/packages/modules/NetworkStack/+/1736503

Change-Id: I85be6a51a09f102a555212f55a3577b8c374b3bf
parents 5f845b33 e5b4fbaf
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -17,13 +17,14 @@
package com.android.networkstack.packets;

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.IPV6_HEADER_LEN;

import android.net.MacAddress;

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

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

    public NeighborAdvertisement(@NonNull final EthernetHeader ethHdr,
            @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.ipv6Hdr = ipv6Hdr;
        this.icmpv6Hdr = icmpv6Hdr;
@@ -71,7 +72,7 @@ public class NeighborAdvertisement {
        final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
        final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.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
                + icmpv6HeaderLen + naHeaderLen + tllaOptionLen);

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

        return packet;
@@ -100,7 +103,7 @@ public class NeighborAdvertisement {
     */
    public static NeighborAdvertisement parse(@NonNull final byte[] recvbuf, final int length)
            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) {
            throw new ParseException("Invalid packet length: " + length);
        }
@@ -111,7 +114,9 @@ public class NeighborAdvertisement {
        final Ipv6Header ipv6Hdr = Struct.parse(Ipv6Header.class, packet);
        final Icmpv6Header icmpv6Hdr = Struct.parse(Icmpv6Header.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);
    }
+2 −4
Original line number Diff line number Diff line
@@ -17,8 +17,8 @@
package com.android.networkstack.packets;

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_NS_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;

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

    @NonNull
    public final EthernetHeader ethHdr;
    @NonNull
@@ -105,7 +103,7 @@ public class NeighborSolicitation {
     */
    public static NeighborSolicitation parse(@NonNull final byte[] recvbuf, final int length)
            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) {
            throw new ParseException("Invalid packet length: " + length);
        }
+73 −10
Original line number 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.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.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
import static com.android.testutils.MiscAsserts.assertThrows;
@@ -90,6 +91,41 @@ public final class NeighborAdvertisementTest {
        // Link-Layer address
        (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[] {
        // dst mac address
        (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) 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[] {
        // dst mac address
@@ -152,7 +192,7 @@ public final class NeighborAdvertisementTest {
        (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
        // TLLA option
        (byte) 0x02, (byte) 0x01,
        // Link-Layer address
        // truncatd Link-Layer address: 4bytes
        (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25,
    };

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

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

    private void assertNeighborAdvertisement(final NeighborAdvertisement na,
            boolean hasTllaOption) {
        assertArrayEquals(TEST_SOURCE_MAC_ADDR, na.ethHdr.srcMac.toByteArray());
        assertArrayEquals(TEST_DST_MAC_ADDR, na.ethHdr.dstMac.toByteArray());
        assertEquals(ETH_P_IPV6, na.ethHdr.etherType);
@@ -181,19 +218,45 @@ public final class NeighborAdvertisementTest {
        assertEquals(0, na.icmpv6Hdr.code);
        assertEquals(0, na.naHdr.flags);
        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);
            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());
    }

    @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,
                () -> 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
    public void testGratuitousNa_lessPacketLength() throws Exception {
        assertThrows(NeighborAdvertisement.ParseException.class,
+4 −1
Original line number 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.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.testutils.MiscAsserts.assertThrows;

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

@@ -218,6 +219,8 @@ public final class NeighborSolicitationTest {
        assertEquals(0, ns.icmpv6Hdr.code);
        assertEquals(TEST_TARGET_ADDR, ns.nsHdr.target);
        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);
        }
    }