• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.os.Build;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 
27 import com.android.net.module.util.InetAddressUtils;
28 
29 import java.net.Inet4Address;
30 import java.net.InetAddress;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Objects;
34 
35 /**
36  * Class that describes static IP configuration.
37  */
38 public final class StaticIpConfiguration implements Parcelable {
39     /** @hide */
40     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
41     @Nullable
42     public LinkAddress ipAddress;
43     /** @hide */
44     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
45     @Nullable
46     public InetAddress gateway;
47     /** @hide */
48     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
49     @NonNull
50     public final ArrayList<InetAddress> dnsServers;
51     /** @hide */
52     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
53     @Nullable
54     public String domains;
55 
56     /** @hide */
57     @SystemApi
StaticIpConfiguration()58     public StaticIpConfiguration() {
59         dnsServers = new ArrayList<>();
60     }
61 
62     /** @hide */
63     @SystemApi
StaticIpConfiguration(@ullable StaticIpConfiguration source)64     public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
65         this();
66         if (source != null) {
67             // All of these except dnsServers are immutable, so no need to make copies.
68             ipAddress = source.ipAddress;
69             gateway = source.gateway;
70             dnsServers.addAll(source.dnsServers);
71             domains = source.domains;
72         }
73     }
74 
75     /** @hide */
76     @SystemApi
clear()77     public void clear() {
78         ipAddress = null;
79         gateway = null;
80         dnsServers.clear();
81         domains = null;
82     }
83 
84     /**
85      * Get the static IP address included in the configuration.
86      */
getIpAddress()87     public @NonNull LinkAddress getIpAddress() {
88         return ipAddress;
89     }
90 
91     /**
92      * Get the gateway included in the configuration.
93      */
getGateway()94     public @Nullable InetAddress getGateway() {
95         return gateway;
96     }
97 
98     /**
99      * Get the DNS servers included in the configuration.
100      */
getDnsServers()101     public @NonNull List<InetAddress> getDnsServers() {
102         return dnsServers;
103     }
104 
105     /**
106      * Get a {@link String} containing the comma separated domains to search when resolving host
107      * names on this link, in priority order.
108      */
getDomains()109     public @Nullable String getDomains() {
110         return domains;
111     }
112 
113     /**
114      * Helper class to build a new instance of {@link StaticIpConfiguration}.
115      */
116     public static final class Builder {
117         private LinkAddress mIpAddress;
118         private InetAddress mGateway;
119         private Iterable<InetAddress> mDnsServers;
120         private String mDomains;
121 
122         /**
123          * Set the IP address to be included in the configuration.
124          *
125          * @return The {@link Builder} for chaining.
126          */
setIpAddress(@onNull LinkAddress ipAddress)127         public @NonNull Builder setIpAddress(@NonNull LinkAddress ipAddress) {
128             if (ipAddress != null && !(ipAddress.getAddress() instanceof Inet4Address)) {
129                 throw new IllegalArgumentException(
130                         "Only IPv4 addresses can be used for the IP configuration");
131             }
132             mIpAddress = ipAddress;
133             return this;
134         }
135 
136         /**
137          * Set the address of the gateway to be included in the configuration; null by default.
138          * @return The {@link Builder} for chaining.
139          */
setGateway(@ullable InetAddress gateway)140         public @NonNull Builder setGateway(@Nullable InetAddress gateway) {
141             if (gateway != null && !(gateway instanceof Inet4Address)) {
142                 throw new IllegalArgumentException(
143                         "Only IPv4 addresses can be used for the gateway configuration");
144             }
145             mGateway = gateway;
146             return this;
147         }
148 
149         /**
150          * Set the addresses of the DNS servers included in the configuration; empty by default.
151          * @return The {@link Builder} for chaining.
152          */
setDnsServers(@onNull Iterable<InetAddress> dnsServers)153         public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
154             Objects.requireNonNull(dnsServers);
155             for (InetAddress inetAddress: dnsServers) {
156                 if (!(inetAddress instanceof Inet4Address)) {
157                     throw new IllegalArgumentException(
158                             "Only IPv4 addresses can be used for the DNS server configuration");
159                 }
160             }
161             mDnsServers = dnsServers;
162             return this;
163         }
164 
165         /**
166          * Sets the DNS domain search path to be used on the link; null by default.
167          * @param newDomains A {@link String} containing the comma separated domains to search when
168          *                   resolving host names on this link, in priority order.
169          * @return The {@link Builder} for chaining.
170          */
setDomains(@ullable String newDomains)171         public @NonNull Builder setDomains(@Nullable String newDomains) {
172             mDomains = newDomains;
173             return this;
174         }
175 
176         /**
177          * Create a {@link StaticIpConfiguration} from the parameters in this {@link Builder}.
178          * @return The newly created StaticIpConfiguration.
179          * @throws IllegalArgumentException if an invalid configuration is attempted, e.g.
180          * if an IP Address was not configured via {@link #setIpAddress(LinkAddress)}.
181          */
build()182         public @NonNull StaticIpConfiguration build() {
183             final StaticIpConfiguration config = new StaticIpConfiguration();
184             config.ipAddress = mIpAddress;
185             config.gateway = mGateway;
186             if (mDnsServers != null) {
187                 for (InetAddress server : mDnsServers) {
188                     config.dnsServers.add(server);
189                 }
190             }
191             config.domains = mDomains;
192             return config;
193         }
194     }
195 
196     /**
197      * Add a DNS server to this configuration.
198      * @hide
199      */
200     @SystemApi
addDnsServer(@onNull InetAddress server)201     public void addDnsServer(@NonNull InetAddress server) {
202         dnsServers.add(server);
203     }
204 
205     /**
206      * Returns the network routes specified by this object. Will typically include a
207      * directly-connected route for the IP address's local subnet and a default route.
208      * @param iface Interface to include in the routes.
209      * @hide
210      */
211     @SystemApi
getRoutes(@ullable String iface)212     public @NonNull List<RouteInfo> getRoutes(@Nullable String iface) {
213         List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
214         if (ipAddress != null) {
215             RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
216             routes.add(connectedRoute);
217             // If the default gateway is not covered by the directly-connected route, also add a
218             // host route to the gateway as well. This configuration is arguably invalid, but it
219             // used to work in K and earlier, and other OSes appear to accept it.
220             if (gateway != null && !connectedRoute.matches(gateway)) {
221                 routes.add(RouteInfo.makeHostRoute(gateway, iface));
222             }
223         }
224         if (gateway != null) {
225             routes.add(new RouteInfo((IpPrefix) null, gateway, iface));
226         }
227         return routes;
228     }
229 
230     /**
231      * Returns a LinkProperties object expressing the data in this object. Note that the information
232      * contained in the LinkProperties will not be a complete picture of the link's configuration,
233      * because any configuration information that is obtained dynamically by the network (e.g.,
234      * IPv6 configuration) will not be included.
235      * @hide
236      */
toLinkProperties(String iface)237     public @NonNull LinkProperties toLinkProperties(String iface) {
238         LinkProperties lp = new LinkProperties();
239         lp.setInterfaceName(iface);
240         if (ipAddress != null) {
241             lp.addLinkAddress(ipAddress);
242         }
243         for (RouteInfo route : getRoutes(iface)) {
244             lp.addRoute(route);
245         }
246         for (InetAddress dns : dnsServers) {
247             lp.addDnsServer(dns);
248         }
249         lp.setDomains(domains);
250         return lp;
251     }
252 
253     @NonNull
254     @Override
toString()255     public String toString() {
256         StringBuffer str = new StringBuffer();
257 
258         str.append("IP address ");
259         if (ipAddress != null ) str.append(ipAddress).append(" ");
260 
261         str.append("Gateway ");
262         if (gateway != null) str.append(gateway.getHostAddress()).append(" ");
263 
264         str.append(" DNS servers: [");
265         for (InetAddress dnsServer : dnsServers) {
266             str.append(" ").append(dnsServer.getHostAddress());
267         }
268 
269         str.append(" ] Domains ");
270         if (domains != null) str.append(domains);
271         return str.toString();
272     }
273 
274     @Override
hashCode()275     public int hashCode() {
276         int result = 13;
277         result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
278         result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
279         result = 47 * result + (domains == null ? 0 : domains.hashCode());
280         result = 47 * result + dnsServers.hashCode();
281         return result;
282     }
283 
284     @Override
equals(@ullable Object obj)285     public boolean equals(@Nullable Object obj) {
286         if (this == obj) return true;
287 
288         if (!(obj instanceof StaticIpConfiguration)) return false;
289 
290         StaticIpConfiguration other = (StaticIpConfiguration) obj;
291 
292         return other != null &&
293                 Objects.equals(ipAddress, other.ipAddress) &&
294                 Objects.equals(gateway, other.gateway) &&
295                 dnsServers.equals(other.dnsServers) &&
296                 Objects.equals(domains, other.domains);
297     }
298 
299     /** Implement the Parcelable interface */
300     public static final @android.annotation.NonNull Creator<StaticIpConfiguration> CREATOR =
301         new Creator<StaticIpConfiguration>() {
302             public StaticIpConfiguration createFromParcel(Parcel in) {
303                 return readFromParcel(in);
304             }
305 
306             public StaticIpConfiguration[] newArray(int size) {
307                 return new StaticIpConfiguration[size];
308             }
309         };
310 
311     /** Implement the Parcelable interface */
312     @Override
describeContents()313     public int describeContents() {
314         return 0;
315     }
316 
317     /** Implement the Parcelable interface */
318     @Override
writeToParcel(@onNull Parcel dest, int flags)319     public void writeToParcel(@NonNull Parcel dest, int flags) {
320         dest.writeParcelable(ipAddress, flags);
321         InetAddressUtils.parcelInetAddress(dest, gateway, flags);
322         dest.writeInt(dnsServers.size());
323         for (InetAddress dnsServer : dnsServers) {
324             InetAddressUtils.parcelInetAddress(dest, dnsServer, flags);
325         }
326         dest.writeString(domains);
327     }
328 
329     /** @hide */
readFromParcel(Parcel in)330     public static @NonNull StaticIpConfiguration readFromParcel(Parcel in) {
331         final StaticIpConfiguration s = new StaticIpConfiguration();
332         s.ipAddress = in.readParcelable(null);
333         s.gateway = InetAddressUtils.unparcelInetAddress(in);
334         s.dnsServers.clear();
335         int size = in.readInt();
336         for (int i = 0; i < size; i++) {
337             s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in));
338         }
339         s.domains = in.readString();
340         return s;
341     }
342 }
343