All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.android.net.module.util.Ipv6Utils Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 15-robolectric-12650502
Show newest version
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.net.module.util;

import static android.system.OsConstants.IPPROTO_ICMPV6;

import static com.android.net.module.util.IpUtils.icmpv6Checksum;
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_SOLICITATION;

import android.net.MacAddress;

import com.android.net.module.util.structs.EthernetHeader;
import com.android.net.module.util.structs.Icmpv6Header;
import com.android.net.module.util.structs.Ipv6Header;
import com.android.net.module.util.structs.NaHeader;
import com.android.net.module.util.structs.NsHeader;
import com.android.net.module.util.structs.RaHeader;
import com.android.net.module.util.structs.RsHeader;

import java.net.Inet6Address;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Utilities for IPv6 packets.
 */
public class Ipv6Utils {
    /**
     * Build a generic ICMPv6 packet(e.g., packet used in the neighbor discovery protocol).
     */
    public static ByteBuffer buildIcmpv6Packet(final MacAddress srcMac, final MacAddress dstMac,
            final Inet6Address srcIp, final Inet6Address dstIp, short type, short code,
            final ByteBuffer... options) {
        final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
        final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
        final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.class);
        int payloadLen = 0;
        for (ByteBuffer option: options) {
            payloadLen += option.limit();
        }
        final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv6HeaderLen
                + icmpv6HeaderLen + payloadLen);
        final EthernetHeader ethHeader =
                new EthernetHeader(dstMac, srcMac, (short) ETHER_TYPE_IPV6);
        final Ipv6Header ipv6Header =
                new Ipv6Header((int) 0x60000000 /* version, traffic class, flowlabel */,
                icmpv6HeaderLen + payloadLen /* payload length */,
                (byte) IPPROTO_ICMPV6 /* next header */, (byte) 0xff /* hop limit */, srcIp, dstIp);
        final Icmpv6Header icmpv6Header = new Icmpv6Header(type, code, (short) 0 /* checksum */);

        ethHeader.writeToByteBuffer(packet);
        ipv6Header.writeToByteBuffer(packet);
        icmpv6Header.writeToByteBuffer(packet);
        for (ByteBuffer option : options) {
            packet.put(option);
            // in case option might be reused by caller, restore the position and
            // limit of bytebuffer.
            option.clear();
        }
        packet.flip();

        // Populate the ICMPv6 checksum field.
        packet.putShort(etherHeaderLen + ipv6HeaderLen + 2, icmpv6Checksum(packet,
                etherHeaderLen /* ipOffset */,
                (int) (etherHeaderLen + ipv6HeaderLen) /* transportOffset */,
                (short) (icmpv6HeaderLen + payloadLen) /* transportLen */));
        return packet;
    }

    /**
     * Build the ICMPv6 packet payload including payload header and specific options.
     */
    private static ByteBuffer[] buildIcmpv6Payload(final ByteBuffer payloadHeader,
            final ByteBuffer... options) {
        final ByteBuffer[] payload = new ByteBuffer[options.length + 1];
        payload[0] = payloadHeader;
        System.arraycopy(options, 0, payload, 1, options.length);
        return payload;
    }

    /**
     * Build an ICMPv6 Router Advertisement packet from the required specified parameters.
     */
    public static ByteBuffer buildRaPacket(final MacAddress srcMac, final MacAddress dstMac,
            final Inet6Address srcIp, final Inet6Address dstIp, final byte flags,
            final int lifetime, final long reachableTime, final long retransTimer,
            final ByteBuffer... options) {
        final RaHeader raHeader = new RaHeader((byte) 0 /* hopLimit, unspecified */,
                flags, lifetime, reachableTime, retransTimer);
        final ByteBuffer[] payload = buildIcmpv6Payload(
                ByteBuffer.wrap(raHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
        return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
                (byte) ICMPV6_ROUTER_ADVERTISEMENT /* type */, (byte) 0 /* code */, payload);
    }

    /**
     * Build an ICMPv6 Neighbor Advertisement packet from the required specified parameters.
     */
    public static ByteBuffer buildNaPacket(final MacAddress srcMac, final MacAddress dstMac,
            final Inet6Address srcIp, final Inet6Address dstIp, final int flags,
            final Inet6Address target, final ByteBuffer... options) {
        final NaHeader naHeader = new NaHeader(flags, target);
        final ByteBuffer[] payload = buildIcmpv6Payload(
                ByteBuffer.wrap(naHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
        return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
                (byte) ICMPV6_NEIGHBOR_ADVERTISEMENT /* type */, (byte) 0 /* code */, payload);
    }

    /**
     * Build an ICMPv6 Neighbor Solicitation packet from the required specified parameters.
     */
    public static ByteBuffer buildNsPacket(final MacAddress srcMac, final MacAddress dstMac,
            final Inet6Address srcIp, final Inet6Address dstIp,
            final Inet6Address target, final ByteBuffer... options) {
        final NsHeader nsHeader = new NsHeader(target);
        final ByteBuffer[] payload = buildIcmpv6Payload(
                ByteBuffer.wrap(nsHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
        return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
                (byte) ICMPV6_NEIGHBOR_SOLICITATION /* type */, (byte) 0 /* code */, payload);
    }

    /**
     * Build an ICMPv6 Router Solicitation packet from the required specified parameters.
     */
    public static ByteBuffer buildRsPacket(final MacAddress srcMac, final MacAddress dstMac,
            final Inet6Address srcIp, final Inet6Address dstIp, final ByteBuffer... options) {
        final RsHeader rsHeader = new RsHeader((int) 0 /* reserved */);
        final ByteBuffer[] payload = buildIcmpv6Payload(
                ByteBuffer.wrap(rsHeader.writeToBytes(ByteOrder.BIG_ENDIAN)), options);
        return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
                (byte) ICMPV6_ROUTER_SOLICITATION /* type */, (byte) 0 /* code */, payload);
    }

    /**
     * Build an ICMPv6 Echo Request packet from the required specified parameters.
     */
    public static ByteBuffer buildEchoRequestPacket(final MacAddress srcMac,
            final MacAddress dstMac, final Inet6Address srcIp, final Inet6Address dstIp) {
        final ByteBuffer payload = ByteBuffer.allocate(4); // ID and Sequence number may be zero.
        return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
                (byte) ICMPV6_ECHO_REQUEST_TYPE /* type */, (byte) 0 /* code */, payload);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy