blob: 050fcfa2527ad9553a5b7ae5662d363895ad301d [file] [log] [blame]
Lorenzo Colitti0a82e802014-07-31 00:48:01 +09001/*
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
17package android.net;
18
paulhu79b380c2019-03-15 17:17:02 +080019import android.annotation.NonNull;
20import android.annotation.Nullable;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090021import android.annotation.SystemApi;
22import android.annotation.TestApi;
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010023import android.annotation.UnsupportedAppUsage;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090024import android.net.shared.InetAddressUtils;
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090025import android.os.Parcel;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090026import android.os.Parcelable;
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090027
28import java.net.InetAddress;
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090029import java.util.ArrayList;
30import java.util.List;
31import java.util.Objects;
32
33/**
34 * Class that describes static IP configuration.
35 *
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090036 * <p>This class is different from {@link LinkProperties} because it represents
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090037 * configuration intent. The general contract is that if we can represent
38 * a configuration here, then we should be able to configure it on a network.
39 * The intent is that it closely match the UI we have for configuring networks.
40 *
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090041 * <p>In contrast, {@link LinkProperties} represents current state. It is much more
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090042 * expressive. For example, it supports multiple IP addresses, multiple routes,
43 * stacked interfaces, and so on. Because LinkProperties is so expressive,
44 * using it to represent configuration intent as well as current state causes
45 * problems. For example, we could unknowingly save a configuration that we are
46 * not in fact capable of applying, or we could save a configuration that the
47 * UI cannot display, which has the potential for malicious code to hide
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090048 * hostile or unexpected configuration from the user.
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090049 *
50 * @hide
51 */
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090052@SystemApi
53@TestApi
54public final class StaticIpConfiguration implements Parcelable {
55 /** @hide */
Chalard Jean7ef65fb2019-05-27 04:33:13 -070056 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080057 @Nullable
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090058 public LinkAddress ipAddress;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090059 /** @hide */
Chalard Jeandf1ac252019-05-22 02:42:25 -070060 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080061 @Nullable
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090062 public InetAddress gateway;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090063 /** @hide */
Chalard Jeandf1ac252019-05-22 02:42:25 -070064 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080065 @NonNull
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090066 public final ArrayList<InetAddress> dnsServers;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090067 /** @hide */
Chalard Jeandf1ac252019-05-22 02:42:25 -070068 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080069 @Nullable
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090070 public String domains;
71
72 public StaticIpConfiguration() {
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090073 dnsServers = new ArrayList<>();
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090074 }
75
paulhu79b380c2019-03-15 17:17:02 +080076 public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090077 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
87 public void clear() {
88 ipAddress = null;
89 gateway = null;
90 dnsServers.clear();
91 domains = null;
92 }
93
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090094 /**
95 * Get the static IP address included in the configuration.
96 */
paulhu79b380c2019-03-15 17:17:02 +080097 public @Nullable LinkAddress getIpAddress() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090098 return ipAddress;
99 }
100
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900101 /**
102 * Get the gateway included in the configuration.
103 */
paulhu79b380c2019-03-15 17:17:02 +0800104 public @Nullable InetAddress getGateway() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900105 return gateway;
106 }
107
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900108 /**
109 * Get the DNS servers included in the configuration.
110 */
paulhu79b380c2019-03-15 17:17:02 +0800111 public @NonNull List<InetAddress> getDnsServers() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900112 return dnsServers;
113 }
114
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900115 /**
116 * Get a {@link String} listing in priority order of the comma separated domains to search when
117 * resolving host names on the link.
118 */
paulhu79b380c2019-03-15 17:17:02 +0800119 public @Nullable String getDomains() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900120 return domains;
121 }
122
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900123 /**
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 */
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 */
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 */
154 public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
155 mDnsServers = dnsServers;
156 return this;
157 }
158
159 /**
160 * Sets the DNS domain search path to be used on the link; null by default.
161 * @param newDomains A {@link String} containing the comma separated domains to search when
162 * resolving host names on this link, in priority order.
163 * @return The {@link Builder} for chaining.
164 */
165 public @NonNull Builder setDomains(@Nullable String newDomains) {
166 mDomains = newDomains;
167 return this;
168 }
169
170 /**
171 * Create a {@link StaticIpConfiguration} from the parameters in this {@link Builder}.
172 * @return The newly created StaticIpConfiguration.
173 */
174 public @NonNull StaticIpConfiguration build() {
175 final StaticIpConfiguration config = new StaticIpConfiguration();
176 config.ipAddress = mIpAddress;
177 config.gateway = mGateway;
178 for (InetAddress server : mDnsServers) {
179 config.dnsServers.add(server);
180 }
181 config.domains = mDomains;
182 return config;
183 }
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900184 }
185
186 /**
187 * Add a DNS server to this configuration.
188 */
paulhu79b380c2019-03-15 17:17:02 +0800189 public void addDnsServer(@NonNull InetAddress server) {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900190 dnsServers.add(server);
191 }
192
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900193 /**
194 * Returns the network routes specified by this object. Will typically include a
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900195 * directly-connected route for the IP address's local subnet and a default route.
196 * @param iface Interface to include in the routes.
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900197 */
Remi NGUYEN VAN45ecef32019-03-25 16:41:08 +0900198 public @NonNull List<RouteInfo> getRoutes(@Nullable String iface) {
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900199 List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900200 if (ipAddress != null) {
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900201 RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
202 routes.add(connectedRoute);
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900203 // If the default gateway is not covered by the directly-connected route, also add a
204 // host route to the gateway as well. This configuration is arguably invalid, but it
205 // used to work in K and earlier, and other OSes appear to accept it.
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900206 if (gateway != null && !connectedRoute.matches(gateway)) {
207 routes.add(RouteInfo.makeHostRoute(gateway, iface));
208 }
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900209 }
210 if (gateway != null) {
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900211 routes.add(new RouteInfo((IpPrefix) null, gateway, iface));
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900212 }
213 return routes;
214 }
215
216 /**
217 * Returns a LinkProperties object expressing the data in this object. Note that the information
218 * contained in the LinkProperties will not be a complete picture of the link's configuration,
219 * because any configuration information that is obtained dynamically by the network (e.g.,
220 * IPv6 configuration) will not be included.
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900221 * @hide
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900222 */
paulhu79b380c2019-03-15 17:17:02 +0800223 public @NonNull LinkProperties toLinkProperties(String iface) {
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900224 LinkProperties lp = new LinkProperties();
225 lp.setInterfaceName(iface);
226 if (ipAddress != null) {
227 lp.addLinkAddress(ipAddress);
228 }
229 for (RouteInfo route : getRoutes(iface)) {
230 lp.addRoute(route);
231 }
232 for (InetAddress dns : dnsServers) {
233 lp.addDnsServer(dns);
234 }
Paul Jensenb3b70972014-11-05 09:35:26 -0500235 lp.setDomains(domains);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900236 return lp;
237 }
238
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900239 @Override
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900240 public String toString() {
241 StringBuffer str = new StringBuffer();
242
243 str.append("IP address ");
244 if (ipAddress != null ) str.append(ipAddress).append(" ");
245
246 str.append("Gateway ");
247 if (gateway != null) str.append(gateway.getHostAddress()).append(" ");
248
249 str.append(" DNS servers: [");
250 for (InetAddress dnsServer : dnsServers) {
251 str.append(" ").append(dnsServer.getHostAddress());
252 }
253
Erik Klineacda32c2016-05-13 17:50:25 +0900254 str.append(" ] Domains ");
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900255 if (domains != null) str.append(domains);
256 return str.toString();
257 }
258
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900259 @Override
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900260 public int hashCode() {
261 int result = 13;
262 result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
263 result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
264 result = 47 * result + (domains == null ? 0 : domains.hashCode());
265 result = 47 * result + dnsServers.hashCode();
266 return result;
267 }
268
269 @Override
270 public boolean equals(Object obj) {
271 if (this == obj) return true;
272
273 if (!(obj instanceof StaticIpConfiguration)) return false;
274
275 StaticIpConfiguration other = (StaticIpConfiguration) obj;
276
277 return other != null &&
278 Objects.equals(ipAddress, other.ipAddress) &&
279 Objects.equals(gateway, other.gateway) &&
280 dnsServers.equals(other.dnsServers) &&
281 Objects.equals(domains, other.domains);
282 }
283
284 /** Implement the Parcelable interface */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700285 public static final @android.annotation.NonNull Creator<StaticIpConfiguration> CREATOR =
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900286 new Creator<StaticIpConfiguration>() {
287 public StaticIpConfiguration createFromParcel(Parcel in) {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900288 return readFromParcel(in);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900289 }
290
291 public StaticIpConfiguration[] newArray(int size) {
292 return new StaticIpConfiguration[size];
293 }
294 };
295
296 /** Implement the Parcelable interface */
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900297 @Override
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900298 public int describeContents() {
299 return 0;
300 }
301
302 /** Implement the Parcelable interface */
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900303 @Override
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900304 public void writeToParcel(Parcel dest, int flags) {
305 dest.writeParcelable(ipAddress, flags);
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900306 InetAddressUtils.parcelInetAddress(dest, gateway, flags);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900307 dest.writeInt(dnsServers.size());
308 for (InetAddress dnsServer : dnsServers) {
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900309 InetAddressUtils.parcelInetAddress(dest, dnsServer, flags);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900310 }
Lorenzo Colittid0cc5442015-01-29 17:10:52 +0900311 dest.writeString(domains);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900312 }
313
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900314 /** @hide */
315 public static StaticIpConfiguration readFromParcel(Parcel in) {
316 final StaticIpConfiguration s = new StaticIpConfiguration();
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900317 s.ipAddress = in.readParcelable(null);
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900318 s.gateway = InetAddressUtils.unparcelInetAddress(in);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900319 s.dnsServers.clear();
320 int size = in.readInt();
321 for (int i = 0; i < size; i++) {
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900322 s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in));
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900323 }
Lorenzo Colittid0cc5442015-01-29 17:10:52 +0900324 s.domains = in.readString();
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900325 return s;
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900326 }
327}