Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/net/util/IPAddressUtil.java
38918 views
/*1* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.net.util;2627import java.net.URL;28import java.util.Arrays;2930public class IPAddressUtil {31private final static int INADDR4SZ = 4;32private final static int INADDR16SZ = 16;33private final static int INT16SZ = 2;3435/*36* Converts IPv4 address in its textual presentation form37* into its numeric binary form.38*39* @param src a String representing an IPv4 address in standard format40* @return a byte array representing the IPv4 numeric address41*/42@SuppressWarnings("fallthrough")43public static byte[] textToNumericFormatV4(String src)44{45byte[] res = new byte[INADDR4SZ];4647long tmpValue = 0;48int currByte = 0;49boolean newOctet = true;5051int len = src.length();52if (len == 0 || len > 15) {53return null;54}55/*56* When only one part is given, the value is stored directly in57* the network address without any byte rearrangement.58*59* When a two part address is supplied, the last part is60* interpreted as a 24-bit quantity and placed in the right61* most three bytes of the network address. This makes the62* two part address format convenient for specifying Class A63* network addresses as net.host.64*65* When a three part address is specified, the last part is66* interpreted as a 16-bit quantity and placed in the right67* most two bytes of the network address. This makes the68* three part address format convenient for specifying69* Class B net- work addresses as 128.net.host.70*71* When four parts are specified, each is interpreted as a72* byte of data and assigned, from left to right, to the73* four bytes of an IPv4 address.74*75* We determine and parse the leading parts, if any, as single76* byte values in one pass directly into the resulting byte[],77* then the remainder is treated as a 8-to-32-bit entity and78* translated into the remaining bytes in the array.79*/80for (int i = 0; i < len; i++) {81char c = src.charAt(i);82if (c == '.') {83if (newOctet || tmpValue < 0 || tmpValue > 0xff || currByte == 3) {84return null;85}86res[currByte++] = (byte) (tmpValue & 0xff);87tmpValue = 0;88newOctet = true;89} else {90int digit = Character.digit(c, 10);91if (digit < 0) {92return null;93}94tmpValue *= 10;95tmpValue += digit;96newOctet = false;97}98}99if (newOctet || tmpValue < 0 || tmpValue >= (1L << ((4 - currByte) * 8))) {100return null;101}102switch (currByte) {103case 0:104res[0] = (byte) ((tmpValue >> 24) & 0xff);105case 1:106res[1] = (byte) ((tmpValue >> 16) & 0xff);107case 2:108res[2] = (byte) ((tmpValue >> 8) & 0xff);109case 3:110res[3] = (byte) ((tmpValue >> 0) & 0xff);111}112return res;113}114115/*116* Convert IPv6 presentation level address to network order binary form.117* credit:118* Converted from C code from Solaris 8 (inet_pton)119*120* Any component of the string following a per-cent % is ignored.121*122* @param src a String representing an IPv6 address in textual format123* @return a byte array representing the IPv6 numeric address124*/125public static byte[] textToNumericFormatV6(String src)126{127// Shortest valid string is "::", hence at least 2 chars128if (src.length() < 2) {129return null;130}131132int colonp;133char ch;134boolean saw_xdigit;135int val;136char[] srcb = src.toCharArray();137byte[] dst = new byte[INADDR16SZ];138139int srcb_length = srcb.length;140int pc = src.indexOf ("%");141if (pc == srcb_length -1) {142return null;143}144145if (pc != -1) {146srcb_length = pc;147}148149colonp = -1;150int i = 0, j = 0;151/* Leading :: requires some special handling. */152if (srcb[i] == ':')153if (srcb[++i] != ':')154return null;155int curtok = i;156saw_xdigit = false;157val = 0;158while (i < srcb_length) {159ch = srcb[i++];160int chval = Character.digit(ch, 16);161if (chval != -1) {162val <<= 4;163val |= chval;164if (val > 0xffff)165return null;166saw_xdigit = true;167continue;168}169if (ch == ':') {170curtok = i;171if (!saw_xdigit) {172if (colonp != -1)173return null;174colonp = j;175continue;176} else if (i == srcb_length) {177return null;178}179if (j + INT16SZ > INADDR16SZ)180return null;181dst[j++] = (byte) ((val >> 8) & 0xff);182dst[j++] = (byte) (val & 0xff);183saw_xdigit = false;184val = 0;185continue;186}187if (ch == '.' && ((j + INADDR4SZ) <= INADDR16SZ)) {188String ia4 = src.substring(curtok, srcb_length);189/* check this IPv4 address has 3 dots, ie. A.B.C.D */190int dot_count = 0, index=0;191while ((index = ia4.indexOf ('.', index)) != -1) {192dot_count ++;193index ++;194}195if (dot_count != 3) {196return null;197}198byte[] v4addr = textToNumericFormatV4(ia4);199if (v4addr == null) {200return null;201}202for (int k = 0; k < INADDR4SZ; k++) {203dst[j++] = v4addr[k];204}205saw_xdigit = false;206break; /* '\0' was seen by inet_pton4(). */207}208return null;209}210if (saw_xdigit) {211if (j + INT16SZ > INADDR16SZ)212return null;213dst[j++] = (byte) ((val >> 8) & 0xff);214dst[j++] = (byte) (val & 0xff);215}216217if (colonp != -1) {218int n = j - colonp;219220if (j == INADDR16SZ)221return null;222for (i = 1; i <= n; i++) {223dst[INADDR16SZ - i] = dst[colonp + n - i];224dst[colonp + n - i] = 0;225}226j = INADDR16SZ;227}228if (j != INADDR16SZ)229return null;230byte[] newdst = convertFromIPv4MappedAddress(dst);231if (newdst != null) {232return newdst;233} else {234return dst;235}236}237238/**239* @param src a String representing an IPv4 address in textual format240* @return a boolean indicating whether src is an IPv4 literal address241*/242public static boolean isIPv4LiteralAddress(String src) {243return textToNumericFormatV4(src) != null;244}245246/**247* @param src a String representing an IPv6 address in textual format248* @return a boolean indicating whether src is an IPv6 literal address249*/250public static boolean isIPv6LiteralAddress(String src) {251return textToNumericFormatV6(src) != null;252}253254/*255* Convert IPv4-Mapped address to IPv4 address. Both input and256* returned value are in network order binary form.257*258* @param src a String representing an IPv4-Mapped address in textual format259* @return a byte array representing the IPv4 numeric address260*/261public static byte[] convertFromIPv4MappedAddress(byte[] addr) {262if (isIPv4MappedAddress(addr)) {263byte[] newAddr = new byte[INADDR4SZ];264System.arraycopy(addr, 12, newAddr, 0, INADDR4SZ);265return newAddr;266}267return null;268}269270/**271* Utility routine to check if the InetAddress is an272* IPv4 mapped IPv6 address.273*274* @return a <code>boolean</code> indicating if the InetAddress is275* an IPv4 mapped IPv6 address; or false if address is IPv4 address.276*/277private static boolean isIPv4MappedAddress(byte[] addr) {278if (addr.length < INADDR16SZ) {279return false;280}281if ((addr[0] == 0x00) && (addr[1] == 0x00) &&282(addr[2] == 0x00) && (addr[3] == 0x00) &&283(addr[4] == 0x00) && (addr[5] == 0x00) &&284(addr[6] == 0x00) && (addr[7] == 0x00) &&285(addr[8] == 0x00) && (addr[9] == 0x00) &&286(addr[10] == (byte)0xff) &&287(addr[11] == (byte)0xff)) {288return true;289}290return false;291}292293// See java.net.URI for more details on how to generate these294// masks.295//296// square brackets297private static final long L_IPV6_DELIMS = 0x0L; // "[]"298private static final long H_IPV6_DELIMS = 0x28000000L; // "[]"299// RFC 3986 gen-delims300private static final long L_GEN_DELIMS = 0x8400800800000000L; // ":/?#[]@"301private static final long H_GEN_DELIMS = 0x28000001L; // ":/?#[]@"302// These gen-delims can appear in authority303private static final long L_AUTH_DELIMS = 0x400000000000000L; // "@[]:"304private static final long H_AUTH_DELIMS = 0x28000001L; // "@[]:"305// colon is allowed in userinfo306private static final long L_COLON = 0x400000000000000L; // ":"307private static final long H_COLON = 0x0L; // ":"308// slash should be encoded in authority309private static final long L_SLASH = 0x800000000000L; // "/"310private static final long H_SLASH = 0x0L; // "/"311// backslash should always be encoded312private static final long L_BACKSLASH = 0x0L; // "\"313private static final long H_BACKSLASH = 0x10000000L; // "\"314// ASCII chars 0-31 + 127 - various controls + CRLF + TAB315private static final long L_NON_PRINTABLE = 0xffffffffL;316private static final long H_NON_PRINTABLE = 0x8000000000000000L;317// All of the above318private static final long L_EXCLUDE = 0x84008008ffffffffL;319private static final long H_EXCLUDE = 0x8000000038000001L;320321private static final char[] OTHERS = {3228263,8264,8265,8448,8449,8453,8454,10868,32365109,65110,65119,65131,65283,65295,65306,65311,65312324};325326// Tell whether the given character is found by the given mask pair327public static boolean match(char c, long lowMask, long highMask) {328if (c < 64)329return ((1L << c) & lowMask) != 0;330if (c < 128)331return ((1L << (c - 64)) & highMask) != 0;332return false; // other non ASCII characters are not filtered333}334335// returns -1 if the string doesn't contain any characters336// from the mask, the index of the first such character found337// otherwise.338public static int scan(String s, long lowMask, long highMask) {339int i = -1, len;340if (s == null || (len = s.length()) == 0) return -1;341boolean match = false;342while (++i < len && !(match = match(s.charAt(i), lowMask, highMask)));343if (match) return i;344return -1;345}346347public static int scan(String s, long lowMask, long highMask, char[] others) {348int i = -1, len;349if (s == null || (len = s.length()) == 0) return -1;350boolean match = false;351char c, c0 = others[0];352while (++i < len && !(match = match((c=s.charAt(i)), lowMask, highMask))) {353if (c >= c0 && (Arrays.binarySearch(others, c) > -1)) {354match = true; break;355}356}357if (match) return i;358359return -1;360}361362private static String describeChar(char c) {363if (c < 32 || c == 127) {364if (c == '\n') return "LF";365if (c == '\r') return "CR";366return "control char (code=" + (int)c + ")";367}368if (c == '\\') return "'\\'";369return "'" + c + "'";370}371372private static String checkUserInfo(String str) {373// colon is permitted in user info374int index = scan(str, L_EXCLUDE & ~L_COLON,375H_EXCLUDE & ~H_COLON);376if (index >= 0) {377return "Illegal character found in user-info: "378+ describeChar(str.charAt(index));379}380return null;381}382383private static String checkHost(String str) {384int index;385if (str.startsWith("[") && str.endsWith("]")) {386str = str.substring(1, str.length() - 1);387if (isIPv6LiteralAddress(str)) {388index = str.indexOf('%');389if (index >= 0) {390index = scan(str = str.substring(index),391L_NON_PRINTABLE | L_IPV6_DELIMS,392H_NON_PRINTABLE | H_IPV6_DELIMS);393if (index >= 0) {394return "Illegal character found in IPv6 scoped address: "395+ describeChar(str.charAt(index));396}397}398return null;399}400return "Unrecognized IPv6 address format";401} else {402index = scan(str, L_EXCLUDE, H_EXCLUDE);403if (index >= 0) {404return "Illegal character found in host: "405+ describeChar(str.charAt(index));406}407}408return null;409}410411private static String checkAuth(String str) {412int index = scan(str,413L_EXCLUDE & ~L_AUTH_DELIMS,414H_EXCLUDE & ~H_AUTH_DELIMS);415if (index >= 0) {416return "Illegal character found in authority: "417+ describeChar(str.charAt(index));418}419return null;420}421422// check authority of hierarchical URL. Appropriate for423// HTTP-like protocol handlers424public static String checkAuthority(URL url) {425String s, u, h;426if (url == null) return null;427if ((s = checkUserInfo(u = url.getUserInfo())) != null) {428return s;429}430if ((s = checkHost(h = url.getHost())) != null) {431return s;432}433if (h == null && u == null) {434return checkAuth(url.getAuthority());435}436return null;437}438439// minimal syntax checks - deeper check may be performed440// by the appropriate protocol handler441public static String checkExternalForm(URL url) {442String s;443if (url == null) return null;444int index = scan(s = url.getUserInfo(),445L_NON_PRINTABLE | L_SLASH,446H_NON_PRINTABLE | H_SLASH);447if (index >= 0) {448return "Illegal character found in authority: "449+ describeChar(s.charAt(index));450}451if ((s = checkHostString(url.getHost())) != null) {452return s;453}454return null;455}456457public static String checkHostString(String host) {458if (host == null) return null;459int index = scan(host,460L_NON_PRINTABLE | L_SLASH,461H_NON_PRINTABLE | H_SLASH,462OTHERS);463if (index >= 0) {464return "Illegal character found in host: "465+ describeChar(host.charAt(index));466}467return null;468}469470}471472473