1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.dhcp; 18 19 import static android.net.InetAddresses.parseNumericAddress; 20 import static android.net.dhcp.DhcpServingParams.MTU_UNSET; 21 22 import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; 23 24 import static junit.framework.Assert.assertEquals; 25 import static junit.framework.Assert.assertFalse; 26 import static junit.framework.Assert.assertTrue; 27 28 import android.annotation.NonNull; 29 import android.annotation.Nullable; 30 import android.net.LinkAddress; 31 import android.net.dhcp.DhcpServingParams.InvalidParameterException; 32 33 import androidx.test.filters.SmallTest; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import com.android.net.module.util.Inet4AddressUtils; 37 import com.android.testutils.MiscAsserts; 38 39 import org.junit.Before; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.net.Inet4Address; 44 import java.util.Arrays; 45 import java.util.Collection; 46 import java.util.HashSet; 47 import java.util.Set; 48 49 @RunWith(AndroidJUnit4.class) 50 @SmallTest 51 public class DhcpServingParamsTest { 52 @NonNull 53 private DhcpServingParams.Builder mBuilder; 54 55 private static final Set<Inet4Address> TEST_DEFAULT_ROUTERS = new HashSet<>( 56 Arrays.asList(parseAddr("192.168.0.123"), parseAddr("192.168.0.124"))); 57 private static final long TEST_LEASE_TIME_SECS = 3600L; 58 private static final Set<Inet4Address> TEST_DNS_SERVERS = new HashSet<>( 59 Arrays.asList(parseAddr("192.168.0.126"), parseAddr("192.168.0.127"))); 60 private static final Inet4Address TEST_SERVER_ADDR = parseAddr("192.168.0.2"); 61 private static final Inet4Address TEST_CLIENT_ADDR = parseAddr("192.168.0.42"); 62 private static final LinkAddress TEST_LINKADDR = new LinkAddress(TEST_SERVER_ADDR, 20); 63 private static final int TEST_MTU = 1500; 64 private static final Set<Inet4Address> TEST_EXCLUDED_ADDRS = new HashSet<>( 65 Arrays.asList(parseAddr("192.168.0.200"), parseAddr("192.168.0.201"))); 66 private static final boolean TEST_METERED = true; 67 private static final boolean TEST_CHANGE_PREFIX_ON_DECLINE = true; 68 private static final int LEASES_SUBNET_PREFIX_LENGTH = 25; 69 70 @Before setUp()71 public void setUp() { 72 mBuilder = new DhcpServingParams.Builder() 73 .setDefaultRouters(TEST_DEFAULT_ROUTERS) 74 .setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS) 75 .setDnsServers(TEST_DNS_SERVERS) 76 .setServerAddr(TEST_LINKADDR) 77 .setLinkMtu(TEST_MTU) 78 .setExcludedAddrs(TEST_EXCLUDED_ADDRS) 79 .setMetered(TEST_METERED) 80 .setSingleClientAddr(TEST_CLIENT_ADDR) 81 .setChangePrefixOnDecline(TEST_CHANGE_PREFIX_ON_DECLINE) 82 .setLeasesSubnetPrefixLength(LEASES_SUBNET_PREFIX_LENGTH); 83 } 84 85 @Test testBuild_Immutable()86 public void testBuild_Immutable() throws InvalidParameterException { 87 final Set<Inet4Address> routers = new HashSet<>(TEST_DEFAULT_ROUTERS); 88 final Set<Inet4Address> dnsServers = new HashSet<>(TEST_DNS_SERVERS); 89 final Set<Inet4Address> excludedAddrs = new HashSet<>(TEST_EXCLUDED_ADDRS); 90 91 final DhcpServingParams params = mBuilder 92 .setDefaultRouters(routers) 93 .setDnsServers(dnsServers) 94 .setExcludedAddrs(excludedAddrs) 95 .build(); 96 97 // Modifications to source objects should not affect builder or final parameters 98 final Inet4Address addedAddr = parseAddr("192.168.0.223"); 99 routers.add(addedAddr); 100 dnsServers.add(addedAddr); 101 excludedAddrs.add(addedAddr); 102 103 assertEquals(TEST_DEFAULT_ROUTERS, params.defaultRouters); 104 assertEquals(TEST_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs); 105 assertEquals(TEST_DNS_SERVERS, params.dnsServers); 106 assertEquals(TEST_LINKADDR, params.serverAddr); 107 assertEquals(TEST_MTU, params.linkMtu); 108 assertEquals(TEST_METERED, params.metered); 109 assertEquals(TEST_CHANGE_PREFIX_ON_DECLINE, params.changePrefixOnDecline); 110 111 assertContains(params.excludedAddrs, TEST_EXCLUDED_ADDRS); 112 assertContains(params.excludedAddrs, TEST_DEFAULT_ROUTERS); 113 assertContains(params.excludedAddrs, TEST_DNS_SERVERS); 114 assertContains(params.excludedAddrs, TEST_SERVER_ADDR); 115 116 assertFalse("excludedAddrs should not contain " + addedAddr, 117 params.excludedAddrs.contains(addedAddr)); 118 } 119 120 @Test(expected = InvalidParameterException.class) testBuild_NegativeLeaseTime()121 public void testBuild_NegativeLeaseTime() throws InvalidParameterException { 122 mBuilder.setDhcpLeaseTimeSecs(-1).build(); 123 } 124 125 @Test(expected = InvalidParameterException.class) testBuild_LeaseTimeTooLarge()126 public void testBuild_LeaseTimeTooLarge() throws InvalidParameterException { 127 // Set lease time larger than max value for uint32 128 mBuilder.setDhcpLeaseTimeSecs(1L << 32).build(); 129 } 130 131 @Test testBuild_InfiniteLeaseTime()132 public void testBuild_InfiniteLeaseTime() throws InvalidParameterException { 133 final long infiniteLeaseTime = 0xffffffffL; 134 final DhcpServingParams params = mBuilder 135 .setDhcpLeaseTimeSecs(infiniteLeaseTime).build(); 136 assertEquals(infiniteLeaseTime, params.dhcpLeaseTimeSecs); 137 assertTrue(params.dhcpLeaseTimeSecs > 0L); 138 } 139 140 @Test testBuild_UnsetMtu()141 public void testBuild_UnsetMtu() throws InvalidParameterException { 142 final DhcpServingParams params = mBuilder.setLinkMtu(MTU_UNSET).build(); 143 assertEquals(MTU_UNSET, params.linkMtu); 144 } 145 146 @Test(expected = InvalidParameterException.class) testBuild_MtuTooSmall()147 public void testBuild_MtuTooSmall() throws InvalidParameterException { 148 mBuilder.setLinkMtu(20).build(); 149 } 150 151 @Test(expected = InvalidParameterException.class) testBuild_MtuTooLarge()152 public void testBuild_MtuTooLarge() throws InvalidParameterException { 153 mBuilder.setLinkMtu(65_536).build(); 154 } 155 156 @Test(expected = InvalidParameterException.class) testBuild_IPv6Addr()157 public void testBuild_IPv6Addr() throws InvalidParameterException { 158 mBuilder.setServerAddr(new LinkAddress(parseNumericAddress("fe80::1111"), 120)).build(); 159 } 160 161 @Test(expected = InvalidParameterException.class) testBuild_PrefixTooLarge()162 public void testBuild_PrefixTooLarge() throws InvalidParameterException { 163 mBuilder.setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 15)).build(); 164 } 165 166 @Test(expected = InvalidParameterException.class) testBuild_PrefixTooSmall()167 public void testBuild_PrefixTooSmall() throws InvalidParameterException { 168 mBuilder.setDefaultRouters(parseAddr("192.168.0.254")) 169 .setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 31)) 170 .build(); 171 } 172 173 @Test(expected = InvalidParameterException.class) testBuild_RouterNotInPrefix()174 public void testBuild_RouterNotInPrefix() throws InvalidParameterException { 175 mBuilder.setDefaultRouters(parseAddr("192.168.254.254")).build(); 176 } 177 178 @Test testBuild_LeasesSubnetPrefixLengthDefault()179 public void testBuild_LeasesSubnetPrefixLengthDefault() throws InvalidParameterException { 180 final DhcpServingParams params = mBuilder.setLeasesSubnetPrefixLength(0).build(); 181 // Same as server address prefix length (20). 182 assertEquals(20, params.leasesSubnetPrefixLength); 183 } 184 185 @Test(expected = InvalidParameterException.class) testBuild_LeasesSubnetPrefixLengthTooSmall()186 public void testBuild_LeasesSubnetPrefixLengthTooSmall() throws InvalidParameterException { 187 // Smaller than server address prefix length (20). 188 mBuilder.setLeasesSubnetPrefixLength(2).build(); 189 } 190 191 @Test(expected = InvalidParameterException.class) testBuild_LeasesSubnetPrefixLengthTooLarge()192 public void testBuild_LeasesSubnetPrefixLengthTooLarge() throws InvalidParameterException { 193 // Larger than max prefix length (30). 194 mBuilder.setLeasesSubnetPrefixLength(31).build(); 195 } 196 197 @Test testFromParcelableObject()198 public void testFromParcelableObject() throws InvalidParameterException { 199 final DhcpServingParams params = mBuilder.build(); 200 final DhcpServingParamsParcel parcel = new DhcpServingParamsParcel(); 201 parcel.defaultRouters = toIntArray(TEST_DEFAULT_ROUTERS); 202 parcel.dhcpLeaseTimeSecs = TEST_LEASE_TIME_SECS; 203 parcel.dnsServers = toIntArray(TEST_DNS_SERVERS); 204 parcel.serverAddr = inet4AddressToIntHTH(TEST_SERVER_ADDR); 205 parcel.serverAddrPrefixLength = TEST_LINKADDR.getPrefixLength(); 206 parcel.linkMtu = TEST_MTU; 207 parcel.excludedAddrs = toIntArray(TEST_EXCLUDED_ADDRS); 208 parcel.metered = TEST_METERED; 209 parcel.singleClientAddr = inet4AddressToIntHTH(TEST_CLIENT_ADDR); 210 parcel.changePrefixOnDecline = TEST_CHANGE_PREFIX_ON_DECLINE; 211 parcel.leasesSubnetPrefixLength = LEASES_SUBNET_PREFIX_LENGTH; 212 final DhcpServingParams parceled = DhcpServingParams.fromParcelableObject(parcel); 213 214 assertEquals(params.defaultRouters, parceled.defaultRouters); 215 assertEquals(params.dhcpLeaseTimeSecs, parceled.dhcpLeaseTimeSecs); 216 assertEquals(params.dnsServers, parceled.dnsServers); 217 assertEquals(params.serverAddr, parceled.serverAddr); 218 assertEquals(params.linkMtu, parceled.linkMtu); 219 assertEquals(params.excludedAddrs, parceled.excludedAddrs); 220 assertEquals(params.metered, parceled.metered); 221 assertEquals(params.singleClientAddr, parceled.singleClientAddr); 222 assertEquals(params.changePrefixOnDecline, parceled.changePrefixOnDecline); 223 assertEquals(params.leasesSubnetPrefixLength, parceled.leasesSubnetPrefixLength); 224 225 MiscAsserts.assertFieldCountEquals(11, DhcpServingParamsParcel.class); 226 } 227 228 @Test(expected = InvalidParameterException.class) testFromParcelableObject_NullArgument()229 public void testFromParcelableObject_NullArgument() throws InvalidParameterException { 230 DhcpServingParams.fromParcelableObject(null); 231 } 232 toIntArray(Collection<Inet4Address> addrs)233 private static int[] toIntArray(Collection<Inet4Address> addrs) { 234 return addrs.stream().mapToInt(Inet4AddressUtils::inet4AddressToIntHTH).toArray(); 235 } 236 assertContains(@onNull Set<T> set, @NonNull Set<T> subset)237 private static <T> void assertContains(@NonNull Set<T> set, @NonNull Set<T> subset) { 238 for (final T elem : subset) { 239 assertContains(set, elem); 240 } 241 } 242 assertContains(@onNull Set<T> set, @Nullable T elem)243 private static <T> void assertContains(@NonNull Set<T> set, @Nullable T elem) { 244 assertTrue("Set does not contain " + elem, set.contains(elem)); 245 } 246 247 @NonNull parseAddr(@onNull String inet4Addr)248 private static Inet4Address parseAddr(@NonNull String inet4Addr) { 249 return (Inet4Address) parseNumericAddress(inet4Addr); 250 } 251 } 252