Loading packages/Tethering/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ java_defaults { srcs: [ "src/**/*.java", ":framework-tethering-shared-srcs", ":net-module-utils-srcs", ":tethering-module-utils-srcs", ":services-tethering-shared-srcs", ], static_libs: [ Loading packages/Tethering/src/android/net/ip/IpServer.java +86 −102 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.net.ConnectivityManager; import android.net.INetd; import android.net.INetworkStackStatusCallback; import android.net.INetworkStatsService; import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; Loading @@ -38,11 +37,11 @@ import android.net.dhcp.DhcpServingParamsParcel; import android.net.dhcp.DhcpServingParamsParcelExt; import android.net.dhcp.IDhcpServer; import android.net.ip.RouterAdvertisementDaemon.RaParams; import android.net.shared.NetdUtils; import android.net.shared.RouteUtils; import android.net.util.InterfaceParams; import android.net.util.InterfaceSet; import android.net.util.NetdService; import android.net.util.SharedLog; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.RemoteException; Loading Loading @@ -144,10 +143,6 @@ public class IpServer extends StateMachine { return InterfaceParams.getByName(ifName); } public INetd getNetdService() { return NetdService.getInstance(); } /** Create a DhcpServer instance to be used by IpServer. */ public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params, DhcpServerCallbacks cb); Loading Loading @@ -180,7 +175,6 @@ public class IpServer extends StateMachine { private final State mUnavailableState; private final SharedLog mLog; private final INetworkManagementService mNMService; private final INetd mNetd; private final INetworkStatsService mStatsService; private final Callback mCallback; Loading Loading @@ -210,15 +204,15 @@ public class IpServer extends StateMachine { private int mDhcpServerStartIndex = 0; private IDhcpServer mDhcpServer; private RaParams mLastRaParams; private LinkAddress mIpv4Address; public IpServer( String ifaceName, Looper looper, int interfaceType, SharedLog log, INetworkManagementService nMService, INetworkStatsService statsService, Callback callback, boolean usingLegacyDhcp, Dependencies deps) { INetd netd, INetworkStatsService statsService, Callback callback, boolean usingLegacyDhcp, Dependencies deps) { super(ifaceName, looper); mLog = log.forSubComponent(ifaceName); mNMService = nMService; mNetd = deps.getNetdService(); mNetd = netd; mStatsService = statsService; mCallback = callback; mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog); Loading Loading @@ -347,7 +341,7 @@ public class IpServer extends StateMachine { } }); } catch (RemoteException e) { e.rethrowFromSystemServer(); throw new IllegalStateException(e); } }); } Loading Loading @@ -395,7 +389,8 @@ public class IpServer extends StateMachine { }); mDhcpServer = null; } catch (RemoteException e) { e.rethrowFromSystemServer(); mLog.e("Error stopping DHCP", e); // Not much more we can do here } } } Loading @@ -414,85 +409,69 @@ public class IpServer extends StateMachine { // NOTE: All of configureIPv4() will be refactored out of existence // into calls to InterfaceController, shared with startIPv4(). mInterfaceCtrl.clearIPv4Address(); mIpv4Address = null; } // TODO: Refactor this in terms of calls to InterfaceController. private boolean configureIPv4(boolean enabled) { if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); // TODO: Replace this hard-coded information with dynamically selected // config passed down to us by a higher layer IP-coordinating element. String ipAsString = null; final Inet4Address srvAddr; int prefixLen = 0; try { if (mInterfaceType == ConnectivityManager.TETHERING_USB) { ipAsString = USB_NEAR_IFACE_ADDR; srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR); prefixLen = USB_PREFIX_LENGTH; } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { ipAsString = getRandomWifiIPv4Address(); srvAddr = (Inet4Address) parseNumericAddress(getRandomWifiIPv4Address()); prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH; } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) { ipAsString = WIFI_P2P_IFACE_ADDR; srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR); prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH; } else { // BT configures the interface elsewhere: only start DHCP. final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR); // TODO: make all tethering types behave the same way, and delete the bluetooth // code that calls into NetworkManagementService directly. srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR); mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); } final LinkAddress linkAddr; try { final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName); if (ifcg == null) { mLog.e("Received null interface config"); mIpv4Address = new LinkAddress(srvAddr, prefixLen); } catch (IllegalArgumentException e) { mLog.e("Error selecting ipv4 address", e); if (!enabled) stopDhcp(); return false; } InetAddress addr = parseNumericAddress(ipAsString); linkAddr = new LinkAddress(addr, prefixLen); ifcg.setLinkAddress(linkAddr); final Boolean setIfaceUp; if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { // The WiFi stack has ownership of the interface up/down state. // It is unclear whether the Bluetooth or USB stacks will manage their own // state. ifcg.ignoreInterfaceUpDownStatus(); } else { if (enabled) { ifcg.setInterfaceUp(); setIfaceUp = null; } else { ifcg.setInterfaceDown(); setIfaceUp = enabled; } } ifcg.clearFlag("running"); // TODO: this may throw if the interface is already gone. Do proper handling and // simplify the DHCP server start/stop. mNMService.setInterfaceConfig(mIfaceName, ifcg); if (!configureDhcp(enabled, (Inet4Address) addr, prefixLen)) { if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) { mLog.e("Error configuring interface"); if (!enabled) stopDhcp(); return false; } } catch (Exception e) { mLog.e("Error configuring interface " + e); if (!enabled) { try { // Calling stopDhcp several times is fine stopDhcp(); } catch (Exception dhcpError) { mLog.e("Error stopping DHCP", dhcpError); } } if (!configureDhcp(enabled, srvAddr, prefixLen)) { return false; } // Directly-connected route. final IpPrefix ipv4Prefix = new IpPrefix(linkAddr.getAddress(), linkAddr.getPrefixLength()); final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(), mIpv4Address.getPrefixLength()); final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST); if (enabled) { mLinkProperties.addLinkAddress(linkAddr); mLinkProperties.addLinkAddress(mIpv4Address); mLinkProperties.addRoute(route); } else { mLinkProperties.removeLinkAddress(linkAddr); mLinkProperties.removeLinkAddress(mIpv4Address); mLinkProperties.removeRoute(route); } return true; Loading Loading @@ -584,15 +563,13 @@ public class IpServer extends StateMachine { if (!deprecatedPrefixes.isEmpty()) { final ArrayList<RouteInfo> toBeRemoved = getLocalRoutesFor(mIfaceName, deprecatedPrefixes); try { final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved); // Remove routes from local network. final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork( mNetd, toBeRemoved); if (removalFailures > 0) { mLog.e(String.format("Failed to remove %d IPv6 routes from local table.", removalFailures)); } } catch (RemoteException e) { mLog.e("Failed to remove IPv6 routes from local table: " + e); } for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); } Loading @@ -608,14 +585,19 @@ public class IpServer extends StateMachine { final ArrayList<RouteInfo> toBeAdded = getLocalRoutesFor(mIfaceName, addedPrefixes); try { // It's safe to call addInterfaceToLocalNetwork() even if // the interface is already in the local_network. Note also // that adding routes that already exist does not cause an // error (EEXIST is silently ignored). mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded); } catch (Exception e) { // It's safe to call networkAddInterface() even if // the interface is already in the local_network. mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName); try { // Add routes from local network. Note that adding routes that // already exist does not cause an error (EEXIST is silently ignored). RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded); } catch (IllegalStateException e) { mLog.e("Failed to add IPv6 routes to local table: " + e); } } catch (ServiceSpecificException | RemoteException e) { mLog.e("Failed to add " + mIfaceName + " to local table: ", e); } for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); } Loading Loading @@ -762,8 +744,10 @@ public class IpServer extends StateMachine { } try { mNMService.tetherInterface(mIfaceName); } catch (Exception e) { final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(), mIpv4Address.getPrefixLength()); NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Error Tethering: " + e); mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR; return; Loading @@ -784,8 +768,8 @@ public class IpServer extends StateMachine { stopIPv6(); try { mNMService.untetherInterface(mIfaceName); } catch (Exception e) { NetdUtils.untetherInterface(mNetd, mIfaceName); } catch (RemoteException | ServiceSpecificException e) { mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; mLog.e("Failed to untether interface: " + e); } Loading Loading @@ -901,17 +885,17 @@ public class IpServer extends StateMachine { // About to tear down NAT; gather remaining statistics. mStatsService.forceUpdate(); } catch (Exception e) { if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString()); mLog.e("Exception in forceUpdate: " + e.toString()); } try { mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface); } catch (Exception e) { if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString()); mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString()); } try { mNMService.disableNat(mIfaceName, upstreamIface); } catch (Exception e) { if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString()); mNetd.tetherRemoveForward(mIfaceName, upstreamIface); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Exception in disableNat: " + e.toString()); } } Loading Loading @@ -947,10 +931,10 @@ public class IpServer extends StateMachine { for (String ifname : added) { try { mNMService.enableNat(mIfaceName, ifname); mNMService.startInterfaceForwarding(mIfaceName, ifname); } catch (Exception e) { mLog.e("Exception enabling NAT: " + e); mNetd.tetherAddForward(mIfaceName, ifname); mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Exception enabling NAT: " + e.toString()); cleanupUpstream(); mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR; transitionTo(mInitialState); Loading packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +39 −37 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ import android.net.NetworkUtils; import android.net.TetherStatesParcel; import android.net.TetheringConfigurationParcel; import android.net.ip.IpServer; import android.net.shared.NetdUtils; import android.net.util.BaseNetdUnsolicitedEventListener; import android.net.util.InterfaceSet; import android.net.util.PrefixUtils; Loading @@ -87,12 +88,12 @@ import android.net.wifi.p2p.WifiP2pManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceSpecificException; import android.os.UserHandle; import android.os.UserManager; import android.telephony.PhoneStateListener; Loading @@ -102,6 +103,9 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; Loading Loading @@ -139,6 +143,8 @@ public class Tethering { }; private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(sMessageClasses); // Keep in sync with NETID_UNSET in system/netd/include/netid_client.h private static final int NETID_UNSET = 0; private static class TetherState { public final IpServer ipServer; Loading Loading @@ -172,8 +178,6 @@ public class Tethering { private final Context mContext; private final ArrayMap<String, TetherState> mTetherStates; private final BroadcastReceiver mStateReceiver; // Stopship: replace mNMService before production. private final INetworkManagementService mNMService; private final INetworkStatsService mStatsService; private final INetworkPolicyManager mPolicyManager; private final Looper mLooper; Loading Loading @@ -210,7 +214,6 @@ public class Tethering { mLog.mark("Tethering.constructed"); mDeps = deps; mContext = mDeps.getContext(); mNMService = mDeps.getINetworkManagementService(); mStatsService = mDeps.getINetworkStatsService(); mPolicyManager = mDeps.getINetworkPolicyManager(); mNetd = mDeps.getINetd(mContext); Loading @@ -225,10 +228,9 @@ public class Tethering { mHandler = mTetherMasterSM.getHandler(); mOffloadController = new OffloadController(mHandler, mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(), mNMService, mLog); mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog, mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(), mDeps.getINetworkManagementService(), mLog); mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK); mForwardedDownstreams = new HashSet<>(); Loading Loading @@ -421,7 +423,6 @@ public class Tethering { } } void interfaceRemoved(String iface) { if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); synchronized (mPublicSync) { Loading Loading @@ -1022,8 +1023,8 @@ public class Tethering { String[] ifaces = null; try { ifaces = mNMService.listInterfaces(); } catch (Exception e) { ifaces = mNetd.interfaceGetList(); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Error listing Interfaces", e); return; } Loading Loading @@ -1282,25 +1283,25 @@ public class Tethering { protected boolean turnOnMasterTetherSettings() { final TetheringConfiguration cfg = mConfig; try { mNMService.setIpForwardingEnabled(true); } catch (Exception e) { mNetd.ipfwdEnableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { mLog.e(e); transitionTo(mSetIpForwardingEnabledErrorState); return false; } // TODO: Randomize DHCPv4 ranges, especially in hotspot mode. // Legacy DHCP server is disabled if passed an empty ranges array final String[] dhcpRanges = cfg.enableLegacyDhcpServer ? cfg.legacyDhcpRanges : new String[0]; ? cfg.legacyDhcpRanges : new String[0]; try { // TODO: Find a more accurate method name (startDHCPv4()?). mNMService.startTethering(dhcpRanges); } catch (Exception e) { NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); } catch (RemoteException | ServiceSpecificException e) { try { mNMService.stopTethering(); mNMService.startTethering(dhcpRanges); } catch (Exception ee) { // Stop and retry. mNetd.tetherStop(); NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); } catch (RemoteException | ServiceSpecificException ee) { mLog.e(ee); transitionTo(mStartTetheringErrorState); return false; Loading @@ -1312,15 +1313,15 @@ public class Tethering { protected boolean turnOffMasterTetherSettings() { try { mNMService.stopTethering(); } catch (Exception e) { mNetd.tetherStop(); } catch (RemoteException | ServiceSpecificException e) { mLog.e(e); transitionTo(mStopTetheringErrorState); return false; } try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { mLog.e(e); transitionTo(mSetIpForwardingDisabledErrorState); return false; Loading Loading @@ -1390,12 +1391,13 @@ public class Tethering { // TODO: remove this invocation of NetworkUtils.makeStrings(). dnsServers = NetworkUtils.makeStrings(dnses); } final int netId = (network != null) ? network.netId : NETID_UNSET; try { mNMService.setDnsForwarders(network, dnsServers); mNetd.tetherDnsSet(netId, dnsServers); mLog.log(String.format( "SET DNS forwarders: network=%s dnsServers=%s", network, Arrays.toString(dnsServers))); } catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) { // TODO: Investigate how this can fail and what exactly // happens if/when such failures occur. mLog.e("setting DNS forwarders failed, " + e); Loading Loading @@ -1698,8 +1700,8 @@ public class Tethering { Log.e(TAG, "Error in startTethering"); notify(IpServer.CMD_START_TETHERING_ERROR); try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { } mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { } } } Loading @@ -1709,8 +1711,8 @@ public class Tethering { Log.e(TAG, "Error in stopTethering"); notify(IpServer.CMD_STOP_TETHERING_ERROR); try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { } mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { } } } Loading @@ -1720,11 +1722,11 @@ public class Tethering { Log.e(TAG, "Error in setDnsForwarders"); notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR); try { mNMService.stopTethering(); } catch (Exception e) { } mNetd.tetherStop(); } catch (RemoteException | ServiceSpecificException e) { } try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { } mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { } } } Loading Loading @@ -1884,7 +1886,7 @@ public class Tethering { } } void dump(FileDescriptor fd, PrintWriter writer, String[] args) { void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { // Binder.java closes the resource for us. @SuppressWarnings("resource") final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); Loading Loading @@ -2065,7 +2067,7 @@ public class Tethering { mLog.log("adding TetheringInterfaceStateMachine for: " + iface); final TetherState tetherState = new TetherState( new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService, new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mStatsService, makeControlCallback(), mConfig.enableLegacyDhcpServer, mDeps.getIpServerDependencies())); mTetherStates.put(iface, tetherState); Loading Loading
packages/Tethering/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ java_defaults { srcs: [ "src/**/*.java", ":framework-tethering-shared-srcs", ":net-module-utils-srcs", ":tethering-module-utils-srcs", ":services-tethering-shared-srcs", ], static_libs: [ Loading
packages/Tethering/src/android/net/ip/IpServer.java +86 −102 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.net.ConnectivityManager; import android.net.INetd; import android.net.INetworkStackStatusCallback; import android.net.INetworkStatsService; import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; Loading @@ -38,11 +37,11 @@ import android.net.dhcp.DhcpServingParamsParcel; import android.net.dhcp.DhcpServingParamsParcelExt; import android.net.dhcp.IDhcpServer; import android.net.ip.RouterAdvertisementDaemon.RaParams; import android.net.shared.NetdUtils; import android.net.shared.RouteUtils; import android.net.util.InterfaceParams; import android.net.util.InterfaceSet; import android.net.util.NetdService; import android.net.util.SharedLog; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.RemoteException; Loading Loading @@ -144,10 +143,6 @@ public class IpServer extends StateMachine { return InterfaceParams.getByName(ifName); } public INetd getNetdService() { return NetdService.getInstance(); } /** Create a DhcpServer instance to be used by IpServer. */ public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params, DhcpServerCallbacks cb); Loading Loading @@ -180,7 +175,6 @@ public class IpServer extends StateMachine { private final State mUnavailableState; private final SharedLog mLog; private final INetworkManagementService mNMService; private final INetd mNetd; private final INetworkStatsService mStatsService; private final Callback mCallback; Loading Loading @@ -210,15 +204,15 @@ public class IpServer extends StateMachine { private int mDhcpServerStartIndex = 0; private IDhcpServer mDhcpServer; private RaParams mLastRaParams; private LinkAddress mIpv4Address; public IpServer( String ifaceName, Looper looper, int interfaceType, SharedLog log, INetworkManagementService nMService, INetworkStatsService statsService, Callback callback, boolean usingLegacyDhcp, Dependencies deps) { INetd netd, INetworkStatsService statsService, Callback callback, boolean usingLegacyDhcp, Dependencies deps) { super(ifaceName, looper); mLog = log.forSubComponent(ifaceName); mNMService = nMService; mNetd = deps.getNetdService(); mNetd = netd; mStatsService = statsService; mCallback = callback; mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog); Loading Loading @@ -347,7 +341,7 @@ public class IpServer extends StateMachine { } }); } catch (RemoteException e) { e.rethrowFromSystemServer(); throw new IllegalStateException(e); } }); } Loading Loading @@ -395,7 +389,8 @@ public class IpServer extends StateMachine { }); mDhcpServer = null; } catch (RemoteException e) { e.rethrowFromSystemServer(); mLog.e("Error stopping DHCP", e); // Not much more we can do here } } } Loading @@ -414,85 +409,69 @@ public class IpServer extends StateMachine { // NOTE: All of configureIPv4() will be refactored out of existence // into calls to InterfaceController, shared with startIPv4(). mInterfaceCtrl.clearIPv4Address(); mIpv4Address = null; } // TODO: Refactor this in terms of calls to InterfaceController. private boolean configureIPv4(boolean enabled) { if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); // TODO: Replace this hard-coded information with dynamically selected // config passed down to us by a higher layer IP-coordinating element. String ipAsString = null; final Inet4Address srvAddr; int prefixLen = 0; try { if (mInterfaceType == ConnectivityManager.TETHERING_USB) { ipAsString = USB_NEAR_IFACE_ADDR; srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR); prefixLen = USB_PREFIX_LENGTH; } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { ipAsString = getRandomWifiIPv4Address(); srvAddr = (Inet4Address) parseNumericAddress(getRandomWifiIPv4Address()); prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH; } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) { ipAsString = WIFI_P2P_IFACE_ADDR; srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR); prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH; } else { // BT configures the interface elsewhere: only start DHCP. final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR); // TODO: make all tethering types behave the same way, and delete the bluetooth // code that calls into NetworkManagementService directly. srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR); mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); } final LinkAddress linkAddr; try { final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName); if (ifcg == null) { mLog.e("Received null interface config"); mIpv4Address = new LinkAddress(srvAddr, prefixLen); } catch (IllegalArgumentException e) { mLog.e("Error selecting ipv4 address", e); if (!enabled) stopDhcp(); return false; } InetAddress addr = parseNumericAddress(ipAsString); linkAddr = new LinkAddress(addr, prefixLen); ifcg.setLinkAddress(linkAddr); final Boolean setIfaceUp; if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { // The WiFi stack has ownership of the interface up/down state. // It is unclear whether the Bluetooth or USB stacks will manage their own // state. ifcg.ignoreInterfaceUpDownStatus(); } else { if (enabled) { ifcg.setInterfaceUp(); setIfaceUp = null; } else { ifcg.setInterfaceDown(); setIfaceUp = enabled; } } ifcg.clearFlag("running"); // TODO: this may throw if the interface is already gone. Do proper handling and // simplify the DHCP server start/stop. mNMService.setInterfaceConfig(mIfaceName, ifcg); if (!configureDhcp(enabled, (Inet4Address) addr, prefixLen)) { if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) { mLog.e("Error configuring interface"); if (!enabled) stopDhcp(); return false; } } catch (Exception e) { mLog.e("Error configuring interface " + e); if (!enabled) { try { // Calling stopDhcp several times is fine stopDhcp(); } catch (Exception dhcpError) { mLog.e("Error stopping DHCP", dhcpError); } } if (!configureDhcp(enabled, srvAddr, prefixLen)) { return false; } // Directly-connected route. final IpPrefix ipv4Prefix = new IpPrefix(linkAddr.getAddress(), linkAddr.getPrefixLength()); final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(), mIpv4Address.getPrefixLength()); final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST); if (enabled) { mLinkProperties.addLinkAddress(linkAddr); mLinkProperties.addLinkAddress(mIpv4Address); mLinkProperties.addRoute(route); } else { mLinkProperties.removeLinkAddress(linkAddr); mLinkProperties.removeLinkAddress(mIpv4Address); mLinkProperties.removeRoute(route); } return true; Loading Loading @@ -584,15 +563,13 @@ public class IpServer extends StateMachine { if (!deprecatedPrefixes.isEmpty()) { final ArrayList<RouteInfo> toBeRemoved = getLocalRoutesFor(mIfaceName, deprecatedPrefixes); try { final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved); // Remove routes from local network. final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork( mNetd, toBeRemoved); if (removalFailures > 0) { mLog.e(String.format("Failed to remove %d IPv6 routes from local table.", removalFailures)); } } catch (RemoteException e) { mLog.e("Failed to remove IPv6 routes from local table: " + e); } for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); } Loading @@ -608,14 +585,19 @@ public class IpServer extends StateMachine { final ArrayList<RouteInfo> toBeAdded = getLocalRoutesFor(mIfaceName, addedPrefixes); try { // It's safe to call addInterfaceToLocalNetwork() even if // the interface is already in the local_network. Note also // that adding routes that already exist does not cause an // error (EEXIST is silently ignored). mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded); } catch (Exception e) { // It's safe to call networkAddInterface() even if // the interface is already in the local_network. mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName); try { // Add routes from local network. Note that adding routes that // already exist does not cause an error (EEXIST is silently ignored). RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded); } catch (IllegalStateException e) { mLog.e("Failed to add IPv6 routes to local table: " + e); } } catch (ServiceSpecificException | RemoteException e) { mLog.e("Failed to add " + mIfaceName + " to local table: ", e); } for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); } Loading Loading @@ -762,8 +744,10 @@ public class IpServer extends StateMachine { } try { mNMService.tetherInterface(mIfaceName); } catch (Exception e) { final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(), mIpv4Address.getPrefixLength()); NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Error Tethering: " + e); mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR; return; Loading @@ -784,8 +768,8 @@ public class IpServer extends StateMachine { stopIPv6(); try { mNMService.untetherInterface(mIfaceName); } catch (Exception e) { NetdUtils.untetherInterface(mNetd, mIfaceName); } catch (RemoteException | ServiceSpecificException e) { mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; mLog.e("Failed to untether interface: " + e); } Loading Loading @@ -901,17 +885,17 @@ public class IpServer extends StateMachine { // About to tear down NAT; gather remaining statistics. mStatsService.forceUpdate(); } catch (Exception e) { if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString()); mLog.e("Exception in forceUpdate: " + e.toString()); } try { mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface); } catch (Exception e) { if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString()); mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString()); } try { mNMService.disableNat(mIfaceName, upstreamIface); } catch (Exception e) { if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString()); mNetd.tetherRemoveForward(mIfaceName, upstreamIface); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Exception in disableNat: " + e.toString()); } } Loading Loading @@ -947,10 +931,10 @@ public class IpServer extends StateMachine { for (String ifname : added) { try { mNMService.enableNat(mIfaceName, ifname); mNMService.startInterfaceForwarding(mIfaceName, ifname); } catch (Exception e) { mLog.e("Exception enabling NAT: " + e); mNetd.tetherAddForward(mIfaceName, ifname); mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname); } catch (RemoteException | ServiceSpecificException e) { mLog.e("Exception enabling NAT: " + e.toString()); cleanupUpstream(); mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR; transitionTo(mInitialState); Loading
packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +39 −37 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ import android.net.NetworkUtils; import android.net.TetherStatesParcel; import android.net.TetheringConfigurationParcel; import android.net.ip.IpServer; import android.net.shared.NetdUtils; import android.net.util.BaseNetdUnsolicitedEventListener; import android.net.util.InterfaceSet; import android.net.util.PrefixUtils; Loading @@ -87,12 +88,12 @@ import android.net.wifi.p2p.WifiP2pManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceSpecificException; import android.os.UserHandle; import android.os.UserManager; import android.telephony.PhoneStateListener; Loading @@ -102,6 +103,9 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; Loading Loading @@ -139,6 +143,8 @@ public class Tethering { }; private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(sMessageClasses); // Keep in sync with NETID_UNSET in system/netd/include/netid_client.h private static final int NETID_UNSET = 0; private static class TetherState { public final IpServer ipServer; Loading Loading @@ -172,8 +178,6 @@ public class Tethering { private final Context mContext; private final ArrayMap<String, TetherState> mTetherStates; private final BroadcastReceiver mStateReceiver; // Stopship: replace mNMService before production. private final INetworkManagementService mNMService; private final INetworkStatsService mStatsService; private final INetworkPolicyManager mPolicyManager; private final Looper mLooper; Loading Loading @@ -210,7 +214,6 @@ public class Tethering { mLog.mark("Tethering.constructed"); mDeps = deps; mContext = mDeps.getContext(); mNMService = mDeps.getINetworkManagementService(); mStatsService = mDeps.getINetworkStatsService(); mPolicyManager = mDeps.getINetworkPolicyManager(); mNetd = mDeps.getINetd(mContext); Loading @@ -225,10 +228,9 @@ public class Tethering { mHandler = mTetherMasterSM.getHandler(); mOffloadController = new OffloadController(mHandler, mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(), mNMService, mLog); mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog, mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(), mDeps.getINetworkManagementService(), mLog); mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK); mForwardedDownstreams = new HashSet<>(); Loading Loading @@ -421,7 +423,6 @@ public class Tethering { } } void interfaceRemoved(String iface) { if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); synchronized (mPublicSync) { Loading Loading @@ -1022,8 +1023,8 @@ public class Tethering { String[] ifaces = null; try { ifaces = mNMService.listInterfaces(); } catch (Exception e) { ifaces = mNetd.interfaceGetList(); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Error listing Interfaces", e); return; } Loading Loading @@ -1282,25 +1283,25 @@ public class Tethering { protected boolean turnOnMasterTetherSettings() { final TetheringConfiguration cfg = mConfig; try { mNMService.setIpForwardingEnabled(true); } catch (Exception e) { mNetd.ipfwdEnableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { mLog.e(e); transitionTo(mSetIpForwardingEnabledErrorState); return false; } // TODO: Randomize DHCPv4 ranges, especially in hotspot mode. // Legacy DHCP server is disabled if passed an empty ranges array final String[] dhcpRanges = cfg.enableLegacyDhcpServer ? cfg.legacyDhcpRanges : new String[0]; ? cfg.legacyDhcpRanges : new String[0]; try { // TODO: Find a more accurate method name (startDHCPv4()?). mNMService.startTethering(dhcpRanges); } catch (Exception e) { NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); } catch (RemoteException | ServiceSpecificException e) { try { mNMService.stopTethering(); mNMService.startTethering(dhcpRanges); } catch (Exception ee) { // Stop and retry. mNetd.tetherStop(); NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); } catch (RemoteException | ServiceSpecificException ee) { mLog.e(ee); transitionTo(mStartTetheringErrorState); return false; Loading @@ -1312,15 +1313,15 @@ public class Tethering { protected boolean turnOffMasterTetherSettings() { try { mNMService.stopTethering(); } catch (Exception e) { mNetd.tetherStop(); } catch (RemoteException | ServiceSpecificException e) { mLog.e(e); transitionTo(mStopTetheringErrorState); return false; } try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { mLog.e(e); transitionTo(mSetIpForwardingDisabledErrorState); return false; Loading Loading @@ -1390,12 +1391,13 @@ public class Tethering { // TODO: remove this invocation of NetworkUtils.makeStrings(). dnsServers = NetworkUtils.makeStrings(dnses); } final int netId = (network != null) ? network.netId : NETID_UNSET; try { mNMService.setDnsForwarders(network, dnsServers); mNetd.tetherDnsSet(netId, dnsServers); mLog.log(String.format( "SET DNS forwarders: network=%s dnsServers=%s", network, Arrays.toString(dnsServers))); } catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) { // TODO: Investigate how this can fail and what exactly // happens if/when such failures occur. mLog.e("setting DNS forwarders failed, " + e); Loading Loading @@ -1698,8 +1700,8 @@ public class Tethering { Log.e(TAG, "Error in startTethering"); notify(IpServer.CMD_START_TETHERING_ERROR); try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { } mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { } } } Loading @@ -1709,8 +1711,8 @@ public class Tethering { Log.e(TAG, "Error in stopTethering"); notify(IpServer.CMD_STOP_TETHERING_ERROR); try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { } mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { } } } Loading @@ -1720,11 +1722,11 @@ public class Tethering { Log.e(TAG, "Error in setDnsForwarders"); notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR); try { mNMService.stopTethering(); } catch (Exception e) { } mNetd.tetherStop(); } catch (RemoteException | ServiceSpecificException e) { } try { mNMService.setIpForwardingEnabled(false); } catch (Exception e) { } mNetd.ipfwdDisableForwarding(TAG); } catch (RemoteException | ServiceSpecificException e) { } } } Loading Loading @@ -1884,7 +1886,7 @@ public class Tethering { } } void dump(FileDescriptor fd, PrintWriter writer, String[] args) { void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { // Binder.java closes the resource for us. @SuppressWarnings("resource") final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); Loading Loading @@ -2065,7 +2067,7 @@ public class Tethering { mLog.log("adding TetheringInterfaceStateMachine for: " + iface); final TetherState tetherState = new TetherState( new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService, new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mStatsService, makeControlCallback(), mConfig.enableLegacyDhcpServer, mDeps.getIpServerDependencies())); mTetherStates.put(iface, tetherState); Loading