blob: 7904f7a4ec17dc83d11e17359110447271aa7f1d [file] [log] [blame]
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +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
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.SystemApi;
22import android.compat.annotation.UnsupportedAppUsage;
23import android.os.Build;
24import android.os.Parcel;
25import android.os.Parcelable;
26
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +090027import com.android.net.module.util.InetAddressUtils;
28
29import java.net.InetAddress;
30import java.util.ArrayList;
31import java.util.List;
32import 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
54public 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
72 public StaticIpConfiguration() {
73 dnsServers = new ArrayList<>();
74 }
75
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
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 */
97 public @Nullable LinkAddress getIpAddress() {
98 return ipAddress;
99 }
100
101 /**
102 * Get the gateway included in the configuration.
103 */
104 public @Nullable InetAddress getGateway() {
105 return gateway;
106 }
107
108 /**
109 * Get the DNS servers included in the configuration.
110 */
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 */
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 */
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 VAN28028e52021-03-15 07:31:54 +0000155 Objects.requireNonNull(dnsServers);
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +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;
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 */
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 */
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 */
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
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
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
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
302 public int describeContents() {
303 return 0;
304 }
305
306 /** Implement the Parcelable interface */
307 @Override
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 */
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}