blob: f24a9bd5303990d1e93e25895c3be29aa4bda612 [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;
Artur Satayev26958002019-12-10 17:47:52 +000023import android.compat.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
Roshan Piusae076892019-11-14 12:20:41 -080028import com.android.internal.util.Preconditions;
29
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090030import java.net.InetAddress;
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090031import java.util.ArrayList;
32import java.util.List;
33import java.util.Objects;
34
35/**
36 * Class that describes static IP configuration.
37 *
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090038 * <p>This class is different from {@link LinkProperties} because it represents
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090039 * configuration intent. The general contract is that if we can represent
40 * a configuration here, then we should be able to configure it on a network.
41 * The intent is that it closely match the UI we have for configuring networks.
42 *
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090043 * <p>In contrast, {@link LinkProperties} represents current state. It is much more
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090044 * expressive. For example, it supports multiple IP addresses, multiple routes,
45 * stacked interfaces, and so on. Because LinkProperties is so expressive,
46 * using it to represent configuration intent as well as current state causes
47 * problems. For example, we could unknowingly save a configuration that we are
48 * not in fact capable of applying, or we could save a configuration that the
49 * UI cannot display, which has the potential for malicious code to hide
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090050 * hostile or unexpected configuration from the user.
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090051 *
52 * @hide
53 */
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090054@SystemApi
55@TestApi
56public final class StaticIpConfiguration implements Parcelable {
57 /** @hide */
Chalard Jean25f18282019-05-22 22:01:23 +090058 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080059 @Nullable
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090060 public LinkAddress ipAddress;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090061 /** @hide */
Chalard Jean9c305302019-05-20 15:45:04 +090062 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080063 @Nullable
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090064 public InetAddress gateway;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090065 /** @hide */
Chalard Jean9c305302019-05-20 15:45:04 +090066 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080067 @NonNull
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090068 public final ArrayList<InetAddress> dnsServers;
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +090069 /** @hide */
Chalard Jean9c305302019-05-20 15:45:04 +090070 @UnsupportedAppUsage
paulhu79b380c2019-03-15 17:17:02 +080071 @Nullable
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090072 public String domains;
73
74 public StaticIpConfiguration() {
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090075 dnsServers = new ArrayList<>();
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090076 }
77
paulhu79b380c2019-03-15 17:17:02 +080078 public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090079 this();
80 if (source != null) {
81 // All of these except dnsServers are immutable, so no need to make copies.
82 ipAddress = source.ipAddress;
83 gateway = source.gateway;
84 dnsServers.addAll(source.dnsServers);
85 domains = source.domains;
86 }
87 }
88
89 public void clear() {
90 ipAddress = null;
91 gateway = null;
92 dnsServers.clear();
93 domains = null;
94 }
95
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +090096 /**
97 * Get the static IP address included in the configuration.
98 */
paulhu79b380c2019-03-15 17:17:02 +080099 public @Nullable LinkAddress getIpAddress() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900100 return ipAddress;
101 }
102
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900103 /**
104 * Get the gateway included in the configuration.
105 */
paulhu79b380c2019-03-15 17:17:02 +0800106 public @Nullable InetAddress getGateway() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900107 return gateway;
108 }
109
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900110 /**
111 * Get the DNS servers included in the configuration.
112 */
paulhu79b380c2019-03-15 17:17:02 +0800113 public @NonNull List<InetAddress> getDnsServers() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900114 return dnsServers;
115 }
116
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900117 /**
Remi NGUYEN VAN28aef542019-04-03 15:54:25 +0900118 * Get a {@link String} containing the comma separated domains to search when resolving host
119 * names on this link, in priority order.
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900120 */
paulhu79b380c2019-03-15 17:17:02 +0800121 public @Nullable String getDomains() {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900122 return domains;
123 }
124
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900125 /**
126 * Helper class to build a new instance of {@link StaticIpConfiguration}.
127 */
128 public static final class Builder {
129 private LinkAddress mIpAddress;
130 private InetAddress mGateway;
131 private Iterable<InetAddress> mDnsServers;
132 private String mDomains;
133
134 /**
135 * Set the IP address to be included in the configuration; null by default.
136 * @return The {@link Builder} for chaining.
137 */
138 public @NonNull Builder setIpAddress(@Nullable LinkAddress ipAddress) {
139 mIpAddress = ipAddress;
140 return this;
141 }
142
143 /**
144 * Set the address of the gateway to be included in the configuration; null by default.
145 * @return The {@link Builder} for chaining.
146 */
147 public @NonNull Builder setGateway(@Nullable InetAddress gateway) {
148 mGateway = gateway;
149 return this;
150 }
151
152 /**
153 * Set the addresses of the DNS servers included in the configuration; empty by default.
154 * @return The {@link Builder} for chaining.
155 */
156 public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
Roshan Piusae076892019-11-14 12:20:41 -0800157 Preconditions.checkNotNull(dnsServers);
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900158 mDnsServers = dnsServers;
159 return this;
160 }
161
162 /**
163 * Sets the DNS domain search path to be used on the link; null by default.
164 * @param newDomains A {@link String} containing the comma separated domains to search when
165 * resolving host names on this link, in priority order.
166 * @return The {@link Builder} for chaining.
167 */
168 public @NonNull Builder setDomains(@Nullable String newDomains) {
169 mDomains = newDomains;
170 return this;
171 }
172
173 /**
174 * Create a {@link StaticIpConfiguration} from the parameters in this {@link Builder}.
175 * @return The newly created StaticIpConfiguration.
176 */
177 public @NonNull StaticIpConfiguration build() {
178 final StaticIpConfiguration config = new StaticIpConfiguration();
179 config.ipAddress = mIpAddress;
180 config.gateway = mGateway;
Roshan Piusae076892019-11-14 12:20:41 -0800181 if (mDnsServers != null) {
182 for (InetAddress server : mDnsServers) {
183 config.dnsServers.add(server);
184 }
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900185 }
186 config.domains = mDomains;
187 return config;
188 }
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900189 }
190
191 /**
192 * Add a DNS server to this configuration.
193 */
paulhu79b380c2019-03-15 17:17:02 +0800194 public void addDnsServer(@NonNull InetAddress server) {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900195 dnsServers.add(server);
196 }
197
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900198 /**
199 * Returns the network routes specified by this object. Will typically include a
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900200 * directly-connected route for the IP address's local subnet and a default route.
201 * @param iface Interface to include in the routes.
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900202 */
Remi NGUYEN VAN45ecef32019-03-25 16:41:08 +0900203 public @NonNull List<RouteInfo> getRoutes(@Nullable String iface) {
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900204 List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900205 if (ipAddress != null) {
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900206 RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
207 routes.add(connectedRoute);
Remi NGUYEN VAN59a06a02019-04-01 17:09:05 +0900208 // If the default gateway is not covered by the directly-connected route, also add a
209 // host route to the gateway as well. This configuration is arguably invalid, but it
210 // used to work in K and earlier, and other OSes appear to accept it.
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900211 if (gateway != null && !connectedRoute.matches(gateway)) {
212 routes.add(RouteInfo.makeHostRoute(gateway, iface));
213 }
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900214 }
215 if (gateway != null) {
Lorenzo Colitti8316b8192015-01-20 15:53:02 +0900216 routes.add(new RouteInfo((IpPrefix) null, gateway, iface));
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900217 }
218 return routes;
219 }
220
221 /**
222 * Returns a LinkProperties object expressing the data in this object. Note that the information
223 * contained in the LinkProperties will not be a complete picture of the link's configuration,
224 * because any configuration information that is obtained dynamically by the network (e.g.,
225 * IPv6 configuration) will not be included.
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900226 * @hide
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900227 */
paulhu79b380c2019-03-15 17:17:02 +0800228 public @NonNull LinkProperties toLinkProperties(String iface) {
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900229 LinkProperties lp = new LinkProperties();
230 lp.setInterfaceName(iface);
231 if (ipAddress != null) {
232 lp.addLinkAddress(ipAddress);
233 }
234 for (RouteInfo route : getRoutes(iface)) {
235 lp.addRoute(route);
236 }
237 for (InetAddress dns : dnsServers) {
238 lp.addDnsServer(dns);
239 }
Paul Jensenb3b70972014-11-05 09:35:26 -0500240 lp.setDomains(domains);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900241 return lp;
242 }
243
Aurimas Liutikas00be9512019-08-28 13:01:05 -0700244 @NonNull
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900245 @Override
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900246 public String toString() {
247 StringBuffer str = new StringBuffer();
248
249 str.append("IP address ");
250 if (ipAddress != null ) str.append(ipAddress).append(" ");
251
252 str.append("Gateway ");
253 if (gateway != null) str.append(gateway.getHostAddress()).append(" ");
254
255 str.append(" DNS servers: [");
256 for (InetAddress dnsServer : dnsServers) {
257 str.append(" ").append(dnsServer.getHostAddress());
258 }
259
Erik Klineacda32c2016-05-13 17:50:25 +0900260 str.append(" ] Domains ");
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900261 if (domains != null) str.append(domains);
262 return str.toString();
263 }
264
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900265 @Override
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900266 public int hashCode() {
267 int result = 13;
268 result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
269 result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
270 result = 47 * result + (domains == null ? 0 : domains.hashCode());
271 result = 47 * result + dnsServers.hashCode();
272 return result;
273 }
274
275 @Override
Aurimas Liutikas00be9512019-08-28 13:01:05 -0700276 public boolean equals(@Nullable Object obj) {
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900277 if (this == obj) return true;
278
279 if (!(obj instanceof StaticIpConfiguration)) return false;
280
281 StaticIpConfiguration other = (StaticIpConfiguration) obj;
282
283 return other != null &&
284 Objects.equals(ipAddress, other.ipAddress) &&
285 Objects.equals(gateway, other.gateway) &&
286 dnsServers.equals(other.dnsServers) &&
287 Objects.equals(domains, other.domains);
288 }
289
290 /** Implement the Parcelable interface */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700291 public static final @android.annotation.NonNull Creator<StaticIpConfiguration> CREATOR =
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900292 new Creator<StaticIpConfiguration>() {
293 public StaticIpConfiguration createFromParcel(Parcel in) {
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900294 return readFromParcel(in);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900295 }
296
297 public StaticIpConfiguration[] newArray(int size) {
298 return new StaticIpConfiguration[size];
299 }
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 int describeContents() {
305 return 0;
306 }
307
308 /** Implement the Parcelable interface */
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900309 @Override
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900310 public void writeToParcel(Parcel dest, int flags) {
311 dest.writeParcelable(ipAddress, flags);
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900312 InetAddressUtils.parcelInetAddress(dest, gateway, flags);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900313 dest.writeInt(dnsServers.size());
314 for (InetAddress dnsServer : dnsServers) {
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900315 InetAddressUtils.parcelInetAddress(dest, dnsServer, flags);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900316 }
Lorenzo Colittid0cc5442015-01-29 17:10:52 +0900317 dest.writeString(domains);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900318 }
319
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900320 /** @hide */
321 public static StaticIpConfiguration readFromParcel(Parcel in) {
322 final StaticIpConfiguration s = new StaticIpConfiguration();
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900323 s.ipAddress = in.readParcelable(null);
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900324 s.gateway = InetAddressUtils.unparcelInetAddress(in);
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900325 s.dnsServers.clear();
326 int size = in.readInt();
327 for (int i = 0; i < size; i++) {
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900328 s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in));
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900329 }
Lorenzo Colittid0cc5442015-01-29 17:10:52 +0900330 s.domains = in.readString();
Remi NGUYEN VANa4bcc862019-01-28 13:28:35 +0900331 return s;
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900332 }
333}