Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd00589e authored by Harout Hedeshian's avatar Harout Hedeshian Committed by Steve Kondik
Browse files

frameworks/base: IPV6 tethering support

This patch adds two new API calls addUpstreamV6Interface and
removeUpstreamV6Interface to the tethering framework to pass the IPv6
upstream and downstream interfaces to netd if IPv6 is available.
Required to enable ICMPv6 forwarding.

Change-Id: I1f4f6284b2f152d8b4f0fbd02ac5a17f57c71dd7
parent 3716068c
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -192,6 +192,16 @@ interface INetworkManagementService
     */
    void disableNat(String internalInterface, String externalInterface);

    /**
     * Add an upstream IPv6 interface
     */
    void addUpstreamV6Interface(String iface);

    /**
     * Remove an upstream IPv6 interface
     */
    void removeUpstreamV6Interface(String iface);

    /**
     ** PPPD
     **/
+35 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import java.util.List;

import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.Preconditions;
@@ -133,6 +134,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        public static final int TetheringStatsResult      = 221;
        public static final int DnsProxyQueryResult       = 222;
        public static final int ClatdStatusResult         = 223;
        public static final int V6RtrAdvResult            = 224;

        public static final int InterfaceChange           = 600;
        public static final int BandwidthControl          = 601;
@@ -493,6 +495,39 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        }
    }

    @Override
    public void addUpstreamV6Interface(String iface) throws IllegalStateException {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");

        Slog.d(TAG, "addUpstreamInterface("+ iface + ")");
        try {
            final Command cmd = new Command("tether", "interface", "add_upstream");
            cmd.appendArg(iface);
            mConnector.execute(cmd);
        } catch (NativeDaemonConnectorException e) {
            throw new IllegalStateException("Cannot add upstream interface");
        }
    }

    @Override
    public void removeUpstreamV6Interface(String iface) throws IllegalStateException {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");

        Slog.d(TAG, "removeUpstreamInterface(" + iface + ")");

        try {
            final Command cmd = new Command("tether", "interface", "add_upstream");
            cmd.appendArg(iface);
            mConnector.execute(cmd);

            mConnector.execute(cmd);
        } catch (NativeDaemonConnectorException e) {
            throw new IllegalStateException("Cannot remove upstream interface");
        }
    }

    @Override
    public InterfaceConfiguration getInterfaceConfig(String iface) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+70 −2
Original line number Diff line number Diff line
@@ -545,7 +545,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                if (networkInfo != null &&
                        networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
                    if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
                    mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
                    mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED, networkInfo);
                }
            } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
                updateConfiguration();
@@ -1318,7 +1318,55 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                return true;
            }

            protected void addUpstreamV6Interface(String iface) {
                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
                INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);

                Log.d(TAG, "adding v6 interface " + iface);
                try {
                    service.addUpstreamV6Interface(iface);
                } catch (Exception e) {
                    Log.e(TAG, "Unable to append v6 upstream interface", e);
                }
            }

            protected void removeUpstreamV6Interface(String iface) {
                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
                INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);

                Log.d(TAG, "removing v6 interface " + iface);
                try {
                    service.removeUpstreamV6Interface(iface);
                } catch (Exception e) {
                    Log.e(TAG, "Unable to remove v6 upstream interface", e);
                }
            }


            boolean isIpv6Connected(IConnectivityManager cm, LinkProperties linkProps) {
                boolean ret = false;
                Collection <InetAddress> addresses = null;

                if (cm == null || linkProps == null) {
                    return false;
                }
                addresses = linkProps.getAddresses();
                for (InetAddress addr: addresses) {
                    if (addr instanceof java.net.Inet6Address) {
                        java.net.Inet6Address i6addr = (java.net.Inet6Address) addr;
                        if (!i6addr.isAnyLocalAddress() && !i6addr.isLinkLocalAddress() &&
                                !i6addr.isLoopbackAddress() && !i6addr.isMulticastAddress()) {
                            ret = true;
                            break;
                        }
                    }
                }
                return ret;
            }

            protected void chooseUpstreamType(boolean tryCell) {
                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                int upType = ConnectivityManager.TYPE_NONE;
                String iface = null;

@@ -1334,11 +1382,20 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

                    for (Integer netType : mUpstreamIfaceTypes) {
                        NetworkInfo info = null;
                        LinkProperties props = null;
                        boolean isV6Connected = false;
                        try {
                            info = mConnService.getNetworkInfo(netType.intValue());
                            info = cm.getNetworkInfo(netType.intValue());
                            if (info != null) {
                                props = cm.getLinkProperties(info.getType());
                                isV6Connected = isIpv6Connected(cm, props);
                            }
                        } catch (RemoteException e) { }
                        if ((info != null) && info.isConnected()) {
                            upType = netType.intValue();
                            if (isV6Connected) {
                                addUpstreamV6Interface(props.getInterfaceName());
                            }
                            break;
                        }
                    }
@@ -1510,8 +1567,19 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                        break;
                    case CMD_UPSTREAM_CHANGED:
                        // need to try DUN immediately if Wifi goes down
                        NetworkInfo info = (NetworkInfo) message.obj;
                        mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
                        chooseUpstreamType(mTryCell);
                        if (!info.isConnected()) {
                            IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                            IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                            try {
                                LinkProperties props = cm.getLinkProperties(info.getType());
                                removeUpstreamV6Interface(props.getInterfaceName());
                            } catch(Exception e) {
                                Log.e(TAG, "Exception querying ConnectivityManager", e);
                            }
                        }
                        mTryCell = !mTryCell;
                        break;
                    case CMD_CELL_CONNECTION_RENEW: