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.shared.Inet4AddressUtils.inet4AddressToIntHTH;
20 
21 import android.net.LinkAddress;
22 import android.util.ArraySet;
23 
24 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable;
26 
27 import java.net.Inet4Address;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Set;
31 
32 /**
33  * Subclass of {@link DhcpServingParamsParcel} with additional utility methods for building.
34  *
35  * <p>This utility class does not check for validity of the parameters: invalid parameters are
36  * reported by the receiving module when unparceling the parcel.
37  *
38  * @see DhcpServingParams
39  * @hide
40  */
41 public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel {
42     public static final int MTU_UNSET = 0;
43 
44     /**
45      * Set the server address and served prefix for the DHCP server.
46      *
47      * <p>This parameter is required.
48      */
setServerAddr(@onNull LinkAddress serverAddr)49     public DhcpServingParamsParcelExt setServerAddr(@NonNull LinkAddress serverAddr) {
50         this.serverAddr = inet4AddressToIntHTH((Inet4Address) serverAddr.getAddress());
51         this.serverAddrPrefixLength = serverAddr.getPrefixLength();
52         return this;
53     }
54 
55     /**
56      * Set the default routers to be advertised to DHCP clients.
57      *
58      * <p>Each router must be inside the served prefix. This may be an empty set, but it must
59      * always be set explicitly.
60      */
setDefaultRouters(@onNull Set<Inet4Address> defaultRouters)61     public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) {
62         this.defaultRouters = toIntArray(defaultRouters);
63         return this;
64     }
65 
66     /**
67      * Set the default routers to be advertised to DHCP clients.
68      *
69      * <p>Each router must be inside the served prefix. This may be an empty list of routers,
70      * but it must always be set explicitly.
71      */
setDefaultRouters(@onNull Inet4Address... defaultRouters)72     public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Inet4Address... defaultRouters) {
73         return setDefaultRouters(newArraySet(defaultRouters));
74     }
75 
76     /**
77      * Convenience method to build the parameters with no default router.
78      *
79      * <p>Equivalent to calling {@link #setDefaultRouters(Inet4Address...)} with no address.
80      */
setNoDefaultRouter()81     public DhcpServingParamsParcelExt setNoDefaultRouter() {
82         return setDefaultRouters();
83     }
84 
85     /**
86      * Set the DNS servers to be advertised to DHCP clients.
87      *
88      * <p>This may be an empty set, but it must always be set explicitly.
89      */
setDnsServers(@onNull Set<Inet4Address> dnsServers)90     public DhcpServingParamsParcelExt setDnsServers(@NonNull Set<Inet4Address> dnsServers) {
91         this.dnsServers = toIntArray(dnsServers);
92         return this;
93     }
94 
95     /**
96      * Set the DNS servers to be advertised to DHCP clients.
97      *
98      * <p>This may be an empty list of servers, but it must always be set explicitly.
99      */
setDnsServers(@onNull Inet4Address... dnsServers)100     public DhcpServingParamsParcelExt setDnsServers(@NonNull Inet4Address... dnsServers) {
101         return setDnsServers(newArraySet(dnsServers));
102     }
103 
104     /**
105      * Convenience method to build the parameters with no DNS server.
106      *
107      * <p>Equivalent to calling {@link #setDnsServers(Inet4Address...)} with no address.
108      */
setNoDnsServer()109     public DhcpServingParamsParcelExt setNoDnsServer() {
110         return setDnsServers();
111     }
112 
113     /**
114      * Set excluded addresses that the DHCP server is not allowed to assign to clients.
115      *
116      * <p>This parameter is optional. DNS servers and default routers are always excluded
117      * and do not need to be set here.
118      */
setExcludedAddrs(@onNull Set<Inet4Address> excludedAddrs)119     public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) {
120         this.excludedAddrs = toIntArray(excludedAddrs);
121         return this;
122     }
123 
124     /**
125      * Set excluded addresses that the DHCP server is not allowed to assign to clients.
126      *
127      * <p>This parameter is optional. DNS servers and default routers are always excluded
128      * and do not need to be set here.
129      */
setExcludedAddrs(@onNull Inet4Address... excludedAddrs)130     public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) {
131         return setExcludedAddrs(newArraySet(excludedAddrs));
132     }
133 
134     /**
135      * Set the lease time for leases assigned by the DHCP server.
136      *
137      * <p>This parameter is required.
138      */
setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs)139     public DhcpServingParamsParcelExt setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) {
140         this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
141         return this;
142     }
143 
144     /**
145      * Set the link MTU to be advertised to DHCP clients.
146      *
147      * <p>If set to {@link #MTU_UNSET}, no MTU will be advertised to clients. This parameter
148      * is optional and defaults to {@link #MTU_UNSET}.
149      */
setLinkMtu(int linkMtu)150     public DhcpServingParamsParcelExt setLinkMtu(int linkMtu) {
151         this.linkMtu = linkMtu;
152         return this;
153     }
154 
155     /**
156      * Set whether the DHCP server should send the ANDROID_METERED vendor-specific option.
157      *
158      * <p>If not set, the default value is false.
159      */
setMetered(boolean metered)160     public DhcpServingParamsParcelExt setMetered(boolean metered) {
161         this.metered = metered;
162         return this;
163     }
164 
165     /**
166      * Set the client address to tell DHCP server only offer this address.
167      * The client's prefix length is the same as server's.
168      *
169      * <p>If not set, the default value is null.
170      */
setSingleClientAddr(@ullable Inet4Address clientAddr)171     public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) {
172         this.singleClientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr);
173         return this;
174     }
175 
176     /**
177      * Set whether the DHCP server should request a new prefix from IpServer when receiving
178      * DHCPDECLINE message in certain particular link (e.g. there is only one downstream USB
179      * tethering client). If it's false, process DHCPDECLINE message as RFC2131#4.3.3 suggests.
180      *
181      * <p>If not set, the default value is false.
182      */
setChangePrefixOnDecline(boolean changePrefixOnDecline)183     public DhcpServingParamsParcelExt setChangePrefixOnDecline(boolean changePrefixOnDecline) {
184         this.changePrefixOnDecline = changePrefixOnDecline;
185         return this;
186     }
187 
toIntArray(@onNull Collection<Inet4Address> addrs)188     private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) {
189         int[] res = new int[addrs.size()];
190         int i = 0;
191         for (Inet4Address addr : addrs) {
192             res[i] = inet4AddressToIntHTH(addr);
193             i++;
194         }
195         return res;
196     }
197 
newArraySet(Inet4Address... addrs)198     private static ArraySet<Inet4Address> newArraySet(Inet4Address... addrs) {
199         ArraySet<Inet4Address> addrSet = new ArraySet<>(addrs.length);
200         Collections.addAll(addrSet, addrs);
201         return addrSet;
202     }
203 }
204