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