• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Nat464Xlat(Context context, INetworkManagementService nmService, IConnectivityManager connService, Handler handler)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      */
requiresClat(int netType, NetworkStateTracker tracker)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 
isRunningClat(LinkProperties lp)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      */
startClat(NetworkStateTracker tracker)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      */
stopClat()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 
isStarted()135     public boolean isStarted() {
136         return mIsStarted;
137     }
138 
isRunning()139     public boolean isRunning() {
140         return mIsRunning;
141     }
142 
143     @Override
interfaceAdded(String iface)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
interfaceRemoved(String iface)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