blob: 299d55e5f06f86ece9ee2491509a39cd83bf657e [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.net;
27
28import java.security.AccessController;
29import java.io.ObjectInputStream;
30import java.io.IOException;
31import java.io.ObjectStreamException;
32import java.io.InvalidObjectException;
33import sun.security.action.*;
34import java.util.Enumeration;
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&nbsp;2373: IP Version 6 Addressing Architecture</i></a>.
40 *
41 * <h4> <A NAME="format">Textual representation of IP addresses</a> </h4>
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 NAME="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><table cellpadding=0 cellspacing=0 summary="layout">
53 * <tr><td><tt>1080:0:0:0:8:800:200C:417A</tt><td></tr>
54 * </table></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><table cellpadding=0 cellspacing=0 summary="layout">
70 * <tr><td><tt>1080::8:800:200C:417A</tt><td></tr>
71 * </table></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><table cellpadding=0 cellspacing=0 summary="layout">
81 * <tr><td><tt>::FFFF:129.144.52.38</tt><td></tr>
82 * <tr><td><tt>::129.144.52.38</tt><td></tr>
83 * </table></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><table cellpadding=0 cellspacing=0 summary="layout">
91 * <tr><td><tt>::FFFF:d.d.d</tt><td></tr>
92 * <tr><td><tt>::FFFF:d.d</tt><td></tr>
93 * <tr><td><tt>::d.d.d</tt><td></tr>
94 * <tr><td><tt>::d.d</tt><td></tr>
95 * </table></blockquote>
96 *
97 * <p> The following form:
98 *
99 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout">
100 * <tr><td><tt>::FFFF:d</tt><td></tr>
101 * </table></blockquote>
102 *
103 * <p> is valid, however it is an unconventional representation of
104 * the IPv4-compatible IPv6 address,
105 *
106 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout">
107 * <tr><td><tt>::255.255.0.d</tt><td></tr>
108 * </table></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 cellspacing=2 summary="Description of IPv4-mapped address"> <tr><th valign=top><i>IPv4-mapped address</i></th>
123 * <td>Of the form::ffff:w.x.y.z, this IPv6 address is used to
124 * represent an IPv4 address. It allows the native program to
125 * use the same address data structure and also the same
126 * socket when communicating with both IPv4 and IPv6 nodes.
127 *
128 * <p>In InetAddress and Inet6Address, it is used for internal
129 * representation; it has no functional role. Java will never
130 * return an IPv4-mapped address. These classes can take an
131 * IPv4-mapped address as input, both in byte array and text
132 * representation. However, it will be converted into an IPv4
133 * address.</td></tr>
134 * </table></blockquote>
135 * <p>
136 * <h4> <A NAME="scoped">Textual representation of IPv6 scoped addresses</a> </h4>
137 * <p>
138 * The textual representation of IPv6 addresses as described above can be extended
139 * to specify IPv6 scoped addresses. This extension to the basic addressing architecture
140 * is described in [draft-ietf-ipngwg-scoping-arch-04.txt].
141 * <p>
142 * Because link-local and site-local addresses are non-global, it is possible that different hosts
143 * may have the same destination address and may be reachable through different interfaces on the
144 * same originating system. In this case, the originating system is said to be connected
145 * to multiple zones of the same scope. In order to disambiguate which is the intended destination
146 * zone, it is possible to append a zone identifier (or <i>scope_id</i>) to an IPv6 address.
147 * <p>
148 * The general format for specifying the <i>scope_id</i> is the following:
149 * <p><blockquote><i>IPv6-address</i>%<i>scope_id</i></blockquote>
150 * <p> The IPv6-address is a literal IPv6 address as described above.
151 * The <i>scope_id</i> refers to an interface on the local system, and it can be specified
152 * in two ways.
153 * <p><ol><li><i>As a numeric identifier.</i> This must be a positive integer that identifies the
154 * particular interface and scope as understood by the system. Usually, the numeric
155 * values can be determined through administration tools on the system. Each interface may
156 * have multiple values, one for each scope. If the scope is unspecified, then the default value
157 * used is zero.</li><p>
158 * <li><i>As a string.</i> This must be the exact string that is returned by
159 * {@link java.net.NetworkInterface#getName()} for the particular interface in question.
160 * When an Inet6Address is created in this way, the numeric scope-id is determined at the time
161 * the object is created by querying the relevant NetworkInterface.</li>
162 * </ol><p>
163 * Note also, that the numeric <i>scope_id</i> can be retrieved from Inet6Address instances returned from the
164 * NetworkInterface class. This can be used to find out the current scope ids configured on the system.
165 * @since 1.4
166 */
167
168public final
169class Inet6Address extends InetAddress {
170 final static int INADDRSZ = 16;
171
172 /*
173 * cached scope_id - for link-local address use only.
174 */
175 private transient int cached_scope_id = 0;
176
177 /**
178 * Holds a 128-bit (16 bytes) IPv6 address.
179 *
180 * @serial
181 */
182 byte[] ipaddress;
183
184 /**
185 * scope_id. The scope specified when the object is created. If the object is created
186 * with an interface name, then the scope_id is not determined until the time it is needed.
187 */
188 private int scope_id = 0;
189
190 /**
191 * This will be set to true when the scope_id field contains a valid
192 * integer scope_id.
193 */
194 private boolean scope_id_set = false;
195
196 /**
197 * scoped interface. scope_id is derived from this as the scope_id of the first
198 * address whose scope is the same as this address for the named interface.
199 */
200 private transient NetworkInterface scope_ifname = null;
201
202 /**
203 * set if the object is constructed with a scoped interface instead of a
204 * numeric scope id.
205 */
206 private boolean scope_ifname_set = false;
207
208 private static final long serialVersionUID = 6880410070516793377L;
209
210 /*
211 * Perform initializations.
212 */
213 static {
214 init();
215 }
216
217 Inet6Address() {
218 super();
219 hostName = null;
220 ipaddress = new byte[INADDRSZ];
221 family = IPv6;
222 }
223
224 /* checking of value for scope_id should be done by caller
225 * scope_id must be >= 0, or -1 to indicate not being set
226 */
227 Inet6Address(String hostName, byte addr[], int scope_id) {
228 this.hostName = hostName;
229 if (addr.length == INADDRSZ) { // normal IPv6 address
230 family = IPv6;
231 ipaddress = addr.clone();
232 }
233 if (scope_id >= 0) {
234 this.scope_id = scope_id;
235 scope_id_set = true;
236 }
237 }
238
239 Inet6Address(String hostName, byte addr[]) {
240 try {
241 initif (hostName, addr, null);
242 } catch (UnknownHostException e) {} /* cant happen if ifname is null */
243 }
244
245 Inet6Address (String hostName, byte addr[], NetworkInterface nif) throws UnknownHostException {
246 initif (hostName, addr, nif);
247 }
248
249 Inet6Address (String hostName, byte addr[], String ifname) throws UnknownHostException {
250 initstr (hostName, addr, ifname);
251 }
252
253 /**
254 * Create an Inet6Address in the exact manner of {@link InetAddress#getByAddress(String,byte[])}
255 * except that the IPv6 scope_id is set to the value corresponding to the given interface
256 * for the address type specified in <code>addr</code>.
257 * The call will fail with an UnknownHostException if the given interface does not have a numeric
258 * scope_id assigned for the given address type (eg. link-local or site-local).
259 * See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
260 * scoped addresses.
261 *
262 * @param host the specified host
263 * @param addr the raw IP address in network byte order
264 * @param nif an interface this address must be associated with.
265 * @return an Inet6Address object created from the raw IP address.
266 * @exception UnknownHostException if IP address is of illegal length, or if the interface
267 * does not have a numeric scope_id assigned for the given address type.
268 *
269 * @since 1.5
270 */
271
272 public static Inet6Address getByAddress(String host, byte[] addr, NetworkInterface nif)
273 throws UnknownHostException {
274 if (host != null && host.length() > 0 && host.charAt(0) == '[') {
275 if (host.charAt(host.length()-1) == ']') {
276 host = host.substring(1, host.length() -1);
277 }
278 }
279 if (addr != null) {
280 if (addr.length == Inet6Address.INADDRSZ) {
281 return new Inet6Address(host, addr, nif);
282 }
283 }
284 throw new UnknownHostException("addr is of illegal length");
285 }
286
287 /**
288 * Create an Inet6Address in the exact manner of {@link InetAddress#getByAddress(String,byte[])}
289 * except that the IPv6 scope_id is set to the given numeric value.
290 * The scope_id is not checked to determine if it corresponds to any interface on the system.
291 * See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
292 * scoped addresses.
293 *
294 * @param host the specified host
295 * @param addr the raw IP address in network byte order
296 * @param scope_id the numeric scope_id for the address.
297 * @return an Inet6Address object created from the raw IP address.
298 * @exception UnknownHostException if IP address is of illegal length.
299 *
300 * @since 1.5
301 */
302
303 public static Inet6Address getByAddress(String host, byte[] addr, int scope_id)
304 throws UnknownHostException {
305 if (host != null && host.length() > 0 && host.charAt(0) == '[') {
306 if (host.charAt(host.length()-1) == ']') {
307 host = host.substring(1, host.length() -1);
308 }
309 }
310 if (addr != null) {
311 if (addr.length == Inet6Address.INADDRSZ) {
312 return new Inet6Address(host, addr, scope_id);
313 }
314 }
315 throw new UnknownHostException("addr is of illegal length");
316 }
317
318 private void initstr (String hostName, byte addr[], String ifname) throws UnknownHostException {
319 try {
320 NetworkInterface nif = NetworkInterface.getByName (ifname);
321 if (nif == null) {
322 throw new UnknownHostException ("no such interface " + ifname);
323 }
324 initif (hostName, addr, nif);
325 } catch (SocketException e) {
326 throw new UnknownHostException ("SocketException thrown" + ifname);
327 }
328 }
329
330 private void initif(String hostName, byte addr[],NetworkInterface nif) throws UnknownHostException {
331 this.hostName = hostName;
332 if (addr.length == INADDRSZ) { // normal IPv6 address
333 family = IPv6;
334 ipaddress = addr.clone();
335 }
336 if (nif != null) {
337 this.scope_ifname = nif;
338 scope_ifname_set = true;
339 scope_id = deriveNumericScope (nif);
340 scope_id_set = true;
341 }
342 }
343
344 /* check the two Ipv6 addresses and return false if they are both
345 * non global address types, but not the same.
346 * (ie. one is sitelocal and the other linklocal)
347 * return true otherwise.
348 */
349 private boolean differentLocalAddressTypes(Inet6Address other) {
350
351 if (isLinkLocalAddress() && !other.isLinkLocalAddress()) {
352 return false;
353 }
354 if (isSiteLocalAddress() && !other.isSiteLocalAddress()) {
355 return false;
356 }
357 return true;
358 }
359
360 private int deriveNumericScope (NetworkInterface ifc) throws UnknownHostException {
361 Enumeration addresses = ifc.getInetAddresses();
362 while (addresses.hasMoreElements()) {
363 InetAddress address = (InetAddress)addresses.nextElement();
364 if (!(address instanceof Inet6Address)) {
365 continue;
366 }
367 Inet6Address ia6_addr = (Inet6Address)address;
368 /* check if site or link local prefixes match */
369 if (!differentLocalAddressTypes(ia6_addr)){
370 /* type not the same, so carry on searching */
371 continue;
372 }
373 /* found a matching address - return its scope_id */
374 return ia6_addr.scope_id;
375 }
376 throw new UnknownHostException ("no scope_id found");
377 }
378
379 private int deriveNumericScope (String ifname) throws UnknownHostException {
380 Enumeration en;
381 try {
382 en = NetworkInterface.getNetworkInterfaces();
383 } catch (SocketException e) {
384 throw new UnknownHostException ("could not enumerate local network interfaces");
385 }
386 while (en.hasMoreElements()) {
387 NetworkInterface ifc = (NetworkInterface)en.nextElement();
388 if (ifc.getName().equals (ifname)) {
389 Enumeration addresses = ifc.getInetAddresses();
390 while (addresses.hasMoreElements()) {
391 InetAddress address = (InetAddress)addresses.nextElement();
392 if (!(address instanceof Inet6Address)) {
393 continue;
394 }
395 Inet6Address ia6_addr = (Inet6Address)address;
396 /* check if site or link local prefixes match */
397 if (!differentLocalAddressTypes(ia6_addr)){
398 /* type not the same, so carry on searching */
399 continue;
400 }
401 /* found a matching address - return its scope_id */
402 return ia6_addr.scope_id;
403 }
404 }
405 }
406 throw new UnknownHostException ("No matching address found for interface : " +ifname);
407 }
408
409 /**
410 * restore the state of this object from stream
411 * including the scope information, only if the
412 * scoped interface name is valid on this system
413 */
414 private void readObject(ObjectInputStream s)
415 throws IOException, ClassNotFoundException {
416 scope_ifname = null;
417 scope_ifname_set = false;
418 s.defaultReadObject();
419
420 if (ifname != null && !"".equals (ifname)) {
421 try {
422 scope_ifname = NetworkInterface.getByName(ifname);
423 try {
424 scope_id = deriveNumericScope (scope_ifname);
425 } catch (UnknownHostException e) {
426 // should not happen
427 assert false;
428 }
429 } catch (SocketException e) {}
430
431 if (scope_ifname == null) {
432 /* the interface does not exist on this system, so we clear
433 * the scope information completely */
434 scope_id_set = false;
435 scope_ifname_set = false;
436 scope_id = 0;
437 }
438 }
439 /* if ifname was not supplied, then the numeric info is used */
440
441 ipaddress = ipaddress.clone();
442
443 // Check that our invariants are satisfied
444 if (ipaddress.length != INADDRSZ) {
445 throw new InvalidObjectException("invalid address length: "+
446 ipaddress.length);
447 }
448
449 if (family != IPv6) {
450 throw new InvalidObjectException("invalid address family type");
451 }
452 }
453
454 /**
455 * Utility routine to check if the InetAddress is an IP multicast
456 * address. 11111111 at the start of the address identifies the
457 * address as being a multicast address.
458 *
459 * @return a <code>boolean</code> indicating if the InetAddress is
460 * an IP multicast address
461 * @since JDK1.1
462 */
463 public boolean isMulticastAddress() {
464 return ((ipaddress[0] & 0xff) == 0xff);
465 }
466
467 /**
468 * Utility routine to check if the InetAddress in a wildcard address.
469 * @return a <code>boolean</code> indicating if the Inetaddress is
470 * a wildcard address.
471 * @since 1.4
472 */
473 public boolean isAnyLocalAddress() {
474 byte test = 0x00;
475 for (int i = 0; i < INADDRSZ; i++) {
476 test |= ipaddress[i];
477 }
478 return (test == 0x00);
479 }
480
481 /**
482 * Utility routine to check if the InetAddress is a loopback address.
483 *
484 * @return a <code>boolean</code> indicating if the InetAddress is
485 * a loopback address; or false otherwise.
486 * @since 1.4
487 */
488 public boolean isLoopbackAddress() {
489 byte test = 0x00;
490 for (int i = 0; i < 15; i++) {
491 test |= ipaddress[i];
492 }
493 return (test == 0x00) && (ipaddress[15] == 0x01);
494 }
495
496 /**
497 * Utility routine to check if the InetAddress is an link local address.
498 *
499 * @return a <code>boolean</code> indicating if the InetAddress is
500 * a link local address; or false if address is not a link local unicast address.
501 * @since 1.4
502 */
503 public boolean isLinkLocalAddress() {
504 return ((ipaddress[0] & 0xff) == 0xfe
505 && (ipaddress[1] & 0xc0) == 0x80);
506 }
507
508 /**
509 * Utility routine to check if the InetAddress is a site local address.
510 *
511 * @return a <code>boolean</code> indicating if the InetAddress is
512 * a site local address; or false if address is not a site local unicast address.
513 * @since 1.4
514 */
515 public boolean isSiteLocalAddress() {
516 return ((ipaddress[0] & 0xff) == 0xfe
517 && (ipaddress[1] & 0xc0) == 0xc0);
518 }
519
520 /**
521 * Utility routine to check if the multicast address has global scope.
522 *
523 * @return a <code>boolean</code> indicating if the address has
524 * is a multicast address of global scope, false if it is not
525 * of global scope or it is not a multicast address
526 * @since 1.4
527 */
528 public boolean isMCGlobal() {
529 return ((ipaddress[0] & 0xff) == 0xff
530 && (ipaddress[1] & 0x0f) == 0x0e);
531 }
532
533 /**
534 * Utility routine to check if the multicast address has node scope.
535 *
536 * @return a <code>boolean</code> indicating if the address has
537 * is a multicast address of node-local scope, false if it is not
538 * of node-local scope or it is not a multicast address
539 * @since 1.4
540 */
541 public boolean isMCNodeLocal() {
542 return ((ipaddress[0] & 0xff) == 0xff
543 && (ipaddress[1] & 0x0f) == 0x01);
544 }
545
546 /**
547 * Utility routine to check if the multicast address has link scope.
548 *
549 * @return a <code>boolean</code> indicating if the address has
550 * is a multicast address of link-local scope, false if it is not
551 * of link-local scope or it is not a multicast address
552 * @since 1.4
553 */
554 public boolean isMCLinkLocal() {
555 return ((ipaddress[0] & 0xff) == 0xff
556 && (ipaddress[1] & 0x0f) == 0x02);
557 }
558
559 /**
560 * Utility routine to check if the multicast address has site scope.
561 *
562 * @return a <code>boolean</code> indicating if the address has
563 * is a multicast address of site-local scope, false if it is not
564 * of site-local scope or it is not a multicast address
565 * @since 1.4
566 */
567 public boolean isMCSiteLocal() {
568 return ((ipaddress[0] & 0xff) == 0xff
569 && (ipaddress[1] & 0x0f) == 0x05);
570 }
571
572 /**
573 * Utility routine to check if the multicast address has organization scope.
574 *
575 * @return a <code>boolean</code> indicating if the address has
576 * is a multicast address of organization-local scope,
577 * false if it is not of organization-local scope
578 * or it is not a multicast address
579 * @since 1.4
580 */
581 public boolean isMCOrgLocal() {
582 return ((ipaddress[0] & 0xff) == 0xff
583 && (ipaddress[1] & 0x0f) == 0x08);
584 }
585
586 /**
587 * Returns the raw IP address of this <code>InetAddress</code>
588 * object. The result is in network byte order: the highest order
589 * byte of the address is in <code>getAddress()[0]</code>.
590 *
591 * @return the raw IP address of this object.
592 */
593 public byte[] getAddress() {
594 return ipaddress.clone();
595 }
596
597 /**
598 * Returns the numeric scopeId, if this instance is associated with
599 * an interface. If no scoped_id is set, the returned value is zero.
600 *
601 * @return the scopeId, or zero if not set.
602 * @since 1.5
603 */
604 public int getScopeId () {
605 return scope_id;
606 }
607
608 /**
609 * Returns the scoped interface, if this instance was created with
610 * with a scoped interface.
611 *
612 * @return the scoped interface, or null if not set.
613 * @since 1.5
614 */
615 public NetworkInterface getScopedInterface () {
616 return scope_ifname;
617 }
618
619 /**
620 * Returns the IP address string in textual presentation. If the instance was created
621 * specifying a scope identifier then the scope id is appended to the IP address preceded by
622 * a "%" (per-cent) character. This can be either a numeric value or a string, depending on which
623 * was used to createthe instance.
624 *
625 * @return the raw IP address in a string format.
626 */
627 public String getHostAddress() {
628 String s = numericToTextFormat(ipaddress);
629 if (scope_ifname_set) { /* must check this first */
630 s = s + "%" + scope_ifname.getName();
631 } else if (scope_id_set) {
632 s = s + "%" + scope_id;
633 }
634 return s;
635 }
636
637 /**
638 * Returns a hashcode for this IP address.
639 *
640 * @return a hash code value for this IP address.
641 */
642 public int hashCode() {
643 if (ipaddress != null) {
644
645 int hash = 0;
646 int i=0;
647 while (i<INADDRSZ) {
648 int j=0;
649 int component=0;
650 while (j<4 && i<INADDRSZ) {
651 component = (component << 8) + ipaddress[i];
652 j++;
653 i++;
654 }
655 hash += component;
656 }
657 return hash;
658
659 } else {
660 return 0;
661 }
662 }
663
664 /**
665 * Compares this object against the specified object.
666 * The result is <code>true</code> if and only if the argument is
667 * not <code>null</code> and it represents the same IP address as
668 * this object.
669 * <p>
670 * Two instances of <code>InetAddress</code> represent the same IP
671 * address if the length of the byte arrays returned by
672 * <code>getAddress</code> is the same for both, and each of the
673 * array components is the same for the byte arrays.
674 *
675 * @param obj the object to compare against.
676 * @return <code>true</code> if the objects are the same;
677 * <code>false</code> otherwise.
678 * @see java.net.InetAddress#getAddress()
679 */
680 public boolean equals(Object obj) {
681 if (obj == null ||
682 !(obj instanceof Inet6Address))
683 return false;
684
685 Inet6Address inetAddr = (Inet6Address)obj;
686
687 for (int i = 0; i < INADDRSZ; i++) {
688 if (ipaddress[i] != inetAddr.ipaddress[i])
689 return false;
690 }
691
692 return true;
693 }
694
695 /**
696 * Utility routine to check if the InetAddress is an
697 * IPv4 compatible IPv6 address.
698 *
699 * @return a <code>boolean</code> indicating if the InetAddress is
700 * an IPv4 compatible IPv6 address; or false if address is IPv4 address.
701 * @since 1.4
702 */
703 public boolean isIPv4CompatibleAddress() {
704 if ((ipaddress[0] == 0x00) && (ipaddress[1] == 0x00) &&
705 (ipaddress[2] == 0x00) && (ipaddress[3] == 0x00) &&
706 (ipaddress[4] == 0x00) && (ipaddress[5] == 0x00) &&
707 (ipaddress[6] == 0x00) && (ipaddress[7] == 0x00) &&
708 (ipaddress[8] == 0x00) && (ipaddress[9] == 0x00) &&
709 (ipaddress[10] == 0x00) && (ipaddress[11] == 0x00)) {
710 return true;
711 }
712 return false;
713 }
714
715 // Utilities
716 private final static int INT16SZ = 2;
717 /*
718 * Convert IPv6 binary address into presentation (printable) format.
719 *
720 * @param src a byte array representing the IPv6 numeric address
721 * @return a String representing an IPv6 address in
722 * textual representation format
723 * @since 1.4
724 */
725 static String numericToTextFormat(byte[] src)
726 {
727 StringBuffer sb = new StringBuffer(39);
728 for (int i = 0; i < (INADDRSZ / INT16SZ); i++) {
729 sb.append(Integer.toHexString(((src[i<<1]<<8) & 0xff00)
730 | (src[(i<<1)+1] & 0xff)));
731 if (i < (INADDRSZ / INT16SZ) -1 ) {
732 sb.append(":");
733 }
734 }
735 return sb.toString();
736 }
737
738 /**
739 * Perform class load-time initializations.
740 */
741 private static native void init();
742
743 /**
744 * Following field is only used during (de)/serialization
745 */
746 private String ifname;
747
748 /**
749 * default behavior is overridden in order to write the
750 * scope_ifname field as a String, rather than a NetworkInterface
751 * which is not serializable
752 */
753 private synchronized void writeObject(java.io.ObjectOutputStream s)
754 throws IOException
755 {
756 if (scope_ifname_set) {
757 ifname = scope_ifname.getName();
758 }
759 s.defaultWriteObject();
760 }
761}