diff options
3 files changed, 61 insertions, 12 deletions
diff --git a/common/netlinkclient/src/android/net/netlink/NdOption.java b/common/netlinkclient/src/android/net/netlink/NdOption.java index db262b9..ab9d2e6 100644 --- a/common/netlinkclient/src/android/net/netlink/NdOption.java +++ b/common/netlinkclient/src/android/net/netlink/NdOption.java @@ -30,7 +30,7 @@ public class NdOption { public final int length; /** Constructs a new NdOption. */ - public NdOption(byte type, int length) { + NdOption(byte type, int length) { this.type = type; this.length = length; } @@ -69,6 +69,11 @@ public class NdOption { } } + void writeToByteBuffer(ByteBuffer buf) { + buf.put(type); + buf.put((byte) length); + } + @Override public String toString() { return String.format("NdOption(%d, %d)", Byte.toUnsignedInt(type), length); diff --git a/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java b/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java index 653d9a1..61a8f3b 100644 --- a/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java +++ b/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java @@ -21,9 +21,11 @@ import android.util.Log; import androidx.annotation.NonNull; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; +import java.util.Objects; /** * The PREF64 router advertisement option. RFC 8781. @@ -89,7 +91,23 @@ public class StructNdOptPref64 extends NdOption { return (short) ((lifetime & 0xfff8) | (prefixLengthCode & 0x7)); } - public StructNdOptPref64(@NonNull ByteBuffer buf) { + public StructNdOptPref64(@NonNull IpPrefix prefix, int lifetime) { + super((byte) TYPE, LENGTH); + + Objects.requireNonNull(prefix, "prefix must not be null"); + if (!(prefix.getAddress() instanceof Inet6Address)) { + throw new IllegalArgumentException("Must be an IPv6 prefix: " + prefix); + } + prefixLengthToPlc(prefix.getPrefixLength()); // Throw if the prefix length is invalid. + this.prefix = prefix; + + if (lifetime < 0 || lifetime > 0xfff8) { + throw new IllegalArgumentException("Invalid lifetime " + lifetime); + } + this.lifetime = lifetime & 0xfff8; + } + + private StructNdOptPref64(@NonNull ByteBuffer buf) { super(buf.get(), Byte.toUnsignedInt(buf.get())); if (type != TYPE) throw new IllegalArgumentException("Invalid type " + type); if (length != LENGTH) throw new IllegalArgumentException("Invalid length " + length); @@ -129,13 +147,16 @@ public class StructNdOptPref64 extends NdOption { } } + protected void writeToByteBuffer(ByteBuffer buf) { + super.writeToByteBuffer(buf); + buf.putShort(getScaledLifetimePlc(lifetime, prefixLengthToPlc(prefix.getPrefixLength()))); + buf.put(prefix.getRawAddress(), 0, 12); + } + /** Outputs the wire format of the option to a new big-endian ByteBuffer. */ public ByteBuffer toByteBuffer() { ByteBuffer buf = ByteBuffer.allocate(STRUCT_SIZE); - buf.put(type); - buf.put((byte) length); - buf.putShort(getScaledLifetimePlc(lifetime, prefixLengthToPlc(prefix.getPrefixLength()))); - buf.put(prefix.getRawAddress(), 0, 12); + writeToByteBuffer(buf); buf.flip(); return buf; } diff --git a/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java b/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java index 550c6dd..fef103b 100644 --- a/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java +++ b/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java @@ -20,9 +20,10 @@ import static android.net.netlink.StructNdOptPref64.getScaledLifetimePlc; import static android.net.netlink.StructNdOptPref64.plcToPrefixLength; import static android.net.netlink.StructNdOptPref64.prefixLengthToPlc; +import static com.android.testutils.MiscAssertsKt.assertThrows; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; import android.net.IpPrefix; @@ -159,14 +160,11 @@ public class StructNdOptPref64Test { } private void assertInvalidPlc(int plc) { - try { - plcToPrefixLength(plc); - fail("Invalid plc " + plc + " should have thrown exception"); - } catch (IllegalArgumentException expected) { } + assertThrows(IllegalArgumentException.class, () -> plcToPrefixLength(plc)); } @Test - public void testPrefixLengthPlc() { + public void testPrefixLengthToPlc() { for (int i = 0; i < 6; i++) { assertEquals(i, prefixLengthToPlc(plcToPrefixLength(i))); } @@ -175,4 +173,29 @@ public class StructNdOptPref64Test { assertInvalidPlc(7); assertEquals(0, prefixLengthToPlc(96)); } + + + private void assertInvalidParameters(IpPrefix prefix, int lifetime) { + assertThrows(IllegalArgumentException.class, () -> new StructNdOptPref64(prefix, lifetime)); + } + + @Test + public void testToByteBuffer() throws Exception { + final IpPrefix prefix1 = prefix(PREFIX1, 56); + final IpPrefix prefix2 = prefix(PREFIX2, 96); + + StructNdOptPref64 opt = new StructNdOptPref64(prefix1, 600); + assertToByteBufferMatches(opt, "2602025a0064ff9b0000000000000000"); + assertEquals(new IpPrefix("64:ff9b::/56"), opt.prefix); + assertEquals(600, opt.lifetime); + + opt = new StructNdOptPref64(prefix2, 65519); + assertToByteBufferMatches(opt, "2602ffe820010db80001000200030064"); + assertEquals(new IpPrefix("2001:db8:1:2:3:64::/96"), opt.prefix); + assertEquals(65512, opt.lifetime); + + assertInvalidParameters(prefix1, 65535); + assertInvalidParameters(prefix2, -1); + assertInvalidParameters(prefix("1.2.3.4", 32), 600); + } } |