Merge "Assign specific client address to dhcp server"
This commit is contained in:
@@ -571,9 +571,8 @@ public class TetheringManager {
|
|||||||
/**
|
/**
|
||||||
* Configure tethering with static IPv4 assignment.
|
* Configure tethering with static IPv4 assignment.
|
||||||
*
|
*
|
||||||
* The clientAddress must be in the localIPv4Address prefix. A DHCP server will be
|
* A DHCP server will be started, but will only be able to offer the client address.
|
||||||
* started, but will only be able to offer the client address. The two addresses must
|
* The two addresses must be in the same prefix.
|
||||||
* be in the same prefix.
|
|
||||||
*
|
*
|
||||||
* @param localIPv4Address The preferred local IPv4 link address to use.
|
* @param localIPv4Address The preferred local IPv4 link address to use.
|
||||||
* @param clientAddress The static client address.
|
* @param clientAddress The static client address.
|
||||||
@@ -584,10 +583,7 @@ public class TetheringManager {
|
|||||||
@NonNull final LinkAddress clientAddress) {
|
@NonNull final LinkAddress clientAddress) {
|
||||||
Objects.requireNonNull(localIPv4Address);
|
Objects.requireNonNull(localIPv4Address);
|
||||||
Objects.requireNonNull(clientAddress);
|
Objects.requireNonNull(clientAddress);
|
||||||
if (localIPv4Address.getPrefixLength() != clientAddress.getPrefixLength()
|
if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) {
|
||||||
|| !localIPv4Address.isIpv4() || !clientAddress.isIpv4()
|
|
||||||
|| !new IpPrefix(localIPv4Address.toString()).equals(
|
|
||||||
new IpPrefix(clientAddress.toString()))) {
|
|
||||||
throw new IllegalArgumentException("Invalid server or client addresses");
|
throw new IllegalArgumentException("Invalid server or client addresses");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,6 +652,19 @@ public class TetheringManager {
|
|||||||
return mRequestParcel.showProvisioningUi;
|
return mRequestParcel.showProvisioningUi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the two addresses are ipv4 and in the same prefix.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static boolean checkStaticAddressConfiguration(
|
||||||
|
@NonNull final LinkAddress localIPv4Address,
|
||||||
|
@NonNull final LinkAddress clientAddress) {
|
||||||
|
return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength()
|
||||||
|
&& localIPv4Address.isIpv4() && clientAddress.isIpv4()
|
||||||
|
&& new IpPrefix(localIPv4Address.toString()).equals(
|
||||||
|
new IpPrefix(clientAddress.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a TetheringRequestParcel from the configuration
|
* Get a TetheringRequestParcel from the configuration
|
||||||
* @hide
|
* @hide
|
||||||
|
|||||||
@@ -18,10 +18,12 @@ package android.net.dhcp;
|
|||||||
|
|
||||||
import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
|
import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -160,6 +162,17 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the client address to tell DHCP server only offer this address.
|
||||||
|
* The client's prefix length is the same as server's.
|
||||||
|
*
|
||||||
|
* <p>If not set, the default value is null.
|
||||||
|
*/
|
||||||
|
public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) {
|
||||||
|
this.clientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) {
|
private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) {
|
||||||
int[] res = new int[addrs.size()];
|
int[] res = new int[addrs.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.net.ip;
|
|||||||
|
|
||||||
import static android.net.InetAddresses.parseNumericAddress;
|
import static android.net.InetAddresses.parseNumericAddress;
|
||||||
import static android.net.RouteInfo.RTN_UNICAST;
|
import static android.net.RouteInfo.RTN_UNICAST;
|
||||||
|
import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration;
|
||||||
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
||||||
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
|
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
|
||||||
import static android.net.util.NetworkConstants.FF;
|
import static android.net.util.NetworkConstants.FF;
|
||||||
@@ -492,17 +493,24 @@ public class IpServer extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean startDhcp(Inet4Address addr, int prefixLen) {
|
private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) {
|
||||||
if (mUsingLegacyDhcp) {
|
if (mUsingLegacyDhcp) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Inet4Address addr = (Inet4Address) serverLinkAddr.getAddress();
|
||||||
|
final int prefixLen = serverLinkAddr.getPrefixLength();
|
||||||
|
final Inet4Address clientAddr = clientLinkAddr == null ? null :
|
||||||
|
(Inet4Address) clientLinkAddr.getAddress();
|
||||||
|
|
||||||
final DhcpServingParamsParcel params;
|
final DhcpServingParamsParcel params;
|
||||||
params = new DhcpServingParamsParcelExt()
|
params = new DhcpServingParamsParcelExt()
|
||||||
.setDefaultRouters(addr)
|
.setDefaultRouters(addr)
|
||||||
.setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS)
|
.setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS)
|
||||||
.setDnsServers(addr)
|
.setDnsServers(addr)
|
||||||
.setServerAddr(new LinkAddress(addr, prefixLen))
|
.setServerAddr(serverLinkAddr)
|
||||||
.setMetered(true);
|
.setMetered(true)
|
||||||
|
.setSingleClientAddr(clientAddr);
|
||||||
// TODO: also advertise link MTU
|
// TODO: also advertise link MTU
|
||||||
|
|
||||||
mDhcpServerStartIndex++;
|
mDhcpServerStartIndex++;
|
||||||
@@ -537,9 +545,10 @@ public class IpServer extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean configureDhcp(boolean enable, Inet4Address addr, int prefixLen) {
|
private boolean configureDhcp(boolean enable, final LinkAddress serverAddr,
|
||||||
|
final LinkAddress clientAddr) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
return startDhcp(addr, prefixLen);
|
return startDhcp(serverAddr, clientAddr);
|
||||||
} else {
|
} else {
|
||||||
stopDhcp();
|
stopDhcp();
|
||||||
return true;
|
return true;
|
||||||
@@ -587,7 +596,7 @@ public class IpServer extends StateMachine {
|
|||||||
// code that calls into NetworkManagementService directly.
|
// code that calls into NetworkManagementService directly.
|
||||||
srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
|
srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
|
||||||
mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
|
mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
|
||||||
return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
|
return configureDhcp(enabled, mIpv4Address, null /* clientAddress */);
|
||||||
}
|
}
|
||||||
mIpv4Address = new LinkAddress(srvAddr, prefixLen);
|
mIpv4Address = new LinkAddress(srvAddr, prefixLen);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
@@ -624,7 +633,7 @@ public class IpServer extends StateMachine {
|
|||||||
mLinkProperties.removeRoute(route);
|
mLinkProperties.removeRoute(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
return configureDhcp(enabled, srvAddr, prefixLen);
|
return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRandomWifiIPv4Address() {
|
private String getRandomWifiIPv4Address() {
|
||||||
@@ -945,7 +954,14 @@ public class IpServer extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void maybeConfigureStaticIp(final TetheringRequestParcel request) {
|
private void maybeConfigureStaticIp(final TetheringRequestParcel request) {
|
||||||
if (request == null) return;
|
// Ignore static address configuration if they are invalid or null. In theory, static
|
||||||
|
// addresses should not be invalid here because TetheringManager do not allow caller to
|
||||||
|
// specify invalid static address configuration.
|
||||||
|
if (request == null || request.localIPv4Address == null
|
||||||
|
|| request.staticClientAddress == null || !checkStaticAddressConfiguration(
|
||||||
|
request.localIPv4Address, request.staticClientAddress)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mStaticIpv4ServerAddr = request.localIPv4Address;
|
mStaticIpv4ServerAddr = request.localIPv4Address;
|
||||||
mStaticIpv4ClientAddr = request.staticClientAddress;
|
mStaticIpv4ClientAddr = request.staticClientAddress;
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ import java.util.stream.IntStream;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
public class DhcpServingParamsParcelExtTest {
|
public class DhcpServingParamsParcelExtTest {
|
||||||
private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123");
|
private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123");
|
||||||
|
private static final Inet4Address TEST_CLIENT_ADDRESS = inet4Addr("192.168.0.42");
|
||||||
private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b;
|
private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b;
|
||||||
|
private static final int TEST_CLIENT_ADDRESS_PARCELED = 0xc0a8002a;
|
||||||
private static final int TEST_PREFIX_LENGTH = 17;
|
private static final int TEST_PREFIX_LENGTH = 17;
|
||||||
private static final int TEST_LEASE_TIME_SECS = 120;
|
private static final int TEST_LEASE_TIME_SECS = 120;
|
||||||
private static final int TEST_MTU = 1000;
|
private static final int TEST_MTU = 1000;
|
||||||
@@ -105,6 +107,12 @@ public class DhcpServingParamsParcelExtTest {
|
|||||||
assertFalse(mParcel.metered);
|
assertFalse(mParcel.metered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetClientAddr() {
|
||||||
|
mParcel.setSingleClientAddr(TEST_CLIENT_ADDRESS);
|
||||||
|
assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.clientAddr);
|
||||||
|
}
|
||||||
|
|
||||||
private static Inet4Address inet4Addr(String addr) {
|
private static Inet4Address inet4Addr(String addr) {
|
||||||
return (Inet4Address) parseNumericAddress(addr);
|
return (Inet4Address) parseNumericAddress(addr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
|
|||||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
||||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||||
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
||||||
|
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
|
||||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
|
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
|
||||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
|
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
|
||||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
|
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
|
||||||
@@ -1654,10 +1655,13 @@ public class TetheringTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRequestStaticServerIp() throws Exception {
|
public void testRequestStaticIp() throws Exception {
|
||||||
final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24");
|
final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24");
|
||||||
final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24");
|
final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24");
|
||||||
final String serverAddr = "192.168.20.1";
|
final String serverAddr = "192.168.0.123";
|
||||||
|
final int clientAddrParceled = 0xc0a8002a;
|
||||||
|
final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor =
|
||||||
|
ArgumentCaptor.forClass(DhcpServingParamsParcel.class);
|
||||||
mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
|
mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
|
||||||
serverLinkAddr, clientLinkAddr), null);
|
serverLinkAddr, clientLinkAddr), null);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
@@ -1666,8 +1670,12 @@ public class TetheringTest {
|
|||||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
|
verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
|
||||||
|
verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(),
|
||||||
// TODO: test static client address.
|
any());
|
||||||
|
final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue();
|
||||||
|
assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress());
|
||||||
|
assertEquals(24, params.serverAddrPrefixLength);
|
||||||
|
assertEquals(clientAddrParceled, params.clientAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Test that a request for hotspot mode doesn't interfere with an
|
// TODO: Test that a request for hotspot mode doesn't interfere with an
|
||||||
|
|||||||
Reference in New Issue
Block a user