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