summaryrefslogtreecommitdiff
path: root/src/android
diff options
context:
space:
mode:
authorXiao Ma <xiaom@google.com>2019-07-24 16:27:50 +0900
committerXiao Ma <xiaom@google.com>2019-12-11 11:26:49 +0900
commit859ceabd04daece392d42d37dbc2092cb88996f1 (patch)
tree2a2adec6473fee85f7aff6971238eb58beaff56e /src/android
parent762f239387423bf2250139f49972d2afa14c7428 (diff)
Add Rapid Commit option support in DHCP Server side.
Bug:136216415 Test: atest FrameworksNetTests NetworkStackTests Test: atest NetworkStackIntegrationTests Test: manual tethering Change-Id: I0f9483c72374bab271eb18549a1a41812f32f2dd
Diffstat (limited to 'src/android')
-rw-r--r--src/android/net/dhcp/DhcpAckPacket.java8
-rw-r--r--src/android/net/dhcp/DhcpClient.java3
-rw-r--r--src/android/net/dhcp/DhcpDiscoverPacket.java3
-rw-r--r--src/android/net/dhcp/DhcpLeaseRepository.java19
-rw-r--r--src/android/net/dhcp/DhcpPacket.java13
-rw-r--r--src/android/net/dhcp/DhcpServer.java62
-rw-r--r--src/android/net/util/NetworkStackUtils.java9
7 files changed, 86 insertions, 31 deletions
diff --git a/src/android/net/dhcp/DhcpAckPacket.java b/src/android/net/dhcp/DhcpAckPacket.java
index 052af35..9e981ef 100644
--- a/src/android/net/dhcp/DhcpAckPacket.java
+++ b/src/android/net/dhcp/DhcpAckPacket.java
@@ -30,10 +30,12 @@ public class DhcpAckPacket extends DhcpPacket {
private final Inet4Address mSrcIp;
DhcpAckPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress,
- Inet4Address relayIp, Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) {
+ Inet4Address relayIp, Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac,
+ boolean rapidCommit) {
super(transId, secs, clientIp, yourIp, serverAddress, relayIp, clientMac, broadcast);
mBroadcast = broadcast;
mSrcIp = serverAddress;
+ mRapidCommit = rapidCommit;
}
public String toString() {
@@ -70,8 +72,10 @@ public class DhcpAckPacket extends DhcpPacket {
void finishPacket(ByteBuffer buffer) {
addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_ACK);
addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
-
addCommonServerTlvs(buffer);
+ if (mRapidCommit) {
+ addTlv(buffer, DHCP_RAPID_COMMIT);
+ }
addTlvEnd(buffer);
}
diff --git a/src/android/net/dhcp/DhcpClient.java b/src/android/net/dhcp/DhcpClient.java
index e7d53ee..dc0175e 100644
--- a/src/android/net/dhcp/DhcpClient.java
+++ b/src/android/net/dhcp/DhcpClient.java
@@ -1171,7 +1171,8 @@ public class DhcpClient extends StateMachine {
final DhcpResults results = packet.toDhcpResults();
if (results != null) {
confirmDhcpLease(packet, results);
- transitionTo(mConfiguringInterfaceState);
+ transitionTo(isDhcpIpConflictDetectEnabled()
+ ? mIpAddressConflictDetectingState : mConfiguringInterfaceState);
}
}
}
diff --git a/src/android/net/dhcp/DhcpDiscoverPacket.java b/src/android/net/dhcp/DhcpDiscoverPacket.java
index a749796..15c20cf 100644
--- a/src/android/net/dhcp/DhcpDiscoverPacket.java
+++ b/src/android/net/dhcp/DhcpDiscoverPacket.java
@@ -32,9 +32,10 @@ public class DhcpDiscoverPacket extends DhcpPacket {
* Generates a DISCOVER packet with the specified parameters.
*/
DhcpDiscoverPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac,
- boolean broadcast, Inet4Address srcIp) {
+ boolean broadcast, Inet4Address srcIp, boolean rapidCommit) {
super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast);
mSrcIp = srcIp;
+ mRapidCommit = rapidCommit;
}
public String toString() {
diff --git a/src/android/net/dhcp/DhcpLeaseRepository.java b/src/android/net/dhcp/DhcpLeaseRepository.java
index d22193b..4e74dc8 100644
--- a/src/android/net/dhcp/DhcpLeaseRepository.java
+++ b/src/android/net/dhcp/DhcpLeaseRepository.java
@@ -190,6 +190,25 @@ class DhcpLeaseRepository {
return newLease;
}
+ /**
+ * Get a rapid committed DHCP Lease, to reply to a DHCPDISCOVER w/ Rapid Commit option.
+ *
+ * @param clientId Client identifier option if specified, or {@link #CLIENTID_UNSPEC}
+ * @param relayAddr Internet address of the relay (giaddr), can be {@link Inet4Address#ANY}
+ * @param hostname Client-provided hostname, or {@link DhcpLease#HOSTNAME_NONE}
+ * @throws OutOfAddressesException The server does not have any available address
+ * @throws InvalidSubnetException The lease was requested from an unsupported subnet
+ */
+ @NonNull
+ public DhcpLease getCommittedLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+ @NonNull Inet4Address relayAddr, @Nullable String hostname)
+ throws OutOfAddressesException, InvalidSubnetException {
+ final DhcpLease newLease = getOffer(clientId, hwAddr, relayAddr, null /* reqAddr */,
+ hostname);
+ commitLease(newLease);
+ return newLease;
+ }
+
private void checkValidRelayAddr(@Nullable Inet4Address relayAddr)
throws InvalidSubnetException {
// As per #4.3.1, addresses are assigned based on the relay address if present. This
diff --git a/src/android/net/dhcp/DhcpPacket.java b/src/android/net/dhcp/DhcpPacket.java
index 5ab769b..c5700b3 100644
--- a/src/android/net/dhcp/DhcpPacket.java
+++ b/src/android/net/dhcp/DhcpPacket.java
@@ -1179,7 +1179,7 @@ public abstract class DhcpPacket {
"No DHCP message type option");
case DHCP_MESSAGE_TYPE_DISCOVER:
newPacket = new DhcpDiscoverPacket(transactionId, secs, relayIp, clientMac,
- broadcast, ipSrc);
+ broadcast, ipSrc, rapidCommit);
break;
case DHCP_MESSAGE_TYPE_OFFER:
newPacket = new DhcpOfferPacket(
@@ -1196,7 +1196,8 @@ public abstract class DhcpPacket {
break;
case DHCP_MESSAGE_TYPE_ACK:
newPacket = new DhcpAckPacket(
- transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac);
+ transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac,
+ rapidCommit);
break;
case DHCP_MESSAGE_TYPE_NAK:
newPacket = new DhcpNakPacket(
@@ -1238,7 +1239,6 @@ public abstract class DhcpPacket {
newPacket.mT2 = T2;
newPacket.mVendorId = vendorId;
newPacket.mVendorInfo = vendorInfo;
- newPacket.mRapidCommit = rapidCommit;
if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) {
newPacket.mServerHostName = serverHostName;
} else {
@@ -1330,9 +1330,8 @@ public abstract class DhcpPacket {
short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams,
boolean rapidCommit) {
DhcpPacket pkt = new DhcpDiscoverPacket(transactionId, secs, INADDR_ANY /* relayIp */,
- clientMac, broadcast, INADDR_ANY /* srcIp */);
+ clientMac, broadcast, INADDR_ANY /* srcIp */, rapidCommit);
pkt.mRequestedParams = expectedParams;
- pkt.mRapidCommit = rapidCommit;
return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
}
@@ -1372,10 +1371,10 @@ public abstract class DhcpPacket {
Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask,
Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
- short mtu) {
+ short mtu, boolean rapidCommit) {
DhcpPacket pkt = new DhcpAckPacket(
transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp,
- mac);
+ mac, rapidCommit);
pkt.mGateways = gateways;
pkt.mDnsServers = dnsServers;
pkt.mLeaseTime = timeout;
diff --git a/src/android/net/dhcp/DhcpServer.java b/src/android/net/dhcp/DhcpServer.java
index 37dd972..4fc213a 100644
--- a/src/android/net/dhcp/DhcpServer.java
+++ b/src/android/net/dhcp/DhcpServer.java
@@ -22,6 +22,8 @@ import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
import static android.net.shared.Inet4AddressUtils.getBroadcastAddress;
import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address;
+import static android.net.util.NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
@@ -38,6 +40,7 @@ import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingP
import static java.lang.Integer.toUnsignedLong;
+import android.content.Context;
import android.net.INetworkStackStatusCallback;
import android.net.MacAddress;
import android.net.TrafficStats;
@@ -92,6 +95,8 @@ public class DhcpServer extends IDhcpServer.Stub {
private static final int CMD_UPDATE_PARAMS = 3;
@NonNull
+ private final Context mContext;
+ @NonNull
private final HandlerThread mHandlerThread;
@NonNull
private final String mIfName;
@@ -107,6 +112,8 @@ public class DhcpServer extends IDhcpServer.Stub {
@Nullable
private volatile ServerHandler mHandler;
+ private final boolean mDhcpRapidCommitEnabled;
+
// Accessed only on the handler thread
@Nullable
private DhcpPacketListener mPacketListener;
@@ -176,6 +183,14 @@ public class DhcpServer extends IDhcpServer.Stub {
* @throws SecurityException The caller is not allowed to call public methods on DhcpServer.
*/
void checkCaller() throws SecurityException;
+
+ /**
+ * Check whether or not one specific experimental feature for connectivity namespace is
+ * enabled.
+ * @param context The global context information about an app environment.
+ * @param name Specific experimental flag name.
+ */
+ boolean isFeatureEnabled(@NonNull Context context, @NonNull String name);
}
private class DependenciesImpl implements Dependencies {
@@ -214,6 +229,11 @@ public class DhcpServer extends IDhcpServer.Stub {
public void checkCaller() {
enforceNetworkStackCallingPermission();
}
+
+ @Override
+ public boolean isFeatureEnabled(@NonNull Context context, @NonNull String name) {
+ return NetworkStackUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name);
+ }
}
private static class MalformedPacketException extends Exception {
@@ -222,19 +242,20 @@ public class DhcpServer extends IDhcpServer.Stub {
}
}
- public DhcpServer(@NonNull String ifName,
+ public DhcpServer(@NonNull Context context, @NonNull String ifName,
@NonNull DhcpServingParams params, @NonNull SharedLog log) {
- this(new HandlerThread(DhcpServer.class.getSimpleName() + "." + ifName),
+ this(context, new HandlerThread(DhcpServer.class.getSimpleName() + "." + ifName),
ifName, params, log, null);
}
@VisibleForTesting
- DhcpServer(@NonNull HandlerThread handlerThread, @NonNull String ifName,
- @NonNull DhcpServingParams params, @NonNull SharedLog log,
+ DhcpServer(@NonNull Context context, @NonNull HandlerThread handlerThread,
+ @NonNull String ifName, @NonNull DhcpServingParams params, @NonNull SharedLog log,
@Nullable Dependencies deps) {
if (deps == null) {
deps = new DependenciesImpl();
}
+ mContext = context;
mHandlerThread = handlerThread;
mIfName = ifName;
mServingParams = params;
@@ -242,6 +263,7 @@ public class DhcpServer extends IDhcpServer.Stub {
mDeps = deps;
mClock = deps.makeClock();
mLeaseRepo = deps.makeLeaseRepository(mServingParams, mLog, mClock);
+ mDhcpRapidCommitEnabled = deps.isFeatureEnabled(context, DHCP_RAPID_COMMIT_VERSION);
}
/**
@@ -388,17 +410,20 @@ public class DhcpServer extends IDhcpServer.Stub {
final DhcpLease lease;
final MacAddress clientMac = getMacAddr(packet);
try {
- lease = mLeaseRepo.getOffer(packet.getExplicitClientIdOrNull(), clientMac,
- packet.mRelayIp, packet.mRequestedIp, packet.mHostName);
+ 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");
- return;
} catch (DhcpLeaseRepository.InvalidSubnetException e) {
logIgnoredPacketInvalidSubnet(e);
- return;
}
-
- transmitOffer(packet, lease, clientMac);
}
private void processRequest(@NonNull DhcpRequestPacket packet) throws MalformedPacketException {
@@ -492,23 +517,24 @@ public class DhcpServer extends IDhcpServer.Stub {
return transmitOfferOrAckPacket(offerPacket, request, lease, clientMac, broadcastFlag);
}
- private boolean transmitAck(@NonNull DhcpPacket request, @NonNull DhcpLease lease,
+ private boolean transmitAck(@NonNull DhcpPacket packet, @NonNull DhcpLease lease,
@NonNull MacAddress clientMac) {
// TODO: replace DhcpPacket's build methods with real builders and use common code with
// transmitOffer above
- final boolean broadcastFlag = getBroadcastFlag(request, lease);
+ final boolean broadcastFlag = getBroadcastFlag(packet, lease);
final int timeout = getLeaseTimeout(lease);
- final String hostname = getHostnameIfRequested(request, lease);
- final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, request.mTransId,
- broadcastFlag, mServingParams.getServerInet4Addr(), request.mRelayIp,
- lease.getNetAddr(), request.mClientIp, request.mClientMac, timeout,
+ final String hostname = getHostnameIfRequested(packet, lease);
+ final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, packet.mTransId,
+ broadcastFlag, mServingParams.getServerInet4Addr(), packet.mRelayIp,
+ lease.getNetAddr(), packet.mClientIp, packet.mClientMac, timeout,
mServingParams.getPrefixMaskAsAddress(), mServingParams.getBroadcastAddress(),
new ArrayList<>(mServingParams.defaultRouters),
new ArrayList<>(mServingParams.dnsServers),
mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
- mServingParams.metered, (short) mServingParams.linkMtu);
+ mServingParams.metered, (short) mServingParams.linkMtu,
+ packet.mRapidCommit && mDhcpRapidCommitEnabled);
- return transmitOfferOrAckPacket(ackPacket, request, lease, clientMac, broadcastFlag);
+ return transmitOfferOrAckPacket(ackPacket, packet, lease, clientMac, broadcastFlag);
}
private boolean transmitNak(DhcpPacket request, String message) {
diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java
index 993f3cb..45ed367 100644
--- a/src/android/net/util/NetworkStackUtils.java
+++ b/src/android/net/util/NetworkStackUtils.java
@@ -112,13 +112,18 @@ public class NetworkStackUtils {
public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
/**
- * Experiment flag to enable DHCP INIT-REBOOT state, default value is false.
+ * @deprecated Considering boolean experiment flag is likely to cause misconfiguration
+ * particularly when NetworkStack module rolls back to previous version. It's
+ * much safer to determine whether or not to enable one specific experimental
+ * feature by comparing flag version with module version.
*/
+ @Deprecated
public static final String DHCP_INIT_REBOOT_ENABLED = "dhcp_init_reboot_enabled";
/**
- * Experiment flag to enable DHCP Rapid Commit option, default value is false.
+ * @deprecated See above explanation.
*/
+ @Deprecated
public static final String DHCP_RAPID_COMMIT_ENABLED = "dhcp_rapid_commit_enabled";
/**