11eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline/*
21eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * Copyright (C) 2016 The Android Open Source Project
31eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline *
41eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * Licensed under the Apache License, Version 2.0 (the "License");
51eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * you may not use this file except in compliance with the License.
61eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * You may obtain a copy of the License at
71eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline *
81eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline *      http://www.apache.org/licenses/LICENSE-2.0
91eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline *
101eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * Unless required by applicable law or agreed to in writing, software
111eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * distributed under the License is distributed on an "AS IS" BASIS,
121eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * See the License for the specific language governing permissions and
141eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * limitations under the License.
151eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline */
161eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
171eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klinepackage com.android.server.connectivity.tethering;
181eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
191eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.ConnectivityManager;
201eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.IpPrefix;
211eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.LinkAddress;
221eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.LinkProperties;
231eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.Network;
241eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.NetworkCapabilities;
251eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.NetworkState;
261eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.net.RouteInfo;
271eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport android.util.Log;
281eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
291eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport java.net.Inet6Address;
301eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport java.net.InetAddress;
311eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klineimport java.util.ArrayList;
326e29bf0069caceb38806101c150acb477df99989Erik Klineimport java.util.LinkedList;
331eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
341eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
351eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline/**
361eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * IPv6 tethering is rather different from IPv4 owing to the absence of NAT.
371eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * This coordinator is responsible for evaluating the dedicated prefixes
381eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * assigned to the device and deciding how to divvy them up among downstream
391eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * interfaces.
401eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline *
411eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline * @hide
421eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline */
431eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Klinepublic class IPv6TetheringCoordinator {
441eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private static final String TAG = IPv6TetheringCoordinator.class.getSimpleName();
451eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private static final boolean DBG = false;
461eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private static final boolean VDBG = false;
471eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
481eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
496e29bf0069caceb38806101c150acb477df99989Erik Kline    private final LinkedList<TetherInterfaceStateMachine> mActiveDownstreams;
501eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private NetworkState mUpstreamNetworkState;
511eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
521eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    public IPv6TetheringCoordinator(ArrayList<TetherInterfaceStateMachine> notifyList) {
531eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        mNotifyList = notifyList;
546e29bf0069caceb38806101c150acb477df99989Erik Kline        mActiveDownstreams = new LinkedList<>();
556e29bf0069caceb38806101c150acb477df99989Erik Kline    }
566e29bf0069caceb38806101c150acb477df99989Erik Kline
576e29bf0069caceb38806101c150acb477df99989Erik Kline    public void addActiveDownstream(TetherInterfaceStateMachine downstream) {
586e29bf0069caceb38806101c150acb477df99989Erik Kline        if (mActiveDownstreams.indexOf(downstream) == -1) {
596e29bf0069caceb38806101c150acb477df99989Erik Kline            // Adding a new downstream appends it to the list. Adding a
606e29bf0069caceb38806101c150acb477df99989Erik Kline            // downstream a second time without first removing it has no effect.
616e29bf0069caceb38806101c150acb477df99989Erik Kline            mActiveDownstreams.offer(downstream);
626e29bf0069caceb38806101c150acb477df99989Erik Kline            updateIPv6TetheringInterfaces();
636e29bf0069caceb38806101c150acb477df99989Erik Kline        }
646e29bf0069caceb38806101c150acb477df99989Erik Kline    }
656e29bf0069caceb38806101c150acb477df99989Erik Kline
666e29bf0069caceb38806101c150acb477df99989Erik Kline    public void removeActiveDownstream(TetherInterfaceStateMachine downstream) {
676e29bf0069caceb38806101c150acb477df99989Erik Kline        stopIPv6TetheringOn(downstream);
686e29bf0069caceb38806101c150acb477df99989Erik Kline        if (mActiveDownstreams.remove(downstream)) {
696e29bf0069caceb38806101c150acb477df99989Erik Kline            updateIPv6TetheringInterfaces();
706e29bf0069caceb38806101c150acb477df99989Erik Kline        }
711eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
721eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
731eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    public void updateUpstreamNetworkState(NetworkState ns) {
741eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        if (VDBG) {
751eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
761eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
77fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline        if (!canTetherIPv6(ns)) {
781eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            stopIPv6TetheringOnAllInterfaces();
791eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            setUpstreamNetworkState(null);
801eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            return;
811eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
821eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
831eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        if (mUpstreamNetworkState != null &&
841eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            !ns.network.equals(mUpstreamNetworkState.network)) {
851eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            stopIPv6TetheringOnAllInterfaces();
861eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
87fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline
881eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        setUpstreamNetworkState(ns);
89fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline        updateIPv6TetheringInterfaces();
901eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
911eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
921eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private void stopIPv6TetheringOnAllInterfaces() {
931eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        for (TetherInterfaceStateMachine sm : mNotifyList) {
946e29bf0069caceb38806101c150acb477df99989Erik Kline            stopIPv6TetheringOn(sm);
951eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
961eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
971eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
981eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private void setUpstreamNetworkState(NetworkState ns) {
99fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline        if (ns == null) {
1001eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            mUpstreamNetworkState = null;
1011eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        } else {
102fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline            // Make a deep copy of the parts we need.
1031eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            mUpstreamNetworkState = new NetworkState(
1041eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    null,
1051eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    new LinkProperties(ns.linkProperties),
1061eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    new NetworkCapabilities(ns.networkCapabilities),
1071eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    new Network(ns.network),
1081eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    null,
1091eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    null);
1101eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
1111eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1121eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        if (DBG) {
1131eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            Log.d(TAG, "setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
1141eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
1151eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
1161eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
117fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline    private void updateIPv6TetheringInterfaces() {
1181eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        for (TetherInterfaceStateMachine sm : mNotifyList) {
1196e29bf0069caceb38806101c150acb477df99989Erik Kline            final LinkProperties lp = getInterfaceIPv6LinkProperties(sm);
120fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline            sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
1211eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            break;
1221eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
1231eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
1241eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1256e29bf0069caceb38806101c150acb477df99989Erik Kline    private LinkProperties getInterfaceIPv6LinkProperties(TetherInterfaceStateMachine sm) {
126fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline        if (mUpstreamNetworkState == null) return null;
127fa37b2f6135a532742ef8242e70dbf499abe8d95Erik Kline
1286e29bf0069caceb38806101c150acb477df99989Erik Kline        if (sm.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) {
1296e29bf0069caceb38806101c150acb477df99989Erik Kline            // TODO: Figure out IPv6 support on PAN interfaces.
1306e29bf0069caceb38806101c150acb477df99989Erik Kline            return null;
1316e29bf0069caceb38806101c150acb477df99989Erik Kline        }
1326e29bf0069caceb38806101c150acb477df99989Erik Kline
1331eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // NOTE: Here, in future, we would have policies to decide how to divvy
1341eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // up the available dedicated prefixes among downstream interfaces.
1351eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // At this time we have no such mechanism--we only support tethering
1366e29bf0069caceb38806101c150acb477df99989Erik Kline        // IPv6 toward the oldest (first requested) active downstream.
1376e29bf0069caceb38806101c150acb477df99989Erik Kline
1386e29bf0069caceb38806101c150acb477df99989Erik Kline        final TetherInterfaceStateMachine currentActive = mActiveDownstreams.peek();
1396e29bf0069caceb38806101c150acb477df99989Erik Kline        if (currentActive != null && currentActive == sm) {
1406e29bf0069caceb38806101c150acb477df99989Erik Kline            final LinkProperties lp = getIPv6OnlyLinkProperties(
1416e29bf0069caceb38806101c150acb477df99989Erik Kline                    mUpstreamNetworkState.linkProperties);
1426e29bf0069caceb38806101c150acb477df99989Erik Kline            if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) {
1436e29bf0069caceb38806101c150acb477df99989Erik Kline                return lp;
1446e29bf0069caceb38806101c150acb477df99989Erik Kline            }
1451eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
1461eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1471eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        return null;
1481eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
1491eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1501eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private static boolean canTetherIPv6(NetworkState ns) {
1511eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // Broadly speaking:
1521eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        //
1531eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        //     [1] does the upstream have an IPv6 default route?
1541eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        //
1551eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // and
1561eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        //
1571eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        //     [2] does the upstream have one or more global IPv6 /64s
1581eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        //         dedicated to this device?
1591eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        //
1601eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // In lieu of Prefix Delegation and other evaluation of whether a
1611eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // prefix may or may not be dedicated to this device, for now just
1621eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // check whether the upstream is TRANSPORT_CELLULAR. This works
1631eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // because "[t]he 3GPP network allocates each default bearer a unique
1641eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // /64 prefix", per RFC 6459, Section 5.2.
1651eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1661eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        final boolean canTether =
1671eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                (ns != null) && (ns.network != null) &&
1681eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                (ns.linkProperties != null) && (ns.networkCapabilities != null) &&
1691eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                // At least one upstream DNS server:
1701eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                ns.linkProperties.isProvisioned() &&
1711eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                // Minimal amount of IPv6 provisioning:
1721eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                ns.linkProperties.hasIPv6DefaultRoute() &&
1731eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                ns.linkProperties.hasGlobalIPv6Address() &&
1741eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                // Temporary approximation of "dedicated prefix":
1751eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
1761eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1771eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // For now, we do not support separate IPv4 and IPv6 upstreams (e.g.
1781eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // tethering with 464xlat involved). TODO: Rectify this shortcoming,
1791eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // likely by calling NetworkManagementService#startInterfaceForwarding()
1801eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // for all upstream interfaces.
1811eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        RouteInfo v4default = null;
1821eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        RouteInfo v6default = null;
1831eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        if (canTether) {
1841eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            for (RouteInfo r : ns.linkProperties.getAllRoutes()) {
1851eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                if (r.isIPv4Default()) {
1861eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    v4default = r;
1871eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                } else if (r.isIPv6Default()) {
1881eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    v6default = r;
1891eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                }
1901eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1911eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                if (v4default != null && v6default != null) {
1921eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                    break;
1931eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                }
1941eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            }
1951eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
1961eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
1971eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        final boolean supportedConfiguration =
1981eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                (v4default != null) && (v6default != null) &&
1991eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                (v4default.getInterface() != null) &&
2001eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                v4default.getInterface().equals(v6default.getInterface());
2011eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2021eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        final boolean outcome = canTether && supportedConfiguration;
2031eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2041eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        if (VDBG) {
2051eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            if (ns == null) {
2061eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                Log.d(TAG, "No available upstream.");
2071eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            } else {
2081eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                Log.d(TAG, String.format("IPv6 tethering is %s for upstream: %s",
2091eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                        (outcome ? "available" : "not available"), toDebugString(ns)));
2101eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            }
2111eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
2121eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2131eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        return outcome;
2141eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
2151eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2161eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private static LinkProperties getIPv6OnlyLinkProperties(LinkProperties lp) {
2171eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        final LinkProperties v6only = new LinkProperties();
2181eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        if (lp == null) {
2191eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            return v6only;
2201eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
2211eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2221eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // NOTE: At this time we don't copy over any information about any
2231eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        // stacked links. No current stacked link configuration has IPv6.
2241eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2251eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        v6only.setInterfaceName(lp.getInterfaceName());
2261eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2271eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        v6only.setMtu(lp.getMtu());
2281eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2291eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        for (LinkAddress linkAddr : lp.getLinkAddresses()) {
2301eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            if (linkAddr.isGlobalPreferred() && linkAddr.getPrefixLength() == 64) {
2311eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                v6only.addLinkAddress(linkAddr);
2321eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            }
2331eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
2341eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2351eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        for (RouteInfo routeInfo : lp.getRoutes()) {
2361eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            final IpPrefix destination = routeInfo.getDestination();
2371eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            if ((destination.getAddress() instanceof Inet6Address) &&
2381eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                (destination.getPrefixLength() <= 64)) {
2391eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                v6only.addRoute(routeInfo);
2401eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            }
2411eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
2421eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2431eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        for (InetAddress dnsServer : lp.getDnsServers()) {
2441eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            if (isIPv6GlobalAddress(dnsServer)) {
2451eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                // For now we include ULAs.
2461eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                v6only.addDnsServer(dnsServer);
2471eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            }
2481eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
2491eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2501eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        v6only.setDomains(lp.getDomains());
2511eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2521eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        return v6only;
2531eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
2541eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2551eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    // TODO: Delete this and switch to LinkAddress#isGlobalPreferred once we
2561eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    // announce our own IPv6 address as DNS server.
2571eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private static boolean isIPv6GlobalAddress(InetAddress ip) {
2581eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        return (ip instanceof Inet6Address) &&
2591eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline               !ip.isAnyLocalAddress() &&
2601eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline               !ip.isLoopbackAddress() &&
2611eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline               !ip.isLinkLocalAddress() &&
2621eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline               !ip.isSiteLocalAddress() &&
2631eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline               !ip.isMulticastAddress();
2641eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
2651eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline
2661eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    private static String toDebugString(NetworkState ns) {
2671eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        if (ns == null) {
2681eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline            return "NetworkState{null}";
2691eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        }
2701eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline        return String.format("NetworkState{%s, %s, %s}",
2711eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                ns.network,
2721eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                ns.networkCapabilities,
2731eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline                ns.linkProperties);
2741eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline    }
2756e29bf0069caceb38806101c150acb477df99989Erik Kline
2766e29bf0069caceb38806101c150acb477df99989Erik Kline    private static void stopIPv6TetheringOn(TetherInterfaceStateMachine sm) {
2776e29bf0069caceb38806101c150acb477df99989Erik Kline        sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
2786e29bf0069caceb38806101c150acb477df99989Erik Kline    }
2791eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline}
280