Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/net/util/IPAddressUtil.java
38918 views
1
/*
2
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.net.util;
27
28
import java.net.URL;
29
import java.util.Arrays;
30
31
public class IPAddressUtil {
32
private final static int INADDR4SZ = 4;
33
private final static int INADDR16SZ = 16;
34
private final static int INT16SZ = 2;
35
36
/*
37
* Converts IPv4 address in its textual presentation form
38
* into its numeric binary form.
39
*
40
* @param src a String representing an IPv4 address in standard format
41
* @return a byte array representing the IPv4 numeric address
42
*/
43
@SuppressWarnings("fallthrough")
44
public static byte[] textToNumericFormatV4(String src)
45
{
46
byte[] res = new byte[INADDR4SZ];
47
48
long tmpValue = 0;
49
int currByte = 0;
50
boolean newOctet = true;
51
52
int len = src.length();
53
if (len == 0 || len > 15) {
54
return null;
55
}
56
/*
57
* When only one part is given, the value is stored directly in
58
* the network address without any byte rearrangement.
59
*
60
* When a two part address is supplied, the last part is
61
* interpreted as a 24-bit quantity and placed in the right
62
* most three bytes of the network address. This makes the
63
* two part address format convenient for specifying Class A
64
* network addresses as net.host.
65
*
66
* When a three part address is specified, the last part is
67
* interpreted as a 16-bit quantity and placed in the right
68
* most two bytes of the network address. This makes the
69
* three part address format convenient for specifying
70
* Class B net- work addresses as 128.net.host.
71
*
72
* When four parts are specified, each is interpreted as a
73
* byte of data and assigned, from left to right, to the
74
* four bytes of an IPv4 address.
75
*
76
* We determine and parse the leading parts, if any, as single
77
* byte values in one pass directly into the resulting byte[],
78
* then the remainder is treated as a 8-to-32-bit entity and
79
* translated into the remaining bytes in the array.
80
*/
81
for (int i = 0; i < len; i++) {
82
char c = src.charAt(i);
83
if (c == '.') {
84
if (newOctet || tmpValue < 0 || tmpValue > 0xff || currByte == 3) {
85
return null;
86
}
87
res[currByte++] = (byte) (tmpValue & 0xff);
88
tmpValue = 0;
89
newOctet = true;
90
} else {
91
int digit = Character.digit(c, 10);
92
if (digit < 0) {
93
return null;
94
}
95
tmpValue *= 10;
96
tmpValue += digit;
97
newOctet = false;
98
}
99
}
100
if (newOctet || tmpValue < 0 || tmpValue >= (1L << ((4 - currByte) * 8))) {
101
return null;
102
}
103
switch (currByte) {
104
case 0:
105
res[0] = (byte) ((tmpValue >> 24) & 0xff);
106
case 1:
107
res[1] = (byte) ((tmpValue >> 16) & 0xff);
108
case 2:
109
res[2] = (byte) ((tmpValue >> 8) & 0xff);
110
case 3:
111
res[3] = (byte) ((tmpValue >> 0) & 0xff);
112
}
113
return res;
114
}
115
116
/*
117
* Convert IPv6 presentation level address to network order binary form.
118
* credit:
119
* Converted from C code from Solaris 8 (inet_pton)
120
*
121
* Any component of the string following a per-cent % is ignored.
122
*
123
* @param src a String representing an IPv6 address in textual format
124
* @return a byte array representing the IPv6 numeric address
125
*/
126
public static byte[] textToNumericFormatV6(String src)
127
{
128
// Shortest valid string is "::", hence at least 2 chars
129
if (src.length() < 2) {
130
return null;
131
}
132
133
int colonp;
134
char ch;
135
boolean saw_xdigit;
136
int val;
137
char[] srcb = src.toCharArray();
138
byte[] dst = new byte[INADDR16SZ];
139
140
int srcb_length = srcb.length;
141
int pc = src.indexOf ("%");
142
if (pc == srcb_length -1) {
143
return null;
144
}
145
146
if (pc != -1) {
147
srcb_length = pc;
148
}
149
150
colonp = -1;
151
int i = 0, j = 0;
152
/* Leading :: requires some special handling. */
153
if (srcb[i] == ':')
154
if (srcb[++i] != ':')
155
return null;
156
int curtok = i;
157
saw_xdigit = false;
158
val = 0;
159
while (i < srcb_length) {
160
ch = srcb[i++];
161
int chval = Character.digit(ch, 16);
162
if (chval != -1) {
163
val <<= 4;
164
val |= chval;
165
if (val > 0xffff)
166
return null;
167
saw_xdigit = true;
168
continue;
169
}
170
if (ch == ':') {
171
curtok = i;
172
if (!saw_xdigit) {
173
if (colonp != -1)
174
return null;
175
colonp = j;
176
continue;
177
} else if (i == srcb_length) {
178
return null;
179
}
180
if (j + INT16SZ > INADDR16SZ)
181
return null;
182
dst[j++] = (byte) ((val >> 8) & 0xff);
183
dst[j++] = (byte) (val & 0xff);
184
saw_xdigit = false;
185
val = 0;
186
continue;
187
}
188
if (ch == '.' && ((j + INADDR4SZ) <= INADDR16SZ)) {
189
String ia4 = src.substring(curtok, srcb_length);
190
/* check this IPv4 address has 3 dots, ie. A.B.C.D */
191
int dot_count = 0, index=0;
192
while ((index = ia4.indexOf ('.', index)) != -1) {
193
dot_count ++;
194
index ++;
195
}
196
if (dot_count != 3) {
197
return null;
198
}
199
byte[] v4addr = textToNumericFormatV4(ia4);
200
if (v4addr == null) {
201
return null;
202
}
203
for (int k = 0; k < INADDR4SZ; k++) {
204
dst[j++] = v4addr[k];
205
}
206
saw_xdigit = false;
207
break; /* '\0' was seen by inet_pton4(). */
208
}
209
return null;
210
}
211
if (saw_xdigit) {
212
if (j + INT16SZ > INADDR16SZ)
213
return null;
214
dst[j++] = (byte) ((val >> 8) & 0xff);
215
dst[j++] = (byte) (val & 0xff);
216
}
217
218
if (colonp != -1) {
219
int n = j - colonp;
220
221
if (j == INADDR16SZ)
222
return null;
223
for (i = 1; i <= n; i++) {
224
dst[INADDR16SZ - i] = dst[colonp + n - i];
225
dst[colonp + n - i] = 0;
226
}
227
j = INADDR16SZ;
228
}
229
if (j != INADDR16SZ)
230
return null;
231
byte[] newdst = convertFromIPv4MappedAddress(dst);
232
if (newdst != null) {
233
return newdst;
234
} else {
235
return dst;
236
}
237
}
238
239
/**
240
* @param src a String representing an IPv4 address in textual format
241
* @return a boolean indicating whether src is an IPv4 literal address
242
*/
243
public static boolean isIPv4LiteralAddress(String src) {
244
return textToNumericFormatV4(src) != null;
245
}
246
247
/**
248
* @param src a String representing an IPv6 address in textual format
249
* @return a boolean indicating whether src is an IPv6 literal address
250
*/
251
public static boolean isIPv6LiteralAddress(String src) {
252
return textToNumericFormatV6(src) != null;
253
}
254
255
/*
256
* Convert IPv4-Mapped address to IPv4 address. Both input and
257
* returned value are in network order binary form.
258
*
259
* @param src a String representing an IPv4-Mapped address in textual format
260
* @return a byte array representing the IPv4 numeric address
261
*/
262
public static byte[] convertFromIPv4MappedAddress(byte[] addr) {
263
if (isIPv4MappedAddress(addr)) {
264
byte[] newAddr = new byte[INADDR4SZ];
265
System.arraycopy(addr, 12, newAddr, 0, INADDR4SZ);
266
return newAddr;
267
}
268
return null;
269
}
270
271
/**
272
* Utility routine to check if the InetAddress is an
273
* IPv4 mapped IPv6 address.
274
*
275
* @return a <code>boolean</code> indicating if the InetAddress is
276
* an IPv4 mapped IPv6 address; or false if address is IPv4 address.
277
*/
278
private static boolean isIPv4MappedAddress(byte[] addr) {
279
if (addr.length < INADDR16SZ) {
280
return false;
281
}
282
if ((addr[0] == 0x00) && (addr[1] == 0x00) &&
283
(addr[2] == 0x00) && (addr[3] == 0x00) &&
284
(addr[4] == 0x00) && (addr[5] == 0x00) &&
285
(addr[6] == 0x00) && (addr[7] == 0x00) &&
286
(addr[8] == 0x00) && (addr[9] == 0x00) &&
287
(addr[10] == (byte)0xff) &&
288
(addr[11] == (byte)0xff)) {
289
return true;
290
}
291
return false;
292
}
293
294
// See java.net.URI for more details on how to generate these
295
// masks.
296
//
297
// square brackets
298
private static final long L_IPV6_DELIMS = 0x0L; // "[]"
299
private static final long H_IPV6_DELIMS = 0x28000000L; // "[]"
300
// RFC 3986 gen-delims
301
private static final long L_GEN_DELIMS = 0x8400800800000000L; // ":/?#[]@"
302
private static final long H_GEN_DELIMS = 0x28000001L; // ":/?#[]@"
303
// These gen-delims can appear in authority
304
private static final long L_AUTH_DELIMS = 0x400000000000000L; // "@[]:"
305
private static final long H_AUTH_DELIMS = 0x28000001L; // "@[]:"
306
// colon is allowed in userinfo
307
private static final long L_COLON = 0x400000000000000L; // ":"
308
private static final long H_COLON = 0x0L; // ":"
309
// slash should be encoded in authority
310
private static final long L_SLASH = 0x800000000000L; // "/"
311
private static final long H_SLASH = 0x0L; // "/"
312
// backslash should always be encoded
313
private static final long L_BACKSLASH = 0x0L; // "\"
314
private static final long H_BACKSLASH = 0x10000000L; // "\"
315
// ASCII chars 0-31 + 127 - various controls + CRLF + TAB
316
private static final long L_NON_PRINTABLE = 0xffffffffL;
317
private static final long H_NON_PRINTABLE = 0x8000000000000000L;
318
// All of the above
319
private static final long L_EXCLUDE = 0x84008008ffffffffL;
320
private static final long H_EXCLUDE = 0x8000000038000001L;
321
322
private static final char[] OTHERS = {
323
8263,8264,8265,8448,8449,8453,8454,10868,
324
65109,65110,65119,65131,65283,65295,65306,65311,65312
325
};
326
327
// Tell whether the given character is found by the given mask pair
328
public static boolean match(char c, long lowMask, long highMask) {
329
if (c < 64)
330
return ((1L << c) & lowMask) != 0;
331
if (c < 128)
332
return ((1L << (c - 64)) & highMask) != 0;
333
return false; // other non ASCII characters are not filtered
334
}
335
336
// returns -1 if the string doesn't contain any characters
337
// from the mask, the index of the first such character found
338
// otherwise.
339
public static int scan(String s, long lowMask, long highMask) {
340
int i = -1, len;
341
if (s == null || (len = s.length()) == 0) return -1;
342
boolean match = false;
343
while (++i < len && !(match = match(s.charAt(i), lowMask, highMask)));
344
if (match) return i;
345
return -1;
346
}
347
348
public static int scan(String s, long lowMask, long highMask, char[] others) {
349
int i = -1, len;
350
if (s == null || (len = s.length()) == 0) return -1;
351
boolean match = false;
352
char c, c0 = others[0];
353
while (++i < len && !(match = match((c=s.charAt(i)), lowMask, highMask))) {
354
if (c >= c0 && (Arrays.binarySearch(others, c) > -1)) {
355
match = true; break;
356
}
357
}
358
if (match) return i;
359
360
return -1;
361
}
362
363
private static String describeChar(char c) {
364
if (c < 32 || c == 127) {
365
if (c == '\n') return "LF";
366
if (c == '\r') return "CR";
367
return "control char (code=" + (int)c + ")";
368
}
369
if (c == '\\') return "'\\'";
370
return "'" + c + "'";
371
}
372
373
private static String checkUserInfo(String str) {
374
// colon is permitted in user info
375
int index = scan(str, L_EXCLUDE & ~L_COLON,
376
H_EXCLUDE & ~H_COLON);
377
if (index >= 0) {
378
return "Illegal character found in user-info: "
379
+ describeChar(str.charAt(index));
380
}
381
return null;
382
}
383
384
private static String checkHost(String str) {
385
int index;
386
if (str.startsWith("[") && str.endsWith("]")) {
387
str = str.substring(1, str.length() - 1);
388
if (isIPv6LiteralAddress(str)) {
389
index = str.indexOf('%');
390
if (index >= 0) {
391
index = scan(str = str.substring(index),
392
L_NON_PRINTABLE | L_IPV6_DELIMS,
393
H_NON_PRINTABLE | H_IPV6_DELIMS);
394
if (index >= 0) {
395
return "Illegal character found in IPv6 scoped address: "
396
+ describeChar(str.charAt(index));
397
}
398
}
399
return null;
400
}
401
return "Unrecognized IPv6 address format";
402
} else {
403
index = scan(str, L_EXCLUDE, H_EXCLUDE);
404
if (index >= 0) {
405
return "Illegal character found in host: "
406
+ describeChar(str.charAt(index));
407
}
408
}
409
return null;
410
}
411
412
private static String checkAuth(String str) {
413
int index = scan(str,
414
L_EXCLUDE & ~L_AUTH_DELIMS,
415
H_EXCLUDE & ~H_AUTH_DELIMS);
416
if (index >= 0) {
417
return "Illegal character found in authority: "
418
+ describeChar(str.charAt(index));
419
}
420
return null;
421
}
422
423
// check authority of hierarchical URL. Appropriate for
424
// HTTP-like protocol handlers
425
public static String checkAuthority(URL url) {
426
String s, u, h;
427
if (url == null) return null;
428
if ((s = checkUserInfo(u = url.getUserInfo())) != null) {
429
return s;
430
}
431
if ((s = checkHost(h = url.getHost())) != null) {
432
return s;
433
}
434
if (h == null && u == null) {
435
return checkAuth(url.getAuthority());
436
}
437
return null;
438
}
439
440
// minimal syntax checks - deeper check may be performed
441
// by the appropriate protocol handler
442
public static String checkExternalForm(URL url) {
443
String s;
444
if (url == null) return null;
445
int index = scan(s = url.getUserInfo(),
446
L_NON_PRINTABLE | L_SLASH,
447
H_NON_PRINTABLE | H_SLASH);
448
if (index >= 0) {
449
return "Illegal character found in authority: "
450
+ describeChar(s.charAt(index));
451
}
452
if ((s = checkHostString(url.getHost())) != null) {
453
return s;
454
}
455
return null;
456
}
457
458
public static String checkHostString(String host) {
459
if (host == null) return null;
460
int index = scan(host,
461
L_NON_PRINTABLE | L_SLASH,
462
H_NON_PRINTABLE | H_SLASH,
463
OTHERS);
464
if (index >= 0) {
465
return "Illegal character found in host: "
466
+ describeChar(host.charAt(index));
467
}
468
return null;
469
}
470
471
}
472
473