summaryrefslogtreecommitdiff
path: root/src/android/net/util/HostnameTransliterator.java
diff options
context:
space:
mode:
authorXiao Ma <xiaom@google.com>2019-08-26 17:24:26 +0900
committerXiao Ma <xiaom@google.com>2019-12-27 17:03:09 +0900
commit8bcd6735907353caa493d232f01a3fa191bc2f4c (patch)
tree8fefdb16aa50f0a31662a37c6f29d44bfa8ff6c1 /src/android/net/util/HostnameTransliterator.java
parent7b60bfa137ad7ec9213ec4c2169cea4f303e2ce0 (diff)
Provide RRO configuration to send DHCP client hostname option.
Add a configurable option in the RRO which controls whether or not to send the hostname set in the Settings->About phone->Device name. The option in RRO is false by default, that means DHCP Request still not include any hostname by default. Once the option is overlaid and enabled, the device name after transliteration will be wrote into hostname option. Bug: 131783527 Test: atest NetworkStackTests NetworkStackIntegrationTests Test: manual test, create empty APK to overlay the RRO configuration. Change-Id: I9af0b0d9e7bb526d3a3c1003bb99d0a3d69b1e9e
Diffstat (limited to 'src/android/net/util/HostnameTransliterator.java')
-rw-r--r--src/android/net/util/HostnameTransliterator.java103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/android/net/util/HostnameTransliterator.java b/src/android/net/util/HostnameTransliterator.java
new file mode 100644
index 0000000..cf126d1
--- /dev/null
+++ b/src/android/net/util/HostnameTransliterator.java
@@ -0,0 +1,103 @@
+/*
+ * 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 android.net.util;
+
+import android.icu.text.Transliterator;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Transliterator to display a human-readable DHCP client hostname.
+ */
+public class HostnameTransliterator {
+ private static final String TAG = "HostnameTransliterator";
+
+ // Maximum length of hostname to be encoded in the DHCP message. Following RFC1035#2.3.4
+ // and this transliterator converts the device name to a single label, so the label length
+ // limit applies to the whole hostname.
+ private static final int MAX_DNS_LABEL_LENGTH = 63;
+
+ @Nullable
+ private final Transliterator mTransliterator;
+
+ public HostnameTransliterator() {
+ final Enumeration<String> availableIDs = Transliterator.getAvailableIDs();
+ final Set<String> actualIds = new HashSet<>(Collections.list(availableIDs));
+ final StringBuilder rules = new StringBuilder();
+ if (actualIds.contains("Any-ASCII")) {
+ rules.append(":: Any-ASCII; ");
+ } else if (actualIds.contains("Any-Latin") && actualIds.contains("Latin-ASCII")) {
+ rules.append(":: Any-Latin; :: Latin-ASCII; ");
+ } else {
+ Log.e(TAG, "ICU Transliterator doesn't include supported ID");
+ mTransliterator = null;
+ return;
+ }
+ mTransliterator = Transliterator.createFromRules("", rules.toString(),
+ Transliterator.FORWARD);
+ }
+
+ @VisibleForTesting
+ public HostnameTransliterator(Transliterator transliterator) {
+ mTransliterator = transliterator;
+ }
+
+ // RFC952 and RFC1123 stipulates an valid hostname should be:
+ // 1. Only contain the alphabet (A-Z, a-z), digits (0-9), minus sign (-).
+ // 2. No blank or space characters are permitted as part of a name.
+ // 3. The first character must be an alpha character or digit.
+ // 4. The last character must not be a minus sign (-).
+ private String maybeRemoveRedundantSymbols(@NonNull String string) {
+ String result = string.replaceAll("[^a-zA-Z0-9-]", "-");
+ result = result.replaceAll("-+", "-");
+ if (result.startsWith("-")) {
+ result = result.replaceFirst("-", "");
+ }
+ if (result.endsWith("-")) {
+ result = result.substring(0, result.length() - 1);
+ }
+ return result;
+ }
+
+ /**
+ * Transliterate the device name to valid hostname that could be human-readable string.
+ */
+ public String transliterate(@NonNull String deviceName) {
+ if (deviceName == null) return null;
+ if (mTransliterator == null) {
+ if (!deviceName.matches("\\p{ASCII}*")) return null;
+ deviceName = maybeRemoveRedundantSymbols(deviceName);
+ if (TextUtils.isEmpty(deviceName)) return null;
+ return deviceName.length() > MAX_DNS_LABEL_LENGTH
+ ? deviceName.substring(0, MAX_DNS_LABEL_LENGTH) : deviceName;
+ }
+
+ String hostname = maybeRemoveRedundantSymbols(mTransliterator.transliterate(deviceName));
+ if (TextUtils.isEmpty(hostname)) return null;
+ return hostname.length() > MAX_DNS_LABEL_LENGTH
+ ? hostname.substring(0, MAX_DNS_LABEL_LENGTH) : hostname;
+ }
+}