blob: 3884ab057bfa45150ac2f7f2b8dfe1aa4497634b [file] [log] [blame]
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +09001/*
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;
Paul Jensen3b759822014-05-13 11:44:01 -040028import android.net.NetworkAgent;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090029import android.net.NetworkUtils;
30import android.net.RouteInfo;
31import android.os.Handler;
32import android.os.Message;
Paul Jensen3b759822014-05-13 11:44:01 -040033import android.os.Messenger;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090034import 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;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090049 // 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;
Paul Jensen3b759822014-05-13 11:44:01 -040055 // 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;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090061
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
79 /**
Paul Jensen3b759822014-05-13 11:44:01 -040080 * Determines whether a network requires clat.
81 * @param network the NetworkAgentInfo corresponding to the network.
82 * @return true if the network requires clat, false otherwise.
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090083 */
Paul Jensen3b759822014-05-13 11:44:01 -040084 public boolean requiresClat(NetworkAgentInfo network) {
85 int netType = network.networkInfo.getType();
86 LinkProperties lp = network.linkProperties;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090087 // Only support clat on mobile for now.
88 Slog.d(TAG, "requiresClat: netType=" + netType + ", hasIPv4Address=" +
89 lp.hasIPv4Address());
90 return netType == TYPE_MOBILE && !lp.hasIPv4Address();
91 }
92
Lorenzo Colittid2ef1e52013-03-28 14:13:43 +090093 public static boolean isRunningClat(LinkProperties lp) {
94 return lp != null && lp.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME);
95 }
96
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090097 /**
98 * Starts the clat daemon.
99 * @param lp The link properties of the interface to start clatd on.
100 */
Paul Jensen3b759822014-05-13 11:44:01 -0400101 public void startClat(NetworkAgentInfo network) {
102 if (mNetworkMessenger != null && mNetworkMessenger != network.messenger) {
103 Slog.e(TAG, "startClat: too many networks requesting clat");
104 return;
105 }
106 mNetworkMessenger = network.messenger;
107 LinkProperties lp = network.linkProperties;
108 mBaseLP = new LinkProperties(lp);
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900109 if (mIsStarted) {
110 Slog.e(TAG, "startClat: already started");
111 return;
112 }
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900113 String iface = lp.getInterfaceName();
114 Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp);
115 try {
116 mNMService.startClatd(iface);
117 } catch(RemoteException e) {
118 Slog.e(TAG, "Error starting clat daemon: " + e);
119 }
120 mIsStarted = true;
121 }
122
123 /**
124 * Stops the clat daemon.
125 */
126 public void stopClat() {
127 if (mIsStarted) {
128 Slog.i(TAG, "Stopping clatd");
129 try {
130 mNMService.stopClatd();
131 } catch(RemoteException e) {
132 Slog.e(TAG, "Error stopping clat daemon: " + e);
133 }
134 mIsStarted = false;
135 mIsRunning = false;
Paul Jensen3b759822014-05-13 11:44:01 -0400136 mNetworkMessenger = null;
137 mBaseLP = null;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900138 mLP.clear();
139 } else {
140 Slog.e(TAG, "stopClat: already stopped");
141 }
142 }
143
144 public boolean isStarted() {
145 return mIsStarted;
146 }
147
148 public boolean isRunning() {
149 return mIsRunning;
150 }
151
Paul Jensen3b759822014-05-13 11:44:01 -0400152 private void updateConnectivityService() {
153 Message msg = mHandler.obtainMessage(
154 NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, mBaseLP);
155 msg.replyTo = mNetworkMessenger;
156 Slog.i(TAG, "sending message to ConnectivityService: " + msg);
157 msg.sendToTarget();
158 }
159
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900160 @Override
161 public void interfaceAdded(String iface) {
162 if (iface.equals(CLAT_INTERFACE_NAME)) {
163 Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME +
164 " added, mIsRunning = " + mIsRunning + " -> true");
165 mIsRunning = true;
166
Lorenzo Colitti861c3fc2013-06-17 11:10:27 -0700167 // Create the LinkProperties for the clat interface by fetching the
168 // IPv4 address for the interface and adding an IPv4 default route,
169 // then stack the LinkProperties on top of the link it's running on.
170 // Although the clat interface is a point-to-point tunnel, we don't
171 // point the route directly at the interface because some apps don't
172 // understand routes without gateways (see, e.g., http://b/9597256
173 // http://b/9597516). Instead, set the next hop of the route to the
174 // clat IPv4 address itself (for those apps, it doesn't matter what
175 // the IP of the gateway is, only that there is one).
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900176 try {
177 InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
Lorenzo Colitti861c3fc2013-06-17 11:10:27 -0700178 LinkAddress clatAddress = config.getLinkAddress();
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900179 mLP.clear();
180 mLP.setInterfaceName(iface);
Lorenzo Colitti861c3fc2013-06-17 11:10:27 -0700181 RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0),
182 clatAddress.getAddress(), iface);
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900183 mLP.addRoute(ipv4Default);
Lorenzo Colitti861c3fc2013-06-17 11:10:27 -0700184 mLP.addLinkAddress(clatAddress);
Paul Jensen3b759822014-05-13 11:44:01 -0400185 mBaseLP.addStackedLink(mLP);
186 Slog.i(TAG, "Adding stacked link. tracker LP: " + mBaseLP);
187 updateConnectivityService();
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900188 } catch(RemoteException e) {
189 Slog.e(TAG, "Error getting link properties: " + e);
190 }
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900191 }
192 }
193
194 @Override
195 public void interfaceRemoved(String iface) {
196 if (iface == CLAT_INTERFACE_NAME) {
197 if (mIsRunning) {
198 NetworkUtils.resetConnections(
199 CLAT_INTERFACE_NAME,
200 NetworkUtils.RESET_IPV4_ADDRESSES);
201 }
202 Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME +
203 " removed, mIsRunning = " + mIsRunning + " -> false");
204 mIsRunning = false;
Paul Jensen3b759822014-05-13 11:44:01 -0400205 mBaseLP.removeStackedLink(mLP);
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900206 mLP.clear();
Paul Jensen3b759822014-05-13 11:44:01 -0400207 updateConnectivityService();
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +0900208 Slog.i(TAG, "mLP = " + mLP);
209 }
210 }
211};