diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-09-02 21:02:14 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-09-02 21:02:14 +0000 |
commit | 46a57a347ec4b5c6974262ed8f88685a854a00af (patch) | |
tree | efaf9e838b13caea604ccea565056c8a4f7f3630 /common/device/com/android/net/module | |
parent | b24f26018c56b85f541aad78ae8d492848847bb3 (diff) | |
parent | c28fc7974331b64aa2d4b96ce9871a7bb6b24f7f (diff) | |
download | net-46a57a347ec4b5c6974262ed8f88685a854a00af.tar.gz |
Snap for 10755155 from c28fc7974331b64aa2d4b96ce9871a7bb6b24f7f to mainline-art-releaseaml_art_341110110aml_art_341110060
Change-Id: I2e5f018bbe03854a833e0bbe548d443b245b5c2f
Diffstat (limited to 'common/device/com/android/net/module')
4 files changed, 232 insertions, 34 deletions
diff --git a/common/device/com/android/net/module/util/BpfMap.java b/common/device/com/android/net/module/util/BpfMap.java index 9df2b035..d45caceb 100644 --- a/common/device/com/android/net/module/util/BpfMap.java +++ b/common/device/com/android/net/module/util/BpfMap.java @@ -194,9 +194,11 @@ public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V> } private K getNextKeyInternal(@Nullable K key) throws ErrnoException { - final byte[] rawKey = getNextRawKey( - key == null ? null : key.writeToBytes()); - if (rawKey == null) return null; + byte[] rawKey = new byte[mKeySize]; + + if (!nativeGetNextMapKey(mMapFd.getFd(), + key == null ? null : key.writeToBytes(), + rawKey)) return null; final ByteBuffer buffer = ByteBuffer.wrap(rawKey); buffer.order(ByteOrder.nativeOrder()); @@ -215,13 +217,6 @@ public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V> return getNextKeyInternal(key); } - private byte[] getNextRawKey(@Nullable final byte[] key) throws ErrnoException { - byte[] nextKey = new byte[mKeySize]; - if (nativeGetNextMapKey(mMapFd.getFd(), key, nextKey)) return nextKey; - - return null; - } - /** Get the first key of eBpf map. */ @Override public K getFirstKey() throws ErrnoException { @@ -233,30 +228,23 @@ public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V> public boolean containsKey(@NonNull K key) throws ErrnoException { Objects.requireNonNull(key); - final byte[] rawValue = getRawValue(key.writeToBytes()); - return rawValue != null; + byte[] rawValue = new byte[mValueSize]; + return nativeFindMapEntry(mMapFd.getFd(), key.writeToBytes(), rawValue); } /** Retrieve a value from the map. Return null if there is no such key. */ @Override public V getValue(@NonNull K key) throws ErrnoException { Objects.requireNonNull(key); - final byte[] rawValue = getRawValue(key.writeToBytes()); - if (rawValue == null) return null; + byte[] rawValue = new byte[mValueSize]; + if (!nativeFindMapEntry(mMapFd.getFd(), key.writeToBytes(), rawValue)) return null; final ByteBuffer buffer = ByteBuffer.wrap(rawValue); buffer.order(ByteOrder.nativeOrder()); return Struct.parse(mValueClass, buffer); } - private byte[] getRawValue(final byte[] key) throws ErrnoException { - byte[] value = new byte[mValueSize]; - if (nativeFindMapEntry(mMapFd.getFd(), key, value)) return value; - - return null; - } - /** * Iterate through the map and handle each key -> value retrieved base on the given BiConsumer. * The given BiConsumer may to delete the passed-in entry, but is not allowed to perform any diff --git a/common/device/com/android/net/module/util/DeviceConfigUtils.java b/common/device/com/android/net/module/util/DeviceConfigUtils.java index bea227d9..fb130f67 100644 --- a/common/device/com/android/net/module/util/DeviceConfigUtils.java +++ b/common/device/com/android/net/module/util/DeviceConfigUtils.java @@ -17,6 +17,7 @@ package com.android.net.module.util; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; +import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; import static android.provider.DeviceConfig.NAMESPACE_TETHERING; import static com.android.net.module.util.FeatureVersions.CONNECTIVITY_MODULE_ID; @@ -207,8 +208,9 @@ public final class DeviceConfigUtils { * null. * @return true if this feature is enabled, or false if disabled. */ - public static boolean isFeatureEnabled(@NonNull Context context, @NonNull String namespace, - @NonNull String name, @NonNull String moduleName, boolean defaultEnabled) { + public static boolean isTetheringFeatureEnabled(@NonNull Context context, + @NonNull String namespace, @NonNull String name, @NonNull String moduleName, + boolean defaultEnabled) { // TODO: migrate callers to a non-generic isTetheringFeatureEnabled method. if (!TETHERING_MODULE_NAME.equals(moduleName)) { throw new IllegalArgumentException( @@ -334,16 +336,42 @@ public final class DeviceConfigUtils { } /** - * Check whether one specific experimental feature in tethering module from {@link DeviceConfig} - * is disabled by setting a non-zero value in the property. + * Check whether one specific experimental feature in specific namespace from + * {@link DeviceConfig} is not disabled. Feature can be disabled by setting a non-zero + * value in the property. If the feature is enabled by default and disabled by flag push + * (kill switch), this method should be used. If the feature is disabled by default and + * enabled by flag push, {@link #isFeatureEnabled} should be used. * + * @param namespace The namespace containing the property to look up. * @param name The name of the property to look up. - * @return true if this feature is force disabled, or false if not disabled. + * @return true if this feature is enabled, or false if disabled. */ - public static boolean isTetheringFeatureForceDisabled(String name) { - final int propertyVersion = getDeviceConfigPropertyInt(NAMESPACE_TETHERING, name, + private static boolean isFeatureNotChickenedOut(String namespace, String name) { + final int propertyVersion = getDeviceConfigPropertyInt(namespace, name, 0 /* default value */); - return propertyVersion != 0; + return propertyVersion == 0; + } + + /** + * Check whether one specific experimental feature in Tethering module from {@link DeviceConfig} + * is not disabled. + * + * @param name The name of the property in tethering module to look up. + * @return true if this feature is enabled, or false if disabled. + */ + public static boolean isTetheringFeatureNotChickenedOut(String name) { + return isFeatureNotChickenedOut(NAMESPACE_TETHERING, name); + } + + /** + * Check whether one specific experimental feature in NetworkStack module from + * {@link DeviceConfig} is not disabled. + * + * @param name The name of the property in NetworkStack module to look up. + * @return true if this feature is enabled, or false if disabled. + */ + public static boolean isNetworkStackFeatureNotChickenedOut(String name) { + return isFeatureNotChickenedOut(NAMESPACE_CONNECTIVITY, name); } /** diff --git a/common/device/com/android/net/module/util/FeatureVersions.java b/common/device/com/android/net/module/util/FeatureVersions.java index 4986a588..149756c3 100644 --- a/common/device/com/android/net/module/util/FeatureVersions.java +++ b/common/device/com/android/net/module/util/FeatureVersions.java @@ -22,13 +22,24 @@ package com.android.net.module.util; * @hide */ public class FeatureVersions { - public static final long MODULE_MASK = 0xFF00_000000000L; - public static final long VERSION_MASK = 0x0000_FFFFFFFFFL; - public static final long CONNECTIVITY_MODULE_ID = 0x0100_000000000L; - public static final long NETWORK_STACK_MODULE_ID = 0x0200_000000000L; + /** + * This constant is used to do bitwise shift operation to create module ids. + * The module version is composed with 9 digits which is placed in the lower 36 bits. + */ + private static final int MODULE_SHIFT = 36; + /** + * The bitmask to do bitwise-and(i.e. {@code &}) operation to get the module id. + */ + public static final long MODULE_MASK = 0xFF0_0000_0000L; + /** + * The bitmask to do bitwise-and(i.e. {@code &}) operation to get the module version. + */ + public static final long VERSION_MASK = 0x00F_FFFF_FFFFL; + public static final long CONNECTIVITY_MODULE_ID = 0x01L << MODULE_SHIFT; + public static final long NETWORK_STACK_MODULE_ID = 0x02L << MODULE_SHIFT; // CLAT_ADDRESS_TRANSLATE is a feature of the network stack, which doesn't throw when system // try to add a NAT-T keepalive packet filter with v6 address, introduced in version // M-2023-Sept on July 3rd, 2023. public static final long FEATURE_CLAT_ADDRESS_TRANSLATE = - NETWORK_STACK_MODULE_ID + 340900000L; + NETWORK_STACK_MODULE_ID + 34_09_00_000L; } diff --git a/common/device/com/android/net/module/util/arp/ArpPacket.java b/common/device/com/android/net/module/util/arp/ArpPacket.java new file mode 100644 index 00000000..dab9694b --- /dev/null +++ b/common/device/com/android/net/module/util/arp/ArpPacket.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util.arp; + +import static android.system.OsConstants.ETH_P_ARP; +import static android.system.OsConstants.ETH_P_IP; + +import static com.android.net.module.util.NetworkStackConstants.ARP_ETHER_IPV4_LEN; +import static com.android.net.module.util.NetworkStackConstants.ARP_HWTYPE_ETHER; +import static com.android.net.module.util.NetworkStackConstants.ARP_REPLY; +import static com.android.net.module.util.NetworkStackConstants.ARP_REQUEST; +import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN; +import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_LEN; + +import android.net.MacAddress; + +import com.android.internal.annotations.VisibleForTesting; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; + +/** + * Defines basic data and operations needed to build and parse packets for the + * ARP protocol. + * + * @hide + */ +public class ArpPacket { + private static final String TAG = "ArpPacket"; + + public final short opCode; + public final Inet4Address senderIp; + public final Inet4Address targetIp; + public final MacAddress senderHwAddress; + public final MacAddress targetHwAddress; + + ArpPacket(short opCode, MacAddress senderHwAddress, Inet4Address senderIp, + MacAddress targetHwAddress, Inet4Address targetIp) { + this.opCode = opCode; + this.senderHwAddress = senderHwAddress; + this.senderIp = senderIp; + this.targetHwAddress = targetHwAddress; + this.targetIp = targetIp; + } + + /** + * Build an ARP packet from the required specified parameters. + */ + @VisibleForTesting + public static ByteBuffer buildArpPacket(final byte[] dstMac, final byte[] srcMac, + final byte[] targetIp, final byte[] targetHwAddress, byte[] senderIp, + final short opCode) { + final ByteBuffer buf = ByteBuffer.allocate(ARP_ETHER_IPV4_LEN); + + // Ether header + buf.put(dstMac); + buf.put(srcMac); + buf.putShort((short) ETH_P_ARP); + + // ARP header + buf.putShort((short) ARP_HWTYPE_ETHER); // hrd + buf.putShort((short) ETH_P_IP); // pro + buf.put((byte) ETHER_ADDR_LEN); // hln + buf.put((byte) IPV4_ADDR_LEN); // pln + buf.putShort(opCode); // op + buf.put(srcMac); // sha + buf.put(senderIp); // spa + buf.put(targetHwAddress); // tha + buf.put(targetIp); // tpa + buf.flip(); + return buf; + } + + /** + * Parse an ARP packet from a ByteBuffer object. + */ + @VisibleForTesting + public static ArpPacket parseArpPacket(final byte[] recvbuf, final int length) + throws ParseException { + try { + if (length < ARP_ETHER_IPV4_LEN || recvbuf.length < length) { + throw new ParseException("Invalid packet length: " + length); + } + + final ByteBuffer buffer = ByteBuffer.wrap(recvbuf, 0, length); + byte[] l2dst = new byte[ETHER_ADDR_LEN]; + byte[] l2src = new byte[ETHER_ADDR_LEN]; + buffer.get(l2dst); + buffer.get(l2src); + + final short etherType = buffer.getShort(); + if (etherType != ETH_P_ARP) { + throw new ParseException("Incorrect Ether Type: " + etherType); + } + + final short hwType = buffer.getShort(); + if (hwType != ARP_HWTYPE_ETHER) { + throw new ParseException("Incorrect HW Type: " + hwType); + } + + final short protoType = buffer.getShort(); + if (protoType != ETH_P_IP) { + throw new ParseException("Incorrect Protocol Type: " + protoType); + } + + final byte hwAddrLength = buffer.get(); + if (hwAddrLength != ETHER_ADDR_LEN) { + throw new ParseException("Incorrect HW address length: " + hwAddrLength); + } + + final byte ipAddrLength = buffer.get(); + if (ipAddrLength != IPV4_ADDR_LEN) { + throw new ParseException("Incorrect Protocol address length: " + ipAddrLength); + } + + final short opCode = buffer.getShort(); + if (opCode != ARP_REQUEST && opCode != ARP_REPLY) { + throw new ParseException("Incorrect opCode: " + opCode); + } + + byte[] senderHwAddress = new byte[ETHER_ADDR_LEN]; + byte[] senderIp = new byte[IPV4_ADDR_LEN]; + buffer.get(senderHwAddress); + buffer.get(senderIp); + + byte[] targetHwAddress = new byte[ETHER_ADDR_LEN]; + byte[] targetIp = new byte[IPV4_ADDR_LEN]; + buffer.get(targetHwAddress); + buffer.get(targetIp); + + return new ArpPacket(opCode, MacAddress.fromBytes(senderHwAddress), + (Inet4Address) InetAddress.getByAddress(senderIp), + MacAddress.fromBytes(targetHwAddress), + (Inet4Address) InetAddress.getByAddress(targetIp)); + } catch (IndexOutOfBoundsException e) { + throw new ParseException("Invalid index when wrapping a byte array into a buffer"); + } catch (BufferUnderflowException e) { + throw new ParseException("Invalid buffer position"); + } catch (IllegalArgumentException e) { + throw new ParseException("Invalid MAC address representation"); + } catch (UnknownHostException e) { + throw new ParseException("Invalid IP address of Host"); + } + } + + /** + * Thrown when parsing ARP packet failed. + */ + public static class ParseException extends Exception { + ParseException(String message) { + super(message); + } + } +} |