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