summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2015-06-02 07:47:46 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-06-02 07:47:48 +0000
commit8f602cdd38f7345eb0a8ec34ae4e51a333edce6c (patch)
tree9ea2de320f8b3981c13e55f7349e6574d0f1207d
parent168bfef182b8e631c93404f4e9e9c0176aa66ece (diff)
parentd973537ee1bd013b4233d3369d66821e124a2e65 (diff)
downloadframeworks_base-8f602cdd38f7345eb0a8ec34ae4e51a333edce6c.zip
frameworks_base-8f602cdd38f7345eb0a8ec34ae4e51a333edce6c.tar.gz
frameworks_base-8f602cdd38f7345eb0a8ec34ae4e51a333edce6c.tar.bz2
Merge "Fix DHCP lease time parsing." into mnc-dev
-rw-r--r--services/net/java/android/net/dhcp/DhcpClient.java28
-rw-r--r--services/net/java/android/net/dhcp/DhcpPacket.java22
-rw-r--r--services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java69
3 files changed, 103 insertions, 16 deletions
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 2692d71..b8c60ec 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -391,11 +391,15 @@ public class DhcpClient extends BaseDhcpStateMachine {
}
private void scheduleRenew() {
- long now = SystemClock.elapsedRealtime();
- long alarmTime = (now + mDhcpLeaseExpiry) / 2;
mAlarmManager.cancel(mRenewIntent);
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mRenewIntent);
- Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s");
+ if (mDhcpLeaseExpiry != 0) {
+ long now = SystemClock.elapsedRealtime();
+ long alarmTime = (now + mDhcpLeaseExpiry) / 2;
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mRenewIntent);
+ Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s");
+ } else {
+ Log.d(TAG, "Infinite lease, no renewal needed");
+ }
}
private void notifyLease() {
@@ -587,6 +591,12 @@ public class DhcpClient extends BaseDhcpStateMachine {
return true;
}
+ public void setDhcpLeaseExpiry(DhcpPacket packet) {
+ long leaseTimeMillis = packet.getLeaseTimeMillis();
+ mDhcpLeaseExpiry =
+ (leaseTimeMillis > 0) ? SystemClock.elapsedRealtime() + leaseTimeMillis : 0;
+ }
+
/**
* Retransmits packets using jittered exponential backoff with an optional timeout. Packet
* transmission is triggered by CMD_KICK, which is sent by an AlarmManager alarm.
@@ -724,10 +734,9 @@ public class DhcpClient extends BaseDhcpStateMachine {
DhcpResults results = packet.toDhcpResults();
if (results != null) {
mDhcpLease = results;
- Log.d(TAG, "Confirmed lease: " + mDhcpLease);
- mDhcpLeaseExpiry = SystemClock.elapsedRealtime() +
- mDhcpLease.leaseDuration * 1000;
mOffer = null;
+ Log.d(TAG, "Confirmed lease: " + mDhcpLease);
+ setDhcpLeaseExpiry(packet);
transitionTo(mDhcpBoundState);
}
} else if (packet instanceof DhcpNakPacket) {
@@ -799,10 +808,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
protected void receivePacket(DhcpPacket packet) {
if (!isValidPacket(packet)) return;
if ((packet instanceof DhcpAckPacket)) {
- DhcpResults results = packet.toDhcpResults();
- mDhcpLease.leaseDuration = results.leaseDuration;
- mDhcpLeaseExpiry = SystemClock.elapsedRealtime() +
- mDhcpLease.leaseDuration * 1000;
+ setDhcpLeaseExpiry(packet);
transitionTo(mDhcpBoundState);
} else if (packet instanceof DhcpNakPacket) {
transitionTo(mDhcpInitState);
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index b923b1b..2a25d30 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -28,6 +28,12 @@ import java.util.List;
abstract class DhcpPacket {
protected static final String TAG = "DhcpPacket";
+ // dhcpcd has a minimum lease of 20 seconds, but DhcpStateMachine would refuse to wake up the
+ // CPU for anything shorter than 5 minutes. For sanity's sake, this must be higher than the
+ // DHCP client timeout.
+ public static final int MINIMUM_LEASE = 60;
+ public static final int INFINITE_LEASE = (int) 0xffffffff;
+
public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY;
public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL;
public static final byte[] ETHER_BROADCAST = new byte[] {
@@ -1006,11 +1012,25 @@ abstract class DhcpPacket {
results.domains = mDomainName;
results.serverAddress = mServerIdentifier;
results.vendorInfo = mVendorId;
- results.leaseDuration = mLeaseTime;
+ results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
return results;
}
/**
+ * Returns the parsed lease time, in milliseconds, or 0 for infinite.
+ */
+ public long getLeaseTimeMillis() {
+ // dhcpcd treats the lack of a lease time option as an infinite lease.
+ if (mLeaseTime == null || mLeaseTime == INFINITE_LEASE) {
+ return 0;
+ } else if (0 <= mLeaseTime && mLeaseTime < MINIMUM_LEASE) {
+ return MINIMUM_LEASE * 1000;
+ } else {
+ return (mLeaseTime & 0xffffffffL) * 1000;
+ }
+ }
+
+ /**
* Builds a DHCP-DISCOVER packet from the required specified
* parameters.
*/
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index 4f7c7ec..f116042 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -17,6 +17,7 @@
package android.net.dhcp;
import android.net.NetworkUtils;
+import android.net.DhcpResults;
import android.system.OsConstants;
import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
@@ -38,14 +39,27 @@ public class DhcpPacketTest extends TestCase {
class TestDhcpPacket extends DhcpPacket {
private byte mType;
// TODO: Make this a map of option numbers to bytes instead.
- private byte[] mDomainBytes, mVendorInfoBytes;
+ private byte[] mDomainBytes, mVendorInfoBytes, mLeaseTimeBytes;
- public TestDhcpPacket(byte type, byte[] domainBytes, byte[] vendorInfoBytes) {
+ public TestDhcpPacket(byte type) {
super(0xdeadbeef, (short) 0, INADDR_ANY, CLIENT_ADDR, INADDR_ANY, INADDR_ANY,
CLIENT_MAC, true);
mType = type;
+ }
+
+ public TestDhcpPacket setDomainBytes(byte[] domainBytes) {
mDomainBytes = domainBytes;
+ return this;
+ }
+
+ public TestDhcpPacket setVendorInfoBytes(byte[] vendorInfoBytes) {
mVendorInfoBytes = vendorInfoBytes;
+ return this;
+ }
+
+ public TestDhcpPacket setLeaseTimeBytes(byte[] leaseTimeBytes) {
+ mLeaseTimeBytes = leaseTimeBytes;
+ return this;
}
public ByteBuffer buildPacket(int encap, short unusedDestUdp, short unusedSrcUdp) {
@@ -63,6 +77,9 @@ public class DhcpPacketTest extends TestCase {
if (mVendorInfoBytes != null) {
addTlv(buffer, DHCP_VENDOR_CLASS_ID, mVendorInfoBytes);
}
+ if (mLeaseTimeBytes != null) {
+ addTlv(buffer, DHCP_LEASE_TIME, mLeaseTimeBytes);
+ }
addTlvEnd(buffer);
}
@@ -78,8 +95,10 @@ public class DhcpPacketTest extends TestCase {
private void assertDomainAndVendorInfoParses(
String expectedDomain, byte[] domainBytes,
String expectedVendorInfo, byte[] vendorInfoBytes) {
- ByteBuffer packet = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER,
- domainBytes, vendorInfoBytes).build();
+ ByteBuffer packet = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER)
+ .setDomainBytes(domainBytes)
+ .setVendorInfoBytes(vendorInfoBytes)
+ .build();
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP);
assertEquals(expectedDomain, offerPacket.mDomainName);
assertEquals(expectedVendorInfo, offerPacket.mVendorId);
@@ -114,4 +133,46 @@ public class DhcpPacketTest extends TestCase {
assertDomainAndVendorInfoParses("goo.gl", trailingNullDomain,
"ANDROID_METERE\u0000", meteredTrailingNull);
}
+
+ private void assertLeaseTimeParses(boolean expectValid, Integer rawLeaseTime,
+ long leaseTimeMillis, byte[] leaseTimeBytes) {
+ TestDhcpPacket testPacket = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER);
+ if (leaseTimeBytes != null) {
+ testPacket.setLeaseTimeBytes(leaseTimeBytes);
+ }
+ ByteBuffer packet = testPacket.build();
+ DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP);
+ if (!expectValid) {
+ assertNull(offerPacket);
+ return;
+ }
+ assertEquals(rawLeaseTime, offerPacket.mLeaseTime);
+ DhcpResults dhcpResults = offerPacket.toDhcpResults(); // Just check this doesn't crash.
+ assertEquals(leaseTimeMillis, offerPacket.getLeaseTimeMillis());
+ }
+
+ @SmallTest
+ public void testLeaseTime() throws Exception {
+ byte[] noLease = null;
+ byte[] tooShortLease = new byte[] { 0x00, 0x00 };
+ byte[] tooLongLease = new byte[] { 0x00, 0x00, 0x00, 60, 0x01 };
+ byte[] zeroLease = new byte[] { 0x00, 0x00, 0x00, 0x00 };
+ byte[] tenSecondLease = new byte[] { 0x00, 0x00, 0x00, 10 };
+ byte[] oneMinuteLease = new byte[] { 0x00, 0x00, 0x00, 60 };
+ byte[] fiveMinuteLease = new byte[] { 0x00, 0x00, 0x01, 0x2c };
+ byte[] oneDayLease = new byte[] { 0x00, 0x01, 0x51, (byte) 0x80 };
+ byte[] maxIntPlusOneLease = new byte[] { (byte) 0x80, 0x00, 0x00, 0x01 };
+ byte[] infiniteLease = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
+
+ assertLeaseTimeParses(true, null, 0, noLease);
+ assertLeaseTimeParses(false, null, 0, tooShortLease);
+ assertLeaseTimeParses(false, null, 0, tooLongLease);
+ assertLeaseTimeParses(true, 0, 60 * 1000, zeroLease);
+ assertLeaseTimeParses(true, 10, 60 * 1000, tenSecondLease);
+ assertLeaseTimeParses(true, 60, 60 * 1000, oneMinuteLease);
+ assertLeaseTimeParses(true, 300, 300 * 1000, fiveMinuteLease);
+ assertLeaseTimeParses(true, 86400, 86400 * 1000, oneDayLease);
+ assertLeaseTimeParses(true, -2147483647, 2147483649L * 1000, maxIntPlusOneLease);
+ assertLeaseTimeParses(true, DhcpPacket.INFINITE_LEASE, 0, infiniteLease);
+ }
}