summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorXiao Ma <xiaom@google.com>2020-05-25 09:08:46 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-05-25 09:08:46 +0000
commitb664b89668e26eff904a5d52eed7e98b2355f2e6 (patch)
tree0dcbc2e1cdec1ac99637f588508ec22c780de6f7 /src
parent4376550b5b3247327012aa28e60b53254aed255f (diff)
parente86b4150de8265ff6e8b1c5f977565ad0309e5c3 (diff)
Merge "Support MirrorLink DHCPDECLINE." into rvc-dev
Diffstat (limited to 'src')
-rw-r--r--src/android/net/dhcp/DhcpLeaseRepository.java22
-rw-r--r--src/android/net/dhcp/DhcpServer.java241
2 files changed, 178 insertions, 85 deletions
diff --git a/src/android/net/dhcp/DhcpLeaseRepository.java b/src/android/net/dhcp/DhcpLeaseRepository.java
index 3639a2d..b7a2572 100644
--- a/src/android/net/dhcp/DhcpLeaseRepository.java
+++ b/src/android/net/dhcp/DhcpLeaseRepository.java
@@ -37,6 +37,7 @@ import android.util.ArrayMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import java.net.Inet4Address;
import java.util.ArrayList;
@@ -158,7 +159,7 @@ class DhcpLeaseRepository {
/**
* From a map keyed by {@link Inet4Address}, remove entries where the key is invalid (as
* specified by {@link #isValidAddress(Inet4Address)}), or is a reserved address.
- * @return true iff at least one entry was removed.
+ * @return true if and only if at least one entry was removed.
*/
private <T> boolean cleanMap(Map<Inet4Address, T> map) {
final Iterator<Entry<Inet4Address, T>> it = map.entrySet().iterator();
@@ -397,7 +398,8 @@ class DhcpLeaseRepository {
mEventCallbacks.finishBroadcast();
}
- public void markLeaseDeclined(@NonNull Inet4Address addr) {
+ @VisibleForTesting
+ void markLeaseDeclined(@NonNull Inet4Address addr) {
if (mDeclinedAddrs.containsKey(addr) || !isValidAddress(addr)) {
mLog.logf("Not marking %s as declined: already declined or not assignable",
inet4AddrToString(addr));
@@ -410,6 +412,22 @@ class DhcpLeaseRepository {
}
/**
+ * Mark a committed lease matching the passed in clientId and hardware address parameters to be
+ * declined, and delete it from the repository.
+ *
+ * @param clientId Client identifier option if specified, or {@link #CLIENTID_UNSPEC}
+ * @param hwAddr client's mac address
+ * @param Addr IPv4 address to be declined
+ * @return true if a lease matching parameters was removed from committed repository.
+ */
+ public boolean markAndReleaseDeclinedLease(@Nullable byte[] clientId,
+ @NonNull MacAddress hwAddr, @NonNull Inet4Address addr) {
+ if (!releaseLease(clientId, hwAddr, addr)) return false;
+ markLeaseDeclined(addr);
+ return true;
+ }
+
+ /**
* Get the list of currently valid committed leases in the repository.
*/
@NonNull
diff --git a/src/android/net/dhcp/DhcpServer.java b/src/android/net/dhcp/DhcpServer.java
index 212e609..55b1f28 100644
--- a/src/android/net/dhcp/DhcpServer.java
+++ b/src/android/net/dhcp/DhcpServer.java
@@ -45,6 +45,7 @@ import static java.lang.Integer.toUnsignedLong;
import android.content.Context;
import android.net.INetworkStackStatusCallback;
+import android.net.IpPrefix;
import android.net.MacAddress;
import android.net.TrafficStats;
import android.net.util.NetworkStackUtils;
@@ -96,7 +97,8 @@ public class DhcpServer extends StateMachine {
private static final int CMD_START_DHCP_SERVER = 1;
private static final int CMD_STOP_DHCP_SERVER = 2;
private static final int CMD_UPDATE_PARAMS = 3;
- private static final int CMD_SUSPEND_DHCP_SERVER = 4;
+ @VisibleForTesting
+ protected static final int CMD_RECEIVE_PACKET = 4;
@NonNull
private final Context mContext;
@@ -126,6 +128,8 @@ public class DhcpServer extends StateMachine {
private final StoppedState mStoppedState = new StoppedState();
private final StartedState mStartedState = new StartedState();
private final RunningState mRunningState = new RunningState();
+ private final WaitBeforeRetrievalState mWaitBeforeRetrievalState =
+ new WaitBeforeRetrievalState();
/**
* Clock to be used by DhcpServer to track time for lease expiration.
@@ -262,6 +266,7 @@ public class DhcpServer extends StateMachine {
addState(mStoppedState);
addState(mStartedState);
addState(mRunningState, mStartedState);
+ addState(mWaitBeforeRetrievalState, mStartedState);
// CHECKSTYLE:ON IndentationCheck
setInitialState(mStoppedState);
@@ -372,6 +377,17 @@ public class DhcpServer extends StateMachine {
}
}
+ private void handleUpdateServingParams(@NonNull DhcpServingParams params,
+ @Nullable INetworkStackStatusCallback cb) {
+ mServingParams = params;
+ mLeaseRepo.updateParams(
+ DhcpServingParams.makeIpPrefix(params.serverAddr),
+ params.excludedAddrs,
+ params.dhcpLeaseTimeSecs * 1000,
+ params.singleClientAddr);
+ maybeNotifyStatus(cb, STATUS_SUCCESS);
+ }
+
class StoppedState extends State {
private INetworkStackStatusCallback mOnStopCallback;
@@ -422,6 +438,8 @@ public class DhcpServer extends StateMachine {
mLeaseRepo.addLeaseCallbacks(mEventCallbacks);
}
maybeNotifyStatus(mOnStartCallback, STATUS_SUCCESS);
+ // Clear INetworkStackStatusCallback binder token, so that it's freed
+ // on the other side.
mOnStartCallback = null;
}
@@ -431,14 +449,7 @@ public class DhcpServer extends StateMachine {
case CMD_UPDATE_PARAMS:
final Pair<DhcpServingParams, INetworkStackStatusCallback> pair =
(Pair<DhcpServingParams, INetworkStackStatusCallback>) msg.obj;
- final DhcpServingParams params = pair.first;
- mServingParams = params;
- mLeaseRepo.updateParams(
- DhcpServingParams.makeIpPrefix(params.serverAddr),
- params.excludedAddrs,
- params.dhcpLeaseTimeSecs * 1000,
- params.singleClientAddr);
- maybeNotifyStatus(pair.second, STATUS_SUCCESS);
+ handleUpdateServingParams(pair.first, pair.second);
return HANDLED;
case CMD_START_DHCP_SERVER:
@@ -466,100 +477,158 @@ public class DhcpServer extends StateMachine {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
- case CMD_SUSPEND_DHCP_SERVER:
- // TODO: transition to the state which waits for IpServer to reconfigure the
- // new selected prefix.
+ case CMD_RECEIVE_PACKET:
+ processPacket((DhcpPacket) msg.obj);
return HANDLED;
+
default:
// Fall through to StartedState.
return NOT_HANDLED;
}
}
- }
- @VisibleForTesting
- void processPacket(@NonNull DhcpPacket packet, int srcPort) {
- final String packetType = packet.getClass().getSimpleName();
- if (srcPort != DHCP_CLIENT) {
- mLog.logf("Ignored packet of type %s sent from client port %d", packetType, srcPort);
- return;
- }
+ private void processPacket(@NonNull DhcpPacket packet) {
+ mLog.log("Received packet of type " + packet.getClass().getSimpleName());
- mLog.log("Received packet of type " + packetType);
- final Inet4Address sid = packet.mServerIdentifier;
- if (sid != null && !sid.equals(mServingParams.serverAddr.getAddress())) {
- mLog.log("Packet ignored due to wrong server identifier: " + sid);
- return;
- }
+ final Inet4Address sid = packet.mServerIdentifier;
+ if (sid != null && !sid.equals(mServingParams.serverAddr.getAddress())) {
+ mLog.log("Packet ignored due to wrong server identifier: " + sid);
+ return;
+ }
- try {
- if (packet instanceof DhcpDiscoverPacket) {
- processDiscover((DhcpDiscoverPacket) packet);
- } else if (packet instanceof DhcpRequestPacket) {
- processRequest((DhcpRequestPacket) packet);
- } else if (packet instanceof DhcpReleasePacket) {
- processRelease((DhcpReleasePacket) packet);
- } else {
- mLog.e("Unknown packet type: " + packet.getClass().getSimpleName());
+ try {
+ if (packet instanceof DhcpDiscoverPacket) {
+ processDiscover((DhcpDiscoverPacket) packet);
+ } else if (packet instanceof DhcpRequestPacket) {
+ processRequest((DhcpRequestPacket) packet);
+ } else if (packet instanceof DhcpReleasePacket) {
+ processRelease((DhcpReleasePacket) packet);
+ } else if (packet instanceof DhcpDeclinePacket) {
+ processDecline((DhcpDeclinePacket) packet);
+ } else {
+ mLog.e("Unknown packet type: " + packet.getClass().getSimpleName());
+ }
+ } catch (MalformedPacketException e) {
+ // Not an internal error: only logging exception message, not stacktrace
+ mLog.e("Ignored malformed packet: " + e.getMessage());
}
- } catch (MalformedPacketException e) {
+ }
+
+ private void logIgnoredPacketInvalidSubnet(DhcpLeaseRepository.InvalidSubnetException e) {
// Not an internal error: only logging exception message, not stacktrace
- mLog.e("Ignored malformed packet: " + e.getMessage());
+ mLog.e("Ignored packet from invalid subnet: " + e.getMessage());
}
- }
- private void logIgnoredPacketInvalidSubnet(DhcpLeaseRepository.InvalidSubnetException e) {
- // Not an internal error: only logging exception message, not stacktrace
- mLog.e("Ignored packet from invalid subnet: " + e.getMessage());
- }
+ private void processDiscover(@NonNull DhcpDiscoverPacket packet)
+ throws MalformedPacketException {
+ final DhcpLease lease;
+ final MacAddress clientMac = getMacAddr(packet);
+ try {
+ if (mDhcpRapidCommitEnabled && packet.mRapidCommit) {
+ lease = mLeaseRepo.getCommittedLease(packet.getExplicitClientIdOrNull(),
+ clientMac, packet.mRelayIp, packet.mHostName);
+ transmitAck(packet, lease, clientMac);
+ } else {
+ lease = mLeaseRepo.getOffer(packet.getExplicitClientIdOrNull(), clientMac,
+ packet.mRelayIp, packet.mRequestedIp, packet.mHostName);
+ transmitOffer(packet, lease, clientMac);
+ }
+ } catch (DhcpLeaseRepository.OutOfAddressesException e) {
+ transmitNak(packet, "Out of addresses to offer");
+ } catch (DhcpLeaseRepository.InvalidSubnetException e) {
+ logIgnoredPacketInvalidSubnet(e);
+ }
+ }
- private void processDiscover(@NonNull DhcpDiscoverPacket packet)
- throws MalformedPacketException {
- final DhcpLease lease;
- final MacAddress clientMac = getMacAddr(packet);
- try {
- if (mDhcpRapidCommitEnabled && packet.mRapidCommit) {
- lease = mLeaseRepo.getCommittedLease(packet.getExplicitClientIdOrNull(), clientMac,
- packet.mRelayIp, packet.mHostName);
- transmitAck(packet, lease, clientMac);
- } else {
- lease = mLeaseRepo.getOffer(packet.getExplicitClientIdOrNull(), clientMac,
- packet.mRelayIp, packet.mRequestedIp, packet.mHostName);
- transmitOffer(packet, lease, clientMac);
+ private void processRequest(@NonNull DhcpRequestPacket packet)
+ throws MalformedPacketException {
+ // If set, packet SID matches with this server's ID as checked in processPacket().
+ final boolean sidSet = packet.mServerIdentifier != null;
+ final DhcpLease lease;
+ final MacAddress clientMac = getMacAddr(packet);
+ try {
+ lease = mLeaseRepo.requestLease(packet.getExplicitClientIdOrNull(), clientMac,
+ packet.mClientIp, packet.mRelayIp, packet.mRequestedIp, sidSet,
+ packet.mHostName);
+ } catch (DhcpLeaseRepository.InvalidAddressException e) {
+ transmitNak(packet, "Invalid requested address");
+ return;
+ } catch (DhcpLeaseRepository.InvalidSubnetException e) {
+ logIgnoredPacketInvalidSubnet(e);
+ return;
}
- } catch (DhcpLeaseRepository.OutOfAddressesException e) {
- transmitNak(packet, "Out of addresses to offer");
- } catch (DhcpLeaseRepository.InvalidSubnetException e) {
- logIgnoredPacketInvalidSubnet(e);
+
+ transmitAck(packet, lease, clientMac);
}
- }
- private void processRequest(@NonNull DhcpRequestPacket packet) throws MalformedPacketException {
- // If set, packet SID matches with this server's ID as checked in processPacket().
- final boolean sidSet = packet.mServerIdentifier != null;
- final DhcpLease lease;
- final MacAddress clientMac = getMacAddr(packet);
- try {
- lease = mLeaseRepo.requestLease(packet.getExplicitClientIdOrNull(), clientMac,
- packet.mClientIp, packet.mRelayIp, packet.mRequestedIp, sidSet,
- packet.mHostName);
- } catch (DhcpLeaseRepository.InvalidAddressException e) {
- transmitNak(packet, "Invalid requested address");
- return;
- } catch (DhcpLeaseRepository.InvalidSubnetException e) {
- logIgnoredPacketInvalidSubnet(e);
- return;
+ private void processRelease(@NonNull DhcpReleasePacket packet)
+ throws MalformedPacketException {
+ final byte[] clientId = packet.getExplicitClientIdOrNull();
+ final MacAddress macAddr = getMacAddr(packet);
+ // Don't care about success (there is no ACK/NAK); logging is already done
+ // in the repository.
+ mLeaseRepo.releaseLease(clientId, macAddr, packet.mClientIp);
}
- transmitAck(packet, lease, clientMac);
+ private void processDecline(@NonNull DhcpDeclinePacket packet)
+ throws MalformedPacketException {
+ final byte[] clientId = packet.getExplicitClientIdOrNull();
+ final MacAddress macAddr = getMacAddr(packet);
+ int committedLeasesCount = mLeaseRepo.getCommittedLeases().size();
+
+ // If peer's clientID and macAddr doesn't match with any issued lease, nothing to do.
+ if (!mLeaseRepo.markAndReleaseDeclinedLease(clientId, macAddr, packet.mRequestedIp)) {
+ return;
+ }
+
+ // Check whether the boolean flag which requests a new prefix is enabled, and if
+ // it's enabled, make sure the issued lease count should be only one, otherwise,
+ // changing a different prefix will cause other exist host(s) configured with the
+ // current prefix lose appropriate route.
+ if (!mServingParams.changePrefixOnDecline || committedLeasesCount > 1) return;
+
+ if (mEventCallbacks == null) {
+ mLog.e("changePrefixOnDecline enabled but caller didn't pass a valid"
+ + "IDhcpEventCallbacks callback.");
+ return;
+ }
+
+ try {
+ mEventCallbacks.onNewPrefixRequest(
+ DhcpServingParams.makeIpPrefix(mServingParams.serverAddr));
+ transitionTo(mWaitBeforeRetrievalState);
+ } catch (RemoteException e) {
+ mLog.e("could not request a new prefix to caller", e);
+ }
+ }
}
- private void processRelease(@NonNull DhcpReleasePacket packet)
- throws MalformedPacketException {
- final byte[] clientId = packet.getExplicitClientIdOrNull();
- final MacAddress macAddr = getMacAddr(packet);
- // Don't care about success (there is no ACK/NAK); logging is already done in the repository
- mLeaseRepo.releaseLease(clientId, macAddr, packet.mClientIp);
+ class WaitBeforeRetrievalState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_UPDATE_PARAMS:
+ final Pair<DhcpServingParams, INetworkStackStatusCallback> pair =
+ (Pair<DhcpServingParams, INetworkStackStatusCallback>) msg.obj;
+ final IpPrefix currentPrefix =
+ DhcpServingParams.makeIpPrefix(mServingParams.serverAddr);
+ final IpPrefix newPrefix =
+ DhcpServingParams.makeIpPrefix(pair.first.serverAddr);
+ handleUpdateServingParams(pair.first, pair.second);
+ if (currentPrefix != null && !currentPrefix.equals(newPrefix)) {
+ transitionTo(mRunningState);
+ }
+ return HANDLED;
+
+ case CMD_RECEIVE_PACKET:
+ deferMessage(msg);
+ return HANDLED;
+
+ default:
+ // Fall through to StartedState.
+ return NOT_HANDLED;
+ }
+ }
}
private Inet4Address getAckOrOfferDst(@NonNull DhcpPacket request, @NonNull DhcpLease lease,
@@ -748,7 +817,13 @@ public class DhcpServer extends StateMachine {
@Override
protected void onReceive(@NonNull DhcpPacket packet, @NonNull Inet4Address srcAddr,
int srcPort) {
- processPacket(packet, srcPort);
+ if (srcPort != DHCP_CLIENT) {
+ final String packetType = packet.getClass().getSimpleName();
+ mLog.logf("Ignored packet of type %s sent from client port %d",
+ packetType, srcPort);
+ return;
+ }
+ sendMessage(CMD_RECEIVE_PACKET, packet);
}
@Override