blob: 80517ce28cda3fbeb1881943b0f44a71253fd9a9 [file] [log] [blame]
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001/*
Wink Saville6e809972010-09-21 09:15:35 -07002 * Copyright (C) 2010 The Android Open Source Project
Robert Greenwalt47f69fe2010-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 Sharkeyeb2c2c72014-08-11 15:22:51 -070019import android.annotation.NonNull;
Jeff Sharkey9da2f1e2014-08-14 12:55:00 -070020import android.annotation.Nullable;
paulhu7610bc72018-12-12 17:52:57 +080021import android.annotation.SystemApi;
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010022import android.annotation.UnsupportedAppUsage;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070023import android.os.Parcel;
Rubin Xu1bb5c082017-09-05 18:40:49 +010024import android.os.Parcelable;
John Wang4e900092011-04-04 12:35:42 -070025import android.text.TextUtils;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070026
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080027import java.net.Inet4Address;
Lorenzo Colitti4faa0272013-08-08 11:00:12 +090028import java.net.Inet6Address;
Rubin Xu1bb5c082017-09-05 18:40:49 +010029import java.net.InetAddress;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070030import java.net.UnknownHostException;
31import java.util.ArrayList;
32import java.util.Collection;
Robert Greenwalt37e65eb2010-08-30 10:56:47 -070033import java.util.Collections;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080034import java.util.Hashtable;
Robert Greenwaltdf2b8782014-06-06 10:30:11 -070035import java.util.List;
Lorenzo Colittic17a1b92014-06-12 23:10:17 +090036import java.util.Objects;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090037import java.util.StringJoiner;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070038
39/**
Robert Greenwalt37e65eb2010-08-30 10:56:47 -070040 * Describes the properties of a network link.
Robert Greenwalt992564e2011-02-09 13:56:06 -080041 *
42 * A link represents a connection to a network.
43 * It may have multiple addresses and multiple gateways,
Robert Greenwalt4f05d552014-05-18 22:01:38 -070044 * multiple dns servers but only one http proxy and one
45 * network interface.
Robert Greenwalt992564e2011-02-09 13:56:06 -080046 *
Robert Greenwalt4f05d552014-05-18 22:01:38 -070047 * Note that this is just a holder of data. Modifying it
48 * does not affect live networks.
Robert Greenwalt992564e2011-02-09 13:56:06 -080049 *
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070050 */
Robert Greenwalte595b972014-06-12 16:24:38 -070051public final class LinkProperties implements Parcelable {
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080052 // The interface described by the network link.
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010053 @UnsupportedAppUsage
Robert Greenwalt4717c262012-10-31 14:32:53 -070054 private String mIfaceName;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090055 private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
56 private ArrayList<InetAddress> mDnses = new ArrayList<>();
57 private ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>();
dalykd9201342018-01-17 14:20:55 -050058 private boolean mUsePrivateDns;
59 private String mPrivateDnsServerName;
Robert Greenwalt8058f622012-11-09 10:52:27 -080060 private String mDomains;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090061 private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
Jason Monk207900c2014-04-25 15:00:09 -040062 private ProxyInfo mHttpProxy;
sy.yun9d9b74a2013-09-02 05:24:09 +090063 private int mMtu;
Robert Greenwalt3f05bf42014-08-06 12:00:25 -070064 // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
65 private String mTcpBufferSizes;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070066
w1997615afd812014-08-05 15:18:11 -070067 private static final int MIN_MTU = 68;
68 private static final int MIN_MTU_V6 = 1280;
69 private static final int MAX_MTU = 10000;
70
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080071 // Stores the properties of links that are "stacked" above this link.
72 // Indexed by interface name to allow modification and to prevent duplicates being added.
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090073 private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080074
Robert Greenwaltdf2b8782014-06-06 10:30:11 -070075 /**
76 * @hide
77 */
Robert Greenwalt0a46db52011-07-14 14:28:05 -070078 public static class CompareResult<T> {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090079 public final List<T> removed = new ArrayList<>();
80 public final List<T> added = new ArrayList<>();
Rubin Xu2fc72f72017-08-22 16:35:52 +010081
82 public CompareResult() {}
83
84 public CompareResult(Collection<T> oldItems, Collection<T> newItems) {
85 if (oldItems != null) {
86 removed.addAll(oldItems);
87 }
88 if (newItems != null) {
89 for (T newItem : newItems) {
90 if (!removed.remove(newItem)) {
91 added.add(newItem);
92 }
93 }
94 }
95 }
Wink Savillee8222252011-07-13 13:44:13 -070096
97 @Override
98 public String toString() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090099 return "removed=[" + TextUtils.join(",", removed)
100 + "] added=[" + TextUtils.join(",", added)
101 + "]";
Wink Savillee8222252011-07-13 13:44:13 -0700102 }
103 }
104
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700105 /**
106 * @hide
107 */
Erik Klinecd7ed162015-05-21 16:15:02 +0900108 public enum ProvisioningChange {
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100109 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900110 STILL_NOT_PROVISIONED,
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100111 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900112 LOST_PROVISIONING,
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100113 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900114 GAINED_PROVISIONING,
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100115 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900116 STILL_PROVISIONED,
117 }
118
119 /**
120 * Compare the provisioning states of two LinkProperties instances.
121 *
122 * @hide
123 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100124 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900125 public static ProvisioningChange compareProvisioning(
126 LinkProperties before, LinkProperties after) {
127 if (before.isProvisioned() && after.isProvisioned()) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900128 // On dual-stack networks, DHCPv4 renewals can occasionally fail.
Erik Klinecd7ed162015-05-21 16:15:02 +0900129 // When this happens, IPv6-reachable services continue to function
130 // normally but IPv4-only services (naturally) fail.
131 //
132 // When an application using an IPv4-only service reports a bad
133 // network condition to the framework, attempts to re-validate
134 // the network succeed (since we support IPv6-only networks) and
135 // nothing is changed.
136 //
137 // For users, this is confusing and unexpected behaviour, and is
138 // not necessarily easy to diagnose. Therefore, we treat changing
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900139 // from a dual-stack network to an IPv6-only network equivalent to
Erik Klinecd7ed162015-05-21 16:15:02 +0900140 // a total loss of provisioning.
141 //
142 // For one such example of this, see b/18867306.
143 //
Erik Kline1ad4e222015-08-14 12:16:55 +0900144 // Additionally, losing IPv6 provisioning can result in TCP
145 // connections getting stuck until timeouts fire and other
146 // baffling failures. Therefore, loss of either IPv4 or IPv6 on a
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900147 // previously dual-stack network is deemed a lost of provisioning.
Erik Kline1ad4e222015-08-14 12:16:55 +0900148 if ((before.isIPv4Provisioned() && !after.isIPv4Provisioned()) ||
149 (before.isIPv6Provisioned() && !after.isIPv6Provisioned())) {
Erik Klinecd7ed162015-05-21 16:15:02 +0900150 return ProvisioningChange.LOST_PROVISIONING;
151 }
152 return ProvisioningChange.STILL_PROVISIONED;
153 } else if (before.isProvisioned() && !after.isProvisioned()) {
154 return ProvisioningChange.LOST_PROVISIONING;
155 } else if (!before.isProvisioned() && after.isProvisioned()) {
156 return ProvisioningChange.GAINED_PROVISIONING;
157 } else { // !before.isProvisioned() && !after.isProvisioned()
158 return ProvisioningChange.STILL_NOT_PROVISIONED;
159 }
160 }
161
162 /**
163 * @hide
164 */
paulhu7610bc72018-12-12 17:52:57 +0800165 @SystemApi
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700166 public LinkProperties() {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700167 }
168
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700169 /**
170 * @hide
171 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100172 @UnsupportedAppUsage
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700173 public LinkProperties(LinkProperties source) {
Irfan Sheriffef6c1432010-08-30 20:37:17 -0700174 if (source != null) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900175 mIfaceName = source.mIfaceName;
176 mLinkAddresses.addAll(source.mLinkAddresses);
177 mDnses.addAll(source.mDnses);
178 mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
dalykd9201342018-01-17 14:20:55 -0500179 mUsePrivateDns = source.mUsePrivateDns;
180 mPrivateDnsServerName = source.mPrivateDnsServerName;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900181 mDomains = source.mDomains;
182 mRoutes.addAll(source.mRoutes);
183 mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800184 for (LinkProperties l: source.mStackedLinks.values()) {
185 addStackedLink(l);
186 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900187 setMtu(source.mMtu);
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700188 mTcpBufferSizes = source.mTcpBufferSizes;
Irfan Sheriffef6c1432010-08-30 20:37:17 -0700189 }
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700190 }
191
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700192 /**
193 * Sets the interface name for this link. All {@link RouteInfo} already set for this
194 * will have their interface changed to match this new value.
195 *
196 * @param iface The name of the network interface used for this link.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700197 * @hide
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700198 */
paulhu7610bc72018-12-12 17:52:57 +0800199 @SystemApi
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700200 public void setInterfaceName(String iface) {
201 mIfaceName = iface;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900202 ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800203 for (RouteInfo route : mRoutes) {
204 newRoutes.add(routeWithInterface(route));
205 }
206 mRoutes = newRoutes;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700207 }
208
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700209 /**
210 * Gets the interface name for this link. May be {@code null} if not set.
211 *
212 * @return The interface name set for this link or {@code null}.
213 */
Jeff Sharkey9da2f1e2014-08-14 12:55:00 -0700214 public @Nullable String getInterfaceName() {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700215 return mIfaceName;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700216 }
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700217
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700218 /**
219 * @hide
220 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100221 @UnsupportedAppUsage
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700222 public List<String> getAllInterfaceNames() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900223 List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1);
224 if (mIfaceName != null) interfaceNames.add(mIfaceName);
Lorenzo Colitti4aa9bcf2013-03-20 19:22:58 +0900225 for (LinkProperties stacked: mStackedLinks.values()) {
226 interfaceNames.addAll(stacked.getAllInterfaceNames());
227 }
228 return interfaceNames;
229 }
230
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900231 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700232 * Returns all the addresses on this link. We often think of a link having a single address,
233 * however, particularly with Ipv6 several addresses are typical. Note that the
234 * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include
235 * prefix lengths for each address. This is a simplified utility alternative to
236 * {@link LinkProperties#getLinkAddresses}.
237 *
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900238 * @return An unmodifiable {@link List} of {@link InetAddress} for this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700239 * @hide
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900240 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100241 @UnsupportedAppUsage
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700242 public List<InetAddress> getAddresses() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900243 List<InetAddress> addresses = new ArrayList<>();
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700244 for (LinkAddress linkAddress : mLinkAddresses) {
245 addresses.add(linkAddress.getAddress());
246 }
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700247 return Collections.unmodifiableList(addresses);
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700248 }
249
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900250 /**
251 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700252 * @hide
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900253 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100254 @UnsupportedAppUsage
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700255 public List<InetAddress> getAllAddresses() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900256 List<InetAddress> addresses = new ArrayList<>();
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900257 for (LinkAddress linkAddress : mLinkAddresses) {
258 addresses.add(linkAddress.getAddress());
259 }
260 for (LinkProperties stacked: mStackedLinks.values()) {
261 addresses.addAll(stacked.getAllAddresses());
262 }
263 return addresses;
264 }
265
Lorenzo Colitti64483942013-11-15 18:43:52 +0900266 private int findLinkAddressIndex(LinkAddress address) {
267 for (int i = 0; i < mLinkAddresses.size(); i++) {
268 if (mLinkAddresses.get(i).isSameAddressAs(address)) {
269 return i;
270 }
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900271 }
Lorenzo Colitti64483942013-11-15 18:43:52 +0900272 return -1;
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900273 }
274
275 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700276 * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the
277 * same address/prefix does not already exist. If it does exist it is replaced.
Lorenzo Colitti64483942013-11-15 18:43:52 +0900278 * @param address The {@code LinkAddress} to add.
279 * @return true if {@code address} was added or updated, false otherwise.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700280 * @hide
Lorenzo Colitti64483942013-11-15 18:43:52 +0900281 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100282 @UnsupportedAppUsage
Lorenzo Colitti64483942013-11-15 18:43:52 +0900283 public boolean addLinkAddress(LinkAddress address) {
284 if (address == null) {
285 return false;
286 }
287 int i = findLinkAddressIndex(address);
288 if (i < 0) {
289 // Address was not present. Add it.
290 mLinkAddresses.add(address);
291 return true;
292 } else if (mLinkAddresses.get(i).equals(address)) {
293 // Address was present and has same properties. Do nothing.
294 return false;
295 } else {
296 // Address was present and has different properties. Update it.
297 mLinkAddresses.set(i, address);
298 return true;
299 }
300 }
301
302 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700303 * Removes a {@link LinkAddress} from this {@code LinkProperties}. Specifically, matches
304 * and {@link LinkAddress} with the same address and prefix.
305 *
306 * @param toRemove A {@link LinkAddress} specifying the address to remove.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900307 * @return true if the address was removed, false if it did not exist.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700308 * @hide
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900309 */
310 public boolean removeLinkAddress(LinkAddress toRemove) {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900311 int i = findLinkAddressIndex(toRemove);
312 if (i >= 0) {
313 mLinkAddresses.remove(i);
314 return true;
315 }
316 return false;
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700317 }
318
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900319 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700320 * Returns all the {@link LinkAddress} on this link. Typically a link will have
321 * one IPv4 address and one or more IPv6 addresses.
322 *
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700323 * @return An unmodifiable {@link List} of {@link LinkAddress} for this link.
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900324 */
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700325 public List<LinkAddress> getLinkAddresses() {
326 return Collections.unmodifiableList(mLinkAddresses);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700327 }
328
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900329 /**
330 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700331 * @hide
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900332 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100333 @UnsupportedAppUsage
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700334 public List<LinkAddress> getAllLinkAddresses() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900335 List<LinkAddress> addresses = new ArrayList<>(mLinkAddresses);
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900336 for (LinkProperties stacked: mStackedLinks.values()) {
337 addresses.addAll(stacked.getAllLinkAddresses());
338 }
339 return addresses;
340 }
341
Lorenzo Colitti22f407b2013-08-23 20:54:49 +0900342 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700343 * Replaces the {@link LinkAddress} in this {@code LinkProperties} with
344 * the given {@link Collection} of {@link LinkAddress}.
345 *
346 * @param addresses The {@link Collection} of {@link LinkAddress} to set in this
347 * object.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700348 * @hide
Lorenzo Colitti22f407b2013-08-23 20:54:49 +0900349 */
paulhu7610bc72018-12-12 17:52:57 +0800350 @SystemApi
Lorenzo Colitti22f407b2013-08-23 20:54:49 +0900351 public void setLinkAddresses(Collection<LinkAddress> addresses) {
352 mLinkAddresses.clear();
353 for (LinkAddress address: addresses) {
354 addLinkAddress(address);
355 }
356 }
357
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700358 /**
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900359 * Adds the given {@link InetAddress} to the list of DNS servers, if not present.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700360 *
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700361 * @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900362 * @return true if the DNS server was added, false if it was already present.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700363 * @hide
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700364 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100365 @UnsupportedAppUsage
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900366 public boolean addDnsServer(InetAddress dnsServer) {
367 if (dnsServer != null && !mDnses.contains(dnsServer)) {
368 mDnses.add(dnsServer);
369 return true;
370 }
371 return false;
372 }
373
374 /**
Erik Klinecd7ed162015-05-21 16:15:02 +0900375 * Removes the given {@link InetAddress} from the list of DNS servers.
376 *
377 * @param dnsServer The {@link InetAddress} to remove from the list of DNS servers.
378 * @return true if the DNS server was removed, false if it did not exist.
379 * @hide
380 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100381 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900382 public boolean removeDnsServer(InetAddress dnsServer) {
383 if (dnsServer != null) {
384 return mDnses.remove(dnsServer);
385 }
386 return false;
387 }
388
389 /**
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900390 * Replaces the DNS servers in this {@code LinkProperties} with
391 * the given {@link Collection} of {@link InetAddress} objects.
392 *
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900393 * @param dnsServers The {@link Collection} of DNS servers to set in this object.
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900394 * @hide
395 */
paulhu7610bc72018-12-12 17:52:57 +0800396 @SystemApi
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900397 public void setDnsServers(Collection<InetAddress> dnsServers) {
398 mDnses.clear();
399 for (InetAddress dnsServer: dnsServers) {
400 addDnsServer(dnsServer);
401 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700402 }
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700403
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700404 /**
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700405 * Returns all the {@link InetAddress} for DNS servers on this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700406 *
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900407 * @return An unmodifiable {@link List} of {@link InetAddress} for DNS servers on
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700408 * this link.
409 */
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700410 public List<InetAddress> getDnsServers() {
411 return Collections.unmodifiableList(mDnses);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700412 }
413
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700414 /**
dalykd9201342018-01-17 14:20:55 -0500415 * Set whether private DNS is currently in use on this network.
416 *
417 * @param usePrivateDns The private DNS state.
418 * @hide
419 */
420 public void setUsePrivateDns(boolean usePrivateDns) {
421 mUsePrivateDns = usePrivateDns;
422 }
423
424 /**
425 * Returns whether private DNS is currently in use on this network. When
426 * private DNS is in use, applications must not send unencrypted DNS
427 * queries as doing so could reveal private user information. Furthermore,
428 * if private DNS is in use and {@link #getPrivateDnsServerName} is not
429 * {@code null}, DNS queries must be sent to the specified DNS server.
430 *
431 * @return {@code true} if private DNS is in use, {@code false} otherwise.
432 */
433 public boolean isPrivateDnsActive() {
434 return mUsePrivateDns;
435 }
436
437 /**
438 * Set the name of the private DNS server to which private DNS queries
439 * should be sent when in strict mode. This value should be {@code null}
440 * when private DNS is off or in opportunistic mode.
441 *
442 * @param privateDnsServerName The private DNS server name.
443 * @hide
444 */
445 public void setPrivateDnsServerName(@Nullable String privateDnsServerName) {
446 mPrivateDnsServerName = privateDnsServerName;
447 }
448
449 /**
450 * Returns the private DNS server name that is in use. If not {@code null},
451 * private DNS is in strict mode. In this mode, applications should ensure
452 * that all DNS queries are encrypted and sent to this hostname and that
453 * queries are only sent if the hostname's certificate is valid. If
454 * {@code null} and {@link #isPrivateDnsActive} is {@code true}, private
455 * DNS is in opportunistic mode, and applications should ensure that DNS
456 * queries are encrypted and sent to a DNS server returned by
457 * {@link #getDnsServers}. System DNS will handle each of these cases
458 * correctly, but applications implementing their own DNS lookups must make
459 * sure to follow these requirements.
460 *
461 * @return The private DNS server name.
462 */
463 public @Nullable String getPrivateDnsServerName() {
464 return mPrivateDnsServerName;
465 }
466
467 /**
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900468 * Adds the given {@link InetAddress} to the list of validated private DNS servers,
469 * if not present. This is distinct from the server name in that these are actually
470 * resolved addresses.
471 *
472 * @param dnsServer The {@link InetAddress} to add to the list of validated private DNS servers.
473 * @return true if the DNS server was added, false if it was already present.
474 * @hide
475 */
476 public boolean addValidatedPrivateDnsServer(InetAddress dnsServer) {
477 if (dnsServer != null && !mValidatedPrivateDnses.contains(dnsServer)) {
478 mValidatedPrivateDnses.add(dnsServer);
479 return true;
480 }
481 return false;
482 }
483
484 /**
485 * Removes the given {@link InetAddress} from the list of validated private DNS servers.
486 *
487 * @param dnsServer The {@link InetAddress} to remove from the list of validated private DNS
488 * servers.
489 * @return true if the DNS server was removed, false if it did not exist.
490 * @hide
491 */
492 public boolean removeValidatedPrivateDnsServer(InetAddress dnsServer) {
493 if (dnsServer != null) {
494 return mValidatedPrivateDnses.remove(dnsServer);
495 }
496 return false;
497 }
498
499 /**
500 * Replaces the validated private DNS servers in this {@code LinkProperties} with
501 * the given {@link Collection} of {@link InetAddress} objects.
502 *
503 * @param dnsServers The {@link Collection} of validated private DNS servers to set in this
504 * object.
505 * @hide
506 */
507 public void setValidatedPrivateDnsServers(Collection<InetAddress> dnsServers) {
508 mValidatedPrivateDnses.clear();
509 for (InetAddress dnsServer: dnsServers) {
510 addValidatedPrivateDnsServer(dnsServer);
511 }
512 }
513
514 /**
515 * Returns all the {@link InetAddress} for validated private DNS servers on this link.
516 * These are resolved from the private DNS server name.
517 *
518 * @return An umodifiable {@link List} of {@link InetAddress} for validated private
519 * DNS servers on this link.
520 * @hide
521 */
522 public List<InetAddress> getValidatedPrivateDnsServers() {
523 return Collections.unmodifiableList(mValidatedPrivateDnses);
524 }
525
526 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700527 * Sets the DNS domain search path used on this link.
528 *
529 * @param domains A {@link String} listing in priority order the comma separated
530 * domains to search when resolving host names on this link.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700531 * @hide
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700532 */
paulhu7610bc72018-12-12 17:52:57 +0800533 @SystemApi
Robert Greenwalt8058f622012-11-09 10:52:27 -0800534 public void setDomains(String domains) {
535 mDomains = domains;
536 }
537
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700538 /**
539 * Get the DNS domains search path set for this link.
540 *
541 * @return A {@link String} containing the comma separated domains to search when resolving
542 * host names on this link.
543 */
544 public String getDomains() {
545 return mDomains;
546 }
547
548 /**
549 * Sets the Maximum Transmission Unit size to use on this link. This should not be used
550 * unless the system default (1500) is incorrect. Values less than 68 or greater than
551 * 10000 will be ignored.
552 *
553 * @param mtu The MTU to use for this link.
554 * @hide
555 */
paulhu7610bc72018-12-12 17:52:57 +0800556 @SystemApi
sy.yun9d9b74a2013-09-02 05:24:09 +0900557 public void setMtu(int mtu) {
558 mMtu = mtu;
559 }
560
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700561 /**
562 * Gets any non-default MTU size set for this link. Note that if the default is being used
563 * this will return 0.
564 *
565 * @return The mtu value set for this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700566 */
sy.yun9d9b74a2013-09-02 05:24:09 +0900567 public int getMtu() {
568 return mMtu;
569 }
570
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700571 /**
572 * Sets the tcp buffers sizes to be used when this link is the system default.
573 * Should be of the form "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max".
574 *
575 * @param tcpBufferSizes The tcp buffers sizes to use.
576 *
577 * @hide
578 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100579 @UnsupportedAppUsage
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700580 public void setTcpBufferSizes(String tcpBufferSizes) {
581 mTcpBufferSizes = tcpBufferSizes;
582 }
583
584 /**
585 * Gets the tcp buffer sizes.
586 *
587 * @return the tcp buffer sizes to use when this link is the system default.
588 *
589 * @hide
590 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100591 @UnsupportedAppUsage
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700592 public String getTcpBufferSizes() {
593 return mTcpBufferSizes;
594 }
595
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800596 private RouteInfo routeWithInterface(RouteInfo route) {
597 return new RouteInfo(
598 route.getDestination(),
599 route.getGateway(),
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900600 mIfaceName,
601 route.getType());
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700602 }
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800603
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700604 /**
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900605 * Adds a {@link RouteInfo} to this {@code LinkProperties}, if not present. If the
606 * {@link RouteInfo} had an interface name set and that differs from the interface set for this
607 * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. The proper
608 * course is to add either un-named or properly named {@link RouteInfo}.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700609 *
610 * @param route A {@link RouteInfo} to add to this object.
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900611 * @return {@code false} if the route was already present, {@code true} if it was added.
612 *
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700613 * @hide
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700614 */
paulhu7610bc72018-12-12 17:52:57 +0800615 @SystemApi
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900616 public boolean addRoute(RouteInfo route) {
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800617 if (route != null) {
618 String routeIface = route.getInterface();
619 if (routeIface != null && !routeIface.equals(mIfaceName)) {
Lorenzo Colitti1994bc12013-03-08 19:11:40 -0800620 throw new IllegalArgumentException(
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800621 "Route added with non-matching interface: " + routeIface +
Lorenzo Colitti1994bc12013-03-08 19:11:40 -0800622 " vs. " + mIfaceName);
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800623 }
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900624 route = routeWithInterface(route);
625 if (!mRoutes.contains(route)) {
626 mRoutes.add(route);
627 return true;
628 }
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800629 }
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900630 return false;
631 }
632
633 /**
634 * Removes a {@link RouteInfo} from this {@code LinkProperties}, if present. The route must
635 * specify an interface and the interface must match the interface of this
636 * {@code LinkProperties}, or it will not be removed.
637 *
638 * @return {@code true} if the route was removed, {@code false} if it was not present.
639 *
640 * @hide
641 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100642 @UnsupportedAppUsage
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900643 public boolean removeRoute(RouteInfo route) {
644 return route != null &&
645 Objects.equals(mIfaceName, route.getInterface()) &&
646 mRoutes.remove(route);
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800647 }
648
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800649 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700650 * Returns all the {@link RouteInfo} set on this link.
651 *
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700652 * @return An unmodifiable {@link List} of {@link RouteInfo} for this link.
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800653 */
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700654 public List<RouteInfo> getRoutes() {
655 return Collections.unmodifiableList(mRoutes);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700656 }
657
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800658 /**
Rubin Xu1bb5c082017-09-05 18:40:49 +0100659 * Make sure this LinkProperties instance contains routes that cover the local subnet
660 * of its link addresses. Add any route that is missing.
661 * @hide
662 */
663 public void ensureDirectlyConnectedRoutes() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900664 for (LinkAddress addr : mLinkAddresses) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100665 addRoute(new RouteInfo(addr, null, mIfaceName));
666 }
667 }
668
669 /**
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800670 * Returns all the routes on this link and all the links stacked above it.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700671 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800672 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100673 @UnsupportedAppUsage
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700674 public List<RouteInfo> getAllRoutes() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900675 List<RouteInfo> routes = new ArrayList<>(mRoutes);
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800676 for (LinkProperties stacked: mStackedLinks.values()) {
677 routes.addAll(stacked.getAllRoutes());
678 }
Robert Greenwalt6629bcd2013-03-15 11:28:50 -0700679 return routes;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800680 }
681
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700682 /**
683 * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none.
684 * Note that Http Proxies are only a hint - the system recommends their use, but it does
685 * not enforce it and applications may ignore them.
686 *
Erik Klineb36a3132015-06-26 19:21:34 +0900687 * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700688 * @hide
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700689 */
paulhu7610bc72018-12-12 17:52:57 +0800690 @SystemApi
Jason Monk207900c2014-04-25 15:00:09 -0400691 public void setHttpProxy(ProxyInfo proxy) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700692 mHttpProxy = proxy;
693 }
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700694
695 /**
696 * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link.
697 *
698 * @return The {@link ProxyInfo} set on this link
699 */
Jason Monk207900c2014-04-25 15:00:09 -0400700 public ProxyInfo getHttpProxy() {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700701 return mHttpProxy;
702 }
703
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800704 /**
705 * Adds a stacked link.
706 *
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900707 * If there is already a stacked link with the same interface name as link,
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800708 * that link is replaced with link. Otherwise, link is added to the list
709 * of stacked links. If link is null, nothing changes.
710 *
711 * @param link The link to add.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900712 * @return true if the link was stacked, false otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700713 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800714 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100715 @UnsupportedAppUsage
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900716 public boolean addStackedLink(LinkProperties link) {
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800717 if (link != null && link.getInterfaceName() != null) {
718 mStackedLinks.put(link.getInterfaceName(), link);
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900719 return true;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800720 }
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900721 return false;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800722 }
723
724 /**
725 * Removes a stacked link.
726 *
Lorenzo Colittif3cab632014-10-20 11:08:03 +0900727 * If there is a stacked link with the given interface name, it is
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800728 * removed. Otherwise, nothing changes.
729 *
Lorenzo Colittif3cab632014-10-20 11:08:03 +0900730 * @param iface The interface name of the link to remove.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900731 * @return true if the link was removed, false otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700732 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800733 */
Lorenzo Colittif3cab632014-10-20 11:08:03 +0900734 public boolean removeStackedLink(String iface) {
735 if (iface != null) {
736 LinkProperties removed = mStackedLinks.remove(iface);
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900737 return removed != null;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800738 }
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900739 return false;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800740 }
741
742 /**
743 * Returns all the links stacked on top of this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700744 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800745 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100746 @UnsupportedAppUsage
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700747 public @NonNull List<LinkProperties> getStackedLinks() {
748 if (mStackedLinks.isEmpty()) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900749 return Collections.emptyList();
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700750 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900751 List<LinkProperties> stacked = new ArrayList<>();
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800752 for (LinkProperties link : mStackedLinks.values()) {
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700753 stacked.add(new LinkProperties(link));
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800754 }
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700755 return Collections.unmodifiableList(stacked);
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800756 }
757
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700758 /**
759 * Clears this object to its initial state.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700760 * @hide
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700761 */
paulhu7610bc72018-12-12 17:52:57 +0800762 @SystemApi
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700763 public void clear() {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700764 mIfaceName = null;
Wink Savillee8222252011-07-13 13:44:13 -0700765 mLinkAddresses.clear();
766 mDnses.clear();
dalykd9201342018-01-17 14:20:55 -0500767 mUsePrivateDns = false;
768 mPrivateDnsServerName = null;
Robert Greenwalt8058f622012-11-09 10:52:27 -0800769 mDomains = null;
Wink Savillee8222252011-07-13 13:44:13 -0700770 mRoutes.clear();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700771 mHttpProxy = null;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800772 mStackedLinks.clear();
sy.yun9d9b74a2013-09-02 05:24:09 +0900773 mMtu = 0;
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700774 mTcpBufferSizes = null;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700775 }
776
777 /**
778 * Implement the Parcelable interface
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700779 */
780 public int describeContents() {
781 return 0;
782 }
783
Wink Saville1f6408a2010-08-27 11:15:18 -0700784 @Override
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700785 public String toString() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900786 // Space as a separator, so no need for spaces at start/end of the individual fragments.
787 final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700788
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900789 if (mIfaceName != null) {
790 resultJoiner.add("InterfaceName:");
791 resultJoiner.add(mIfaceName);
792 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700793
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900794 resultJoiner.add("LinkAddresses: [");
795 if (!mLinkAddresses.isEmpty()) {
796 resultJoiner.add(TextUtils.join(",", mLinkAddresses));
797 }
798 resultJoiner.add("]");
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700799
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900800 resultJoiner.add("DnsAddresses: [");
801 if (!mDnses.isEmpty()) {
802 resultJoiner.add(TextUtils.join(",", mDnses));
803 }
804 resultJoiner.add("]");
dalykd9201342018-01-17 14:20:55 -0500805
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900806 if (mUsePrivateDns) {
807 resultJoiner.add("UsePrivateDns: true");
808 }
809
Chalard Jeanfaaf2fe2018-06-07 13:28:09 +0900810 if (mPrivateDnsServerName != null) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900811 resultJoiner.add("PrivateDnsServerName:");
812 resultJoiner.add(mPrivateDnsServerName);
dalykd9201342018-01-17 14:20:55 -0500813 }
814
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900815 if (!mValidatedPrivateDnses.isEmpty()) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900816 final StringJoiner validatedPrivateDnsesJoiner =
817 new StringJoiner(",", "ValidatedPrivateDnsAddresses: [", "]");
818 for (final InetAddress addr : mValidatedPrivateDnses) {
819 validatedPrivateDnsesJoiner.add(addr.getHostAddress());
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900820 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900821 resultJoiner.add(validatedPrivateDnsesJoiner.toString());
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900822 }
823
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900824 resultJoiner.add("Domains:");
825 resultJoiner.add(mDomains);
Robert Greenwalt8058f622012-11-09 10:52:27 -0800826
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900827 resultJoiner.add("MTU:");
828 resultJoiner.add(Integer.toString(mMtu));
sy.yun9d9b74a2013-09-02 05:24:09 +0900829
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700830 if (mTcpBufferSizes != null) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900831 resultJoiner.add("TcpBufferSizes:");
832 resultJoiner.add(mTcpBufferSizes);
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700833 }
834
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900835 resultJoiner.add("Routes: [");
836 if (!mRoutes.isEmpty()) {
837 resultJoiner.add(TextUtils.join(",", mRoutes));
838 }
839 resultJoiner.add("]");
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700840
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900841 if (mHttpProxy != null) {
842 resultJoiner.add("HttpProxy:");
843 resultJoiner.add(mHttpProxy.toString());
844 }
845
846 final Collection<LinkProperties> stackedLinksValues = mStackedLinks.values();
847 if (!stackedLinksValues.isEmpty()) {
848 final StringJoiner stackedLinksJoiner = new StringJoiner(",", "Stacked: [", "]");
849 for (final LinkProperties lp : stackedLinksValues) {
850 stackedLinksJoiner.add("[ " + lp + " ]");
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800851 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900852 resultJoiner.add(stackedLinksJoiner.toString());
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800853 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900854
855 return resultJoiner.toString();
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800856 }
857
858 /**
859 * Returns true if this link has an IPv4 address.
860 *
861 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700862 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800863 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100864 @UnsupportedAppUsage
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800865 public boolean hasIPv4Address() {
866 for (LinkAddress address : mLinkAddresses) {
Hugo Benichibd87a392017-10-10 16:29:06 +0900867 if (address.getAddress() instanceof Inet4Address) {
868 return true;
869 }
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800870 }
871 return false;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700872 }
873
Wink Savillee8222252011-07-13 13:44:13 -0700874 /**
Lorenzo Colitti87cfc702015-07-27 16:35:33 +0900875 * Returns true if this link or any of its stacked interfaces has an IPv4 address.
876 *
877 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
878 */
879 private boolean hasIPv4AddressOnInterface(String iface) {
Lorenzo Colitti89b63922015-07-30 23:41:43 +0900880 // mIfaceName can be null.
881 return (Objects.equals(iface, mIfaceName) && hasIPv4Address()) ||
Lorenzo Colitti87cfc702015-07-27 16:35:33 +0900882 (iface != null && mStackedLinks.containsKey(iface) &&
883 mStackedLinks.get(iface).hasIPv4Address());
884 }
885
886 /**
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900887 * Returns true if this link has a global preferred IPv6 address.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900888 *
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900889 * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700890 * @hide
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900891 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100892 @UnsupportedAppUsage
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900893 public boolean hasGlobalIPv6Address() {
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900894 for (LinkAddress address : mLinkAddresses) {
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900895 if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) {
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900896 return true;
897 }
898 }
899 return false;
900 }
901
902 /**
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900903 * Returns true if this link has an IPv4 default route.
904 *
905 * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
906 * @hide
907 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100908 @UnsupportedAppUsage
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900909 public boolean hasIPv4DefaultRoute() {
910 for (RouteInfo r : mRoutes) {
Hugo Benichibd87a392017-10-10 16:29:06 +0900911 if (r.isIPv4Default()) {
912 return true;
913 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900914 }
915 return false;
916 }
917
918 /**
919 * Returns true if this link has an IPv6 default route.
920 *
921 * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
922 * @hide
923 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100924 @UnsupportedAppUsage
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900925 public boolean hasIPv6DefaultRoute() {
926 for (RouteInfo r : mRoutes) {
Hugo Benichibd87a392017-10-10 16:29:06 +0900927 if (r.isIPv6Default()) {
928 return true;
929 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900930 }
931 return false;
932 }
933
934 /**
935 * Returns true if this link has an IPv4 DNS server.
936 *
937 * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
938 * @hide
939 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100940 @UnsupportedAppUsage
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900941 public boolean hasIPv4DnsServer() {
942 for (InetAddress ia : mDnses) {
Hugo Benichibd87a392017-10-10 16:29:06 +0900943 if (ia instanceof Inet4Address) {
944 return true;
945 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900946 }
947 return false;
948 }
949
950 /**
951 * Returns true if this link has an IPv6 DNS server.
952 *
953 * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
954 * @hide
955 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100956 @UnsupportedAppUsage
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900957 public boolean hasIPv6DnsServer() {
958 for (InetAddress ia : mDnses) {
Hugo Benichibd87a392017-10-10 16:29:06 +0900959 if (ia instanceof Inet6Address) {
960 return true;
961 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900962 }
963 return false;
964 }
965
966 /**
Erik Klined3b9fd32014-10-24 21:50:20 +0900967 * Returns true if this link is provisioned for global IPv4 connectivity.
968 * This requires an IP address, default route, and DNS server.
969 *
970 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Klinecd7ed162015-05-21 16:15:02 +0900971 * @hide
Erik Klined3b9fd32014-10-24 21:50:20 +0900972 */
Erik Klinecd7ed162015-05-21 16:15:02 +0900973 public boolean isIPv4Provisioned() {
Erik Klined3b9fd32014-10-24 21:50:20 +0900974 return (hasIPv4Address() &&
975 hasIPv4DefaultRoute() &&
976 hasIPv4DnsServer());
977 }
978
979 /**
980 * Returns true if this link is provisioned for global IPv6 connectivity.
981 * This requires an IP address, default route, and DNS server.
982 *
983 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Klinecd7ed162015-05-21 16:15:02 +0900984 * @hide
Erik Klined3b9fd32014-10-24 21:50:20 +0900985 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100986 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900987 public boolean isIPv6Provisioned() {
Erik Klined3b9fd32014-10-24 21:50:20 +0900988 return (hasGlobalIPv6Address() &&
989 hasIPv6DefaultRoute() &&
990 hasIPv6DnsServer());
991 }
992
993 /**
994 * Returns true if this link is provisioned for global connectivity,
995 * for at least one Internet Protocol family.
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +0900996 *
997 * @return {@code true} if the link is provisioned, {@code false} otherwise.
998 * @hide
999 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001000 @UnsupportedAppUsage
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001001 public boolean isProvisioned() {
Erik Klinecd7ed162015-05-21 16:15:02 +09001002 return (isIPv4Provisioned() || isIPv6Provisioned());
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001003 }
1004
1005 /**
Erik Klineb36a3132015-06-26 19:21:34 +09001006 * Evaluate whether the {@link InetAddress} is considered reachable.
1007 *
1008 * @return {@code true} if the given {@link InetAddress} is considered reachable,
1009 * {@code false} otherwise.
1010 * @hide
1011 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001012 @UnsupportedAppUsage
Erik Klineb36a3132015-06-26 19:21:34 +09001013 public boolean isReachable(InetAddress ip) {
1014 final List<RouteInfo> allRoutes = getAllRoutes();
1015 // If we don't have a route to this IP address, it's not reachable.
1016 final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip);
1017 if (bestRoute == null) {
1018 return false;
1019 }
1020
1021 // TODO: better source address evaluation for destination addresses.
1022
1023 if (ip instanceof Inet4Address) {
1024 // For IPv4, it suffices for now to simply have any address.
Lorenzo Colitti87cfc702015-07-27 16:35:33 +09001025 return hasIPv4AddressOnInterface(bestRoute.getInterface());
Erik Klineb36a3132015-06-26 19:21:34 +09001026 } else if (ip instanceof Inet6Address) {
1027 if (ip.isLinkLocalAddress()) {
1028 // For now, just make sure link-local destinations have
1029 // scopedIds set, since transmits will generally fail otherwise.
1030 // TODO: verify it matches the ifindex of one of the interfaces.
1031 return (((Inet6Address)ip).getScopeId() != 0);
1032 } else {
1033 // For non-link-local destinations check that either the best route
1034 // is directly connected or that some global preferred address exists.
1035 // TODO: reconsider all cases (disconnected ULA networks, ...).
1036 return (!bestRoute.hasGateway() || hasGlobalIPv6Address());
1037 }
1038 }
1039
1040 return false;
1041 }
1042
1043 /**
Wink Savillee8222252011-07-13 13:44:13 -07001044 * Compares this {@code LinkProperties} interface name against the target
1045 *
1046 * @param target LinkProperties to compare.
1047 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001048 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001049 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001050 @UnsupportedAppUsage
Wink Savillee8222252011-07-13 13:44:13 -07001051 public boolean isIdenticalInterfaceName(LinkProperties target) {
1052 return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
1053 }
1054
1055 /**
Robert Greenwalt4717c262012-10-31 14:32:53 -07001056 * Compares this {@code LinkProperties} interface addresses against the target
Wink Savillee8222252011-07-13 13:44:13 -07001057 *
1058 * @param target LinkProperties to compare.
1059 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001060 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001061 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001062 @UnsupportedAppUsage
Wink Savillee8222252011-07-13 13:44:13 -07001063 public boolean isIdenticalAddresses(LinkProperties target) {
1064 Collection<InetAddress> targetAddresses = target.getAddresses();
1065 Collection<InetAddress> sourceAddresses = getAddresses();
1066 return (sourceAddresses.size() == targetAddresses.size()) ?
1067 sourceAddresses.containsAll(targetAddresses) : false;
1068 }
1069
1070 /**
1071 * Compares this {@code LinkProperties} DNS addresses against the target
1072 *
1073 * @param target LinkProperties to compare.
1074 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001075 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001076 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001077 @UnsupportedAppUsage
Wink Savillee8222252011-07-13 13:44:13 -07001078 public boolean isIdenticalDnses(LinkProperties target) {
Robert Greenwaltdf2b8782014-06-06 10:30:11 -07001079 Collection<InetAddress> targetDnses = target.getDnsServers();
Robert Greenwalt8058f622012-11-09 10:52:27 -08001080 String targetDomains = target.getDomains();
1081 if (mDomains == null) {
1082 if (targetDomains != null) return false;
1083 } else {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001084 if (!mDomains.equals(targetDomains)) return false;
Robert Greenwalt8058f622012-11-09 10:52:27 -08001085 }
Wink Savillee8222252011-07-13 13:44:13 -07001086 return (mDnses.size() == targetDnses.size()) ?
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001087 mDnses.containsAll(targetDnses) : false;
Wink Savillee8222252011-07-13 13:44:13 -07001088 }
1089
1090 /**
dalykd9201342018-01-17 14:20:55 -05001091 * Compares this {@code LinkProperties} private DNS settings against the
1092 * target.
1093 *
1094 * @param target LinkProperties to compare.
1095 * @return {@code true} if both are identical, {@code false} otherwise.
1096 * @hide
1097 */
1098 public boolean isIdenticalPrivateDns(LinkProperties target) {
1099 return (isPrivateDnsActive() == target.isPrivateDnsActive()
1100 && TextUtils.equals(getPrivateDnsServerName(),
1101 target.getPrivateDnsServerName()));
1102 }
1103
1104 /**
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001105 * Compares this {@code LinkProperties} validated private DNS addresses against
1106 * the target
1107 *
1108 * @param target LinkProperties to compare.
1109 * @return {@code true} if both are identical, {@code false} otherwise.
1110 * @hide
1111 */
1112 public boolean isIdenticalValidatedPrivateDnses(LinkProperties target) {
1113 Collection<InetAddress> targetDnses = target.getValidatedPrivateDnsServers();
1114 return (mValidatedPrivateDnses.size() == targetDnses.size())
1115 ? mValidatedPrivateDnses.containsAll(targetDnses) : false;
1116 }
1117
1118 /**
Wink Savillee8222252011-07-13 13:44:13 -07001119 * Compares this {@code LinkProperties} Routes against the target
1120 *
1121 * @param target LinkProperties to compare.
1122 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001123 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001124 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001125 @UnsupportedAppUsage
Wink Savillee8222252011-07-13 13:44:13 -07001126 public boolean isIdenticalRoutes(LinkProperties target) {
1127 Collection<RouteInfo> targetRoutes = target.getRoutes();
1128 return (mRoutes.size() == targetRoutes.size()) ?
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001129 mRoutes.containsAll(targetRoutes) : false;
Wink Savillee8222252011-07-13 13:44:13 -07001130 }
1131
1132 /**
1133 * Compares this {@code LinkProperties} HttpProxy against the target
1134 *
1135 * @param target LinkProperties to compare.
1136 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001137 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001138 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001139 @UnsupportedAppUsage
Wink Savillee8222252011-07-13 13:44:13 -07001140 public boolean isIdenticalHttpProxy(LinkProperties target) {
1141 return getHttpProxy() == null ? target.getHttpProxy() == null :
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001142 getHttpProxy().equals(target.getHttpProxy());
Wink Savillee8222252011-07-13 13:44:13 -07001143 }
John Wang4e900092011-04-04 12:35:42 -07001144
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001145 /**
1146 * Compares this {@code LinkProperties} stacked links against the target
1147 *
1148 * @param target LinkProperties to compare.
1149 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001150 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001151 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001152 @UnsupportedAppUsage
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001153 public boolean isIdenticalStackedLinks(LinkProperties target) {
Lorenzo Colitti213f98b2013-04-01 10:47:43 +09001154 if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001155 return false;
1156 }
1157 for (LinkProperties stacked : mStackedLinks.values()) {
1158 // Hashtable values can never be null.
1159 String iface = stacked.getInterfaceName();
1160 if (!stacked.equals(target.mStackedLinks.get(iface))) {
1161 return false;
1162 }
1163 }
1164 return true;
1165 }
1166
sy.yun9d9b74a2013-09-02 05:24:09 +09001167 /**
1168 * Compares this {@code LinkProperties} MTU against the target
1169 *
Ying Wangd57de6a2013-09-06 22:53:16 -07001170 * @param target LinkProperties to compare.
sy.yun9d9b74a2013-09-02 05:24:09 +09001171 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001172 * @hide
sy.yun9d9b74a2013-09-02 05:24:09 +09001173 */
1174 public boolean isIdenticalMtu(LinkProperties target) {
1175 return getMtu() == target.getMtu();
1176 }
1177
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001178 /**
1179 * Compares this {@code LinkProperties} Tcp buffer sizes against the target.
1180 *
1181 * @param target LinkProperties to compare.
1182 * @return {@code true} if both are identical, {@code false} otherwise.
1183 * @hide
1184 */
1185 public boolean isIdenticalTcpBufferSizes(LinkProperties target) {
1186 return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes);
1187 }
1188
John Wang4e900092011-04-04 12:35:42 -07001189 /**
1190 * Compares this {@code LinkProperties} instance against the target
1191 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
1192 * all their fields are equal in values.
1193 *
1194 * For collection fields, such as mDnses, containsAll() is used to check
1195 * if two collections contains the same elements, independent of order.
1196 * There are two thoughts regarding containsAll()
1197 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
1198 * 2. Worst case performance is O(n^2).
1199 *
1200 * @param obj the object to be tested for equality.
1201 * @return {@code true} if both objects are equal, {@code false} otherwise.
1202 */
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001203 @Override
John Wang4e900092011-04-04 12:35:42 -07001204 public boolean equals(Object obj) {
1205 if (this == obj) return true;
1206
1207 if (!(obj instanceof LinkProperties)) return false;
1208
John Wang4e900092011-04-04 12:35:42 -07001209 LinkProperties target = (LinkProperties) obj;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001210 /*
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001211 * This method does not check that stacked interfaces are equal, because
1212 * stacked interfaces are not so much a property of the link as a
1213 * description of connections between links.
1214 */
dalykd9201342018-01-17 14:20:55 -05001215 return isIdenticalInterfaceName(target)
1216 && isIdenticalAddresses(target)
1217 && isIdenticalDnses(target)
1218 && isIdenticalPrivateDns(target)
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001219 && isIdenticalValidatedPrivateDnses(target)
dalykd9201342018-01-17 14:20:55 -05001220 && isIdenticalRoutes(target)
1221 && isIdenticalHttpProxy(target)
1222 && isIdenticalStackedLinks(target)
1223 && isIdenticalMtu(target)
1224 && isIdenticalTcpBufferSizes(target);
Wink Savillee8222252011-07-13 13:44:13 -07001225 }
John Wang4e900092011-04-04 12:35:42 -07001226
Wink Savillee8222252011-07-13 13:44:13 -07001227 /**
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001228 * Compares the addresses in this LinkProperties with another
1229 * LinkProperties, examining only addresses on the base link.
Wink Savillee8222252011-07-13 13:44:13 -07001230 *
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001231 * @param target a LinkProperties with the new list of addresses
1232 * @return the differences between the addresses.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001233 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001234 */
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001235 public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
Wink Savillee8222252011-07-13 13:44:13 -07001236 /*
1237 * Duplicate the LinkAddresses into removed, we will be removing
1238 * address which are common between mLinkAddresses and target
1239 * leaving the addresses that are different. And address which
1240 * are in target but not in mLinkAddresses are placed in the
1241 * addedAddresses.
1242 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001243 return new CompareResult<>(mLinkAddresses,
1244 target != null ? target.getLinkAddresses() : null);
John Wang4e900092011-04-04 12:35:42 -07001245 }
1246
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001247 /**
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001248 * Compares the DNS addresses in this LinkProperties with another
1249 * LinkProperties, examining only DNS addresses on the base link.
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001250 *
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001251 * @param target a LinkProperties with the new list of dns addresses
1252 * @return the differences between the DNS addresses.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001253 * @hide
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001254 */
1255 public CompareResult<InetAddress> compareDnses(LinkProperties target) {
1256 /*
1257 * Duplicate the InetAddresses into removed, we will be removing
1258 * dns address which are common between mDnses and target
1259 * leaving the addresses that are different. And dns address which
1260 * are in target but not in mDnses are placed in the
1261 * addedAddresses.
1262 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001263 return new CompareResult<>(mDnses, target != null ? target.getDnsServers() : null);
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001264 }
1265
1266 /**
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001267 * Compares the validated private DNS addresses in this LinkProperties with another
1268 * LinkProperties.
1269 *
1270 * @param target a LinkProperties with the new list of validated private dns addresses
1271 * @return the differences between the DNS addresses.
1272 * @hide
1273 */
1274 public CompareResult<InetAddress> compareValidatedPrivateDnses(LinkProperties target) {
1275 return new CompareResult<>(mValidatedPrivateDnses,
1276 target != null ? target.getValidatedPrivateDnsServers() : null);
1277 }
1278
1279 /**
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001280 * Compares all routes in this LinkProperties with another LinkProperties,
1281 * examining both the the base link and all stacked links.
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001282 *
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001283 * @param target a LinkProperties with the new list of routes
1284 * @return the differences between the routes.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001285 * @hide
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001286 */
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001287 public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) {
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001288 /*
1289 * Duplicate the RouteInfos into removed, we will be removing
Lorenzo Colitti1994bc12013-03-08 19:11:40 -08001290 * routes which are common between mRoutes and target
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001291 * leaving the routes that are different. And route address which
1292 * are in target but not in mRoutes are placed in added.
1293 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001294 return new CompareResult<>(getAllRoutes(), target != null ? target.getAllRoutes() : null);
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001295 }
1296
Paul Jensen992f2522014-04-28 10:33:11 -04001297 /**
1298 * Compares all interface names in this LinkProperties with another
1299 * LinkProperties, examining both the the base link and all stacked links.
1300 *
1301 * @param target a LinkProperties with the new list of interface names
1302 * @return the differences between the interface names.
1303 * @hide
1304 */
1305 public CompareResult<String> compareAllInterfaceNames(LinkProperties target) {
1306 /*
1307 * Duplicate the interface names into removed, we will be removing
1308 * interface names which are common between this and target
1309 * leaving the interface names that are different. And interface names which
1310 * are in target but not in this are placed in added.
1311 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001312 return new CompareResult<>(getAllInterfaceNames(),
1313 target != null ? target.getAllInterfaceNames() : null);
Paul Jensen992f2522014-04-28 10:33:11 -04001314 }
1315
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001316
John Wang4e900092011-04-04 12:35:42 -07001317 /**
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001318 * Generate hashcode based on significant fields
1319 *
John Wang4e900092011-04-04 12:35:42 -07001320 * Equal objects must produce the same hash code, while unequal objects
1321 * may have the same hash codes.
1322 */
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001323 @Override
John Wang4e900092011-04-04 12:35:42 -07001324 public int hashCode() {
1325 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
1326 + mLinkAddresses.size() * 31
1327 + mDnses.size() * 37
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001328 + mValidatedPrivateDnses.size() * 61
Robert Greenwalt8058f622012-11-09 10:52:27 -08001329 + ((null == mDomains) ? 0 : mDomains.hashCode())
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001330 + mRoutes.size() * 41
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001331 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
sy.yun9d9b74a2013-09-02 05:24:09 +09001332 + mStackedLinks.hashCode() * 47)
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001333 + mMtu * 51
dalykd9201342018-01-17 14:20:55 -05001334 + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
1335 + (mUsePrivateDns ? 57 : 0)
1336 + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode());
John Wang4e900092011-04-04 12:35:42 -07001337 }
1338
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001339 /**
1340 * Implement the Parcelable interface.
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001341 */
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001342 public void writeToParcel(Parcel dest, int flags) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001343 dest.writeString(getInterfaceName());
Irfan Sheriffed5d7d12010-10-01 16:08:28 -07001344 dest.writeInt(mLinkAddresses.size());
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001345 for (LinkAddress linkAddress : mLinkAddresses) {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -07001346 dest.writeParcelable(linkAddress, flags);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001347 }
Irfan Sheriffed5d7d12010-10-01 16:08:28 -07001348
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001349 dest.writeInt(mDnses.size());
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001350 for (InetAddress d : mDnses) {
1351 dest.writeByteArray(d.getAddress());
1352 }
1353 dest.writeInt(mValidatedPrivateDnses.size());
1354 for (InetAddress d : mValidatedPrivateDnses) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001355 dest.writeByteArray(d.getAddress());
1356 }
dalykd9201342018-01-17 14:20:55 -05001357 dest.writeBoolean(mUsePrivateDns);
1358 dest.writeString(mPrivateDnsServerName);
Robert Greenwalt8058f622012-11-09 10:52:27 -08001359 dest.writeString(mDomains);
sy.yun9d9b74a2013-09-02 05:24:09 +09001360 dest.writeInt(mMtu);
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001361 dest.writeString(mTcpBufferSizes);
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001362 dest.writeInt(mRoutes.size());
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001363 for (RouteInfo route : mRoutes) {
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001364 dest.writeParcelable(route, flags);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001365 }
Robert Greenwalt992564e2011-02-09 13:56:06 -08001366
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001367 if (mHttpProxy != null) {
1368 dest.writeByte((byte)1);
1369 dest.writeParcelable(mHttpProxy, flags);
1370 } else {
1371 dest.writeByte((byte)0);
1372 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001373 ArrayList<LinkProperties> stackedLinks = new ArrayList<>(mStackedLinks.values());
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001374 dest.writeList(stackedLinks);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001375 }
1376
1377 /**
1378 * Implement the Parcelable interface.
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001379 */
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001380 public static final Creator<LinkProperties> CREATOR =
1381 new Creator<LinkProperties>() {
1382 public LinkProperties createFromParcel(Parcel in) {
1383 LinkProperties netProp = new LinkProperties();
Robert Greenwalt4717c262012-10-31 14:32:53 -07001384
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001385 String iface = in.readString();
1386 if (iface != null) {
Robert Greenwalt4717c262012-10-31 14:32:53 -07001387 netProp.setInterfaceName(iface);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001388 }
1389 int addressCount = in.readInt();
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001390 for (int i = 0; i < addressCount; i++) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001391 netProp.addLinkAddress(in.readParcelable(null));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001392 }
1393 addressCount = in.readInt();
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001394 for (int i = 0; i < addressCount; i++) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001395 try {
Robert Greenwaltdf2b8782014-06-06 10:30:11 -07001396 netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001397 } catch (UnknownHostException e) { }
1398 }
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001399 addressCount = in.readInt();
1400 for (int i = 0; i < addressCount; i++) {
1401 try {
1402 netProp.addValidatedPrivateDnsServer(
1403 InetAddress.getByAddress(in.createByteArray()));
1404 } catch (UnknownHostException e) { }
1405 }
dalykd9201342018-01-17 14:20:55 -05001406 netProp.setUsePrivateDns(in.readBoolean());
1407 netProp.setPrivateDnsServerName(in.readString());
Robert Greenwalt8058f622012-11-09 10:52:27 -08001408 netProp.setDomains(in.readString());
sy.yun9d9b74a2013-09-02 05:24:09 +09001409 netProp.setMtu(in.readInt());
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001410 netProp.setTcpBufferSizes(in.readString());
Robert Greenwalt992564e2011-02-09 13:56:06 -08001411 addressCount = in.readInt();
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001412 for (int i = 0; i < addressCount; i++) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001413 netProp.addRoute(in.readParcelable(null));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001414 }
1415 if (in.readByte() == 1) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001416 netProp.setHttpProxy(in.readParcelable(null));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001417 }
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001418 ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
1419 in.readList(stackedLinks, LinkProperties.class.getClassLoader());
1420 for (LinkProperties stackedLink: stackedLinks) {
1421 netProp.addStackedLink(stackedLink);
1422 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001423 return netProp;
1424 }
1425
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001426 public LinkProperties[] newArray(int size) {
1427 return new LinkProperties[size];
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001428 }
1429 };
w1997615afd812014-08-05 15:18:11 -07001430
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001431 /**
1432 * Check the valid MTU range based on IPv4 or IPv6.
1433 * @hide
1434 */
1435 public static boolean isValidMtu(int mtu, boolean ipv6) {
1436 if (ipv6) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001437 return mtu >= MIN_MTU_V6 && mtu <= MAX_MTU;
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001438 } else {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001439 return mtu >= MIN_MTU && mtu <= MAX_MTU;
w1997615afd812014-08-05 15:18:11 -07001440 }
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001441 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001442}