From acda32c35fc6a30ce11abfddb26ec5052de063f4 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Fri, 13 May 2016 17:50:25 +0900 Subject: [PATCH] DHCPv4: lease expiration is fatal, renew failures are not Bug: 24837343 Change-Id: Ib330864f8376b0907390d581b48cff5446b3392b --- .../android/net/StaticIpConfiguration.java | 2 +- .../net/java/android/net/dhcp/DhcpClient.java | 83 ++++++++++++++----- 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index 7f1b1791b5d33..58b1b88d89760 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -131,7 +131,7 @@ public class StaticIpConfiguration implements Parcelable { str.append(" ").append(dnsServer.getHostAddress()); } - str.append(" ] Domains"); + str.append(" ] Domains "); if (domains != null) str.append(domains); return str.toString(); } diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index db521e2d51791..505d15a061e94 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -135,6 +135,7 @@ public class DhcpClient extends StateMachine { private static final int CMD_RECEIVED_PACKET = PRIVATE_BASE + 2; private static final int CMD_TIMEOUT = PRIVATE_BASE + 3; private static final int CMD_RENEW_DHCP = PRIVATE_BASE + 4; + private static final int CMD_EXPIRE_DHCP = PRIVATE_BASE + 5; // For message logging. private static final Class[] sMessageClasses = { DhcpClient.class }; @@ -176,6 +177,7 @@ public class DhcpClient extends StateMachine { private final WakeupMessage mKickAlarm; private final WakeupMessage mTimeoutAlarm; private final WakeupMessage mRenewAlarm; + private final WakeupMessage mExpiryAlarm; private final String mIfaceName; private boolean mRegisteredForPreDhcpNotification; @@ -241,6 +243,7 @@ public class DhcpClient extends StateMachine { mTimeoutAlarm = makeWakeupMessage("TIMEOUT", CMD_TIMEOUT); // Used to schedule DHCP renews. mRenewAlarm = makeWakeupMessage("RENEW", CMD_RENEW_DHCP); + mExpiryAlarm = makeWakeupMessage("EXPIRY", CMD_EXPIRE_DHCP); } public void registerForPreDhcpNotification() { @@ -403,15 +406,21 @@ public class DhcpClient extends StateMachine { return transmitPacket(packet, description, to); } - private void scheduleRenew() { - if (mDhcpLeaseExpiry != 0) { - long now = SystemClock.elapsedRealtime(); - long alarmTime = (now + mDhcpLeaseExpiry) / 2; - mRenewAlarm.schedule(alarmTime); - Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s"); - } else { - Log.d(TAG, "Infinite lease, no renewal needed"); + private void scheduleLeaseTimers() { + if (mDhcpLeaseExpiry == 0) { + Log.d(TAG, "Infinite lease, no timer scheduling needed"); + return; } + + final long now = SystemClock.elapsedRealtime(); + long renewTime = (now + mDhcpLeaseExpiry) / 2; + mRenewAlarm.schedule(renewTime); + long secondsHence = (renewTime - now) / 1000; + Log.d(TAG, "Scheduling renewal in " + secondsHence + "s"); + + mExpiryAlarm.schedule(mDhcpLeaseExpiry); + secondsHence = (mDhcpLeaseExpiry - now) / 1000; + Log.d(TAG, "Scheduling expiry in " + secondsHence + "s"); } private void notifySuccess() { @@ -423,6 +432,13 @@ public class DhcpClient extends StateMachine { mController.sendMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0, null); } + private void acceptDhcpResults(DhcpResults results, String msg) { + mDhcpLease = results; + mOffer = null; + Log.d(TAG, msg + " lease: " + mDhcpLease); + notifySuccess(); + } + private void clearDhcpState() { mDhcpLease = null; mDhcpLeaseExpiry = 0; @@ -720,11 +736,8 @@ public class DhcpClient extends StateMachine { if ((packet instanceof DhcpAckPacket)) { DhcpResults results = packet.toDhcpResults(); if (results != null) { - mDhcpLease = results; - mOffer = null; - Log.d(TAG, "Confirmed lease: " + mDhcpLease); setDhcpLeaseExpiry(packet); - notifySuccess(); + acceptDhcpResults(results, "Confirmed"); transitionTo(mConfiguringInterfaceState); } } else if (packet instanceof DhcpNakPacket) { @@ -748,8 +761,23 @@ public class DhcpClient extends StateMachine { super.enter(); } + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case CMD_EXPIRE_DHCP: + Log.d(TAG, "Lease expired!"); + notifyFailure(); + transitionTo(mDhcpInitState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + @Override public void exit() { + mExpiryAlarm.cancel(); // Tell IpManager to clear the IPv4 address. There is no need to // wait for confirmation since any subsequent packets are sent from // INADDR_ANY anyway (DISCOVER, REQUEST). @@ -797,7 +825,7 @@ public class DhcpClient extends StateMachine { super.enter(); // TODO: DhcpStateMachine only supported renewing at 50% of the lease time, // and did not support rebinding. Now that the legacy DHCP client is gone, fix this. - scheduleRenew(); + scheduleLeaseTimers(); } @Override @@ -849,22 +877,31 @@ public class DhcpClient extends StateMachine { protected void receivePacket(DhcpPacket packet) { if (!isValidPacket(packet)) return; if ((packet instanceof DhcpAckPacket)) { - setDhcpLeaseExpiry(packet); - notifySuccess(); - transitionTo(mDhcpBoundState); + final DhcpResults results = packet.toDhcpResults(); + if (results != null) { + if (!mDhcpLease.ipAddress.equals(results.ipAddress)) { + Log.d(TAG, "Renewed lease not for our current IP address!"); + notifyFailure(); + transitionTo(mDhcpInitState); + } + setDhcpLeaseExpiry(packet); + // Updating our notion of DhcpResults here only causes the + // DNS servers and routes to be updated in LinkProperties + // in IpManager and by any overridden relevant handlers of + // the registered IpManager.Callback. IP address changes + // are not supported here. + acceptDhcpResults(results, "Renewed"); + transitionTo(mDhcpBoundState); + } } else if (packet instanceof DhcpNakPacket) { + Log.d(TAG, "Received NAK, returning to INIT"); + notifyFailure(); transitionTo(mDhcpInitState); } } - - @Override - protected void timeout() { - transitionTo(mDhcpInitState); - notifyFailure(); - } } - // Not implemented. DhcpStateMachine did not implement it either. + // Not implemented--yet. DhcpStateMachine did not implement it either. class DhcpRebindingState extends LoggingState { }