1 /*
2 * Copyright (c) 2000, 2018, 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.io.IOException;
29 import java.io.InvalidObjectException;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.io.ObjectStreamField;
33 import java.util.Enumeration;
34 import java.util.Arrays;
35
36 /**
37 * This class represents an Internet Protocol version 6 (IPv6) address.
38 * Defined by <a href="http://www.ietf.org/rfc/rfc2373.txt">
39 * <i>RFC 2373: IP Version 6 Addressing Architecture</i></a>.
40 *
41 * <h3> <a id="format">Textual representation of IP addresses</a> </h3>
42 *
43 * Textual representation of IPv6 address used as input to methods
44 * takes one of the following forms:
45 *
46 * <ol>
47 * <li><p> <a id="lform">The preferred form</a> is x:x:x:x:x:x:x:x,
48 * where the 'x's are
49 * the hexadecimal values of the eight 16-bit pieces of the
50 * address. This is the full form. For example,
51 *
52 * <blockquote><ul style="list-style-type:none">
53 * <li>{@code 1080:0:0:0:8:800:200C:417A}</li>
54 * </ul></blockquote>
55 *
56 * <p> Note that it is not necessary to write the leading zeros in
57 * an individual field. However, there must be at least one numeral
58 * in every field, except as described below.</li>
59 *
60 * <li><p> Due to some methods of allocating certain styles of IPv6
61 * addresses, it will be common for addresses to contain long
62 * strings of zero bits. In order to make writing addresses
63 * containing zero bits easier, a special syntax is available to
64 * compress the zeros. The use of "::" indicates multiple groups
65 * of 16-bits of zeros. The "::" can only appear once in an address.
66 * The "::" can also be used to compress the leading and/or trailing
67 * zeros in an address. For example,
68 *
69 * <blockquote><ul style="list-style-type:none">
70 * <li>{@code 1080::8:800:200C:417A}</li>
71 * </ul></blockquote>
72 *
73 * <li><p> An alternative form that is sometimes more convenient
74 * when dealing with a mixed environment of IPv4 and IPv6 nodes is
75 * x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values
76 * of the six high-order 16-bit pieces of the address, and the 'd's
77 * are the decimal values of the four low-order 8-bit pieces of the
78 * standard IPv4 representation address, for example,
79 *
80 * <blockquote><ul style="list-style-type:none">
81 * <li>{@code ::FFFF:129.144.52.38}</li>
82 * <li>{@code ::129.144.52.38}</li>
83 * </ul></blockquote>
84 *
85 * <p> where "::FFFF:d.d.d.d" and "::d.d.d.d" are, respectively, the
86 * general forms of an IPv4-mapped IPv6 address and an
87 * IPv4-compatible IPv6 address. Note that the IPv4 portion must be
88 * in the "d.d.d.d" form. The following forms are invalid:
89 *
90 * <blockquote><ul style="list-style-type:none">
91 * <li>{@code ::FFFF:d.d.d}</li>
92 * <li>{@code ::FFFF:d.d}</li>
93 * <li>{@code ::d.d.d}</li>
94 * <li>{@code ::d.d}</li>
95 * </ul></blockquote>
96 *
97 * <p> The following form:
98 *
99 * <blockquote><ul style="list-style-type:none">
100 * <li>{@code ::FFFF:d}</li>
101 * </ul></blockquote>
102 *
103 * <p> is valid, however it is an unconventional representation of
104 * the IPv4-compatible IPv6 address,
105 *
106 * <blockquote><ul style="list-style-type:none">
107 * <li>{@code ::255.255.0.d}</li>
108 * </ul></blockquote>
109 *
110 * <p> while "::d" corresponds to the general IPv6 address
111 * "0:0:0:0:0:0:0:d".</li>
112 * </ol>
113 *
114 * <p> For methods that return a textual representation as output
115 * value, the full form is used. Inet6Address will return the full
116 * form because it is unambiguous when used in combination with other
117 * textual data.
118 *
119 * <h4> Special IPv6 address </h4>
120 *
121 * <blockquote>
122 * <table class="borderless">
123 * <caption style="display:none">Description of IPv4-mapped address</caption>
124 * <tr><th style="vertical-align:top; padding-right:2px"><i>IPv4-mapped address</i></th>
125 * <td>Of the form ::ffff:w.x.y.z, this IPv6 address is used to
126 * represent an IPv4 address. It allows the native program to
127 * use the same address data structure and also the same
128 * socket when communicating with both IPv4 and IPv6 nodes.
129 *
130 * <p>In InetAddress and Inet6Address, it is used for internal
131 * representation; it has no functional role. Java will never
132 * return an IPv4-mapped address. These classes can take an
133 * IPv4-mapped address as input, both in byte array and text
134 * representation. However, it will be converted into an IPv4
135 * address.</td></tr>
136 * </table></blockquote>
137 *
138 * <h4><a id="scoped">Textual representation of IPv6 scoped addresses</a></h4>
139 *
140 * <p> The textual representation of IPv6 addresses as described above can be
141 * extended to specify IPv6 scoped addresses. This extension to the basic
142 * addressing architecture is described in [draft-ietf-ipngwg-scoping-arch-04.txt].
143 *
144 * <p> Because link-local and site-local addresses are non-global, it is possible
145 * that different hosts may have the same destination address and may be
146 * reachable through different interfaces on the same originating system. In
147 * this case, the originating system is said to be connected to multiple zones
148 * of the same scope. In order to disambiguate which is the intended destination
149 * zone, it is possible to append a zone identifier (or <i>scope_id</i>) to an
150 * IPv6 address.
151 *
152 * <p> The general format for specifying the <i>scope_id</i> is the following:
153 *
154 * <blockquote><i>IPv6-address</i>%<i>scope_id</i></blockquote>
155 * <p> The IPv6-address is a literal IPv6 address as described above.
156 * The <i>scope_id</i> refers to an interface on the local system, and it can be
157 * specified in two ways.
158 * <ol><li><i>As a numeric identifier.</i> This must be a positive integer
159 * that identifies the particular interface and scope as understood by the
160 * system. Usually, the numeric values can be determined through administration
161 * tools on the system. Each interface may have multiple values, one for each
162 * scope. If the scope is unspecified, then the default value used is zero.</li>
163 * <li><i>As a string.</i> This must be the exact string that is returned by
164 * {@link java.net.NetworkInterface#getName()} for the particular interface in
165 * question. When an Inet6Address is created in this way, the numeric scope-id
166 * is determined at the time the object is created by querying the relevant
167 * NetworkInterface.</li></ol>
168 *
169 * <p> Note also, that the numeric <i>scope_id</i> can be retrieved from
170 * Inet6Address instances returned from the NetworkInterface class. This can be
171 * used to find out the current scope ids configured on the system.
172 * @since 1.4
173 */
174
175 public final
176 class Inet6Address extends InetAddress {
177 static final int INADDRSZ = 16;
178
179 /*
180 * cached scope_id - for link-local address use only.
181 */
182 private transient int cached_scope_id; // 0
183
184 private class Inet6AddressHolder {
185
186 private Inet6AddressHolder() {
187 ipaddress = new byte[INADDRSZ];
188 }
189
190 private Inet6AddressHolder(
191 byte[] ipaddress, int scope_id, boolean scope_id_set,
192 NetworkInterface ifname, boolean scope_ifname_set)
193 {
194 this.ipaddress = ipaddress;
195 this.scope_id = scope_id;
196 this.scope_id_set = scope_id_set;
197 this.scope_ifname_set = scope_ifname_set;
198 this.scope_ifname = ifname;
199 }
200
201 /**
202 * Holds a 128-bit (16 bytes) IPv6 address.
203 */
204 byte[] ipaddress;
205
206 /**
207 * scope_id. The scope specified when the object is created. If the object
208 * is created with an interface name, then the scope_id is not determined
209 * until the time it is needed.
210 */
211 int scope_id; // 0
212
213 /**
214 * This will be set to true when the scope_id field contains a valid
215 * integer scope_id.
216 */
217 boolean scope_id_set; // false
218
219 /**
220 * scoped interface. scope_id is derived from this as the scope_id of the first
221 * address whose scope is the same as this address for the named interface.
222 */
223 NetworkInterface scope_ifname; // null
224
225 /**
226 * set if the object is constructed with a scoped
227 * interface instead of a numeric scope id.
228 */
229 boolean scope_ifname_set; // false;
230
231 void setAddr(byte addr[]) {
232 if (addr.length == INADDRSZ) { // normal IPv6 address
233 System.arraycopy(addr, 0, ipaddress, 0, INADDRSZ);
234 }
235 }
236
237 void init(byte addr[], int scope_id) {
238 setAddr(addr);
239
240 if (scope_id >= 0) {
241 this.scope_id = scope_id;
242 this.scope_id_set = true;
243 }
244 }
245
246 void init(byte addr[], NetworkInterface nif)
247 throws UnknownHostException
248 {
249 setAddr(addr);
250
251 if (nif != null) {
252 this.scope_id = deriveNumericScope(ipaddress, nif);
253 this.scope_id_set = true;
254 this.scope_ifname = nif;
255 this.scope_ifname_set = true;
256 }
257 }
258
259 String getHostAddress() {
260 String s = numericToTextFormat(ipaddress);
261 if (scope_ifname != null) { /* must check this first */
262 s = s + "%" + scope_ifname.getName();
263 } else if (scope_id_set) {
264 s = s + "%" + scope_id;
265 }
266 return s;
267 }
268
269 public boolean equals(Object o) {
270 if (! (o instanceof Inet6AddressHolder)) {
271 return false;
272 }
273 Inet6AddressHolder that = (Inet6AddressHolder)o;
274
275 return Arrays.equals(this.ipaddress, that.ipaddress);
276 }
277
278 public int hashCode() {
279 if (ipaddress != null) {
280
281 int hash = 0;
282 int i=0;
283 while (i<INADDRSZ) {
284 int j=0;
285 int component=0;
286 while (j<4 && i<INADDRSZ) {
287 component = (component << 8) + ipaddress[i];
288 j++;
289 i++;
290 }
291 hash += component;
292 }
293 return hash;
294
295 } else {
296 return 0;
297 }
298 }
299
300 boolean isIPv4CompatibleAddress() {
301 if ((ipaddress[0] == 0x00) && (ipaddress[1] == 0x00) &&
302 (ipaddress[2] == 0x00) && (ipaddress[3] == 0x00) &&
303 (ipaddress[4] == 0x00) && (ipaddress[5] == 0x00) &&
304 (ipaddress[6] == 0x00) && (ipaddress[7] == 0x00) &&
305 (ipaddress[8] == 0x00) && (ipaddress[9] == 0x00) &&
306 (ipaddress[10] == 0x00) && (ipaddress[11] == 0x00)) {
307 return true;
308 }
309 return false;
310 }
311
312 boolean isMulticastAddress() {
313 return ((ipaddress[0] & 0xff) == 0xff);
314 }
315
316 boolean isAnyLocalAddress() {
317 byte test = 0x00;
318 for (int i = 0; i < INADDRSZ; i++) {
319 test |= ipaddress[i];
320 }
321 return (test == 0x00);
322 }
323
324 boolean isLoopbackAddress() {
325 byte test = 0x00;
326 for (int i = 0; i < 15; i++) {
327 test |= ipaddress[i];
328 }
329 return (test == 0x00) && (ipaddress[15] == 0x01);
330 }
331
332 boolean isLinkLocalAddress() {
333 return ((ipaddress[0] & 0xff) == 0xfe
334 && (ipaddress[1] & 0xc0) == 0x80);
335 }
336
337
338 boolean isSiteLocalAddress() {
339 return ((ipaddress[0] & 0xff) == 0xfe
340 && (ipaddress[1] & 0xc0) == 0xc0);
341 }
342
343 boolean isMCGlobal() {
344 return ((ipaddress[0] & 0xff) == 0xff
345 && (ipaddress[1] & 0x0f) == 0x0e);
346 }
347
348 boolean isMCNodeLocal() {
349 return ((ipaddress[0] & 0xff) == 0xff
350 && (ipaddress[1] & 0x0f) == 0x01);
351 }
352
353 boolean isMCLinkLocal() {
354 return ((ipaddress[0] & 0xff) == 0xff
355 && (ipaddress[1] & 0x0f) == 0x02);
356 }
357
358 boolean isMCSiteLocal() {
359 return ((ipaddress[0] & 0xff) == 0xff
360 && (ipaddress[1] & 0x0f) == 0x05);
361 }
362
363 boolean isMCOrgLocal() {
364 return ((ipaddress[0] & 0xff) == 0xff
365 && (ipaddress[1] & 0x0f) == 0x08);
366 }
367 }
368
369 private final transient Inet6AddressHolder holder6;
370
371 private static final long serialVersionUID = 6880410070516793377L;
372
373 // Perform native initialization
374 static { init(); }
375
376 Inet6Address() {
377 super();
378 holder.init(null, IPv6);
379 holder6 = new Inet6AddressHolder();
380 }
381
382 /* checking of value for scope_id should be done by caller
383 * scope_id must be >= 0, or -1 to indicate not being set
384 */
385 Inet6Address(String hostName, byte addr[], int scope_id) {
386 holder.init(hostName, IPv6);
387 holder6 = new Inet6AddressHolder();
388 holder6.init(addr, scope_id);
389 }
390
391 Inet6Address(String hostName, byte addr[]) {
392 holder6 = new Inet6AddressHolder();
393 try {
394 initif (hostName, addr, null);
395 } catch (UnknownHostException e) {} /* cant happen if ifname is null */
396 }
397
398 Inet6Address (String hostName, byte addr[], NetworkInterface nif)
399 throws UnknownHostException
400 {
401 holder6 = new Inet6AddressHolder();
402 initif (hostName, addr, nif);
403 }
404
405 Inet6Address (String hostName, byte addr[], String ifname)
406 throws UnknownHostException
407 {
408 holder6 = new Inet6AddressHolder();
409 initstr (hostName, addr, ifname);
410 }
411
412 /**
413 * Create an Inet6Address in the exact manner of {@link
414 * InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is
415 * set to the value corresponding to the given interface for the address
416 * type specified in {@code addr}. The call will fail with an
417 * UnknownHostException if the given interface does not have a numeric
418 * scope_id assigned for the given address type (eg. link-local or site-local).
419 * See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
420 * scoped addresses.
421 *
422 * @param host the specified host
423 * @param addr the raw IP address in network byte order
424 * @param nif an interface this address must be associated with.
425 * @return an Inet6Address object created from the raw IP address.
426 * @throws UnknownHostException
427 * if IP address is of illegal length, or if the interface does not
428 * have a numeric scope_id assigned for the given address type.
429 *
430 * @since 1.5
431 */
432 public static Inet6Address getByAddress(String host, byte[] addr,
433 NetworkInterface nif)
434 throws UnknownHostException
435 {
436 if (host != null && !host.isEmpty() && host.charAt(0) == '[') {
437 if (host.charAt(host.length()-1) == ']') {
438 host = host.substring(1, host.length() -1);
439 }
440 }
441 if (addr != null) {
442 if (addr.length == Inet6Address.INADDRSZ) {
443 return new Inet6Address(host, addr, nif);
444 }
445 }
446 throw new UnknownHostException("addr is of illegal length");
447 }
448
449 /**
450 * Create an Inet6Address in the exact manner of {@link
451 * InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is
452 * set to the given numeric value. The scope_id is not checked to determine
453 * if it corresponds to any interface on the system.
454 * See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
455 * scoped addresses.
456 *
457 * @param host the specified host
458 * @param addr the raw IP address in network byte order
459 * @param scope_id the numeric scope_id for the address.
460 * @return an Inet6Address object created from the raw IP address.
461 * @throws UnknownHostException if IP address is of illegal length.
462 *
463 * @since 1.5
464 */
465 public static Inet6Address getByAddress(String host, byte[] addr,
466 int scope_id)
467 throws UnknownHostException
468 {
469 if (host != null && !host.isEmpty() && host.charAt(0) == '[') {
470 if (host.charAt(host.length()-1) == ']') {
471 host = host.substring(1, host.length() -1);
472 }
473 }
474 if (addr != null) {
475 if (addr.length == Inet6Address.INADDRSZ) {
476 return new Inet6Address(host, addr, scope_id);
477 }
478 }
479 throw new UnknownHostException("addr is of illegal length");
480 }
481
482 private void initstr(String hostName, byte addr[], String ifname)
483 throws UnknownHostException
484 {
485 try {
486 NetworkInterface nif = NetworkInterface.getByName (ifname);
487 if (nif == null) {
488 throw new UnknownHostException ("no such interface " + ifname);
489 }
490 initif (hostName, addr, nif);
491 } catch (SocketException e) {
492 throw new UnknownHostException ("SocketException thrown" + ifname);
493 }
494 }
495
496 private void initif(String hostName, byte addr[], NetworkInterface nif)
497 throws UnknownHostException
498 {
499 int family = -1;
500 holder6.init(addr, nif);
501
502 if (addr.length == INADDRSZ) { // normal IPv6 address
503 family = IPv6;
504 }
505 holder.init(hostName, family);
506 }
507
508 /* check the two Ipv6 addresses and return false if they are both
509 * non global address types, but not the same.
510 * (ie. one is sitelocal and the other linklocal)
511 * return true otherwise.
512 */
513
514 private static boolean isDifferentLocalAddressType(
515 byte[] thisAddr, byte[] otherAddr) {
516
517 if (Inet6Address.isLinkLocalAddress(thisAddr) &&
518 !Inet6Address.isLinkLocalAddress(otherAddr)) {
519 return false;
520 }
521 if (Inet6Address.isSiteLocalAddress(thisAddr) &&
522 !Inet6Address.isSiteLocalAddress(otherAddr)) {
523 return false;
524 }
525 return true;
526 }
527
528 private static int deriveNumericScope (byte[] thisAddr, NetworkInterface ifc) throws UnknownHostException {
529 Enumeration<InetAddress> addresses = ifc.getInetAddresses();
530 while (addresses.hasMoreElements()) {
531 InetAddress addr = addresses.nextElement();
532 if (!(addr instanceof Inet6Address)) {
533 continue;
534 }
535 Inet6Address ia6_addr = (Inet6Address)addr;
536 /* check if site or link local prefixes match */
537 if (!isDifferentLocalAddressType(thisAddr, ia6_addr.getAddress())){
538 /* type not the same, so carry on searching */
539 continue;
540 }
541 /* found a matching address - return its scope_id */
542 return ia6_addr.getScopeId();
543 }
544 throw new UnknownHostException ("no scope_id found");
545 }
546
547 private int deriveNumericScope (String ifname) throws UnknownHostException {
548 Enumeration<NetworkInterface> en;
549 try {
550 en = NetworkInterface.getNetworkInterfaces();
551 } catch (SocketException e) {
552 throw new UnknownHostException ("could not enumerate local network interfaces");
553 }
554 while (en.hasMoreElements()) {
555 NetworkInterface ifc = en.nextElement();
556 if (ifc.getName().equals (ifname)) {
557 return deriveNumericScope(holder6.ipaddress, ifc);
558 }
559 }
560 throw new UnknownHostException ("No matching address found for interface : " +ifname);
561 }
562
563 /**
564 * @serialField ipaddress byte[]
565 * @serialField scope_id int
566 * @serialField scope_id_set boolean
567 * @serialField scope_ifname_set boolean
568 * @serialField ifname String
569 */
570
571 private static final ObjectStreamField[] serialPersistentFields = {
572 new ObjectStreamField("ipaddress", byte[].class),
573 new ObjectStreamField("scope_id", int.class),
574 new ObjectStreamField("scope_id_set", boolean.class),
575 new ObjectStreamField("scope_ifname_set", boolean.class),
576 new ObjectStreamField("ifname", String.class)
577 };
578
579 private static final jdk.internal.misc.Unsafe UNSAFE
580 = jdk.internal.misc.Unsafe.getUnsafe();
581 private static final long FIELDS_OFFSET = UNSAFE.objectFieldOffset(
582 Inet6Address.class, "holder6");
583
584 /**
585 * restore the state of this object from stream
586 * including the scope information, only if the
587 * scoped interface name is valid on this system
588 */
589 private void readObject(ObjectInputStream s)
590 throws IOException, ClassNotFoundException {
591 NetworkInterface scope_ifname = null;
592
593 if (getClass().getClassLoader() != null) {
594 throw new SecurityException ("invalid address type");
595 }
596
597 ObjectInputStream.GetField gf = s.readFields();
598 byte[] ipaddress = (byte[])gf.get("ipaddress", new byte[0]);
599 int scope_id = gf.get("scope_id", -1);
600 boolean scope_id_set = gf.get("scope_id_set", false);
601 boolean scope_ifname_set = gf.get("scope_ifname_set", false);
602 String ifname = (String)gf.get("ifname", null);
603
604 if (ifname != null && !ifname.isEmpty()) {
605 try {
606 scope_ifname = NetworkInterface.getByName(ifname);
607 if (scope_ifname == null) {
608 /* the interface does not exist on this system, so we clear
609 * the scope information completely */
610 scope_id_set = false;
611 scope_ifname_set = false;
612 scope_id = 0;
613 } else {
614 scope_ifname_set = true;
615 try {
616 scope_id = deriveNumericScope (ipaddress, scope_ifname);
617 } catch (UnknownHostException e) {
618 // typically should not happen, but it may be that
619 // the machine being used for deserialization has
620 // the same interface name but without IPv6 configured.
621 }
622 }
623 } catch (SocketException e) {}
624 }
625
626 /* if ifname was not supplied, then the numeric info is used */
627
628 ipaddress = ipaddress.clone();
629
630 // Check that our invariants are satisfied
631 if (ipaddress.length != INADDRSZ) {
632 throw new InvalidObjectException("invalid address length: "+
633 ipaddress.length);
634 }
635
636 if (holder.getFamily() != IPv6) {
637 throw new InvalidObjectException("invalid address family type");
638 }
639
640 Inet6AddressHolder h = new Inet6AddressHolder(
641 ipaddress, scope_id, scope_id_set, scope_ifname, scope_ifname_set
642 );
643
644 UNSAFE.putObject(this, FIELDS_OFFSET, h);
645 }
646
647 /**
648 * default behavior is overridden in order to write the
649 * scope_ifname field as a String, rather than a NetworkInterface
650 * which is not serializable
651 */
652 private synchronized void writeObject(ObjectOutputStream s)
653 throws IOException
654 {
655 String ifname = null;
656
657 if (holder6.scope_ifname != null) {
658 ifname = holder6.scope_ifname.getName();
659 holder6.scope_ifname_set = true;
660 }
661 ObjectOutputStream.PutField pfields = s.putFields();
662 pfields.put("ipaddress", holder6.ipaddress);
663 pfields.put("scope_id", holder6.scope_id);
664 pfields.put("scope_id_set", holder6.scope_id_set);
665 pfields.put("scope_ifname_set", holder6.scope_ifname_set);
666 pfields.put("ifname", ifname);
667 s.writeFields();
668 }
669
670 /**
671 * Utility routine to check if the InetAddress is an IP multicast
672 * address. 11111111 at the start of the address identifies the
673 * address as being a multicast address.
674 *
675 * @return a {@code boolean} indicating if the InetAddress is an IP
676 * multicast address
677 */
678 @Override
679 public boolean isMulticastAddress() {
680 return holder6.isMulticastAddress();
681 }
682
683 /**
684 * Utility routine to check if the InetAddress is a wildcard address.
685 *
686 * @return a {@code boolean} indicating if the Inetaddress is
687 * a wildcard address.
688 */
689 @Override
690 public boolean isAnyLocalAddress() {
691 return holder6.isAnyLocalAddress();
692 }
693
694 /**
695 * Utility routine to check if the InetAddress is a loopback address.
696 *
697 * @return a {@code boolean} indicating if the InetAddress is a loopback
698 * address; or false otherwise.
699 */
700 @Override
701 public boolean isLoopbackAddress() {
702 return holder6.isLoopbackAddress();
703 }
704
705 /**
706 * Utility routine to check if the InetAddress is an link local address.
707 *
708 * @return a {@code boolean} indicating if the InetAddress is a link local
709 * address; or false if address is not a link local unicast address.
710 */
711 @Override
712 public boolean isLinkLocalAddress() {
713 return holder6.isLinkLocalAddress();
714 }
715
716 /* static version of above */
717 static boolean isLinkLocalAddress(byte[] ipaddress) {
718 return ((ipaddress[0] & 0xff) == 0xfe
719 && (ipaddress[1] & 0xc0) == 0x80);
720 }
721
722 /**
723 * Utility routine to check if the InetAddress is a site local address.
724 *
725 * @return a {@code boolean} indicating if the InetAddress is a site local
726 * address; or false if address is not a site local unicast address.
727 */
728 @Override
729 public boolean isSiteLocalAddress() {
730 return holder6.isSiteLocalAddress();
731 }
732
733 /* static version of above */
734 static boolean isSiteLocalAddress(byte[] ipaddress) {
735 return ((ipaddress[0] & 0xff) == 0xfe
736 && (ipaddress[1] & 0xc0) == 0xc0);
737 }
738
739 /**
740 * Utility routine to check if the multicast address has global scope.
741 *
742 * @return a {@code boolean} indicating if the address has is a multicast
743 * address of global scope, false if it is not of global scope or
744 * it is not a multicast address
745 */
746 @Override
747 public boolean isMCGlobal() {
748 return holder6.isMCGlobal();
749 }
750
751 /**
752 * Utility routine to check if the multicast address has node scope.
753 *
754 * @return a {@code boolean} indicating if the address has is a multicast
755 * address of node-local scope, false if it is not of node-local
756 * scope or it is not a multicast address
757 */
758 @Override
759 public boolean isMCNodeLocal() {
760 return holder6.isMCNodeLocal();
761 }
762
763 /**
764 * Utility routine to check if the multicast address has link scope.
765 *
766 * @return a {@code boolean} indicating if the address has is a multicast
767 * address of link-local scope, false if it is not of link-local
768 * scope or it is not a multicast address
769 */
770 @Override
771 public boolean isMCLinkLocal() {
772 return holder6.isMCLinkLocal();
773 }
774
775 /**
776 * Utility routine to check if the multicast address has site scope.
777 *
778 * @return a {@code boolean} indicating if the address has is a multicast
779 * address of site-local scope, false if it is not of site-local
780 * scope or it is not a multicast address
781 */
782 @Override
783 public boolean isMCSiteLocal() {
784 return holder6.isMCSiteLocal();
785 }
786
787 /**
788 * Utility routine to check if the multicast address has organization scope.
789 *
790 * @return a {@code boolean} indicating if the address has is a multicast
791 * address of organization-local scope, false if it is not of
792 * organization-local scope or it is not a multicast address
793 */
794 @Override
795 public boolean isMCOrgLocal() {
796 return holder6.isMCOrgLocal();
797 }
798 /**
799 * Returns the raw IP address of this {@code InetAddress} object. The result
800 * is in network byte order: the highest order byte of the address is in
801 * {@code getAddress()[0]}.
802 *
803 * @return the raw IP address of this object.
804 */
805 @Override
806 public byte[] getAddress() {
807 return holder6.ipaddress.clone();
808 }
809
810 /**
811 * Returns the numeric scopeId, if this instance is associated with
812 * an interface. If no scoped_id is set, the returned value is zero.
813 *
814 * @return the scopeId, or zero if not set.
815 *
816 * @since 1.5
817 */
818 public int getScopeId() {
819 return holder6.scope_id;
820 }
821
822 /**
823 * Returns the scoped interface, if this instance was created with
824 * with a scoped interface.
825 *
826 * @return the scoped interface, or null if not set.
827 * @since 1.5
828 */
829 public NetworkInterface getScopedInterface() {
830 return holder6.scope_ifname;
831 }
832
833 /**
834 * Returns the IP address string in textual presentation. If the instance
835 * was created specifying a scope identifier then the scope id is appended
836 * to the IP address preceded by a "%" (per-cent) character. This can be
837 * either a numeric value or a string, depending on which was used to create
838 * the instance.
839 *
840 * @return the raw IP address in a string format.
841 */
842 @Override
843 public String getHostAddress() {
844 return holder6.getHostAddress();
845 }
846
847 /**
848 * Returns a hashcode for this IP address.
849 *
850 * @return a hash code value for this IP address.
851 */
852 @Override
853 public int hashCode() {
854 return holder6.hashCode();
855 }
856
857 /**
858 * Compares this object against the specified object. The result is {@code
859 * true} if and only if the argument is not {@code null} and it represents
860 * the same IP address as this object.
861 *
862 * <p> Two instances of {@code InetAddress} represent the same IP address
863 * if the length of the byte arrays returned by {@code getAddress} is the
864 * same for both, and each of the array components is the same for the byte
865 * arrays.
866 *
867 * @param obj the object to compare against.
868 *
869 * @return {@code true} if the objects are the same; {@code false} otherwise.
870 *
871 * @see java.net.InetAddress#getAddress()
872 */
873 @Override
874 public boolean equals(Object obj) {
875 if (obj == null || !(obj instanceof Inet6Address))
876 return false;
877
878 Inet6Address inetAddr = (Inet6Address)obj;
879
880 return holder6.equals(inetAddr.holder6);
881 }
882
883 /**
884 * Utility routine to check if the InetAddress is an
885 * IPv4 compatible IPv6 address.
886 *
887 * @return a {@code boolean} indicating if the InetAddress is an IPv4
888 * compatible IPv6 address; or false if address is IPv4 address.
889 */
890 public boolean isIPv4CompatibleAddress() {
891 return holder6.isIPv4CompatibleAddress();
892 }
893
894 // Utilities
895
896 private static final int INT16SZ = 2;
897
898 /**
899 * Convert IPv6 binary address into presentation (printable) format.
900 *
901 * @param src a byte array representing the IPv6 numeric address
902 * @return a String representing an IPv6 address in
903 * textual representation format
904 */
905 static String numericToTextFormat(byte[] src) {
906 StringBuilder sb = new StringBuilder(39);
907 for (int i = 0; i < (INADDRSZ / INT16SZ); i++) {
908 sb.append(Integer.toHexString(((src[i<<1]<<8) & 0xff00)
909 | (src[(i<<1)+1] & 0xff)));
910 if (i < (INADDRSZ / INT16SZ) -1 ) {
911 sb.append(":");
912 }
913 }
914 return sb.toString();
915 }
916
917 /**
918 * Perform class load-time initializations.
919 */
920 private static native void init();
921 }
922