diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2020-03-19 11:19:26 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-03-19 11:19:26 +0000 |
commit | 21b9e60863f8f0fe040210f966f0173c46130525 (patch) | |
tree | a58445e6ef8253bdd2ec70872220b53ea82c3a47 /src/android/net/ip/IpClient.java | |
parent | 7120763069c8f1257bc8e0f3367a5b4eebb7941a (diff) | |
parent | 21ea24de47194c277070fc2dc1d606536e5164d0 (diff) |
Merge "Detect upstream hotspot device type by checking the vendor specific IE." into rvc-dev
Diffstat (limited to 'src/android/net/ip/IpClient.java')
-rw-r--r-- | src/android/net/ip/IpClient.java | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java index bfeac8b..ebb31c6 100644 --- a/src/android/net/ip/IpClient.java +++ b/src/android/net/ip/IpClient.java @@ -20,6 +20,7 @@ import static android.net.RouteInfo.RTN_UNICAST; import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; +import static com.android.server.util.NetworkStackConstants.VENDOR_SPECIFIC_IE_ID; import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission; import android.content.Context; @@ -40,10 +41,13 @@ import android.net.Uri; import android.net.apf.ApfCapabilities; import android.net.apf.ApfFilter; import android.net.dhcp.DhcpClient; +import android.net.dhcp.DhcpPacket; import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpManagerEvent; import android.net.shared.InitialConfiguration; import android.net.shared.ProvisioningConfiguration; +import android.net.shared.ProvisioningConfiguration.ScanResultInfo; +import android.net.shared.ProvisioningConfiguration.ScanResultInfo.InformationElement; import android.net.util.InterfaceParams; import android.net.util.NetworkStackUtils; import android.net.util.SharedLog; @@ -64,6 +68,7 @@ import android.util.SparseArray; import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.HexDump; import com.android.internal.util.IState; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.MessageUtils; @@ -80,6 +85,10 @@ import com.android.server.NetworkStackService.NetworkStackServiceManager; import java.io.FileDescriptor; import java.io.PrintWriter; import java.net.InetAddress; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -406,6 +415,13 @@ public class IpClient extends StateMachine { private static final int PROV_CHANGE_GAINED_PROVISIONING = 3; private static final int PROV_CHANGE_STILL_PROVISIONED = 4; + // Specific vendor OUI(3 bytes)/vendor specific type(1 byte) pattern for upstream hotspot + // device detection. Add new byte array pattern below in turn. + private static final List<byte[]> METERED_IE_PATTERN_LIST = Collections.unmodifiableList( + Arrays.asList( + new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xf2, (byte) 0x06 } + )); + private final State mStoppedState = new StoppedState(); private final State mStoppingState = new StoppingState(); private final State mClearingIpAddressesState = new ClearingIpAddressesState(); @@ -1269,16 +1285,71 @@ public class IpClient extends StateMachine { return (delta != PROV_CHANGE_LOST_PROVISIONING); } + @VisibleForTesting + static String removeDoubleQuotes(@NonNull String ssid) { + final int length = ssid.length(); + if ((length > 1) && (ssid.charAt(0) == '"') && (ssid.charAt(length - 1) == '"')) { + return ssid.substring(1, length - 1); + } + return ssid; + } + + private List<ByteBuffer> getVendorSpecificIEs(@NonNull ScanResultInfo scanResultInfo) { + ArrayList<ByteBuffer> vendorSpecificPayloadList = new ArrayList<>(); + for (InformationElement ie : scanResultInfo.getInformationElements()) { + if (ie.getId() == VENDOR_SPECIFIC_IE_ID) { + vendorSpecificPayloadList.add(ie.getPayload()); + } + } + return vendorSpecificPayloadList; + } + + private boolean detectUpstreamHotspotFromVendorIe() { + if (mConfiguration.mScanResultInfo == null) return false; + final ScanResultInfo scanResultInfo = mConfiguration.mScanResultInfo; + final String ssid = scanResultInfo.getSsid(); + final List<ByteBuffer> vendorSpecificPayloadList = getVendorSpecificIEs(scanResultInfo); + + if (mConfiguration.mDisplayName == null + || !removeDoubleQuotes(mConfiguration.mDisplayName).equals(ssid)) { + return false; + } + + for (ByteBuffer payload : vendorSpecificPayloadList) { + byte[] ouiAndType = new byte[4]; + try { + payload.get(ouiAndType); + } catch (BufferUnderflowException e) { + Log.e(mTag, "Couldn't parse vendor specific IE, buffer underflow"); + return false; + } + for (byte[] pattern : METERED_IE_PATTERN_LIST) { + if (Arrays.equals(pattern, ouiAndType)) { + if (DBG) { + Log.d(mTag, "detected upstream hotspot that matches OUI:" + + HexDump.toHexString(ouiAndType)); + } + return true; + } + } + } + return false; + } + private void handleIPv4Success(DhcpResults dhcpResults) { mDhcpResults = new DhcpResults(dhcpResults); final LinkProperties newLp = assembleLinkProperties(); final int delta = setLinkProperties(newLp); + if (mDhcpResults.vendorInfo == null && detectUpstreamHotspotFromVendorIe()) { + mDhcpResults.vendorInfo = DhcpPacket.VENDOR_INFO_ANDROID_METERED; + } + if (DBG) { - Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")"); + Log.d(mTag, "onNewDhcpResults(" + Objects.toString(mDhcpResults) + ")"); Log.d(mTag, "handleIPv4Success newLp{" + newLp + "}"); } - mCallback.onNewDhcpResults(dhcpResults); + mCallback.onNewDhcpResults(mDhcpResults); maybeSaveNetworkToIpMemoryStore(); dispatchCallback(delta, newLp); |