diff options
Diffstat (limited to 'common/framework/com/android')
28 files changed, 0 insertions, 5080 deletions
diff --git a/common/framework/com/android/net/module/util/BestClock.java b/common/framework/com/android/net/module/util/BestClock.java deleted file mode 100644 index 35391add..00000000 --- a/common/framework/com/android/net/module/util/BestClock.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2021 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; - -import android.util.Log; - -import java.time.Clock; -import java.time.DateTimeException; -import java.time.Instant; -import java.time.ZoneId; -import java.util.Arrays; - -/** - * Single {@link Clock} that will return the best available time from a set of - * prioritized {@link Clock} instances. - * <p> - * For example, when {@link SystemClock#currentNetworkTimeClock()} isn't able to - * provide the time, this class could use {@link Clock#systemUTC()} instead. - * - * Note that this is re-implemented based on {@code android.os.BestClock} to be used inside - * the mainline module. And the class does NOT support serialization. - * - * @hide - */ -final public class BestClock extends Clock { - private static final String TAG = "BestClock"; - private final ZoneId mZone; - private final Clock[] mClocks; - - public BestClock(ZoneId zone, Clock... clocks) { - super(); - this.mZone = zone; - this.mClocks = clocks; - } - - @Override - public long millis() { - for (Clock clock : mClocks) { - try { - return clock.millis(); - } catch (DateTimeException e) { - // Ignore and attempt the next clock - Log.w(TAG, e.toString()); - } - } - throw new DateTimeException( - "No clocks in " + Arrays.toString(mClocks) + " were able to provide time"); - } - - @Override - public ZoneId getZone() { - return mZone; - } - - @Override - public Clock withZone(ZoneId zone) { - return new BestClock(zone, mClocks); - } - - @Override - public Instant instant() { - return Instant.ofEpochMilli(millis()); - } -} diff --git a/common/framework/com/android/net/module/util/BinderUtils.java b/common/framework/com/android/net/module/util/BinderUtils.java deleted file mode 100644 index e4d14ea8..00000000 --- a/common/framework/com/android/net/module/util/BinderUtils.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2021 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; - -import android.annotation.NonNull; -import android.os.Binder; - -import java.util.function.Supplier; - -/** - * Collection of utilities for {@link Binder} and related classes. - * @hide - */ -public class BinderUtils { - /** - * Convenience method for running the provided action enclosed in - * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} - * - * Any exception thrown by the given action will be caught and rethrown after the call to - * {@link Binder#restoreCallingIdentity} - * - * Note that this is copied from Binder#withCleanCallingIdentity with minor changes - * since it is not public. - * - * @hide - */ - public static final <T extends Exception> void withCleanCallingIdentity( - @NonNull ThrowingRunnable<T> action) throws T { - final long callingIdentity = Binder.clearCallingIdentity(); - try { - action.run(); - } finally { - Binder.restoreCallingIdentity(callingIdentity); - } - } - - /** - * Like a Runnable, but declared to throw an exception. - * - * @param <T> The exception class which is declared to be thrown. - */ - @FunctionalInterface - public interface ThrowingRunnable<T extends Exception> { - /** @see java.lang.Runnable */ - void run() throws T; - } - - /** - * Convenience method for running the provided action enclosed in - * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} returning the - * result. - * - * <p>Any exception thrown by the given action will be caught and rethrown after - * the call to {@link Binder#restoreCallingIdentity}. - * - * Note that this is copied from Binder#withCleanCallingIdentity with minor changes - * since it is not public. - * - * @hide - */ - public static final <T, E extends Exception> T withCleanCallingIdentity( - @NonNull ThrowingSupplier<T, E> action) throws E { - final long callingIdentity = Binder.clearCallingIdentity(); - try { - return action.get(); - } finally { - Binder.restoreCallingIdentity(callingIdentity); - } - } - - /** - * An equivalent of {@link Supplier} - * - * @param <T> The class which is declared to be returned. - * @param <E> The exception class which is declared to be thrown. - */ - @FunctionalInterface - public interface ThrowingSupplier<T, E extends Exception> { - /** @see java.util.function.Supplier */ - T get() throws E; - } -} diff --git a/common/framework/com/android/net/module/util/BitUtils.java b/common/framework/com/android/net/module/util/BitUtils.java deleted file mode 100644 index 3062d8cf..00000000 --- a/common/framework/com/android/net/module/util/BitUtils.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2022 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; - -import android.annotation.NonNull; -import android.annotation.Nullable; - -/** - * @hide - */ -public class BitUtils { - /** - * Unpacks long value into an array of bits. - */ - public static int[] unpackBits(long val) { - int size = Long.bitCount(val); - int[] result = new int[size]; - int index = 0; - int bitPos = 0; - while (val != 0) { - if ((val & 1) == 1) result[index++] = bitPos; - val = val >>> 1; - bitPos++; - } - return result; - } - - /** - * Packs a list of ints in the same way as packBits() - * - * Each passed int is the rank of a bit that should be set in the returned long. - * Example : passing (1,3) will return in 0b00001010 and passing (5,6,0) will return 0b01100001 - * - * @param bits bits to pack - * @return a long with the specified bits set. - */ - public static long packBitList(int... bits) { - return packBits(bits); - } - - /** - * Packs array of bits into a long value. - * - * Each passed int is the rank of a bit that should be set in the returned long. - * Example : passing [1,3] will return in 0b00001010 and passing [5,6,0] will return 0b01100001 - * - * @param bits bits to pack - * @return a long with the specified bits set. - */ - public static long packBits(int[] bits) { - long packed = 0; - for (int b : bits) { - packed |= (1L << b); - } - return packed; - } - - /** - * An interface for a function that can retrieve a name associated with an int. - * - * This is useful for bitfields like network capabilities or network score policies. - */ - @FunctionalInterface - public interface NameOf { - /** Retrieve the name associated with the passed value */ - String nameOf(int value); - } - - /** - * Given a bitmask and a name fetcher, append names of all set bits to the builder - * - * This method takes all bit sets in the passed bitmask, will figure out the name associated - * with the weight of each bit with the passed name fetcher, and append each name to the - * passed StringBuilder, separated by the passed separator. - * - * For example, if the bitmask is 0110, and the name fetcher return "BIT_1" to "BIT_4" for - * numbers from 1 to 4, and the separator is "&", this method appends "BIT_2&BIT3" to the - * StringBuilder. - */ - public static void appendStringRepresentationOfBitMaskToStringBuilder(@NonNull StringBuilder sb, - long bitMask, @NonNull NameOf nameFetcher, @NonNull String separator) { - int bitPos = 0; - boolean firstElementAdded = false; - while (bitMask != 0) { - if ((bitMask & 1) != 0) { - if (firstElementAdded) { - sb.append(separator); - } else { - firstElementAdded = true; - } - sb.append(nameFetcher.nameOf(bitPos)); - } - bitMask >>>= 1; - ++bitPos; - } - } - - /** - * Returns a short but human-readable string of updates between an old and a new bit fields. - * - * @param oldVal the old bit field to diff from - * @param newVal the new bit field to diff to - * @return a string fit for logging differences, or null if no differences. - * this method cannot return the empty string. - */ - @Nullable - public static String describeDifferences(final long oldVal, final long newVal, - @NonNull final NameOf nameFetcher) { - final long changed = oldVal ^ newVal; - if (0 == changed) return null; - // If the control reaches here, there are changes (additions, removals, or both) so - // the code below is guaranteed to add something to the string and can't return "". - final long removed = oldVal & changed; - final long added = newVal & changed; - final StringBuilder sb = new StringBuilder(); - if (0 != removed) { - sb.append("-"); - appendStringRepresentationOfBitMaskToStringBuilder(sb, removed, nameFetcher, "-"); - } - if (0 != added) { - sb.append("+"); - appendStringRepresentationOfBitMaskToStringBuilder(sb, added, nameFetcher, "+"); - } - return sb.toString(); - } -} diff --git a/common/framework/com/android/net/module/util/ByteUtils.java b/common/framework/com/android/net/module/util/ByteUtils.java deleted file mode 100644 index 290ed465..00000000 --- a/common/framework/com/android/net/module/util/ByteUtils.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2022 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; - -import android.annotation.NonNull; - -/** - * Byte utility functions. - * @hide - */ -public class ByteUtils { - /** - * Returns the index of the first appearance of the value {@code target} in {@code array}. - * - * @param array an array of {@code byte} values, possibly empty - * @param target a primitive {@code byte} value - * @return the least index {@code i} for which {@code array[i] == target}, or {@code -1} if no - * such index exists. - */ - public static int indexOf(@NonNull byte[] array, byte target) { - return indexOf(array, target, 0, array.length); - } - - private static int indexOf(byte[] array, byte target, int start, int end) { - for (int i = start; i < end; i++) { - if (array[i] == target) { - return i; - } - } - return -1; - } - - /** - * Returns the values from each provided array combined into a single array. For example, {@code - * concat(new byte[] {a, b}, new byte[] {}, new byte[] {c}} returns the array {@code {a, b, c}}. - * - * @param arrays zero or more {@code byte} arrays - * @return a single array containing all the values from the source arrays, in order - */ - public static byte[] concat(@NonNull byte[]... arrays) { - int length = 0; - for (byte[] array : arrays) { - length += array.length; - } - byte[] result = new byte[length]; - int pos = 0; - for (byte[] array : arrays) { - System.arraycopy(array, 0, result, pos, array.length); - pos += array.length; - } - return result; - } -} diff --git a/common/framework/com/android/net/module/util/CollectionUtils.java b/common/framework/com/android/net/module/util/CollectionUtils.java deleted file mode 100644 index 39e7ce94..00000000 --- a/common/framework/com/android/net/module/util/CollectionUtils.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.util.ArrayMap; -import android.util.Pair; -import android.util.SparseArray; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Utilities for {@link Collection} and arrays. - * @hide - */ -public final class CollectionUtils { - private CollectionUtils() {} - - /** - * @return True if the array is null or 0-length. - */ - public static <T> boolean isEmpty(@Nullable T[] array) { - return array == null || array.length == 0; - } - - /** - * @return True if the collection is null or 0-length. - */ - public static <T> boolean isEmpty(@Nullable Collection<T> collection) { - return collection == null || collection.isEmpty(); - } - - /** - * Returns an int array from the given Integer list. - */ - @NonNull - public static int[] toIntArray(@NonNull Collection<Integer> list) { - int[] array = new int[list.size()]; - int i = 0; - for (Integer item : list) { - array[i] = item; - i++; - } - return array; - } - - /** - * Returns a long array from the given long list. - */ - @NonNull - public static long[] toLongArray(@NonNull Collection<Long> list) { - long[] array = new long[list.size()]; - int i = 0; - for (Long item : list) { - array[i] = item; - i++; - } - return array; - } - - /** - * @return True if all elements satisfy the predicate, false otherwise. - * Note that means this always returns true for empty collections. - */ - public static <T> boolean all(@NonNull Collection<T> elem, @NonNull Predicate<T> predicate) { - for (final T e : elem) { - if (!predicate.test(e)) return false; - } - return true; - - } - - /** - * @return True if any element satisfies the predicate, false otherwise. - * Note that means this always returns false for empty collections. - */ - public static <T> boolean any(@NonNull Collection<T> elem, @NonNull Predicate<T> predicate) { - return indexOf(elem, predicate) >= 0; - } - - /** - * @return The index of the first element that matches the predicate, or -1 if none. - */ - public static <T> int indexOf(@NonNull final Collection<T> elem, - @NonNull final Predicate<? super T> predicate) { - int idx = 0; - for (final T e : elem) { - if (predicate.test(e)) return idx; - idx++; - } - return -1; - } - - /** - * @return True if there exists at least one element in the sparse array for which - * condition {@code predicate} - */ - public static <T> boolean any(@NonNull SparseArray<T> array, @NonNull Predicate<T> predicate) { - for (int i = 0; i < array.size(); ++i) { - if (predicate.test(array.valueAt(i))) { - return true; - } - } - return false; - } - - /** - * @return true if the array contains the specified value. - */ - public static boolean contains(@Nullable short[] array, short value) { - if (array == null) return false; - for (int element : array) { - if (element == value) { - return true; - } - } - return false; - } - - /** - * @return true if the array contains the specified value. - */ - public static boolean contains(@Nullable int[] array, int value) { - if (array == null) return false; - for (int element : array) { - if (element == value) { - return true; - } - } - return false; - } - - /** - * @return true if the array contains the specified value. - */ - public static <T> boolean contains(@Nullable T[] array, @Nullable T value) { - return indexOf(array, value) != -1; - } - - /** - * Return first index of value in given array, or -1 if not found. - */ - public static <T> int indexOf(@Nullable T[] array, @Nullable T value) { - if (array == null) return -1; - for (int i = 0; i < array.length; i++) { - if (Objects.equals(array[i], value)) return i; - } - return -1; - } - - /** - * Returns the index of the needle array in the haystack array, or -1 if it can't be found. - * This is a byte array equivalent of Collections.indexOfSubList(). - */ - public static int indexOfSubArray(@NonNull byte[] haystack, @NonNull byte[] needle) { - for (int i = 0; i < haystack.length - needle.length + 1; i++) { - boolean found = true; - for (int j = 0; j < needle.length; j++) { - if (haystack[i + j] != needle[j]) { - found = false; - break; - } - } - if (found) { - return i; - } - } - return -1; - } - - /** - * Returns a new collection of elements that match the passed predicate. - * @param source the elements to filter. - * @param test the predicate to test for. - * @return a new collection containing only the source elements that satisfy the predicate. - */ - @NonNull public static <T> ArrayList<T> filter(@NonNull final Collection<T> source, - @NonNull final Predicate<T> test) { - final ArrayList<T> matches = new ArrayList<>(); - for (final T e : source) { - if (test.test(e)) { - matches.add(e); - } - } - return matches; - } - - /** - * Return sum of the given long array. - */ - public static long total(@Nullable long[] array) { - long total = 0; - if (array != null) { - for (long value : array) { - total += value; - } - } - return total; - } - - /** - * Returns true if the first collection contains any of the elements of the second. - * @param haystack where to search - * @param needles what to search for - * @param <T> type of elements - * @return true if |haystack| contains any of the |needles|, false otherwise - */ - public static <T> boolean containsAny(@NonNull final Collection<T> haystack, - @NonNull final Collection<? extends T> needles) { - for (T needle : needles) { - if (haystack.contains(needle)) return true; - } - return false; - } - - /** - * Returns true if the first collection contains all of the elements of the second. - * @param haystack where to search - * @param needles what to search for - * @param <T> type of elements - * @return true if |haystack| contains all of the |needles|, false otherwise - */ - public static <T> boolean containsAll(@NonNull final Collection<T> haystack, - @NonNull final Collection<? extends T> needles) { - return haystack.containsAll(needles); - } - - /** - * Returns the first item of a collection that matches the predicate. - * @param haystack The collection to search. - * @param condition The predicate to match. - * @param <T> The type of element in the collection. - * @return The first element matching the predicate, or null if none. - */ - @Nullable - public static <T> T findFirst(@NonNull final Collection<T> haystack, - @NonNull final Predicate<? super T> condition) { - for (T needle : haystack) { - if (condition.test(needle)) return needle; - } - return null; - } - - /** - * Returns the last item of a List that matches the predicate. - * @param haystack The List to search. - * @param condition The predicate to match. - * @param <T> The type of element in the list. - * @return The last element matching the predicate, or null if none. - */ - // There is no way to reverse iterate a Collection in Java (e.g. the collection may - // be a single-linked list), so implementing this on Collection is necessarily very - // wasteful (store and reverse a copy, test all elements, or recurse to the end of the - // list to test on the up path and possibly blow the call stack) - @Nullable - public static <T> T findLast(@NonNull final List<T> haystack, - @NonNull final Predicate<? super T> condition) { - for (int i = haystack.size() - 1; i >= 0; --i) { - final T needle = haystack.get(i); - if (condition.test(needle)) return needle; - } - return null; - } - - /** - * Returns whether a collection contains an element matching a condition - * @param haystack The collection to search. - * @param condition The predicate to match. - * @param <T> The type of element in the collection. - * @return Whether the collection contains any element matching the condition. - */ - public static <T> boolean contains(@NonNull final Collection<T> haystack, - @NonNull final Predicate<? super T> condition) { - return -1 != indexOf(haystack, condition); - } - - /** - * Standard map function, but returns a new modifiable ArrayList - * - * This returns a new list that contains, for each element of the source collection, its - * image through the passed transform. - * Elements in the source can be null if the transform accepts null inputs. - * Elements in the output can be null if the transform ever returns null. - * This function never returns null. If the source collection is empty, it returns the - * empty list. - * Contract : this method calls the transform function exactly once for each element in the - * list, in iteration order. - * - * @param source the source collection - * @param transform the function to transform the elements - * @param <T> type of source elements - * @param <R> type of destination elements - * @return an unmodifiable list of transformed elements - */ - @NonNull - public static <T, R> ArrayList<R> map(@NonNull final Collection<T> source, - @NonNull final Function<? super T, ? extends R> transform) { - final ArrayList<R> dest = new ArrayList<>(source.size()); - for (final T e : source) { - dest.add(transform.apply(e)); - } - return dest; - } - - /** - * Standard zip function, but returns a new modifiable ArrayList - * - * This returns a list of pairs containing, at each position, a pair of the element from the - * first list at that index and the element from the second list at that index. - * Both lists must be the same size. They may contain null. - * - * The easiest way to visualize what's happening is to think of two lists being laid out next - * to each other and stitched together with a zipper. - * - * Contract : this method will read each element of each list exactly once, in some unspecified - * order. If it throws, it will not read any element. - * - * @param first the first list of elements - * @param second the second list of elements - * @param <T> the type of first elements - * @param <R> the type of second elements - * @return the zipped list - */ - @NonNull - public static <T, R> ArrayList<Pair<T, R>> zip(@NonNull final List<T> first, - @NonNull final List<R> second) { - final int size = first.size(); - if (size != second.size()) { - throw new IllegalArgumentException("zip : collections must be the same size"); - } - final ArrayList<Pair<T, R>> dest = new ArrayList<>(size); - for (int i = 0; i < size; ++i) { - dest.add(new Pair<>(first.get(i), second.get(i))); - } - return dest; - } - - /** - * Returns a new ArrayMap that associates each key with the value at the same index. - * - * Both lists must be the same size. - * Both keys and values may contain null. - * Keys may not contain the same value twice. - * - * Contract : this method will read each element of each list exactly once, but does not - * specify the order, except if it throws in which case the number of reads is undefined. - * - * @param keys The list of keys - * @param values The list of values - * @param <T> The type of keys - * @param <R> The type of values - * @return The associated map - */ - @NonNull - public static <T, R> ArrayMap<T, R> assoc( - @NonNull final List<T> keys, @NonNull final List<R> values) { - final int size = keys.size(); - if (size != values.size()) { - throw new IllegalArgumentException("assoc : collections must be the same size"); - } - final ArrayMap<T, R> dest = new ArrayMap<>(size); - for (int i = 0; i < size; ++i) { - final T key = keys.get(i); - if (dest.containsKey(key)) { - throw new IllegalArgumentException( - "assoc : keys may not contain the same value twice"); - } - dest.put(key, values.get(i)); - } - return dest; - } -} diff --git a/common/framework/com/android/net/module/util/ConnectivitySettingsUtils.java b/common/framework/com/android/net/module/util/ConnectivitySettingsUtils.java deleted file mode 100644 index f4856b34..00000000 --- a/common/framework/com/android/net/module/util/ConnectivitySettingsUtils.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2021 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; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.ContentResolver; -import android.content.Context; -import android.provider.Settings; -import android.text.TextUtils; - -/** - * Collection of connectivity settings utilities. - * - * @hide - */ -public class ConnectivitySettingsUtils { - public static final int PRIVATE_DNS_MODE_OFF = 1; - public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; - public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; - - public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode"; - public static final String PRIVATE_DNS_MODE = "private_dns_mode"; - public static final String PRIVATE_DNS_MODE_OFF_STRING = "off"; - public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING = "opportunistic"; - public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING = "hostname"; - public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier"; - - /** - * Get private DNS mode as string. - * - * @param mode One of the private DNS values. - * @return A string of private DNS mode. - */ - public static String getPrivateDnsModeAsString(int mode) { - switch (mode) { - case PRIVATE_DNS_MODE_OFF: - return PRIVATE_DNS_MODE_OFF_STRING; - case PRIVATE_DNS_MODE_OPPORTUNISTIC: - return PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING; - case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME: - return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING; - default: - throw new IllegalArgumentException("Invalid private dns mode: " + mode); - } - } - - private static int getPrivateDnsModeAsInt(String mode) { - // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose - // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode. - if (TextUtils.isEmpty(mode)) - return PRIVATE_DNS_MODE_OPPORTUNISTIC; - switch (mode) { - case "off": - return PRIVATE_DNS_MODE_OFF; - case "hostname": - return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; - case "opportunistic": - return PRIVATE_DNS_MODE_OPPORTUNISTIC; - default: - // b/260211513: adb shell settings put global private_dns_mode foo - // can result in arbitrary strings - treat any unknown value as empty string. - // throw new IllegalArgumentException("Invalid private dns mode: " + mode); - return PRIVATE_DNS_MODE_OPPORTUNISTIC; - } - } - - /** - * Get private DNS mode from settings. - * - * @param context The Context to query the private DNS mode from settings. - * @return An integer of private DNS mode. - */ - public static int getPrivateDnsMode(@NonNull Context context) { - final ContentResolver cr = context.getContentResolver(); - String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); - if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); - return getPrivateDnsModeAsInt(mode); - } - - /** - * Set private DNS mode to settings. - * - * @param context The {@link Context} to set the private DNS mode. - * @param mode The private dns mode. This should be one of the PRIVATE_DNS_MODE_* constants. - */ - public static void setPrivateDnsMode(@NonNull Context context, int mode) { - if (!(mode == PRIVATE_DNS_MODE_OFF - || mode == PRIVATE_DNS_MODE_OPPORTUNISTIC - || mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) { - throw new IllegalArgumentException("Invalid private dns mode: " + mode); - } - Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_MODE, - getPrivateDnsModeAsString(mode)); - } - - /** - * Get specific private dns provider name from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @return The specific private dns provider name, or null if no setting value. - */ - @Nullable - public static String getPrivateDnsHostname(@NonNull Context context) { - return Settings.Global.getString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER); - } - - /** - * Set specific private dns provider name to {@link Settings}. - * - * @param context The {@link Context} to set the setting. - * @param specifier The specific private dns provider name. - */ - public static void setPrivateDnsHostname(@NonNull Context context, @Nullable String specifier) { - Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER, specifier); - } -} diff --git a/common/framework/com/android/net/module/util/ConnectivityUtils.java b/common/framework/com/android/net/module/util/ConnectivityUtils.java deleted file mode 100644 index c135e466..00000000 --- a/common/framework/com/android/net/module/util/ConnectivityUtils.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2020 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; - - -import android.annotation.Nullable; - -import java.net.Inet6Address; -import java.net.InetAddress; - -/** - * Various utilities used in connectivity code. - * @hide - */ -public final class ConnectivityUtils { - private ConnectivityUtils() {} - - - /** - * Return IP address and port in a string format. - */ - public static String addressAndPortToString(InetAddress address, int port) { - return String.format( - (address instanceof Inet6Address) ? "[%s]:%d" : "%s:%d", - address.getHostAddress(), port); - } - - /** - * Return true if the provided address is non-null and an IPv6 Unique Local Address (RFC4193). - */ - public static boolean isIPv6ULA(@Nullable InetAddress addr) { - return addr instanceof Inet6Address - && ((addr.getAddress()[0] & 0xfe) == 0xfc); - } - - /** - * Returns the {@code int} nearest in value to {@code value}. - * - * @param value any {@code long} value - * @return the same value cast to {@code int} if it is in the range of the {@code int} - * type, {@link Integer#MAX_VALUE} if it is too large, or {@link Integer#MIN_VALUE} if - * it is too small - */ - public static int saturatedCast(long value) { - if (value > Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } - if (value < Integer.MIN_VALUE) { - return Integer.MIN_VALUE; - } - return (int) value; - } -} diff --git a/common/framework/com/android/net/module/util/DnsPacket.java b/common/framework/com/android/net/module/util/DnsPacket.java deleted file mode 100644 index 0dcdf1e6..00000000 --- a/common/framework/com/android/net/module/util/DnsPacket.java +++ /dev/null @@ -1,599 +0,0 @@ -/* - * 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; - -import static android.net.DnsResolver.TYPE_A; -import static android.net.DnsResolver.TYPE_AAAA; - -import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; -import static com.android.net.module.util.DnsPacketUtils.DnsRecordParser.domainNameToLabels; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.net.module.util.DnsPacketUtils.DnsRecordParser; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.InetAddress; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * Defines basic data for DNS protocol based on RFC 1035. - * Subclasses create the specific format used in DNS packet. - * - * @hide - */ -public abstract class DnsPacket { - /** - * Type of the canonical name for an alias. Refer to RFC 1035 section 3.2.2. - */ - // TODO: Define the constant as a public constant in DnsResolver since it can never change. - private static final int TYPE_CNAME = 5; - - /** - * Thrown when parsing packet failed. - */ - public static class ParseException extends RuntimeException { - public String reason; - public ParseException(@NonNull String reason) { - super(reason); - this.reason = reason; - } - - public ParseException(@NonNull String reason, @NonNull Throwable cause) { - super(reason, cause); - this.reason = reason; - } - } - - /** - * DNS header for DNS protocol based on RFC 1035 section 4.1.1. - * - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ID | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * |QR| Opcode |AA|TC|RD|RA| Z | RCODE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QDCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ANCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | NSCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ARCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - public static class DnsHeader { - private static final String TAG = "DnsHeader"; - private static final int SIZE_IN_BYTES = 12; - private final int mId; - private final int mFlags; - private final int[] mRecordCount; - - /* If this bit in the 'flags' field is set to 0, the DNS message corresponding to this - * header is a query; otherwise, it is a response. - */ - private static final int FLAGS_SECTION_QR_BIT = 15; - - /** - * Create a new DnsHeader from a positioned ByteBuffer. - * - * The ByteBuffer must be in network byte order (which is the default). - * Reads the passed ByteBuffer from its current position and decodes a DNS header. - * When this constructor returns, the reading position of the ByteBuffer has been - * advanced to the end of the DNS header record. - * This is meant to chain with other methods reading a DNS response in sequence. - */ - @VisibleForTesting - public DnsHeader(@NonNull ByteBuffer buf) throws BufferUnderflowException { - Objects.requireNonNull(buf); - mId = Short.toUnsignedInt(buf.getShort()); - mFlags = Short.toUnsignedInt(buf.getShort()); - mRecordCount = new int[NUM_SECTIONS]; - for (int i = 0; i < NUM_SECTIONS; ++i) { - mRecordCount[i] = Short.toUnsignedInt(buf.getShort()); - } - } - - /** - * Determines if the DNS message corresponding to this header is a response, as defined in - * RFC 1035 Section 4.1.1. - */ - public boolean isResponse() { - return (mFlags & (1 << FLAGS_SECTION_QR_BIT)) != 0; - } - - /** - * Create a new DnsHeader from specified parameters. - * - * This constructor only builds the question and answer sections. Authority - * and additional sections are not supported. Useful when synthesizing dns - * responses from query or reply packets. - */ - @VisibleForTesting - public DnsHeader(int id, int flags, int qdcount, int ancount) { - this.mId = id; - this.mFlags = flags; - mRecordCount = new int[NUM_SECTIONS]; - mRecordCount[QDSECTION] = qdcount; - mRecordCount[ANSECTION] = ancount; - } - - /** - * Get record count by type. - */ - public int getRecordCount(int type) { - return mRecordCount[type]; - } - - /** - * Get flags of this instance. - */ - public int getFlags() { - return mFlags; - } - - /** - * Get id of this instance. - */ - public int getId() { - return mId; - } - - @Override - public String toString() { - return "DnsHeader{" + "id=" + mId + ", flags=" + mFlags - + ", recordCounts=" + Arrays.toString(mRecordCount) + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o.getClass() != getClass()) return false; - final DnsHeader other = (DnsHeader) o; - return mId == other.mId - && mFlags == other.mFlags - && Arrays.equals(mRecordCount, other.mRecordCount); - } - - @Override - public int hashCode() { - return 31 * mId + 37 * mFlags + Arrays.hashCode(mRecordCount); - } - - /** - * Get DnsHeader as byte array. - */ - @NonNull - public byte[] getBytes() { - // TODO: if this is called often, optimize the ByteBuffer out and write to the - // array directly. - final ByteBuffer buf = ByteBuffer.allocate(SIZE_IN_BYTES); - buf.putShort((short) mId); - buf.putShort((short) mFlags); - for (int i = 0; i < NUM_SECTIONS; ++i) { - buf.putShort((short) mRecordCount[i]); - } - return buf.array(); - } - } - - /** - * Superclass for DNS questions and DNS resource records. - * - * DNS questions (No TTL/RDLENGTH/RDATA) based on RFC 1035 section 4.1.2. - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | | - * / QNAME / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QTYPE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QCLASS | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * DNS resource records (With TTL/RDLENGTH/RDATA) based on RFC 1035 section 4.1.3. - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | | - * / / - * / NAME / - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | TYPE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | CLASS | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | TTL | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | RDLENGTH | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| - * / RDATA / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * Note that this class is meant to be used by composition and not inheritance, and - * that classes implementing more specific DNS records should call #parse. - */ - // TODO: Make DnsResourceRecord and DnsQuestion subclasses of DnsRecord. - public static class DnsRecord { - // Refer to RFC 1035 section 2.3.4 for MAXNAMESIZE. - // NAME_NORMAL and NAME_COMPRESSION are used for checking name compression, - // refer to rfc 1035 section 4.1.4. - public static final int MAXNAMESIZE = 255; - public static final int NAME_NORMAL = 0; - public static final int NAME_COMPRESSION = 0xC0; - - private static final String TAG = "DnsRecord"; - - public final String dName; - public final int nsType; - public final int nsClass; - public final long ttl; - private final byte[] mRdata; - /** - * Type of this DNS record. - */ - @RecordType - public final int rType; - - /** - * Create a new DnsRecord from a positioned ByteBuffer. - * - * Reads the passed ByteBuffer from its current position and decodes a DNS record. - * When this constructor returns, the reading position of the ByteBuffer has been - * advanced to the end of the DNS resource record. - * This is meant to chain with other methods reading a DNS response in sequence. - * - * @param rType Type of the record. - * @param buf ByteBuffer input of record, must be in network byte order - * (which is the default). - */ - private DnsRecord(@RecordType int rType, @NonNull ByteBuffer buf) - throws BufferUnderflowException, ParseException { - Objects.requireNonNull(buf); - this.rType = rType; - dName = DnsRecordParser.parseName(buf, 0 /* Parse depth */, - true /* isNameCompressionSupported */); - if (dName.length() > MAXNAMESIZE) { - throw new ParseException( - "Parse name fail, name size is too long: " + dName.length()); - } - nsType = Short.toUnsignedInt(buf.getShort()); - nsClass = Short.toUnsignedInt(buf.getShort()); - - if (rType != QDSECTION) { - ttl = Integer.toUnsignedLong(buf.getInt()); - final int length = Short.toUnsignedInt(buf.getShort()); - mRdata = new byte[length]; - buf.get(mRdata); - } else { - ttl = 0; - mRdata = null; - } - } - - /** - * Create a new DnsRecord or subclass of DnsRecord instance from a positioned ByteBuffer. - * - * Peek the nsType, sending the buffer to corresponding DnsRecord subclass constructors - * to allow constructing the corresponding object. - */ - @VisibleForTesting(visibility = PRIVATE) - public static DnsRecord parse(@RecordType int rType, @NonNull ByteBuffer buf) - throws BufferUnderflowException, ParseException { - Objects.requireNonNull(buf); - final int oldPos = buf.position(); - // Parsed name not used, just for jumping to nsType position. - DnsRecordParser.parseName(buf, 0 /* Parse depth */, - true /* isNameCompressionSupported */); - // Peek the nsType. - final int nsType = Short.toUnsignedInt(buf.getShort()); - buf.position(oldPos); - // Return a DnsRecord instance by default for backward compatibility, this is useful - // when a partner supports new type of DnsRecord but does not inherit DnsRecord. - switch (nsType) { - default: - return new DnsRecord(rType, buf); - } - } - - /** - * Make an A or AAAA record based on the specified parameters. - * - * @param rType Type of the record, can be {@link #ANSECTION}, {@link #ARSECTION} - * or {@link #NSSECTION}. - * @param dName Domain name of the record. - * @param nsClass Class of the record. See RFC 1035 section 3.2.4. - * @param ttl time interval (in seconds) that the resource record may be - * cached before it should be discarded. Zero values are - * interpreted to mean that the RR can only be used for the - * transaction in progress, and should not be cached. - * @param address Instance of {@link InetAddress} - * @return A record if the {@code address} is an IPv4 address, or AAAA record if the - * {@code address} is an IPv6 address. - */ - public static DnsRecord makeAOrAAAARecord(int rType, @NonNull String dName, - int nsClass, long ttl, @NonNull InetAddress address) throws IOException { - final int nsType = (address.getAddress().length == 4) ? TYPE_A : TYPE_AAAA; - return new DnsRecord(rType, dName, nsType, nsClass, ttl, address, null /* rDataStr */); - } - - /** - * Make an CNAME record based on the specified parameters. - * - * @param rType Type of the record, can be {@link #ANSECTION}, {@link #ARSECTION} - * or {@link #NSSECTION}. - * @param dName Domain name of the record. - * @param nsClass Class of the record. See RFC 1035 section 3.2.4. - * @param ttl time interval (in seconds) that the resource record may be - * cached before it should be discarded. Zero values are - * interpreted to mean that the RR can only be used for the - * transaction in progress, and should not be cached. - * @param domainName Canonical name of the {@code dName}. - * @return A record if the {@code address} is an IPv4 address, or AAAA record if the - * {@code address} is an IPv6 address. - */ - public static DnsRecord makeCNameRecord(int rType, @NonNull String dName, int nsClass, - long ttl, @NonNull String domainName) throws IOException { - return new DnsRecord(rType, dName, TYPE_CNAME, nsClass, ttl, null /* address */, - domainName); - } - - /** - * Make a DNS question based on the specified parameters. - */ - public static DnsRecord makeQuestion(@NonNull String dName, int nsType, int nsClass) { - return new DnsRecord(dName, nsType, nsClass); - } - - private static String requireHostName(@NonNull String name) { - if (!DnsRecordParser.isHostName(name)) { - throw new IllegalArgumentException("Expected domain name but got " + name); - } - return name; - } - - /** - * Create a new query DnsRecord from specified parameters, useful when synthesizing - * dns response. - */ - private DnsRecord(@NonNull String dName, int nsType, int nsClass) { - this.rType = QDSECTION; - this.dName = requireHostName(dName); - this.nsType = nsType; - this.nsClass = nsClass; - mRdata = null; - this.ttl = 0; - } - - /** - * Create a new CNAME/A/AAAA DnsRecord from specified parameters. - * - * @param address The address only used when synthesizing A or AAAA record. - * @param rDataStr The alias of the domain, only used when synthesizing CNAME record. - */ - private DnsRecord(@RecordType int rType, @NonNull String dName, int nsType, int nsClass, - long ttl, @Nullable InetAddress address, @Nullable String rDataStr) - throws IOException { - this.rType = rType; - this.dName = requireHostName(dName); - this.nsType = nsType; - this.nsClass = nsClass; - if (rType < 0 || rType >= NUM_SECTIONS || rType == QDSECTION) { - throw new IllegalArgumentException("Unexpected record type: " + rType); - } - mRdata = nsType == TYPE_CNAME ? domainNameToLabels(rDataStr) : address.getAddress(); - this.ttl = ttl; - } - - /** - * Get a copy of rdata. - */ - @Nullable - public byte[] getRR() { - return (mRdata == null) ? null : mRdata.clone(); - } - - /** - * Get DnsRecord as byte array. - */ - @NonNull - public byte[] getBytes() throws IOException { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final DataOutputStream dos = new DataOutputStream(baos); - dos.write(domainNameToLabels(dName)); - dos.writeShort(nsType); - dos.writeShort(nsClass); - if (rType != QDSECTION) { - dos.writeInt((int) ttl); - if (mRdata == null) { - dos.writeShort(0); - } else { - dos.writeShort(mRdata.length); - dos.write(mRdata); - } - } - return baos.toByteArray(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o.getClass() != getClass()) return false; - final DnsRecord other = (DnsRecord) o; - return rType == other.rType - && nsType == other.nsType - && nsClass == other.nsClass - && ttl == other.ttl - && TextUtils.equals(dName, other.dName) - && Arrays.equals(mRdata, other.mRdata); - } - - @Override - public int hashCode() { - return 31 * Objects.hash(dName) - + 37 * ((int) (ttl & 0xFFFFFFFF)) - + 41 * ((int) (ttl >> 32)) - + 43 * nsType - + 47 * nsClass - + 53 * rType - + Arrays.hashCode(mRdata); - } - - @Override - public String toString() { - return "DnsRecord{" - + "rType=" + rType - + ", dName='" + dName + '\'' - + ", nsType=" + nsType - + ", nsClass=" + nsClass - + ", ttl=" + ttl - + ", mRdata=" + Arrays.toString(mRdata) - + '}'; - } - } - - /** - * Header section types, refer to RFC 1035 section 4.1.1. - */ - public static final int QDSECTION = 0; - public static final int ANSECTION = 1; - public static final int NSSECTION = 2; - public static final int ARSECTION = 3; - @VisibleForTesting(visibility = PRIVATE) - static final int NUM_SECTIONS = ARSECTION + 1; - - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - QDSECTION, - ANSECTION, - NSSECTION, - ARSECTION, - }) - public @interface RecordType {} - - - private static final String TAG = DnsPacket.class.getSimpleName(); - - protected final DnsHeader mHeader; - protected final List<DnsRecord>[] mRecords; - - protected DnsPacket(@NonNull byte[] data) throws ParseException { - if (null == data) { - throw new ParseException("Parse header failed, null input data"); - } - - final ByteBuffer buffer; - try { - buffer = ByteBuffer.wrap(data); - mHeader = new DnsHeader(buffer); - } catch (BufferUnderflowException e) { - throw new ParseException("Parse Header fail, bad input data", e); - } - - mRecords = new ArrayList[NUM_SECTIONS]; - - for (int i = 0; i < NUM_SECTIONS; ++i) { - final int count = mHeader.getRecordCount(i); - mRecords[i] = new ArrayList(count); - for (int j = 0; j < count; ++j) { - try { - mRecords[i].add(DnsRecord.parse(i, buffer)); - } catch (BufferUnderflowException e) { - throw new ParseException("Parse record fail", e); - } - } - } - } - - /** - * Create a new {@link #DnsPacket} from specified parameters. - * - * Note that authority records section and additional records section is not supported. - */ - protected DnsPacket(@NonNull DnsHeader header, @NonNull List<DnsRecord> qd, - @NonNull List<DnsRecord> an) { - mHeader = Objects.requireNonNull(header); - mRecords = new List[NUM_SECTIONS]; - mRecords[QDSECTION] = Collections.unmodifiableList(new ArrayList<>(qd)); - mRecords[ANSECTION] = Collections.unmodifiableList(new ArrayList<>(an)); - mRecords[NSSECTION] = new ArrayList<>(); - mRecords[ARSECTION] = new ArrayList<>(); - for (int i = 0; i < NUM_SECTIONS; i++) { - if (mHeader.mRecordCount[i] != mRecords[i].size()) { - throw new IllegalArgumentException("Record count mismatch: expected " - + mHeader.mRecordCount[i] + " but was " + mRecords[i]); - } - } - } - - /** - * Get DnsPacket as byte array. - */ - public @NonNull byte[] getBytes() throws IOException { - final ByteArrayOutputStream buf = new ByteArrayOutputStream(); - buf.write(mHeader.getBytes()); - - for (int i = 0; i < NUM_SECTIONS; ++i) { - for (final DnsRecord record : mRecords[i]) { - buf.write(record.getBytes()); - } - } - return buf.toByteArray(); - } - - @Override - public String toString() { - return "DnsPacket{" + "header=" + mHeader + ", records='" + Arrays.toString(mRecords) + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o.getClass() != getClass()) return false; - final DnsPacket other = (DnsPacket) o; - return Objects.equals(mHeader, other.mHeader) - && Arrays.deepEquals(mRecords, other.mRecords); - } - - @Override - public int hashCode() { - int result = Objects.hash(mHeader); - result = 31 * result + Arrays.hashCode(mRecords); - return result; - } -} diff --git a/common/framework/com/android/net/module/util/DnsPacketUtils.java b/common/framework/com/android/net/module/util/DnsPacketUtils.java deleted file mode 100644 index 105d7837..00000000 --- a/common/framework/com/android/net/module/util/DnsPacketUtils.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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; - -import static com.android.net.module.util.DnsPacket.DnsRecord.NAME_COMPRESSION; -import static com.android.net.module.util.DnsPacket.DnsRecord.NAME_NORMAL; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.InetAddresses; -import android.net.ParseException; -import android.text.TextUtils; -import android.util.Patterns; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.text.DecimalFormat; -import java.text.FieldPosition; - -/** - * Utilities for decoding the contents of a DnsPacket. - * - * @hide - */ -public final class DnsPacketUtils { - /** - * Reads the passed ByteBuffer from its current position and decodes a DNS record. - */ - public static class DnsRecordParser { - private static final int MAXLABELSIZE = 63; - private static final int MAXNAMESIZE = 255; - private static final int MAXLABELCOUNT = 128; - - private static final DecimalFormat sByteFormat = new DecimalFormat(); - private static final FieldPosition sPos = new FieldPosition(0); - - /** - * Convert label from {@code byte[]} to {@code String} - * - * <p>Follows the same conversion rules of the native code (ns_name.c in libc). - */ - @VisibleForTesting - static String labelToString(@NonNull byte[] label) { - final StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < label.length; ++i) { - int b = Byte.toUnsignedInt(label[i]); - // Control characters and non-ASCII characters. - if (b <= 0x20 || b >= 0x7f) { - // Append the byte as an escaped decimal number, e.g., "\19" for 0x13. - sb.append('\\'); - sByteFormat.format(b, sb, sPos); - } else if (b == '"' || b == '.' || b == ';' || b == '\\' || b == '(' || b == ')' - || b == '@' || b == '$') { - // Append the byte as an escaped character, e.g., "\:" for 0x3a. - sb.append('\\'); - sb.append((char) b); - } else { - // Append the byte as a character, e.g., "a" for 0x61. - sb.append((char) b); - } - } - return sb.toString(); - } - - /** - * Converts domain name to labels according to RFC 1035. - * - * @param name Domain name as String that needs to be converted to labels. - * @return An encoded byte array that is constructed out of labels, - * and ends with zero-length label. - * @throws ParseException if failed to parse the given domain name or - * IOException if failed to output labels. - */ - public static @NonNull byte[] domainNameToLabels(@NonNull String name) throws - IOException, ParseException { - if (name.length() > MAXNAMESIZE) { - throw new ParseException("Domain name exceeds max length: " + name.length()); - } - if (!isHostName(name)) { - throw new ParseException("Failed to parse domain name: " + name); - } - final ByteArrayOutputStream buf = new ByteArrayOutputStream(); - final String[] labels = name.split("\\."); - for (final String label : labels) { - if (label.length() > MAXLABELSIZE) { - throw new ParseException("label is too long: " + label); - } - buf.write(label.length()); - // Encode as UTF-8 as suggested in RFC 6055 section 3. - buf.write(label.getBytes(StandardCharsets.UTF_8)); - } - buf.write(0x00); // end with zero-length label - return buf.toByteArray(); - } - - /** - * Check whether the input is a valid hostname based on rfc 1035 section 3.3. - * - * @param hostName the target host name. - * @return true if the input is a valid hostname. - */ - public static boolean isHostName(@Nullable String hostName) { - // TODO: Use {@code Patterns.HOST_NAME} if available. - // Patterns.DOMAIN_NAME accepts host names or IP addresses, so reject - // IP addresses. - return hostName != null - && Patterns.DOMAIN_NAME.matcher(hostName).matches() - && !InetAddresses.isNumericAddress(hostName); - } - - /** - * Parses the domain / target name of a DNS record. - */ - public static String parseName(final ByteBuffer buf, int depth, - boolean isNameCompressionSupported) throws - BufferUnderflowException, DnsPacket.ParseException { - return parseName(buf, depth, MAXLABELCOUNT, isNameCompressionSupported); - } - - /** - * Parses the domain / target name of a DNS record. - * - * As described in RFC 1035 Section 4.1.3, the NAME field of a DNS Resource Record always - * supports Name Compression, whereas domain names contained in the RDATA payload of a DNS - * record may or may not support Name Compression, depending on the record TYPE. Moreover, - * even if Name Compression is supported, its usage is left to the implementation. - */ - public static String parseName(final ByteBuffer buf, int depth, int maxLabelCount, - boolean isNameCompressionSupported) throws - BufferUnderflowException, DnsPacket.ParseException { - if (depth > maxLabelCount) { - throw new DnsPacket.ParseException("Failed to parse name, too many labels"); - } - final int len = Byte.toUnsignedInt(buf.get()); - final int mask = len & NAME_COMPRESSION; - if (0 == len) { - return ""; - } else if (mask != NAME_NORMAL && mask != NAME_COMPRESSION - || (!isNameCompressionSupported && mask == NAME_COMPRESSION)) { - throw new DnsPacket.ParseException("Parse name fail, bad label type: " + mask); - } else if (mask == NAME_COMPRESSION) { - // Name compression based on RFC 1035 - 4.1.4 Message compression - final int offset = ((len & ~NAME_COMPRESSION) << 8) + Byte.toUnsignedInt(buf.get()); - final int oldPos = buf.position(); - if (offset >= oldPos - 2) { - throw new DnsPacket.ParseException( - "Parse compression name fail, invalid compression"); - } - buf.position(offset); - final String pointed = parseName(buf, depth + 1, maxLabelCount, - isNameCompressionSupported); - buf.position(oldPos); - return pointed; - } else { - final byte[] label = new byte[len]; - buf.get(label); - final String head = labelToString(label); - if (head.length() > MAXLABELSIZE) { - throw new DnsPacket.ParseException("Parse name fail, invalid label length"); - } - final String tail = parseName(buf, depth + 1, maxLabelCount, - isNameCompressionSupported); - return TextUtils.isEmpty(tail) ? head : head + "." + tail; - } - } - - private DnsRecordParser() {} - } - - private DnsPacketUtils() {} -} diff --git a/common/framework/com/android/net/module/util/DnsSdTxtRecord.java b/common/framework/com/android/net/module/util/DnsSdTxtRecord.java deleted file mode 100644 index 760891b9..00000000 --- a/common/framework/com/android/net/module/util/DnsSdTxtRecord.java +++ /dev/null @@ -1,325 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * 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. - - To do: - - implement remove() - - fix set() to replace existing values - */ - -package com.android.net.module.util; - -import android.os.Parcelable; -import android.os.Parcel; - -import java.util.Arrays; - -/** - * This class handles TXT record data for DNS based service discovery as specified at - * http://tools.ietf.org/html/draft-cheshire-dnsext-dns-sd-11 - * - * DNS-SD specifies that a TXT record corresponding to an SRV record consist of - * a packed array of bytes, each preceded by a length byte. Each string - * is an attribute-value pair. - * - * The DnsSdTxtRecord object stores the entire TXT data as a single byte array, traversing it - * as need be to implement its various methods. - * @hide - * - */ -public class DnsSdTxtRecord implements Parcelable { - private static final byte mSeparator = '='; - - private byte[] mData; - - /** Constructs a new, empty TXT record. */ - public DnsSdTxtRecord() { - mData = new byte[0]; - } - - /** Constructs a new TXT record from a byte array in the standard format. */ - public DnsSdTxtRecord(byte[] data) { - mData = (byte[]) data.clone(); - } - - /** Copy constructor */ - public DnsSdTxtRecord(DnsSdTxtRecord src) { - if (src != null && src.mData != null) { - mData = (byte[]) src.mData.clone(); - } - } - - /** - * Set a key/value pair. Setting an existing key will replace its value. - * @param key Must be ascii with no '=' - * @param value matching value to key - */ - public void set(String key, String value) { - byte[] keyBytes; - byte[] valBytes; - int valLen; - - if (value != null) { - valBytes = value.getBytes(); - valLen = valBytes.length; - } else { - valBytes = null; - valLen = 0; - } - - try { - keyBytes = key.getBytes("US-ASCII"); - } - catch (java.io.UnsupportedEncodingException e) { - throw new IllegalArgumentException("key should be US-ASCII"); - } - - for (int i = 0; i < keyBytes.length; i++) { - if (keyBytes[i] == '=') { - throw new IllegalArgumentException("= is not a valid character in key"); - } - } - - if (keyBytes.length + valLen >= 255) { - throw new IllegalArgumentException("Key and Value length cannot exceed 255 bytes"); - } - - int currentLoc = remove(key); - if (currentLoc == -1) - currentLoc = keyCount(); - - insert(keyBytes, valBytes, currentLoc); - } - - /** - * Get a value for a key - * - * @param key - * @return The value associated with the key - */ - public String get(String key) { - byte[] val = this.getValue(key); - return val != null ? new String(val) : null; - } - - /** Remove a key/value pair. If found, returns the index or -1 if not found */ - public int remove(String key) { - int avStart = 0; - - for (int i=0; avStart < mData.length; i++) { - int avLen = mData[avStart]; - if (key.length() <= avLen && - (key.length() == avLen || mData[avStart + key.length() + 1] == mSeparator)) { - String s = new String(mData, avStart + 1, key.length()); - if (0 == key.compareToIgnoreCase(s)) { - byte[] oldBytes = mData; - mData = new byte[oldBytes.length - avLen - 1]; - System.arraycopy(oldBytes, 0, mData, 0, avStart); - System.arraycopy(oldBytes, avStart + avLen + 1, mData, avStart, - oldBytes.length - avStart - avLen - 1); - return i; - } - } - avStart += (0xFF & (avLen + 1)); - } - return -1; - } - - /** Return the count of keys */ - public int keyCount() { - int count = 0, nextKey; - for (nextKey = 0; nextKey < mData.length; count++) { - nextKey += (0xFF & (mData[nextKey] + 1)); - } - return count; - } - - /** Return true if key is present, false if not. */ - public boolean contains(String key) { - String s = null; - for (int i = 0; null != (s = this.getKey(i)); i++) { - if (0 == key.compareToIgnoreCase(s)) return true; - } - return false; - } - - /* Gets the size in bytes */ - public int size() { - return mData.length; - } - - /* Gets the raw data in bytes */ - public byte[] getRawData() { - return (byte[]) mData.clone(); - } - - private void insert(byte[] keyBytes, byte[] value, int index) { - byte[] oldBytes = mData; - int valLen = (value != null) ? value.length : 0; - int insertion = 0; - int newLen, avLen; - - for (int i = 0; i < index && insertion < mData.length; i++) { - insertion += (0xFF & (mData[insertion] + 1)); - } - - avLen = keyBytes.length + valLen + (value != null ? 1 : 0); - newLen = avLen + oldBytes.length + 1; - - mData = new byte[newLen]; - System.arraycopy(oldBytes, 0, mData, 0, insertion); - int secondHalfLen = oldBytes.length - insertion; - System.arraycopy(oldBytes, insertion, mData, newLen - secondHalfLen, secondHalfLen); - mData[insertion] = (byte) avLen; - System.arraycopy(keyBytes, 0, mData, insertion + 1, keyBytes.length); - if (value != null) { - mData[insertion + 1 + keyBytes.length] = mSeparator; - System.arraycopy(value, 0, mData, insertion + keyBytes.length + 2, valLen); - } - } - - /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */ - private String getKey(int index) { - int avStart = 0; - - for (int i=0; i < index && avStart < mData.length; i++) { - avStart += mData[avStart] + 1; - } - - if (avStart < mData.length) { - int avLen = mData[avStart]; - int aLen = 0; - - for (aLen=0; aLen < avLen; aLen++) { - if (mData[avStart + aLen + 1] == mSeparator) break; - } - return new String(mData, avStart + 1, aLen); - } - return null; - } - - /** - * Look up a key in the TXT record by zero-based index and return its value. - * Returns null if index exceeds the total number of keys. - * Returns null if the key is present with no value. - */ - private byte[] getValue(int index) { - int avStart = 0; - byte[] value = null; - - for (int i=0; i < index && avStart < mData.length; i++) { - avStart += mData[avStart] + 1; - } - - if (avStart < mData.length) { - int avLen = mData[avStart]; - int aLen = 0; - - for (aLen=0; aLen < avLen; aLen++) { - if (mData[avStart + aLen + 1] == mSeparator) { - value = new byte[avLen - aLen - 1]; - System.arraycopy(mData, avStart + aLen + 2, value, 0, avLen - aLen - 1); - break; - } - } - } - return value; - } - - private String getValueAsString(int index) { - byte[] value = this.getValue(index); - return value != null ? new String(value) : null; - } - - private byte[] getValue(String forKey) { - String s = null; - int i; - - for (i = 0; null != (s = this.getKey(i)); i++) { - if (0 == forKey.compareToIgnoreCase(s)) { - return this.getValue(i); - } - } - - return null; - } - - /** - * Return a string representation. - * Example : {key1=value1},{key2=value2}.. - * - * For a key say like "key3" with null value - * {key1=value1},{key2=value2}{key3} - */ - public String toString() { - String a, result = null; - - for (int i = 0; null != (a = this.getKey(i)); i++) { - String av = "{" + a; - String val = this.getValueAsString(i); - if (val != null) - av += "=" + val + "}"; - else - av += "}"; - if (result == null) - result = av; - else - result = result + ", " + av; - } - return result != null ? result : ""; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof DnsSdTxtRecord)) { - return false; - } - - DnsSdTxtRecord record = (DnsSdTxtRecord)o; - return Arrays.equals(record.mData, mData); - } - - @Override - public int hashCode() { - return Arrays.hashCode(mData); - } - - /** Implement the Parcelable interface */ - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeByteArray(mData); - } - - /** Implement the Parcelable interface */ - public static final @android.annotation.NonNull Creator<DnsSdTxtRecord> CREATOR = - new Creator<DnsSdTxtRecord>() { - public DnsSdTxtRecord createFromParcel(Parcel in) { - DnsSdTxtRecord info = new DnsSdTxtRecord(); - in.readByteArray(info.mData); - return info; - } - - public DnsSdTxtRecord[] newArray(int size) { - return new DnsSdTxtRecord[size]; - } - }; -} diff --git a/common/framework/com/android/net/module/util/HexDump.java b/common/framework/com/android/net/module/util/HexDump.java deleted file mode 100644 index a22c258d..00000000 --- a/common/framework/com/android/net/module/util/HexDump.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2021 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; - -import androidx.annotation.Nullable; - -/** - * Hex utility functions. - * - * @hide - */ -public class HexDump { - private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F' }; - private static final char[] HEX_LOWER_CASE_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - - /** - * Dump the hex string corresponding to the specified byte array. - * - * @param array byte array to be dumped. - */ - public static String dumpHexString(@Nullable byte[] array) { - if (array == null) return "(null)"; - return dumpHexString(array, 0, array.length); - } - - /** - * Dump the hex string corresponding to the specified byte array. - * - * @param array byte array to be dumped. - * @param offset the offset in array where dump should start. - * @param length the length of bytes to be dumped. - */ - public static String dumpHexString(@Nullable byte[] array, int offset, int length) { - if (array == null) return "(null)"; - StringBuilder result = new StringBuilder(); - - byte[] line = new byte[16]; - int lineIndex = 0; - - result.append("\n0x"); - result.append(toHexString(offset)); - - for (int i = offset; i < offset + length; i++) { - if (lineIndex == 16) { - result.append(" "); - - for (int j = 0; j < 16; j++) { - if (line[j] > ' ' && line[j] < '~') { - result.append(new String(line, j, 1)); - } else { - result.append("."); - } - } - - result.append("\n0x"); - result.append(toHexString(i)); - lineIndex = 0; - } - - byte b = array[i]; - result.append(" "); - result.append(HEX_DIGITS[(b >>> 4) & 0x0F]); - result.append(HEX_DIGITS[b & 0x0F]); - - line[lineIndex++] = b; - } - - if (lineIndex != 16) { - int count = (16 - lineIndex) * 3; - count++; - for (int i = 0; i < count; i++) { - result.append(" "); - } - - for (int i = 0; i < lineIndex; i++) { - if (line[i] > ' ' && line[i] < '~') { - result.append(new String(line, i, 1)); - } else { - result.append("."); - } - } - } - - return result.toString(); - } - - /** - * Convert a byte to an uppercase hex string. - * - * @param b the byte to be converted. - */ - public static String toHexString(byte b) { - return toHexString(toByteArray(b)); - } - - /** - * Convert a byte array to an uppercase hex string. - * - * @param array the byte array to be converted. - */ - public static String toHexString(byte[] array) { - return toHexString(array, 0, array.length, true); - } - - /** - * Convert a byte array to a hex string. - * - * @param array the byte array to be converted. - * @param upperCase whether the converted hex string should be uppercase or not. - */ - public static String toHexString(byte[] array, boolean upperCase) { - return toHexString(array, 0, array.length, upperCase); - } - - /** - * Convert a byte array to hex string. - * - * @param array the byte array to be converted. - * @param offset the offset in array where conversion should start. - * @param length the length of bytes to be converted. - */ - public static String toHexString(byte[] array, int offset, int length) { - return toHexString(array, offset, length, true); - } - - /** - * Convert a byte array to hex string. - * - * @param array the byte array to be converted. - * @param offset the offset in array where conversion should start. - * @param length the length of bytes to be converted. - * @param upperCase whether the converted hex string should be uppercase or not. - */ - public static String toHexString(byte[] array, int offset, int length, boolean upperCase) { - char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS; - char[] buf = new char[length * 2]; - - int bufIndex = 0; - for (int i = offset; i < offset + length; i++) { - byte b = array[i]; - buf[bufIndex++] = digits[(b >>> 4) & 0x0F]; - buf[bufIndex++] = digits[b & 0x0F]; - } - - return new String(buf); - } - - /** - * Convert an integer to hex string. - * - * @param i the integer to be converted. - */ - public static String toHexString(int i) { - return toHexString(toByteArray(i)); - } - - /** - * Convert a byte to byte array. - * - * @param b the byte to be converted. - */ - public static byte[] toByteArray(byte b) { - byte[] array = new byte[1]; - array[0] = b; - return array; - } - - /** - * Convert an integer to byte array. - * - * @param i the integer to be converted. - */ - public static byte[] toByteArray(int i) { - byte[] array = new byte[4]; - - array[3] = (byte) (i & 0xFF); - array[2] = (byte) ((i >> 8) & 0xFF); - array[1] = (byte) ((i >> 16) & 0xFF); - array[0] = (byte) ((i >> 24) & 0xFF); - - return array; - } - - private static int toByte(char c) { - if (c >= '0' && c <= '9') return (c - '0'); - if (c >= 'A' && c <= 'F') return (c - 'A' + 10); - if (c >= 'a' && c <= 'f') return (c - 'a' + 10); - - throw new RuntimeException("Invalid hex char '" + c + "'"); - } - - /** - * Convert a hex string to a byte array. - * - * @param hexString the string to be converted. - */ - public static byte[] hexStringToByteArray(String hexString) { - int length = hexString.length(); - byte[] buffer = new byte[length / 2]; - - for (int i = 0; i < length; i += 2) { - buffer[i / 2] = - (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1))); - } - - return buffer; - } - - /** - * Convert a byte to hex string and append it to StringBuilder. - * - * @param sb StringBuilder instance. - * @param b the byte to be converted. - * @param upperCase whether the converted hex string should be uppercase or not. - */ - public static StringBuilder appendByteAsHex(StringBuilder sb, byte b, boolean upperCase) { - char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS; - sb.append(digits[(b >> 4) & 0xf]); - sb.append(digits[b & 0xf]); - return sb; - } -} diff --git a/common/framework/com/android/net/module/util/Inet4AddressUtils.java b/common/framework/com/android/net/module/util/Inet4AddressUtils.java deleted file mode 100644 index 87f43d51..00000000 --- a/common/framework/com/android/net/module/util/Inet4AddressUtils.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Collection of utilities to work with IPv4 addresses. - * @hide - */ -public class Inet4AddressUtils { - - /** - * Convert a IPv4 address from an integer to an InetAddress (0x04030201 -> 1.2.3.4) - * - * <p>This method uses the higher-order int bytes as the lower-order IPv4 address bytes, - * which is an unusual convention. Consider {@link #intToInet4AddressHTH(int)} instead. - * @param hostAddress an int coding for an IPv4 address, where higher-order int byte is - * lower-order IPv4 address byte - */ - public static Inet4Address intToInet4AddressHTL(int hostAddress) { - return intToInet4AddressHTH(Integer.reverseBytes(hostAddress)); - } - - /** - * Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4) - * @param hostAddress an int coding for an IPv4 address - */ - public static Inet4Address intToInet4AddressHTH(int hostAddress) { - byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)), - (byte) (0xff & (hostAddress >> 16)), - (byte) (0xff & (hostAddress >> 8)), - (byte) (0xff & hostAddress) }; - - try { - return (Inet4Address) InetAddress.getByAddress(addressBytes); - } catch (UnknownHostException e) { - throw new AssertionError(); - } - } - - /** - * Convert an IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x01020304) - * - * <p>This conversion can help order IP addresses: considering the ordering - * 192.0.2.1 < 192.0.2.2 < ..., resulting ints will follow that ordering if read as unsigned - * integers with {@link Integer#toUnsignedLong}. - * @param inetAddr is an InetAddress corresponding to the IPv4 address - * @return the IP address as integer - */ - public static int inet4AddressToIntHTH(Inet4Address inetAddr) - throws IllegalArgumentException { - byte [] addr = inetAddr.getAddress(); - return ((addr[0] & 0xff) << 24) | ((addr[1] & 0xff) << 16) - | ((addr[2] & 0xff) << 8) | (addr[3] & 0xff); - } - - /** - * Convert a IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x04030201) - * - * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes, - * which is an unusual convention. Consider {@link #inet4AddressToIntHTH(Inet4Address)} instead. - * @param inetAddr is an InetAddress corresponding to the IPv4 address - * @return the IP address as integer - */ - public static int inet4AddressToIntHTL(Inet4Address inetAddr) { - return Integer.reverseBytes(inet4AddressToIntHTH(inetAddr)); - } - - /** - * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0xffff8000) - * @return the IPv4 netmask as an integer - */ - public static int prefixLengthToV4NetmaskIntHTH(int prefixLength) - throws IllegalArgumentException { - if (prefixLength < 0 || prefixLength > 32) { - throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)"); - } - // (int)a << b is equivalent to a << (b & 0x1f): can't shift by 32 (-1 << 32 == -1) - return prefixLength == 0 ? 0 : 0xffffffff << (32 - prefixLength); - } - - /** - * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0x0080ffff). - * - * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes, - * which is an unusual convention. Consider {@link #prefixLengthToV4NetmaskIntHTH(int)} instead. - * @return the IPv4 netmask as an integer - */ - public static int prefixLengthToV4NetmaskIntHTL(int prefixLength) - throws IllegalArgumentException { - return Integer.reverseBytes(prefixLengthToV4NetmaskIntHTH(prefixLength)); - } - - /** - * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous. - * @param netmask as a {@code Inet4Address}. - * @return the network prefix length - * @throws IllegalArgumentException the specified netmask was not contiguous. - * @hide - */ - public static int netmaskToPrefixLength(Inet4Address netmask) { - // inetAddressToInt returns an int in *network* byte order. - int i = inet4AddressToIntHTH(netmask); - int prefixLength = Integer.bitCount(i); - int trailingZeros = Integer.numberOfTrailingZeros(i); - if (trailingZeros != 32 - prefixLength) { - throw new IllegalArgumentException("Non-contiguous netmask: " + Integer.toHexString(i)); - } - return prefixLength; - } - - /** - * Returns the implicit netmask of an IPv4 address, as was the custom before 1993. - */ - public static int getImplicitNetmask(Inet4Address address) { - int firstByte = address.getAddress()[0] & 0xff; // Convert to an unsigned value. - if (firstByte < 128) { - return 8; - } else if (firstByte < 192) { - return 16; - } else if (firstByte < 224) { - return 24; - } else { - return 32; // Will likely not end well for other reasons. - } - } - - /** - * Get the broadcast address for a given prefix. - * - * <p>For example 192.168.0.1/24 -> 192.168.0.255 - */ - public static Inet4Address getBroadcastAddress(Inet4Address addr, int prefixLength) - throws IllegalArgumentException { - final int intBroadcastAddr = inet4AddressToIntHTH(addr) - | ~prefixLengthToV4NetmaskIntHTH(prefixLength); - return intToInet4AddressHTH(intBroadcastAddr); - } - - /** - * Get a prefix mask as Inet4Address for a given prefix length. - * - * <p>For example 20 -> 255.255.240.0 - */ - public static Inet4Address getPrefixMaskAsInet4Address(int prefixLength) - throws IllegalArgumentException { - return intToInet4AddressHTH(prefixLengthToV4NetmaskIntHTH(prefixLength)); - } - - /** - * Trim leading zeros from IPv4 address strings - * Non-v4 addresses and host names remain unchanged. - * For example, 192.168.000.010 -> 192.168.0.10 - * @param addr a string representing an ip address - * @return a string properly trimmed - */ - public static String trimAddressZeros(String addr) { - if (addr == null) return null; - String[] octets = addr.split("\\."); - if (octets.length != 4) return addr; - StringBuilder builder = new StringBuilder(16); - String result = null; - for (int i = 0; i < 4; i++) { - try { - if (octets[i].length() > 3) return addr; - builder.append(Integer.parseInt(octets[i])); - } catch (NumberFormatException e) { - return addr; - } - if (i < 3) builder.append('.'); - } - result = builder.toString(); - return result; - } -} diff --git a/common/framework/com/android/net/module/util/InetAddressUtils.java b/common/framework/com/android/net/module/util/InetAddressUtils.java deleted file mode 100644 index 40fc59fb..00000000 --- a/common/framework/com/android/net/module/util/InetAddressUtils.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import android.annotation.NonNull; -import android.os.Parcel; -import android.util.Log; - - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Collection of utilities to interact with {@link InetAddress} - * @hide - */ -public class InetAddressUtils { - - private static final String TAG = InetAddressUtils.class.getSimpleName(); - private static final int INET6_ADDR_LENGTH = 16; - - /** - * Writes an InetAddress to a parcel. The address may be null. This is likely faster than - * calling writeSerializable. - * @hide - */ - public static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) { - byte[] addressArray = (address != null) ? address.getAddress() : null; - parcel.writeByteArray(addressArray); - if (address instanceof Inet6Address) { - final Inet6Address v6Address = (Inet6Address) address; - final boolean hasScopeId = v6Address.getScopeId() != 0; - parcel.writeBoolean(hasScopeId); - if (hasScopeId) parcel.writeInt(v6Address.getScopeId()); - } - - } - - /** - * Reads an InetAddress from a parcel. Returns null if the address that was written was null - * or if the data is invalid. - * @hide - */ - public static InetAddress unparcelInetAddress(Parcel in) { - byte[] addressArray = in.createByteArray(); - if (addressArray == null) { - return null; - } - - try { - if (addressArray.length == INET6_ADDR_LENGTH) { - final boolean hasScopeId = in.readBoolean(); - final int scopeId = hasScopeId ? in.readInt() : 0; - return Inet6Address.getByAddress(null /* host */, addressArray, scopeId); - } - - return InetAddress.getByAddress(addressArray); - } catch (UnknownHostException e) { - return null; - } - } - - /** - * Create a Inet6Address with scope id if it is a link local address. Otherwise, returns the - * original address. - */ - public static Inet6Address withScopeId(@NonNull final Inet6Address addr, int scopeid) { - if (!addr.isLinkLocalAddress()) { - return addr; - } - try { - return Inet6Address.getByAddress(null /* host */, addr.getAddress(), - scopeid); - } catch (UnknownHostException impossible) { - Log.wtf(TAG, "Cannot construct scoped Inet6Address with Inet6Address.getAddress(" - + addr.getHostAddress() + "): ", impossible); - return null; - } - } - - private InetAddressUtils() {} -} diff --git a/common/framework/com/android/net/module/util/InterfaceParams.java b/common/framework/com/android/net/module/util/InterfaceParams.java deleted file mode 100644 index 30762ebb..00000000 --- a/common/framework/com/android/net/module/util/InterfaceParams.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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; - -import android.net.MacAddress; -import android.text.TextUtils; - -import java.net.NetworkInterface; -import java.net.SocketException; - - -/** - * Encapsulate the interface parameters common to IpClient/IpServer components. - * - * Basically all java.net.NetworkInterface methods throw Exceptions. IpClient - * and IpServer (sub)components need most or all of this information at some - * point during their lifecycles, so pass only this simplified object around - * which can be created once when IpClient/IpServer are told to start. - * - * @hide - */ -public class InterfaceParams { - public final String name; - public final int index; - public final boolean hasMacAddress; - public final MacAddress macAddr; - public final int defaultMtu; - - // TODO: move the below to NetworkStackConstants when this class is moved to the NetworkStack. - private static final int ETHER_MTU = 1500; - private static final int IPV6_MIN_MTU = 1280; - - - /** - * Return InterfaceParams corresponding with an interface name - * @param name the interface name - */ - public static InterfaceParams getByName(String name) { - final NetworkInterface netif = getNetworkInterfaceByName(name); - if (netif == null) return null; - - // Not all interfaces have MAC addresses, e.g. rmnet_data0. - final MacAddress macAddr = getMacAddress(netif); - - try { - return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU()); - } catch (IllegalArgumentException | SocketException e) { - return null; - } - } - - public InterfaceParams(String name, int index, MacAddress macAddr) { - this(name, index, macAddr, ETHER_MTU); - } - - public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) { - if (TextUtils.isEmpty(name)) { - throw new IllegalArgumentException("impossible interface name"); - } - - if (index <= 0) throw new IllegalArgumentException("invalid interface index"); - - this.name = name; - this.index = index; - this.hasMacAddress = (macAddr != null); - this.macAddr = hasMacAddress ? macAddr : MacAddress.fromBytes(new byte[] { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }); - this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU; - } - - @Override - public String toString() { - return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu); - } - - private static NetworkInterface getNetworkInterfaceByName(String name) { - try { - return NetworkInterface.getByName(name); - } catch (NullPointerException | SocketException e) { - return null; - } - } - - private static MacAddress getMacAddress(NetworkInterface netif) { - try { - return MacAddress.fromBytes(netif.getHardwareAddress()); - } catch (IllegalArgumentException | NullPointerException | SocketException e) { - return null; - } - } -} diff --git a/common/framework/com/android/net/module/util/IpRange.java b/common/framework/com/android/net/module/util/IpRange.java deleted file mode 100644 index 0a3f95be..00000000 --- a/common/framework/com/android/net/module/util/IpRange.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import static com.android.internal.annotations.VisibleForTesting.Visibility; - -import android.annotation.NonNull; -import android.net.IpPrefix; - -import com.android.internal.annotations.VisibleForTesting; - -import java.math.BigInteger; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; -import java.util.Queue; - -/** - * This class represents an IP range, i.e., a contiguous block of IP addresses defined by a starting - * and ending IP address. These addresses may not be power-of-two aligned. - * - * <p>Conversion to prefixes are deterministic, and will always return the same set of {@link - * IpPrefix}(es). Ordering of IpPrefix instances is not guaranteed. - * - * @hide - */ -public final class IpRange { - private static final int SIGNUM_POSITIVE = 1; - - private final byte[] mStartAddr; - private final byte[] mEndAddr; - - public IpRange(@NonNull InetAddress startAddr, @NonNull InetAddress endAddr) { - Objects.requireNonNull(startAddr, "startAddr must not be null"); - Objects.requireNonNull(endAddr, "endAddr must not be null"); - - if (!startAddr.getClass().equals(endAddr.getClass())) { - throw new IllegalArgumentException("Invalid range: Address family mismatch"); - } - if (addrToBigInteger(startAddr.getAddress()).compareTo( - addrToBigInteger(endAddr.getAddress())) >= 0) { - throw new IllegalArgumentException( - "Invalid range; start address must be before end address"); - } - - mStartAddr = startAddr.getAddress(); - mEndAddr = endAddr.getAddress(); - } - - @VisibleForTesting(visibility = Visibility.PRIVATE) - public IpRange(@NonNull IpPrefix prefix) { - Objects.requireNonNull(prefix, "prefix must not be null"); - - // Use masked address from IpPrefix to zero out lower order bits. - mStartAddr = prefix.getRawAddress(); - - // Set all non-prefix bits to max. - mEndAddr = prefix.getRawAddress(); - for (int bitIndex = prefix.getPrefixLength(); bitIndex < 8 * mEndAddr.length; ++bitIndex) { - mEndAddr[bitIndex / 8] |= (byte) (0x80 >> (bitIndex % 8)); - } - } - - private static InetAddress getAsInetAddress(byte[] address) { - try { - return InetAddress.getByAddress(address); - } catch (UnknownHostException e) { - // Cannot happen. InetAddress.getByAddress can only throw an exception if the byte - // array is the wrong length, but are always generated from InetAddress(es). - throw new IllegalArgumentException("Address is invalid"); - } - } - - @VisibleForTesting(visibility = Visibility.PRIVATE) - public InetAddress getStartAddr() { - return getAsInetAddress(mStartAddr); - } - - @VisibleForTesting(visibility = Visibility.PRIVATE) - public InetAddress getEndAddr() { - return getAsInetAddress(mEndAddr); - } - - /** - * Converts this IP range to a list of IpPrefix instances. - * - * <p>This method outputs the IpPrefix instances for use in the routing architecture. - * - * <p>For example, the range 192.0.2.4 - 192.0.3.1 converts to the following prefixes: - * - * <ul> - * <li>192.0.2.128/25 - * <li>192.0.2.64/26 - * <li>192.0.2.32/27 - * <li>192.0.2.16/28 - * <li>192.0.2.8/29 - * <li>192.0.2.4/30 - * <li>192.0.3.0/31 - * </ul> - */ - public List<IpPrefix> asIpPrefixes() { - final boolean isIpv6 = (mStartAddr.length == 16); - final List<IpPrefix> result = new ArrayList<>(); - final Queue<IpPrefix> workingSet = new LinkedList<>(); - - // Start with the any-address. Inet4/6Address.ANY requires compiling against - // core-platform-api. - workingSet.add(new IpPrefix(isIpv6 ? getAsInetAddress(new byte[16]) /* IPv6_ANY */ - : getAsInetAddress(new byte[4]) /* IPv4_ANY */, 0)); - - // While items are still in the queue, test and narrow to subsets. - while (!workingSet.isEmpty()) { - final IpPrefix workingPrefix = workingSet.poll(); - final IpRange workingRange = new IpRange(workingPrefix); - - // If the other range is contained within, it's part of the output. Do not test subsets, - // or we will end up with duplicates. - if (containsRange(workingRange)) { - result.add(workingPrefix); - continue; - } - - // If there is any overlap, split the working range into it's two subsets, and - // reevaluate those. - if (overlapsRange(workingRange)) { - workingSet.addAll(getSubsetPrefixes(workingPrefix)); - } - } - - return result; - } - - /** - * Returns the two prefixes that comprise the given prefix. - * - * <p>For example, for the prefix 192.0.2.0/24, this will return the two prefixes that combined - * make up the current prefix: - * - * <ul> - * <li>192.0.2.0/25 - * <li>192.0.2.128/25 - * </ul> - */ - private static List<IpPrefix> getSubsetPrefixes(IpPrefix prefix) { - final List<IpPrefix> result = new ArrayList<>(); - - final int currentPrefixLen = prefix.getPrefixLength(); - result.add(new IpPrefix(prefix.getAddress(), currentPrefixLen + 1)); - - final byte[] other = prefix.getRawAddress(); - other[currentPrefixLen / 8] = - (byte) (other[currentPrefixLen / 8] ^ (0x80 >> (currentPrefixLen % 8))); - result.add(new IpPrefix(getAsInetAddress(other), currentPrefixLen + 1)); - - return result; - } - - /** - * Checks if the other IP range is contained within this one - * - * <p>Checks based on byte values. For other to be contained within this IP range, other's - * starting address must be greater or equal to the current IpRange's starting address, and the - * other's ending address must be less than or equal to the current IP range's ending address. - */ - @VisibleForTesting(visibility = Visibility.PRIVATE) - public boolean containsRange(IpRange other) { - return addrToBigInteger(mStartAddr).compareTo(addrToBigInteger(other.mStartAddr)) <= 0 - && addrToBigInteger(mEndAddr).compareTo(addrToBigInteger(other.mEndAddr)) >= 0; - } - - /** - * Checks if the other IP range overlaps with this one - * - * <p>Checks based on byte values. For there to be overlap, this IpRange's starting address must - * be less than the other's ending address, and vice versa. - */ - @VisibleForTesting(visibility = Visibility.PRIVATE) - public boolean overlapsRange(IpRange other) { - return addrToBigInteger(mStartAddr).compareTo(addrToBigInteger(other.mEndAddr)) <= 0 - && addrToBigInteger(other.mStartAddr).compareTo(addrToBigInteger(mEndAddr)) <= 0; - } - - @Override - public int hashCode() { - return Objects.hash(Arrays.hashCode(mStartAddr), Arrays.hashCode(mEndAddr)); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof IpRange)) { - return false; - } - - final IpRange other = (IpRange) obj; - return Arrays.equals(mStartAddr, other.mStartAddr) - && Arrays.equals(mEndAddr, other.mEndAddr); - } - - /** Gets the InetAddress in BigInteger form */ - private static BigInteger addrToBigInteger(byte[] addr) { - // Since addr.getAddress() returns network byte order (big-endian), it is compatible with - // the BigInteger constructor (which assumes big-endian). - return new BigInteger(SIGNUM_POSITIVE, addr); - } -} diff --git a/common/framework/com/android/net/module/util/IpUtils.java b/common/framework/com/android/net/module/util/IpUtils.java deleted file mode 100644 index 18d96f30..00000000 --- a/common/framework/com/android/net/module/util/IpUtils.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2015 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; - -import com.android.internal.annotations.VisibleForTesting; - -import static android.system.OsConstants.IPPROTO_ICMPV6; -import static android.system.OsConstants.IPPROTO_TCP; -import static android.system.OsConstants.IPPROTO_UDP; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.nio.ShortBuffer; - -/** - * @hide - */ -public class IpUtils { - /** - * Converts a signed short value to an unsigned int value. Needed - * because Java does not have unsigned types. - */ - private static int intAbs(short v) { - return v & 0xFFFF; - } - - /** - * Performs an IP checksum (used in IP header and across UDP - * payload) or ICMP checksum on the specified portion of a ByteBuffer. The seed - * allows the checksum to commence with a specified value. - */ - @VisibleForTesting - public static int checksum(ByteBuffer buf, int seed, int start, int end) { - int sum = seed + 0xFFFF; // to make things work with empty / zero-filled buffer - final int bufPosition = buf.position(); - - // set position of original ByteBuffer, so that the ShortBuffer - // will be correctly initialized - buf.position(start); - ShortBuffer shortBuf = buf.asShortBuffer(); - - // re-set ByteBuffer position - buf.position(bufPosition); - - final int numShorts = (end - start) / 2; - for (int i = 0; i < numShorts; i++) { - sum += intAbs(shortBuf.get(i)); - } - start += numShorts * 2; - - // see if a singleton byte remains - if (end != start) { - short b = buf.get(start); - - // make it unsigned - if (b < 0) { - b += 256; - } - - sum += b * 256; // assumes bytebuffer is network order (ie. big endian) - } - - sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF); // max sum is 0x1FFFE - sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF); // max sum is 0xFFFF - return sum ^ 0xFFFF; // u16 bitwise negation - } - - private static int pseudoChecksumIPv4( - ByteBuffer buf, int headerOffset, int protocol, int transportLen) { - int partial = protocol + transportLen; - partial += intAbs(buf.getShort(headerOffset + 12)); - partial += intAbs(buf.getShort(headerOffset + 14)); - partial += intAbs(buf.getShort(headerOffset + 16)); - partial += intAbs(buf.getShort(headerOffset + 18)); - return partial; - } - - private static int pseudoChecksumIPv6( - ByteBuffer buf, int headerOffset, int protocol, int transportLen) { - int partial = protocol + transportLen; - for (int offset = 8; offset < 40; offset += 2) { - partial += intAbs(buf.getShort(headerOffset + offset)); - } - return partial; - } - - private static byte ipversion(ByteBuffer buf, int headerOffset) { - return (byte) ((buf.get(headerOffset) & (byte) 0xf0) >> 4); - } - - public static short ipChecksum(ByteBuffer buf, int headerOffset) { - byte ihl = (byte) (buf.get(headerOffset) & 0x0f); - return (short) checksum(buf, 0, headerOffset, headerOffset + ihl * 4); - } - - private static short transportChecksum(ByteBuffer buf, int protocol, - int ipOffset, int transportOffset, int transportLen) { - if (transportLen < 0) { - throw new IllegalArgumentException("Transport length < 0: " + transportLen); - } - int sum; - byte ver = ipversion(buf, ipOffset); - if (ver == 4) { - sum = pseudoChecksumIPv4(buf, ipOffset, protocol, transportLen); - } else if (ver == 6) { - sum = pseudoChecksumIPv6(buf, ipOffset, protocol, transportLen); - } else { - throw new UnsupportedOperationException("Checksum must be IPv4 or IPv6"); - } - - sum = checksum(buf, sum, transportOffset, transportOffset + transportLen); - if (protocol == IPPROTO_UDP && sum == 0) { - sum = (short) 0xffff; - } - return (short) sum; - } - - /** - * Calculate the UDP checksum for an UDP packet. - */ - public static short udpChecksum(ByteBuffer buf, int ipOffset, int transportOffset) { - int transportLen = intAbs(buf.getShort(transportOffset + 4)); - return transportChecksum(buf, IPPROTO_UDP, ipOffset, transportOffset, transportLen); - } - - /** - * Calculate the TCP checksum for a TCP packet. - */ - public static short tcpChecksum(ByteBuffer buf, int ipOffset, int transportOffset, - int transportLen) { - return transportChecksum(buf, IPPROTO_TCP, ipOffset, transportOffset, transportLen); - } - - /** - * Calculate the ICMP checksum for an ICMPv4 packet. - */ - public static short icmpChecksum(ByteBuffer buf, int transportOffset, int transportLen) { - // ICMP checksum doesn't include pseudo-header. See RFC 792. - return (short) checksum(buf, 0, transportOffset, transportOffset + transportLen); - } - - /** - * Calculate the ICMPv6 checksum for an ICMPv6 packet. - */ - public static short icmpv6Checksum(ByteBuffer buf, int ipOffset, int transportOffset, - int transportLen) { - return transportChecksum(buf, IPPROTO_ICMPV6, ipOffset, transportOffset, transportLen); - } - - public static String addressAndPortToString(InetAddress address, int port) { - return String.format( - (address instanceof Inet6Address) ? "[%s]:%d" : "%s:%d", - address.getHostAddress(), port); - } - - public static boolean isValidUdpOrTcpPort(int port) { - return port > 0 && port < 65536; - } -} diff --git a/common/framework/com/android/net/module/util/LinkPropertiesUtils.java b/common/framework/com/android/net/module/util/LinkPropertiesUtils.java deleted file mode 100644 index e271f649..00000000 --- a/common/framework/com/android/net/module/util/LinkPropertiesUtils.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.RouteInfo; -import android.text.TextUtils; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; - -/** - * Collection of link properties utilities. - * @hide - */ -public final class LinkPropertiesUtils { - - /** - * @param <T> The type of data to compare. - */ - public static class CompareResult<T> { - public final List<T> removed = new ArrayList<>(); - public final List<T> added = new ArrayList<>(); - - public CompareResult() {} - - public CompareResult(@Nullable Collection<T> oldItems, @Nullable Collection<T> newItems) { - if (oldItems != null) { - removed.addAll(oldItems); - } - if (newItems != null) { - for (T newItem : newItems) { - if (!removed.remove(newItem)) { - added.add(newItem); - } - } - } - } - - @Override - public String toString() { - return "removed=[" + TextUtils.join(",", removed) - + "] added=[" + TextUtils.join(",", added) - + "]"; - } - } - - /** - * Generic class to compare two lists of items of type {@code T} whose properties can change. - * The items to be compared must provide a way to calculate a corresponding key of type - * {@code K} such that if (and only if) an old and a new item have the same key, then the new - * item is an update of the old item. Both the old list and the new list may not contain more - * than one item with the same key, and may not contain any null items. - * - * @param <K> A class that represents the key of the items to be compared. - * @param <T> The class that represents the object to be compared. - */ - public static class CompareOrUpdateResult<K, T> { - public final List<T> added = new ArrayList<>(); - public final List<T> removed = new ArrayList<>(); - public final List<T> updated = new ArrayList<>(); - - /** - * Compares two lists of items. - * @param oldItems the old list of items. - * @param newItems the new list of items. - * @param keyCalculator a {@link Function} that calculates an item's key. - */ - public CompareOrUpdateResult(Collection<T> oldItems, Collection<T> newItems, - Function<T, K> keyCalculator) { - HashMap<K, T> updateTracker = new HashMap<>(); - - if (oldItems != null) { - for (T oldItem : oldItems) { - updateTracker.put(keyCalculator.apply(oldItem), oldItem); - } - } - - if (newItems != null) { - for (T newItem : newItems) { - T oldItem = updateTracker.remove(keyCalculator.apply(newItem)); - if (oldItem != null) { - if (!oldItem.equals(newItem)) { - // Update of existing item. - updated.add(newItem); - } - } else { - // New item. - added.add(newItem); - } - } - } - - removed.addAll(updateTracker.values()); - } - - @Override - public String toString() { - return "removed=[" + TextUtils.join(",", removed) - + "] added=[" + TextUtils.join(",", added) - + "] updated=[" + TextUtils.join(",", updated) - + "]"; - } - } - - /** - * Compares the addresses in {@code left} LinkProperties with {@code right} - * LinkProperties, examining only addresses on the base link. - * - * @param left A LinkProperties with the old list of addresses. - * @param right A LinkProperties with the new list of addresses. - * @return the differences between the addresses. - */ - public static @NonNull CompareResult<LinkAddress> compareAddresses( - @Nullable LinkProperties left, @Nullable LinkProperties right) { - /* - * Duplicate the LinkAddresses into removed, we will be removing - * address which are common between mLinkAddresses and target - * leaving the addresses that are different. And address which - * are in target but not in mLinkAddresses are placed in the - * addedAddresses. - */ - return new CompareResult<>(left != null ? left.getLinkAddresses() : null, - right != null ? right.getLinkAddresses() : null); - } - - /** - * Compares {@code left} {@code LinkProperties} allLinkAddresses against the {@code right}. - * - * @param left A LinkProperties or null - * @param right A LinkProperties or null - * @return {@code true} if both are identical, {@code false} otherwise. - * @see LinkProperties#getAllLinkAddresses() - */ - public static boolean isIdenticalAllLinkAddresses(@Nullable LinkProperties left, - @Nullable LinkProperties right) { - if (left == right) return true; - if (left == null || right == null) return false; - final List<LinkAddress> leftAddresses = left.getAllLinkAddresses(); - final List<LinkAddress> rightAddresses = right.getAllLinkAddresses(); - if (leftAddresses.size() != rightAddresses.size()) return false; - return leftAddresses.containsAll(rightAddresses); - } - - /** - * Compares {@code left} {@code LinkProperties} interface addresses against the {@code right}. - * - * @param left A LinkProperties. - * @param right LinkProperties to be compared with {@code left}. - * @return {@code true} if both are identical, {@code false} otherwise. - */ - public static boolean isIdenticalAddresses(@NonNull LinkProperties left, - @NonNull LinkProperties right) { - final Collection<InetAddress> leftAddresses = left.getAddresses(); - final Collection<InetAddress> rightAddresses = right.getAddresses(); - return (leftAddresses.size() == rightAddresses.size()) - ? leftAddresses.containsAll(rightAddresses) : false; - } - - /** - * Compares {@code left} {@code LinkProperties} DNS addresses against the {@code right}. - * - * @param left A LinkProperties. - * @param right A LinkProperties to be compared with {@code left}. - * @return {@code true} if both are identical, {@code false} otherwise. - */ - public static boolean isIdenticalDnses(@NonNull LinkProperties left, - @NonNull LinkProperties right) { - final Collection<InetAddress> leftDnses = left.getDnsServers(); - final Collection<InetAddress> rightDnses = right.getDnsServers(); - - final String leftDomains = left.getDomains(); - final String rightDomains = right.getDomains(); - if (leftDomains == null) { - if (rightDomains != null) return false; - } else { - if (!leftDomains.equals(rightDomains)) return false; - } - return (leftDnses.size() == rightDnses.size()) - ? leftDnses.containsAll(rightDnses) : false; - } - - /** - * Compares {@code left} {@code LinkProperties} HttpProxy against the {@code right}. - * - * @param left A LinkProperties. - * @param right A LinkProperties to be compared with {@code left}. - * @return {@code true} if both are identical, {@code false} otherwise. - */ - public static boolean isIdenticalHttpProxy(@NonNull LinkProperties left, - @NonNull LinkProperties right) { - return Objects.equals(left.getHttpProxy(), right.getHttpProxy()); - } - - /** - * Compares {@code left} {@code LinkProperties} interface name against the {@code right}. - * - * @param left A LinkProperties. - * @param right A LinkProperties to be compared with {@code left}. - * @return {@code true} if both are identical, {@code false} otherwise. - */ - public static boolean isIdenticalInterfaceName(@NonNull LinkProperties left, - @NonNull LinkProperties right) { - return TextUtils.equals(left.getInterfaceName(), right.getInterfaceName()); - } - - /** - * Compares {@code left} {@code LinkProperties} Routes against the {@code right}. - * - * @param left A LinkProperties. - * @param right A LinkProperties to be compared with {@code left}. - * @return {@code true} if both are identical, {@code false} otherwise. - */ - public static boolean isIdenticalRoutes(@NonNull LinkProperties left, - @NonNull LinkProperties right) { - final Collection<RouteInfo> leftRoutes = left.getRoutes(); - final Collection<RouteInfo> rightRoutes = right.getRoutes(); - return (leftRoutes.size() == rightRoutes.size()) - ? leftRoutes.containsAll(rightRoutes) : false; - } -} diff --git a/common/framework/com/android/net/module/util/LocationPermissionChecker.java b/common/framework/com/android/net/module/util/LocationPermissionChecker.java deleted file mode 100644 index cd1f31cb..00000000 --- a/common/framework/com/android/net/module/util/LocationPermissionChecker.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import android.Manifest; -import android.annotation.IntDef; -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.net.NetworkStack; -import android.os.Binder; -import android.os.Build; -import android.os.UserHandle; -import android.util.Log; - -import androidx.annotation.RequiresApi; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - - -/** - * The methods used for location permission and location mode checking. - * - * @hide - */ -@RequiresApi(Build.VERSION_CODES.R) -public class LocationPermissionChecker { - - private static final String TAG = "LocationPermissionChecker"; - - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"LOCATION_PERMISSION_CHECK_STATUS_"}, value = { - SUCCEEDED, - ERROR_LOCATION_MODE_OFF, - ERROR_LOCATION_PERMISSION_MISSING, - }) - public @interface LocationPermissionCheckStatus{} - - // The location permission check succeeded. - public static final int SUCCEEDED = 0; - // The location mode turns off for the caller. - public static final int ERROR_LOCATION_MODE_OFF = 1; - // The location permission isn't granted for the caller. - public static final int ERROR_LOCATION_PERMISSION_MISSING = 2; - - private final Context mContext; - private final AppOpsManager mAppOpsManager; - - public LocationPermissionChecker(Context context) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - throw new UnsupportedOperationException("This utility is not supported before R"); - } - - mContext = context; - mAppOpsManager = mContext.getSystemService(AppOpsManager.class); - } - - /** - * Check location permission granted by the caller. - * - * This API check if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - * - * @return {@code true} returns if the caller has location permission and the location mode is - * enabled. - */ - public boolean checkLocationPermission(String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - return checkLocationPermissionInternal(pkgName, featureId, uid, message) == SUCCEEDED; - } - - /** - * Check location permission granted by the caller. - * - * This API check if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * Compared with {@link #checkLocationPermission(String, String, int, String)}, this API returns - * the detail information about the checking result, including the reason why it's failed and - * logs the error for the caller. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - * - * @return {@link LocationPermissionCheckStatus} the result of the location permission check. - */ - public @LocationPermissionCheckStatus int checkLocationPermissionWithDetailInfo( - String pkgName, @Nullable String featureId, int uid, @Nullable String message) { - final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); - switch (result) { - case ERROR_LOCATION_MODE_OFF: - Log.e(TAG, "Location mode is disabled for the device"); - break; - case ERROR_LOCATION_PERMISSION_MISSING: - Log.e(TAG, "UID " + uid + " has no location permission"); - break; - } - return result; - } - - /** - * Enforce the caller has location permission. - * - * This API determines if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * SecurityException is thrown if the caller has no permission or the location mode is disabled. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid, - @Nullable String message) throws SecurityException { - final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); - - switch (result) { - case ERROR_LOCATION_MODE_OFF: - throw new SecurityException("Location mode is disabled for the device"); - case ERROR_LOCATION_PERMISSION_MISSING: - throw new SecurityException("UID " + uid + " has no location permission"); - } - } - - private int checkLocationPermissionInternal(String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - checkPackage(uid, pkgName); - - // Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_STACK & MAINLINE_NETWORK_STACK - // are granted a bypass. - if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid) - || checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid)) { - return SUCCEEDED; - } - - // Location mode must be enabled - if (!isLocationModeEnabled()) { - return ERROR_LOCATION_MODE_OFF; - } - - // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to - // location information. - if (!checkCallersLocationPermission(pkgName, featureId, uid, - true /* coarseForTargetSdkLessThanQ */, message)) { - return ERROR_LOCATION_PERMISSION_MISSING; - } - return SUCCEEDED; - } - - /** - * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION or - * android.Manifest.permission.ACCESS_COARSE_LOCATION (depending on config/targetSDK level) - * and a corresponding app op is allowed for this package and uid. - * - * @param pkgName PackageName of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param coarseForTargetSdkLessThanQ If true and the targetSDK < Q then will check for COARSE - * else (false or targetSDK >= Q) then will check for FINE - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId, - int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) { - - boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid); - - String permissionType = Manifest.permission.ACCESS_FINE_LOCATION; - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - // Having FINE permission implies having COARSE permission (but not the reverse) - permissionType = Manifest.permission.ACCESS_COARSE_LOCATION; - } - if (getUidPermission(permissionType, uid) == PackageManager.PERMISSION_DENIED) { - return false; - } - - // Always checking FINE - even if will not enforce. This will record the request for FINE - // so that a location request by the app is surfaced to the user. - boolean isFineLocationAllowed = noteAppOpAllowed( - AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, message); - if (isFineLocationAllowed) { - return true; - } - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - return noteAppOpAllowed(AppOpsManager.OPSTR_COARSE_LOCATION, pkgName, featureId, uid, - message); - } - return false; - } - - /** - * Retrieves a handle to LocationManager (if not already done) and check if location is enabled. - */ - public boolean isLocationModeEnabled() { - final LocationManager LocationManager = mContext.getSystemService(LocationManager.class); - try { - return LocationManager.isLocationEnabledForUser(UserHandle.of( - getCurrentUser())); - } catch (Exception e) { - Log.e(TAG, "Failure to get location mode via API, falling back to settings", e); - return false; - } - } - - private boolean isTargetSdkLessThan(String packageName, int versionCode, int callingUid) { - final long ident = Binder.clearCallingIdentity(); - try { - if (mContext.getPackageManager().getApplicationInfoAsUser( - packageName, 0, - UserHandle.getUserHandleForUid(callingUid)).targetSdkVersion - < versionCode) { - return true; - } - } catch (PackageManager.NameNotFoundException e) { - // In case of exception, assume unknown app (more strict checking) - // Note: This case will never happen since checkPackage is - // called to verify validity before checking App's version. - } finally { - Binder.restoreCallingIdentity(ident); - } - return false; - } - - private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - return mAppOpsManager.noteOp(op, uid, pkgName, featureId, message) - == AppOpsManager.MODE_ALLOWED; - } - - private void checkPackage(int uid, String pkgName) - throws SecurityException { - if (pkgName == null) { - throw new SecurityException("Checking UID " + uid + " but Package Name is Null"); - } - mAppOpsManager.checkPackage(uid, pkgName); - } - - @VisibleForTesting - protected int getCurrentUser() { - return ActivityManager.getCurrentUser(); - } - - private int getUidPermission(String permissionType, int uid) { - // We don't care about pid, pass in -1 - return mContext.checkPermission(permissionType, -1, uid); - } - - /** - * Returns true if the |uid| holds NETWORK_SETTINGS permission. - */ - public boolean checkNetworkSettingsPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_SETTINGS, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission. - */ - public boolean checkNetworkSetupWizardPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_STACK permission. - */ - public boolean checkNetworkStackPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission. - */ - public boolean checkMainlineNetworkStackPermission(int uid) { - return getUidPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - -} diff --git a/common/framework/com/android/net/module/util/MacAddressUtils.java b/common/framework/com/android/net/module/util/MacAddressUtils.java deleted file mode 100644 index ab0040c0..00000000 --- a/common/framework/com/android/net/module/util/MacAddressUtils.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 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; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.MacAddress; - -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.Objects; -import java.util.Random; - -/** - * Collection of MAC address utilities. - * @hide - */ -public final class MacAddressUtils { - - private static final long VALID_LONG_MASK = (1L << 48) - 1; - private static final long LOCALLY_ASSIGNED_MASK = longAddrFromByteAddr( - MacAddress.fromString("2:0:0:0:0:0").toByteArray()); - private static final long MULTICAST_MASK = longAddrFromByteAddr( - MacAddress.fromString("1:0:0:0:0:0").toByteArray()); - private static final long OUI_MASK = longAddrFromByteAddr( - MacAddress.fromString("ff:ff:ff:0:0:0").toByteArray()); - private static final long NIC_MASK = longAddrFromByteAddr( - MacAddress.fromString("0:0:0:ff:ff:ff").toByteArray()); - // Matches WifiInfo.DEFAULT_MAC_ADDRESS - private static final MacAddress DEFAULT_MAC_ADDRESS = - MacAddress.fromString("02:00:00:00:00:00"); - private static final int ETHER_ADDR_LEN = 6; - - /** - * @return true if this MacAddress is a multicast address. - */ - public static boolean isMulticastAddress(@NonNull MacAddress address) { - return (longAddrFromByteAddr(address.toByteArray()) & MULTICAST_MASK) != 0; - } - - /** - * Returns a generated MAC address whose 46 bits, excluding the locally assigned bit and the - * unicast bit, are randomly selected. - * - * The locally assigned bit is always set to 1. The multicast bit is always set to 0. - * - * @return a random locally assigned, unicast MacAddress. - */ - public static @NonNull MacAddress createRandomUnicastAddress() { - return createRandomUnicastAddress(null, new SecureRandom()); - } - - /** - * Returns a randomly generated MAC address using the given Random object and the same - * OUI values as the given MacAddress. - * - * The locally assigned bit is always set to 1. The multicast bit is always set to 0. - * - * @param base a base MacAddress whose OUI is used for generating the random address. - * If base == null then the OUI will also be randomized. - * @param r a standard Java Random object used for generating the random address. - * @return a random locally assigned MacAddress. - */ - public static @NonNull MacAddress createRandomUnicastAddress(@Nullable MacAddress base, - @NonNull Random r) { - long addr; - - if (base == null) { - addr = r.nextLong() & VALID_LONG_MASK; - } else { - addr = (longAddrFromByteAddr(base.toByteArray()) & OUI_MASK) - | (NIC_MASK & r.nextLong()); - } - addr |= LOCALLY_ASSIGNED_MASK; - addr &= ~MULTICAST_MASK; - MacAddress mac = MacAddress.fromBytes(byteAddrFromLongAddr(addr)); - if (mac.equals(DEFAULT_MAC_ADDRESS)) { - return createRandomUnicastAddress(base, r); - } - return mac; - } - - /** - * Convert a byte address to long address. - */ - public static long longAddrFromByteAddr(byte[] addr) { - Objects.requireNonNull(addr); - if (!isMacAddress(addr)) { - throw new IllegalArgumentException( - Arrays.toString(addr) + " was not a valid MAC address"); - } - long longAddr = 0; - for (byte b : addr) { - final int uint8Byte = b & 0xff; - longAddr = (longAddr << 8) + uint8Byte; - } - return longAddr; - } - - /** - * Convert a long address to byte address. - */ - public static byte[] byteAddrFromLongAddr(long addr) { - byte[] bytes = new byte[ETHER_ADDR_LEN]; - int index = ETHER_ADDR_LEN; - while (index-- > 0) { - bytes[index] = (byte) addr; - addr = addr >> 8; - } - return bytes; - } - - /** - * Returns true if the given byte array is a valid MAC address. - * A valid byte array representation for a MacAddress is a non-null array of length 6. - * - * @param addr a byte array. - * @return true if the given byte array is not null and has the length of a MAC address. - * - */ - public static boolean isMacAddress(byte[] addr) { - return addr != null && addr.length == ETHER_ADDR_LEN; - } -} diff --git a/common/framework/com/android/net/module/util/NetUtils.java b/common/framework/com/android/net/module/util/NetUtils.java deleted file mode 100644 index ae1b9bbc..00000000 --- a/common/framework/com/android/net/module/util/NetUtils.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 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; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.RouteInfo; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Collection; - -/** - * Collection of network common utilities. - * @hide - */ -public final class NetUtils { - - /** - * Check if IP address type is consistent between two InetAddress. - * @return true if both are the same type. False otherwise. - */ - public static boolean addressTypeMatches(@NonNull InetAddress left, - @NonNull InetAddress right) { - return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) - || ((left instanceof Inet6Address) && (right instanceof Inet6Address))); - } - - /** - * Find the route from a Collection of routes that best matches a given address. - * May return null if no routes are applicable, or the best route is not a route of - * {@link RouteInfo.RTN_UNICAST} type. - * - * @param routes a Collection of RouteInfos to chose from - * @param dest the InetAddress your trying to get to - * @return the RouteInfo from the Collection that best fits the given address - */ - @Nullable - public static RouteInfo selectBestRoute(@Nullable Collection<RouteInfo> routes, - @Nullable InetAddress dest) { - if ((routes == null) || (dest == null)) return null; - - RouteInfo bestRoute = null; - - // pick a longest prefix match under same address type - for (RouteInfo route : routes) { - if (addressTypeMatches(route.getDestination().getAddress(), dest)) { - if ((bestRoute != null) - && (bestRoute.getDestination().getPrefixLength() - >= route.getDestination().getPrefixLength())) { - continue; - } - if (route.matches(dest)) bestRoute = route; - } - } - - if (bestRoute != null && bestRoute.getType() == RouteInfo.RTN_UNICAST) { - return bestRoute; - } else { - return null; - } - } - - /** - * Get InetAddress masked with prefixLength. Will never return null. - * @param address the IP address to mask with - * @param prefixLength the prefixLength used to mask the IP - */ - public static InetAddress getNetworkPart(InetAddress address, int prefixLength) { - byte[] array = address.getAddress(); - maskRawAddress(array, prefixLength); - - InetAddress netPart = null; - try { - netPart = InetAddress.getByAddress(array); - } catch (UnknownHostException e) { - throw new RuntimeException("getNetworkPart error - " + e.toString()); - } - return netPart; - } - - /** - * Masks a raw IP address byte array with the specified prefix length. - */ - public static void maskRawAddress(byte[] array, int prefixLength) { - if (prefixLength < 0 || prefixLength > array.length * 8) { - throw new RuntimeException("IP address with " + array.length - + " bytes has invalid prefix length " + prefixLength); - } - - int offset = prefixLength / 8; - int remainder = prefixLength % 8; - byte mask = (byte) (0xFF << (8 - remainder)); - - if (offset < array.length) array[offset] = (byte) (array[offset] & mask); - - offset++; - - for (; offset < array.length; offset++) { - array[offset] = 0; - } - } -} diff --git a/common/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java b/common/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java deleted file mode 100644 index 54ce01ec..00000000 --- a/common/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA; -import static android.net.NetworkCapabilities.NET_CAPABILITY_IA; -import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_MCX; -import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_MMTEL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM; -import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; -import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP; -import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; -import static android.net.NetworkCapabilities.TRANSPORT_USB; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; - -import static com.android.net.module.util.BitUtils.packBitList; -import static com.android.net.module.util.BitUtils.unpackBits; - -import android.annotation.NonNull; -import android.net.NetworkCapabilities; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * Utilities to examine {@link android.net.NetworkCapabilities}. - * @hide - */ -public final class NetworkCapabilitiesUtils { - // Transports considered to classify networks in UI, in order of which transport should be - // surfaced when there are multiple transports. Transports not in this list do not have - // an ordering preference (in practice they will have a deterministic order based on the - // transport int itself). - private static final int[] DISPLAY_TRANSPORT_PRIORITIES = new int[] { - // Users think of their VPNs as VPNs, not as any of the underlying nets - TRANSPORT_VPN, - // If the network has cell, prefer showing that because it's usually metered. - TRANSPORT_CELLULAR, - // If the network has WiFi aware, prefer showing that as it's a more specific use case. - // Ethernet can masquerade as other transports, where the device uses ethernet to connect to - // a box providing cell or wifi. Today this is represented by only the masqueraded type for - // backward compatibility, but these networks should morally have Ethernet & the masqueraded - // type. Because of this, prefer other transports instead of Ethernet. - TRANSPORT_WIFI_AWARE, - TRANSPORT_BLUETOOTH, - TRANSPORT_WIFI, - TRANSPORT_ETHERNET, - TRANSPORT_USB - - // Notably, TRANSPORT_TEST is not in this list as any network that has TRANSPORT_TEST and - // one of the above transports should be counted as that transport, to keep tests as - // realistic as possible. - }; - - /** - * Capabilities that suggest that a network is restricted. - * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted}, - * and {@code FORCE_RESTRICTED_CAPABILITIES}. - */ - @VisibleForTesting - public static final long RESTRICTED_CAPABILITIES = packBitList( - NET_CAPABILITY_BIP, - NET_CAPABILITY_CBS, - NET_CAPABILITY_DUN, - NET_CAPABILITY_EIMS, - NET_CAPABILITY_ENTERPRISE, - NET_CAPABILITY_FOTA, - NET_CAPABILITY_IA, - NET_CAPABILITY_IMS, - NET_CAPABILITY_MCX, - NET_CAPABILITY_RCS, - NET_CAPABILITY_VEHICLE_INTERNAL, - NET_CAPABILITY_VSIM, - NET_CAPABILITY_XCAP, - NET_CAPABILITY_MMTEL); - - /** - * Capabilities that force network to be restricted. - * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted}. - */ - private static final long FORCE_RESTRICTED_CAPABILITIES = packBitList( - NET_CAPABILITY_ENTERPRISE, - NET_CAPABILITY_OEM_PAID, - NET_CAPABILITY_OEM_PRIVATE); - - /** - * Capabilities that suggest that a network is unrestricted. - * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted}. - */ - @VisibleForTesting - public static final long UNRESTRICTED_CAPABILITIES = packBitList( - NET_CAPABILITY_INTERNET, - NET_CAPABILITY_MMS, - NET_CAPABILITY_SUPL, - NET_CAPABILITY_WIFI_P2P); - - /** - * Get a transport that can be used to classify a network when displaying its info to users. - * - * While networks can have multiple transports, users generally think of them as "wifi", - * "mobile data", "vpn" and expect them to be classified as such in UI such as settings. - * @param transports Non-empty array of transports on a network - * @return A single transport - * @throws IllegalArgumentException The array is empty - */ - public static int getDisplayTransport(@NonNull int[] transports) { - for (int transport : DISPLAY_TRANSPORT_PRIORITIES) { - if (CollectionUtils.contains(transports, transport)) { - return transport; - } - } - - if (transports.length < 1) { - // All NetworkCapabilities representing a network have at least one transport, so an - // empty transport array would be created by the caller instead of extracted from - // NetworkCapabilities. - throw new IllegalArgumentException("No transport in the provided array"); - } - return transports[0]; - } - - - /** - * Infers that all the capabilities it provides are typically provided by restricted networks - * or not. - * - * @param nc the {@link NetworkCapabilities} to infer the restricted capabilities. - * - * @return {@code true} if the network should be restricted. - */ - // TODO: Use packBits(nc.getCapabilities()) to check more easily using bit masks. - public static boolean inferRestrictedCapability(NetworkCapabilities nc) { - // Check if we have any capability that forces the network to be restricted. - for (int capability : unpackBits(FORCE_RESTRICTED_CAPABILITIES)) { - if (nc.hasCapability(capability)) { - return true; - } - } - - // Verify there aren't any unrestricted capabilities. If there are we say - // the whole thing is unrestricted unless it is forced to be restricted. - for (int capability : unpackBits(UNRESTRICTED_CAPABILITIES)) { - if (nc.hasCapability(capability)) { - return false; - } - } - - // Must have at least some restricted capabilities. - for (int capability : unpackBits(RESTRICTED_CAPABILITIES)) { - if (nc.hasCapability(capability)) { - return true; - } - } - return false; - } - -} diff --git a/common/framework/com/android/net/module/util/NetworkIdentityUtils.java b/common/framework/com/android/net/module/util/NetworkIdentityUtils.java deleted file mode 100644 index b641753c..00000000 --- a/common/framework/com/android/net/module/util/NetworkIdentityUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2021 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; - -import android.annotation.NonNull; -import android.annotation.Nullable; - -/** - * Utilities to examine {@link android.net.NetworkIdentity}. - * @hide - */ -public class NetworkIdentityUtils { - /** - * Scrub given IMSI on production builds. - */ - @NonNull - public static String scrubSubscriberId(@Nullable String subscriberId) { - if (subscriberId != null) { - // TODO: parse this as MCC+MNC instead of hard-coding - return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "..."; - } else { - return "null"; - } - } - - /** - * Scrub given IMSI on production builds. - */ - @Nullable - public static String[] scrubSubscriberIds(@Nullable String[] subscriberIds) { - if (subscriberIds == null) return null; - final String[] res = new String[subscriberIds.length]; - for (int i = 0; i < res.length; i++) { - res[i] = scrubSubscriberId(subscriberIds[i]); - } - return res; - } -} diff --git a/common/framework/com/android/net/module/util/NetworkStackConstants.java b/common/framework/com/android/net/module/util/NetworkStackConstants.java deleted file mode 100644 index 91491605..00000000 --- a/common/framework/com/android/net/module/util/NetworkStackConstants.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import android.net.InetAddresses; -import android.net.IpPrefix; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Network constants used by the network stack. - * @hide - */ -public final class NetworkStackConstants { - - /** - * Ethernet constants. - * - * See also: - * - https://tools.ietf.org/html/rfc894 - * - https://tools.ietf.org/html/rfc2464 - * - https://tools.ietf.org/html/rfc7042 - * - http://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml - * - http://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml - */ - public static final int ETHER_DST_ADDR_OFFSET = 0; - public static final int ETHER_SRC_ADDR_OFFSET = 6; - public static final int ETHER_ADDR_LEN = 6; - public static final int ETHER_TYPE_OFFSET = 12; - public static final int ETHER_TYPE_LENGTH = 2; - public static final int ETHER_TYPE_ARP = 0x0806; - public static final int ETHER_TYPE_IPV4 = 0x0800; - public static final int ETHER_TYPE_IPV6 = 0x86dd; - public static final int ETHER_HEADER_LEN = 14; - public static final int ETHER_MTU = 1500; - public static final byte[] ETHER_BROADCAST = new byte[] { - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - }; - - /** - * ARP constants. - * - * See also: - * - https://tools.ietf.org/html/rfc826 - * - http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml - */ - public static final int ARP_PAYLOAD_LEN = 28; // For Ethernet+IPv4. - public static final int ARP_ETHER_IPV4_LEN = ARP_PAYLOAD_LEN + ETHER_HEADER_LEN; - public static final int ARP_REQUEST = 1; - public static final int ARP_REPLY = 2; - public static final int ARP_HWTYPE_RESERVED_LO = 0; - public static final int ARP_HWTYPE_ETHER = 1; - public static final int ARP_HWTYPE_RESERVED_HI = 0xffff; - - /** - * IPv4 Address Conflict Detection constants. - * - * See also: - * - https://tools.ietf.org/html/rfc5227 - */ - public static final int IPV4_CONFLICT_PROBE_NUM = 3; - public static final int IPV4_CONFLICT_ANNOUNCE_NUM = 2; - - /** - * IPv4 constants. - * - * See also: - * - https://tools.ietf.org/html/rfc791 - */ - public static final int IPV4_ADDR_BITS = 32; - public static final int IPV4_MIN_MTU = 68; - public static final int IPV4_MAX_MTU = 65_535; - public static final int IPV4_HEADER_MIN_LEN = 20; - public static final int IPV4_IHL_MASK = 0xf; - public static final int IPV4_LENGTH_OFFSET = 2; - public static final int IPV4_FLAGS_OFFSET = 6; - public static final int IPV4_FRAGMENT_MASK = 0x1fff; - public static final int IPV4_PROTOCOL_OFFSET = 9; - public static final int IPV4_CHECKSUM_OFFSET = 10; - public static final int IPV4_SRC_ADDR_OFFSET = 12; - public static final int IPV4_DST_ADDR_OFFSET = 16; - public static final int IPV4_ADDR_LEN = 4; - public static final int IPV4_FLAG_MF = 0x2000; - public static final int IPV4_FLAG_DF = 0x4000; - // getSockOpt() for v4 MTU - public static final int IP_MTU = 14; - public static final Inet4Address IPV4_ADDR_ALL = makeInet4Address( - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff); - public static final Inet4Address IPV4_ADDR_ANY = makeInet4Address( - (byte) 0, (byte) 0, (byte) 0, (byte) 0); - public static final Inet6Address IPV6_ADDR_ANY = makeInet6Address(new byte[]{ - (byte) 0, (byte) 0, (byte) 0, (byte) 0, - (byte) 0, (byte) 0, (byte) 0, (byte) 0, - (byte) 0, (byte) 0, (byte) 0, (byte) 0, - (byte) 0, (byte) 0, (byte) 0, (byte) 0 }); - - /** - * CLAT constants - */ - public static final IpPrefix CLAT_PREFIX = new IpPrefix("192.0.0.0/29"); - - /** - * IPv6 constants. - * - * See also: - * - https://tools.ietf.org/html/rfc2460 - */ - public static final int IPV6_ADDR_LEN = 16; - public static final int IPV6_HEADER_LEN = 40; - public static final int IPV6_LEN_OFFSET = 4; - public static final int IPV6_PROTOCOL_OFFSET = 6; - public static final int IPV6_SRC_ADDR_OFFSET = 8; - public static final int IPV6_DST_ADDR_OFFSET = 24; - public static final int IPV6_MIN_MTU = 1280; - public static final int IPV6_FRAGMENT_HEADER_LEN = 8; - public static final int RFC7421_PREFIX_LENGTH = 64; - // getSockOpt() for v6 MTU - public static final int IPV6_MTU = 24; - public static final Inet6Address IPV6_ADDR_ALL_NODES_MULTICAST = - (Inet6Address) InetAddresses.parseNumericAddress("ff02::1"); - public static final Inet6Address IPV6_ADDR_ALL_ROUTERS_MULTICAST = - (Inet6Address) InetAddresses.parseNumericAddress("ff02::2"); - public static final Inet6Address IPV6_ADDR_ALL_HOSTS_MULTICAST = - (Inet6Address) InetAddresses.parseNumericAddress("ff02::3"); - - /** - * ICMP constants. - * - * See also: - * - https://tools.ietf.org/html/rfc792 - */ - public static final int ICMP_CHECKSUM_OFFSET = 2; - public static final int ICMP_HEADER_LEN = 8; - /** - * ICMPv6 constants. - * - * See also: - * - https://tools.ietf.org/html/rfc4191 - * - https://tools.ietf.org/html/rfc4443 - * - https://tools.ietf.org/html/rfc4861 - */ - public static final int ICMPV6_HEADER_MIN_LEN = 4; - public static final int ICMPV6_CHECKSUM_OFFSET = 2; - public static final int ICMPV6_ECHO_REPLY_TYPE = 129; - public static final int ICMPV6_ECHO_REQUEST_TYPE = 128; - public static final int ICMPV6_ROUTER_SOLICITATION = 133; - public static final int ICMPV6_ROUTER_ADVERTISEMENT = 134; - public static final int ICMPV6_NEIGHBOR_SOLICITATION = 135; - public static final int ICMPV6_NEIGHBOR_ADVERTISEMENT = 136; - public static final int ICMPV6_ND_OPTION_MIN_LENGTH = 8; - public static final int ICMPV6_ND_OPTION_LENGTH_SCALING_FACTOR = 8; - public static final int ICMPV6_ND_OPTION_SLLA = 1; - public static final int ICMPV6_ND_OPTION_TLLA = 2; - public static final int ICMPV6_ND_OPTION_PIO = 3; - public static final int ICMPV6_ND_OPTION_MTU = 5; - public static final int ICMPV6_ND_OPTION_RIO = 24; - public static final int ICMPV6_ND_OPTION_RDNSS = 25; - public static final int ICMPV6_ND_OPTION_PREF64 = 38; - - public static final int ICMPV6_RS_HEADER_LEN = 8; - public static final int ICMPV6_RA_HEADER_LEN = 16; - public static final int ICMPV6_NS_HEADER_LEN = 24; - public static final int ICMPV6_NA_HEADER_LEN = 24; - - public static final int NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER = 1 << 31; - public static final int NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED = 1 << 30; - public static final int NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE = 1 << 29; - - public static final byte ROUTER_ADVERTISEMENT_FLAG_MANAGED_ADDRESS = (byte) (1 << 7); - public static final byte ROUTER_ADVERTISEMENT_FLAG_OTHER = (byte) (1 << 6); - - public static final byte PIO_FLAG_ON_LINK = (byte) (1 << 7); - public static final byte PIO_FLAG_AUTONOMOUS = (byte) (1 << 6); - - /** - * TCP constants. - * - * See also: - * - https://tools.ietf.org/html/rfc793 - */ - public static final int TCP_HEADER_MIN_LEN = 20; - public static final int TCP_CHECKSUM_OFFSET = 16; - public static final byte TCPHDR_FIN = (byte) (1 << 0); - public static final byte TCPHDR_SYN = (byte) (1 << 1); - public static final byte TCPHDR_RST = (byte) (1 << 2); - public static final byte TCPHDR_PSH = (byte) (1 << 3); - public static final byte TCPHDR_ACK = (byte) (1 << 4); - public static final byte TCPHDR_URG = (byte) (1 << 5); - - /** - * UDP constants. - * - * See also: - * - https://tools.ietf.org/html/rfc768 - */ - public static final int UDP_HEADER_LEN = 8; - public static final int UDP_SRCPORT_OFFSET = 0; - public static final int UDP_DSTPORT_OFFSET = 2; - public static final int UDP_LENGTH_OFFSET = 4; - public static final int UDP_CHECKSUM_OFFSET = 6; - - /** - * DHCP constants. - * - * See also: - * - https://tools.ietf.org/html/rfc2131 - */ - public static final int INFINITE_LEASE = 0xffffffff; - public static final int DHCP4_CLIENT_PORT = 68; - // The maximum length of a DHCP packet that can be constructed. - public static final int DHCP_MAX_LENGTH = 1500; - public static final int DHCP_MAX_OPTION_LEN = 255; - - /** - * DHCPv6 constants. - * - * See also: - * - https://datatracker.ietf.org/doc/html/rfc8415 - * - https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml - */ - public static final int DHCP6_CLIENT_PORT = 546; - public static final int DHCP6_SERVER_PORT = 547; - public static final Inet6Address ALL_DHCP_RELAY_AGENTS_AND_SERVERS = - (Inet6Address) InetAddresses.parseNumericAddress("ff02::1:2"); - public static final int DHCP6_OPTION_IA_PD = 25; - public static final int DHCP6_OPTION_IAPREFIX = 26; - - /** - * DNS constants. - * - * See also: - * - https://datatracker.ietf.org/doc/html/rfc7858#section-3.1 - */ - public static final short DNS_OVER_TLS_PORT = 853; - - /** - * IEEE802.11 standard constants. - * - * See also: - * - https://ieeexplore.ieee.org/document/7786995 - */ - public static final int VENDOR_SPECIFIC_IE_ID = 0xdd; - - - /** - * TrafficStats constants. - */ - // These tags are used by the network stack to do traffic for its own purposes. Traffic - // tagged with these will be counted toward the network stack and must stay inside the - // range defined by - // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_START} and - // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_END}. - public static final int TAG_SYSTEM_DHCP = 0xFFFFFE01; - public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFE02; - public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFE03; - - // These tags are used by the network stack to do traffic on behalf of apps. Traffic - // tagged with these will be counted toward the app on behalf of which the network - // stack is doing this traffic. These values must stay inside the range defined by - // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_START} and - // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_END}. - public static final int TAG_SYSTEM_PROBE = 0xFFFFFF81; - public static final int TAG_SYSTEM_DNS = 0xFFFFFF82; - - /** - * A test URL used to override configuration settings and overlays for the network validation - * HTTPS URL, when set in {@link android.provider.DeviceConfig} configuration. - * - * <p>This URL will be ignored if the host is not "localhost" (it can only be used to test with - * a local test server), and must not be set in production scenarios (as enforced by CTS tests). - * - * <p>{@link #TEST_URL_EXPIRATION_TIME} must also be set to use this setting. - */ - public static final String TEST_CAPTIVE_PORTAL_HTTPS_URL = "test_captive_portal_https_url"; - /** - * A test URL used to override configuration settings and overlays for the network validation - * HTTP URL, when set in {@link android.provider.DeviceConfig} configuration. - * - * <p>This URL will be ignored if the host is not "localhost" (it can only be used to test with - * a local test server), and must not be set in production scenarios (as enforced by CTS tests). - * - * <p>{@link #TEST_URL_EXPIRATION_TIME} must also be set to use this setting. - */ - public static final String TEST_CAPTIVE_PORTAL_HTTP_URL = "test_captive_portal_http_url"; - /** - * Expiration time of the test URL, in ms, relative to {@link System#currentTimeMillis()}. - * - * <p>After this expiration time, test URLs will be ignored. They will also be ignored if - * the expiration time is more than 10 minutes in the future, to avoid misconfiguration - * following test runs. - */ - public static final String TEST_URL_EXPIRATION_TIME = "test_url_expiration_time"; - - // TODO: Move to Inet4AddressUtils - // See aosp/1455936: NetworkStackConstants can't depend on it as it causes jarjar-related issues - // for users of both the net-utils-device-common and net-utils-framework-common libraries. - // Jarjar rule management needs to be simplified for that: b/170445871 - - /** - * Make an Inet4Address from 4 bytes in network byte order. - */ - private static Inet4Address makeInet4Address(byte b1, byte b2, byte b3, byte b4) { - try { - return (Inet4Address) InetAddress.getByAddress(new byte[] { b1, b2, b3, b4 }); - } catch (UnknownHostException e) { - throw new IllegalArgumentException("addr must be 4 bytes: this should never happen"); - } - } - - /** - * Make an Inet6Address from 16 bytes in network byte order. - */ - private static Inet6Address makeInet6Address(byte[] bytes) { - try { - return (Inet6Address) InetAddress.getByAddress(bytes); - } catch (UnknownHostException e) { - throw new IllegalArgumentException("addr must be 16 bytes: this should never happen"); - } - } - private NetworkStackConstants() { - throw new UnsupportedOperationException("This class is not to be instantiated"); - } -} diff --git a/common/framework/com/android/net/module/util/NetworkStatsUtils.java b/common/framework/com/android/net/module/util/NetworkStatsUtils.java deleted file mode 100644 index 41a9428a..00000000 --- a/common/framework/com/android/net/module/util/NetworkStatsUtils.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2021 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; - -import android.app.usage.NetworkStats; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * Various utilities used for NetworkStats related code. - * - * @hide - */ -public class NetworkStatsUtils { - // These constants must be synced with the definition in android.net.NetworkStats. - // TODO: update to formal APIs once all downstreams have these APIs. - private static final int SET_ALL = -1; - private static final int METERED_ALL = -1; - private static final int ROAMING_ALL = -1; - private static final int DEFAULT_NETWORK_ALL = -1; - - /** - * Safely multiple a value by a rational. - * <p> - * Internally it uses integer-based math whenever possible, but switches - * over to double-based math if values would overflow. - * @hide - */ - public static long multiplySafeByRational(long value, long num, long den) { - if (den == 0) { - throw new ArithmeticException("Invalid Denominator"); - } - long x = value; - long y = num; - - // Logic shamelessly borrowed from Math.multiplyExact() - long r = x * y; - long ax = Math.abs(x); - long ay = Math.abs(y); - if (((ax | ay) >>> 31 != 0)) { - // Some bits greater than 2^31 that might cause overflow - // Check the result using the divide operator - // and check for the special case of Long.MIN_VALUE * -1 - if (((y != 0) && (r / y != x)) - || (x == Long.MIN_VALUE && y == -1)) { - // Use double math to avoid overflowing - return (long) (((double) num / den) * value); - } - } - return r / den; - } - - /** - * Value of the match rule of the subscriberId to match networks with specific subscriberId. - * - * @hide - */ - public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0; - /** - * Value of the match rule of the subscriberId to match networks with any subscriberId which - * includes null and non-null. - * - * @hide - */ - public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1; - - /** - * Name representing {@link #bandwidthSetGlobalAlert(long)} limit when delivered to - * {@link AlertObserver#onQuotaLimitReached(String, String)}. - */ - public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; - - /** - * Return the constrained value by given the lower and upper bounds. - */ - public static int constrain(int amount, int low, int high) { - if (low > high) throw new IllegalArgumentException("low(" + low + ") > high(" + high + ")"); - return amount < low ? low : (amount > high ? high : amount); - } - - /** - * Return the constrained value by given the lower and upper bounds. - */ - public static long constrain(long amount, long low, long high) { - if (low > high) throw new IllegalArgumentException("low(" + low + ") > high(" + high + ")"); - return amount < low ? low : (amount > high ? high : amount); - } - - /** - * Convert structure from android.app.usage.NetworkStats to android.net.NetworkStats. - */ - public static android.net.NetworkStats fromPublicNetworkStats( - NetworkStats publiceNetworkStats) { - android.net.NetworkStats stats = new android.net.NetworkStats(0L, 0); - while (publiceNetworkStats.hasNextBucket()) { - NetworkStats.Bucket bucket = new NetworkStats.Bucket(); - publiceNetworkStats.getNextBucket(bucket); - final android.net.NetworkStats.Entry entry = fromBucket(bucket); - stats = stats.addEntry(entry); - } - return stats; - } - - @VisibleForTesting - public static android.net.NetworkStats.Entry fromBucket(NetworkStats.Bucket bucket) { - return new android.net.NetworkStats.Entry( - null /* IFACE_ALL */, bucket.getUid(), convertBucketState(bucket.getState()), - convertBucketTag(bucket.getTag()), convertBucketMetered(bucket.getMetered()), - convertBucketRoaming(bucket.getRoaming()), - convertBucketDefaultNetworkStatus(bucket.getDefaultNetworkStatus()), - bucket.getRxBytes(), bucket.getRxPackets(), - bucket.getTxBytes(), bucket.getTxPackets(), 0 /* operations */); - } - - private static int convertBucketState(int networkStatsSet) { - switch (networkStatsSet) { - case NetworkStats.Bucket.STATE_ALL: return SET_ALL; - case NetworkStats.Bucket.STATE_DEFAULT: return android.net.NetworkStats.SET_DEFAULT; - case NetworkStats.Bucket.STATE_FOREGROUND: - return android.net.NetworkStats.SET_FOREGROUND; - } - return 0; - } - - private static int convertBucketTag(int tag) { - switch (tag) { - case NetworkStats.Bucket.TAG_NONE: return android.net.NetworkStats.TAG_NONE; - } - return tag; - } - - private static int convertBucketMetered(int metered) { - switch (metered) { - case NetworkStats.Bucket.METERED_ALL: return METERED_ALL; - case NetworkStats.Bucket.METERED_NO: return android.net.NetworkStats.METERED_NO; - case NetworkStats.Bucket.METERED_YES: return android.net.NetworkStats.METERED_YES; - } - return 0; - } - - private static int convertBucketRoaming(int roaming) { - switch (roaming) { - case NetworkStats.Bucket.ROAMING_ALL: return ROAMING_ALL; - case NetworkStats.Bucket.ROAMING_NO: return android.net.NetworkStats.ROAMING_NO; - case NetworkStats.Bucket.ROAMING_YES: return android.net.NetworkStats.ROAMING_YES; - } - return 0; - } - - private static int convertBucketDefaultNetworkStatus(int defaultNetworkStatus) { - switch (defaultNetworkStatus) { - case NetworkStats.Bucket.DEFAULT_NETWORK_ALL: - return DEFAULT_NETWORK_ALL; - case NetworkStats.Bucket.DEFAULT_NETWORK_NO: - return android.net.NetworkStats.DEFAULT_NETWORK_NO; - case NetworkStats.Bucket.DEFAULT_NETWORK_YES: - return android.net.NetworkStats.DEFAULT_NETWORK_YES; - } - return 0; - } -} diff --git a/common/framework/com/android/net/module/util/PerUidCounter.java b/common/framework/com/android/net/module/util/PerUidCounter.java deleted file mode 100644 index 463b0c42..00000000 --- a/common/framework/com/android/net/module/util/PerUidCounter.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2022 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; - -import android.util.SparseIntArray; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -/** - * Keeps track of the counters under different uid, fire exception if the counter - * exceeded the specified maximum value. - * - * @hide - */ -public class PerUidCounter { - private final int mMaxCountPerUid; - - // Map from UID to count that UID has filed. - @VisibleForTesting - @GuardedBy("this") - final SparseIntArray mUidToCount = new SparseIntArray(); - - /** - * Constructor - * - * @param maxCountPerUid the maximum count per uid allowed - */ - public PerUidCounter(final int maxCountPerUid) { - if (maxCountPerUid <= 0) { - throw new IllegalArgumentException("Maximum counter value must be positive"); - } - mMaxCountPerUid = maxCountPerUid; - } - - /** - * Increments the count of the given uid. Throws an exception if the number - * of the counter for the uid exceeds the value of maxCounterPerUid which is the value - * passed into the constructor. see: {@link #PerUidCounter(int)}. - * - * @throws IllegalStateException if the number of counter for the uid exceed - * the allowed number. - * - * @param uid the uid that the counter was made under - */ - public synchronized void incrementCountOrThrow(final int uid) { - final long newCount = ((long) mUidToCount.get(uid, 0)) + 1; - if (newCount > mMaxCountPerUid) { - throw new IllegalStateException("Uid " + uid + " exceeded its allowed limit"); - } - // Since the count cannot be greater than Integer.MAX_VALUE here since mMaxCountPerUid - // is an integer, it is safe to cast to int. - mUidToCount.put(uid, (int) newCount); - } - - /** - * Decrements the count of the given uid. Throws an exception if the number - * of the counter goes below zero. - * - * @throws IllegalStateException if the number of counter for the uid goes below - * zero. - * - * @param uid the uid that the count was made under - */ - public synchronized void decrementCountOrThrow(final int uid) { - final int newCount = mUidToCount.get(uid, 0) - 1; - if (newCount < 0) { - throw new IllegalStateException("BUG: too small count " + newCount + " for UID " + uid); - } else if (newCount == 0) { - mUidToCount.delete(uid); - } else { - mUidToCount.put(uid, newCount); - } - } - - @VisibleForTesting - public synchronized int get(int uid) { - return mUidToCount.get(uid, 0); - } -} diff --git a/common/framework/com/android/net/module/util/PermissionUtils.java b/common/framework/com/android/net/module/util/PermissionUtils.java deleted file mode 100644 index 8315b8f6..00000000 --- a/common/framework/com/android/net/module/util/PermissionUtils.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2021 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; - -import static android.Manifest.permission.ACCESS_NETWORK_STATE; -import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; -import static android.Manifest.permission.NETWORK_STACK; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.os.Binder; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Collection of permission utilities. - * @hide - */ -public final class PermissionUtils { - /** - * Return true if the context has one of given permission. - */ - public static boolean checkAnyPermissionOf(@NonNull Context context, - @NonNull String... permissions) { - for (String permission : permissions) { - if (context.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { - return true; - } - } - return false; - } - - /** - * Return true if the context has one of give permission that is allowed - * for a particular process and user ID running in the system. - */ - public static boolean checkAnyPermissionOf(@NonNull Context context, - int pid, int uid, @NonNull String... permissions) { - for (String permission : permissions) { - if (context.checkPermission(permission, pid, uid) == PERMISSION_GRANTED) { - return true; - } - } - return false; - } - - /** - * Enforce permission check on the context that should have one of given permission. - */ - public static void enforceAnyPermissionOf(@NonNull Context context, - @NonNull String... permissions) { - if (!checkAnyPermissionOf(context, permissions)) { - throw new SecurityException("Requires one of the following permissions: " - + String.join(", ", permissions) + "."); - } - } - - /** - * If the NetworkStack, MAINLINE_NETWORK_STACK are not allowed for a particular process, throw a - * {@link SecurityException}. - * - * @param context {@link android.content.Context} for the process. - */ - public static void enforceNetworkStackPermission(final @NonNull Context context) { - enforceNetworkStackPermissionOr(context); - } - - /** - * If the NetworkStack, MAINLINE_NETWORK_STACK or other specified permissions are not allowed - * for a particular process, throw a {@link SecurityException}. - * - * @param context {@link android.content.Context} for the process. - * @param otherPermissions The set of permissions that could be the candidate permissions , or - * empty string if none of other permissions needed. - */ - public static void enforceNetworkStackPermissionOr(final @NonNull Context context, - final @NonNull String... otherPermissions) { - ArrayList<String> permissions = new ArrayList<String>(Arrays.asList(otherPermissions)); - permissions.add(NETWORK_STACK); - permissions.add(PERMISSION_MAINLINE_NETWORK_STACK); - enforceAnyPermissionOf(context, permissions.toArray(new String[0])); - } - - /** - * If the CONNECTIVITY_USE_RESTRICTED_NETWORKS is not allowed for a particular process, throw a - * {@link SecurityException}. - * - * @param context {@link android.content.Context} for the process. - * @param message A message to include in the exception if it is thrown. - */ - public static void enforceRestrictedNetworkPermission( - final @NonNull Context context, final @Nullable String message) { - context.enforceCallingOrSelfPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, message); - } - - /** - * If the ACCESS_NETWORK_STATE is not allowed for a particular process, throw a - * {@link SecurityException}. - * - * @param context {@link android.content.Context} for the process. - * @param message A message to include in the exception if it is thrown. - */ - public static void enforceAccessNetworkStatePermission( - final @NonNull Context context, final @Nullable String message) { - context.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, message); - } - - /** - * Return true if the context has DUMP permission. - */ - public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { - if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump " + tag + " from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() - + " due to missing android.permission.DUMP permission"); - return false; - } else { - return true; - } - } - - /** - * Enforce that a given feature is available and if not, throw an - * {@link UnsupportedOperationException}. - * - * @param context {@link android.content.Context} for the process. - * @param feature the feature name to enforce. - * @param errorMessage an optional error message to include. - */ - public static void enforceSystemFeature(final @NonNull Context context, - final @NonNull String feature, final @Nullable String errorMessage) { - final boolean hasSystemFeature = - context.getPackageManager().hasSystemFeature(feature); - if (!hasSystemFeature) { - if (null == errorMessage) { - throw new UnsupportedOperationException(); - } - throw new UnsupportedOperationException(errorMessage); - } - } - - /** - * Get the list of granted permissions for a package info. - * - * PackageInfo contains the list of requested permissions, and their state (whether they - * were granted or not, in particular) as a parallel array. Most users care only about - * granted permissions. This method returns the list of them. - * - * @param packageInfo the package info for the relevant uid. - * @return the list of granted permissions. - */ - public static List<String> getGrantedPermissions(final @NonNull PackageInfo packageInfo) { - if (null == packageInfo.requestedPermissions) return Collections.emptyList(); - final ArrayList<String> result = new ArrayList<>(packageInfo.requestedPermissions.length); - for (int i = 0; i < packageInfo.requestedPermissions.length; ++i) { - if (0 != (REQUESTED_PERMISSION_GRANTED & packageInfo.requestedPermissionsFlags[i])) { - result.add(packageInfo.requestedPermissions[i]); - } - } - return result; - } -} diff --git a/common/framework/com/android/net/module/util/ProxyUtils.java b/common/framework/com/android/net/module/util/ProxyUtils.java deleted file mode 100644 index fdd7dca1..00000000 --- a/common/framework/com/android/net/module/util/ProxyUtils.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2020 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; - -import android.text.TextUtils; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Collection of network common utilities. - * - * @hide - */ -public final class ProxyUtils { - - public static final int PROXY_VALID = 0; - public static final int PROXY_HOSTNAME_EMPTY = 1; - public static final int PROXY_HOSTNAME_INVALID = 2; - public static final int PROXY_PORT_EMPTY = 3; - public static final int PROXY_PORT_INVALID = 4; - public static final int PROXY_EXCLLIST_INVALID = 5; - - // Hostname / IP REGEX validation - // Matches blank input, ips, and domain names - private static final String NAME_IP_REGEX = - "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*"; - private static final Pattern HOSTNAME_PATTERN; - private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$"; - private static final Pattern EXCLLIST_PATTERN; - private static final String EXCL_REGEX = - "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*"; - private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$"; - static { - HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP); - EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP); - } - - /** Converts exclusion list from String to List. */ - public static List<String> exclusionStringAsList(String exclusionList) { - if (exclusionList == null) { - return Collections.emptyList(); - } - return Arrays.asList(exclusionList.toLowerCase(Locale.ROOT).split(",")); - } - - /** Converts exclusion list from List to string */ - public static String exclusionListAsString(String[] exclusionList) { - if (exclusionList == null) { - return ""; - } - return TextUtils.join(",", exclusionList); - } - - /** - * Validate syntax of hostname, port and exclusion list entries - */ - public static int validate(String hostname, String port, String exclList) { - Matcher match = HOSTNAME_PATTERN.matcher(hostname); - Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList); - - if (!match.matches()) return PROXY_HOSTNAME_INVALID; - - if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID; - - if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY; - - if (port.length() > 0) { - if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY; - int portVal = -1; - try { - portVal = Integer.parseInt(port); - } catch (NumberFormatException ex) { - return PROXY_PORT_INVALID; - } - if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID; - } - return PROXY_VALID; - } -} diff --git a/common/framework/com/android/net/module/util/RouteUtils.java b/common/framework/com/android/net/module/util/RouteUtils.java deleted file mode 100644 index c2416802..00000000 --- a/common/framework/com/android/net/module/util/RouteUtils.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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; - -/** @hide */ -// RouteUtils is now empty, because some new methods will be added to it soon and it is less -// expensive to keep it empty than to remove it now and add it again later. -public class RouteUtils { -} |