• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.ethernet;
18 
19 import static android.net.EthernetManager.ETHERNET_STATE_DISABLED;
20 import static android.net.EthernetManager.ETHERNET_STATE_ENABLED;
21 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
22 import static android.net.NetworkCapabilities.TRANSPORT_LOWPAN;
23 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
24 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
25 import static android.net.TestNetworkManager.TEST_TAP_PREFIX;
26 
27 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
28 import static com.android.net.module.util.netlink.NetlinkConstants.IFF_UP;
29 
30 import android.annotation.NonNull;
31 import android.annotation.Nullable;
32 import android.content.Context;
33 import android.net.EthernetManager;
34 import android.net.IEthernetServiceListener;
35 import android.net.INetd;
36 import android.net.ITetheredInterfaceCallback;
37 import android.net.InterfaceConfigurationParcel;
38 import android.net.IpConfiguration;
39 import android.net.IpConfiguration.IpAssignment;
40 import android.net.IpConfiguration.ProxySettings;
41 import android.net.LinkAddress;
42 import android.net.NetworkCapabilities;
43 import android.net.StaticIpConfiguration;
44 import android.os.ConditionVariable;
45 import android.os.Handler;
46 import android.os.RemoteCallbackList;
47 import android.os.RemoteException;
48 import android.system.OsConstants;
49 import android.text.TextUtils;
50 import android.util.ArrayMap;
51 import android.util.Log;
52 
53 import com.android.internal.annotations.VisibleForTesting;
54 import com.android.internal.util.IndentingPrintWriter;
55 import com.android.modules.utils.build.SdkLevel;
56 import com.android.net.module.util.HandlerUtils;
57 import com.android.net.module.util.NetdUtils;
58 import com.android.net.module.util.SharedLog;
59 import com.android.net.module.util.ip.NetlinkMonitor;
60 import com.android.net.module.util.netlink.NetlinkConstants;
61 import com.android.net.module.util.netlink.NetlinkMessage;
62 import com.android.net.module.util.netlink.NetlinkUtils;
63 import com.android.net.module.util.netlink.RtNetlinkLinkMessage;
64 import com.android.net.module.util.netlink.StructIfinfoMsg;
65 import com.android.server.connectivity.ConnectivityResources;
66 
67 import java.io.FileDescriptor;
68 import java.net.InetAddress;
69 import java.net.NetworkInterface;
70 import java.net.SocketException;
71 import java.util.ArrayList;
72 import java.util.Enumeration;
73 import java.util.Iterator;
74 import java.util.List;
75 import java.util.Objects;
76 import java.util.concurrent.ConcurrentHashMap;
77 
78 /**
79  * Tracks Ethernet interfaces and manages interface configurations.
80  *
81  * <p>Interfaces may have different {@link android.net.NetworkCapabilities}. This mapping is defined
82  * in {@code config_ethernet_interfaces}. Notably, some interfaces could be marked as restricted by
83  * not specifying {@link android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED} flag.
84  * Interfaces could have associated {@link android.net.IpConfiguration}.
85  * Ethernet Interfaces may be present at boot time or appear after boot (e.g., for Ethernet adapters
86  * connected over USB). This class supports multiple interfaces. When an interface appears on the
87  * system (or is present at boot time) this class will start tracking it and bring it up. Only
88  * interfaces whose names match the {@code config_ethernet_iface_regex} regular expression are
89  * tracked.
90  *
91  * <p>All public or package private methods must be thread-safe unless stated otherwise.
92  */
93 @VisibleForTesting(visibility = PACKAGE)
94 public class EthernetTracker {
95     private static final int INTERFACE_MODE_CLIENT = 1;
96     private static final int INTERFACE_MODE_SERVER = 2;
97 
98     private static final String TAG = EthernetTracker.class.getSimpleName();
99     private static final boolean DBG = EthernetNetworkFactory.DBG;
100 
101     private static final String TEST_IFACE_REGEXP = TEST_TAP_PREFIX + "\\d+";
102 
103     // TODO: consider using SharedLog consistently across ethernet service.
104     private static final SharedLog sLog = new SharedLog(TAG);
105 
106     @VisibleForTesting
107     public static final NetworkCapabilities DEFAULT_CAPABILITIES = new NetworkCapabilities.Builder()
108                         .addTransportType(TRANSPORT_ETHERNET)
109                         .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
110                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
111                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
112                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
113                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
114                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
115                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
116                         // TODO: do not hardcode link bandwidth.
117                         .setLinkUpstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
118                         .setLinkDownstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
119                         .build();
120 
121 
122     /**
123      * Interface names we track. This is a product-dependent regular expression.
124      * Use isValidEthernetInterface to check if a interface name is a valid ethernet interface (this
125      * includes test interfaces if setIncludeTestInterfaces is set to true).
126      */
127     private final String mIfaceMatch;
128 
129     /**
130      * Track test interfaces if true, don't track otherwise.
131      * Volatile is needed as getEthernetInterfaceList() does not run on the handler thread.
132      */
133     private volatile boolean mIncludeTestInterfaces = false;
134 
135     /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */
136     private final ConcurrentHashMap<String, NetworkCapabilities> mNetworkCapabilities =
137             new ConcurrentHashMap<>();
138     private final ConcurrentHashMap<String, IpConfiguration> mIpConfigurations =
139             new ConcurrentHashMap<>();
140 
141     private final Context mContext;
142     private final INetd mNetd;
143     private final Handler mHandler;
144     private final EthernetNetworkFactory mFactory;
145     private final EthernetConfigStore mConfigStore;
146     private final NetlinkMonitor mNetlinkMonitor;
147     private final Dependencies mDeps;
148 
149     private final RemoteCallbackList<IEthernetServiceListener> mListeners =
150             new RemoteCallbackList<>();
151     private final TetheredInterfaceRequestList mTetheredInterfaceRequests =
152             new TetheredInterfaceRequestList();
153 
154     // The first interface discovered is set as the mTetheringInterface. It is the interface that is
155     // returned when a tethered interface is requested; until then, it remains in client mode. Its
156     // current mode is reflected in mTetheringInterfaceMode.
157     private String mTetheringInterface;
158     // If the tethering interface is in server mode, it is not tracked by factory. The HW address
159     // must be maintained by the EthernetTracker. Its current mode is reflected in
160     // mTetheringInterfaceMode.
161     private String mTetheringInterfaceHwAddr;
162     private int mTetheringInterfaceMode = INTERFACE_MODE_CLIENT;
163     // Tracks whether clients were notified that the tethered interface is available
164     private boolean mTetheredInterfaceWasAvailable = false;
165     // Tracks the current state of ethernet as configured by EthernetManager#setEthernetEnabled.
166     private boolean mIsEthernetEnabled = true;
167 
168     private class TetheredInterfaceRequestList extends
169             RemoteCallbackList<ITetheredInterfaceCallback> {
170         @Override
onCallbackDied(ITetheredInterfaceCallback cb, Object cookie)171         public void onCallbackDied(ITetheredInterfaceCallback cb, Object cookie) {
172             mHandler.post(EthernetTracker.this::maybeUntetherInterface);
173         }
174     }
175 
176     public static class Dependencies {
getInterfaceRegexFromResource(Context context)177         public String getInterfaceRegexFromResource(Context context) {
178             final ConnectivityResources resources = new ConnectivityResources(context);
179             return resources.get().getString(
180                     com.android.connectivity.resources.R.string.config_ethernet_iface_regex);
181         }
182 
getInterfaceConfigFromResource(Context context)183         public String[] getInterfaceConfigFromResource(Context context) {
184             final ConnectivityResources resources = new ConnectivityResources(context);
185             return resources.get().getStringArray(
186                     com.android.connectivity.resources.R.array.config_ethernet_interfaces);
187         }
188 
isAtLeastB()189         public boolean isAtLeastB() {
190             return SdkLevel.isAtLeastB();
191         }
192     }
193 
194     private class EthernetNetlinkMonitor extends NetlinkMonitor {
EthernetNetlinkMonitor(Handler handler)195         EthernetNetlinkMonitor(Handler handler) {
196             super(handler, sLog, EthernetNetlinkMonitor.class.getSimpleName(),
197                     OsConstants.NETLINK_ROUTE, NetlinkConstants.RTMGRP_LINK);
198         }
199 
onNewLink(String ifname, boolean linkUp)200         private void onNewLink(String ifname, boolean linkUp) {
201             if (!mFactory.hasInterface(ifname) && !ifname.equals(mTetheringInterface)) {
202                 Log.i(TAG, "onInterfaceAdded, iface: " + ifname);
203                 maybeTrackInterface(ifname);
204             }
205             Log.i(TAG, "interfaceLinkStateChanged, iface: " + ifname + ", up: " + linkUp);
206             updateInterfaceState(ifname, linkUp);
207         }
208 
onDelLink(String ifname)209         private void onDelLink(String ifname) {
210             Log.i(TAG, "onInterfaceRemoved, iface: " + ifname);
211             stopTrackingInterface(ifname);
212         }
213 
processRtNetlinkLinkMessage(RtNetlinkLinkMessage msg)214         private void processRtNetlinkLinkMessage(RtNetlinkLinkMessage msg) {
215             final StructIfinfoMsg ifinfomsg = msg.getIfinfoHeader();
216             // check if the message is valid
217             if (ifinfomsg.family != OsConstants.AF_UNSPEC) return;
218 
219             // ignore messages for the loopback interface
220             if ((ifinfomsg.flags & OsConstants.IFF_LOOPBACK) != 0) return;
221 
222             // check if the received message applies to an ethernet interface.
223             final String ifname = msg.getInterfaceName();
224             if (!isValidEthernetInterface(ifname)) return;
225 
226             switch (msg.getHeader().nlmsg_type) {
227                 case NetlinkConstants.RTM_NEWLINK:
228                     final boolean linkUp = (ifinfomsg.flags & NetlinkConstants.IFF_LOWER_UP) != 0;
229                     onNewLink(ifname, linkUp);
230                     break;
231 
232                 case NetlinkConstants.RTM_DELLINK:
233                     onDelLink(ifname);
234                     break;
235 
236                 default:
237                     Log.e(TAG, "Unknown rtnetlink link msg type: " + msg);
238                     break;
239             }
240         }
241 
242         // Note: processNetlinkMessage is called on the handler thread.
243         @Override
processNetlinkMessage(NetlinkMessage nlMsg, long whenMs)244         protected void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) {
245             if (nlMsg instanceof RtNetlinkLinkMessage) {
246                 processRtNetlinkLinkMessage((RtNetlinkLinkMessage) nlMsg);
247             } else {
248                 Log.e(TAG, "Unknown netlink message: " + nlMsg);
249             }
250         }
251     }
252 
253 
EthernetTracker(@onNull final Context context, @NonNull final Handler handler, @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd)254     EthernetTracker(@NonNull final Context context, @NonNull final Handler handler,
255             @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd) {
256         this(context, handler, factory, netd, new Dependencies());
257     }
258 
259     @VisibleForTesting
EthernetTracker(@onNull final Context context, @NonNull final Handler handler, @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd, @NonNull final Dependencies deps)260     EthernetTracker(@NonNull final Context context, @NonNull final Handler handler,
261             @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd,
262             @NonNull final Dependencies deps) {
263         mContext = context;
264         mHandler = handler;
265         mFactory = factory;
266         mNetd = netd;
267         mDeps = deps;
268 
269         // Interface match regex.
270         String ifaceMatchRegex = mDeps.getInterfaceRegexFromResource(mContext);
271         // "*" is a magic string to indicate "pick the default".
272         if (ifaceMatchRegex.equals("*")) {
273             if (SdkLevel.isAtLeastV()) {
274                 // On V+, include both usb%d and eth%d interfaces.
275                 ifaceMatchRegex = "(usb|eth)\\d+";
276             } else {
277                 // On T and U, include only eth%d interfaces.
278                 ifaceMatchRegex = "eth\\d+";
279             }
280         }
281         mIfaceMatch = ifaceMatchRegex;
282 
283         // Read default Ethernet interface configuration from resources
284         final String[] interfaceConfigs = mDeps.getInterfaceConfigFromResource(context);
285         for (String strConfig : interfaceConfigs) {
286             parseEthernetConfig(strConfig);
287         }
288 
289         mConfigStore = new EthernetConfigStore();
290         mNetlinkMonitor = new EthernetNetlinkMonitor(mHandler);
291     }
292 
start()293     void start() {
294         mFactory.register();
295         mConfigStore.read();
296 
297         final ArrayMap<String, IpConfiguration> configs = mConfigStore.getIpConfigurations();
298         for (int i = 0; i < configs.size(); i++) {
299             mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i));
300         }
301 
302         mHandler.post(() -> {
303             mNetlinkMonitor.start();
304             trackAvailableInterfaces();
305         });
306     }
307 
updateIpConfiguration(String iface, IpConfiguration ipConfiguration)308     void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) {
309         if (DBG) {
310             Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration);
311         }
312         writeIpConfiguration(iface, ipConfiguration);
313         mHandler.post(() -> {
314             mFactory.updateInterface(iface, ipConfiguration, null);
315             broadcastInterfaceStateChange(iface);
316         });
317     }
318 
writeIpConfiguration(@onNull final String iface, @NonNull final IpConfiguration ipConfig)319     private void writeIpConfiguration(@NonNull final String iface,
320             @NonNull final IpConfiguration ipConfig) {
321         mConfigStore.write(iface, ipConfig);
322         mIpConfigurations.put(iface, ipConfig);
323     }
324 
getIpConfigurationForCallback(String iface, int state)325     private IpConfiguration getIpConfigurationForCallback(String iface, int state) {
326         return (state == EthernetManager.STATE_ABSENT) ? null : getOrCreateIpConfiguration(iface);
327     }
328 
ensureRunningOnEthernetServiceThread()329     private void ensureRunningOnEthernetServiceThread() {
330         HandlerUtils.ensureRunningOnHandlerThread(mHandler);
331     }
332 
333     /**
334      * Broadcast the link state or IpConfiguration change of existing Ethernet interfaces to all
335      * listeners.
336      */
broadcastInterfaceStateChange(@onNull String iface)337     protected void broadcastInterfaceStateChange(@NonNull String iface) {
338         ensureRunningOnEthernetServiceThread();
339         final int state = getInterfaceState(iface);
340         final int role = getInterfaceRole(iface);
341         final IpConfiguration config = getIpConfigurationForCallback(iface, state);
342         final boolean isRestricted = isRestrictedInterface(iface);
343         final int n = mListeners.beginBroadcast();
344         for (int i = 0; i < n; i++) {
345             try {
346                 if (isRestricted) {
347                     final ListenerInfo info = (ListenerInfo) mListeners.getBroadcastCookie(i);
348                     if (!info.canUseRestrictedNetworks) continue;
349                 }
350                 mListeners.getBroadcastItem(i).onInterfaceStateChanged(iface, state, role, config);
351             } catch (RemoteException e) {
352                 // Do nothing here.
353             }
354         }
355         mListeners.finishBroadcast();
356     }
357 
358     /**
359      * Unicast the interface state or IpConfiguration change of existing Ethernet interfaces to a
360      * specific listener.
361      */
unicastInterfaceStateChange(@onNull IEthernetServiceListener listener, @NonNull String iface)362     protected void unicastInterfaceStateChange(@NonNull IEthernetServiceListener listener,
363             @NonNull String iface) {
364         ensureRunningOnEthernetServiceThread();
365         final int state = getInterfaceState(iface);
366         final int role = getInterfaceRole(iface);
367         final IpConfiguration config = getIpConfigurationForCallback(iface, state);
368         try {
369             listener.onInterfaceStateChanged(iface, state, role, config);
370         } catch (RemoteException e) {
371             // Do nothing here.
372         }
373     }
374 
375     @VisibleForTesting(visibility = PACKAGE)
updateConfiguration(@onNull final String iface, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, @Nullable final EthernetCallback cb)376     protected void updateConfiguration(@NonNull final String iface,
377             @Nullable final IpConfiguration ipConfig,
378             @Nullable final NetworkCapabilities capabilities,
379             @Nullable final EthernetCallback cb) {
380         if (DBG) {
381             Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities
382                     + ", ipConfig: " + ipConfig);
383         }
384 
385         // TODO: do the right thing if the interface was in server mode: either fail this operation,
386         // or take the interface out of server mode.
387         final IpConfiguration localIpConfig = ipConfig == null
388                 ? null : new IpConfiguration(ipConfig);
389         if (ipConfig != null) {
390             writeIpConfiguration(iface, localIpConfig);
391         }
392 
393         if (null != capabilities) {
394             mNetworkCapabilities.put(iface, capabilities);
395         }
396         mHandler.post(() -> {
397             mFactory.updateInterface(iface, localIpConfig, capabilities);
398 
399             // only broadcast state change when the ip configuration is updated.
400             if (ipConfig != null) {
401                 broadcastInterfaceStateChange(iface);
402             }
403             // Always return success. Even if the interface does not currently exist, the
404             // IpConfiguration and NetworkCapabilities were saved and will be applied if an
405             // interface with the given name is ever added.
406             cb.onResult(iface);
407         });
408     }
409 
410     /** Configure the administrative state of ethernet interface by toggling IFF_UP. */
setInterfaceEnabled(String iface, boolean enabled, EthernetCallback cb)411     public void setInterfaceEnabled(String iface, boolean enabled, EthernetCallback cb) {
412         mHandler.post(() -> setInterfaceAdministrativeState(iface, enabled, cb));
413     }
414 
getIpConfiguration(String iface)415     IpConfiguration getIpConfiguration(String iface) {
416         return mIpConfigurations.get(iface);
417     }
418 
419     @VisibleForTesting(visibility = PACKAGE)
isTrackingInterface(String iface)420     protected boolean isTrackingInterface(String iface) {
421         return mFactory.hasInterface(iface);
422     }
423 
getAllInterfaces()424     private List<String> getAllInterfaces() {
425         final ArrayList<String> interfaces = new ArrayList<>(
426                 List.of(mFactory.getAvailableInterfaces(/* includeRestricted */ true)));
427 
428         if (mTetheringInterfaceMode == INTERFACE_MODE_SERVER && mTetheringInterface != null) {
429             interfaces.add(mTetheringInterface);
430         }
431         return interfaces;
432     }
433 
getClientModeInterfaces(boolean includeRestricted)434     String[] getClientModeInterfaces(boolean includeRestricted) {
435         return mFactory.getAvailableInterfaces(includeRestricted);
436     }
437 
getEthernetInterfaceList()438     List<String> getEthernetInterfaceList() {
439         final List<String> interfaceList = new ArrayList<String>();
440         final Enumeration<NetworkInterface> ifaces;
441         try {
442             ifaces = NetworkInterface.getNetworkInterfaces();
443         } catch (SocketException e) {
444             Log.e(TAG, "Failed to get ethernet interfaces: ", e);
445             return interfaceList;
446         }
447 
448         // There is a possible race with setIncludeTestInterfaces() which can affect
449         // isValidEthernetInterface (it returns true for test interfaces if setIncludeTestInterfaces
450         // is set to true).
451         // setIncludeTestInterfaces() is only used in tests, and since getEthernetInterfaceList()
452         // does not run on the handler thread, the behavior around setIncludeTestInterfaces() is
453         // indeterminate either way. This can easily be circumvented by waiting on a callback from
454         // a test interface after calling setIncludeTestInterfaces() before calling this function.
455         // In production code, this has no effect.
456         while (ifaces.hasMoreElements()) {
457             NetworkInterface iface = ifaces.nextElement();
458             if (isValidEthernetInterface(iface.getName())) interfaceList.add(iface.getName());
459         }
460         return interfaceList;
461     }
462 
463     /**
464      * Returns true if given interface was configured as restricted (doesn't have
465      * NET_CAPABILITY_NOT_RESTRICTED) capability. Otherwise, returns false.
466      */
isRestrictedInterface(String iface)467     boolean isRestrictedInterface(String iface) {
468         final NetworkCapabilities nc = mNetworkCapabilities.get(iface);
469         return nc != null && !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
470     }
471 
addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks)472     void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) {
473         mHandler.post(() -> {
474             if (!mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks))) {
475                 // Remote process has already died
476                 return;
477             }
478             for (String iface : getClientModeInterfaces(canUseRestrictedNetworks)) {
479                 unicastInterfaceStateChange(listener, iface);
480             }
481             if (mTetheringInterface != null && mTetheringInterfaceMode == INTERFACE_MODE_SERVER) {
482                 unicastInterfaceStateChange(listener, mTetheringInterface);
483             }
484 
485             unicastEthernetStateChange(listener, mIsEthernetEnabled);
486         });
487     }
488 
removeListener(IEthernetServiceListener listener)489     void removeListener(IEthernetServiceListener listener) {
490         mHandler.post(() -> mListeners.unregister(listener));
491     }
492 
setIncludeTestInterfaces(boolean include)493     public void setIncludeTestInterfaces(boolean include) {
494         mHandler.post(() -> {
495             mIncludeTestInterfaces = include;
496             if (include) {
497                 trackAvailableInterfaces();
498             } else {
499                 removeTestData();
500                 // remove all test interfaces
501                 for (String iface : getAllInterfaces()) {
502                     if (isValidEthernetInterface(iface)) continue;
503                     stopTrackingInterface(iface);
504                 }
505             }
506         });
507     }
508 
removeTestData()509     private void removeTestData() {
510         removeTestIpData();
511         removeTestCapabilityData();
512     }
513 
removeTestIpData()514     private void removeTestIpData() {
515         final Iterator<String> iterator = mIpConfigurations.keySet().iterator();
516         while (iterator.hasNext()) {
517             final String iface = iterator.next();
518             if (iface.matches(TEST_IFACE_REGEXP)) {
519                 mConfigStore.write(iface, null);
520                 iterator.remove();
521             }
522         }
523     }
524 
removeTestCapabilityData()525     private void removeTestCapabilityData() {
526         mNetworkCapabilities.keySet().removeIf(iface -> iface.matches(TEST_IFACE_REGEXP));
527     }
528 
requestTetheredInterface(ITetheredInterfaceCallback callback)529     public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
530         mHandler.post(() -> {
531             if (!mTetheredInterfaceRequests.register(callback)) {
532                 // Remote process has already died
533                 return;
534             }
535             if (mTetheringInterfaceMode == INTERFACE_MODE_SERVER) {
536                 if (mTetheredInterfaceWasAvailable) {
537                     notifyTetheredInterfaceAvailable(callback, mTetheringInterface);
538                 }
539                 return;
540             }
541 
542             setTetheringInterfaceMode(INTERFACE_MODE_SERVER);
543         });
544     }
545 
releaseTetheredInterface(ITetheredInterfaceCallback callback)546     public void releaseTetheredInterface(ITetheredInterfaceCallback callback) {
547         mHandler.post(() -> {
548             mTetheredInterfaceRequests.unregister(callback);
549             maybeUntetherInterface();
550         });
551     }
552 
notifyTetheredInterfaceAvailable(ITetheredInterfaceCallback cb, String iface)553     private void notifyTetheredInterfaceAvailable(ITetheredInterfaceCallback cb, String iface) {
554         try {
555             cb.onAvailable(iface);
556         } catch (RemoteException e) {
557             Log.e(TAG, "Error sending tethered interface available callback", e);
558         }
559     }
560 
notifyTetheredInterfaceUnavailable(ITetheredInterfaceCallback cb)561     private void notifyTetheredInterfaceUnavailable(ITetheredInterfaceCallback cb) {
562         try {
563             cb.onUnavailable();
564         } catch (RemoteException e) {
565             Log.e(TAG, "Error sending tethered interface available callback", e);
566         }
567     }
568 
maybeUntetherInterface()569     private void maybeUntetherInterface() {
570         if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return;
571         if (mTetheringInterfaceMode == INTERFACE_MODE_CLIENT) return;
572         setTetheringInterfaceMode(INTERFACE_MODE_CLIENT);
573     }
574 
setTetheringInterfaceMode(int mode)575     private void setTetheringInterfaceMode(int mode) {
576         Log.d(TAG, "Setting tethering interface mode to " + mode);
577         mTetheringInterfaceMode = mode;
578         if (mTetheringInterface != null) {
579             removeInterface(mTetheringInterface);
580             addInterface(mTetheringInterface);
581             // when this broadcast is sent, any calls to notifyTetheredInterfaceAvailable or
582             // notifyTetheredInterfaceUnavailable have already happened
583             broadcastInterfaceStateChange(mTetheringInterface);
584         }
585     }
586 
getInterfaceState(final String iface)587     private int getInterfaceState(final String iface) {
588         if (mFactory.hasInterface(iface)) {
589             return mFactory.getInterfaceState(iface);
590         }
591         if (getInterfaceMode(iface) == INTERFACE_MODE_SERVER) {
592             // server mode interfaces are not tracked by the factory.
593             // TODO(b/234743836): interface state for server mode interfaces is not tracked
594             // properly; just return link up.
595             return EthernetManager.STATE_LINK_UP;
596         }
597         return EthernetManager.STATE_ABSENT;
598     }
599 
getInterfaceRole(final String iface)600     private int getInterfaceRole(final String iface) {
601         if (mFactory.hasInterface(iface)) {
602             // only client mode interfaces are tracked by the factory.
603             return EthernetManager.ROLE_CLIENT;
604         }
605         if (getInterfaceMode(iface) == INTERFACE_MODE_SERVER) {
606             return EthernetManager.ROLE_SERVER;
607         }
608         return EthernetManager.ROLE_NONE;
609     }
610 
getInterfaceMode(final String iface)611     private int getInterfaceMode(final String iface) {
612         if (iface.equals(mTetheringInterface)) {
613             return mTetheringInterfaceMode;
614         }
615         return INTERFACE_MODE_CLIENT;
616     }
617 
removeInterface(String iface)618     private void removeInterface(String iface) {
619         mFactory.removeInterface(iface);
620         maybeUpdateServerModeInterfaceState(iface, false);
621     }
622 
stopTrackingInterface(String iface)623     private void stopTrackingInterface(String iface) {
624         removeInterface(iface);
625         if (iface.equals(mTetheringInterface)) {
626             mTetheringInterface = null;
627             mTetheringInterfaceHwAddr = null;
628         }
629         broadcastInterfaceStateChange(iface);
630     }
631 
addInterface(String iface)632     private void addInterface(String iface) {
633         InterfaceConfigurationParcel config = null;
634         // Bring up the interface so we get link status indications.
635         try {
636             // Read the flags before attempting to bring up the interface. If the interface is
637             // already running an UP event is created after adding the interface.
638             config = NetdUtils.getInterfaceConfigParcel(mNetd, iface);
639             // Only bring the interface up when ethernet is enabled, otherwise set interface down.
640             setInterfaceUpState(iface, mIsEthernetEnabled);
641         } catch (IllegalStateException e) {
642             // Either the system is crashing or the interface has disappeared. Just ignore the
643             // error; we haven't modified any state because we only do that if our calls succeed.
644             Log.e(TAG, "Error upping interface " + iface, e);
645         }
646 
647         if (config == null) {
648             Log.e(TAG, "Null interface config parcelable for " + iface + ". Bailing out.");
649             return;
650         }
651 
652         final String hwAddress = config.hwAddr;
653 
654         if (getInterfaceMode(iface) == INTERFACE_MODE_SERVER) {
655             maybeUpdateServerModeInterfaceState(iface, true);
656             mTetheringInterfaceHwAddr = hwAddress;
657             return;
658         }
659 
660         NetworkCapabilities nc = mNetworkCapabilities.get(iface);
661         if (nc == null) {
662             // Try to resolve using mac address
663             nc = mNetworkCapabilities.get(hwAddress);
664             if (nc == null) {
665                 final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP);
666                 nc = createDefaultNetworkCapabilities(isTestIface);
667             }
668         }
669 
670         IpConfiguration ipConfiguration = getOrCreateIpConfiguration(iface);
671         Log.d(TAG, "Tracking interface in client mode: " + iface);
672         mFactory.addInterface(iface, hwAddress, ipConfiguration, nc);
673 
674         // Note: if the interface already has link (e.g., if we crashed and got
675         // restarted while it was running), we need to fake a link up notification so we
676         // start configuring it.
677         if (NetdUtils.hasFlag(config, INetd.IF_FLAG_RUNNING)) {
678             // no need to send an interface state change as this is not a true "state change". The
679             // callers (maybeTrackInterface() and setTetheringInterfaceMode()) already broadcast the
680             // state change.
681             mFactory.updateInterfaceLinkState(iface, true);
682         }
683     }
684 
setInterfaceAdministrativeState(String iface, boolean up, EthernetCallback cb)685     private void setInterfaceAdministrativeState(String iface, boolean up, EthernetCallback cb) {
686         if (!mIsEthernetEnabled) {
687             cb.onError("Cannot enable/disable interface when ethernet is disabled");
688             return;
689         }
690         if (getInterfaceState(iface) == EthernetManager.STATE_ABSENT) {
691             cb.onError("Failed to enable/disable absent interface: " + iface);
692             return;
693         }
694         if (getInterfaceRole(iface) == EthernetManager.ROLE_SERVER) {
695             // TODO: support setEthernetState for server mode interfaces.
696             cb.onError("Failed to enable/disable interface in server mode: " + iface);
697             return;
698         }
699 
700         setInterfaceUpState(iface, up);
701         cb.onResult(iface);
702     }
703 
updateInterfaceState(String iface, boolean up)704     private void updateInterfaceState(String iface, boolean up) {
705         final int mode = getInterfaceMode(iface);
706         if (mode == INTERFACE_MODE_SERVER) {
707             // TODO: support tracking link state for interfaces in server mode.
708             return;
709         }
710 
711         // If updateInterfaceLinkState returns false, the interface is already in the correct state.
712         if (mFactory.updateInterfaceLinkState(iface, up)) {
713             broadcastInterfaceStateChange(iface);
714         }
715     }
716 
maybeUpdateServerModeInterfaceState(String iface, boolean available)717     private void maybeUpdateServerModeInterfaceState(String iface, boolean available) {
718         if (available == mTetheredInterfaceWasAvailable || !iface.equals(mTetheringInterface)) {
719             return;
720         }
721 
722         Log.d(TAG, (available ? "Tracking" : "No longer tracking")
723                 + " interface in server mode: " + iface);
724 
725         final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast();
726         for (int i = 0; i < pendingCbs; i++) {
727             ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i);
728             if (available) {
729                 notifyTetheredInterfaceAvailable(item, iface);
730             } else {
731                 notifyTetheredInterfaceUnavailable(item);
732             }
733         }
734         mTetheredInterfaceRequests.finishBroadcast();
735         mTetheredInterfaceWasAvailable = available;
736     }
737 
maybeTrackInterface(String iface)738     private void maybeTrackInterface(String iface) {
739         // If we don't already track this interface, and if this interface matches
740         // our regex, start tracking it.
741         if (mFactory.hasInterface(iface) || iface.equals(mTetheringInterface)) {
742             if (DBG) Log.w(TAG, "Ignoring already-tracked interface " + iface);
743             return;
744         }
745         if (DBG) Log.i(TAG, "maybeTrackInterface: " + iface);
746 
747         // Do not use an interface for tethering if it has configured NetworkCapabilities.
748         if (mTetheringInterface == null && !mNetworkCapabilities.containsKey(iface)) {
749             mTetheringInterface = iface;
750         }
751 
752         addInterface(iface);
753 
754         broadcastInterfaceStateChange(iface);
755     }
756 
trackAvailableInterfaces()757     private void trackAvailableInterfaces() {
758         final List<String> ifaces = getEthernetInterfaceList();
759         for (String iface : ifaces) {
760             maybeTrackInterface(iface);
761         }
762     }
763 
764     private static class ListenerInfo {
765 
766         boolean canUseRestrictedNetworks = false;
767 
ListenerInfo(boolean canUseRestrictedNetworks)768         ListenerInfo(boolean canUseRestrictedNetworks) {
769             this.canUseRestrictedNetworks = canUseRestrictedNetworks;
770         }
771     }
772 
773     /**
774      * Parses an Ethernet interface configuration
775      *
776      * @param configString represents an Ethernet configuration in the following format: {@code
777      * <interface name|mac address>;[Network Capabilities];[IP config];[Override Transport]}
778      */
parseEthernetConfig(String configString)779     private void parseEthernetConfig(String configString) {
780         final EthernetConfigParser config =
781                 new EthernetConfigParser(configString, mDeps.isAtLeastB());
782         mNetworkCapabilities.put(config.mIface, config.mCaps);
783 
784         if (null != config.mIpConfig) {
785             IpConfiguration ipConfig = parseStaticIpConfiguration(config.mIpConfig);
786             mIpConfigurations.put(config.mIface, ipConfig);
787         }
788     }
789 
createDefaultNetworkCapabilities(boolean isTestIface)790     private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) {
791         final NetworkCapabilities.Builder builder =
792                 new NetworkCapabilities.Builder(DEFAULT_CAPABILITIES);
793         if (isTestIface) {
794             builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST);
795             // TODO: do not remove INTERNET capability for test networks.
796             builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
797         }
798 
799         return builder.build();
800     }
801 
802     /**
803      * Parses static IP configuration.
804      *
805      * @param staticIpConfig represents static IP configuration in the following format: {@code
806      * ip=<ip-address/mask> gateway=<ip-address> dns=<comma-sep-ip-addresses>
807      *     domains=<comma-sep-domains>}
808      */
809     @VisibleForTesting
parseStaticIpConfiguration(String staticIpConfig)810     static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) {
811         final StaticIpConfiguration.Builder staticIpConfigBuilder =
812                 new StaticIpConfiguration.Builder();
813 
814         for (String keyValueAsString : staticIpConfig.trim().split(" ")) {
815             if (TextUtils.isEmpty(keyValueAsString)) continue;
816 
817             String[] pair = keyValueAsString.split("=");
818             if (pair.length != 2) {
819                 throw new IllegalArgumentException("Unexpected token: " + keyValueAsString
820                         + " in " + staticIpConfig);
821             }
822 
823             String key = pair[0];
824             String value = pair[1];
825 
826             switch (key) {
827                 case "ip":
828                     staticIpConfigBuilder.setIpAddress(new LinkAddress(value));
829                     break;
830                 case "domains":
831                     staticIpConfigBuilder.setDomains(value);
832                     break;
833                 case "gateway":
834                     staticIpConfigBuilder.setGateway(InetAddress.parseNumericAddress(value));
835                     break;
836                 case "dns": {
837                     ArrayList<InetAddress> dnsAddresses = new ArrayList<>();
838                     for (String address: value.split(",")) {
839                         dnsAddresses.add(InetAddress.parseNumericAddress(address));
840                     }
841                     staticIpConfigBuilder.setDnsServers(dnsAddresses);
842                     break;
843                 }
844                 default : {
845                     throw new IllegalArgumentException("Unexpected key: " + key
846                             + " in " + staticIpConfig);
847                 }
848             }
849         }
850         return createIpConfiguration(staticIpConfigBuilder.build());
851     }
852 
createIpConfiguration( @onNull final StaticIpConfiguration staticIpConfig)853     private static IpConfiguration createIpConfiguration(
854             @NonNull final StaticIpConfiguration staticIpConfig) {
855         return new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build();
856     }
857 
getOrCreateIpConfiguration(String iface)858     private IpConfiguration getOrCreateIpConfiguration(String iface) {
859         IpConfiguration ret = mIpConfigurations.get(iface);
860         if (ret != null) return ret;
861         ret = new IpConfiguration();
862         ret.setIpAssignment(IpAssignment.DHCP);
863         ret.setProxySettings(ProxySettings.NONE);
864         return ret;
865     }
866 
isValidEthernetInterface(String iface)867     private boolean isValidEthernetInterface(String iface) {
868         return iface.matches(mIfaceMatch) || isValidTestInterface(iface);
869     }
870 
871     /**
872      * Validate if a given interface is valid for testing.
873      *
874      * @param iface the name of the interface to validate.
875      * @return {@code true} if test interfaces are enabled and the given {@code iface} has a test
876      * interface prefix, {@code false} otherwise.
877      */
isValidTestInterface(@onNull final String iface)878     public boolean isValidTestInterface(@NonNull final String iface) {
879         return mIncludeTestInterfaces && iface.matches(TEST_IFACE_REGEXP);
880     }
881 
postAndWaitForRunnable(Runnable r)882     private void postAndWaitForRunnable(Runnable r) {
883         final ConditionVariable cv = new ConditionVariable();
884         if (mHandler.post(() -> {
885             r.run();
886             cv.open();
887         })) {
888             cv.block(2000L);
889         }
890     }
891 
892     @VisibleForTesting(visibility = PACKAGE)
setEthernetEnabled(boolean enabled)893     protected void setEthernetEnabled(boolean enabled) {
894         mHandler.post(() -> {
895             if (mIsEthernetEnabled == enabled) return;
896 
897             mIsEthernetEnabled = enabled;
898             for (String iface : getAllInterfaces()) {
899                 setInterfaceUpState(iface, enabled);
900             }
901             broadcastEthernetStateChange(mIsEthernetEnabled);
902         });
903     }
904 
isEthernetEnabledAsInt(boolean state)905     private int isEthernetEnabledAsInt(boolean state) {
906         return state ? ETHERNET_STATE_ENABLED : ETHERNET_STATE_DISABLED;
907     }
908 
unicastEthernetStateChange(@onNull IEthernetServiceListener listener, boolean enabled)909     private void unicastEthernetStateChange(@NonNull IEthernetServiceListener listener,
910             boolean enabled) {
911         ensureRunningOnEthernetServiceThread();
912         try {
913             listener.onEthernetStateChanged(isEthernetEnabledAsInt(enabled));
914         } catch (RemoteException e) {
915             // Do nothing here.
916         }
917     }
918 
broadcastEthernetStateChange(boolean enabled)919     private void broadcastEthernetStateChange(boolean enabled) {
920         ensureRunningOnEthernetServiceThread();
921         final int n = mListeners.beginBroadcast();
922         for (int i = 0; i < n; i++) {
923             try {
924                 mListeners.getBroadcastItem(i)
925                             .onEthernetStateChanged(isEthernetEnabledAsInt(enabled));
926             } catch (RemoteException e) {
927                 // Do nothing here.
928             }
929         }
930         mListeners.finishBroadcast();
931     }
932 
setInterfaceUpState(@onNull String interfaceName, boolean up)933     private void setInterfaceUpState(@NonNull String interfaceName, boolean up) {
934         if (!NetlinkUtils.setInterfaceFlags(interfaceName, up ? IFF_UP : ~IFF_UP)) {
935             Log.e(TAG, "Failed to set interface " + interfaceName + (up ? " up" : " down"));
936         }
937     }
938 
dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args)939     void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
940         postAndWaitForRunnable(() -> {
941             pw.println(getClass().getSimpleName());
942             pw.println("Ethernet State: "
943                     + (mIsEthernetEnabled ? "enabled" : "disabled"));
944             pw.println("Ethernet interface name filter: " + mIfaceMatch);
945             pw.println("Interface used for tethering: " + mTetheringInterface);
946             pw.println("Tethering interface mode: " + mTetheringInterfaceMode);
947             pw.println("Tethered interface requests: "
948                     + mTetheredInterfaceRequests.getRegisteredCallbackCount());
949             pw.println("Listeners: " + mListeners.getRegisteredCallbackCount());
950             pw.println("IP Configurations:");
951             pw.increaseIndent();
952             for (String iface : mIpConfigurations.keySet()) {
953                 pw.println(iface + ": " + mIpConfigurations.get(iface));
954             }
955             pw.decreaseIndent();
956             pw.println();
957 
958             pw.println("Network Capabilities:");
959             pw.increaseIndent();
960             for (String iface : mNetworkCapabilities.keySet()) {
961                 pw.println(iface + ": " + mNetworkCapabilities.get(iface));
962             }
963             pw.decreaseIndent();
964             pw.println();
965 
966             mFactory.dump(fd, pw, args);
967         });
968     }
969 
970     @VisibleForTesting
971     static class EthernetConfigParser {
972         final String mIface;
973         final NetworkCapabilities mCaps;
974         final String mIpConfig;
975 
parseCapabilities(@ullable String capabilitiesString, boolean isAtLeastB)976         private static NetworkCapabilities parseCapabilities(@Nullable String capabilitiesString,
977                 boolean isAtLeastB) {
978             final NetworkCapabilities.Builder builder =
979                     NetworkCapabilities.Builder.withoutDefaultCapabilities();
980             builder.setLinkUpstreamBandwidthKbps(100 * 1000 /* 100 Mbps */);
981             builder.setLinkDownstreamBandwidthKbps(100 * 1000 /* 100 Mbps */);
982             // Ethernet networks have no way to update the following capabilities, so they always
983             // have them.
984             builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
985             builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
986             builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
987 
988             if (capabilitiesString == null) {
989                 return builder.build();
990             }
991 
992             if (isAtLeastB && capabilitiesString.equals("*")) {
993                 // On Android B+, a "*" string defaults to the same set of default
994                 // capabilities assigned to unconfigured interfaces.
995                 // Note that the transport type is populated later with the result of
996                 // parseTransportType().
997                 return new NetworkCapabilities.Builder(DEFAULT_CAPABILITIES)
998                         .removeTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
999                         .build();
1000             }
1001 
1002             for (String strNetworkCapability : capabilitiesString.split(",")) {
1003                 if (TextUtils.isEmpty(strNetworkCapability)) {
1004                     continue;
1005                 }
1006                 final Integer capability;
1007                 try {
1008                     builder.addCapability(Integer.valueOf(strNetworkCapability));
1009                 } catch (NumberFormatException e) {
1010                     Log.e(TAG, "Failed to parse capability: " + strNetworkCapability, e);
1011                     continue;
1012                 }
1013             }
1014             return builder.build();
1015         }
1016 
parseTransportType(@ullable String transportString)1017         private static int parseTransportType(@Nullable String transportString) {
1018             if (TextUtils.isEmpty(transportString)) {
1019                 return TRANSPORT_ETHERNET;
1020             }
1021 
1022             final int parsedTransport;
1023             try {
1024                 parsedTransport = Integer.valueOf(transportString);
1025             } catch (NumberFormatException e) {
1026                 Log.e(TAG, "Failed to parse transport type", e);
1027                 return TRANSPORT_ETHERNET;
1028             }
1029 
1030             if (!NetworkCapabilities.isValidTransport(parsedTransport)) {
1031                 return TRANSPORT_ETHERNET;
1032             }
1033 
1034             switch (parsedTransport) {
1035                 case TRANSPORT_VPN:
1036                 case TRANSPORT_WIFI_AWARE:
1037                 case TRANSPORT_LOWPAN:
1038                     Log.e(TAG, "Unsupported transport type '" + parsedTransport + "'");
1039                     return TRANSPORT_ETHERNET;
1040                 default:
1041                     return parsedTransport;
1042             }
1043         }
1044 
EthernetConfigParser(String configString, boolean isAtLeastB)1045         EthernetConfigParser(String configString, boolean isAtLeastB) {
1046             Objects.requireNonNull(configString, "EthernetConfigParser requires non-null config");
1047             final String[] tokens = configString.split(";", /* limit of tokens */ 4);
1048             mIface = tokens[0];
1049 
1050             final NetworkCapabilities nc =
1051                     parseCapabilities(tokens.length > 1 ? tokens[1] : null, isAtLeastB);
1052             final int transportType = parseTransportType(tokens.length > 3 ? tokens[3] : null);
1053             nc.addTransportType(transportType);
1054             mCaps = nc;
1055 
1056             mIpConfig = tokens.length > 2 && !TextUtils.isEmpty(tokens[2]) ? tokens[2] : null;
1057         }
1058     }
1059 }
1060