Nat464Xlat.java revision 43b76dfddbfe2a27a0658dbca8632a9b1dc8d6ff
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 17package com.android.server.connectivity; 18 19import static android.net.ConnectivityManager.TYPE_MOBILE; 20 21import java.net.Inet4Address; 22 23import android.content.Context; 24import android.net.IConnectivityManager; 25import android.net.InterfaceConfiguration; 26import android.net.LinkAddress; 27import android.net.LinkProperties; 28import android.net.NetworkAgent; 29import android.net.NetworkUtils; 30import android.net.RouteInfo; 31import android.os.Handler; 32import android.os.Message; 33import android.os.Messenger; 34import android.os.INetworkManagementService; 35import android.os.RemoteException; 36import android.util.Slog; 37 38import com.android.server.net.BaseNetworkObserver; 39 40/** 41 * @hide 42 * 43 * Class to manage a 464xlat CLAT daemon. 44 */ 45public class Nat464Xlat extends BaseNetworkObserver { 46 private Context mContext; 47 private INetworkManagementService mNMService; 48 private IConnectivityManager mConnService; 49 // Whether we started clatd and expect it to be running. 50 private boolean mIsStarted; 51 // Whether the clatd interface exists (i.e., clatd is running). 52 private boolean mIsRunning; 53 // The LinkProperties of the clat interface. 54 private LinkProperties mLP; 55 // Current LinkProperties of the network. Includes mLP as a stacked link when clat is active. 56 private LinkProperties mBaseLP; 57 // ConnectivityService Handler for LinkProperties updates. 58 private Handler mHandler; 59 // Marker to connote which network we're augmenting. 60 private Messenger mNetworkMessenger; 61 62 // This must match the interface name in clatd.conf. 63 private static final String CLAT_INTERFACE_NAME = "clat4"; 64 65 private static final String TAG = "Nat464Xlat"; 66 67 public Nat464Xlat(Context context, INetworkManagementService nmService, 68 IConnectivityManager connService, Handler handler) { 69 mContext = context; 70 mNMService = nmService; 71 mConnService = connService; 72 mHandler = handler; 73 74 mIsStarted = false; 75 mIsRunning = false; 76 mLP = new LinkProperties(); 77 78 // If this is a runtime restart, it's possible that clatd is already 79 // running, but we don't know about it. If so, stop it. 80 try { 81 if (mNMService.isClatdStarted()) { 82 mNMService.stopClatd(); 83 } 84 } catch(RemoteException e) {} // Well, we tried. 85 } 86 87 /** 88 * Determines whether a network requires clat. 89 * @param network the NetworkAgentInfo corresponding to the network. 90 * @return true if the network requires clat, false otherwise. 91 */ 92 public boolean requiresClat(NetworkAgentInfo network) { 93 int netType = network.networkInfo.getType(); 94 LinkProperties lp = network.linkProperties; 95 // Only support clat on mobile for now. 96 Slog.d(TAG, "requiresClat: netType=" + netType + ", hasIPv4Address=" + 97 lp.hasIPv4Address()); 98 return netType == TYPE_MOBILE && !lp.hasIPv4Address(); 99 } 100 101 public static boolean isRunningClat(LinkProperties lp) { 102 return lp != null && lp.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME); 103 } 104 105 /** 106 * Starts the clat daemon. 107 * @param lp The link properties of the interface to start clatd on. 108 */ 109 public void startClat(NetworkAgentInfo network) { 110 if (mNetworkMessenger != null && mNetworkMessenger != network.messenger) { 111 Slog.e(TAG, "startClat: too many networks requesting clat"); 112 return; 113 } 114 mNetworkMessenger = network.messenger; 115 LinkProperties lp = network.linkProperties; 116 mBaseLP = new LinkProperties(lp); 117 if (mIsStarted) { 118 Slog.e(TAG, "startClat: already started"); 119 return; 120 } 121 String iface = lp.getInterfaceName(); 122 Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp); 123 try { 124 mNMService.startClatd(iface); 125 } catch(RemoteException e) { 126 Slog.e(TAG, "Error starting clat daemon: " + e); 127 } 128 mIsStarted = true; 129 } 130 131 /** 132 * Stops the clat daemon. 133 */ 134 public void stopClat() { 135 if (mIsStarted) { 136 Slog.i(TAG, "Stopping clatd"); 137 try { 138 mNMService.stopClatd(); 139 } catch(RemoteException e) { 140 Slog.e(TAG, "Error stopping clat daemon: " + e); 141 } 142 mIsStarted = false; 143 mIsRunning = false; 144 mNetworkMessenger = null; 145 mBaseLP = null; 146 mLP.clear(); 147 } else { 148 Slog.e(TAG, "stopClat: already stopped"); 149 } 150 } 151 152 public boolean isStarted() { 153 return mIsStarted; 154 } 155 156 public boolean isRunning() { 157 return mIsRunning; 158 } 159 160 private void updateConnectivityService() { 161 Message msg = mHandler.obtainMessage( 162 NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, mBaseLP); 163 msg.replyTo = mNetworkMessenger; 164 Slog.i(TAG, "sending message to ConnectivityService: " + msg); 165 msg.sendToTarget(); 166 } 167 168 @Override 169 public void interfaceAdded(String iface) { 170 if (iface.equals(CLAT_INTERFACE_NAME)) { 171 Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + 172 " added, mIsRunning = " + mIsRunning + " -> true"); 173 mIsRunning = true; 174 175 // Create the LinkProperties for the clat interface by fetching the 176 // IPv4 address for the interface and adding an IPv4 default route, 177 // then stack the LinkProperties on top of the link it's running on. 178 // Although the clat interface is a point-to-point tunnel, we don't 179 // point the route directly at the interface because some apps don't 180 // understand routes without gateways (see, e.g., http://b/9597256 181 // http://b/9597516). Instead, set the next hop of the route to the 182 // clat IPv4 address itself (for those apps, it doesn't matter what 183 // the IP of the gateway is, only that there is one). 184 try { 185 InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); 186 LinkAddress clatAddress = config.getLinkAddress(); 187 mLP.clear(); 188 mLP.setInterfaceName(iface); 189 RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0), 190 clatAddress.getAddress(), iface); 191 mLP.addRoute(ipv4Default); 192 mLP.addLinkAddress(clatAddress); 193 mBaseLP.addStackedLink(mLP); 194 Slog.i(TAG, "Adding stacked link. tracker LP: " + mBaseLP); 195 updateConnectivityService(); 196 } catch(RemoteException e) { 197 Slog.e(TAG, "Error getting link properties: " + e); 198 } 199 } 200 } 201 202 @Override 203 public void interfaceRemoved(String iface) { 204 if (iface == CLAT_INTERFACE_NAME) { 205 if (mIsRunning) { 206 NetworkUtils.resetConnections( 207 CLAT_INTERFACE_NAME, 208 NetworkUtils.RESET_IPV4_ADDRESSES); 209 mBaseLP.removeStackedLink(mLP); 210 updateConnectivityService(); 211 } 212 Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + 213 " removed, mIsRunning = " + mIsRunning + " -> false"); 214 mIsRunning = false; 215 mLP.clear(); 216 Slog.i(TAG, "mLP = " + mLP); 217 } 218 } 219}; 220