History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/net/Inet6Address.java (1 of 18352 files). Show all

Unified · Split

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