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 
69     @Before
setUp()70     public void setUp() {
71         mBuilder = new DhcpServingParams.Builder()
72                 .setDefaultRouters(TEST_DEFAULT_ROUTERS)
73                 .setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS)
74                 .setDnsServers(TEST_DNS_SERVERS)
75                 .setServerAddr(TEST_LINKADDR)
76                 .setLinkMtu(TEST_MTU)
77                 .setExcludedAddrs(TEST_EXCLUDED_ADDRS)
78                 .setMetered(TEST_METERED)
79                 .setSingleClientAddr(TEST_CLIENT_ADDR)
80                 .setChangePrefixOnDecline(TEST_CHANGE_PREFIX_ON_DECLINE);
81     }
82 
83     @Test
testBuild_Immutable()84     public void testBuild_Immutable() throws InvalidParameterException {
85         final Set<Inet4Address> routers = new HashSet<>(TEST_DEFAULT_ROUTERS);
86         final Set<Inet4Address> dnsServers = new HashSet<>(TEST_DNS_SERVERS);
87         final Set<Inet4Address> excludedAddrs = new HashSet<>(TEST_EXCLUDED_ADDRS);
88 
89         final DhcpServingParams params = mBuilder
90                 .setDefaultRouters(routers)
91                 .setDnsServers(dnsServers)
92                 .setExcludedAddrs(excludedAddrs)
93                 .build();
94 
95         // Modifications to source objects should not affect builder or final parameters
96         final Inet4Address addedAddr = parseAddr("192.168.0.223");
97         routers.add(addedAddr);
98         dnsServers.add(addedAddr);
99         excludedAddrs.add(addedAddr);
100 
101         assertEquals(TEST_DEFAULT_ROUTERS, params.defaultRouters);
102         assertEquals(TEST_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
103         assertEquals(TEST_DNS_SERVERS, params.dnsServers);
104         assertEquals(TEST_LINKADDR, params.serverAddr);
105         assertEquals(TEST_MTU, params.linkMtu);
106         assertEquals(TEST_METERED, params.metered);
107         assertEquals(TEST_CHANGE_PREFIX_ON_DECLINE, params.changePrefixOnDecline);
108 
109         assertContains(params.excludedAddrs, TEST_EXCLUDED_ADDRS);
110         assertContains(params.excludedAddrs, TEST_DEFAULT_ROUTERS);
111         assertContains(params.excludedAddrs, TEST_DNS_SERVERS);
112         assertContains(params.excludedAddrs, TEST_SERVER_ADDR);
113 
114         assertFalse("excludedAddrs should not contain " + addedAddr,
115                 params.excludedAddrs.contains(addedAddr));
116     }
117 
118     @Test(expected = InvalidParameterException.class)
testBuild_NegativeLeaseTime()119     public void testBuild_NegativeLeaseTime() throws InvalidParameterException {
120         mBuilder.setDhcpLeaseTimeSecs(-1).build();
121     }
122 
123     @Test(expected = InvalidParameterException.class)
testBuild_LeaseTimeTooLarge()124     public void testBuild_LeaseTimeTooLarge() throws InvalidParameterException {
125         // Set lease time larger than max value for uint32
126         mBuilder.setDhcpLeaseTimeSecs(1L << 32).build();
127     }
128 
129     @Test
testBuild_InfiniteLeaseTime()130     public void testBuild_InfiniteLeaseTime() throws InvalidParameterException {
131         final long infiniteLeaseTime = 0xffffffffL;
132         final DhcpServingParams params = mBuilder
133                 .setDhcpLeaseTimeSecs(infiniteLeaseTime).build();
134         assertEquals(infiniteLeaseTime, params.dhcpLeaseTimeSecs);
135         assertTrue(params.dhcpLeaseTimeSecs > 0L);
136     }
137 
138     @Test
testBuild_UnsetMtu()139     public void testBuild_UnsetMtu() throws InvalidParameterException {
140         final DhcpServingParams params = mBuilder.setLinkMtu(MTU_UNSET).build();
141         assertEquals(MTU_UNSET, params.linkMtu);
142     }
143 
144     @Test(expected = InvalidParameterException.class)
testBuild_MtuTooSmall()145     public void testBuild_MtuTooSmall() throws InvalidParameterException {
146         mBuilder.setLinkMtu(20).build();
147     }
148 
149     @Test(expected = InvalidParameterException.class)
testBuild_MtuTooLarge()150     public void testBuild_MtuTooLarge() throws InvalidParameterException {
151         mBuilder.setLinkMtu(65_536).build();
152     }
153 
154     @Test(expected = InvalidParameterException.class)
testBuild_IPv6Addr()155     public void testBuild_IPv6Addr() throws InvalidParameterException {
156         mBuilder.setServerAddr(new LinkAddress(parseNumericAddress("fe80::1111"), 120)).build();
157     }
158 
159     @Test(expected = InvalidParameterException.class)
testBuild_PrefixTooLarge()160     public void testBuild_PrefixTooLarge() throws InvalidParameterException {
161         mBuilder.setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 15)).build();
162     }
163 
164     @Test(expected = InvalidParameterException.class)
testBuild_PrefixTooSmall()165     public void testBuild_PrefixTooSmall() throws InvalidParameterException {
166         mBuilder.setDefaultRouters(parseAddr("192.168.0.254"))
167                 .setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 31))
168                 .build();
169     }
170 
171     @Test(expected = InvalidParameterException.class)
testBuild_RouterNotInPrefix()172     public void testBuild_RouterNotInPrefix() throws InvalidParameterException {
173         mBuilder.setDefaultRouters(parseAddr("192.168.254.254")).build();
174     }
175 
176     @Test
testFromParcelableObject()177     public void testFromParcelableObject() throws InvalidParameterException {
178         final DhcpServingParams params = mBuilder.build();
179         final DhcpServingParamsParcel parcel = new DhcpServingParamsParcel();
180         parcel.defaultRouters = toIntArray(TEST_DEFAULT_ROUTERS);
181         parcel.dhcpLeaseTimeSecs = TEST_LEASE_TIME_SECS;
182         parcel.dnsServers = toIntArray(TEST_DNS_SERVERS);
183         parcel.serverAddr = inet4AddressToIntHTH(TEST_SERVER_ADDR);
184         parcel.serverAddrPrefixLength = TEST_LINKADDR.getPrefixLength();
185         parcel.linkMtu = TEST_MTU;
186         parcel.excludedAddrs = toIntArray(TEST_EXCLUDED_ADDRS);
187         parcel.metered = TEST_METERED;
188         parcel.singleClientAddr = inet4AddressToIntHTH(TEST_CLIENT_ADDR);
189         parcel.changePrefixOnDecline = TEST_CHANGE_PREFIX_ON_DECLINE;
190         final DhcpServingParams parceled = DhcpServingParams.fromParcelableObject(parcel);
191 
192         assertEquals(params.defaultRouters, parceled.defaultRouters);
193         assertEquals(params.dhcpLeaseTimeSecs, parceled.dhcpLeaseTimeSecs);
194         assertEquals(params.dnsServers, parceled.dnsServers);
195         assertEquals(params.serverAddr, parceled.serverAddr);
196         assertEquals(params.linkMtu, parceled.linkMtu);
197         assertEquals(params.excludedAddrs, parceled.excludedAddrs);
198         assertEquals(params.metered, parceled.metered);
199         assertEquals(params.singleClientAddr, parceled.singleClientAddr);
200         assertEquals(params.changePrefixOnDecline, parceled.changePrefixOnDecline);
201 
202         MiscAsserts.assertFieldCountEquals(10, DhcpServingParamsParcel.class);
203     }
204 
205     @Test(expected = InvalidParameterException.class)
testFromParcelableObject_NullArgument()206     public void testFromParcelableObject_NullArgument() throws InvalidParameterException {
207         DhcpServingParams.fromParcelableObject(null);
208     }
209 
toIntArray(Collection<Inet4Address> addrs)210     private static int[] toIntArray(Collection<Inet4Address> addrs) {
211         return addrs.stream().mapToInt(Inet4AddressUtils::inet4AddressToIntHTH).toArray();
212     }
213 
assertContains(@onNull Set<T> set, @NonNull Set<T> subset)214     private static <T> void assertContains(@NonNull Set<T> set, @NonNull Set<T> subset) {
215         for (final T elem : subset) {
216             assertContains(set, elem);
217         }
218     }
219 
assertContains(@onNull Set<T> set, @Nullable T elem)220     private static <T> void assertContains(@NonNull Set<T> set, @Nullable T elem) {
221         assertTrue("Set does not contain " + elem, set.contains(elem));
222     }
223 
224     @NonNull
parseAddr(@onNull String inet4Addr)225     private static Inet4Address parseAddr(@NonNull String inet4Addr) {
226         return (Inet4Address) parseNumericAddress(inet4Addr);
227     }
228 }
229