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