diff --git a/staticlibs/testutils/devicetests/com/android/testutils/PacketBuilderUtils.kt b/staticlibs/testutils/devicetests/com/android/testutils/PacketBuilderUtils.kt index 7a952f4df8..3475c72584 100644 --- a/staticlibs/testutils/devicetests/com/android/testutils/PacketBuilderUtils.kt +++ b/staticlibs/testutils/devicetests/com/android/testutils/PacketBuilderUtils.kt @@ -105,13 +105,14 @@ class NaPkt( } /** Add Target Link-Layer Address Option */ - fun addTllaOption(lla: MacAddress) { + fun addTllaOption(lla: MacAddress): NaPkt { val llao = ByteBuffer.allocate(8) llao.put(2) // Type = 2 (Target Link-layer Address) llao.put(1) // Length in units of 8 octets llao.put(lla.toByteArray()) llao.flip() outputStream.write(llao.array()) + return this } /** @@ -119,8 +120,8 @@ class NaPkt( * * @param lla Link-Layer Address as a String; e.g. {@code "0:0:5e:0:53:0"} */ - fun addTllaOption(lla: String) { - addTllaOption(MacAddress.fromString(lla)) + fun addTllaOption(lla: String): NaPkt { + return addTllaOption(MacAddress.fromString(lla)) } override fun toByteArray() = outputStream.toByteArray() @@ -130,6 +131,11 @@ class NaPkt( * Class that facilitates the creation of RA packets. * * Default argument values reflect the rfc4861 defaults where applicable. + * + * @param routerLft lifetime of the default router in seconds. + * @param reachableTime The time, in milliseconds, that a node assumes a neighbor is reachable. + * @param retransTimer The time, in milliseconds, between retransmitted NS messages. + * @param flags The Router Advertisement flags. */ class RaPkt( private val routerLft: Short, @@ -137,6 +143,14 @@ class RaPkt( private val retransTimer: Int, private val flags: EnumSet, ) : L4Packet { + /** + * Convenience constructor accepting flags parameter as String + * + * @param routerLft lifetime of the default router in seconds. + * @param reachableTime The time, in milliseconds, that a node assumes a neighbor is reachable. + * @param retransTimer The time, in milliseconds, between retransmitted NS messages. + * @param flags The Router Advertisement flags as a String; e.g. {@code "MO"}. Defaults to "". + */ constructor( routerLft: Short = 1800, reachableTime: Int = 0, @@ -145,7 +159,9 @@ class RaPkt( ) : this(routerLft, reachableTime, retransTimer, enumSetOfFlags(flags)) enum class RaFlags(override val value: Int) : Flags { + /** Managed address configuration: indicates addresses are available via DHCPv6. */ M(0x80), + /** Other configuration: indicates other configuration info is available via DHCPv6. */ O(0x40), } @@ -169,42 +185,73 @@ class RaPkt( } enum class PioFlags(override val value: Int) : Flags { + /** On-Link: indicates that this prefix can be used for on-link determination. */ L(0x80), + /** Autonomous address-configuration: indicates that this prefix can be used for SLAAC. */ A(0x40), + /** Router Address: obsolete. */ R(0x20), + /** PD Preferred: indicates that the network prefers the use of DHCPv6-PD over SLAAC. */ P(0x10), } + /** + * Add a Prefix Information Option + * + * @param prefix The prefix of an IPv6 address. + * @param validLft The time, in seconds, that the prefix is valid for on-link determination. + * @param preferredLft The time, in seconds, that SLAAC-generated addresses remain preferred. + * @param flags The Prefix Information Option flags. + */ fun addPioOption( prefix: IpPrefix, validLft: Int, preferredLft: Int, flags: EnumSet, - ) { + ): RaPkt { if (!prefix.isIPv6()) throw IllegalArgumentException("Invalid prefix") val pio = ByteBuffer.allocate(32) pio.put(3) // Type = 3 pio.put(4) // Length = 4 (*8) - pio.put(prefix.getPrefixLength().toByte()) // Prefix Length + pio.put(prefix.prefixLength.toByte()) // Prefix Length pio.put(flags.toByte()) // Flags pio.putInt(validLft) // Valid Lifetime pio.putInt(preferredLft) // Preferred Lifetime pio.putInt(0) // Reserved2 - pio.put(prefix.getRawAddress()) + pio.put(prefix.rawAddress) pio.flip() outputStream.write(pio.array()) + return this } + /** + * Add a Prefix Information Option + * + * @param prefix The IPv6 prefix as a String; e.g. {@code "2001:db8::/64"} + * @param validLft The time, in seconds, that the prefix is valid for on-link determination. + * @param preferredLft The time, in seconds, that SLAAC-generated addresses remain preferred. + * @param flags The PIO flags as a String; e.g. {@code "LA"} + */ fun addPioOption( prefix: String, validLft: Int = 2592000, preferredLft: Int = 604800, flags: String = "L", - ) { - addPioOption(IpPrefix(prefix), validLft, preferredLft, enumSetOfFlags(flags)) + ): RaPkt { + return addPioOption( + IpPrefix(prefix), + validLft, + preferredLft, + enumSetOfFlags(flags) + ) } - fun addRdnssOption(dns: List, lft: Int) { + /** Add a Recursive DNS Server Option + * + * @param dns The list of DNS servers. + * @param lft The time, in seconds, over which the DNS servers may be used for resolution. + */ + fun addRdnssOption(dns: List, lft: Int): RaPkt { val length = 1 + (dns.size * 2) val rdnss = ByteBuffer.allocate(length * 8) // length is in units of 8 octets. rdnss.put(25) // Type = 25 @@ -216,14 +263,25 @@ class RaPkt( } rdnss.flip() outputStream.write(rdnss.array()) + return this } - fun addRdnssOption(dns: String, lft: Int = 1800) { + /** Add a Recursive DNS Server Option + * + * @param dns The list of DNS servers as a String; e.g. {@code "2001:db8:1,2001:db8:2"} + * @param lft The time, in seconds, over which the DNS servers may be used for resolution. + */ + fun addRdnssOption(dns: String, lft: Int = 1800): RaPkt { val dnsServers = dns.split(",").map { InetAddress.getByName(it) as Inet6Address } - addRdnssOption(dnsServers, lft) + return addRdnssOption(dnsServers, lft) } - fun addRioOption(prefix: IpPrefix, lft: Int) { + /** Add a Route Information Option + * + * @param prefix The IPv6 prefix of the route. + * @param lft The lifetime of the route in seconds. + */ + fun addRioOption(prefix: IpPrefix, lft: Int): RaPkt { val rio = ByteBuffer.allocate(24) rio.put(24) // Type = 24 rio.put(3) // Length = 3 -- TODO: support variable prefix length @@ -234,13 +292,24 @@ class RaPkt( rio.put(prefix.rawAddress) rio.flip() outputStream.write(rio.array()) + return this } - fun addRioOption(prefix: String, lft: Int = 1800) { - addRioOption(IpPrefix(prefix), lft) + /** Add a Route Information Option + * + * @param prefix The IPv6 prefix of the route as a String; e.g. {@code "2001:db8::/48"} + * @param lft The lifetime of the route in seconds. + */ + fun addRioOption(prefix: String, lft: Int = 1800): RaPkt { + return addRioOption(IpPrefix(prefix), lft) } - fun addPref64Option(prefix: IpPrefix, lft: Int) { + /** Add a PREF64 Option + * + * @param prefix The PREF64 prefix. + * @param lft The lifetime of the PREF64 prefix in seconds. + */ + fun addPref64Option(prefix: IpPrefix, lft: Int): RaPkt { val pref64 = ByteBuffer.allocate(16) pref64.put(38) // Type = 38 pref64.put(2) // Length = 2 (*8) @@ -258,10 +327,16 @@ class RaPkt( pref64.put(prefix.rawAddress, 0 /*offset*/, 12 /*length*/) // highest 96 bits of prefix. pref64.flip() outputStream.write(pref64.array()) + return this } - fun addPref64Option(prefix: String, lft: Int = 1800) { - addPref64Option(IpPrefix(prefix), lft) + /** Add a PREF64 Option + * + * @param prefix The PREF64 prefix as a String; e.g. {@code "2001:db8::/64"} + * @param lft The lifetime of the PREF64 prefix in seconds. + */ + fun addPref64Option(prefix: String, lft: Int = 1800): RaPkt { + return addPref64Option(IpPrefix(prefix), lft) } override fun toByteArray() = outputStream.toByteArray() @@ -271,12 +346,12 @@ class RaPkt( class Ip6Pkt( private val src: Inet6Address, private val dst: Inet6Address, - private val payload: L4Packet, + private val data: L4Packet, ) : L3Packet { - constructor(src: String, dst: String, payload: L4Packet) : this( + constructor(src: String, dst: String, data: L4Packet) : this( InetAddress.getByName(src) as Inet6Address, InetAddress.getByName(dst) as Inet6Address, - payload, + data, ) override val etherType = 0x86dd.toShort() @@ -290,16 +365,16 @@ class Ip6Pkt( init { val ipv6Header = ByteBuffer.allocate(40) ipv6Header.putInt((6 shl 28) or (tc shl 20) or flowlabel) - ipv6Header.putShort(payload.size) - ipv6Header.put(payload.proto) + ipv6Header.putShort(data.size) + ipv6Header.put(data.proto) ipv6Header.put(hlim) - ipv6Header.put(src.getAddress()) - ipv6Header.put(dst.getAddress()) + ipv6Header.put(src.address) + ipv6Header.put(dst.address) ipv6Header.flip() val outputStream = ByteArrayOutputStream() outputStream.write(ipv6Header.array()) - outputStream.write(payload.toByteArray()) + outputStream.write(data.toByteArray()) bytes = outputStream.toByteArray() } @@ -315,18 +390,18 @@ class Ip6Pkt( * {@code * val ra = RaPkt(routerLft = 50, reachableTime = 100, flags = "O") * ra.addPioOption(prefix = "2001:db8::1/64", flags = "LA") - * val ipv6 = Ip6Pkt(src = "fe80::1", dst = "fe80::2", payload = ra) - * val ether = EtherPkt(src = "1:2:3:4:5:6", dst = "1:1:1:1:1:1", payload = ipv6) + * val ipv6 = Ip6Pkt(src = "fe80::1", dst = "fe80::2", data = ra) + * val ether = EtherPkt(src = "1:2:3:4:5:6", dst = "1:1:1:1:1:1", data = ipv6) * } * **/ class EtherPkt( dst: MacAddress, src: MacAddress, - payload: L3Packet, + data: L3Packet, ) : Packet { - constructor(dst: String, src: String, payload: L3Packet) : - this(MacAddress.fromString(dst), MacAddress.fromString(src), payload) + constructor(dst: String, src: String, data: L3Packet) : + this(MacAddress.fromString(dst), MacAddress.fromString(src), data) val bytes: ByteArray @@ -334,12 +409,12 @@ class EtherPkt( val ethernetHeader = ByteBuffer.allocate(14) ethernetHeader.put(dst.toByteArray()) ethernetHeader.put(src.toByteArray()) - ethernetHeader.putShort(payload.etherType) + ethernetHeader.putShort(data.etherType) ethernetHeader.flip() val outputStream = ByteArrayOutputStream() outputStream.write(ethernetHeader.array()) - outputStream.write(payload.toByteArray()) + outputStream.write(data.toByteArray()) bytes = outputStream.toByteArray() }