blob: 2884eafd07f6a0d7af66576dc9096ed8b15d759d [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;
28import android.net.NetworkStateTracker;
29import android.net.NetworkUtils;
30import android.net.RouteInfo;
31import android.os.Handler;
32import android.os.Message;
33import android.os.INetworkManagementService;
34import android.os.RemoteException;
35import android.util.Slog;
36
37import com.android.server.net.BaseNetworkObserver;
38
39/**
40 * @hide
41 *
42 * Class to manage a 464xlat CLAT daemon.
43 */
44public 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 /**
91 * Starts the clat daemon.
92 * @param lp The link properties of the interface to start clatd on.
93 */
94 public void startClat(NetworkStateTracker tracker) {
95 if (mIsStarted) {
96 Slog.e(TAG, "startClat: already started");
97 return;
98 }
99 mTracker = tracker;
100 LinkProperties lp = mTracker.getLinkProperties();
101 String iface = lp.getInterfaceName();
102 Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp);
103 try {
104 mNMService.startClatd(iface);
105 } catch(RemoteException e) {
106 Slog.e(TAG, "Error starting clat daemon: " + e);
107 }
108 mIsStarted = true;
109 }
110
111 /**
112 * Stops the clat daemon.
113 */
114 public void stopClat() {
115 if (mIsStarted) {
116 Slog.i(TAG, "Stopping clatd");
117 try {
118 mNMService.stopClatd();
119 } catch(RemoteException e) {
120 Slog.e(TAG, "Error stopping clat daemon: " + e);
121 }
122 mIsStarted = false;
123 mIsRunning = false;
124 mTracker = null;
125 mLP.clear();
126 } else {
127 Slog.e(TAG, "stopClat: already stopped");
128 }
129 }
130
131 public boolean isStarted() {
132 return mIsStarted;
133 }
134
135 public boolean isRunning() {
136 return mIsRunning;
137 }
138
139 @Override
140 public void interfaceAdded(String iface) {
141 if (iface.equals(CLAT_INTERFACE_NAME)) {
142 Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME +
143 " added, mIsRunning = " + mIsRunning + " -> true");
144 mIsRunning = true;
145
146 // Get the network configuration of the clat interface, store it
147 // in our link properties, and stack it on top of the interface
148 // it's running on.
149 try {
150 InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
151 mLP.clear();
152 mLP.setInterfaceName(iface);
153 RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0), null,
154 iface);
155 mLP.addRoute(ipv4Default);
156 mLP.addLinkAddress(config.getLinkAddress());
157 mTracker.addStackedLink(mLP);
158 Slog.i(TAG, "Adding stacked link. tracker LP: " +
159 mTracker.getLinkProperties());
160 } catch(RemoteException e) {
161 Slog.e(TAG, "Error getting link properties: " + e);
162 }
163
164 // Inform ConnectivityService that things have changed.
165 Message msg = mHandler.obtainMessage(
166 NetworkStateTracker.EVENT_CONFIGURATION_CHANGED,
167 mTracker.getNetworkInfo());
168 Slog.i(TAG, "sending message to ConnectivityService: " + msg);
169 msg.sendToTarget();
170 }
171 }
172
173 @Override
174 public void interfaceRemoved(String iface) {
175 if (iface == CLAT_INTERFACE_NAME) {
176 if (mIsRunning) {
177 NetworkUtils.resetConnections(
178 CLAT_INTERFACE_NAME,
179 NetworkUtils.RESET_IPV4_ADDRESSES);
180 }
181 Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME +
182 " removed, mIsRunning = " + mIsRunning + " -> false");
183 mIsRunning = false;
184 mTracker.removeStackedLink(mLP);
185 mLP.clear();
186 Slog.i(TAG, "mLP = " + mLP);
187 }
188 }
189};