diff options
8 files changed, 186 insertions, 61 deletions
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java index 1a4119cbbb98..5accb452d10a 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java @@ -218,6 +218,7 @@ public class TetherInterfaceStateMachine extends StateMachine { .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS) .setDnsServers(addr) .setServerAddr(new LinkAddress(addr, prefixLen)) + .setMetered(true) .build(); // TODO: also advertise link MTU } catch (DhcpServingParams.InvalidParameterException e) { diff --git a/services/net/java/android/net/dhcp/DhcpAckPacket.java b/services/net/java/android/net/dhcp/DhcpAckPacket.java index df44b11fffa5..b2eb4e21b591 100644 --- a/services/net/java/android/net/dhcp/DhcpAckPacket.java +++ b/services/net/java/android/net/dhcp/DhcpAckPacket.java @@ -30,8 +30,8 @@ class DhcpAckPacket extends DhcpPacket { private final Inet4Address mSrcIp; DhcpAckPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress, - Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) { - super(transId, secs, clientIp, yourIp, serverAddress, INADDR_ANY, clientMac, broadcast); + Inet4Address relayIp, Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) { + super(transId, secs, clientIp, yourIp, serverAddress, relayIp, clientMac, broadcast); mBroadcast = broadcast; mSrcIp = serverAddress; } @@ -70,19 +70,8 @@ class DhcpAckPacket extends DhcpPacket { void finishPacket(ByteBuffer buffer) { addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_ACK); addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier); - addTlv(buffer, DHCP_LEASE_TIME, mLeaseTime); - // the client should renew at 1/2 the lease-expiry interval - if (mLeaseTime != null) { - addTlv(buffer, DHCP_RENEWAL_TIME, - Integer.valueOf(mLeaseTime.intValue() / 2)); - } - - addTlv(buffer, DHCP_SUBNET_MASK, mSubnetMask); - addTlv(buffer, DHCP_ROUTER, mGateways); - addTlv(buffer, DHCP_DOMAIN_NAME, mDomainName); - addTlv(buffer, DHCP_BROADCAST_ADDRESS, mBroadcastAddress); - addTlv(buffer, DHCP_DNS_SERVER, mDnsServers); + addCommonServerTlvs(buffer); addTlvEnd(buffer); } diff --git a/services/net/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java index ef9af527d063..1da0b7300559 100644 --- a/services/net/java/android/net/dhcp/DhcpNakPacket.java +++ b/services/net/java/android/net/dhcp/DhcpNakPacket.java @@ -26,9 +26,10 @@ class DhcpNakPacket extends DhcpPacket { /** * Generates a NAK packet with the specified parameters. */ - DhcpNakPacket(int transId, short secs, Inet4Address nextIp, Inet4Address relayIp, - byte[] clientMac, boolean broadcast) { - super(transId, secs, INADDR_ANY, INADDR_ANY, nextIp, relayIp, clientMac, broadcast); + DhcpNakPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac, + boolean broadcast) { + super(transId, secs, INADDR_ANY /* clientIp */, INADDR_ANY /* yourIp */, + INADDR_ANY /* nextIp */, relayIp, clientMac, broadcast); } public String toString() { diff --git a/services/net/java/android/net/dhcp/DhcpOfferPacket.java b/services/net/java/android/net/dhcp/DhcpOfferPacket.java index 99154ef0498c..0eba77e4a682 100644 --- a/services/net/java/android/net/dhcp/DhcpOfferPacket.java +++ b/services/net/java/android/net/dhcp/DhcpOfferPacket.java @@ -32,8 +32,8 @@ class DhcpOfferPacket extends DhcpPacket { * Generates a OFFER packet with the specified parameters. */ DhcpOfferPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress, - Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) { - super(transId, secs, clientIp, yourIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast); + Inet4Address relayIp, Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) { + super(transId, secs, clientIp, yourIp, serverAddress, relayIp, clientMac, broadcast); mSrcIp = serverAddress; } @@ -72,19 +72,8 @@ class DhcpOfferPacket extends DhcpPacket { void finishPacket(ByteBuffer buffer) { addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_OFFER); addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier); - addTlv(buffer, DHCP_LEASE_TIME, mLeaseTime); - // the client should renew at 1/2 the lease-expiry interval - if (mLeaseTime != null) { - addTlv(buffer, DHCP_RENEWAL_TIME, - Integer.valueOf(mLeaseTime.intValue() / 2)); - } - - addTlv(buffer, DHCP_SUBNET_MASK, mSubnetMask); - addTlv(buffer, DHCP_ROUTER, mGateways); - addTlv(buffer, DHCP_DOMAIN_NAME, mDomainName); - addTlv(buffer, DHCP_BROADCAST_ADDRESS, mBroadcastAddress); - addTlv(buffer, DHCP_DNS_SERVER, mDnsServers); + addCommonServerTlvs(buffer); addTlvEnd(buffer); } } diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index 175e27eb9467..595a12922a7e 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -184,6 +184,11 @@ public abstract class DhcpPacket { protected String mVendorInfo; /** + * Value of the vendor specific option used to indicate that the network is metered + */ + public static final String VENDOR_INFO_ANDROID_METERED = "ANDROID_METERED"; + + /** * DHCP Optional Type: DHCP Requested IP Address */ protected static final byte DHCP_REQUESTED_IP = 50; @@ -677,6 +682,23 @@ public abstract class DhcpPacket { if (!TextUtils.isEmpty(hn)) addTlv(buf, DHCP_HOST_NAME, hn); } + protected void addCommonServerTlvs(ByteBuffer buf) { + addTlv(buf, DHCP_LEASE_TIME, mLeaseTime); + if (mLeaseTime != null && mLeaseTime != INFINITE_LEASE) { + // The client should renew at 1/2 the lease-expiry interval + addTlv(buf, DHCP_RENEWAL_TIME, (int) (Integer.toUnsignedLong(mLeaseTime) / 2)); + // Default rebinding time is set as below by RFC2131 + addTlv(buf, DHCP_REBINDING_TIME, + (int) (Integer.toUnsignedLong(mLeaseTime) * 875L / 1000L)); + } + addTlv(buf, DHCP_SUBNET_MASK, mSubnetMask); + addTlv(buf, DHCP_BROADCAST_ADDRESS, mBroadcastAddress); + addTlv(buf, DHCP_ROUTER, mGateways); + addTlv(buf, DHCP_DNS_SERVER, mDnsServers); + addTlv(buf, DHCP_DOMAIN_NAME, mDomainName); + addTlv(buf, DHCP_VENDOR_INFO, mVendorInfo); + } + /** * Converts a MAC from an array of octets to an ASCII string. */ @@ -1085,7 +1107,7 @@ public abstract class DhcpPacket { break; case DHCP_MESSAGE_TYPE_OFFER: newPacket = new DhcpOfferPacket( - transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac); + transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac); break; case DHCP_MESSAGE_TYPE_REQUEST: newPacket = new DhcpRequestPacket( @@ -1098,11 +1120,11 @@ public abstract class DhcpPacket { break; case DHCP_MESSAGE_TYPE_ACK: newPacket = new DhcpAckPacket( - transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac); + transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac); break; case DHCP_MESSAGE_TYPE_NAK: newPacket = new DhcpNakPacket( - transactionId, secs, nextIp, relayIp, clientMac, broadcast); + transactionId, secs, relayIp, clientMac, broadcast); break; case DHCP_MESSAGE_TYPE_RELEASE: if (serverIdentifier == null) { @@ -1234,12 +1256,13 @@ public abstract class DhcpPacket { * parameters. */ public static ByteBuffer buildOfferPacket(int encap, int transactionId, - boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, - byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, - List<Inet4Address> gateways, List<Inet4Address> dnsServers, - Inet4Address dhcpServerIdentifier, String domainName) { + boolean broadcast, Inet4Address serverIpAddr, Inet4Address relayIp, + Inet4Address yourIp, byte[] mac, Integer timeout, Inet4Address netMask, + Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers, + Inet4Address dhcpServerIdentifier, String domainName, boolean metered) { DhcpPacket pkt = new DhcpOfferPacket( - transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac); + transactionId, (short) 0, broadcast, serverIpAddr, relayIp, + INADDR_ANY /* clientIp */, yourIp, mac); pkt.mGateways = gateways; pkt.mDnsServers = dnsServers; pkt.mLeaseTime = timeout; @@ -1247,6 +1270,9 @@ public abstract class DhcpPacket { pkt.mServerIdentifier = dhcpServerIdentifier; pkt.mSubnetMask = netMask; pkt.mBroadcastAddress = bcAddr; + if (metered) { + pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED; + } return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); } @@ -1254,12 +1280,13 @@ public abstract class DhcpPacket { * Builds a DHCP-ACK packet from the required specified parameters. */ public static ByteBuffer buildAckPacket(int encap, int transactionId, - boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, + boolean broadcast, Inet4Address serverIpAddr, Inet4Address relayIp, Inet4Address yourIp, byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers, - Inet4Address dhcpServerIdentifier, String domainName) { + Inet4Address dhcpServerIdentifier, String domainName, boolean metered) { DhcpPacket pkt = new DhcpAckPacket( - transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac); + transactionId, (short) 0, broadcast, serverIpAddr, relayIp, + INADDR_ANY /* clientIp */, yourIp, mac); pkt.mGateways = gateways; pkt.mDnsServers = dnsServers; pkt.mLeaseTime = timeout; @@ -1267,6 +1294,9 @@ public abstract class DhcpPacket { pkt.mSubnetMask = netMask; pkt.mServerIdentifier = dhcpServerIdentifier; pkt.mBroadcastAddress = bcAddr; + if (metered) { + pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED; + } return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); } @@ -1274,10 +1304,11 @@ public abstract class DhcpPacket { * Builds a DHCP-NAK packet from the required specified parameters. */ public static ByteBuffer buildNakPacket(int encap, int transactionId, Inet4Address serverIpAddr, - byte[] mac, boolean broadcast, String message) { + Inet4Address relayIp, byte[] mac, boolean broadcast, String message) { DhcpPacket pkt = new DhcpNakPacket( - transactionId, (short) 0, serverIpAddr, serverIpAddr, mac, broadcast); + transactionId, (short) 0, relayIp, mac, broadcast); pkt.mMessage = message; + pkt.mServerIdentifier = serverIpAddr; return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); } diff --git a/services/net/java/android/net/dhcp/DhcpServer.java b/services/net/java/android/net/dhcp/DhcpServer.java index 095a5eb72289..da8c8bbcf057 100644 --- a/services/net/java/android/net/dhcp/DhcpServer.java +++ b/services/net/java/android/net/dhcp/DhcpServer.java @@ -351,12 +351,10 @@ public class DhcpServer { mServingParams.getServerInet4Addr(), mServingParams.serverAddr.getPrefixLength()); final ByteBuffer offerPacket = DhcpPacket.buildOfferPacket( ENCAP_BOOTP, request.mTransId, broadcastFlag, mServingParams.getServerInet4Addr(), - lease.getNetAddr(), request.mClientMac, timeout, - prefixMask, - broadcastAddr, - new ArrayList<>(mServingParams.defaultRouters), + request.mRelayIp, lease.getNetAddr(), request.mClientMac, timeout, prefixMask, + broadcastAddr, new ArrayList<>(mServingParams.defaultRouters), new ArrayList<>(mServingParams.dnsServers), - mServingParams.getServerInet4Addr(), null /* domainName */); + mServingParams.getServerInet4Addr(), null /* domainName */, mServingParams.metered); return transmitOfferOrAckPacket(offerPacket, request, lease, clientMac, broadcastFlag); } @@ -368,12 +366,12 @@ public class DhcpServer { final boolean broadcastFlag = getBroadcastFlag(request, lease); final int timeout = getLeaseTimeout(lease); final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, request.mTransId, - broadcastFlag, mServingParams.getServerInet4Addr(), lease.getNetAddr(), - request.mClientMac, timeout, mServingParams.getPrefixMaskAsAddress(), - mServingParams.getBroadcastAddress(), + broadcastFlag, mServingParams.getServerInet4Addr(), request.mRelayIp, + lease.getNetAddr(), request.mClientMac, timeout, + mServingParams.getPrefixMaskAsAddress(), mServingParams.getBroadcastAddress(), new ArrayList<>(mServingParams.defaultRouters), new ArrayList<>(mServingParams.dnsServers), - mServingParams.getServerInet4Addr(), null /* domainName */); + mServingParams.getServerInet4Addr(), null /* domainName */, mServingParams.metered); return transmitOfferOrAckPacket(ackPacket, request, lease, clientMac, broadcastFlag); } @@ -383,7 +381,7 @@ public class DhcpServer { // Always set broadcast flag for NAK: client may not have a correct IP final ByteBuffer nakPacket = DhcpPacket.buildNakPacket( ENCAP_BOOTP, request.mTransId, mServingParams.getServerInet4Addr(), - request.mClientMac, true /* broadcast */, message); + request.mRelayIp, request.mClientMac, true /* broadcast */, message); final Inet4Address dst = isEmpty(request.mRelayIp) ? (Inet4Address) Inet4Address.ALL diff --git a/services/net/java/android/net/dhcp/DhcpServingParams.java b/services/net/java/android/net/dhcp/DhcpServingParams.java index 6d58bc63a5f2..df15ba1c5507 100644 --- a/services/net/java/android/net/dhcp/DhcpServingParams.java +++ b/services/net/java/android/net/dhcp/DhcpServingParams.java @@ -76,6 +76,11 @@ public class DhcpServingParams { public final int linkMtu; /** + * Indicates whether the DHCP server should send the ANDROID_METERED vendor-specific option. + */ + public final boolean metered; + + /** * Checked exception thrown when some parameters used to build {@link DhcpServingParams} are * missing or invalid. */ @@ -88,13 +93,14 @@ public class DhcpServingParams { private DhcpServingParams(@NonNull LinkAddress serverAddr, @NonNull Set<Inet4Address> defaultRouters, @NonNull Set<Inet4Address> dnsServers, @NonNull Set<Inet4Address> excludedAddrs, - long dhcpLeaseTimeSecs, int linkMtu) { + long dhcpLeaseTimeSecs, int linkMtu, boolean metered) { this.serverAddr = serverAddr; this.defaultRouters = defaultRouters; this.dnsServers = dnsServers; this.excludedAddrs = excludedAddrs; this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs; this.linkMtu = linkMtu; + this.metered = metered; } @NonNull @@ -134,6 +140,7 @@ public class DhcpServingParams { private Set<Inet4Address> excludedAddrs; private long dhcpLeaseTimeSecs; private int linkMtu = MTU_UNSET; + private boolean metered; /** * Set the server address and served prefix for the DHCP server. @@ -248,6 +255,16 @@ public class DhcpServingParams { } /** + * Set whether the DHCP server should send the ANDROID_METERED vendor-specific option. + * + * <p>If not set, the default value is false. + */ + public Builder setMetered(boolean metered) { + this.metered = metered; + return this; + } + + /** * Create a new {@link DhcpServingParams} instance based on parameters set in the builder. * * <p>This method has no side-effects. If it does not throw, a valid @@ -301,7 +318,7 @@ public class DhcpServingParams { Collections.unmodifiableSet(new HashSet<>(defaultRouters)), Collections.unmodifiableSet(new HashSet<>(dnsServers)), Collections.unmodifiableSet(excl), - dhcpLeaseTimeSecs, linkMtu); + dhcpLeaseTimeSecs, linkMtu, metered); } } diff --git a/tests/net/java/android/net/dhcp/DhcpPacketTest.java b/tests/net/java/android/net/dhcp/DhcpPacketTest.java index 050183c1ac1f..312b3d1878d6 100644 --- a/tests/net/java/android/net/dhcp/DhcpPacketTest.java +++ b/tests/net/java/android/net/dhcp/DhcpPacketTest.java @@ -16,6 +16,8 @@ package android.net.dhcp; +import static android.net.NetworkUtils.getBroadcastAddress; +import static android.net.NetworkUtils.getPrefixMaskAsInet4Address; import static android.net.dhcp.DhcpPacket.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -29,14 +31,15 @@ import android.net.NetworkUtils; import android.net.metrics.DhcpErrorEvent; import android.support.test.runner.AndroidJUnit4; import android.support.test.filters.SmallTest; -import android.system.OsConstants; import com.android.internal.util.HexDump; +import java.io.ByteArrayOutputStream; import java.net.Inet4Address; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Random; import org.junit.Before; @@ -47,13 +50,17 @@ import org.junit.runner.RunWith; @SmallTest public class DhcpPacketTest { - private static Inet4Address SERVER_ADDR = v4Address("192.0.2.1"); - private static Inet4Address CLIENT_ADDR = v4Address("192.0.2.234"); + private static final Inet4Address SERVER_ADDR = v4Address("192.0.2.1"); + private static final Inet4Address CLIENT_ADDR = v4Address("192.0.2.234"); + private static final int PREFIX_LENGTH = 22; + private static final Inet4Address NETMASK = getPrefixMaskAsInet4Address(PREFIX_LENGTH); + private static final Inet4Address BROADCAST_ADDR = getBroadcastAddress( + SERVER_ADDR, PREFIX_LENGTH); // Use our own empty address instead of Inet4Address.ANY or INADDR_ANY to ensure that the code // doesn't use == instead of equals when comparing addresses. - private static Inet4Address ANY = (Inet4Address) v4Address("0.0.0.0"); + private static final Inet4Address ANY = (Inet4Address) v4Address("0.0.0.0"); - private static byte[] CLIENT_MAC = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; + private static final byte[] CLIENT_MAC = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; private static final Inet4Address v4Address(String addrString) throws IllegalArgumentException { return (Inet4Address) NetworkUtils.numericToInetAddress(addrString); @@ -952,4 +959,96 @@ public class DhcpPacketTest { "\nActual:\n " + Arrays.toString(actual); assertTrue(msg, Arrays.equals(expected, actual)); } + + public void checkBuildOfferPacket(int leaseTimeSecs) throws Exception { + final int renewalTime = (int) (Integer.toUnsignedLong(leaseTimeSecs) / 2); + final int rebindingTime = (int) (Integer.toUnsignedLong(leaseTimeSecs) * 875 / 1000); + final int transactionId = 0xdeadbeef; + + final ByteBuffer packet = DhcpPacket.buildOfferPacket( + DhcpPacket.ENCAP_BOOTP, transactionId, false /* broadcast */, + SERVER_ADDR, INADDR_ANY /* relayIp */, CLIENT_ADDR /* yourIp */, + CLIENT_MAC, leaseTimeSecs, NETMASK /* netMask */, + BROADCAST_ADDR /* bcAddr */, Collections.singletonList(SERVER_ADDR) /* gateways */, + Collections.singletonList(SERVER_ADDR) /* dnsServers */, + SERVER_ADDR /* dhcpServerIdentifier */, null /* domainName */, false /* metered */); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + // BOOTP headers + bos.write(new byte[] { + (byte) 0x02, (byte) 0x01, (byte) 0x06, (byte) 0x00, + (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + // ciaddr + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + }); + // yiaddr + bos.write(CLIENT_ADDR.getAddress()); + // siaddr + bos.write(SERVER_ADDR.getAddress()); + // giaddr + bos.write(INADDR_ANY.getAddress()); + // chaddr + bos.write(CLIENT_MAC); + + // Padding + bos.write(new byte[202]); + + // Options + bos.write(new byte[]{ + // Magic cookie 0x63825363. + (byte) 0x63, (byte) 0x82, (byte) 0x53, (byte) 0x63, + // Message type OFFER. + (byte) 0x35, (byte) 0x01, (byte) 0x02, + }); + // Server ID + bos.write(new byte[] { (byte) 0x36, (byte) 0x04 }); + bos.write(SERVER_ADDR.getAddress()); + // Lease time + bos.write(new byte[] { (byte) 0x33, (byte) 0x04 }); + bos.write(intToByteArray(leaseTimeSecs)); + if (leaseTimeSecs != INFINITE_LEASE) { + // Renewal time + bos.write(new byte[]{(byte) 0x3a, (byte) 0x04}); + bos.write(intToByteArray(renewalTime)); + // Rebinding time + bos.write(new byte[]{(byte) 0x3b, (byte) 0x04}); + bos.write(intToByteArray(rebindingTime)); + } + // Subnet mask + bos.write(new byte[] { (byte) 0x01, (byte) 0x04 }); + bos.write(NETMASK.getAddress()); + // Broadcast address + bos.write(new byte[] { (byte) 0x1c, (byte) 0x04 }); + bos.write(BROADCAST_ADDR.getAddress()); + // Router + bos.write(new byte[] { (byte) 0x03, (byte) 0x04 }); + bos.write(SERVER_ADDR.getAddress()); + // Nameserver + bos.write(new byte[] { (byte) 0x06, (byte) 0x04 }); + bos.write(SERVER_ADDR.getAddress()); + // End options. + bos.write(0xff); + + final byte[] expected = bos.toByteArray(); + assertTrue((expected.length & 1) == 0); + + final byte[] actual = new byte[packet.limit()]; + packet.get(actual); + final String msg = "Expected:\n " + HexDump.dumpHexString(expected) + + "\nActual:\n " + HexDump.dumpHexString(actual); + assertTrue(msg, Arrays.equals(expected, actual)); + } + + @Test + public void testOfferPacket() throws Exception { + checkBuildOfferPacket(3600); + checkBuildOfferPacket(Integer.MAX_VALUE); + checkBuildOfferPacket(0x80000000); + checkBuildOfferPacket(INFINITE_LEASE); + } + + private static byte[] intToByteArray(int val) { + return ByteBuffer.allocate(4).putInt(val).array(); + } } |