From c72191f62a01abd289b9b89ea4af8da8800732d9 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Fri, 7 Feb 2025 15:18:26 -0800 Subject: [PATCH] Add createL2capNetwork helper Adds a function to create a tun interface configured for blocking i/o. Also adds a helper function to create an L2capNetwork which calls createTunInterface(). createL2capNetwork() requires the caller to pass a *connected* BluetoothSocket and will be used for both server and client networks. Note that this split isn't particularly logical (because this function does not get called yet), but was the easiest way to make the code more reviewable. Test: atest L2capNetworkProviderTest Change-Id: I61efbedbf56fe9b4ba6d0050eaa29ead3023da3f --- .../android/server/L2capNetworkProvider.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/service/src/com/android/server/L2capNetworkProvider.java b/service/src/com/android/server/L2capNetworkProvider.java index 787cab52d5..3866cef78e 100644 --- a/service/src/com/android/server/L2capNetworkProvider.java +++ b/service/src/com/android/server/L2capNetworkProvider.java @@ -30,11 +30,15 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.RES_ID_MATCH_ALL_RESERVATIONS; import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; import static android.content.pm.PackageManager.FEATURE_BLUETOOTH_LE; +import static android.system.OsConstants.F_GETFL; +import static android.system.OsConstants.F_SETFL; +import static android.system.OsConstants.O_NONBLOCK; import android.annotation.Nullable; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothServerSocket; +import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.pm.PackageManager; import android.net.ConnectivityManager; @@ -48,10 +52,14 @@ import android.net.NetworkSpecifier; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; +import android.os.ParcelFileDescriptor; +import android.system.Os; import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.ServiceConnectivityJni; +import com.android.server.net.L2capNetwork; import java.io.IOException; import java.util.Set; @@ -84,6 +92,10 @@ public class L2capNetworkProvider { @Nullable private BluetoothManager mBluetoothManager; + // Note: IFNAMSIZ is 16. + private static final String TUN_IFNAME = "l2cap-tun"; + private static int sTunIndex = 0; + /** * The blanket reservation offer is used to create an L2CAP server network, i.e. a network * based on a BluetoothServerSocket. @@ -222,6 +234,40 @@ public class L2capNetworkProvider { mProvider.unregisterNetworkOffer(reservedOffer); } + @Nullable + private static ParcelFileDescriptor createTunInterface(String ifname) { + final ParcelFileDescriptor fd; + try { + fd = ParcelFileDescriptor.adoptFd( + ServiceConnectivityJni.createTunTap( + true /*isTun*/, true /*hasCarrier*/, true /*setIffMulticast*/, ifname)); + ServiceConnectivityJni.bringUpInterface(ifname); + // TODO: consider adding a parameter to createTunTap() (or the Builder that should + // be added) to configure i/o blocking. + final int flags = Os.fcntlInt(fd.getFileDescriptor(), F_GETFL, 0); + Os.fcntlInt(fd.getFileDescriptor(), F_SETFL, flags & ~O_NONBLOCK); + } catch (Exception e) { + // Note: createTunTap currently throws an IllegalStateException on failure. + // TODO: native functions should throw ErrnoException. + Log.e(TAG, "Failed to create tun interface", e); + return null; + } + return fd; + } + + @Nullable + private L2capNetwork createL2capNetwork(BluetoothSocket socket, NetworkCapabilities caps, + L2capNetwork.ICallback cb) { + final String ifname = TUN_IFNAME + String.valueOf(sTunIndex++); + final ParcelFileDescriptor tunFd = createTunInterface(ifname); + if (tunFd == null) { + return null; + } + + return new L2capNetwork(mHandler, mContext, mProvider, ifname, socket, tunFd, caps, cb); + } + + private class ReservedServerOffer implements NetworkOfferCallback { private final NetworkCapabilities mReservedCapabilities; private final BluetoothServerSocket mServerSocket;