Support MirrorLink DHCPDECLINE.
Add the specific implementation of onNewPrefixRequest callback on IpServer side, also refactor some common code. Bug: 130741856 Test: atest TetheringTests Change-Id: If2871bf899cb5890bbfee18063a194c92b6f474e
This commit is contained in:
@@ -173,6 +173,18 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the DHCP server should request a new prefix from IpServer when receiving
|
||||
* DHCPDECLINE message in certain particular link (e.g. there is only one downstream USB
|
||||
* tethering client). If it's false, process DHCPDECLINE message as RFC2131#4.3.3 suggests.
|
||||
*
|
||||
* <p>If not set, the default value is false.
|
||||
*/
|
||||
public DhcpServingParamsParcelExt setChangePrefixOnDecline(boolean changePrefixOnDecline) {
|
||||
this.changePrefixOnDecline = changePrefixOnDecline;
|
||||
return this;
|
||||
}
|
||||
|
||||
private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) {
|
||||
int[] res = new int[addrs.size()];
|
||||
int i = 0;
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.net.shared.NetdUtils;
|
||||
import android.net.shared.RouteUtils;
|
||||
import android.net.util.InterfaceParams;
|
||||
import android.net.util.InterfaceSet;
|
||||
import android.net.util.PrefixUtils;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -60,6 +61,7 @@ import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.util.MessageUtils;
|
||||
import com.android.internal.util.State;
|
||||
@@ -115,6 +117,15 @@ public class IpServer extends StateMachine {
|
||||
private static final String ETHERNET_IFACE_ADDR = "192.168.50.1";
|
||||
private static final int ETHERNET_IFACE_PREFIX_LENGTH = 24;
|
||||
|
||||
// TODO: remove this constant after introducing PrivateAddressCoordinator.
|
||||
private static final List<IpPrefix> NCM_PREFIXES = Collections.unmodifiableList(
|
||||
Arrays.asList(
|
||||
new IpPrefix("192.168.42.0/24"),
|
||||
new IpPrefix("192.168.51.0/24"),
|
||||
new IpPrefix("192.168.52.0/24"),
|
||||
new IpPrefix("192.168.53.0/24")
|
||||
));
|
||||
|
||||
// TODO: have PanService use some visible version of this constant
|
||||
private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
|
||||
private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
|
||||
@@ -212,6 +223,8 @@ public class IpServer extends StateMachine {
|
||||
public static final int CMD_IPV6_TETHER_UPDATE = BASE_IPSERVER + 10;
|
||||
// new neighbor cache entry on our interface
|
||||
public static final int CMD_NEIGHBOR_EVENT = BASE_IPSERVER + 11;
|
||||
// request from DHCP server that it wants to have a new prefix
|
||||
public static final int CMD_NEW_PREFIX_REQUEST = BASE_IPSERVER + 12;
|
||||
|
||||
private final State mInitialState;
|
||||
private final State mLocalHotspotState;
|
||||
@@ -462,7 +475,7 @@ public class IpServer extends StateMachine {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
}, new DhcpLeaseCallback());
|
||||
}, new DhcpEventCallback());
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
@@ -475,7 +488,7 @@ public class IpServer extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
private class DhcpLeaseCallback extends IDhcpEventCallbacks.Stub {
|
||||
private class DhcpEventCallback extends IDhcpEventCallbacks.Stub {
|
||||
@Override
|
||||
public void onLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables) {
|
||||
final ArrayList<TetheredClient> leases = new ArrayList<>();
|
||||
@@ -509,8 +522,9 @@ public class IpServer extends StateMachine {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewPrefixRequest(IpPrefix currentPrefix) {
|
||||
//TODO: add specific implementation.
|
||||
public void onNewPrefixRequest(@NonNull final IpPrefix currentPrefix) {
|
||||
Objects.requireNonNull(currentPrefix);
|
||||
sendMessage(CMD_NEW_PREFIX_REQUEST, currentPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -524,26 +538,38 @@ public class IpServer extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
private RouteInfo getDirectConnectedRoute(@NonNull final LinkAddress ipv4Address) {
|
||||
Objects.requireNonNull(ipv4Address);
|
||||
return new RouteInfo(PrefixUtils.asIpPrefix(ipv4Address), null, mIfaceName, RTN_UNICAST);
|
||||
}
|
||||
|
||||
private DhcpServingParamsParcel makeServingParams(@NonNull final Inet4Address defaultRouter,
|
||||
@NonNull final Inet4Address dnsServer, @NonNull LinkAddress serverAddr,
|
||||
@Nullable Inet4Address clientAddr) {
|
||||
final boolean changePrefixOnDecline =
|
||||
(mInterfaceType == TetheringManager.TETHERING_NCM && clientAddr == null);
|
||||
return new DhcpServingParamsParcelExt()
|
||||
.setDefaultRouters(defaultRouter)
|
||||
.setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS)
|
||||
.setDnsServers(dnsServer)
|
||||
.setServerAddr(serverAddr)
|
||||
.setMetered(true)
|
||||
.setSingleClientAddr(clientAddr)
|
||||
.setChangePrefixOnDecline(changePrefixOnDecline);
|
||||
// TODO: also advertise link MTU
|
||||
}
|
||||
|
||||
private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) {
|
||||
if (mUsingLegacyDhcp) {
|
||||
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;
|
||||
params = new DhcpServingParamsParcelExt()
|
||||
.setDefaultRouters(addr)
|
||||
.setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS)
|
||||
.setDnsServers(addr)
|
||||
.setServerAddr(serverLinkAddr)
|
||||
.setMetered(true)
|
||||
.setSingleClientAddr(clientAddr);
|
||||
// TODO: also advertise link MTU
|
||||
|
||||
final DhcpServingParamsParcel params = makeServingParams(addr /* defaultRouter */,
|
||||
addr /* dnsServer */, serverLinkAddr, clientAddr);
|
||||
mDhcpServerStartIndex++;
|
||||
mDeps.makeDhcpServer(
|
||||
mIfaceName, params, new DhcpServerCallbacksImpl(mDhcpServerStartIndex));
|
||||
@@ -570,7 +596,7 @@ public class IpServer extends StateMachine {
|
||||
});
|
||||
mDhcpServer = null;
|
||||
} catch (RemoteException e) {
|
||||
mLog.e("Error stopping DHCP", e);
|
||||
mLog.e("Error stopping DHCP server", e);
|
||||
// Not much more we can do here
|
||||
}
|
||||
}
|
||||
@@ -652,31 +678,33 @@ public class IpServer extends StateMachine {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Directly-connected route.
|
||||
final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
|
||||
mIpv4Address.getPrefixLength());
|
||||
final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST);
|
||||
if (enabled) {
|
||||
mLinkProperties.addLinkAddress(mIpv4Address);
|
||||
mLinkProperties.addRoute(route);
|
||||
mLinkProperties.addRoute(getDirectConnectedRoute(mIpv4Address));
|
||||
} else {
|
||||
mLinkProperties.removeLinkAddress(mIpv4Address);
|
||||
mLinkProperties.removeRoute(route);
|
||||
mLinkProperties.removeRoute(getDirectConnectedRoute(mIpv4Address));
|
||||
}
|
||||
|
||||
return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr);
|
||||
}
|
||||
|
||||
private String getRandomWifiIPv4Address() {
|
||||
private Inet4Address getRandomIPv4Address(@NonNull final byte[] rawAddr) {
|
||||
final byte[] ipv4Addr = rawAddr;
|
||||
ipv4Addr[3] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1), FF);
|
||||
try {
|
||||
byte[] bytes = parseNumericAddress(WIFI_HOST_IFACE_ADDR).getAddress();
|
||||
bytes[3] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1), FF);
|
||||
return InetAddress.getByAddress(bytes).getHostAddress();
|
||||
} catch (Exception e) {
|
||||
return WIFI_HOST_IFACE_ADDR;
|
||||
return (Inet4Address) InetAddress.getByAddress(ipv4Addr);
|
||||
} catch (UnknownHostException e) {
|
||||
mLog.e("Failed to construct Inet4Address from raw IPv4 addr");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getRandomWifiIPv4Address() {
|
||||
final Inet4Address ipv4Addr =
|
||||
getRandomIPv4Address(parseNumericAddress(WIFI_HOST_IFACE_ADDR).getAddress());
|
||||
return ipv4Addr != null ? ipv4Addr.getHostAddress() : WIFI_HOST_IFACE_ADDR;
|
||||
}
|
||||
|
||||
private boolean startIPv6() {
|
||||
mInterfaceParams = mDeps.getInterfaceParams(mIfaceName);
|
||||
if (mInterfaceParams == null) {
|
||||
@@ -761,13 +789,7 @@ public class IpServer extends StateMachine {
|
||||
mLastIPv6UpstreamIfindex = upstreamIfindex;
|
||||
}
|
||||
|
||||
private void configureLocalIPv6Routes(
|
||||
HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) {
|
||||
// [1] Remove the routes that are deprecated.
|
||||
if (!deprecatedPrefixes.isEmpty()) {
|
||||
final ArrayList<RouteInfo> toBeRemoved =
|
||||
getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
|
||||
// Remove routes from local network.
|
||||
private void removeRoutesFromLocalNetwork(@NonNull final List<RouteInfo> toBeRemoved) {
|
||||
final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork(
|
||||
mNetd, toBeRemoved);
|
||||
if (removalFailures > 0) {
|
||||
@@ -778,16 +800,7 @@ public class IpServer extends StateMachine {
|
||||
for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
|
||||
}
|
||||
|
||||
// [2] Add only the routes that have not previously been added.
|
||||
if (newPrefixes != null && !newPrefixes.isEmpty()) {
|
||||
HashSet<IpPrefix> addedPrefixes = (HashSet) newPrefixes.clone();
|
||||
if (mLastRaParams != null) {
|
||||
addedPrefixes.removeAll(mLastRaParams.prefixes);
|
||||
}
|
||||
|
||||
if (!addedPrefixes.isEmpty()) {
|
||||
final ArrayList<RouteInfo> toBeAdded =
|
||||
getLocalRoutesFor(mIfaceName, addedPrefixes);
|
||||
private void addRoutesToLocalNetwork(@NonNull final List<RouteInfo> toBeAdded) {
|
||||
try {
|
||||
// It's safe to call networkAddInterface() even if
|
||||
// the interface is already in the local_network.
|
||||
@@ -797,14 +810,34 @@ public class IpServer extends StateMachine {
|
||||
// already exist does not cause an error (EEXIST is silently ignored).
|
||||
RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
|
||||
} catch (IllegalStateException e) {
|
||||
mLog.e("Failed to add IPv6 routes to local table: " + e);
|
||||
mLog.e("Failed to add IPv4/v6 routes to local table: " + e);
|
||||
return;
|
||||
}
|
||||
} catch (ServiceSpecificException | RemoteException e) {
|
||||
mLog.e("Failed to add " + mIfaceName + " to local table: ", e);
|
||||
return;
|
||||
}
|
||||
|
||||
for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
|
||||
}
|
||||
|
||||
private void configureLocalIPv6Routes(
|
||||
HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) {
|
||||
// [1] Remove the routes that are deprecated.
|
||||
if (!deprecatedPrefixes.isEmpty()) {
|
||||
removeRoutesFromLocalNetwork(getLocalRoutesFor(mIfaceName, deprecatedPrefixes));
|
||||
}
|
||||
|
||||
// [2] Add only the routes that have not previously been added.
|
||||
if (newPrefixes != null && !newPrefixes.isEmpty()) {
|
||||
HashSet<IpPrefix> addedPrefixes = (HashSet) newPrefixes.clone();
|
||||
if (mLastRaParams != null) {
|
||||
addedPrefixes.removeAll(mLastRaParams.prefixes);
|
||||
}
|
||||
|
||||
if (!addedPrefixes.isEmpty()) {
|
||||
addRoutesToLocalNetwork(getLocalRoutesFor(mIfaceName, addedPrefixes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,6 +978,80 @@ public class IpServer extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: call PrivateAddressCoordinator.requestDownstreamAddress instead of this temporary
|
||||
// logic.
|
||||
private Inet4Address requestDownstreamAddress(@NonNull final IpPrefix currentPrefix) {
|
||||
final int oldIndex = NCM_PREFIXES.indexOf(currentPrefix);
|
||||
if (oldIndex == -1) {
|
||||
mLog.e("current prefix isn't supported for NCM link: " + currentPrefix);
|
||||
return null;
|
||||
}
|
||||
|
||||
final IpPrefix newPrefix = NCM_PREFIXES.get((oldIndex + 1) % NCM_PREFIXES.size());
|
||||
return getRandomIPv4Address(newPrefix.getRawAddress());
|
||||
}
|
||||
|
||||
private void handleNewPrefixRequest(@NonNull final IpPrefix currentPrefix) {
|
||||
if (!currentPrefix.contains(mIpv4Address.getAddress())
|
||||
|| currentPrefix.getPrefixLength() != mIpv4Address.getPrefixLength()) {
|
||||
Log.e(TAG, "Invalid prefix: " + currentPrefix);
|
||||
return;
|
||||
}
|
||||
|
||||
final LinkAddress deprecatedLinkAddress = mIpv4Address;
|
||||
final Inet4Address srvAddr = requestDownstreamAddress(currentPrefix);
|
||||
if (srvAddr == null) {
|
||||
mLog.e("Fail to request a new downstream prefix");
|
||||
return;
|
||||
}
|
||||
mIpv4Address = new LinkAddress(srvAddr, currentPrefix.getPrefixLength());
|
||||
|
||||
// Add new IPv4 address on the interface.
|
||||
if (!mInterfaceCtrl.addAddress(srvAddr, currentPrefix.getPrefixLength())) {
|
||||
mLog.e("Failed to add new IP " + srvAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove deprecated routes from local network.
|
||||
removeRoutesFromLocalNetwork(
|
||||
Collections.singletonList(getDirectConnectedRoute(deprecatedLinkAddress)));
|
||||
mLinkProperties.removeLinkAddress(deprecatedLinkAddress);
|
||||
|
||||
// Add new routes to local network.
|
||||
addRoutesToLocalNetwork(
|
||||
Collections.singletonList(getDirectConnectedRoute(mIpv4Address)));
|
||||
mLinkProperties.addLinkAddress(mIpv4Address);
|
||||
|
||||
// Update local DNS caching server with new IPv4 address, otherwise, dnsmasq doesn't
|
||||
// listen on the interface configured with new IPv4 address, that results DNS validation
|
||||
// failure of downstream client even if appropriate routes have been configured.
|
||||
try {
|
||||
mNetd.tetherApplyDnsInterfaces();
|
||||
} catch (ServiceSpecificException | RemoteException e) {
|
||||
mLog.e("Failed to update local DNS caching server");
|
||||
return;
|
||||
}
|
||||
sendLinkProperties();
|
||||
|
||||
// Notify DHCP server that new prefix/route has been applied on IpServer.
|
||||
final Inet4Address clientAddr = mStaticIpv4ClientAddr == null ? null :
|
||||
(Inet4Address) mStaticIpv4ClientAddr.getAddress();
|
||||
final DhcpServingParamsParcel params = makeServingParams(srvAddr /* defaultRouter */,
|
||||
srvAddr /* dnsServer */, mIpv4Address /* serverLinkAddress */, clientAddr);
|
||||
try {
|
||||
mDhcpServer.updateParams(params, new OnHandlerStatusCallback() {
|
||||
@Override
|
||||
public void callback(int statusCode) {
|
||||
if (statusCode != STATUS_SUCCESS) {
|
||||
mLog.e("Error updating DHCP serving params: " + statusCode);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
mLog.e("Error updating DHCP serving params", e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte getHopLimit(String upstreamIface) {
|
||||
try {
|
||||
int upstreamHopLimit = Integer.parseUnsignedInt(
|
||||
@@ -1056,11 +1163,9 @@ public class IpServer extends StateMachine {
|
||||
}
|
||||
|
||||
try {
|
||||
final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
|
||||
mIpv4Address.getPrefixLength());
|
||||
NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix);
|
||||
NetdUtils.tetherInterface(mNetd, mIfaceName, PrefixUtils.asIpPrefix(mIpv4Address));
|
||||
} catch (RemoteException | ServiceSpecificException | IllegalStateException e) {
|
||||
mLog.e("Error Tethering: " + e);
|
||||
mLog.e("Error Tethering", e);
|
||||
mLastError = TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
|
||||
return;
|
||||
}
|
||||
@@ -1115,6 +1220,9 @@ public class IpServer extends StateMachine {
|
||||
mLastError = TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
|
||||
transitionTo(mInitialState);
|
||||
break;
|
||||
case CMD_NEW_PREFIX_REQUEST:
|
||||
handleNewPrefixRequest((IpPrefix) message.obj);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.net.ip;
|
||||
|
||||
import static android.net.INetd.IF_STATE_UP;
|
||||
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.TetheringManager.TETHERING_NCM;
|
||||
import static android.net.TetheringManager.TETHERING_USB;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
||||
@@ -38,6 +39,7 @@ import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -67,6 +69,7 @@ import android.net.MacAddress;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.TetherOffloadRuleParcel;
|
||||
import android.net.dhcp.DhcpServingParamsParcel;
|
||||
import android.net.dhcp.IDhcpEventCallbacks;
|
||||
import android.net.dhcp.IDhcpServer;
|
||||
import android.net.dhcp.IDhcpServerCallbacks;
|
||||
import android.net.ip.IpNeighborMonitor.NeighborEvent;
|
||||
@@ -94,6 +97,7 @@ import org.mockito.MockitoAnnotations;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
@@ -496,6 +500,59 @@ public class IpServerTest {
|
||||
assertDhcpStarted(new IpPrefix("192.168.49.0/24"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startsDhcpServerOnNcm() throws Exception {
|
||||
initStateMachine(TETHERING_NCM);
|
||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||
|
||||
assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnNewPrefixRequest() throws Exception {
|
||||
initStateMachine(TETHERING_NCM);
|
||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
|
||||
|
||||
final IDhcpEventCallbacks eventCallbacks;
|
||||
final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor =
|
||||
ArgumentCaptor.forClass(IDhcpEventCallbacks.class);
|
||||
verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
|
||||
any(), dhcpEventCbsCaptor.capture());
|
||||
eventCallbacks = dhcpEventCbsCaptor.getValue();
|
||||
assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
|
||||
|
||||
// Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals
|
||||
// onNewPrefixRequest callback.
|
||||
eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24"));
|
||||
mLooper.dispatchAll();
|
||||
|
||||
final ArgumentCaptor<LinkProperties> lpCaptor =
|
||||
ArgumentCaptor.forClass(LinkProperties.class);
|
||||
InOrder inOrder = inOrder(mNetd, mCallback);
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
|
||||
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
|
||||
// One for ipv4 route, one for ipv6 link local route.
|
||||
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
|
||||
any(), any());
|
||||
inOrder.verify(mNetd).tetherApplyDnsInterfaces();
|
||||
inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
|
||||
verifyNoMoreInteractions(mCallback);
|
||||
|
||||
final LinkProperties linkProperties = lpCaptor.getValue();
|
||||
final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
|
||||
assertEquals(1, linkProperties.getLinkAddresses().size());
|
||||
assertEquals(1, linkProperties.getRoutes().size());
|
||||
final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(),
|
||||
linkAddresses.get(0).getPrefixLength());
|
||||
assertNotEquals(prefix, new IpPrefix("192.168.42.0/24"));
|
||||
|
||||
verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any());
|
||||
assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotStartDhcpServerIfDisabled() throws Exception {
|
||||
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */,
|
||||
@@ -731,19 +788,26 @@ public class IpServerTest {
|
||||
verify(mIpNeighborMonitor, never()).start();
|
||||
}
|
||||
|
||||
private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
|
||||
verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
|
||||
verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
|
||||
any(), any());
|
||||
final DhcpServingParamsParcel params = mDhcpParamsCaptor.getValue();
|
||||
private void assertDhcpServingParams(final DhcpServingParamsParcel params,
|
||||
final IpPrefix prefix) {
|
||||
// Last address byte is random
|
||||
assertTrue(expectedPrefix.contains(intToInet4AddressHTH(params.serverAddr)));
|
||||
assertEquals(expectedPrefix.getPrefixLength(), params.serverAddrPrefixLength);
|
||||
assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr)));
|
||||
assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength);
|
||||
assertEquals(1, params.defaultRouters.length);
|
||||
assertEquals(params.serverAddr, params.defaultRouters[0]);
|
||||
assertEquals(1, params.dnsServers.length);
|
||||
assertEquals(params.serverAddr, params.dnsServers[0]);
|
||||
assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
|
||||
if (mIpServer.interfaceType() == TETHERING_NCM) {
|
||||
assertTrue(params.changePrefixOnDecline);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
|
||||
verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
|
||||
verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
|
||||
any(), any());
|
||||
assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user