147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt/*
26e80997a9a7b6a15370544edde322cd8833e9524Wink Saville * Copyright (C) 2010 The Android Open Source Project
347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *
447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * you may not use this file except in compliance with the License.
647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * You may obtain a copy of the License at
747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *
847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *
1047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * Unless required by applicable law or agreed to in writing, software
1147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
1247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * See the License for the specific language governing permissions and
1447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * limitations under the License.
1547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt */
1647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
1747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltpackage android.net;
1847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
19eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkeyimport android.annotation.NonNull;
209da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkeyimport android.annotation.Nullable;
21207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monkimport android.net.ProxyInfo;
2247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport android.os.Parcelable;
2347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport android.os.Parcel;
244e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wangimport android.text.TextUtils;
2547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
2647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.net.InetAddress;
27419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colittiimport java.net.Inet4Address;
284faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colittiimport java.net.Inet6Address;
2947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.net.UnknownHostException;
3047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.util.ArrayList;
3147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.util.Collection;
3237e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwaltimport java.util.Collections;
33419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colittiimport java.util.Hashtable;
34df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwaltimport java.util.List;
35c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colittiimport java.util.Objects;
3647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
3747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt/**
3837e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt * Describes the properties of a network link.
39992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt *
40992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * A link represents a connection to a network.
41992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * It may have multiple addresses and multiple gateways,
424f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt * multiple dns servers but only one http proxy and one
434f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt * network interface.
44992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt *
454f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt * Note that this is just a holder of data.  Modifying it
464f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt * does not affect live networks.
47992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt *
4847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt */
49e595b97ff470a5e92151350e4d7b4173032fde23Robert Greenwaltpublic final class LinkProperties implements Parcelable {
50419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // The interface described by the network link.
514717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    private String mIfaceName;
5264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
5364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private ArrayList<InetAddress> mDnses = new ArrayList<InetAddress>();
548058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    private String mDomains;
5564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
56207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    private ProxyInfo mHttpProxy;
579d9b74a900696191048aa97cc3c854072640428bsy.yun    private int mMtu;
583f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
593f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    private String mTcpBufferSizes;
6047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
6115afd8115869bf22534a1f26fe6e389c9e5ef413w    private static final int MIN_MTU    = 68;
6215afd8115869bf22534a1f26fe6e389c9e5ef413w    private static final int MIN_MTU_V6 = 1280;
6315afd8115869bf22534a1f26fe6e389c9e5ef413w    private static final int MAX_MTU    = 10000;
6415afd8115869bf22534a1f26fe6e389c9e5ef413w
65419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // Stores the properties of links that are "stacked" above this link.
66419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // Indexed by interface name to allow modification and to prevent duplicates being added.
67419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    private Hashtable<String, LinkProperties> mStackedLinks =
68419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        new Hashtable<String, LinkProperties>();
69419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
70df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    /**
71df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
72df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     */
730a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public static class CompareResult<T> {
74df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        public List<T> removed = new ArrayList<T>();
75df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        public List<T> added = new ArrayList<T>();
76e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
77e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        @Override
78e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        public String toString() {
790a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            String retVal = "removed=[";
800a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (T addr : removed) retVal += addr.toString() + ",";
810a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            retVal += "] added=[";
820a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (T addr : added) retVal += addr.toString() + ",";
83e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            retVal += "]";
84e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            return retVal;
85e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        }
86e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
87e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
88cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
89cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
90cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
91cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    public enum ProvisioningChange {
92cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        STILL_NOT_PROVISIONED,
93cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LOST_PROVISIONING,
94cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        GAINED_PROVISIONING,
95cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        STILL_PROVISIONED,
96cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    }
97cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
98cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    /**
99cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * Compare the provisioning states of two LinkProperties instances.
100cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     *
101cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * @hide
102cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     */
103cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    public static ProvisioningChange compareProvisioning(
104cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            LinkProperties before, LinkProperties after) {
105cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        if (before.isProvisioned() && after.isProvisioned()) {
106cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // On dualstack networks, DHCPv4 renewals can occasionally fail.
107cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // When this happens, IPv6-reachable services continue to function
108cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // normally but IPv4-only services (naturally) fail.
109cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            //
110cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // When an application using an IPv4-only service reports a bad
111cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // network condition to the framework, attempts to re-validate
112cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // the network succeed (since we support IPv6-only networks) and
113cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // nothing is changed.
114cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            //
115cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // For users, this is confusing and unexpected behaviour, and is
116cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // not necessarily easy to diagnose.  Therefore, we treat changing
117cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // from a dualstack network to an IPv6-only network equivalent to
118cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // a total loss of provisioning.
119cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            //
120cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            // For one such example of this, see b/18867306.
121cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            //
1221ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline            // Additionally, losing IPv6 provisioning can result in TCP
1231ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline            // connections getting stuck until timeouts fire and other
1241ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline            // baffling failures. Therefore, loss of either IPv4 or IPv6 on a
1251ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline            // previously dualstack network is deemed a lost of provisioning.
1261ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline            if ((before.isIPv4Provisioned() && !after.isIPv4Provisioned()) ||
1271ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline                (before.isIPv6Provisioned() && !after.isIPv6Provisioned())) {
128cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                return ProvisioningChange.LOST_PROVISIONING;
129cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            }
130cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            return ProvisioningChange.STILL_PROVISIONED;
131cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        } else if (before.isProvisioned() && !after.isProvisioned()) {
132cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            return ProvisioningChange.LOST_PROVISIONING;
133cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        } else if (!before.isProvisioned() && after.isProvisioned()) {
134cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            return ProvisioningChange.GAINED_PROVISIONING;
135cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        } else {  // !before.isProvisioned() && !after.isProvisioned()
136cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            return ProvisioningChange.STILL_NOT_PROVISIONED;
137cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        }
138cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    }
139cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
140cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    /**
141cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * @hide
142cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     */
14337e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public LinkProperties() {
14447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
14547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
146cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
147cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
148cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
14937e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public LinkProperties(LinkProperties source) {
150ef6c1431fa2039a4b8c604d651bb8f4dc0806581Irfan Sheriff        if (source != null) {
151ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            mIfaceName = source.getInterfaceName();
1520d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
153df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt            for (InetAddress i : source.getDnsServers()) mDnses.add(i);
1548058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            mDomains = source.getDomains();
1550d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
156be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            mHttpProxy = (source.getHttpProxy() == null)  ?
157207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk                    null : new ProxyInfo(source.getHttpProxy());
158419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (LinkProperties l: source.mStackedLinks.values()) {
159419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                addStackedLink(l);
160419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
1619d9b74a900696191048aa97cc3c854072640428bsy.yun            setMtu(source.getMtu());
1623f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt            mTcpBufferSizes = source.mTcpBufferSizes;
163ef6c1431fa2039a4b8c604d651bb8f4dc0806581Irfan Sheriff        }
16437e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    }
16537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt
1664f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
1674f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Sets the interface name for this link.  All {@link RouteInfo} already set for this
1684f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * will have their interface changed to match this new value.
1694f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
1704f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @param iface The name of the network interface used for this link.
171df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
1724f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
173ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public void setInterfaceName(String iface) {
174ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        mIfaceName = iface;
17545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size());
17645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        for (RouteInfo route : mRoutes) {
17745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            newRoutes.add(routeWithInterface(route));
17845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        }
17945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        mRoutes = newRoutes;
18047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
181ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
1824f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
1834f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Gets the interface name for this link.  May be {@code null} if not set.
1844f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
1854f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @return The interface name set for this link or {@code null}.
1864f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
1879da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey    public @Nullable String getInterfaceName() {
188ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return mIfaceName;
18947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
19047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
191df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    /**
192df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
193df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     */
194df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<String> getAllInterfaceNames() {
195df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        List<String> interfaceNames = new ArrayList<String>(mStackedLinks.size() + 1);
19655187f18505aad67f824094061af1b6d0a0ebb38Robert Greenwalt        if (mIfaceName != null) interfaceNames.add(new String(mIfaceName));
1974aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
1984aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti            interfaceNames.addAll(stacked.getAllInterfaceNames());
1994aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        }
2004aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        return interfaceNames;
2014aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti    }
2024aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti
203d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
2044f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Returns all the addresses on this link.  We often think of a link having a single address,
2054f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * however, particularly with Ipv6 several addresses are typical.  Note that the
2064f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include
2074f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * prefix lengths for each address.  This is a simplified utility alternative to
2084f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * {@link LinkProperties#getLinkAddresses}.
2094f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
210df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @return An umodifiable {@link List} of {@link InetAddress} for this link.
2114f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
212d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
213df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<InetAddress> getAddresses() {
214df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        List<InetAddress> addresses = new ArrayList<InetAddress>();
215ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        for (LinkAddress linkAddress : mLinkAddresses) {
216ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            addresses.add(linkAddress.getAddress());
217ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        }
218df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        return Collections.unmodifiableList(addresses);
219ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
220ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
221d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
222d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link and all the links stacked above it.
2234f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
224d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
225df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<InetAddress> getAllAddresses() {
226df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        List<InetAddress> addresses = new ArrayList<InetAddress>();
227d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkAddress linkAddress : mLinkAddresses) {
228d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.add(linkAddress.getAddress());
229d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
230d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
231d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.addAll(stacked.getAllAddresses());
232d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
233d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        return addresses;
234d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    }
235d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
23664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private int findLinkAddressIndex(LinkAddress address) {
23764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        for (int i = 0; i < mLinkAddresses.size(); i++) {
23864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            if (mLinkAddresses.get(i).isSameAddressAs(address)) {
23964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti                return i;
24064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            }
24164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        }
24264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        return -1;
24364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    }
24464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
2454faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
2464f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the
2474f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * same address/prefix does not already exist.  If it does exist it is replaced.
2484faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @param address The {@code LinkAddress} to add.
24964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti     * @return true if {@code address} was added or updated, false otherwise.
250df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
2514faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
2524faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean addLinkAddress(LinkAddress address) {
25364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        if (address == null) {
25464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return false;
25564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        }
25664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        int i = findLinkAddressIndex(address);
25764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        if (i < 0) {
25864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            // Address was not present. Add it.
2594faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            mLinkAddresses.add(address);
2604faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
26164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        } else if (mLinkAddresses.get(i).equals(address)) {
26264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            // Address was present and has same properties. Do nothing.
26364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return false;
26464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        } else {
26564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            // Address was present and has different properties. Update it.
26664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            mLinkAddresses.set(i, address);
26764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return true;
2684faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        }
2694faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
2704faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
2714faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
2724f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Removes a {@link LinkAddress} from this {@code LinkProperties}.  Specifically, matches
2734f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * and {@link LinkAddress} with the same address and prefix.
2744f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
2754f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @param toRemove A {@link LinkAddress} specifying the address to remove.
2764faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the address was removed, false if it did not exist.
277df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
2784faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
2794faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean removeLinkAddress(LinkAddress toRemove) {
28064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        int i = findLinkAddressIndex(toRemove);
28164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        if (i >= 0) {
28264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            mLinkAddresses.remove(i);
28364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return true;
28464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        }
28564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        return false;
286ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
287ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
288d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
2894f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Returns all the {@link LinkAddress} on this link.  Typically a link will have
2904f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * one IPv4 address and one or more IPv6 addresses.
2914f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
292df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @return An unmodifiable {@link List} of {@link LinkAddress} for this link.
293d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
294df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<LinkAddress> getLinkAddresses() {
295df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        return Collections.unmodifiableList(mLinkAddresses);
29647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
29747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
298d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
299d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link and all the links stacked above it.
3004f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
301d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
302df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<LinkAddress> getAllLinkAddresses() {
303df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        List<LinkAddress> addresses = new ArrayList<LinkAddress>();
304d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        addresses.addAll(mLinkAddresses);
305d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
306d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.addAll(stacked.getAllLinkAddresses());
307d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
308d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        return addresses;
309d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    }
310d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
31122f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    /**
3124f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Replaces the {@link LinkAddress} in this {@code LinkProperties} with
3134f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * the given {@link Collection} of {@link LinkAddress}.
3144f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
3154f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @param addresses The {@link Collection} of {@link LinkAddress} to set in this
3164f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *                  object.
317df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
31822f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti     */
31922f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    public void setLinkAddresses(Collection<LinkAddress> addresses) {
32022f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        mLinkAddresses.clear();
32122f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        for (LinkAddress address: addresses) {
32222f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti            addLinkAddress(address);
32322f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        }
32422f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    }
32522f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
3264f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
327309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     * Adds the given {@link InetAddress} to the list of DNS servers, if not present.
3284f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
329df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
330309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     * @return true if the DNS server was added, false if it was already present.
331df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
3324f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
333309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti    public boolean addDnsServer(InetAddress dnsServer) {
334309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti        if (dnsServer != null && !mDnses.contains(dnsServer)) {
335309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti            mDnses.add(dnsServer);
336309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti            return true;
337309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti        }
338309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti        return false;
339309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti    }
340309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti
341309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti    /**
342cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * Removes the given {@link InetAddress} from the list of DNS servers.
343cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     *
344cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * @param dnsServer The {@link InetAddress} to remove from the list of DNS servers.
345cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * @return true if the DNS server was removed, false if it did not exist.
346cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * @hide
347cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     */
348cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    public boolean removeDnsServer(InetAddress dnsServer) {
349cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        if (dnsServer != null) {
350cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline            return mDnses.remove(dnsServer);
351cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        }
352cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        return false;
353cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    }
354cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
355cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    /**
356309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     * Replaces the DNS servers in this {@code LinkProperties} with
357309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     * the given {@link Collection} of {@link InetAddress} objects.
358309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     *
359309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     * @param addresses The {@link Collection} of DNS servers to set in this object.
360309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     * @hide
361309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti     */
362309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti    public void setDnsServers(Collection<InetAddress> dnsServers) {
363309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti        mDnses.clear();
364309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti        for (InetAddress dnsServer: dnsServers) {
365309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti            addDnsServer(dnsServer);
366309a75dbc3a96471f66967379b0e6b043244ae42Lorenzo Colitti        }
36747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
368ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
3694f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
370cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * Returns all the {@link InetAddress} for DNS servers on this link.
3714f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
372df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @return An umodifiable {@link List} of {@link InetAddress} for DNS servers on
3734f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *         this link.
3744f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
375df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<InetAddress> getDnsServers() {
376df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        return Collections.unmodifiableList(mDnses);
37747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
37847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
3794f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
3804f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Sets the DNS domain search path used on this link.
3814f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
3824f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @param domains A {@link String} listing in priority order the comma separated
3834f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *                domains to search when resolving host names on this link.
384df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
3854f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
3868058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    public void setDomains(String domains) {
3878058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        mDomains = domains;
3888058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    }
3898058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
3904f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
3914f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Get the DNS domains search path set for this link.
3924f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
3934f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @return A {@link String} containing the comma separated domains to search when resolving
3944f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *         host names on this link.
3954f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
3964f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    public String getDomains() {
3974f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt        return mDomains;
3984f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    }
3994f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt
4004f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
4014f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Sets the Maximum Transmission Unit size to use on this link.  This should not be used
4024f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * unless the system default (1500) is incorrect.  Values less than 68 or greater than
4034f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * 10000 will be ignored.
4044f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
4054f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @param mtu The MTU to use for this link.
4064f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
4074f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
4089d9b74a900696191048aa97cc3c854072640428bsy.yun    public void setMtu(int mtu) {
4099d9b74a900696191048aa97cc3c854072640428bsy.yun        mMtu = mtu;
4109d9b74a900696191048aa97cc3c854072640428bsy.yun    }
4119d9b74a900696191048aa97cc3c854072640428bsy.yun
4124f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
4134f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Gets any non-default MTU size set for this link.  Note that if the default is being used
4144f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * this will return 0.
4154f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
4164f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @return The mtu value set for this link.
4174f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
4184f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
4199d9b74a900696191048aa97cc3c854072640428bsy.yun    public int getMtu() {
4209d9b74a900696191048aa97cc3c854072640428bsy.yun        return mMtu;
4219d9b74a900696191048aa97cc3c854072640428bsy.yun    }
4229d9b74a900696191048aa97cc3c854072640428bsy.yun
4233f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    /**
4243f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * Sets the tcp buffers sizes to be used when this link is the system default.
4253f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * Should be of the form "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max".
4263f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     *
4273f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * @param tcpBufferSizes The tcp buffers sizes to use.
4283f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     *
4293f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * @hide
4303f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     */
4313f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    public void setTcpBufferSizes(String tcpBufferSizes) {
4323f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        mTcpBufferSizes = tcpBufferSizes;
4333f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    }
4343f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt
4353f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    /**
4363f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * Gets the tcp buffer sizes.
4373f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     *
4383f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * @return the tcp buffer sizes to use when this link is the system default.
4393f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     *
4403f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * @hide
4413f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     */
4423f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    public String getTcpBufferSizes() {
4433f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        return mTcpBufferSizes;
4443f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    }
4453f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt
44645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    private RouteInfo routeWithInterface(RouteInfo route) {
44745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return new RouteInfo(
44845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            route.getDestination(),
44945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            route.getGateway(),
4504b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            mIfaceName,
4514b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            route.getType());
45245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
45345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
4544f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
455c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * Adds a {@link RouteInfo} to this {@code LinkProperties}, if not present. If the
456c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * {@link RouteInfo} had an interface name set and that differs from the interface set for this
457c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown.  The proper
458c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * course is to add either un-named or properly named {@link RouteInfo}.
4594f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
4604f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @param route A {@link RouteInfo} to add to this object.
461c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * @return {@code false} if the route was already present, {@code true} if it was added.
462c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     *
463df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
4644f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
465c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti    public boolean addRoute(RouteInfo route) {
46645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        if (route != null) {
46745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            String routeIface = route.getInterface();
46845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            if (routeIface != null && !routeIface.equals(mIfaceName)) {
4691994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti                throw new IllegalArgumentException(
47045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                   "Route added with non-matching interface: " + routeIface +
4711994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti                   " vs. " + mIfaceName);
47245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            }
473c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti            route = routeWithInterface(route);
474c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti            if (!mRoutes.contains(route)) {
475c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti                mRoutes.add(route);
476c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti                return true;
477c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti            }
47845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        }
479c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti        return false;
480c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti    }
481c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti
482c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti    /**
483c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * Removes a {@link RouteInfo} from this {@code LinkProperties}, if present. The route must
484c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * specify an interface and the interface must match the interface of this
485c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * {@code LinkProperties}, or it will not be removed.
486c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     *
487c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * @return {@code true} if the route was removed, {@code false} if it was not present.
488c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     *
489c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     * @hide
490c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti     */
491c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti    public boolean removeRoute(RouteInfo route) {
492c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti        return route != null &&
493c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti                Objects.equals(mIfaceName, route.getInterface()) &&
494c17a1b9ee4e2e72d640b97ef174d9a78a8ef9a8aLorenzo Colitti                mRoutes.remove(route);
49547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
49645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
497419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
4984f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Returns all the {@link RouteInfo} set on this link.
4994f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
500df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @return An unmodifiable {@link List} of {@link RouteInfo} for this link.
501419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
502df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<RouteInfo> getRoutes() {
503df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        return Collections.unmodifiableList(mRoutes);
50447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
50547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
506419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
507419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the routes on this link and all the links stacked above it.
5084f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
509419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
510df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt    public List<RouteInfo> getAllRoutes() {
511df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        List<RouteInfo> routes = new ArrayList();
512419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        routes.addAll(mRoutes);
513419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
514419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            routes.addAll(stacked.getAllRoutes());
515419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
5166629bcd6608cccbd5997ac99bf4474c00def0431Robert Greenwalt        return routes;
517419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
518419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
5194f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
5204f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none.
5214f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Note that Http Proxies are only a hint - the system recommends their use, but it does
5224f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * not enforce it and applications may ignore them.
5234f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
524b36a3131d1b05efa176f79d318197499b2c45380Erik Kline     * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
525df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
5264f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
527207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    public void setHttpProxy(ProxyInfo proxy) {
52847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        mHttpProxy = proxy;
52947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
5304f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt
5314f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
5324f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link.
5334f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     *
5344f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @return The {@link ProxyInfo} set on this link
5354f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
536207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    public ProxyInfo getHttpProxy() {
53747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        return mHttpProxy;
53847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
53947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
540419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
541419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Adds a stacked link.
542419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
543419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * If there is already a stacked link with the same interfacename as link,
544419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * that link is replaced with link. Otherwise, link is added to the list
545419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * of stacked links. If link is null, nothing changes.
546419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
547419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @param link The link to add.
5484faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the link was stacked, false otherwise.
5494f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
550419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
5514faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean addStackedLink(LinkProperties link) {
552419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (link != null && link.getInterfaceName() != null) {
553419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            mStackedLinks.put(link.getInterfaceName(), link);
5544faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
555419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
5564faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
557419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
558419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
559419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
560419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Removes a stacked link.
561419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
562f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti     * If there is a stacked link with the given interface name, it is
563419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * removed. Otherwise, nothing changes.
564419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
565f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti     * @param iface The interface name of the link to remove.
5664faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the link was removed, false otherwise.
5674f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
568419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
569f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti    public boolean removeStackedLink(String iface) {
570f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti        if (iface != null) {
571f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti            LinkProperties removed = mStackedLinks.remove(iface);
5724faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return removed != null;
573419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
5744faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
575419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
576419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
577419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
578419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the links stacked on top of this link.
5794f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
580419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
581eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey    public @NonNull List<LinkProperties> getStackedLinks() {
582eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey        if (mStackedLinks.isEmpty()) {
583eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey            return Collections.EMPTY_LIST;
584eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey        }
585df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        List<LinkProperties> stacked = new ArrayList<LinkProperties>();
586419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties link : mStackedLinks.values()) {
587eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey            stacked.add(new LinkProperties(link));
588419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
589df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        return Collections.unmodifiableList(stacked);
590419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
591419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
5924f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt    /**
5934f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * Clears this object to its initial state.
594df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
5954f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     */
59637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void clear() {
597ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        mIfaceName = null;
598e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mLinkAddresses.clear();
599e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mDnses.clear();
6008058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        mDomains = null;
601e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mRoutes.clear();
60247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        mHttpProxy = null;
603419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        mStackedLinks.clear();
6049d9b74a900696191048aa97cc3c854072640428bsy.yun        mMtu = 0;
6053f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        mTcpBufferSizes = null;
60647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
60747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
60847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
60947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface
61047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
61147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    public int describeContents() {
61247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        return 0;
61347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
61447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
6151f6408a96c757b3001c553f8f34ef0bda00a224dWink Saville    @Override
61637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public String toString() {
617ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
61847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
619ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        String linkAddresses = "LinkAddresses: [";
6204e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
621ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        linkAddresses += "] ";
62247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
62347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        String dns = "DnsAddresses: [";
6241f6408a96c757b3001c553f8f34ef0bda00a224dWink Saville        for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
62547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dns += "] ";
62647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
6278058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String domainName = "Domains: " + mDomains;
6288058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
629cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        String mtu = " MTU: " + mMtu;
6309d9b74a900696191048aa97cc3c854072640428bsy.yun
6313f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        String tcpBuffSizes = "";
6323f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        if (mTcpBufferSizes != null) {
6333f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt            tcpBuffSizes = " TcpBufferSizes: " + mTcpBufferSizes;
6343f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        }
6353f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt
6368058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String routes = " Routes: [";
637aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        for (RouteInfo route : mRoutes) routes += route.toString() + ",";
638aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        routes += "] ";
639cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        String proxy = (mHttpProxy == null ? "" : " HttpProxy: " + mHttpProxy.toString() + " ");
64047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
641419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        String stacked = "";
642419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (mStackedLinks.values().size() > 0) {
643419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            stacked += " Stacked: [";
644419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (LinkProperties link: mStackedLinks.values()) {
645419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                stacked += " [" + link.toString() + " ],";
646419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
647419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            stacked += "] ";
648419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
6499d9b74a900696191048aa97cc3c854072640428bsy.yun        return "{" + ifaceName + linkAddresses + routes + dns + domainName + mtu
6503f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt            + tcpBuffSizes + proxy + stacked + "}";
651419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
652419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
653419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
654419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns true if this link has an IPv4 address.
655419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
656419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
657df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
658419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
659419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public boolean hasIPv4Address() {
660419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkAddress address : mLinkAddresses) {
661419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          if (address.getAddress() instanceof Inet4Address) {
662419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            return true;
663419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          }
664419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
665419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return false;
66647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
66747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
668e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
66987cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti     * Returns true if this link or any of its stacked interfaces has an IPv4 address.
67087cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti     *
67187cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti     * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
67287cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti     */
67387cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti    private boolean hasIPv4AddressOnInterface(String iface) {
67489b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        // mIfaceName can be null.
67589b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        return (Objects.equals(iface, mIfaceName) && hasIPv4Address()) ||
67687cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti                (iface != null && mStackedLinks.containsKey(iface) &&
67787cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti                        mStackedLinks.get(iface).hasIPv4Address());
67887cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti    }
67987cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti
68087cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti    /**
68176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * Returns true if this link has a global preferred IPv6 address.
6824faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     *
68376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
684df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt     * @hide
6854faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
68676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    public boolean hasGlobalIPv6Address() {
6874faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        for (LinkAddress address : mLinkAddresses) {
68876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) {
6894faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
6904faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti          }
6914faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        }
6924faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
6934faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
6944faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
6954faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
69676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * Returns true if this link has an IPv4 default route.
69776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     *
69876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
69976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @hide
70076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     */
70176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    public boolean hasIPv4DefaultRoute() {
70276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        for (RouteInfo r : mRoutes) {
70376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          if (r.isIPv4Default()) {
70476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti            return true;
70576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          }
70676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        }
70776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        return false;
70876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    }
70976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
71076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    /**
71176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * Returns true if this link has an IPv6 default route.
71276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     *
71376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
71476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @hide
71576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     */
71676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    public boolean hasIPv6DefaultRoute() {
71776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        for (RouteInfo r : mRoutes) {
71876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          if (r.isIPv6Default()) {
71976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti            return true;
72076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          }
72176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        }
72276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        return false;
72376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    }
72476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
72576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    /**
72676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * Returns true if this link has an IPv4 DNS server.
72776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     *
72876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
72976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @hide
73076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     */
73176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    public boolean hasIPv4DnsServer() {
73276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        for (InetAddress ia : mDnses) {
73376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          if (ia instanceof Inet4Address) {
73476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti            return true;
73576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          }
73676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        }
73776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        return false;
73876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    }
73976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
74076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    /**
74176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * Returns true if this link has an IPv6 DNS server.
74276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     *
74376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
74476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @hide
74576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     */
74676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    public boolean hasIPv6DnsServer() {
74776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        for (InetAddress ia : mDnses) {
74876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          if (ia instanceof Inet6Address) {
74976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti            return true;
75076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti          }
75176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        }
75276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        return false;
75376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    }
75476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
75576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    /**
756d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * Returns true if this link is provisioned for global IPv4 connectivity.
757d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * This requires an IP address, default route, and DNS server.
758d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     *
759d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * @return {@code true} if the link is provisioned, {@code false} otherwise.
760cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * @hide
761d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     */
762cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    public boolean isIPv4Provisioned() {
763d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        return (hasIPv4Address() &&
764d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline                hasIPv4DefaultRoute() &&
765d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline                hasIPv4DnsServer());
766d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    }
767d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
768d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    /**
769d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * Returns true if this link is provisioned for global IPv6 connectivity.
770d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * This requires an IP address, default route, and DNS server.
771d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     *
772d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * @return {@code true} if the link is provisioned, {@code false} otherwise.
773cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline     * @hide
774d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     */
775cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    public boolean isIPv6Provisioned() {
776d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        return (hasGlobalIPv6Address() &&
777d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline                hasIPv6DefaultRoute() &&
778d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline                hasIPv6DnsServer());
779d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    }
780d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
781d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    /**
782d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * Returns true if this link is provisioned for global connectivity,
783d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline     * for at least one Internet Protocol family.
78476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     *
78576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @return {@code true} if the link is provisioned, {@code false} otherwise.
78676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     * @hide
78776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti     */
78876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    public boolean isProvisioned() {
789cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        return (isIPv4Provisioned() || isIPv6Provisioned());
79076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    }
79176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
79276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    /**
793b36a3131d1b05efa176f79d318197499b2c45380Erik Kline     * Evaluate whether the {@link InetAddress} is considered reachable.
794b36a3131d1b05efa176f79d318197499b2c45380Erik Kline     *
795b36a3131d1b05efa176f79d318197499b2c45380Erik Kline     * @return {@code true} if the given {@link InetAddress} is considered reachable,
796b36a3131d1b05efa176f79d318197499b2c45380Erik Kline     *         {@code false} otherwise.
797b36a3131d1b05efa176f79d318197499b2c45380Erik Kline     * @hide
798b36a3131d1b05efa176f79d318197499b2c45380Erik Kline     */
799b36a3131d1b05efa176f79d318197499b2c45380Erik Kline    public boolean isReachable(InetAddress ip) {
800b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final List<RouteInfo> allRoutes = getAllRoutes();
801b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // If we don't have a route to this IP address, it's not reachable.
802b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip);
803b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        if (bestRoute == null) {
804b36a3131d1b05efa176f79d318197499b2c45380Erik Kline            return false;
805b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        }
806b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
807b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // TODO: better source address evaluation for destination addresses.
808b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
809b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        if (ip instanceof Inet4Address) {
810b36a3131d1b05efa176f79d318197499b2c45380Erik Kline            // For IPv4, it suffices for now to simply have any address.
81187cfc70b732422d6927ad9fe97f1ad7ab65fd508Lorenzo Colitti            return hasIPv4AddressOnInterface(bestRoute.getInterface());
812b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        } else if (ip instanceof Inet6Address) {
813b36a3131d1b05efa176f79d318197499b2c45380Erik Kline            if (ip.isLinkLocalAddress()) {
814b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                // For now, just make sure link-local destinations have
815b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                // scopedIds set, since transmits will generally fail otherwise.
816b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                // TODO: verify it matches the ifindex of one of the interfaces.
817b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                return (((Inet6Address)ip).getScopeId() != 0);
818b36a3131d1b05efa176f79d318197499b2c45380Erik Kline            }  else {
819b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                // For non-link-local destinations check that either the best route
820b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                // is directly connected or that some global preferred address exists.
821b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                // TODO: reconsider all cases (disconnected ULA networks, ...).
822b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                return (!bestRoute.hasGateway() || hasGlobalIPv6Address());
823b36a3131d1b05efa176f79d318197499b2c45380Erik Kline            }
824b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        }
825b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
826b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        return false;
827b36a3131d1b05efa176f79d318197499b2c45380Erik Kline    }
828b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
829b36a3131d1b05efa176f79d318197499b2c45380Erik Kline    /**
830e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} interface name against the target
831e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
832e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
833e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
8344f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
835e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
836e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalInterfaceName(LinkProperties target) {
837e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
838e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
839e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
840e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
8414717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt     * Compares this {@code LinkProperties} interface addresses against the target
842e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
843e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
844e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
8454f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
846e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
847e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalAddresses(LinkProperties target) {
848e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> targetAddresses = target.getAddresses();
849e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> sourceAddresses = getAddresses();
850e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (sourceAddresses.size() == targetAddresses.size()) ?
851e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    sourceAddresses.containsAll(targetAddresses) : false;
852e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
853e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
854e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
855e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} DNS addresses against the target
856e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
857e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
858e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
8594f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
860e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
861e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalDnses(LinkProperties target) {
862df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt        Collection<InetAddress> targetDnses = target.getDnsServers();
8638058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String targetDomains = target.getDomains();
8648058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        if (mDomains == null) {
8658058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            if (targetDomains != null) return false;
8668058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        } else {
8678058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            if (mDomains.equals(targetDomains) == false) return false;
8688058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        }
869e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (mDnses.size() == targetDnses.size()) ?
870e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    mDnses.containsAll(targetDnses) : false;
871e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
872e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
873e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
874e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} Routes against the target
875e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
876e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
877e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
8784f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
879e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
880e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalRoutes(LinkProperties target) {
881e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<RouteInfo> targetRoutes = target.getRoutes();
882e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (mRoutes.size() == targetRoutes.size()) ?
883e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    mRoutes.containsAll(targetRoutes) : false;
884e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
885e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
886e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
887e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} HttpProxy against the target
888e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
889e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
890e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
8914f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
892e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
893e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalHttpProxy(LinkProperties target) {
894e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return getHttpProxy() == null ? target.getHttpProxy() == null :
895e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    getHttpProxy().equals(target.getHttpProxy());
896e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
8974e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
898419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
899419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Compares this {@code LinkProperties} stacked links against the target
900419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
901419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @param target LinkProperties to compare.
902419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @return {@code true} if both are identical, {@code false} otherwise.
9034f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
904419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
905419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public boolean isIdenticalStackedLinks(LinkProperties target) {
906213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
907419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            return false;
908419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
909419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties stacked : mStackedLinks.values()) {
910419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            // Hashtable values can never be null.
911419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            String iface = stacked.getInterfaceName();
912419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            if (!stacked.equals(target.mStackedLinks.get(iface))) {
913419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                return false;
914419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
915419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
916419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return true;
917419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
918419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
9199d9b74a900696191048aa97cc3c854072640428bsy.yun    /**
9209d9b74a900696191048aa97cc3c854072640428bsy.yun     * Compares this {@code LinkProperties} MTU against the target
9219d9b74a900696191048aa97cc3c854072640428bsy.yun     *
922d57de6afb8981dc1663d41a842ab7cdae93427a1Ying Wang     * @param target LinkProperties to compare.
9239d9b74a900696191048aa97cc3c854072640428bsy.yun     * @return {@code true} if both are identical, {@code false} otherwise.
9244f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
9259d9b74a900696191048aa97cc3c854072640428bsy.yun     */
9269d9b74a900696191048aa97cc3c854072640428bsy.yun    public boolean isIdenticalMtu(LinkProperties target) {
9279d9b74a900696191048aa97cc3c854072640428bsy.yun        return getMtu() == target.getMtu();
9289d9b74a900696191048aa97cc3c854072640428bsy.yun    }
9299d9b74a900696191048aa97cc3c854072640428bsy.yun
9303f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    /**
9313f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * Compares this {@code LinkProperties} Tcp buffer sizes against the target.
9323f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     *
9333f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * @param target LinkProperties to compare.
9343f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * @return {@code true} if both are identical, {@code false} otherwise.
9353f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     * @hide
9363f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt     */
9373f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    public boolean isIdenticalTcpBufferSizes(LinkProperties target) {
9383f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes);
9393f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt    }
9403f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt
9414e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    @Override
9424e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    /**
9434e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * Compares this {@code LinkProperties} instance against the target
9444e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
9454e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * all their fields are equal in values.
9464e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     *
9474e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * For collection fields, such as mDnses, containsAll() is used to check
9484e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * if two collections contains the same elements, independent of order.
9494e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * There are two thoughts regarding containsAll()
9504e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
9514e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * 2. Worst case performance is O(n^2).
9524e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     *
9534e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * @param obj the object to be tested for equality.
9544e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * @return {@code true} if both objects are equal, {@code false} otherwise.
9554e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     */
9564e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public boolean equals(Object obj) {
9574e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        if (this == obj) return true;
9584e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
9594e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        if (!(obj instanceof LinkProperties)) return false;
9604e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
9614e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        LinkProperties target = (LinkProperties) obj;
9624f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt        /**
9634f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt         * This method does not check that stacked interfaces are equal, because
9644f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt         * stacked interfaces are not so much a property of the link as a
9654f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt         * description of connections between links.
9664f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt         */
967e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return isIdenticalInterfaceName(target) &&
968e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalAddresses(target) &&
969e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalDnses(target) &&
970e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalRoutes(target) &&
971419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                isIdenticalHttpProxy(target) &&
9729d9b74a900696191048aa97cc3c854072640428bsy.yun                isIdenticalStackedLinks(target) &&
9733f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt                isIdenticalMtu(target) &&
9743f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt                isIdenticalTcpBufferSizes(target);
975e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
9764e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
977e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
978d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares the addresses in this LinkProperties with another
979d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * LinkProperties, examining only addresses on the base link.
980e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
981d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of addresses
982d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the addresses.
9834f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
984e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
9850a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
986e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        /*
987e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * Duplicate the LinkAddresses into removed, we will be removing
988e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * address which are common between mLinkAddresses and target
989e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * leaving the addresses that are different. And address which
990e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * are in target but not in mLinkAddresses are placed in the
991e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * addedAddresses.
992e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         */
9930a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<LinkAddress> result = new CompareResult<LinkAddress>();
994e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
995e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        result.added.clear();
9960a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
9970a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (LinkAddress newAddress : target.getLinkAddresses()) {
9980a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(newAddress)) {
9990a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(newAddress);
10000a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
1001e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            }
1002e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        }
1003e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return result;
10044e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
10054e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
10060a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    /**
1007d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares the DNS addresses in this LinkProperties with another
1008d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * LinkProperties, examining only DNS addresses on the base link.
10090a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     *
1010d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of dns addresses
1011d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the DNS addresses.
10124f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
10130a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     */
10140a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public CompareResult<InetAddress> compareDnses(LinkProperties target) {
10150a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        /*
10160a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * Duplicate the InetAddresses into removed, we will be removing
10170a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * dns address which are common between mDnses and target
10180a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * leaving the addresses that are different. And dns address which
10190a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * are in target but not in mDnses are placed in the
10200a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * addedAddresses.
10210a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         */
10220a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<InetAddress> result = new CompareResult<InetAddress>();
10230a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
10240a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.removed = new ArrayList<InetAddress>(mDnses);
10250a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.added.clear();
10260a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
1027df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt            for (InetAddress newAddress : target.getDnsServers()) {
10280a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(newAddress)) {
10290a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(newAddress);
10300a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
10310a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            }
10320a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        }
10330a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return result;
10340a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
10350a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
10360a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    /**
1037d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares all routes in this LinkProperties with another LinkProperties,
1038d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * examining both the the base link and all stacked links.
10390a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     *
1040d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of routes
1041d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the routes.
10424f05d5529625fd2f0ad13ff9974c338d2f847934Robert Greenwalt     * @hide
10430a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     */
1044d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) {
10450a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        /*
10460a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * Duplicate the RouteInfos into removed, we will be removing
10471994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti         * routes which are common between mRoutes and target
10480a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * leaving the routes that are different. And route address which
10490a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * are in target but not in mRoutes are placed in added.
10500a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         */
10510a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
10520a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
1053419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        result.removed = getAllRoutes();
10540a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.added.clear();
10550a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
1056419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (RouteInfo r : target.getAllRoutes()) {
10570a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(r)) {
10580a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(r);
10590a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
10600a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            }
10610a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        }
10620a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return result;
10630a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
10640a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
1065992f25257938ecc0378514f21c6e6e6375272976Paul Jensen    /**
1066992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * Compares all interface names in this LinkProperties with another
1067992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * LinkProperties, examining both the the base link and all stacked links.
1068992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     *
1069992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * @param target a LinkProperties with the new list of interface names
1070992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * @return the differences between the interface names.
1071992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * @hide
1072992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     */
1073992f25257938ecc0378514f21c6e6e6375272976Paul Jensen    public CompareResult<String> compareAllInterfaceNames(LinkProperties target) {
1074992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        /*
1075992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * Duplicate the interface names into removed, we will be removing
1076992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * interface names which are common between this and target
1077992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * leaving the interface names that are different. And interface names which
1078992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * are in target but not in this are placed in added.
1079992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         */
1080992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        CompareResult<String> result = new CompareResult<String>();
1081992f25257938ecc0378514f21c6e6e6375272976Paul Jensen
1082992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        result.removed = getAllInterfaceNames();
1083992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        result.added.clear();
1084992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        if (target != null) {
1085992f25257938ecc0378514f21c6e6e6375272976Paul Jensen            for (String r : target.getAllInterfaceNames()) {
1086992f25257938ecc0378514f21c6e6e6375272976Paul Jensen                if (! result.removed.remove(r)) {
1087992f25257938ecc0378514f21c6e6e6375272976Paul Jensen                    result.added.add(r);
1088992f25257938ecc0378514f21c6e6e6375272976Paul Jensen                }
1089992f25257938ecc0378514f21c6e6e6375272976Paul Jensen            }
1090992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        }
1091992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        return result;
1092992f25257938ecc0378514f21c6e6e6375272976Paul Jensen    }
1093992f25257938ecc0378514f21c6e6e6375272976Paul Jensen
10940a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
10954e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    @Override
10964e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    /**
10974e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * generate hashcode based on significant fields
10984e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * Equal objects must produce the same hash code, while unequal objects
10994e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * may have the same hash codes.
11004e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     */
11014e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public int hashCode() {
11024e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
11034e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang                + mLinkAddresses.size() * 31
11044e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang                + mDnses.size() * 37
11058058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt                + ((null == mDomains) ? 0 : mDomains.hashCode())
1106aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                + mRoutes.size() * 41
1107419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
11089d9b74a900696191048aa97cc3c854072640428bsy.yun                + mStackedLinks.hashCode() * 47)
11093f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt                + mMtu * 51
11103f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt                + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode());
11114e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
11124e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
111347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
111447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface.
111547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
111637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
111747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dest.writeString(getInterfaceName());
1118ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        dest.writeInt(mLinkAddresses.size());
1119ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        for(LinkAddress linkAddress : mLinkAddresses) {
1120ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            dest.writeParcelable(linkAddress, flags);
112147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
1122ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
112347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dest.writeInt(mDnses.size());
112447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        for(InetAddress d : mDnses) {
112547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByteArray(d.getAddress());
112647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
11278058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        dest.writeString(mDomains);
11289d9b74a900696191048aa97cc3c854072640428bsy.yun        dest.writeInt(mMtu);
11293f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt        dest.writeString(mTcpBufferSizes);
1130aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        dest.writeInt(mRoutes.size());
1131aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        for(RouteInfo route : mRoutes) {
1132aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeParcelable(route, flags);
113347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
1134992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt
113547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        if (mHttpProxy != null) {
113647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByte((byte)1);
113747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeParcelable(mHttpProxy, flags);
113847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        } else {
113947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByte((byte)0);
114047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
1141419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        ArrayList<LinkProperties> stackedLinks = new ArrayList(mStackedLinks.values());
1142419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        dest.writeList(stackedLinks);
114347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
114447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
114547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
114647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface.
114747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
114837e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public static final Creator<LinkProperties> CREATOR =
114937e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt        new Creator<LinkProperties>() {
115037e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt            public LinkProperties createFromParcel(Parcel in) {
115137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt                LinkProperties netProp = new LinkProperties();
11524717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt
115347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                String iface = in.readString();
115447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                if (iface != null) {
11554717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt                    netProp.setInterfaceName(iface);
115647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
115747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                int addressCount = in.readInt();
115847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                for (int i=0; i<addressCount; i++) {
1159ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                    netProp.addLinkAddress((LinkAddress)in.readParcelable(null));
116047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
116147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                addressCount = in.readInt();
116247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                for (int i=0; i<addressCount; i++) {
116347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                    try {
1164df2b878ff4e7b4a258588d3a93574c399db78a07Robert Greenwalt                        netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
116547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                    } catch (UnknownHostException e) { }
116647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
11678058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt                netProp.setDomains(in.readString());
11689d9b74a900696191048aa97cc3c854072640428bsy.yun                netProp.setMtu(in.readInt());
11693f05bf4d7838cb719e78f9d93b22d7ce777392c5Robert Greenwalt                netProp.setTcpBufferSizes(in.readString());
1170992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt                addressCount = in.readInt();
1171992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt                for (int i=0; i<addressCount; i++) {
1172aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    netProp.addRoute((RouteInfo)in.readParcelable(null));
117347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
117447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                if (in.readByte() == 1) {
1175207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk                    netProp.setHttpProxy((ProxyInfo)in.readParcelable(null));
117647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
1177419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
1178419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                in.readList(stackedLinks, LinkProperties.class.getClassLoader());
1179419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                for (LinkProperties stackedLink: stackedLinks) {
1180419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                    netProp.addStackedLink(stackedLink);
1181419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                }
118247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                return netProp;
118347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            }
118447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
118537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt            public LinkProperties[] newArray(int size) {
118637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt                return new LinkProperties[size];
118747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            }
118847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        };
118915afd8115869bf22534a1f26fe6e389c9e5ef413w
119015afd8115869bf22534a1f26fe6e389c9e5ef413w        /**
119115afd8115869bf22534a1f26fe6e389c9e5ef413w         * Check the valid MTU range based on IPv4 or IPv6.
119215afd8115869bf22534a1f26fe6e389c9e5ef413w         * @hide
119315afd8115869bf22534a1f26fe6e389c9e5ef413w         */
119415afd8115869bf22534a1f26fe6e389c9e5ef413w        public static boolean isValidMtu(int mtu, boolean ipv6) {
119515afd8115869bf22534a1f26fe6e389c9e5ef413w            if (ipv6) {
119615afd8115869bf22534a1f26fe6e389c9e5ef413w                if ((mtu >= MIN_MTU_V6 && mtu <= MAX_MTU)) return true;
119715afd8115869bf22534a1f26fe6e389c9e5ef413w            } else {
119815afd8115869bf22534a1f26fe6e389c9e5ef413w                if ((mtu >= MIN_MTU && mtu <= MAX_MTU)) return true;
119915afd8115869bf22534a1f26fe6e389c9e5ef413w            }
120015afd8115869bf22534a1f26fe6e389c9e5ef413w            return false;
120115afd8115869bf22534a1f26fe6e389c9e5ef413w        }
120247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt}
1203