Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/classes/java/net/InetAddress.java
67862 views
1
/*
2
* Copyright (c) 1995, 2021, 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 java.net;
27
28
import java.util.List;
29
import java.util.NavigableSet;
30
import java.util.ArrayList;
31
import java.util.Objects;
32
import java.util.Scanner;
33
import java.io.File;
34
import java.io.ObjectStreamException;
35
import java.io.ObjectStreamField;
36
import java.io.IOException;
37
import java.io.InvalidObjectException;
38
import java.io.ObjectInputStream;
39
import java.io.ObjectInputStream.GetField;
40
import java.io.ObjectOutputStream;
41
import java.io.ObjectOutputStream.PutField;
42
import java.lang.annotation.Native;
43
import java.util.concurrent.ConcurrentHashMap;
44
import java.util.concurrent.ConcurrentMap;
45
import java.util.concurrent.ConcurrentSkipListSet;
46
import java.util.concurrent.atomic.AtomicLong;
47
import java.util.Arrays;
48
49
import jdk.internal.access.JavaNetInetAddressAccess;
50
import jdk.internal.access.SharedSecrets;
51
import sun.security.action.*;
52
import sun.net.InetAddressCachePolicy;
53
import sun.net.util.IPAddressUtil;
54
import sun.nio.cs.UTF_8;
55
56
/**
57
* This class represents an Internet Protocol (IP) address.
58
*
59
* <p> An IP address is either a 32-bit or 128-bit unsigned number
60
* used by IP, a lower-level protocol on which protocols like UDP and
61
* TCP are built. The IP address architecture is defined by <a
62
* href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC&nbsp;790:
63
* Assigned Numbers</i></a>, <a
64
* href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC&nbsp;1918:
65
* Address Allocation for Private Internets</i></a>, <a
66
* href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC&nbsp;2365:
67
* Administratively Scoped IP Multicast</i></a>, and <a
68
* href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IP
69
* Version 6 Addressing Architecture</i></a>. An instance of an
70
* InetAddress consists of an IP address and possibly its
71
* corresponding host name (depending on whether it is constructed
72
* with a host name or whether it has already done reverse host name
73
* resolution).
74
*
75
* <h2> Address types </h2>
76
*
77
* <table class="striped" style="margin-left:2em">
78
* <caption style="display:none">Description of unicast and multicast address types</caption>
79
* <thead>
80
* <tr><th scope="col">Address Type</th><th scope="col">Description</th></tr>
81
* </thead>
82
* <tbody>
83
* <tr><th scope="row" style="vertical-align:top">unicast</th>
84
* <td>An identifier for a single interface. A packet sent to
85
* a unicast address is delivered to the interface identified by
86
* that address.
87
*
88
* <p> The Unspecified Address -- Also called anylocal or wildcard
89
* address. It must never be assigned to any node. It indicates the
90
* absence of an address. One example of its use is as the target of
91
* bind, which allows a server to accept a client connection on any
92
* interface, in case the server host has multiple interfaces.
93
*
94
* <p> The <i>unspecified</i> address must not be used as
95
* the destination address of an IP packet.
96
*
97
* <p> The <i>Loopback</i> Addresses -- This is the address
98
* assigned to the loopback interface. Anything sent to this
99
* IP address loops around and becomes IP input on the local
100
* host. This address is often used when testing a
101
* client.</td></tr>
102
* <tr><th scope="row" style="vertical-align:top">multicast</th>
103
* <td>An identifier for a set of interfaces (typically belonging
104
* to different nodes). A packet sent to a multicast address is
105
* delivered to all interfaces identified by that address.</td></tr>
106
* </tbody>
107
* </table>
108
*
109
* <h3> IP address scope </h3>
110
*
111
* <p> <i>Link-local</i> addresses are designed to be used for addressing
112
* on a single link for purposes such as auto-address configuration,
113
* neighbor discovery, or when no routers are present.
114
*
115
* <p> <i>Site-local</i> addresses are designed to be used for addressing
116
* inside of a site without the need for a global prefix.
117
*
118
* <p> <i>Global</i> addresses are unique across the internet.
119
*
120
* <h3> Textual representation of IP addresses </h3>
121
*
122
* The textual representation of an IP address is address family specific.
123
*
124
* <p>
125
*
126
* For IPv4 address format, please refer to <A
127
* HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6
128
* address format, please refer to <A
129
* HREF="Inet6Address.html#format">Inet6Address#format</A>.
130
*
131
* <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
132
* System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P>
133
*
134
* <h3> Host Name Resolution </h3>
135
*
136
* Host name-to-IP address <i>resolution</i> is accomplished through
137
* the use of a combination of local machine configuration information
138
* and network naming services such as the Domain Name System (DNS)
139
* and Network Information Service(NIS). The particular naming
140
* services(s) being used is by default the local machine configured
141
* one. For any host name, its corresponding IP address is returned.
142
*
143
* <p> <i>Reverse name resolution</i> means that for any IP address,
144
* the host associated with the IP address is returned.
145
*
146
* <p> The InetAddress class provides methods to resolve host names to
147
* their IP addresses and vice versa.
148
*
149
* <h3> InetAddress Caching </h3>
150
*
151
* The InetAddress class has a cache to store successful as well as
152
* unsuccessful host name resolutions.
153
*
154
* <p> By default, when a security manager is installed, in order to
155
* protect against DNS spoofing attacks,
156
* the result of positive host name resolutions are
157
* cached forever. When a security manager is not installed, the default
158
* behavior is to cache entries for a finite (implementation dependent)
159
* period of time. The result of unsuccessful host
160
* name resolution is cached for a very short period of time (10
161
* seconds) to improve performance.
162
*
163
* <p> If the default behavior is not desired, then a Java security property
164
* can be set to a different Time-to-live (TTL) value for positive
165
* caching. Likewise, a system admin can configure a different
166
* negative caching TTL value when needed.
167
*
168
* <p> Two Java security properties control the TTL values used for
169
* positive and negative host name resolution caching:
170
*
171
* <dl style="margin-left:2em">
172
* <dt><b>networkaddress.cache.ttl</b></dt>
173
* <dd>Indicates the caching policy for successful name lookups from
174
* the name service. The value is specified as an integer to indicate
175
* the number of seconds to cache the successful lookup. The default
176
* setting is to cache for an implementation specific period of time.
177
* <p>
178
* A value of -1 indicates "cache forever".
179
* </dd>
180
* <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt>
181
* <dd>Indicates the caching policy for un-successful name lookups
182
* from the name service. The value is specified as an integer to
183
* indicate the number of seconds to cache the failure for
184
* un-successful lookups.
185
* <p>
186
* A value of 0 indicates "never cache".
187
* A value of -1 indicates "cache forever".
188
* </dd>
189
* </dl>
190
*
191
* @author Chris Warth
192
* @see java.net.InetAddress#getByAddress(byte[])
193
* @see java.net.InetAddress#getByAddress(java.lang.String, byte[])
194
* @see java.net.InetAddress#getAllByName(java.lang.String)
195
* @see java.net.InetAddress#getByName(java.lang.String)
196
* @see java.net.InetAddress#getLocalHost()
197
* @since 1.0
198
*/
199
public class InetAddress implements java.io.Serializable {
200
201
@Native static final int PREFER_IPV4_VALUE = 0;
202
@Native static final int PREFER_IPV6_VALUE = 1;
203
@Native static final int PREFER_SYSTEM_VALUE = 2;
204
205
/**
206
* Specify the address family: Internet Protocol, Version 4
207
* @since 1.4
208
*/
209
@Native static final int IPv4 = 1;
210
211
/**
212
* Specify the address family: Internet Protocol, Version 6
213
* @since 1.4
214
*/
215
@Native static final int IPv6 = 2;
216
217
/* Specify address family preference */
218
static transient final int preferIPv6Address;
219
220
static class InetAddressHolder {
221
/**
222
* Reserve the original application specified hostname.
223
*
224
* The original hostname is useful for domain-based endpoint
225
* identification (see RFC 2818 and RFC 6125). If an address
226
* was created with a raw IP address, a reverse name lookup
227
* may introduce endpoint identification security issue via
228
* DNS forging.
229
*
230
* Oracle JSSE provider is using this original hostname, via
231
* jdk.internal.misc.JavaNetAccess, for SSL/TLS endpoint identification.
232
*
233
* Note: May define a new public method in the future if necessary.
234
*/
235
String originalHostName;
236
237
InetAddressHolder() {}
238
239
InetAddressHolder(String hostName, int address, int family) {
240
this.originalHostName = hostName;
241
this.hostName = hostName;
242
this.address = address;
243
this.family = family;
244
}
245
246
void init(String hostName, int family) {
247
this.originalHostName = hostName;
248
this.hostName = hostName;
249
if (family != -1) {
250
this.family = family;
251
}
252
}
253
254
String hostName;
255
256
String getHostName() {
257
return hostName;
258
}
259
260
String getOriginalHostName() {
261
return originalHostName;
262
}
263
264
/**
265
* Holds a 32-bit IPv4 address.
266
*/
267
int address;
268
269
int getAddress() {
270
return address;
271
}
272
273
/**
274
* Specifies the address family type, for instance, '1' for IPv4
275
* addresses, and '2' for IPv6 addresses.
276
*/
277
int family;
278
279
int getFamily() {
280
return family;
281
}
282
}
283
284
/* Used to store the serializable fields of InetAddress */
285
final transient InetAddressHolder holder;
286
287
InetAddressHolder holder() {
288
return holder;
289
}
290
291
/* Used to store the name service provider */
292
private static transient NameService nameService;
293
294
/**
295
* Used to store the best available hostname.
296
* Lazily initialized via a data race; safe because Strings are immutable.
297
*/
298
private transient String canonicalHostName = null;
299
300
/** use serialVersionUID from JDK 1.0.2 for interoperability */
301
@java.io.Serial
302
private static final long serialVersionUID = 3286316764910316507L;
303
304
/*
305
* Load net library into runtime, and perform initializations.
306
*/
307
static {
308
String str = GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
309
if (str == null) {
310
preferIPv6Address = PREFER_IPV4_VALUE;
311
} else if (str.equalsIgnoreCase("true")) {
312
preferIPv6Address = PREFER_IPV6_VALUE;
313
} else if (str.equalsIgnoreCase("false")) {
314
preferIPv6Address = PREFER_IPV4_VALUE;
315
} else if (str.equalsIgnoreCase("system")) {
316
preferIPv6Address = PREFER_SYSTEM_VALUE;
317
} else {
318
preferIPv6Address = PREFER_IPV4_VALUE;
319
}
320
jdk.internal.loader.BootLoader.loadLibrary("net");
321
SharedSecrets.setJavaNetInetAddressAccess(
322
new JavaNetInetAddressAccess() {
323
public String getOriginalHostName(InetAddress ia) {
324
return ia.holder.getOriginalHostName();
325
}
326
327
public InetAddress getByName(String hostName,
328
InetAddress hostAddress)
329
throws UnknownHostException
330
{
331
return InetAddress.getByName(hostName, hostAddress);
332
}
333
334
public int addressValue(Inet4Address inet4Address) {
335
return inet4Address.addressValue();
336
}
337
338
public byte[] addressBytes(Inet6Address inet6Address) {
339
return inet6Address.addressBytes();
340
}
341
}
342
);
343
init();
344
}
345
346
/**
347
* Constructor for the Socket.accept() method.
348
* This creates an empty InetAddress, which is filled in by
349
* the accept() method. This InetAddress, however, is not
350
* put in the address cache, since it is not created by name.
351
*/
352
InetAddress() {
353
holder = new InetAddressHolder();
354
}
355
356
/**
357
* Replaces the de-serialized object with an Inet4Address object.
358
*
359
* @return the alternate object to the de-serialized object.
360
*
361
* @throws ObjectStreamException if a new object replacing this
362
* object could not be created
363
*/
364
@java.io.Serial
365
private Object readResolve() throws ObjectStreamException {
366
// will replace the deserialized 'this' object
367
return new Inet4Address(holder().getHostName(), holder().getAddress());
368
}
369
370
/**
371
* Utility routine to check if the InetAddress is an
372
* IP multicast address.
373
* @return a {@code boolean} indicating if the InetAddress is
374
* an IP multicast address
375
* @since 1.1
376
*/
377
public boolean isMulticastAddress() {
378
return false;
379
}
380
381
/**
382
* Utility routine to check if the InetAddress is a wildcard address.
383
* @return a {@code boolean} indicating if the InetAddress is
384
* a wildcard address.
385
* @since 1.4
386
*/
387
public boolean isAnyLocalAddress() {
388
return false;
389
}
390
391
/**
392
* Utility routine to check if the InetAddress is a loopback address.
393
*
394
* @return a {@code boolean} indicating if the InetAddress is
395
* a loopback address; or false otherwise.
396
* @since 1.4
397
*/
398
public boolean isLoopbackAddress() {
399
return false;
400
}
401
402
/**
403
* Utility routine to check if the InetAddress is an link local address.
404
*
405
* @return a {@code boolean} indicating if the InetAddress is
406
* a link local address; or false if address is not a link local unicast address.
407
* @since 1.4
408
*/
409
public boolean isLinkLocalAddress() {
410
return false;
411
}
412
413
/**
414
* Utility routine to check if the InetAddress is a site local address.
415
*
416
* @return a {@code boolean} indicating if the InetAddress is
417
* a site local address; or false if address is not a site local unicast address.
418
* @since 1.4
419
*/
420
public boolean isSiteLocalAddress() {
421
return false;
422
}
423
424
/**
425
* Utility routine to check if the multicast address has global scope.
426
*
427
* @return a {@code boolean} indicating if the address has
428
* is a multicast address of global scope, false if it is not
429
* of global scope or it is not a multicast address
430
* @since 1.4
431
*/
432
public boolean isMCGlobal() {
433
return false;
434
}
435
436
/**
437
* Utility routine to check if the multicast address has node scope.
438
*
439
* @return a {@code boolean} indicating if the address has
440
* is a multicast address of node-local scope, false if it is not
441
* of node-local scope or it is not a multicast address
442
* @since 1.4
443
*/
444
public boolean isMCNodeLocal() {
445
return false;
446
}
447
448
/**
449
* Utility routine to check if the multicast address has link scope.
450
*
451
* @return a {@code boolean} indicating if the address has
452
* is a multicast address of link-local scope, false if it is not
453
* of link-local scope or it is not a multicast address
454
* @since 1.4
455
*/
456
public boolean isMCLinkLocal() {
457
return false;
458
}
459
460
/**
461
* Utility routine to check if the multicast address has site scope.
462
*
463
* @return a {@code boolean} indicating if the address has
464
* is a multicast address of site-local scope, false if it is not
465
* of site-local scope or it is not a multicast address
466
* @since 1.4
467
*/
468
public boolean isMCSiteLocal() {
469
return false;
470
}
471
472
/**
473
* Utility routine to check if the multicast address has organization scope.
474
*
475
* @return a {@code boolean} indicating if the address has
476
* is a multicast address of organization-local scope,
477
* false if it is not of organization-local scope
478
* or it is not a multicast address
479
* @since 1.4
480
*/
481
public boolean isMCOrgLocal() {
482
return false;
483
}
484
485
486
/**
487
* Test whether that address is reachable. Best effort is made by the
488
* implementation to try to reach the host, but firewalls and server
489
* configuration may block requests resulting in a unreachable status
490
* while some specific ports may be accessible.
491
* A typical implementation will use ICMP ECHO REQUESTs if the
492
* privilege can be obtained, otherwise it will try to establish
493
* a TCP connection on port 7 (Echo) of the destination host.
494
* <p>
495
* The timeout value, in milliseconds, indicates the maximum amount of time
496
* the try should take. If the operation times out before getting an
497
* answer, the host is deemed unreachable. A negative value will result
498
* in an IllegalArgumentException being thrown.
499
*
500
* @param timeout the time, in milliseconds, before the call aborts
501
* @return a {@code boolean} indicating if the address is reachable.
502
* @throws IOException if a network error occurs
503
* @throws IllegalArgumentException if {@code timeout} is negative.
504
* @since 1.5
505
*/
506
public boolean isReachable(int timeout) throws IOException {
507
return isReachable(null, 0 , timeout);
508
}
509
510
/**
511
* Test whether that address is reachable. Best effort is made by the
512
* implementation to try to reach the host, but firewalls and server
513
* configuration may block requests resulting in a unreachable status
514
* while some specific ports may be accessible.
515
* A typical implementation will use ICMP ECHO REQUESTs if the
516
* privilege can be obtained, otherwise it will try to establish
517
* a TCP connection on port 7 (Echo) of the destination host.
518
* <p>
519
* The {@code network interface} and {@code ttl} parameters
520
* let the caller specify which network interface the test will go through
521
* and the maximum number of hops the packets should go through.
522
* A negative value for the {@code ttl} will result in an
523
* IllegalArgumentException being thrown.
524
* <p>
525
* The timeout value, in milliseconds, indicates the maximum amount of time
526
* the try should take. If the operation times out before getting an
527
* answer, the host is deemed unreachable. A negative value will result
528
* in an IllegalArgumentException being thrown.
529
*
530
* @param netif the NetworkInterface through which the
531
* test will be done, or null for any interface
532
* @param ttl the maximum numbers of hops to try or 0 for the
533
* default
534
* @param timeout the time, in milliseconds, before the call aborts
535
* @throws IllegalArgumentException if either {@code timeout}
536
* or {@code ttl} are negative.
537
* @return a {@code boolean} indicating if the address is reachable.
538
* @throws IOException if a network error occurs
539
* @since 1.5
540
*/
541
public boolean isReachable(NetworkInterface netif, int ttl,
542
int timeout) throws IOException {
543
if (ttl < 0)
544
throw new IllegalArgumentException("ttl can't be negative");
545
if (timeout < 0)
546
throw new IllegalArgumentException("timeout can't be negative");
547
548
return impl.isReachable(this, timeout, netif, ttl);
549
}
550
551
/**
552
* Gets the host name for this IP address.
553
*
554
* <p>If this InetAddress was created with a host name,
555
* this host name will be remembered and returned;
556
* otherwise, a reverse name lookup will be performed
557
* and the result will be returned based on the system
558
* configured name lookup service. If a lookup of the name service
559
* is required, call
560
* {@link #getCanonicalHostName() getCanonicalHostName}.
561
*
562
* <p>If there is a security manager, its
563
* {@code checkConnect} method is first called
564
* with the hostname and {@code -1}
565
* as its arguments to see if the operation is allowed.
566
* If the operation is not allowed, it will return
567
* the textual representation of the IP address.
568
*
569
* @return the host name for this IP address, or if the operation
570
* is not allowed by the security check, the textual
571
* representation of the IP address.
572
*
573
* @see InetAddress#getCanonicalHostName
574
* @see SecurityManager#checkConnect
575
*/
576
public String getHostName() {
577
return getHostName(true);
578
}
579
580
/**
581
* Returns the hostname for this address.
582
* If the host is equal to null, then this address refers to any
583
* of the local machine's available network addresses.
584
* this is package private so SocketPermission can make calls into
585
* here without a security check.
586
*
587
* <p>If there is a security manager, this method first
588
* calls its {@code checkConnect} method
589
* with the hostname and {@code -1}
590
* as its arguments to see if the calling code is allowed to know
591
* the hostname for this IP address, i.e., to connect to the host.
592
* If the operation is not allowed, it will return
593
* the textual representation of the IP address.
594
*
595
* @return the host name for this IP address, or if the operation
596
* is not allowed by the security check, the textual
597
* representation of the IP address.
598
*
599
* @param check make security check if true
600
*
601
* @see SecurityManager#checkConnect
602
*/
603
String getHostName(boolean check) {
604
if (holder().getHostName() == null) {
605
holder().hostName = InetAddress.getHostFromNameService(this, check);
606
}
607
return holder().getHostName();
608
}
609
610
/**
611
* Gets the fully qualified domain name for this IP address.
612
* Best effort method, meaning we may not be able to return
613
* the FQDN depending on the underlying system configuration.
614
*
615
* <p>If there is a security manager, this method first
616
* calls its {@code checkConnect} method
617
* with the hostname and {@code -1}
618
* as its arguments to see if the calling code is allowed to know
619
* the hostname for this IP address, i.e., to connect to the host.
620
* If the operation is not allowed, it will return
621
* the textual representation of the IP address.
622
*
623
* @return the fully qualified domain name for this IP address,
624
* or if the operation is not allowed by the security check,
625
* the textual representation of the IP address.
626
*
627
* @see SecurityManager#checkConnect
628
*
629
* @since 1.4
630
*/
631
public String getCanonicalHostName() {
632
String value = canonicalHostName;
633
if (value == null)
634
canonicalHostName = value =
635
InetAddress.getHostFromNameService(this, true);
636
return value;
637
}
638
639
/**
640
* Returns the hostname for this address.
641
*
642
* <p>If there is a security manager, this method first
643
* calls its {@code checkConnect} method
644
* with the hostname and {@code -1}
645
* as its arguments to see if the calling code is allowed to know
646
* the hostname for this IP address, i.e., to connect to the host.
647
* If the operation is not allowed, it will return
648
* the textual representation of the IP address.
649
*
650
* @return the host name for this IP address, or if the operation
651
* is not allowed by the security check, the textual
652
* representation of the IP address.
653
*
654
* @param check make security check if true
655
*
656
* @see SecurityManager#checkConnect
657
*/
658
private static String getHostFromNameService(InetAddress addr, boolean check) {
659
String host = null;
660
try {
661
// first lookup the hostname
662
host = nameService.getHostByAddr(addr.getAddress());
663
664
/* check to see if calling code is allowed to know
665
* the hostname for this IP address, ie, connect to the host
666
*/
667
if (check) {
668
@SuppressWarnings("removal")
669
SecurityManager sec = System.getSecurityManager();
670
if (sec != null) {
671
sec.checkConnect(host, -1);
672
}
673
}
674
675
/* now get all the IP addresses for this hostname,
676
* and make sure one of them matches the original IP
677
* address. We do this to try and prevent spoofing.
678
*/
679
680
InetAddress[] arr = InetAddress.getAllByName0(host, check);
681
boolean ok = false;
682
683
if(arr != null) {
684
for(int i = 0; !ok && i < arr.length; i++) {
685
ok = addr.equals(arr[i]);
686
}
687
}
688
689
//XXX: if it looks a spoof just return the address?
690
if (!ok) {
691
host = addr.getHostAddress();
692
return host;
693
}
694
} catch (SecurityException e) {
695
host = addr.getHostAddress();
696
} catch (UnknownHostException e) {
697
host = addr.getHostAddress();
698
// let next provider resolve the hostname
699
}
700
return host;
701
}
702
703
/**
704
* Returns the raw IP address of this {@code InetAddress}
705
* object. The result is in network byte order: the highest order
706
* byte of the address is in {@code getAddress()[0]}.
707
*
708
* @return the raw IP address of this object.
709
*/
710
public byte[] getAddress() {
711
return null;
712
}
713
714
/**
715
* Returns the IP address string in textual presentation.
716
*
717
* @return the raw IP address in a string format.
718
* @since 1.0.2
719
*/
720
public String getHostAddress() {
721
return null;
722
}
723
724
/**
725
* Returns a hashcode for this IP address.
726
*
727
* @return a hash code value for this IP address.
728
*/
729
public int hashCode() {
730
return -1;
731
}
732
733
/**
734
* Compares this object against the specified object.
735
* The result is {@code true} if and only if the argument is
736
* not {@code null} and it represents the same IP address as
737
* this object.
738
* <p>
739
* Two instances of {@code InetAddress} represent the same IP
740
* address if the length of the byte arrays returned by
741
* {@code getAddress} is the same for both, and each of the
742
* array components is the same for the byte arrays.
743
*
744
* @param obj the object to compare against.
745
* @return {@code true} if the objects are the same;
746
* {@code false} otherwise.
747
* @see java.net.InetAddress#getAddress()
748
*/
749
public boolean equals(Object obj) {
750
return false;
751
}
752
753
/**
754
* Converts this IP address to a {@code String}. The
755
* string returned is of the form: hostname / literal IP
756
* address.
757
*
758
* If the host name is unresolved, no reverse name service lookup
759
* is performed. The hostname part will be represented by an empty string.
760
*
761
* @return a string representation of this IP address.
762
*/
763
public String toString() {
764
String hostName = holder().getHostName();
765
return Objects.toString(hostName, "")
766
+ "/" + getHostAddress();
767
}
768
769
// mapping from host name to Addresses - either NameServiceAddresses (while
770
// still being looked-up by NameService(s)) or CachedAddresses when cached
771
private static final ConcurrentMap<String, Addresses> cache =
772
new ConcurrentHashMap<>();
773
774
// CachedAddresses that have to expire are kept ordered in this NavigableSet
775
// which is scanned on each access
776
private static final NavigableSet<CachedAddresses> expirySet =
777
new ConcurrentSkipListSet<>();
778
779
// common interface
780
private interface Addresses {
781
InetAddress[] get() throws UnknownHostException;
782
}
783
784
// a holder for cached addresses with required metadata
785
private static final class CachedAddresses implements Addresses, Comparable<CachedAddresses> {
786
private static final AtomicLong seq = new AtomicLong();
787
final String host;
788
final InetAddress[] inetAddresses;
789
final long expiryTime; // time of expiry (in terms of System.nanoTime())
790
final long id = seq.incrementAndGet(); // each instance is unique
791
792
CachedAddresses(String host, InetAddress[] inetAddresses, long expiryTime) {
793
this.host = host;
794
this.inetAddresses = inetAddresses;
795
this.expiryTime = expiryTime;
796
}
797
798
@Override
799
public InetAddress[] get() throws UnknownHostException {
800
if (inetAddresses == null) {
801
throw new UnknownHostException(host);
802
}
803
return inetAddresses;
804
}
805
806
@Override
807
public int compareTo(CachedAddresses other) {
808
// natural order is expiry time -
809
// compare difference of expiry times rather than
810
// expiry times directly, to avoid possible overflow.
811
// (see System.nanoTime() recommendations...)
812
long diff = this.expiryTime - other.expiryTime;
813
if (diff < 0L) return -1;
814
if (diff > 0L) return 1;
815
// ties are broken using unique id
816
return Long.compare(this.id, other.id);
817
}
818
}
819
820
// a name service lookup based Addresses implementation which replaces itself
821
// in cache when the result is obtained
822
private static final class NameServiceAddresses implements Addresses {
823
private final String host;
824
private final InetAddress reqAddr;
825
826
NameServiceAddresses(String host, InetAddress reqAddr) {
827
this.host = host;
828
this.reqAddr = reqAddr;
829
}
830
831
@Override
832
public InetAddress[] get() throws UnknownHostException {
833
Addresses addresses;
834
// only one thread is doing lookup to name service
835
// for particular host at any time.
836
synchronized (this) {
837
// re-check that we are still us + re-install us if slot empty
838
addresses = cache.putIfAbsent(host, this);
839
if (addresses == null) {
840
// this can happen when we were replaced by CachedAddresses in
841
// some other thread, then CachedAddresses expired and were
842
// removed from cache while we were waiting for lock...
843
addresses = this;
844
}
845
// still us ?
846
if (addresses == this) {
847
// lookup name services
848
InetAddress[] inetAddresses;
849
UnknownHostException ex;
850
int cachePolicy;
851
try {
852
inetAddresses = getAddressesFromNameService(host, reqAddr);
853
ex = null;
854
cachePolicy = InetAddressCachePolicy.get();
855
} catch (UnknownHostException uhe) {
856
inetAddresses = null;
857
ex = uhe;
858
cachePolicy = InetAddressCachePolicy.getNegative();
859
}
860
// remove or replace us with cached addresses according to cachePolicy
861
if (cachePolicy == InetAddressCachePolicy.NEVER) {
862
cache.remove(host, this);
863
} else {
864
CachedAddresses cachedAddresses = new CachedAddresses(
865
host,
866
inetAddresses,
867
cachePolicy == InetAddressCachePolicy.FOREVER
868
? 0L
869
// cachePolicy is in [s] - we need [ns]
870
: System.nanoTime() + 1000_000_000L * cachePolicy
871
);
872
if (cache.replace(host, this, cachedAddresses) &&
873
cachePolicy != InetAddressCachePolicy.FOREVER) {
874
// schedule expiry
875
expirySet.add(cachedAddresses);
876
}
877
}
878
if (inetAddresses == null) {
879
throw ex == null ? new UnknownHostException(host) : ex;
880
}
881
return inetAddresses;
882
}
883
// else addresses != this
884
}
885
// delegate to different addresses when we are already replaced
886
// but outside of synchronized block to avoid any chance of dead-locking
887
return addresses.get();
888
}
889
}
890
891
/**
892
* NameService provides host and address lookup service
893
*
894
* @since 9
895
*/
896
private interface NameService {
897
898
/**
899
* Lookup a host mapping by name. Retrieve the IP addresses
900
* associated with a host
901
*
902
* @param host the specified hostname
903
* @return array of IP addresses for the requested host
904
* @throws UnknownHostException
905
* if no IP address for the {@code host} could be found
906
*/
907
InetAddress[] lookupAllHostAddr(String host)
908
throws UnknownHostException;
909
910
/**
911
* Lookup the host corresponding to the IP address provided
912
*
913
* @param addr byte array representing an IP address
914
* @return {@code String} representing the host name mapping
915
* @throws UnknownHostException
916
* if no host found for the specified IP address
917
*/
918
String getHostByAddr(byte[] addr) throws UnknownHostException;
919
920
}
921
922
/**
923
* The default NameService implementation, which delegates to the underlying
924
* OS network libraries to resolve host address mappings.
925
*
926
* @since 9
927
*/
928
private static final class PlatformNameService implements NameService {
929
930
public InetAddress[] lookupAllHostAddr(String host)
931
throws UnknownHostException
932
{
933
return impl.lookupAllHostAddr(host);
934
}
935
936
public String getHostByAddr(byte[] addr)
937
throws UnknownHostException
938
{
939
return impl.getHostByAddr(addr);
940
}
941
}
942
943
/**
944
* The HostsFileNameService provides host address mapping
945
* by reading the entries in a hosts file, which is specified by
946
* {@code jdk.net.hosts.file} system property
947
*
948
* <p>The file format is that which corresponds with the /etc/hosts file
949
* IP Address host alias list.
950
*
951
* <p>When the file lookup is enabled it replaces the default NameService
952
* implementation
953
*
954
* @since 9
955
*/
956
private static final class HostsFileNameService implements NameService {
957
958
private static final InetAddress[] EMPTY_ARRAY = new InetAddress[0];
959
960
// Specify if only IPv4 addresses should be returned by HostsFileService implementation
961
private static final boolean preferIPv4Stack = Boolean.parseBoolean(
962
GetPropertyAction.privilegedGetProperty("java.net.preferIPv4Stack"));
963
964
private final String hostsFile;
965
966
public HostsFileNameService(String hostsFileName) {
967
this.hostsFile = hostsFileName;
968
}
969
970
/**
971
* Lookup the host name corresponding to the IP address provided.
972
* Search the configured host file a host name corresponding to
973
* the specified IP address.
974
*
975
* @param addr byte array representing an IP address
976
* @return {@code String} representing the host name mapping
977
* @throws UnknownHostException
978
* if no host found for the specified IP address
979
*/
980
@Override
981
public String getHostByAddr(byte[] addr) throws UnknownHostException {
982
String hostEntry;
983
String host = null;
984
985
try (Scanner hostsFileScanner = new Scanner(new File(hostsFile),
986
UTF_8.INSTANCE))
987
{
988
while (hostsFileScanner.hasNextLine()) {
989
hostEntry = hostsFileScanner.nextLine();
990
if (!hostEntry.startsWith("#")) {
991
hostEntry = removeComments(hostEntry);
992
String[] mapping = hostEntry.split("\\s+");
993
if (mapping.length >= 2 &&
994
Arrays.equals(addr, createAddressByteArray(mapping[0]))) {
995
host = mapping[1];
996
break;
997
}
998
}
999
}
1000
} catch (IOException e) {
1001
throw new UnknownHostException("Unable to resolve address "
1002
+ Arrays.toString(addr) + " as hosts file " + hostsFile
1003
+ " not found ");
1004
}
1005
1006
if ((host == null) || (host.isEmpty()) || (host.equals(" "))) {
1007
throw new UnknownHostException("Requested address "
1008
+ Arrays.toString(addr)
1009
+ " resolves to an invalid entry in hosts file "
1010
+ hostsFile);
1011
}
1012
return host;
1013
}
1014
1015
/**
1016
* <p>Lookup a host mapping by name. Retrieve the IP addresses
1017
* associated with a host.
1018
*
1019
* <p>Search the configured hosts file for the addresses associated
1020
* with the specified host name.
1021
*
1022
* @param host the specified hostname
1023
* @return array of IP addresses for the requested host
1024
* @throws UnknownHostException
1025
* if no IP address for the {@code host} could be found
1026
*/
1027
public InetAddress[] lookupAllHostAddr(String host)
1028
throws UnknownHostException {
1029
String hostEntry;
1030
String addrStr;
1031
byte addr[];
1032
List<InetAddress> inetAddresses = new ArrayList<>();
1033
List<InetAddress> inet4Addresses = new ArrayList<>();
1034
List<InetAddress> inet6Addresses = new ArrayList<>();
1035
1036
// lookup the file and create a list InetAddress for the specified host
1037
try (Scanner hostsFileScanner = new Scanner(new File(hostsFile),
1038
UTF_8.INSTANCE)) {
1039
while (hostsFileScanner.hasNextLine()) {
1040
hostEntry = hostsFileScanner.nextLine();
1041
if (!hostEntry.startsWith("#")) {
1042
hostEntry = removeComments(hostEntry);
1043
if (hostEntry.contains(host)) {
1044
addrStr = extractHostAddr(hostEntry, host);
1045
if ((addrStr != null) && (!addrStr.isEmpty())) {
1046
addr = createAddressByteArray(addrStr);
1047
if (addr != null) {
1048
InetAddress address = InetAddress.getByAddress(host, addr);
1049
inetAddresses.add(address);
1050
if (address instanceof Inet4Address) {
1051
inet4Addresses.add(address);
1052
}
1053
if (address instanceof Inet6Address) {
1054
inet6Addresses.add(address);
1055
}
1056
}
1057
}
1058
}
1059
}
1060
}
1061
} catch (IOException e) {
1062
throw new UnknownHostException("Unable to resolve host " + host
1063
+ " as hosts file " + hostsFile + " not found ");
1064
}
1065
1066
List<InetAddress> res;
1067
// If "preferIPv4Stack" system property is set to "true" then return
1068
// only IPv4 addresses
1069
if (preferIPv4Stack) {
1070
res = inet4Addresses;
1071
} else {
1072
// Otherwise, analyse "preferIPv6Addresses" value
1073
res = switch (preferIPv6Address) {
1074
case PREFER_IPV4_VALUE -> concatAddresses(inet4Addresses, inet6Addresses);
1075
case PREFER_IPV6_VALUE -> concatAddresses(inet6Addresses, inet4Addresses);
1076
default -> inetAddresses;
1077
};
1078
}
1079
1080
if (res.isEmpty()) {
1081
throw new UnknownHostException("Unable to resolve host " + host
1082
+ " in hosts file " + hostsFile);
1083
}
1084
return res.toArray(EMPTY_ARRAY);
1085
}
1086
1087
private static List<InetAddress> concatAddresses(List<InetAddress> firstPart,
1088
List<InetAddress> secondPart) {
1089
List<InetAddress> result = new ArrayList<>(firstPart);
1090
result.addAll(secondPart);
1091
return result;
1092
}
1093
1094
private String removeComments(String hostsEntry) {
1095
String filteredEntry = hostsEntry;
1096
int hashIndex;
1097
1098
if ((hashIndex = hostsEntry.indexOf("#")) != -1) {
1099
filteredEntry = hostsEntry.substring(0, hashIndex);
1100
}
1101
return filteredEntry;
1102
}
1103
1104
private byte [] createAddressByteArray(String addrStr) {
1105
byte[] addrArray;
1106
// check if IPV4 address - most likely
1107
try {
1108
addrArray = IPAddressUtil.validateNumericFormatV4(addrStr);
1109
} catch (IllegalArgumentException iae) {
1110
return null;
1111
}
1112
if (addrArray == null) {
1113
addrArray = IPAddressUtil.textToNumericFormatV6(addrStr);
1114
}
1115
return addrArray;
1116
}
1117
1118
/** host to ip address mapping */
1119
private String extractHostAddr(String hostEntry, String host) {
1120
String[] mapping = hostEntry.split("\\s+");
1121
String hostAddr = null;
1122
1123
if (mapping.length >= 2) {
1124
// look at the host aliases
1125
for (int i = 1; i < mapping.length; i++) {
1126
if (mapping[i].equalsIgnoreCase(host)) {
1127
hostAddr = mapping[0];
1128
}
1129
}
1130
}
1131
return hostAddr;
1132
}
1133
}
1134
1135
static final InetAddressImpl impl;
1136
1137
static {
1138
// create the impl
1139
impl = InetAddressImplFactory.create();
1140
1141
// create name service
1142
nameService = createNameService();
1143
}
1144
1145
/**
1146
* Create an instance of the NameService interface based on
1147
* the setting of the {@code jdk.net.hosts.file} system property.
1148
*
1149
* <p>The default NameService is the PlatformNameService, which typically
1150
* delegates name and address resolution calls to the underlying
1151
* OS network libraries.
1152
*
1153
* <p> A HostsFileNameService is created if the {@code jdk.net.hosts.file}
1154
* system property is set. If the specified file doesn't exist, the name or
1155
* address lookup will result in an UnknownHostException. Thus, non existent
1156
* hosts file is handled as if the file is empty.
1157
*
1158
* @return a NameService
1159
*/
1160
private static NameService createNameService() {
1161
1162
String hostsFileName =
1163
GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file");
1164
NameService theNameService;
1165
if (hostsFileName != null) {
1166
theNameService = new HostsFileNameService(hostsFileName);
1167
} else {
1168
theNameService = new PlatformNameService();
1169
}
1170
return theNameService;
1171
}
1172
1173
/**
1174
* Creates an InetAddress based on the provided host name and IP address.
1175
* No name service is checked for the validity of the address.
1176
*
1177
* <p> The host name can either be a machine name, such as
1178
* "{@code www.example.com}", or a textual representation of its IP
1179
* address.
1180
* <p> No validity checking is done on the host name either.
1181
*
1182
* <p> If addr specifies an IPv4 address an instance of Inet4Address
1183
* will be returned; otherwise, an instance of Inet6Address
1184
* will be returned.
1185
*
1186
* <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
1187
* must be 16 bytes long
1188
*
1189
* @param host the specified host
1190
* @param addr the raw IP address in network byte order
1191
* @return an InetAddress object created from the raw IP address.
1192
* @throws UnknownHostException if IP address is of illegal length
1193
* @since 1.4
1194
*/
1195
public static InetAddress getByAddress(String host, byte[] addr)
1196
throws UnknownHostException {
1197
if (host != null && !host.isEmpty() && host.charAt(0) == '[') {
1198
if (host.charAt(host.length()-1) == ']') {
1199
host = host.substring(1, host.length() -1);
1200
}
1201
}
1202
if (addr != null) {
1203
if (addr.length == Inet4Address.INADDRSZ) {
1204
return new Inet4Address(host, addr);
1205
} else if (addr.length == Inet6Address.INADDRSZ) {
1206
byte[] newAddr
1207
= IPAddressUtil.convertFromIPv4MappedAddress(addr);
1208
if (newAddr != null) {
1209
return new Inet4Address(host, newAddr);
1210
} else {
1211
return new Inet6Address(host, addr);
1212
}
1213
}
1214
}
1215
throw new UnknownHostException("addr is of illegal length");
1216
}
1217
1218
1219
/**
1220
* Determines the IP address of a host, given the host's name.
1221
*
1222
* <p> The host name can either be a machine name, such as
1223
* "{@code www.example.com}", or a textual representation of its
1224
* IP address. If a literal IP address is supplied, only the
1225
* validity of the address format is checked.
1226
*
1227
* <p> For {@code host} specified in literal IPv6 address,
1228
* either the form defined in RFC 2732 or the literal IPv6 address
1229
* format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
1230
* supported. See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
1231
* scoped addresses.
1232
*
1233
* <p> If the host is {@code null} or {@code host.length()} is equal
1234
* to zero, then an {@code InetAddress} representing an address of the
1235
* loopback interface is returned.
1236
* See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC&nbsp;3330</a>
1237
* section&nbsp;2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>
1238
* section&nbsp;2.5.3.
1239
*
1240
* <p> If there is a security manager, and {@code host} is not {@code null}
1241
* or {@code host.length() } is not equal to zero, the security manager's
1242
* {@code checkConnect} method is called with the hostname and {@code -1}
1243
* as its arguments to determine if the operation is allowed.
1244
*
1245
* @param host the specified host, or {@code null}.
1246
* @return an IP address for the given host name.
1247
* @throws UnknownHostException if no IP address for the
1248
* {@code host} could be found, or if a scope_id was specified
1249
* for a global IPv6 address.
1250
* @throws SecurityException if a security manager exists
1251
* and its checkConnect method doesn't allow the operation
1252
*/
1253
public static InetAddress getByName(String host)
1254
throws UnknownHostException {
1255
return InetAddress.getAllByName(host)[0];
1256
}
1257
1258
// called from deployment cache manager
1259
private static InetAddress getByName(String host, InetAddress reqAddr)
1260
throws UnknownHostException {
1261
return InetAddress.getAllByName(host, reqAddr)[0];
1262
}
1263
1264
/**
1265
* Given the name of a host, returns an array of its IP addresses,
1266
* based on the configured name service on the system.
1267
*
1268
* <p> The host name can either be a machine name, such as
1269
* "{@code www.example.com}", or a textual representation of its IP
1270
* address. If a literal IP address is supplied, only the
1271
* validity of the address format is checked.
1272
*
1273
* <p> For {@code host} specified in <i>literal IPv6 address</i>,
1274
* either the form defined in RFC 2732 or the literal IPv6 address
1275
* format defined in RFC 2373 is accepted. A literal IPv6 address may
1276
* also be qualified by appending a scoped zone identifier or scope_id.
1277
* The syntax and usage of scope_ids is described
1278
* <a href="Inet6Address.html#scoped">here</a>.
1279
*
1280
* <p> If the host is {@code null} or {@code host.length()} is equal
1281
* to zero, then an {@code InetAddress} representing an address of the
1282
* loopback interface is returned.
1283
* See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC&nbsp;3330</a>
1284
* section&nbsp;2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>
1285
* section&nbsp;2.5.3. </p>
1286
*
1287
* <p> If there is a security manager, and {@code host} is not {@code null}
1288
* or {@code host.length() } is not equal to zero, the security manager's
1289
* {@code checkConnect} method is called with the hostname and {@code -1}
1290
* as its arguments to determine if the operation is allowed.
1291
*
1292
* @param host the name of the host, or {@code null}.
1293
* @return an array of all the IP addresses for a given host name.
1294
*
1295
* @throws UnknownHostException if no IP address for the
1296
* {@code host} could be found, or if a scope_id was specified
1297
* for a global IPv6 address.
1298
* @throws SecurityException if a security manager exists and its
1299
* {@code checkConnect} method doesn't allow the operation.
1300
*
1301
* @see SecurityManager#checkConnect
1302
*/
1303
public static InetAddress[] getAllByName(String host)
1304
throws UnknownHostException {
1305
return getAllByName(host, null);
1306
}
1307
1308
private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
1309
throws UnknownHostException {
1310
1311
if (host == null || host.isEmpty()) {
1312
InetAddress[] ret = new InetAddress[1];
1313
ret[0] = impl.loopbackAddress();
1314
return ret;
1315
}
1316
1317
boolean ipv6Expected = false;
1318
if (host.charAt(0) == '[') {
1319
// This is supposed to be an IPv6 literal
1320
if (host.length() > 2 && host.charAt(host.length()-1) == ']') {
1321
host = host.substring(1, host.length() -1);
1322
ipv6Expected = true;
1323
} else {
1324
// This was supposed to be a IPv6 address, but it's not!
1325
throw new UnknownHostException(host + ": invalid IPv6 address");
1326
}
1327
}
1328
1329
// if host is an IP address, we won't do further lookup
1330
if (IPAddressUtil.digit(host.charAt(0), 16) != -1
1331
|| (host.charAt(0) == ':')) {
1332
byte[] addr;
1333
int numericZone = -1;
1334
String ifname = null;
1335
// see if it is IPv4 address
1336
try {
1337
addr = IPAddressUtil.validateNumericFormatV4(host);
1338
} catch (IllegalArgumentException iae) {
1339
var uhe = new UnknownHostException(host);
1340
uhe.initCause(iae);
1341
throw uhe;
1342
}
1343
if (addr == null) {
1344
// This is supposed to be an IPv6 literal
1345
// Check if a numeric or string zone id is present
1346
int pos;
1347
if ((pos=host.indexOf ('%')) != -1) {
1348
numericZone = checkNumericZone (host);
1349
if (numericZone == -1) { /* remainder of string must be an ifname */
1350
ifname = host.substring (pos+1);
1351
}
1352
}
1353
if ((addr = IPAddressUtil.textToNumericFormatV6(host)) == null && host.contains(":")) {
1354
throw new UnknownHostException(host + ": invalid IPv6 address");
1355
}
1356
} else if (ipv6Expected) {
1357
// Means an IPv4 literal between brackets!
1358
throw new UnknownHostException("["+host+"]");
1359
}
1360
InetAddress[] ret = new InetAddress[1];
1361
if(addr != null) {
1362
if (addr.length == Inet4Address.INADDRSZ) {
1363
ret[0] = new Inet4Address(null, addr);
1364
} else {
1365
if (ifname != null) {
1366
ret[0] = new Inet6Address(null, addr, ifname);
1367
} else {
1368
ret[0] = new Inet6Address(null, addr, numericZone);
1369
}
1370
}
1371
return ret;
1372
}
1373
} else if (ipv6Expected) {
1374
// We were expecting an IPv6 Literal, but got something else
1375
throw new UnknownHostException("["+host+"]");
1376
}
1377
return getAllByName0(host, reqAddr, true, true);
1378
}
1379
1380
/**
1381
* Returns the loopback address.
1382
* <p>
1383
* The InetAddress returned will represent the IPv4
1384
* loopback address, 127.0.0.1, or the IPv6 loopback
1385
* address, ::1. The IPv4 loopback address returned
1386
* is only one of many in the form 127.*.*.*
1387
*
1388
* @return the InetAddress loopback instance.
1389
* @since 1.7
1390
*/
1391
public static InetAddress getLoopbackAddress() {
1392
return impl.loopbackAddress();
1393
}
1394
1395
1396
/**
1397
* check if the literal address string has %nn appended
1398
* returns -1 if not, or the numeric value otherwise.
1399
*
1400
* %nn may also be a string that represents the displayName of
1401
* a currently available NetworkInterface.
1402
*/
1403
private static int checkNumericZone (String s) throws UnknownHostException {
1404
int percent = s.indexOf ('%');
1405
int slen = s.length();
1406
int digit, zone=0;
1407
if (percent == -1) {
1408
return -1;
1409
}
1410
for (int i=percent+1; i<slen; i++) {
1411
char c = s.charAt(i);
1412
if (c == ']') {
1413
if (i == percent+1) {
1414
/* empty per-cent field */
1415
return -1;
1416
}
1417
break;
1418
}
1419
if ((digit = Character.digit (c, 10)) < 0) {
1420
return -1;
1421
}
1422
zone = (zone * 10) + digit;
1423
}
1424
return zone;
1425
}
1426
1427
private static InetAddress[] getAllByName0 (String host)
1428
throws UnknownHostException
1429
{
1430
return getAllByName0(host, true);
1431
}
1432
1433
/**
1434
* package private so SocketPermission can call it
1435
*/
1436
static InetAddress[] getAllByName0 (String host, boolean check)
1437
throws UnknownHostException {
1438
return getAllByName0 (host, null, check, true);
1439
}
1440
1441
/**
1442
* Designated lookup method.
1443
*
1444
* @param host host name to look up
1445
* @param reqAddr requested address to be the 1st in returned array
1446
* @param check perform security check
1447
* @param useCache use cached value if not expired else always
1448
* perform name service lookup (and cache the result)
1449
* @return array of InetAddress(es)
1450
* @throws UnknownHostException if host name is not found
1451
*/
1452
private static InetAddress[] getAllByName0(String host,
1453
InetAddress reqAddr,
1454
boolean check,
1455
boolean useCache)
1456
throws UnknownHostException {
1457
1458
/* If it gets here it is presumed to be a hostname */
1459
1460
/* make sure the connection to the host is allowed, before we
1461
* give out a hostname
1462
*/
1463
if (check) {
1464
@SuppressWarnings("removal")
1465
SecurityManager security = System.getSecurityManager();
1466
if (security != null) {
1467
security.checkConnect(host, -1);
1468
}
1469
}
1470
1471
// remove expired addresses from cache - expirySet keeps them ordered
1472
// by expiry time so we only need to iterate the prefix of the NavigableSet...
1473
long now = System.nanoTime();
1474
for (CachedAddresses caddrs : expirySet) {
1475
// compare difference of time instants rather than
1476
// time instants directly, to avoid possible overflow.
1477
// (see System.nanoTime() recommendations...)
1478
if ((caddrs.expiryTime - now) < 0L) {
1479
// ConcurrentSkipListSet uses weakly consistent iterator,
1480
// so removing while iterating is OK...
1481
if (expirySet.remove(caddrs)) {
1482
// ... remove from cache
1483
cache.remove(caddrs.host, caddrs);
1484
}
1485
} else {
1486
// we encountered 1st element that expires in future
1487
break;
1488
}
1489
}
1490
1491
// look-up or remove from cache
1492
Addresses addrs;
1493
if (useCache) {
1494
addrs = cache.get(host);
1495
} else {
1496
addrs = cache.remove(host);
1497
if (addrs != null) {
1498
if (addrs instanceof CachedAddresses) {
1499
// try removing from expirySet too if CachedAddresses
1500
expirySet.remove(addrs);
1501
}
1502
addrs = null;
1503
}
1504
}
1505
1506
if (addrs == null) {
1507
// create a NameServiceAddresses instance which will look up
1508
// the name service and install it within cache...
1509
Addresses oldAddrs = cache.putIfAbsent(
1510
host,
1511
addrs = new NameServiceAddresses(host, reqAddr)
1512
);
1513
if (oldAddrs != null) { // lost putIfAbsent race
1514
addrs = oldAddrs;
1515
}
1516
}
1517
1518
// ask Addresses to get an array of InetAddress(es) and clone it
1519
return addrs.get().clone();
1520
}
1521
1522
static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
1523
throws UnknownHostException
1524
{
1525
InetAddress[] addresses = null;
1526
UnknownHostException ex = null;
1527
1528
try {
1529
addresses = nameService.lookupAllHostAddr(host);
1530
} catch (UnknownHostException uhe) {
1531
if (host.equalsIgnoreCase("localhost")) {
1532
addresses = new InetAddress[] { impl.loopbackAddress() };
1533
}
1534
else {
1535
ex = uhe;
1536
}
1537
}
1538
1539
if (addresses == null) {
1540
throw ex == null ? new UnknownHostException(host) : ex;
1541
}
1542
1543
// More to do?
1544
if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
1545
// Find it?
1546
int i = 1;
1547
for (; i < addresses.length; i++) {
1548
if (addresses[i].equals(reqAddr)) {
1549
break;
1550
}
1551
}
1552
// Rotate
1553
if (i < addresses.length) {
1554
InetAddress tmp, tmp2 = reqAddr;
1555
for (int j = 0; j < i; j++) {
1556
tmp = addresses[j];
1557
addresses[j] = tmp2;
1558
tmp2 = tmp;
1559
}
1560
addresses[i] = tmp2;
1561
}
1562
}
1563
1564
return addresses;
1565
}
1566
1567
/**
1568
* Returns an {@code InetAddress} object given the raw IP address .
1569
* The argument is in network byte order: the highest order
1570
* byte of the address is in {@code getAddress()[0]}.
1571
*
1572
* <p> This method doesn't block, i.e. no reverse name service lookup
1573
* is performed.
1574
*
1575
* <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
1576
* must be 16 bytes long
1577
*
1578
* @param addr the raw IP address in network byte order
1579
* @return an InetAddress object created from the raw IP address.
1580
* @throws UnknownHostException if IP address is of illegal length
1581
* @since 1.4
1582
*/
1583
public static InetAddress getByAddress(byte[] addr)
1584
throws UnknownHostException {
1585
return getByAddress(null, addr);
1586
}
1587
1588
private static final class CachedLocalHost {
1589
final String host;
1590
final InetAddress addr;
1591
final long expiryTime = System.nanoTime() + 5000_000_000L; // now + 5s;
1592
1593
CachedLocalHost(String host, InetAddress addr) {
1594
this.host = host;
1595
this.addr = addr;
1596
}
1597
}
1598
1599
private static volatile CachedLocalHost cachedLocalHost;
1600
1601
/**
1602
* Returns the address of the local host. This is achieved by retrieving
1603
* the name of the host from the system, then resolving that name into
1604
* an {@code InetAddress}.
1605
*
1606
* <P>Note: The resolved address may be cached for a short period of time.
1607
* </P>
1608
*
1609
* <p>If there is a security manager, its
1610
* {@code checkConnect} method is called
1611
* with the local host name and {@code -1}
1612
* as its arguments to see if the operation is allowed.
1613
* If the operation is not allowed, an InetAddress representing
1614
* the loopback address is returned.
1615
*
1616
* @return the address of the local host.
1617
*
1618
* @throws UnknownHostException if the local host name could not
1619
* be resolved into an address.
1620
*
1621
* @see SecurityManager#checkConnect
1622
* @see java.net.InetAddress#getByName(java.lang.String)
1623
*/
1624
public static InetAddress getLocalHost() throws UnknownHostException {
1625
1626
@SuppressWarnings("removal")
1627
SecurityManager security = System.getSecurityManager();
1628
try {
1629
// is cached data still valid?
1630
CachedLocalHost clh = cachedLocalHost;
1631
if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) {
1632
if (security != null) {
1633
security.checkConnect(clh.host, -1);
1634
}
1635
return clh.addr;
1636
}
1637
1638
String local = impl.getLocalHostName();
1639
1640
if (security != null) {
1641
security.checkConnect(local, -1);
1642
}
1643
1644
InetAddress localAddr;
1645
if (local.equals("localhost")) {
1646
// shortcut for "localhost" host name
1647
localAddr = impl.loopbackAddress();
1648
} else {
1649
// call getAllByName0 without security checks and
1650
// without using cached data
1651
try {
1652
localAddr = getAllByName0(local, null, false, false)[0];
1653
} catch (UnknownHostException uhe) {
1654
// Rethrow with a more informative error message.
1655
UnknownHostException uhe2 =
1656
new UnknownHostException(local + ": " +
1657
uhe.getMessage());
1658
uhe2.initCause(uhe);
1659
throw uhe2;
1660
}
1661
}
1662
cachedLocalHost = new CachedLocalHost(local, localAddr);
1663
return localAddr;
1664
} catch (java.lang.SecurityException e) {
1665
return impl.loopbackAddress();
1666
}
1667
}
1668
1669
/**
1670
* Perform class load-time initializations.
1671
*/
1672
private static native void init();
1673
1674
1675
/*
1676
* Returns the InetAddress representing anyLocalAddress
1677
* (typically 0.0.0.0 or ::0)
1678
*/
1679
static InetAddress anyLocalAddress() {
1680
return impl.anyLocalAddress();
1681
}
1682
1683
/*
1684
* Load and instantiate an underlying impl class
1685
*/
1686
static InetAddressImpl loadImpl(String implName) {
1687
Object impl = null;
1688
1689
/*
1690
* Property "impl.prefix" will be prepended to the classname
1691
* of the implementation object we instantiate, to which we
1692
* delegate the real work (like native methods). This
1693
* property can vary across implementations of the java.
1694
* classes. The default is an empty String "".
1695
*/
1696
String prefix = GetPropertyAction.privilegedGetProperty("impl.prefix", "");
1697
try {
1698
@SuppressWarnings("deprecation")
1699
Object tmp = Class.forName("java.net." + prefix + implName).newInstance();
1700
impl = tmp;
1701
} catch (ClassNotFoundException e) {
1702
System.err.println("Class not found: java.net." + prefix +
1703
implName + ":\ncheck impl.prefix property " +
1704
"in your properties file.");
1705
} catch (InstantiationException e) {
1706
System.err.println("Could not instantiate: java.net." + prefix +
1707
implName + ":\ncheck impl.prefix property " +
1708
"in your properties file.");
1709
} catch (IllegalAccessException e) {
1710
System.err.println("Cannot access class: java.net." + prefix +
1711
implName + ":\ncheck impl.prefix property " +
1712
"in your properties file.");
1713
}
1714
1715
if (impl == null) {
1716
try {
1717
@SuppressWarnings("deprecation")
1718
Object tmp = Class.forName(implName).newInstance();
1719
impl = tmp;
1720
} catch (Exception e) {
1721
throw new Error("System property impl.prefix incorrect");
1722
}
1723
}
1724
1725
return (InetAddressImpl) impl;
1726
}
1727
1728
/**
1729
* Initializes an empty InetAddress.
1730
*/
1731
@java.io.Serial
1732
private void readObjectNoData () {
1733
if (getClass().getClassLoader() != null) {
1734
throw new SecurityException ("invalid address type");
1735
}
1736
}
1737
1738
private static final jdk.internal.misc.Unsafe UNSAFE
1739
= jdk.internal.misc.Unsafe.getUnsafe();
1740
private static final long FIELDS_OFFSET
1741
= UNSAFE.objectFieldOffset(InetAddress.class, "holder");
1742
1743
/**
1744
* Restores the state of this object from the stream.
1745
*
1746
* @param s the {@code ObjectInputStream} from which data is read
1747
* @throws IOException if an I/O error occurs
1748
* @throws ClassNotFoundException if a serialized class cannot be loaded
1749
*/
1750
@java.io.Serial
1751
private void readObject (ObjectInputStream s) throws
1752
IOException, ClassNotFoundException {
1753
if (getClass().getClassLoader() != null) {
1754
throw new SecurityException ("invalid address type");
1755
}
1756
GetField gf = s.readFields();
1757
String host = (String)gf.get("hostName", null);
1758
int address = gf.get("address", 0);
1759
int family = gf.get("family", 0);
1760
if (family != IPv4 && family != IPv6) {
1761
throw new InvalidObjectException("invalid address family type: " + family);
1762
}
1763
InetAddressHolder h = new InetAddressHolder(host, address, family);
1764
UNSAFE.putReference(this, FIELDS_OFFSET, h);
1765
}
1766
1767
/* needed because the serializable fields no longer exist */
1768
1769
/**
1770
* @serialField hostName String the hostname for this address
1771
* @serialField address int holds a 32-bit IPv4 address.
1772
* @serialField family int specifies the address family type, for instance,
1773
* {@code '1'} for IPv4 addresses, and {@code '2'} for IPv6 addresses.
1774
*/
1775
@java.io.Serial
1776
private static final ObjectStreamField[] serialPersistentFields = {
1777
new ObjectStreamField("hostName", String.class),
1778
new ObjectStreamField("address", int.class),
1779
new ObjectStreamField("family", int.class),
1780
};
1781
1782
/**
1783
* Writes the state of this object to the stream.
1784
*
1785
* @param s the {@code ObjectOutputStream} to which data is written
1786
* @throws IOException if an I/O error occurs
1787
*/
1788
@java.io.Serial
1789
private void writeObject (ObjectOutputStream s) throws
1790
IOException {
1791
if (getClass().getClassLoader() != null) {
1792
throw new SecurityException ("invalid address type");
1793
}
1794
PutField pf = s.putFields();
1795
pf.put("hostName", holder().getHostName());
1796
pf.put("address", holder().getAddress());
1797
pf.put("family", holder().getFamily());
1798
s.writeFields();
1799
}
1800
}
1801
1802
/*
1803
* Simple factory to create the impl
1804
*/
1805
class InetAddressImplFactory {
1806
1807
static InetAddressImpl create() {
1808
return InetAddress.loadImpl(isIPv6Supported() ?
1809
"Inet6AddressImpl" : "Inet4AddressImpl");
1810
}
1811
1812
static native boolean isIPv6Supported();
1813
}
1814
1815