Home | History | Annotate | Download | only in connectivity
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.connectivity;
     18 
     19 import static android.net.ConnectivityManager.TYPE_MOBILE;
     20 
     21 import java.net.Inet4Address;
     22 
     23 import android.content.Context;
     24 import android.net.IConnectivityManager;
     25 import android.net.InterfaceConfiguration;
     26 import android.net.LinkAddress;
     27 import android.net.LinkProperties;
     28 import android.net.NetworkStateTracker;
     29 import android.net.NetworkUtils;
     30 import android.net.RouteInfo;
     31 import android.os.Handler;
     32 import android.os.Message;
     33 import android.os.INetworkManagementService;
     34 import android.os.RemoteException;
     35 import android.util.Slog;
     36 
     37 import com.android.server.net.BaseNetworkObserver;
     38 
     39 /**
     40  * @hide
     41  *
     42  * Class to manage a 464xlat CLAT daemon.
     43  */
     44 public class Nat464Xlat extends BaseNetworkObserver {
     45     private Context mContext;
     46     private INetworkManagementService mNMService;
     47     private IConnectivityManager mConnService;
     48     private NetworkStateTracker mTracker;
     49     private Handler mHandler;
     50 
     51     // Whether we started clatd and expect it to be running.
     52     private boolean mIsStarted;
     53     // Whether the clatd interface exists (i.e., clatd is running).
     54     private boolean mIsRunning;
     55     // The LinkProperties of the clat interface.
     56     private LinkProperties mLP;
     57 
     58     // This must match the interface name in clatd.conf.
     59     private static final String CLAT_INTERFACE_NAME = "clat4";
     60 
     61     private static final String TAG = "Nat464Xlat";
     62 
     63     public Nat464Xlat(Context context, INetworkManagementService nmService,
     64                       IConnectivityManager connService, Handler handler) {
     65         mContext = context;
     66         mNMService = nmService;
     67         mConnService = connService;
     68         mHandler = handler;
     69 
     70         mIsStarted = false;
     71         mIsRunning = false;
     72         mLP = new LinkProperties();
     73     }
     74 
     75     /**
     76      * Determines whether an interface requires clat.
     77      * @param netType the network type (one of the
     78      *   android.net.ConnectivityManager.TYPE_* constants)
     79      * @param tracker the NetworkStateTracker corresponding to the network type.
     80      * @return true if the interface requires clat, false otherwise.
     81      */
     82     public boolean requiresClat(int netType, NetworkStateTracker tracker) {
     83         LinkProperties lp = tracker.getLinkProperties();
     84         // Only support clat on mobile for now.
     85         Slog.d(TAG, "requiresClat: netType=" + netType + ", hasIPv4Address=" +
     86                lp.hasIPv4Address());
     87         return netType == TYPE_MOBILE && !lp.hasIPv4Address();
     88     }
     89 
     90     public static boolean isRunningClat(LinkProperties lp) {
     91       return lp != null && lp.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME);
     92     }
     93 
     94     /**
     95      * Starts the clat daemon.
     96      * @param lp The link properties of the interface to start clatd on.
     97      */
     98     public void startClat(NetworkStateTracker tracker) {
     99         if (mIsStarted) {
    100             Slog.e(TAG, "startClat: already started");
    101             return;
    102         }
    103         mTracker = tracker;
    104         LinkProperties lp = mTracker.getLinkProperties();
    105         String iface = lp.getInterfaceName();
    106         Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp);
    107         try {
    108             mNMService.startClatd(iface);
    109         } catch(RemoteException e) {
    110             Slog.e(TAG, "Error starting clat daemon: " + e);
    111         }
    112         mIsStarted = true;
    113     }
    114 
    115     /**
    116      * Stops the clat daemon.
    117      */
    118     public void stopClat() {
    119         if (mIsStarted) {
    120             Slog.i(TAG, "Stopping clatd");
    121             try {
    122                 mNMService.stopClatd();
    123             } catch(RemoteException e) {
    124                 Slog.e(TAG, "Error stopping clat daemon: " + e);
    125             }
    126             mIsStarted = false;
    127             mIsRunning = false;
    128             mTracker = null;
    129             mLP.clear();
    130         } else {
    131             Slog.e(TAG, "stopClat: already stopped");
    132         }
    133     }
    134 
    135     public boolean isStarted() {
    136         return mIsStarted;
    137     }
    138 
    139     public boolean isRunning() {
    140         return mIsRunning;
    141     }
    142 
    143     @Override
    144     public void interfaceAdded(String iface) {
    145         if (iface.equals(CLAT_INTERFACE_NAME)) {
    146             Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME +
    147                    " added, mIsRunning = " + mIsRunning + " -> true");
    148             mIsRunning = true;
    149 
    150             // Get the network configuration of the clat interface, store it
    151             // in our link properties, and stack it on top of the interface
    152             // it's running on.
    153             try {
    154                 InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
    155                 mLP.clear();
    156                 mLP.setInterfaceName(iface);
    157                 RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0), null,
    158                                                       iface);
    159                 mLP.addRoute(ipv4Default);
    160                 mLP.addLinkAddress(config.getLinkAddress());
    161                 mTracker.addStackedLink(mLP);
    162                 Slog.i(TAG, "Adding stacked link. tracker LP: " +
    163                        mTracker.getLinkProperties());
    164             } catch(RemoteException e) {
    165                 Slog.e(TAG, "Error getting link properties: " + e);
    166             }
    167 
    168             // Inform ConnectivityService that things have changed.
    169             Message msg = mHandler.obtainMessage(
    170                 NetworkStateTracker.EVENT_CONFIGURATION_CHANGED,
    171                 mTracker.getNetworkInfo());
    172             Slog.i(TAG, "sending message to ConnectivityService: " + msg);
    173             msg.sendToTarget();
    174         }
    175     }
    176 
    177     @Override
    178     public void interfaceRemoved(String iface) {
    179         if (iface == CLAT_INTERFACE_NAME) {
    180             if (mIsRunning) {
    181                 NetworkUtils.resetConnections(
    182                     CLAT_INTERFACE_NAME,
    183                     NetworkUtils.RESET_IPV4_ADDRESSES);
    184             }
    185             Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME +
    186                    " removed, mIsRunning = " + mIsRunning + " -> false");
    187             mIsRunning = false;
    188             mTracker.removeStackedLink(mLP);
    189             mLP.clear();
    190             Slog.i(TAG, "mLP = " + mLP);
    191         }
    192     }
    193 };
    194