blob: 7904f7a4ec17dc83d11e17359110447271aa7f1d [file] [log] [blame]
Lorenzo Colittief734f82014-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
paulhu38068532019-03-15 17:17:02 +080019import android.annotation.NonNull;
20import android.annotation.Nullable;
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090021import android.annotation.SystemApi;
Artur Satayev9c2add62019-12-10 17:47:52 +000022import android.compat.annotation.UnsupportedAppUsage;
Mathew Inwoode1a17ba2020-11-04 09:29:36 +000023import android.os.Build;
Lorenzo Colittief734f82014-07-31 00:48:01 +090024import android.os.Parcel;
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090025import android.os.Parcelable;
Lorenzo Colittief734f82014-07-31 00:48:01 +090026
Chalard Jean059356d2020-07-31 20:00:30 +090027import com.android.net.module.util.InetAddressUtils;
Roshan Pius32b898b2019-11-14 12:20:41 -080028
Lorenzo Colittief734f82014-07-31 00:48:01 +090029import java.net.InetAddress;
Lorenzo Colittief734f82014-07-31 00:48:01 +090030import java.util.ArrayList;
31import java.util.List;
32import java.util.Objects;
33
34/**
35 * Class that describes static IP configuration.
36 *
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +090037 * <p>This class is different from {@link LinkProperties} because it represents
Lorenzo Colittief734f82014-07-31 00:48:01 +090038 * 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 *
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +090042 * <p>In contrast, {@link LinkProperties} represents current state. It is much more
Lorenzo Colittief734f82014-07-31 00:48:01 +090043 * 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
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +090049 * hostile or unexpected configuration from the user.
Lorenzo Colittief734f82014-07-31 00:48:01 +090050 *
51 * @hide
52 */
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090053@SystemApi
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090054public final class StaticIpConfiguration implements Parcelable {
55 /** @hide */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +000056 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu38068532019-03-15 17:17:02 +080057 @Nullable
Lorenzo Colittief734f82014-07-31 00:48:01 +090058 public LinkAddress ipAddress;
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090059 /** @hide */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +000060 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu38068532019-03-15 17:17:02 +080061 @Nullable
Lorenzo Colittief734f82014-07-31 00:48:01 +090062 public InetAddress gateway;
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090063 /** @hide */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +000064 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu38068532019-03-15 17:17:02 +080065 @NonNull
Lorenzo Colittief734f82014-07-31 00:48:01 +090066 public final ArrayList<InetAddress> dnsServers;
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090067 /** @hide */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +000068 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu38068532019-03-15 17:17:02 +080069 @Nullable
Lorenzo Colittief734f82014-07-31 00:48:01 +090070 public String domains;
71
72 public StaticIpConfiguration() {
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +090073 dnsServers = new ArrayList<>();
Lorenzo Colittief734f82014-07-31 00:48:01 +090074 }
75
paulhu38068532019-03-15 17:17:02 +080076 public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
Lorenzo Colittief734f82014-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 VAN04c58fe2019-04-01 17:09:05 +090094 /**
95 * Get the static IP address included in the configuration.
96 */
paulhu38068532019-03-15 17:17:02 +080097 public @Nullable LinkAddress getIpAddress() {
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +090098 return ipAddress;
99 }
100
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900101 /**
102 * Get the gateway included in the configuration.
103 */
paulhu38068532019-03-15 17:17:02 +0800104 public @Nullable InetAddress getGateway() {
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900105 return gateway;
106 }
107
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900108 /**
109 * Get the DNS servers included in the configuration.
110 */
paulhu38068532019-03-15 17:17:02 +0800111 public @NonNull List<InetAddress> getDnsServers() {
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900112 return dnsServers;
113 }
114
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900115 /**
Remi NGUYEN VAN9ed32082019-04-03 15:54:25 +0900116 * Get a {@link String} containing the comma separated domains to search when resolving host
117 * names on this link, in priority order.
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900118 */
paulhu38068532019-03-15 17:17:02 +0800119 public @Nullable String getDomains() {
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900120 return domains;
121 }
122
Remi NGUYEN VAN04c58fe2019-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) {
Remi NGUYEN VAN81f68422021-03-15 07:31:54 +0000155 Objects.requireNonNull(dnsServers);
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900156 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 */
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 */
175 public @NonNull StaticIpConfiguration build() {
176 final StaticIpConfiguration config = new StaticIpConfiguration();
177 config.ipAddress = mIpAddress;
178 config.gateway = mGateway;
Roshan Pius32b898b2019-11-14 12:20:41 -0800179 if (mDnsServers != null) {
180 for (InetAddress server : mDnsServers) {
181 config.dnsServers.add(server);
182 }
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900183 }
184 config.domains = mDomains;
185 return config;
186 }
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900187 }
188
189 /**
190 * Add a DNS server to this configuration.
191 */
paulhu38068532019-03-15 17:17:02 +0800192 public void addDnsServer(@NonNull InetAddress server) {
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900193 dnsServers.add(server);
194 }
195
Lorenzo Colittief734f82014-07-31 00:48:01 +0900196 /**
197 * Returns the network routes specified by this object. Will typically include a
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900198 * directly-connected route for the IP address's local subnet and a default route.
199 * @param iface Interface to include in the routes.
Lorenzo Colittief734f82014-07-31 00:48:01 +0900200 */
Remi NGUYEN VANbe381ab2019-03-25 16:41:08 +0900201 public @NonNull List<RouteInfo> getRoutes(@Nullable String iface) {
Lorenzo Colittic915d4c2015-01-20 15:53:02 +0900202 List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
Lorenzo Colittief734f82014-07-31 00:48:01 +0900203 if (ipAddress != null) {
Lorenzo Colittic915d4c2015-01-20 15:53:02 +0900204 RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
205 routes.add(connectedRoute);
Remi NGUYEN VAN04c58fe2019-04-01 17:09:05 +0900206 // 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.
Lorenzo Colittic915d4c2015-01-20 15:53:02 +0900209 if (gateway != null && !connectedRoute.matches(gateway)) {
210 routes.add(RouteInfo.makeHostRoute(gateway, iface));
211 }
Lorenzo Colittief734f82014-07-31 00:48:01 +0900212 }
213 if (gateway != null) {
Lorenzo Colittic915d4c2015-01-20 15:53:02 +0900214 routes.add(new RouteInfo((IpPrefix) null, gateway, iface));
Lorenzo Colittief734f82014-07-31 00:48:01 +0900215 }
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.
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900224 * @hide
Lorenzo Colittief734f82014-07-31 00:48:01 +0900225 */
paulhu38068532019-03-15 17:17:02 +0800226 public @NonNull LinkProperties toLinkProperties(String iface) {
Lorenzo Colittief734f82014-07-31 00:48:01 +0900227 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 }
Paul Jensen99366a82014-11-05 09:35:26 -0500238 lp.setDomains(domains);
Lorenzo Colittief734f82014-07-31 00:48:01 +0900239 return lp;
240 }
241
Aurimas Liutikas8fae99352019-08-28 13:01:05 -0700242 @NonNull
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900243 @Override
Lorenzo Colittief734f82014-07-31 00:48:01 +0900244 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
Erik Kline7b0a5812016-05-13 17:50:25 +0900258 str.append(" ] Domains ");
Lorenzo Colittief734f82014-07-31 00:48:01 +0900259 if (domains != null) str.append(domains);
260 return str.toString();
261 }
262
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900263 @Override
Lorenzo Colittief734f82014-07-31 00:48:01 +0900264 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
Aurimas Liutikas8fae99352019-08-28 13:01:05 -0700274 public boolean equals(@Nullable Object obj) {
Lorenzo Colittief734f82014-07-31 00:48:01 +0900275 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 */
Jeff Sharkeyf8525282019-02-28 12:06:45 -0700289 public static final @android.annotation.NonNull Creator<StaticIpConfiguration> CREATOR =
Lorenzo Colittief734f82014-07-31 00:48:01 +0900290 new Creator<StaticIpConfiguration>() {
291 public StaticIpConfiguration createFromParcel(Parcel in) {
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900292 return readFromParcel(in);
Lorenzo Colittief734f82014-07-31 00:48:01 +0900293 }
294
295 public StaticIpConfiguration[] newArray(int size) {
296 return new StaticIpConfiguration[size];
297 }
298 };
299
300 /** Implement the Parcelable interface */
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900301 @Override
Lorenzo Colittief734f82014-07-31 00:48:01 +0900302 public int describeContents() {
303 return 0;
304 }
305
306 /** Implement the Parcelable interface */
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900307 @Override
Lorenzo Colittief734f82014-07-31 00:48:01 +0900308 public void writeToParcel(Parcel dest, int flags) {
309 dest.writeParcelable(ipAddress, flags);
Remi NGUYEN VAN6e82be42019-01-29 15:38:52 +0900310 InetAddressUtils.parcelInetAddress(dest, gateway, flags);
Lorenzo Colittief734f82014-07-31 00:48:01 +0900311 dest.writeInt(dnsServers.size());
312 for (InetAddress dnsServer : dnsServers) {
Remi NGUYEN VAN6e82be42019-01-29 15:38:52 +0900313 InetAddressUtils.parcelInetAddress(dest, dnsServer, flags);
Lorenzo Colittief734f82014-07-31 00:48:01 +0900314 }
Lorenzo Colitti68a1a342015-01-29 17:10:52 +0900315 dest.writeString(domains);
Lorenzo Colittief734f82014-07-31 00:48:01 +0900316 }
317
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900318 /** @hide */
319 public static StaticIpConfiguration readFromParcel(Parcel in) {
320 final StaticIpConfiguration s = new StaticIpConfiguration();
Lorenzo Colittief734f82014-07-31 00:48:01 +0900321 s.ipAddress = in.readParcelable(null);
Remi NGUYEN VAN6e82be42019-01-29 15:38:52 +0900322 s.gateway = InetAddressUtils.unparcelInetAddress(in);
Lorenzo Colittief734f82014-07-31 00:48:01 +0900323 s.dnsServers.clear();
324 int size = in.readInt();
325 for (int i = 0; i < size; i++) {
Remi NGUYEN VAN6e82be42019-01-29 15:38:52 +0900326 s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in));
Lorenzo Colittief734f82014-07-31 00:48:01 +0900327 }
Lorenzo Colitti68a1a342015-01-29 17:10:52 +0900328 s.domains = in.readString();
Remi NGUYEN VAN8bd18cf2019-01-28 13:28:35 +0900329 return s;
Lorenzo Colittief734f82014-07-31 00:48:01 +0900330 }
331}