Add some ipv6 packet utils
1. Allow build icmpv6 packet without ethernet header.
2. Add util for building icmpv6 echo reply.
Bug: 183166581
Test: atest EthernetTetheringTest
Change-Id: I79eb78c8ae4859749f5a5d8d0dc240025d8784e2
diff --git a/staticlibs/device/com/android/net/module/util/Ipv6Utils.java b/staticlibs/device/com/android/net/module/util/Ipv6Utils.java
index fe7c89b..d538221 100644
--- a/staticlibs/device/com/android/net/module/util/Ipv6Utils.java
+++ b/staticlibs/device/com/android/net/module/util/Ipv6Utils.java
@@ -20,6 +20,7 @@
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_REPLY_TYPE;
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;
@@ -45,29 +46,23 @@
*/
public class Ipv6Utils {
/**
- * Build a generic ICMPv6 packet(e.g., packet used in the neighbor discovery protocol).
+ * Build a generic ICMPv6 packet without Ethernet header.
*/
- 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);
+ public static ByteBuffer buildIcmpv6Packet(final Inet6Address srcIp, final Inet6Address dstIp,
+ short type, short code, final ByteBuffer... options) {
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 ByteBuffer packet = ByteBuffer.allocate(ipv6HeaderLen + icmpv6HeaderLen + payloadLen);
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) {
@@ -79,11 +74,31 @@
packet.flip();
// Populate the ICMPv6 checksum field.
- packet.putShort(etherHeaderLen + ipv6HeaderLen + 2, icmpv6Checksum(packet,
- etherHeaderLen /* ipOffset */,
- (int) (etherHeaderLen + ipv6HeaderLen) /* transportOffset */,
+ packet.putShort(ipv6HeaderLen + 2, icmpv6Checksum(packet, 0 /* ipOffset */,
+ ipv6HeaderLen /* transportOffset */,
(short) (icmpv6HeaderLen + payloadLen) /* transportLen */));
return packet;
+
+ }
+
+ /**
+ * 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 ByteBuffer payload = buildIcmpv6Packet(srcIp, dstIp, type, code, options);
+
+ final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
+ final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + payload.limit());
+ final EthernetHeader ethHeader =
+ new EthernetHeader(dstMac, srcMac, (short) ETHER_TYPE_IPV6);
+
+ ethHeader.writeToByteBuffer(packet);
+ packet.put(payload);
+ packet.flip();
+
+ return packet;
}
/**
@@ -159,4 +174,14 @@
return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
(byte) ICMPV6_ECHO_REQUEST_TYPE /* type */, (byte) 0 /* code */, payload);
}
+
+ /**
+ * Build an ICMPv6 Echo Reply packet without ethernet header.
+ */
+ public static ByteBuffer buildEchoReplyPacket(final Inet6Address srcIp,
+ final Inet6Address dstIp) {
+ final ByteBuffer payload = ByteBuffer.allocate(4); // ID and Sequence number may be zero.
+ return buildIcmpv6Packet(srcIp, dstIp, (byte) ICMPV6_ECHO_REPLY_TYPE /* type */,
+ (byte) 0 /* code */, payload);
+ }
}