blob: 8782b33be5ed97d8a8778b8c7611dd2ded1ba517 [file] [log] [blame]
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001/*
Wink Saville17465432010-09-21 09:15:35 -07002 * Copyright (C) 2010 The Android Open Source Project
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07003 *
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
Jeff Sharkey0aef9342014-08-11 15:22:51 -070019import android.annotation.NonNull;
Jeff Sharkeyf2ceed82014-08-14 12:55:00 -070020import android.annotation.Nullable;
paulhu058120d2018-12-12 17:52:57 +080021import android.annotation.SystemApi;
Taras Antoshchuk30d41e52021-08-02 18:06:35 +020022import android.app.compat.CompatChanges;
23import android.compat.annotation.ChangeId;
24import android.compat.annotation.EnabledAfter;
Artur Satayev9c2add62019-12-10 17:47:52 +000025import android.compat.annotation.UnsupportedAppUsage;
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +000026import android.os.Build;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070027import android.os.Parcel;
Rubin Xuffd77d82017-09-05 18:40:49 +010028import android.os.Parcelable;
John Wang3e567d52011-04-04 12:35:42 -070029import android.text.TextUtils;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070030
Taras Antoshchuk30d41e52021-08-02 18:06:35 +020031import com.android.internal.annotations.VisibleForTesting;
Chalard Jean79162542020-08-19 16:07:22 +090032import com.android.net.module.util.LinkPropertiesUtils;
33
Lorenzo Colittic0803122013-03-07 10:59:25 -080034import java.net.Inet4Address;
Lorenzo Colitti09de4182013-08-08 11:00:12 +090035import java.net.Inet6Address;
Rubin Xuffd77d82017-09-05 18:40:49 +010036import java.net.InetAddress;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070037import java.net.UnknownHostException;
38import java.util.ArrayList;
39import java.util.Collection;
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -070040import java.util.Collections;
Lorenzo Colittic0803122013-03-07 10:59:25 -080041import java.util.Hashtable;
Robert Greenwalt69aceaf2014-06-06 10:30:11 -070042import java.util.List;
Lorenzo Colitti36ddd9d2014-06-12 23:10:17 +090043import java.util.Objects;
Chalard Jeand51966a2018-06-07 13:27:00 +090044import java.util.StringJoiner;
Taras Antoshchuk30d41e52021-08-02 18:06:35 +020045import java.util.stream.Collectors;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070046
47/**
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -070048 * Describes the properties of a network link.
Robert Greenwalt5c733972011-02-09 13:56:06 -080049 *
50 * A link represents a connection to a network.
51 * It may have multiple addresses and multiple gateways,
Robert Greenwalteaa84d52014-05-18 22:01:38 -070052 * multiple dns servers but only one http proxy and one
53 * network interface.
Robert Greenwalt5c733972011-02-09 13:56:06 -080054 *
Robert Greenwalteaa84d52014-05-18 22:01:38 -070055 * Note that this is just a holder of data. Modifying it
56 * does not affect live networks.
Robert Greenwalt5c733972011-02-09 13:56:06 -080057 *
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070058 */
Robert Greenwaltc4920a52014-06-12 16:24:38 -070059public final class LinkProperties implements Parcelable {
Taras Antoshchuk30d41e52021-08-02 18:06:35 +020060 /**
61 * The {@link #getRoutes()} now can contain excluded as well as included routes. Use
62 * {@link RouteInfo#getType()} to determine route type.
63 *
64 * @hide
65 */
66 @ChangeId
67 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S) // Switch to S_V2 when it is available.
68 @VisibleForTesting
69 public static final long EXCLUDED_ROUTES = 186082280;
70
Lorenzo Colittic0803122013-03-07 10:59:25 -080071 // The interface described by the network link.
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +000072 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt462e5702012-10-31 14:32:53 -070073 private String mIfaceName;
paulhucbbc3db2019-03-08 16:35:20 +080074 private final ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
75 private final ArrayList<InetAddress> mDnses = new ArrayList<>();
Hongshike2d7cf52018-06-28 20:42:19 +090076 // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service.
paulhucbbc3db2019-03-08 16:35:20 +080077 private final ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>();
78 private final ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>();
dalyk7643abc2018-01-17 14:20:55 -050079 private boolean mUsePrivateDns;
80 private String mPrivateDnsServerName;
Robert Greenwaltcd277852012-11-09 10:52:27 -080081 private String mDomains;
Chalard Jeand51966a2018-06-07 13:27:00 +090082 private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
ruibin zhangca75bc82019-05-23 19:35:30 +080083 private Inet4Address mDhcpServerAddress;
Jason Monk4d5e20f2014-04-25 15:00:09 -040084 private ProxyInfo mHttpProxy;
sy.yun4aa73922013-09-02 05:24:09 +090085 private int mMtu;
Robert Greenwaltdebf0e02014-08-06 12:00:25 -070086 // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
87 private String mTcpBufferSizes;
Lorenzo Colitti981b34f2019-01-08 09:58:59 +090088 private IpPrefix mNat64Prefix;
Valentin Iftime9fa35092019-09-24 13:32:13 +020089 private boolean mWakeOnLanSupported;
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +090090 private Uri mCaptivePortalApiUrl;
91 private CaptivePortalData mCaptivePortalData;
92
93 /**
94 * Indicates whether parceling should preserve fields that are set based on permissions of
95 * the process receiving the {@link LinkProperties}.
96 */
97 private final transient boolean mParcelSensitiveFields;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070098
w19976e714f1d2014-08-05 15:18:11 -070099 private static final int MIN_MTU = 68;
Benedict Wongf3215112020-11-19 00:17:29 -0800100
Remi NGUYEN VAN00c5e702020-11-30 16:35:43 +0900101 private static final int MIN_MTU_V6 = 1280;
Benedict Wongf3215112020-11-19 00:17:29 -0800102
w19976e714f1d2014-08-05 15:18:11 -0700103 private static final int MAX_MTU = 10000;
104
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +0900105 private static final int INET6_ADDR_LENGTH = 16;
106
Lorenzo Colittic0803122013-03-07 10:59:25 -0800107 // Stores the properties of links that are "stacked" above this link.
108 // Indexed by interface name to allow modification and to prevent duplicates being added.
Chalard Jeand51966a2018-06-07 13:27:00 +0900109 private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
Lorenzo Colittic0803122013-03-07 10:59:25 -0800110
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700111 /**
112 * @hide
113 */
Artur Satayev56cb6bb2019-11-04 17:50:59 +0000114 @UnsupportedAppUsage(implicitMember =
115 "values()[Landroid/net/LinkProperties$ProvisioningChange;")
Erik Kline04612b02015-05-21 16:15:02 +0900116 public enum ProvisioningChange {
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100117 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900118 STILL_NOT_PROVISIONED,
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100119 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900120 LOST_PROVISIONING,
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100121 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900122 GAINED_PROVISIONING,
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100123 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900124 STILL_PROVISIONED,
125 }
126
127 /**
128 * Compare the provisioning states of two LinkProperties instances.
129 *
130 * @hide
131 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000132 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Erik Kline04612b02015-05-21 16:15:02 +0900133 public static ProvisioningChange compareProvisioning(
134 LinkProperties before, LinkProperties after) {
135 if (before.isProvisioned() && after.isProvisioned()) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900136 // On dual-stack networks, DHCPv4 renewals can occasionally fail.
Erik Kline04612b02015-05-21 16:15:02 +0900137 // When this happens, IPv6-reachable services continue to function
138 // normally but IPv4-only services (naturally) fail.
139 //
140 // When an application using an IPv4-only service reports a bad
141 // network condition to the framework, attempts to re-validate
142 // the network succeed (since we support IPv6-only networks) and
143 // nothing is changed.
144 //
145 // For users, this is confusing and unexpected behaviour, and is
146 // not necessarily easy to diagnose. Therefore, we treat changing
Chalard Jeand51966a2018-06-07 13:27:00 +0900147 // from a dual-stack network to an IPv6-only network equivalent to
Erik Kline04612b02015-05-21 16:15:02 +0900148 // a total loss of provisioning.
149 //
150 // For one such example of this, see b/18867306.
151 //
Erik Klineaa8f8f32015-08-14 12:16:55 +0900152 // Additionally, losing IPv6 provisioning can result in TCP
153 // connections getting stuck until timeouts fire and other
154 // baffling failures. Therefore, loss of either IPv4 or IPv6 on a
Chalard Jeand51966a2018-06-07 13:27:00 +0900155 // previously dual-stack network is deemed a lost of provisioning.
paulhucbbc3db2019-03-08 16:35:20 +0800156 if ((before.isIpv4Provisioned() && !after.isIpv4Provisioned())
157 || (before.isIpv6Provisioned() && !after.isIpv6Provisioned())) {
Erik Kline04612b02015-05-21 16:15:02 +0900158 return ProvisioningChange.LOST_PROVISIONING;
159 }
160 return ProvisioningChange.STILL_PROVISIONED;
161 } else if (before.isProvisioned() && !after.isProvisioned()) {
162 return ProvisioningChange.LOST_PROVISIONING;
163 } else if (!before.isProvisioned() && after.isProvisioned()) {
164 return ProvisioningChange.GAINED_PROVISIONING;
165 } else { // !before.isProvisioned() && !after.isProvisioned()
166 return ProvisioningChange.STILL_NOT_PROVISIONED;
167 }
168 }
169
170 /**
paulhucbbc3db2019-03-08 16:35:20 +0800171 * Constructs a new {@code LinkProperties} with default values.
Erik Kline04612b02015-05-21 16:15:02 +0900172 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700173 public LinkProperties() {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900174 mParcelSensitiveFields = false;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700175 }
176
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700177 /**
178 * @hide
179 */
Remi NGUYEN VANd9f75862019-01-23 21:35:52 +0900180 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800181 public LinkProperties(@Nullable LinkProperties source) {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900182 this(source, false /* parcelSensitiveFields */);
183 }
184
Remi NGUYEN VAN8dd694d2020-03-16 14:48:37 +0900185 /**
186 * Create a copy of a {@link LinkProperties} that may preserve fields that were set
187 * based on the permissions of the process that originally received it.
188 *
189 * <p>By default {@link LinkProperties} does not preserve such fields during parceling, as
190 * they should not be shared outside of the process that receives them without appropriate
191 * checks.
192 * @param parcelSensitiveFields Whether the sensitive fields should be kept when parceling
193 * @hide
194 */
195 @SystemApi
Remi NGUYEN VAN8dd694d2020-03-16 14:48:37 +0900196 public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900197 mParcelSensitiveFields = parcelSensitiveFields;
198 if (source == null) return;
199 mIfaceName = source.mIfaceName;
200 mLinkAddresses.addAll(source.mLinkAddresses);
201 mDnses.addAll(source.mDnses);
202 mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
203 mUsePrivateDns = source.mUsePrivateDns;
204 mPrivateDnsServerName = source.mPrivateDnsServerName;
205 mPcscfs.addAll(source.mPcscfs);
206 mDomains = source.mDomains;
207 mRoutes.addAll(source.mRoutes);
208 mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
209 for (LinkProperties l: source.mStackedLinks.values()) {
210 addStackedLink(l);
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700211 }
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900212 setMtu(source.mMtu);
213 setDhcpServerAddress(source.getDhcpServerAddress());
214 mTcpBufferSizes = source.mTcpBufferSizes;
215 mNat64Prefix = source.mNat64Prefix;
216 mWakeOnLanSupported = source.mWakeOnLanSupported;
217 mCaptivePortalApiUrl = source.mCaptivePortalApiUrl;
218 mCaptivePortalData = source.mCaptivePortalData;
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700219 }
220
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700221 /**
222 * Sets the interface name for this link. All {@link RouteInfo} already set for this
223 * will have their interface changed to match this new value.
224 *
225 * @param iface The name of the network interface used for this link.
226 */
paulhucbbc3db2019-03-08 16:35:20 +0800227 public void setInterfaceName(@Nullable String iface) {
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700228 mIfaceName = iface;
Chalard Jeand51966a2018-06-07 13:27:00 +0900229 ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800230 for (RouteInfo route : mRoutes) {
231 newRoutes.add(routeWithInterface(route));
232 }
233 mRoutes = newRoutes;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700234 }
235
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700236 /**
237 * Gets the interface name for this link. May be {@code null} if not set.
238 *
239 * @return The interface name set for this link or {@code null}.
240 */
Jeff Sharkeyf2ceed82014-08-14 12:55:00 -0700241 public @Nullable String getInterfaceName() {
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700242 return mIfaceName;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700243 }
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700244
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700245 /**
246 * @hide
247 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800248 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800249 public @NonNull List<String> getAllInterfaceNames() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900250 List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1);
251 if (mIfaceName != null) interfaceNames.add(mIfaceName);
Lorenzo Colitti63839822013-03-20 19:22:58 +0900252 for (LinkProperties stacked: mStackedLinks.values()) {
253 interfaceNames.addAll(stacked.getAllInterfaceNames());
254 }
255 return interfaceNames;
256 }
257
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900258 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700259 * Returns all the addresses on this link. We often think of a link having a single address,
260 * however, particularly with Ipv6 several addresses are typical. Note that the
261 * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include
262 * prefix lengths for each address. This is a simplified utility alternative to
263 * {@link LinkProperties#getLinkAddresses}.
264 *
Chalard Jeand51966a2018-06-07 13:27:00 +0900265 * @return An unmodifiable {@link List} of {@link InetAddress} for this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700266 * @hide
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900267 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800268 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800269 public @NonNull List<InetAddress> getAddresses() {
270 final List<InetAddress> addresses = new ArrayList<>();
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700271 for (LinkAddress linkAddress : mLinkAddresses) {
272 addresses.add(linkAddress.getAddress());
273 }
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700274 return Collections.unmodifiableList(addresses);
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700275 }
276
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900277 /**
278 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700279 * @hide
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900280 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100281 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +0800282 public @NonNull List<InetAddress> getAllAddresses() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900283 List<InetAddress> addresses = new ArrayList<>();
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900284 for (LinkAddress linkAddress : mLinkAddresses) {
285 addresses.add(linkAddress.getAddress());
286 }
287 for (LinkProperties stacked: mStackedLinks.values()) {
288 addresses.addAll(stacked.getAllAddresses());
289 }
290 return addresses;
291 }
292
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900293 private int findLinkAddressIndex(LinkAddress address) {
294 for (int i = 0; i < mLinkAddresses.size(); i++) {
295 if (mLinkAddresses.get(i).isSameAddressAs(address)) {
296 return i;
297 }
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900298 }
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900299 return -1;
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900300 }
301
302 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700303 * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the
304 * same address/prefix does not already exist. If it does exist it is replaced.
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900305 * @param address The {@code LinkAddress} to add.
306 * @return true if {@code address} was added or updated, false otherwise.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700307 * @hide
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900308 */
Remi NGUYEN VANc7fe99f2019-01-29 12:08:43 +0900309 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800310 public boolean addLinkAddress(@NonNull LinkAddress address) {
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900311 if (address == null) {
312 return false;
313 }
314 int i = findLinkAddressIndex(address);
315 if (i < 0) {
316 // Address was not present. Add it.
317 mLinkAddresses.add(address);
318 return true;
319 } else if (mLinkAddresses.get(i).equals(address)) {
320 // Address was present and has same properties. Do nothing.
321 return false;
322 } else {
323 // Address was present and has different properties. Update it.
324 mLinkAddresses.set(i, address);
325 return true;
326 }
327 }
328
329 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700330 * Removes a {@link LinkAddress} from this {@code LinkProperties}. Specifically, matches
331 * and {@link LinkAddress} with the same address and prefix.
332 *
333 * @param toRemove A {@link LinkAddress} specifying the address to remove.
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900334 * @return true if the address was removed, false if it did not exist.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700335 * @hide
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900336 */
Remi NGUYEN VANc7fe99f2019-01-29 12:08:43 +0900337 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800338 public boolean removeLinkAddress(@NonNull LinkAddress toRemove) {
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900339 int i = findLinkAddressIndex(toRemove);
340 if (i >= 0) {
341 mLinkAddresses.remove(i);
342 return true;
343 }
344 return false;
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700345 }
346
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900347 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700348 * Returns all the {@link LinkAddress} on this link. Typically a link will have
349 * one IPv4 address and one or more IPv6 addresses.
350 *
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700351 * @return An unmodifiable {@link List} of {@link LinkAddress} for this link.
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900352 */
paulhucbbc3db2019-03-08 16:35:20 +0800353 public @NonNull List<LinkAddress> getLinkAddresses() {
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700354 return Collections.unmodifiableList(mLinkAddresses);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700355 }
356
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900357 /**
358 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700359 * @hide
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900360 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800361 @SystemApi
362 public @NonNull List<LinkAddress> getAllLinkAddresses() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900363 List<LinkAddress> addresses = new ArrayList<>(mLinkAddresses);
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900364 for (LinkProperties stacked: mStackedLinks.values()) {
365 addresses.addAll(stacked.getAllLinkAddresses());
366 }
367 return addresses;
368 }
369
Lorenzo Colitti174782b2013-08-23 20:54:49 +0900370 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700371 * Replaces the {@link LinkAddress} in this {@code LinkProperties} with
372 * the given {@link Collection} of {@link LinkAddress}.
373 *
374 * @param addresses The {@link Collection} of {@link LinkAddress} to set in this
375 * object.
Lorenzo Colitti174782b2013-08-23 20:54:49 +0900376 */
paulhucbbc3db2019-03-08 16:35:20 +0800377 public void setLinkAddresses(@NonNull Collection<LinkAddress> addresses) {
Lorenzo Colitti174782b2013-08-23 20:54:49 +0900378 mLinkAddresses.clear();
379 for (LinkAddress address: addresses) {
380 addLinkAddress(address);
381 }
382 }
383
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700384 /**
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900385 * Adds the given {@link InetAddress} to the list of DNS servers, if not present.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700386 *
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700387 * @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900388 * @return true if the DNS server was added, false if it was already present.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700389 * @hide
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700390 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900391 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800392 public boolean addDnsServer(@NonNull InetAddress dnsServer) {
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900393 if (dnsServer != null && !mDnses.contains(dnsServer)) {
394 mDnses.add(dnsServer);
395 return true;
396 }
397 return false;
398 }
399
400 /**
Erik Kline04612b02015-05-21 16:15:02 +0900401 * Removes the given {@link InetAddress} from the list of DNS servers.
402 *
403 * @param dnsServer The {@link InetAddress} to remove from the list of DNS servers.
404 * @return true if the DNS server was removed, false if it did not exist.
405 * @hide
406 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900407 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800408 public boolean removeDnsServer(@NonNull InetAddress dnsServer) {
paulhu1a407652019-03-22 16:35:06 +0800409 return mDnses.remove(dnsServer);
Erik Kline04612b02015-05-21 16:15:02 +0900410 }
411
412 /**
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900413 * Replaces the DNS servers in this {@code LinkProperties} with
414 * the given {@link Collection} of {@link InetAddress} objects.
415 *
Chalard Jean299d8562018-04-11 16:36:41 +0900416 * @param dnsServers The {@link Collection} of DNS servers to set in this object.
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900417 */
paulhucbbc3db2019-03-08 16:35:20 +0800418 public void setDnsServers(@NonNull Collection<InetAddress> dnsServers) {
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900419 mDnses.clear();
420 for (InetAddress dnsServer: dnsServers) {
421 addDnsServer(dnsServer);
422 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700423 }
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700424
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700425 /**
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700426 * Returns all the {@link InetAddress} for DNS servers on this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700427 *
Chalard Jeand51966a2018-06-07 13:27:00 +0900428 * @return An unmodifiable {@link List} of {@link InetAddress} for DNS servers on
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700429 * this link.
430 */
paulhucbbc3db2019-03-08 16:35:20 +0800431 public @NonNull List<InetAddress> getDnsServers() {
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700432 return Collections.unmodifiableList(mDnses);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700433 }
434
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700435 /**
dalyk7643abc2018-01-17 14:20:55 -0500436 * Set whether private DNS is currently in use on this network.
437 *
438 * @param usePrivateDns The private DNS state.
439 * @hide
440 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900441 @SystemApi
dalyk7643abc2018-01-17 14:20:55 -0500442 public void setUsePrivateDns(boolean usePrivateDns) {
443 mUsePrivateDns = usePrivateDns;
444 }
445
446 /**
447 * Returns whether private DNS is currently in use on this network. When
448 * private DNS is in use, applications must not send unencrypted DNS
449 * queries as doing so could reveal private user information. Furthermore,
450 * if private DNS is in use and {@link #getPrivateDnsServerName} is not
451 * {@code null}, DNS queries must be sent to the specified DNS server.
452 *
453 * @return {@code true} if private DNS is in use, {@code false} otherwise.
454 */
455 public boolean isPrivateDnsActive() {
456 return mUsePrivateDns;
457 }
458
459 /**
460 * Set the name of the private DNS server to which private DNS queries
461 * should be sent when in strict mode. This value should be {@code null}
462 * when private DNS is off or in opportunistic mode.
463 *
464 * @param privateDnsServerName The private DNS server name.
465 * @hide
466 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900467 @SystemApi
dalyk7643abc2018-01-17 14:20:55 -0500468 public void setPrivateDnsServerName(@Nullable String privateDnsServerName) {
469 mPrivateDnsServerName = privateDnsServerName;
470 }
471
472 /**
ruibin zhangca75bc82019-05-23 19:35:30 +0800473 * Set DHCP server address.
474 *
475 * @param serverAddress the server address to set.
476 */
477 public void setDhcpServerAddress(@Nullable Inet4Address serverAddress) {
478 mDhcpServerAddress = serverAddress;
479 }
480
481 /**
482 * Get DHCP server address
483 *
484 * @return The current DHCP server address.
485 */
486 public @Nullable Inet4Address getDhcpServerAddress() {
487 return mDhcpServerAddress;
488 }
489
490 /**
dalyk7643abc2018-01-17 14:20:55 -0500491 * Returns the private DNS server name that is in use. If not {@code null},
492 * private DNS is in strict mode. In this mode, applications should ensure
493 * that all DNS queries are encrypted and sent to this hostname and that
494 * queries are only sent if the hostname's certificate is valid. If
495 * {@code null} and {@link #isPrivateDnsActive} is {@code true}, private
496 * DNS is in opportunistic mode, and applications should ensure that DNS
497 * queries are encrypted and sent to a DNS server returned by
498 * {@link #getDnsServers}. System DNS will handle each of these cases
499 * correctly, but applications implementing their own DNS lookups must make
500 * sure to follow these requirements.
501 *
502 * @return The private DNS server name.
503 */
504 public @Nullable String getPrivateDnsServerName() {
505 return mPrivateDnsServerName;
506 }
507
508 /**
Chalard Jean299d8562018-04-11 16:36:41 +0900509 * Adds the given {@link InetAddress} to the list of validated private DNS servers,
510 * if not present. This is distinct from the server name in that these are actually
511 * resolved addresses.
512 *
513 * @param dnsServer The {@link InetAddress} to add to the list of validated private DNS servers.
514 * @return true if the DNS server was added, false if it was already present.
515 * @hide
516 */
paulhucbbc3db2019-03-08 16:35:20 +0800517 public boolean addValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) {
Chalard Jean299d8562018-04-11 16:36:41 +0900518 if (dnsServer != null && !mValidatedPrivateDnses.contains(dnsServer)) {
519 mValidatedPrivateDnses.add(dnsServer);
520 return true;
521 }
522 return false;
523 }
524
525 /**
526 * Removes the given {@link InetAddress} from the list of validated private DNS servers.
527 *
528 * @param dnsServer The {@link InetAddress} to remove from the list of validated private DNS
529 * servers.
530 * @return true if the DNS server was removed, false if it did not exist.
531 * @hide
532 */
paulhucbbc3db2019-03-08 16:35:20 +0800533 public boolean removeValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) {
534 return mValidatedPrivateDnses.remove(dnsServer);
Chalard Jean299d8562018-04-11 16:36:41 +0900535 }
536
537 /**
538 * Replaces the validated private DNS servers in this {@code LinkProperties} with
539 * the given {@link Collection} of {@link InetAddress} objects.
540 *
541 * @param dnsServers The {@link Collection} of validated private DNS servers to set in this
542 * object.
543 * @hide
544 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900545 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800546 public void setValidatedPrivateDnsServers(@NonNull Collection<InetAddress> dnsServers) {
Chalard Jean299d8562018-04-11 16:36:41 +0900547 mValidatedPrivateDnses.clear();
548 for (InetAddress dnsServer: dnsServers) {
549 addValidatedPrivateDnsServer(dnsServer);
550 }
551 }
552
553 /**
554 * Returns all the {@link InetAddress} for validated private DNS servers on this link.
555 * These are resolved from the private DNS server name.
556 *
paulhucbbc3db2019-03-08 16:35:20 +0800557 * @return An unmodifiable {@link List} of {@link InetAddress} for validated private
Chalard Jean299d8562018-04-11 16:36:41 +0900558 * DNS servers on this link.
559 * @hide
560 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900561 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800562 public @NonNull List<InetAddress> getValidatedPrivateDnsServers() {
Chalard Jean299d8562018-04-11 16:36:41 +0900563 return Collections.unmodifiableList(mValidatedPrivateDnses);
564 }
565
566 /**
Hongshike2d7cf52018-06-28 20:42:19 +0900567 * Adds the given {@link InetAddress} to the list of PCSCF servers, if not present.
568 *
569 * @param pcscfServer The {@link InetAddress} to add to the list of PCSCF servers.
570 * @return true if the PCSCF server was added, false otherwise.
571 * @hide
572 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800573 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800574 public boolean addPcscfServer(@NonNull InetAddress pcscfServer) {
Hongshike2d7cf52018-06-28 20:42:19 +0900575 if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) {
576 mPcscfs.add(pcscfServer);
577 return true;
578 }
579 return false;
580 }
581
582 /**
583 * Removes the given {@link InetAddress} from the list of PCSCF servers.
584 *
paulhucbbc3db2019-03-08 16:35:20 +0800585 * @param pcscfServer The {@link InetAddress} to remove from the list of PCSCF servers.
Hongshike2d7cf52018-06-28 20:42:19 +0900586 * @return true if the PCSCF server was removed, false otherwise.
587 * @hide
588 */
paulhucbbc3db2019-03-08 16:35:20 +0800589 public boolean removePcscfServer(@NonNull InetAddress pcscfServer) {
590 return mPcscfs.remove(pcscfServer);
Hongshike2d7cf52018-06-28 20:42:19 +0900591 }
592
593 /**
594 * Replaces the PCSCF servers in this {@code LinkProperties} with
595 * the given {@link Collection} of {@link InetAddress} objects.
596 *
paulhucbbc3db2019-03-08 16:35:20 +0800597 * @param pcscfServers The {@link Collection} of PCSCF servers to set in this object.
Hongshike2d7cf52018-06-28 20:42:19 +0900598 * @hide
599 */
Remi NGUYEN VANd9f75862019-01-23 21:35:52 +0900600 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800601 public void setPcscfServers(@NonNull Collection<InetAddress> pcscfServers) {
Hongshike2d7cf52018-06-28 20:42:19 +0900602 mPcscfs.clear();
603 for (InetAddress pcscfServer: pcscfServers) {
604 addPcscfServer(pcscfServer);
605 }
606 }
607
608 /**
609 * Returns all the {@link InetAddress} for PCSCF servers on this link.
610 *
611 * @return An unmodifiable {@link List} of {@link InetAddress} for PCSCF servers on
612 * this link.
613 * @hide
614 */
Remi NGUYEN VANd9f75862019-01-23 21:35:52 +0900615 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800616 public @NonNull List<InetAddress> getPcscfServers() {
Hongshike2d7cf52018-06-28 20:42:19 +0900617 return Collections.unmodifiableList(mPcscfs);
618 }
619
620 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700621 * Sets the DNS domain search path used on this link.
622 *
623 * @param domains A {@link String} listing in priority order the comma separated
624 * domains to search when resolving host names on this link.
625 */
paulhucbbc3db2019-03-08 16:35:20 +0800626 public void setDomains(@Nullable String domains) {
Robert Greenwaltcd277852012-11-09 10:52:27 -0800627 mDomains = domains;
628 }
629
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700630 /**
paulhucbbc3db2019-03-08 16:35:20 +0800631 * Get the DNS domains search path set for this link. May be {@code null} if not set.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700632 *
paulhucbbc3db2019-03-08 16:35:20 +0800633 * @return A {@link String} containing the comma separated domains to search when resolving host
634 * names on this link or {@code null}.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700635 */
paulhucbbc3db2019-03-08 16:35:20 +0800636 public @Nullable String getDomains() {
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700637 return mDomains;
638 }
639
640 /**
641 * Sets the Maximum Transmission Unit size to use on this link. This should not be used
642 * unless the system default (1500) is incorrect. Values less than 68 or greater than
643 * 10000 will be ignored.
644 *
645 * @param mtu The MTU to use for this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700646 */
sy.yun4aa73922013-09-02 05:24:09 +0900647 public void setMtu(int mtu) {
648 mMtu = mtu;
649 }
650
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700651 /**
652 * Gets any non-default MTU size set for this link. Note that if the default is being used
653 * this will return 0.
654 *
655 * @return The mtu value set for this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700656 */
sy.yun4aa73922013-09-02 05:24:09 +0900657 public int getMtu() {
658 return mMtu;
659 }
660
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700661 /**
662 * Sets the tcp buffers sizes to be used when this link is the system default.
663 * Should be of the form "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max".
664 *
665 * @param tcpBufferSizes The tcp buffers sizes to use.
666 *
667 * @hide
668 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900669 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800670 public void setTcpBufferSizes(@Nullable String tcpBufferSizes) {
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700671 mTcpBufferSizes = tcpBufferSizes;
672 }
673
674 /**
paulhucbbc3db2019-03-08 16:35:20 +0800675 * Gets the tcp buffer sizes. May be {@code null} if not set.
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700676 *
paulhucbbc3db2019-03-08 16:35:20 +0800677 * @return the tcp buffer sizes to use when this link is the system default or {@code null}.
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700678 *
679 * @hide
680 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900681 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800682 public @Nullable String getTcpBufferSizes() {
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700683 return mTcpBufferSizes;
684 }
685
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800686 private RouteInfo routeWithInterface(RouteInfo route) {
687 return new RouteInfo(
688 route.getDestination(),
689 route.getGateway(),
Lorenzo Colitti21290342014-09-19 01:49:05 +0900690 mIfaceName,
Tyler Weare4314862019-12-05 14:55:30 -0800691 route.getType(),
692 route.getMtu());
693 }
694
junyulaia1493a52020-03-23 20:49:43 +0800695 private int findRouteIndexByRouteKey(RouteInfo route) {
Tyler Weare4314862019-12-05 14:55:30 -0800696 for (int i = 0; i < mRoutes.size(); i++) {
junyulaia1493a52020-03-23 20:49:43 +0800697 if (mRoutes.get(i).getRouteKey().equals(route.getRouteKey())) {
Tyler Weare4314862019-12-05 14:55:30 -0800698 return i;
699 }
700 }
701 return -1;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700702 }
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800703
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700704 /**
Chiachang Wang52a55922021-04-15 16:04:00 +0800705 * Adds a {@link RouteInfo} to this {@code LinkProperties}. If there is a {@link RouteInfo}
706 * with the same destination, gateway and interface with different properties
junyulaia1493a52020-03-23 20:49:43 +0800707 * (e.g., different MTU), it will be updated. If the {@link RouteInfo} had an
708 * interface name set and that differs from the interface set for this
709 * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown.
710 * The proper course is to add either un-named or properly named {@link RouteInfo}.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700711 *
712 * @param route A {@link RouteInfo} to add to this object.
Tyler Weare4314862019-12-05 14:55:30 -0800713 * @return {@code true} was added or updated, false otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700714 */
paulhucbbc3db2019-03-08 16:35:20 +0800715 public boolean addRoute(@NonNull RouteInfo route) {
716 String routeIface = route.getInterface();
717 if (routeIface != null && !routeIface.equals(mIfaceName)) {
718 throw new IllegalArgumentException(
719 "Route added with non-matching interface: " + routeIface
720 + " vs. " + mIfaceName);
721 }
722 route = routeWithInterface(route);
Tyler Weare4314862019-12-05 14:55:30 -0800723
junyulaia1493a52020-03-23 20:49:43 +0800724 int i = findRouteIndexByRouteKey(route);
Tyler Weare4314862019-12-05 14:55:30 -0800725 if (i == -1) {
726 // Route was not present. Add it.
paulhucbbc3db2019-03-08 16:35:20 +0800727 mRoutes.add(route);
728 return true;
Tyler Weare4314862019-12-05 14:55:30 -0800729 } else if (mRoutes.get(i).equals(route)) {
730 // Route was present and has same properties. Do nothing.
731 return false;
732 } else {
733 // Route was present and has different properties. Update it.
734 mRoutes.set(i, route);
735 return true;
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800736 }
Lorenzo Colitti36ddd9d2014-06-12 23:10:17 +0900737 }
738
739 /**
740 * Removes a {@link RouteInfo} from this {@code LinkProperties}, if present. The route must
741 * specify an interface and the interface must match the interface of this
742 * {@code LinkProperties}, or it will not be removed.
743 *
Tyler Weare4314862019-12-05 14:55:30 -0800744 * @param route A {@link RouteInfo} specifying the route to remove.
Lorenzo Colitti36ddd9d2014-06-12 23:10:17 +0900745 * @return {@code true} if the route was removed, {@code false} if it was not present.
746 *
747 * @hide
748 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900749 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800750 public boolean removeRoute(@NonNull RouteInfo route) {
751 return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route);
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800752 }
753
Lorenzo Colittic0803122013-03-07 10:59:25 -0800754 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700755 * Returns all the {@link RouteInfo} set on this link.
756 *
Taras Antoshchuk30d41e52021-08-02 18:06:35 +0200757 * Only unicast routes are returned for apps targeting Android S or below.
758 *
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700759 * @return An unmodifiable {@link List} of {@link RouteInfo} for this link.
Lorenzo Colittic0803122013-03-07 10:59:25 -0800760 */
paulhucbbc3db2019-03-08 16:35:20 +0800761 public @NonNull List<RouteInfo> getRoutes() {
Taras Antoshchuk30d41e52021-08-02 18:06:35 +0200762 if (CompatChanges.isChangeEnabled(EXCLUDED_ROUTES)) {
763 return Collections.unmodifiableList(mRoutes);
764 } else {
765 return Collections.unmodifiableList(getUnicastRoutes());
766 }
767 }
768
769 /**
770 * Returns all the {@link RouteInfo} of type {@link RouteInfo#RTN_UNICAST} set on this link.
771 */
772 private @NonNull List<RouteInfo> getUnicastRoutes() {
773 return mRoutes.stream()
774 .filter(route -> route.getType() == RouteInfo.RTN_UNICAST)
775 .collect(Collectors.toList());
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700776 }
777
Lorenzo Colittic0803122013-03-07 10:59:25 -0800778 /**
Rubin Xuffd77d82017-09-05 18:40:49 +0100779 * Make sure this LinkProperties instance contains routes that cover the local subnet
780 * of its link addresses. Add any route that is missing.
781 * @hide
782 */
783 public void ensureDirectlyConnectedRoutes() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900784 for (LinkAddress addr : mLinkAddresses) {
Rubin Xuffd77d82017-09-05 18:40:49 +0100785 addRoute(new RouteInfo(addr, null, mIfaceName));
786 }
787 }
788
789 /**
Lorenzo Colittic0803122013-03-07 10:59:25 -0800790 * Returns all the routes on this link and all the links stacked above it.
Taras Antoshchuk30d41e52021-08-02 18:06:35 +0200791 *
792 * Only unicast routes are returned for apps targeting Android S or below.
793 *
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700794 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800795 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800796 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800797 public @NonNull List<RouteInfo> getAllRoutes() {
Taras Antoshchuk30d41e52021-08-02 18:06:35 +0200798 final List<RouteInfo> routes = new ArrayList<>(getRoutes());
Lorenzo Colittic0803122013-03-07 10:59:25 -0800799 for (LinkProperties stacked: mStackedLinks.values()) {
800 routes.addAll(stacked.getAllRoutes());
801 }
Robert Greenwaltf3385082013-03-15 11:28:50 -0700802 return routes;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800803 }
804
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700805 /**
806 * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none.
807 * Note that Http Proxies are only a hint - the system recommends their use, but it does
808 * not enforce it and applications may ignore them.
809 *
Erik Klinea923dba2015-06-26 19:21:34 +0900810 * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700811 */
paulhucbbc3db2019-03-08 16:35:20 +0800812 public void setHttpProxy(@Nullable ProxyInfo proxy) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700813 mHttpProxy = proxy;
814 }
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700815
816 /**
817 * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link.
818 *
paulhucbbc3db2019-03-08 16:35:20 +0800819 * @return The {@link ProxyInfo} set on this link or {@code null}.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700820 */
paulhucbbc3db2019-03-08 16:35:20 +0800821 public @Nullable ProxyInfo getHttpProxy() {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700822 return mHttpProxy;
823 }
824
Lorenzo Colittic0803122013-03-07 10:59:25 -0800825 /**
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900826 * Returns the NAT64 prefix in use on this link, if any.
827 *
paulhucbbc3db2019-03-08 16:35:20 +0800828 * @return the NAT64 prefix or {@code null}.
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900829 */
830 public @Nullable IpPrefix getNat64Prefix() {
831 return mNat64Prefix;
832 }
833
834 /**
835 * Sets the NAT64 prefix in use on this link.
836 *
837 * Currently, only 96-bit prefixes (i.e., where the 32-bit IPv4 address is at the end of the
paulhucbbc3db2019-03-08 16:35:20 +0800838 * 128-bit IPv6 address) are supported or {@code null} for no prefix.
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900839 *
840 * @param prefix the NAT64 prefix.
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900841 */
paulhucbbc3db2019-03-08 16:35:20 +0800842 public void setNat64Prefix(@Nullable IpPrefix prefix) {
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900843 if (prefix != null && prefix.getPrefixLength() != 96) {
844 throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix);
845 }
846 mNat64Prefix = prefix; // IpPrefix objects are immutable.
847 }
848
849 /**
Lorenzo Colittic0803122013-03-07 10:59:25 -0800850 * Adds a stacked link.
851 *
Chalard Jeand51966a2018-06-07 13:27:00 +0900852 * If there is already a stacked link with the same interface name as link,
Lorenzo Colittic0803122013-03-07 10:59:25 -0800853 * that link is replaced with link. Otherwise, link is added to the list
paulhucbbc3db2019-03-08 16:35:20 +0800854 * of stacked links.
Lorenzo Colittic0803122013-03-07 10:59:25 -0800855 *
856 * @param link The link to add.
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900857 * @return true if the link was stacked, false otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700858 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800859 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100860 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +0800861 public boolean addStackedLink(@NonNull LinkProperties link) {
862 if (link.getInterfaceName() != null) {
Lorenzo Colittic0803122013-03-07 10:59:25 -0800863 mStackedLinks.put(link.getInterfaceName(), link);
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900864 return true;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800865 }
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900866 return false;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800867 }
868
869 /**
870 * Removes a stacked link.
871 *
Lorenzo Colitti38258432014-10-20 11:08:03 +0900872 * If there is a stacked link with the given interface name, it is
Lorenzo Colittic0803122013-03-07 10:59:25 -0800873 * removed. Otherwise, nothing changes.
874 *
Lorenzo Colitti38258432014-10-20 11:08:03 +0900875 * @param iface The interface name of the link to remove.
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900876 * @return true if the link was removed, false otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700877 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800878 */
paulhucbbc3db2019-03-08 16:35:20 +0800879 public boolean removeStackedLink(@NonNull String iface) {
880 LinkProperties removed = mStackedLinks.remove(iface);
881 return removed != null;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800882 }
883
884 /**
885 * Returns all the links stacked on top of this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700886 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800887 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000888 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jeff Sharkey0aef9342014-08-11 15:22:51 -0700889 public @NonNull List<LinkProperties> getStackedLinks() {
890 if (mStackedLinks.isEmpty()) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900891 return Collections.emptyList();
Jeff Sharkey0aef9342014-08-11 15:22:51 -0700892 }
paulhucbbc3db2019-03-08 16:35:20 +0800893 final List<LinkProperties> stacked = new ArrayList<>();
Lorenzo Colittic0803122013-03-07 10:59:25 -0800894 for (LinkProperties link : mStackedLinks.values()) {
Jeff Sharkey0aef9342014-08-11 15:22:51 -0700895 stacked.add(new LinkProperties(link));
Lorenzo Colittic0803122013-03-07 10:59:25 -0800896 }
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700897 return Collections.unmodifiableList(stacked);
Lorenzo Colittic0803122013-03-07 10:59:25 -0800898 }
899
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700900 /**
901 * Clears this object to its initial state.
902 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700903 public void clear() {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900904 if (mParcelSensitiveFields) {
905 throw new UnsupportedOperationException(
906 "Cannot clear LinkProperties when parcelSensitiveFields is set");
907 }
908
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700909 mIfaceName = null;
Wink Saville051a6642011-07-13 13:44:13 -0700910 mLinkAddresses.clear();
911 mDnses.clear();
dalyk7643abc2018-01-17 14:20:55 -0500912 mUsePrivateDns = false;
913 mPrivateDnsServerName = null;
Hongshike2d7cf52018-06-28 20:42:19 +0900914 mPcscfs.clear();
Robert Greenwaltcd277852012-11-09 10:52:27 -0800915 mDomains = null;
Wink Saville051a6642011-07-13 13:44:13 -0700916 mRoutes.clear();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700917 mHttpProxy = null;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800918 mStackedLinks.clear();
sy.yun4aa73922013-09-02 05:24:09 +0900919 mMtu = 0;
ruibin zhangca75bc82019-05-23 19:35:30 +0800920 mDhcpServerAddress = null;
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700921 mTcpBufferSizes = null;
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900922 mNat64Prefix = null;
Valentin Iftime9fa35092019-09-24 13:32:13 +0200923 mWakeOnLanSupported = false;
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900924 mCaptivePortalApiUrl = null;
925 mCaptivePortalData = null;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700926 }
927
928 /**
929 * Implement the Parcelable interface
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700930 */
931 public int describeContents() {
932 return 0;
933 }
934
Wink Saville7d857902010-08-27 11:15:18 -0700935 @Override
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700936 public String toString() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900937 // Space as a separator, so no need for spaces at start/end of the individual fragments.
938 final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700939
Chalard Jeand51966a2018-06-07 13:27:00 +0900940 if (mIfaceName != null) {
941 resultJoiner.add("InterfaceName:");
942 resultJoiner.add(mIfaceName);
943 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700944
Chalard Jeand51966a2018-06-07 13:27:00 +0900945 resultJoiner.add("LinkAddresses: [");
946 if (!mLinkAddresses.isEmpty()) {
947 resultJoiner.add(TextUtils.join(",", mLinkAddresses));
948 }
949 resultJoiner.add("]");
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700950
Chalard Jeand51966a2018-06-07 13:27:00 +0900951 resultJoiner.add("DnsAddresses: [");
952 if (!mDnses.isEmpty()) {
953 resultJoiner.add(TextUtils.join(",", mDnses));
954 }
955 resultJoiner.add("]");
dalyk7643abc2018-01-17 14:20:55 -0500956
Chalard Jeand51966a2018-06-07 13:27:00 +0900957 if (mUsePrivateDns) {
958 resultJoiner.add("UsePrivateDns: true");
959 }
960
Chalard Jeand3930f12018-06-07 13:28:09 +0900961 if (mPrivateDnsServerName != null) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900962 resultJoiner.add("PrivateDnsServerName:");
963 resultJoiner.add(mPrivateDnsServerName);
dalyk7643abc2018-01-17 14:20:55 -0500964 }
965
Hongshike2d7cf52018-06-28 20:42:19 +0900966 if (!mPcscfs.isEmpty()) {
967 resultJoiner.add("PcscfAddresses: [");
968 resultJoiner.add(TextUtils.join(",", mPcscfs));
969 resultJoiner.add("]");
970 }
971
Chalard Jean299d8562018-04-11 16:36:41 +0900972 if (!mValidatedPrivateDnses.isEmpty()) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900973 final StringJoiner validatedPrivateDnsesJoiner =
974 new StringJoiner(",", "ValidatedPrivateDnsAddresses: [", "]");
975 for (final InetAddress addr : mValidatedPrivateDnses) {
976 validatedPrivateDnsesJoiner.add(addr.getHostAddress());
Chalard Jean299d8562018-04-11 16:36:41 +0900977 }
Chalard Jeand51966a2018-06-07 13:27:00 +0900978 resultJoiner.add(validatedPrivateDnsesJoiner.toString());
Chalard Jean299d8562018-04-11 16:36:41 +0900979 }
980
Chalard Jeand51966a2018-06-07 13:27:00 +0900981 resultJoiner.add("Domains:");
982 resultJoiner.add(mDomains);
Robert Greenwaltcd277852012-11-09 10:52:27 -0800983
Chalard Jeand51966a2018-06-07 13:27:00 +0900984 resultJoiner.add("MTU:");
985 resultJoiner.add(Integer.toString(mMtu));
sy.yun4aa73922013-09-02 05:24:09 +0900986
Valentin Iftime9fa35092019-09-24 13:32:13 +0200987 if (mWakeOnLanSupported) {
988 resultJoiner.add("WakeOnLanSupported: true");
989 }
990
ruibin zhangca75bc82019-05-23 19:35:30 +0800991 if (mDhcpServerAddress != null) {
992 resultJoiner.add("ServerAddress:");
993 resultJoiner.add(mDhcpServerAddress.toString());
994 }
995
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900996 if (mCaptivePortalApiUrl != null) {
997 resultJoiner.add("CaptivePortalApiUrl: " + mCaptivePortalApiUrl);
998 }
999
1000 if (mCaptivePortalData != null) {
1001 resultJoiner.add("CaptivePortalData: " + mCaptivePortalData);
1002 }
1003
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001004 if (mTcpBufferSizes != null) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001005 resultJoiner.add("TcpBufferSizes:");
1006 resultJoiner.add(mTcpBufferSizes);
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001007 }
1008
Chalard Jeand51966a2018-06-07 13:27:00 +09001009 resultJoiner.add("Routes: [");
1010 if (!mRoutes.isEmpty()) {
1011 resultJoiner.add(TextUtils.join(",", mRoutes));
1012 }
1013 resultJoiner.add("]");
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001014
Chalard Jeand51966a2018-06-07 13:27:00 +09001015 if (mHttpProxy != null) {
1016 resultJoiner.add("HttpProxy:");
1017 resultJoiner.add(mHttpProxy.toString());
1018 }
1019
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001020 if (mNat64Prefix != null) {
1021 resultJoiner.add("Nat64Prefix:");
1022 resultJoiner.add(mNat64Prefix.toString());
1023 }
1024
Chalard Jeand51966a2018-06-07 13:27:00 +09001025 final Collection<LinkProperties> stackedLinksValues = mStackedLinks.values();
1026 if (!stackedLinksValues.isEmpty()) {
1027 final StringJoiner stackedLinksJoiner = new StringJoiner(",", "Stacked: [", "]");
1028 for (final LinkProperties lp : stackedLinksValues) {
1029 stackedLinksJoiner.add("[ " + lp + " ]");
Lorenzo Colittic0803122013-03-07 10:59:25 -08001030 }
Chalard Jeand51966a2018-06-07 13:27:00 +09001031 resultJoiner.add(stackedLinksJoiner.toString());
Lorenzo Colittic0803122013-03-07 10:59:25 -08001032 }
Chalard Jeand51966a2018-06-07 13:27:00 +09001033
1034 return resultJoiner.toString();
Lorenzo Colittic0803122013-03-07 10:59:25 -08001035 }
1036
1037 /**
1038 * Returns true if this link has an IPv4 address.
1039 *
1040 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -07001041 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -08001042 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001043 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001044 public boolean hasIpv4Address() {
Lorenzo Colittic0803122013-03-07 10:59:25 -08001045 for (LinkAddress address : mLinkAddresses) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001046 if (address.getAddress() instanceof Inet4Address) {
1047 return true;
1048 }
Lorenzo Colittic0803122013-03-07 10:59:25 -08001049 }
1050 return false;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001051 }
1052
Wink Saville051a6642011-07-13 13:44:13 -07001053 /**
paulhucbbc3db2019-03-08 16:35:20 +08001054 * For backward compatibility.
1055 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1056 * just yet.
1057 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
1058 * @hide
1059 */
1060 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1061 public boolean hasIPv4Address() {
1062 return hasIpv4Address();
1063 }
1064
1065 /**
Lorenzo Colitti05a505c2015-07-27 16:35:33 +09001066 * Returns true if this link or any of its stacked interfaces has an IPv4 address.
1067 *
1068 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
1069 */
paulhucbbc3db2019-03-08 16:35:20 +08001070 private boolean hasIpv4AddressOnInterface(String iface) {
Lorenzo Colitti28bb16c2015-07-30 23:41:43 +09001071 // mIfaceName can be null.
paulhucbbc3db2019-03-08 16:35:20 +08001072 return (Objects.equals(iface, mIfaceName) && hasIpv4Address())
1073 || (iface != null && mStackedLinks.containsKey(iface)
1074 && mStackedLinks.get(iface).hasIpv4Address());
Lorenzo Colitti05a505c2015-07-27 16:35:33 +09001075 }
1076
1077 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001078 * Returns true if this link has a global preferred IPv6 address.
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001079 *
Lorenzo Colittifc854692014-06-23 22:33:43 +09001080 * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -07001081 * @hide
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001082 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001083 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001084 public boolean hasGlobalIpv6Address() {
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001085 for (LinkAddress address : mLinkAddresses) {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001086 if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) {
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001087 return true;
1088 }
1089 }
1090 return false;
1091 }
1092
1093 /**
Rubin Xuab8cf302020-03-30 14:37:05 +01001094 * Returns true if this link has an IPv4 unreachable default route.
1095 *
1096 * @return {@code true} if there is an IPv4 unreachable default route, {@code false} otherwise.
1097 * @hide
1098 */
1099 public boolean hasIpv4UnreachableDefaultRoute() {
1100 for (RouteInfo r : mRoutes) {
1101 if (r.isIPv4UnreachableDefault()) {
1102 return true;
1103 }
1104 }
1105 return false;
1106 }
1107
1108 /**
paulhucbbc3db2019-03-08 16:35:20 +08001109 * For backward compatibility.
1110 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1111 * just yet.
1112 * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
1113 * @hide
1114 */
1115 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1116 public boolean hasGlobalIPv6Address() {
1117 return hasGlobalIpv6Address();
1118 }
1119
1120 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001121 * Returns true if this link has an IPv4 default route.
1122 *
1123 * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
1124 * @hide
1125 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +08001126 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001127 public boolean hasIpv4DefaultRoute() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001128 for (RouteInfo r : mRoutes) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001129 if (r.isIPv4Default()) {
1130 return true;
1131 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001132 }
1133 return false;
1134 }
1135
1136 /**
Rubin Xuab8cf302020-03-30 14:37:05 +01001137 * Returns true if this link has an IPv6 unreachable default route.
1138 *
1139 * @return {@code true} if there is an IPv6 unreachable default route, {@code false} otherwise.
1140 * @hide
1141 */
1142 public boolean hasIpv6UnreachableDefaultRoute() {
1143 for (RouteInfo r : mRoutes) {
1144 if (r.isIPv6UnreachableDefault()) {
1145 return true;
1146 }
1147 }
1148 return false;
1149 }
1150
1151 /**
paulhucbbc3db2019-03-08 16:35:20 +08001152 * For backward compatibility.
1153 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1154 * just yet.
1155 * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
1156 * @hide
1157 */
1158 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1159 public boolean hasIPv4DefaultRoute() {
1160 return hasIpv4DefaultRoute();
1161 }
1162
1163 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001164 * Returns true if this link has an IPv6 default route.
1165 *
1166 * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
1167 * @hide
1168 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001169 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001170 public boolean hasIpv6DefaultRoute() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001171 for (RouteInfo r : mRoutes) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001172 if (r.isIPv6Default()) {
1173 return true;
1174 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001175 }
1176 return false;
1177 }
1178
1179 /**
paulhucbbc3db2019-03-08 16:35:20 +08001180 * For backward compatibility.
1181 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1182 * just yet.
1183 * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
1184 * @hide
1185 */
1186 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1187 public boolean hasIPv6DefaultRoute() {
1188 return hasIpv6DefaultRoute();
1189 }
1190
1191 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001192 * Returns true if this link has an IPv4 DNS server.
1193 *
1194 * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
1195 * @hide
1196 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +08001197 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001198 public boolean hasIpv4DnsServer() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001199 for (InetAddress ia : mDnses) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001200 if (ia instanceof Inet4Address) {
1201 return true;
1202 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001203 }
1204 return false;
1205 }
1206
1207 /**
paulhucbbc3db2019-03-08 16:35:20 +08001208 * For backward compatibility.
1209 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1210 * just yet.
1211 * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
1212 * @hide
1213 */
1214 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1215 public boolean hasIPv4DnsServer() {
1216 return hasIpv4DnsServer();
1217 }
1218
1219 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001220 * Returns true if this link has an IPv6 DNS server.
1221 *
1222 * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
1223 * @hide
1224 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +08001225 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001226 public boolean hasIpv6DnsServer() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001227 for (InetAddress ia : mDnses) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001228 if (ia instanceof Inet6Address) {
1229 return true;
1230 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001231 }
1232 return false;
1233 }
1234
1235 /**
paulhucbbc3db2019-03-08 16:35:20 +08001236 * For backward compatibility.
1237 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1238 * just yet.
1239 * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
1240 * @hide
1241 */
1242 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1243 public boolean hasIPv6DnsServer() {
1244 return hasIpv6DnsServer();
1245 }
1246
1247 /**
Hongshike2d7cf52018-06-28 20:42:19 +09001248 * Returns true if this link has an IPv4 PCSCF server.
1249 *
1250 * @return {@code true} if there is an IPv4 PCSCF server, {@code false} otherwise.
1251 * @hide
1252 */
paulhucbbc3db2019-03-08 16:35:20 +08001253 public boolean hasIpv4PcscfServer() {
Hongshike2d7cf52018-06-28 20:42:19 +09001254 for (InetAddress ia : mPcscfs) {
1255 if (ia instanceof Inet4Address) {
1256 return true;
1257 }
1258 }
1259 return false;
1260 }
1261
1262 /**
1263 * Returns true if this link has an IPv6 PCSCF server.
1264 *
1265 * @return {@code true} if there is an IPv6 PCSCF server, {@code false} otherwise.
1266 * @hide
1267 */
paulhucbbc3db2019-03-08 16:35:20 +08001268 public boolean hasIpv6PcscfServer() {
Hongshike2d7cf52018-06-28 20:42:19 +09001269 for (InetAddress ia : mPcscfs) {
1270 if (ia instanceof Inet6Address) {
1271 return true;
1272 }
1273 }
1274 return false;
1275 }
1276
1277 /**
Erik Kline8b023072014-10-24 21:50:20 +09001278 * Returns true if this link is provisioned for global IPv4 connectivity.
1279 * This requires an IP address, default route, and DNS server.
1280 *
1281 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Kline04612b02015-05-21 16:15:02 +09001282 * @hide
Erik Kline8b023072014-10-24 21:50:20 +09001283 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001284 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001285 public boolean isIpv4Provisioned() {
1286 return (hasIpv4Address()
1287 && hasIpv4DefaultRoute()
1288 && hasIpv4DnsServer());
Erik Kline8b023072014-10-24 21:50:20 +09001289 }
1290
1291 /**
1292 * Returns true if this link is provisioned for global IPv6 connectivity.
1293 * This requires an IP address, default route, and DNS server.
1294 *
1295 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Kline04612b02015-05-21 16:15:02 +09001296 * @hide
Erik Kline8b023072014-10-24 21:50:20 +09001297 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001298 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001299 public boolean isIpv6Provisioned() {
1300 return (hasGlobalIpv6Address()
1301 && hasIpv6DefaultRoute()
1302 && hasIpv6DnsServer());
Erik Kline8b023072014-10-24 21:50:20 +09001303 }
1304
1305 /**
paulhucbbc3db2019-03-08 16:35:20 +08001306 * For backward compatibility.
1307 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1308 * just yet.
1309 * @return {@code true} if the link is provisioned, {@code false} otherwise.
1310 * @hide
1311 */
1312 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1313 public boolean isIPv6Provisioned() {
1314 return isIpv6Provisioned();
1315 }
1316
1317
1318 /**
Erik Kline8b023072014-10-24 21:50:20 +09001319 * Returns true if this link is provisioned for global connectivity,
1320 * for at least one Internet Protocol family.
Lorenzo Colittifc854692014-06-23 22:33:43 +09001321 *
1322 * @return {@code true} if the link is provisioned, {@code false} otherwise.
1323 * @hide
1324 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001325 @SystemApi
Lorenzo Colittifc854692014-06-23 22:33:43 +09001326 public boolean isProvisioned() {
paulhucbbc3db2019-03-08 16:35:20 +08001327 return (isIpv4Provisioned() || isIpv6Provisioned());
Lorenzo Colittifc854692014-06-23 22:33:43 +09001328 }
1329
1330 /**
Erik Klinea923dba2015-06-26 19:21:34 +09001331 * Evaluate whether the {@link InetAddress} is considered reachable.
1332 *
1333 * @return {@code true} if the given {@link InetAddress} is considered reachable,
1334 * {@code false} otherwise.
1335 * @hide
1336 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001337 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001338 public boolean isReachable(@NonNull InetAddress ip) {
Erik Klinea923dba2015-06-26 19:21:34 +09001339 final List<RouteInfo> allRoutes = getAllRoutes();
1340 // If we don't have a route to this IP address, it's not reachable.
1341 final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip);
1342 if (bestRoute == null) {
1343 return false;
1344 }
1345
1346 // TODO: better source address evaluation for destination addresses.
1347
1348 if (ip instanceof Inet4Address) {
1349 // For IPv4, it suffices for now to simply have any address.
paulhucbbc3db2019-03-08 16:35:20 +08001350 return hasIpv4AddressOnInterface(bestRoute.getInterface());
Erik Klinea923dba2015-06-26 19:21:34 +09001351 } else if (ip instanceof Inet6Address) {
1352 if (ip.isLinkLocalAddress()) {
1353 // For now, just make sure link-local destinations have
1354 // scopedIds set, since transmits will generally fail otherwise.
1355 // TODO: verify it matches the ifindex of one of the interfaces.
1356 return (((Inet6Address)ip).getScopeId() != 0);
1357 } else {
1358 // For non-link-local destinations check that either the best route
1359 // is directly connected or that some global preferred address exists.
1360 // TODO: reconsider all cases (disconnected ULA networks, ...).
paulhucbbc3db2019-03-08 16:35:20 +08001361 return (!bestRoute.hasGateway() || hasGlobalIpv6Address());
Erik Klinea923dba2015-06-26 19:21:34 +09001362 }
1363 }
1364
1365 return false;
1366 }
1367
1368 /**
Wink Saville051a6642011-07-13 13:44:13 -07001369 * Compares this {@code LinkProperties} interface name against the target
1370 *
1371 * @param target LinkProperties to compare.
1372 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001373 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001374 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001375 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001376 public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001377 return LinkPropertiesUtils.isIdenticalInterfaceName(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001378 }
1379
1380 /**
ruibin zhangca75bc82019-05-23 19:35:30 +08001381 * Compares this {@code LinkProperties} DHCP server address against the target
1382 *
1383 * @param target LinkProperties to compare.
1384 * @return {@code true} if both are identical, {@code false} otherwise.
1385 * @hide
1386 */
1387 public boolean isIdenticalDhcpServerAddress(@NonNull LinkProperties target) {
1388 return Objects.equals(mDhcpServerAddress, target.mDhcpServerAddress);
1389 }
1390
1391 /**
Robert Greenwalt462e5702012-10-31 14:32:53 -07001392 * Compares this {@code LinkProperties} interface addresses against the target
Wink Saville051a6642011-07-13 13:44:13 -07001393 *
1394 * @param target LinkProperties to compare.
1395 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001396 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001397 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001398 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001399 public boolean isIdenticalAddresses(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001400 return LinkPropertiesUtils.isIdenticalAddresses(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001401 }
1402
1403 /**
1404 * Compares this {@code LinkProperties} DNS addresses against the target
1405 *
1406 * @param target LinkProperties to compare.
1407 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001408 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001409 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001410 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001411 public boolean isIdenticalDnses(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001412 return LinkPropertiesUtils.isIdenticalDnses(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001413 }
1414
1415 /**
dalyk7643abc2018-01-17 14:20:55 -05001416 * Compares this {@code LinkProperties} private DNS settings against the
1417 * target.
1418 *
1419 * @param target LinkProperties to compare.
1420 * @return {@code true} if both are identical, {@code false} otherwise.
1421 * @hide
1422 */
paulhucbbc3db2019-03-08 16:35:20 +08001423 public boolean isIdenticalPrivateDns(@NonNull LinkProperties target) {
dalyk7643abc2018-01-17 14:20:55 -05001424 return (isPrivateDnsActive() == target.isPrivateDnsActive()
1425 && TextUtils.equals(getPrivateDnsServerName(),
1426 target.getPrivateDnsServerName()));
1427 }
1428
1429 /**
Chalard Jean299d8562018-04-11 16:36:41 +09001430 * Compares this {@code LinkProperties} validated private DNS addresses against
1431 * the target
1432 *
1433 * @param target LinkProperties to compare.
1434 * @return {@code true} if both are identical, {@code false} otherwise.
1435 * @hide
1436 */
paulhucbbc3db2019-03-08 16:35:20 +08001437 public boolean isIdenticalValidatedPrivateDnses(@NonNull LinkProperties target) {
Chalard Jean299d8562018-04-11 16:36:41 +09001438 Collection<InetAddress> targetDnses = target.getValidatedPrivateDnsServers();
1439 return (mValidatedPrivateDnses.size() == targetDnses.size())
1440 ? mValidatedPrivateDnses.containsAll(targetDnses) : false;
1441 }
1442
1443 /**
Hongshike2d7cf52018-06-28 20:42:19 +09001444 * Compares this {@code LinkProperties} PCSCF addresses against the target
1445 *
1446 * @param target LinkProperties to compare.
1447 * @return {@code true} if both are identical, {@code false} otherwise.
1448 * @hide
1449 */
paulhucbbc3db2019-03-08 16:35:20 +08001450 public boolean isIdenticalPcscfs(@NonNull LinkProperties target) {
Hongshike2d7cf52018-06-28 20:42:19 +09001451 Collection<InetAddress> targetPcscfs = target.getPcscfServers();
1452 return (mPcscfs.size() == targetPcscfs.size()) ?
1453 mPcscfs.containsAll(targetPcscfs) : false;
1454 }
1455
1456 /**
Wink Saville051a6642011-07-13 13:44:13 -07001457 * Compares this {@code LinkProperties} Routes against the target
1458 *
1459 * @param target LinkProperties to compare.
1460 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001461 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001462 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001463 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001464 public boolean isIdenticalRoutes(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001465 return LinkPropertiesUtils.isIdenticalRoutes(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001466 }
1467
1468 /**
1469 * Compares this {@code LinkProperties} HttpProxy against the target
1470 *
1471 * @param target LinkProperties to compare.
1472 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001473 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001474 */
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +00001475 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
paulhucbbc3db2019-03-08 16:35:20 +08001476 public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001477 return LinkPropertiesUtils.isIdenticalHttpProxy(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001478 }
John Wang3e567d52011-04-04 12:35:42 -07001479
Lorenzo Colittic0803122013-03-07 10:59:25 -08001480 /**
1481 * Compares this {@code LinkProperties} stacked links against the target
1482 *
1483 * @param target LinkProperties to compare.
1484 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001485 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -08001486 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +00001487 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhucbbc3db2019-03-08 16:35:20 +08001488 public boolean isIdenticalStackedLinks(@NonNull LinkProperties target) {
Lorenzo Colitti89218e52013-04-01 10:47:43 +09001489 if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
Lorenzo Colittic0803122013-03-07 10:59:25 -08001490 return false;
1491 }
1492 for (LinkProperties stacked : mStackedLinks.values()) {
1493 // Hashtable values can never be null.
1494 String iface = stacked.getInterfaceName();
1495 if (!stacked.equals(target.mStackedLinks.get(iface))) {
1496 return false;
1497 }
1498 }
1499 return true;
1500 }
1501
sy.yun4aa73922013-09-02 05:24:09 +09001502 /**
1503 * Compares this {@code LinkProperties} MTU against the target
1504 *
Ying Wangcb5620b2013-09-06 22:53:16 -07001505 * @param target LinkProperties to compare.
sy.yun4aa73922013-09-02 05:24:09 +09001506 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001507 * @hide
sy.yun4aa73922013-09-02 05:24:09 +09001508 */
paulhucbbc3db2019-03-08 16:35:20 +08001509 public boolean isIdenticalMtu(@NonNull LinkProperties target) {
sy.yun4aa73922013-09-02 05:24:09 +09001510 return getMtu() == target.getMtu();
1511 }
1512
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001513 /**
1514 * Compares this {@code LinkProperties} Tcp buffer sizes against the target.
1515 *
1516 * @param target LinkProperties to compare.
1517 * @return {@code true} if both are identical, {@code false} otherwise.
1518 * @hide
1519 */
paulhucbbc3db2019-03-08 16:35:20 +08001520 public boolean isIdenticalTcpBufferSizes(@NonNull LinkProperties target) {
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001521 return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes);
1522 }
1523
John Wang3e567d52011-04-04 12:35:42 -07001524 /**
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001525 * Compares this {@code LinkProperties} NAT64 prefix against the target.
1526 *
1527 * @param target LinkProperties to compare.
1528 * @return {@code true} if both are identical, {@code false} otherwise.
1529 * @hide
1530 */
paulhucbbc3db2019-03-08 16:35:20 +08001531 public boolean isIdenticalNat64Prefix(@NonNull LinkProperties target) {
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001532 return Objects.equals(mNat64Prefix, target.mNat64Prefix);
1533 }
1534
1535 /**
Valentin Iftime9fa35092019-09-24 13:32:13 +02001536 * Compares this {@code LinkProperties} WakeOnLan supported against the target.
1537 *
1538 * @param target LinkProperties to compare.
1539 * @return {@code true} if both are identical, {@code false} otherwise.
1540 * @hide
1541 */
1542 public boolean isIdenticalWakeOnLan(LinkProperties target) {
1543 return isWakeOnLanSupported() == target.isWakeOnLanSupported();
1544 }
1545
1546 /**
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001547 * Compares this {@code LinkProperties}'s CaptivePortalApiUrl against the target.
1548 *
1549 * @param target LinkProperties to compare.
1550 * @return {@code true} if both are identical, {@code false} otherwise.
1551 * @hide
1552 */
1553 public boolean isIdenticalCaptivePortalApiUrl(LinkProperties target) {
1554 return Objects.equals(mCaptivePortalApiUrl, target.mCaptivePortalApiUrl);
1555 }
1556
1557 /**
1558 * Compares this {@code LinkProperties}'s CaptivePortalData against the target.
1559 *
1560 * @param target LinkProperties to compare.
1561 * @return {@code true} if both are identical, {@code false} otherwise.
1562 * @hide
1563 */
1564 public boolean isIdenticalCaptivePortalData(LinkProperties target) {
1565 return Objects.equals(mCaptivePortalData, target.mCaptivePortalData);
1566 }
1567
1568 /**
Valentin Iftime9fa35092019-09-24 13:32:13 +02001569 * Set whether the network interface supports WakeOnLAN
1570 *
1571 * @param supported WakeOnLAN supported value
1572 *
1573 * @hide
1574 */
1575 public void setWakeOnLanSupported(boolean supported) {
1576 mWakeOnLanSupported = supported;
1577 }
1578
1579 /**
1580 * Returns whether the network interface supports WakeOnLAN
1581 *
1582 * @return {@code true} if interface supports WakeOnLAN, {@code false} otherwise.
1583 */
1584 public boolean isWakeOnLanSupported() {
1585 return mWakeOnLanSupported;
1586 }
1587
1588 /**
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001589 * Set the URL of the captive portal API endpoint to get more information about the network.
1590 * @hide
1591 */
1592 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001593 public void setCaptivePortalApiUrl(@Nullable Uri url) {
1594 mCaptivePortalApiUrl = url;
1595 }
1596
1597 /**
1598 * Get the URL of the captive portal API endpoint to get more information about the network.
1599 *
1600 * <p>This is null unless the application has
1601 * {@link android.Manifest.permission.NETWORK_SETTINGS} or
1602 * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions, and the network provided
1603 * the URL.
1604 * @hide
1605 */
1606 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001607 @Nullable
1608 public Uri getCaptivePortalApiUrl() {
1609 return mCaptivePortalApiUrl;
1610 }
1611
1612 /**
1613 * Set the CaptivePortalData obtained from the captive portal API (RFC7710bis).
1614 * @hide
1615 */
1616 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001617 public void setCaptivePortalData(@Nullable CaptivePortalData data) {
1618 mCaptivePortalData = data;
1619 }
1620
1621 /**
1622 * Get the CaptivePortalData obtained from the captive portal API (RFC7710bis).
1623 *
1624 * <p>This is null unless the application has
1625 * {@link android.Manifest.permission.NETWORK_SETTINGS} or
1626 * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions.
1627 * @hide
1628 */
1629 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001630 @Nullable
1631 public CaptivePortalData getCaptivePortalData() {
1632 return mCaptivePortalData;
1633 }
1634
1635 /**
John Wang3e567d52011-04-04 12:35:42 -07001636 * Compares this {@code LinkProperties} instance against the target
1637 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
1638 * all their fields are equal in values.
1639 *
1640 * For collection fields, such as mDnses, containsAll() is used to check
1641 * if two collections contains the same elements, independent of order.
1642 * There are two thoughts regarding containsAll()
1643 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
1644 * 2. Worst case performance is O(n^2).
1645 *
1646 * @param obj the object to be tested for equality.
1647 * @return {@code true} if both objects are equal, {@code false} otherwise.
1648 */
Chalard Jeand51966a2018-06-07 13:27:00 +09001649 @Override
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -07001650 public boolean equals(@Nullable Object obj) {
John Wang3e567d52011-04-04 12:35:42 -07001651 if (this == obj) return true;
1652
1653 if (!(obj instanceof LinkProperties)) return false;
1654
John Wang3e567d52011-04-04 12:35:42 -07001655 LinkProperties target = (LinkProperties) obj;
Chalard Jeand51966a2018-06-07 13:27:00 +09001656 /*
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001657 * This method does not check that stacked interfaces are equal, because
1658 * stacked interfaces are not so much a property of the link as a
1659 * description of connections between links.
1660 */
dalyk7643abc2018-01-17 14:20:55 -05001661 return isIdenticalInterfaceName(target)
1662 && isIdenticalAddresses(target)
ruibin zhangca75bc82019-05-23 19:35:30 +08001663 && isIdenticalDhcpServerAddress(target)
dalyk7643abc2018-01-17 14:20:55 -05001664 && isIdenticalDnses(target)
1665 && isIdenticalPrivateDns(target)
Chalard Jean299d8562018-04-11 16:36:41 +09001666 && isIdenticalValidatedPrivateDnses(target)
Hongshike2d7cf52018-06-28 20:42:19 +09001667 && isIdenticalPcscfs(target)
dalyk7643abc2018-01-17 14:20:55 -05001668 && isIdenticalRoutes(target)
1669 && isIdenticalHttpProxy(target)
1670 && isIdenticalStackedLinks(target)
1671 && isIdenticalMtu(target)
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001672 && isIdenticalTcpBufferSizes(target)
Valentin Iftime9fa35092019-09-24 13:32:13 +02001673 && isIdenticalNat64Prefix(target)
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001674 && isIdenticalWakeOnLan(target)
1675 && isIdenticalCaptivePortalApiUrl(target)
1676 && isIdenticalCaptivePortalData(target);
Wink Saville051a6642011-07-13 13:44:13 -07001677 }
John Wang3e567d52011-04-04 12:35:42 -07001678
Wink Saville051a6642011-07-13 13:44:13 -07001679 /**
Chalard Jeand51966a2018-06-07 13:27:00 +09001680 * Generate hashcode based on significant fields
1681 *
John Wang3e567d52011-04-04 12:35:42 -07001682 * Equal objects must produce the same hash code, while unequal objects
1683 * may have the same hash codes.
1684 */
Chalard Jeand51966a2018-06-07 13:27:00 +09001685 @Override
John Wang3e567d52011-04-04 12:35:42 -07001686 public int hashCode() {
1687 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
1688 + mLinkAddresses.size() * 31
1689 + mDnses.size() * 37
Chalard Jean299d8562018-04-11 16:36:41 +09001690 + mValidatedPrivateDnses.size() * 61
Robert Greenwaltcd277852012-11-09 10:52:27 -08001691 + ((null == mDomains) ? 0 : mDomains.hashCode())
Robert Greenwalt5a901292011-04-28 14:28:50 -07001692 + mRoutes.size() * 41
Lorenzo Colittic0803122013-03-07 10:59:25 -08001693 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
sy.yun4aa73922013-09-02 05:24:09 +09001694 + mStackedLinks.hashCode() * 47)
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001695 + mMtu * 51
dalyk7643abc2018-01-17 14:20:55 -05001696 + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
1697 + (mUsePrivateDns ? 57 : 0)
ruibin zhangca75bc82019-05-23 19:35:30 +08001698 + ((null == mDhcpServerAddress) ? 0 : mDhcpServerAddress.hashCode())
Hongshike2d7cf52018-06-28 20:42:19 +09001699 + mPcscfs.size() * 67
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001700 + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
Valentin Iftime9fa35092019-09-24 13:32:13 +02001701 + Objects.hash(mNat64Prefix)
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001702 + (mWakeOnLanSupported ? 71 : 0)
1703 + Objects.hash(mCaptivePortalApiUrl, mCaptivePortalData);
John Wang3e567d52011-04-04 12:35:42 -07001704 }
1705
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001706 /**
1707 * Implement the Parcelable interface.
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001708 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001709 public void writeToParcel(Parcel dest, int flags) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001710 dest.writeString(getInterfaceName());
Irfan Sherifffb7c9642010-10-01 16:08:28 -07001711 dest.writeInt(mLinkAddresses.size());
Chalard Jean299d8562018-04-11 16:36:41 +09001712 for (LinkAddress linkAddress : mLinkAddresses) {
Irfan Sherifffb7c9642010-10-01 16:08:28 -07001713 dest.writeParcelable(linkAddress, flags);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001714 }
Irfan Sherifffb7c9642010-10-01 16:08:28 -07001715
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001716 writeAddresses(dest, mDnses);
1717 writeAddresses(dest, mValidatedPrivateDnses);
dalyk7643abc2018-01-17 14:20:55 -05001718 dest.writeBoolean(mUsePrivateDns);
1719 dest.writeString(mPrivateDnsServerName);
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001720 writeAddresses(dest, mPcscfs);
Robert Greenwaltcd277852012-11-09 10:52:27 -08001721 dest.writeString(mDomains);
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001722 writeAddress(dest, mDhcpServerAddress);
sy.yun4aa73922013-09-02 05:24:09 +09001723 dest.writeInt(mMtu);
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001724 dest.writeString(mTcpBufferSizes);
Robert Greenwalt5a901292011-04-28 14:28:50 -07001725 dest.writeInt(mRoutes.size());
Chalard Jean299d8562018-04-11 16:36:41 +09001726 for (RouteInfo route : mRoutes) {
Robert Greenwalt5a901292011-04-28 14:28:50 -07001727 dest.writeParcelable(route, flags);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001728 }
Robert Greenwalt5c733972011-02-09 13:56:06 -08001729
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001730 if (mHttpProxy != null) {
1731 dest.writeByte((byte)1);
1732 dest.writeParcelable(mHttpProxy, flags);
1733 } else {
1734 dest.writeByte((byte)0);
1735 }
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001736 dest.writeParcelable(mNat64Prefix, 0);
1737
Chalard Jeand51966a2018-06-07 13:27:00 +09001738 ArrayList<LinkProperties> stackedLinks = new ArrayList<>(mStackedLinks.values());
Lorenzo Colittic0803122013-03-07 10:59:25 -08001739 dest.writeList(stackedLinks);
Valentin Iftime9fa35092019-09-24 13:32:13 +02001740
1741 dest.writeBoolean(mWakeOnLanSupported);
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001742 dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalApiUrl : null, 0);
1743 dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalData : null, 0);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001744 }
1745
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001746 private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
1747 dest.writeInt(list.size());
1748 for (InetAddress d : list) {
1749 writeAddress(dest, d);
1750 }
1751 }
1752
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001753 private static void writeAddress(@NonNull Parcel dest, @Nullable InetAddress addr) {
1754 byte[] addressBytes = (addr == null ? null : addr.getAddress());
1755 dest.writeByteArray(addressBytes);
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001756 if (addr instanceof Inet6Address) {
1757 final Inet6Address v6Addr = (Inet6Address) addr;
1758 final boolean hasScopeId = v6Addr.getScopeId() != 0;
1759 dest.writeBoolean(hasScopeId);
1760 if (hasScopeId) dest.writeInt(v6Addr.getScopeId());
1761 }
1762 }
1763
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001764 @Nullable
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001765 private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
1766 final byte[] addr = p.createByteArray();
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001767 if (addr == null) return null;
1768
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001769 if (addr.length == INET6_ADDR_LENGTH) {
1770 final boolean hasScopeId = p.readBoolean();
1771 final int scopeId = hasScopeId ? p.readInt() : 0;
1772 return Inet6Address.getByAddress(null /* host */, addr, scopeId);
1773 }
1774
1775 return InetAddress.getByAddress(addr);
1776 }
1777
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001778 /**
1779 * Implement the Parcelable interface.
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001780 */
Jeff Sharkeyf8525282019-02-28 12:06:45 -07001781 public static final @android.annotation.NonNull Creator<LinkProperties> CREATOR =
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001782 new Creator<LinkProperties>() {
1783 public LinkProperties createFromParcel(Parcel in) {
1784 LinkProperties netProp = new LinkProperties();
Robert Greenwalt462e5702012-10-31 14:32:53 -07001785
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001786 String iface = in.readString();
1787 if (iface != null) {
Robert Greenwalt462e5702012-10-31 14:32:53 -07001788 netProp.setInterfaceName(iface);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001789 }
1790 int addressCount = in.readInt();
Chalard Jean299d8562018-04-11 16:36:41 +09001791 for (int i = 0; i < addressCount; i++) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001792 netProp.addLinkAddress(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001793 }
1794 addressCount = in.readInt();
Chalard Jean299d8562018-04-11 16:36:41 +09001795 for (int i = 0; i < addressCount; i++) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001796 try {
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001797 netProp.addDnsServer(readAddress(in));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001798 } catch (UnknownHostException e) { }
1799 }
Chalard Jean299d8562018-04-11 16:36:41 +09001800 addressCount = in.readInt();
1801 for (int i = 0; i < addressCount; i++) {
1802 try {
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001803 netProp.addValidatedPrivateDnsServer(readAddress(in));
Chalard Jean299d8562018-04-11 16:36:41 +09001804 } catch (UnknownHostException e) { }
1805 }
dalyk7643abc2018-01-17 14:20:55 -05001806 netProp.setUsePrivateDns(in.readBoolean());
1807 netProp.setPrivateDnsServerName(in.readString());
Hongshike2d7cf52018-06-28 20:42:19 +09001808 addressCount = in.readInt();
1809 for (int i = 0; i < addressCount; i++) {
1810 try {
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001811 netProp.addPcscfServer(readAddress(in));
Hongshike2d7cf52018-06-28 20:42:19 +09001812 } catch (UnknownHostException e) { }
1813 }
Robert Greenwaltcd277852012-11-09 10:52:27 -08001814 netProp.setDomains(in.readString());
ruibin zhangca75bc82019-05-23 19:35:30 +08001815 try {
1816 netProp.setDhcpServerAddress((Inet4Address) InetAddress
1817 .getByAddress(in.createByteArray()));
1818 } catch (UnknownHostException e) { }
sy.yun4aa73922013-09-02 05:24:09 +09001819 netProp.setMtu(in.readInt());
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001820 netProp.setTcpBufferSizes(in.readString());
Robert Greenwalt5c733972011-02-09 13:56:06 -08001821 addressCount = in.readInt();
Chalard Jean299d8562018-04-11 16:36:41 +09001822 for (int i = 0; i < addressCount; i++) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001823 netProp.addRoute(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001824 }
1825 if (in.readByte() == 1) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001826 netProp.setHttpProxy(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001827 }
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001828 netProp.setNat64Prefix(in.readParcelable(null));
Lorenzo Colittic0803122013-03-07 10:59:25 -08001829 ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
1830 in.readList(stackedLinks, LinkProperties.class.getClassLoader());
1831 for (LinkProperties stackedLink: stackedLinks) {
1832 netProp.addStackedLink(stackedLink);
1833 }
Valentin Iftime9fa35092019-09-24 13:32:13 +02001834 netProp.setWakeOnLanSupported(in.readBoolean());
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001835
1836 netProp.setCaptivePortalApiUrl(in.readParcelable(null));
1837 netProp.setCaptivePortalData(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001838 return netProp;
1839 }
1840
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001841 public LinkProperties[] newArray(int size) {
1842 return new LinkProperties[size];
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001843 }
1844 };
w19976e714f1d2014-08-05 15:18:11 -07001845
Chalard Jean299d8562018-04-11 16:36:41 +09001846 /**
1847 * Check the valid MTU range based on IPv4 or IPv6.
1848 * @hide
1849 */
1850 public static boolean isValidMtu(int mtu, boolean ipv6) {
1851 if (ipv6) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001852 return mtu >= MIN_MTU_V6 && mtu <= MAX_MTU;
Chalard Jean299d8562018-04-11 16:36:41 +09001853 } else {
Chalard Jeand51966a2018-06-07 13:27:00 +09001854 return mtu >= MIN_MTU && mtu <= MAX_MTU;
w19976e714f1d2014-08-05 15:18:11 -07001855 }
Chalard Jean299d8562018-04-11 16:36:41 +09001856 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001857}