OSDN Git Service

2006-09-20 Gary Benson <gbenson@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / net / Inet6Address.java
1 /* Inet6Address.java --
2    Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package java.net;
40
41 import java.util.Arrays;
42 import java.io.ObjectInputStream;
43 import java.io.ObjectOutputStream;
44 import java.io.IOException;
45
46 /*
47  * Written using on-line Java Platform 1.4 API Specification and
48  * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt)
49  * 
50  * @author Michael Koch
51  * @status Updated to 1.5. Serialization compatibility is tested.
52  */
53 public final class Inet6Address extends InetAddress
54 {
55   static final long serialVersionUID = 6880410070516793377L;
56
57   /**
58    * Needed for serialization
59    */
60   byte[] ipaddress;
61
62   /**
63    * The scope ID, if any. 
64    * @since 1.5
65    * @serial 
66    */
67   private int scope_id;
68
69   /**
70    * The scope ID, if any. 
71    * @since 1.5
72    * @serial 
73    */
74   private boolean scope_id_set;
75
76   /**
77    * Whether ifname is set or not.
78    * @since 1.5
79    * @serial 
80    */
81   private boolean scope_ifname_set;
82
83   /**
84    * Name of the network interface, used only by the serialization methods
85    * @since 1.5
86    * @serial 
87    */
88   private String ifname;
89
90   /**
91    * Scope network interface, or <code>null</code>.
92    */
93   private transient NetworkInterface nif; 
94
95   /**
96    * The address family of these addresses (used for serialization).
97    */
98   private static final int FAMILY = 10; // AF_INET6
99
100   /**
101    * Create an Inet6Address object
102    *
103    * @param addr The IP address
104    * @param host The hostname
105    */
106   Inet6Address(byte[] addr, String host)
107   {
108     super(addr, host, FAMILY);
109     // Super constructor clones the addr.  Get a reference to the clone.
110     this.ipaddress = this.addr;
111     ifname = null;
112     scope_ifname_set = scope_id_set = false;
113     scope_id = 0;
114     nif = null;
115   }
116
117   /**
118    * Utility routine to check if the InetAddress is an IP multicast address
119    *
120    * @since 1.1
121    */
122   public boolean isMulticastAddress()
123   {
124     return ipaddress[0] == 0xFF;
125   }
126
127   /**
128    * Utility routine to check if the InetAddress in a wildcard address
129    *
130    * @since 1.4
131    */
132   public boolean isAnyLocalAddress()
133   {
134     byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
135
136     return Arrays.equals(ipaddress, anylocal);
137   }
138
139   /**
140    * Utility routine to check if the InetAddress is a loopback address
141    *
142    * @since 1.4
143    */
144   public boolean isLoopbackAddress()
145   {
146     byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
147
148     return Arrays.equals(ipaddress, loopback);
149   }
150
151   /**
152    * Utility routine to check if the InetAddress is an link local address
153    *
154    * @since 1.4
155    */
156   public boolean isLinkLocalAddress()
157   {
158     return ipaddress[0] == 0xFA;
159   }
160
161   /**
162    * Utility routine to check if the InetAddress is a site local address
163    *
164    * @since 1.4
165    */
166   public boolean isSiteLocalAddress()
167   {
168     return ipaddress[0] == 0xFB;
169   }
170
171   /**
172    * Utility routine to check if the multicast address has global scope
173    *
174    * @since 1.4
175    */
176   public boolean isMCGlobal()
177   {
178     if (! isMulticastAddress())
179       return false;
180
181     return (ipaddress[1] & 0x0F) == 0xE;
182   }
183
184   /**
185    * Utility routine to check if the multicast address has node scope
186    *
187    * @since 1.4
188    */
189   public boolean isMCNodeLocal()
190   {
191     if (! isMulticastAddress())
192       return false;
193
194     return (ipaddress[1] & 0x0F) == 0x1;
195   }
196
197   /**
198    * Utility routine to check if the multicast address has link scope
199    *
200    * @since 1.4
201    */
202   public boolean isMCLinkLocal()
203   {
204     if (! isMulticastAddress())
205       return false;
206
207     return (ipaddress[1] & 0x0F) == 0x2;
208   }
209
210   /**
211    * Utility routine to check if the multicast address has site scope
212    *
213    * @since 1.4
214    */
215   public boolean isMCSiteLocal()
216   {
217     if (! isMulticastAddress())
218       return false;
219
220     return (ipaddress[1] & 0x0F) == 0x5;
221   }
222
223   /**
224    * Utility routine to check if the multicast address has organization scope
225    *
226    * @since 1.4
227    */
228   public boolean isMCOrgLocal()
229   {
230     if (! isMulticastAddress())
231       return false;
232
233     return (ipaddress[1] & 0x0F) == 0x8;
234   }
235
236   /**
237    * Returns the raw IP address of this InetAddress object. The result is in
238    * network byte order: the highest order byte of the address is i
239    * n getAddress()[0]
240    */
241   public byte[] getAddress()
242   {
243     return (byte[]) ipaddress.clone();
244   }
245
246   /**
247    * Creates a scoped Inet6Address where the scope has an integer id.
248    *
249    * @throws UnkownHostException if the address is an invalid number of bytes.
250    * @since 1.5
251    */  
252   public static Inet6Address getByAddress(String host, byte[] addr, 
253                                           int scopeId)
254     throws UnknownHostException
255   {
256     if( addr.length != 16 )
257       throw new UnknownHostException("Illegal address length: " + addr.length
258                                      + " bytes.");
259     Inet6Address ip = new Inet6Address( addr, host );
260     ip.scope_id = scopeId;
261     ip.scope_id_set = true;
262     return ip;
263   }
264
265   /**
266    * Creates a scoped Inet6Address where the scope is a given
267    * NetworkInterface.
268    *
269    * @throws UnkownHostException if the address is an invalid number of bytes.
270    * @since 1.5
271    */  
272   public static Inet6Address getByAddress(String host, byte[] addr, 
273                                           NetworkInterface nif)
274     throws UnknownHostException
275   {
276     if( addr.length != 16 )
277       throw new UnknownHostException("Illegal address length: " + addr.length
278                                      + " bytes.");
279     Inet6Address ip = new Inet6Address( addr, host );
280     ip.nif = nif;
281
282     return ip;
283   }
284
285   /**
286    * Returns the <code>NetworkInterface</code> of the address scope
287    * if it is a scoped address and the scope is given in the form of a
288    * NetworkInterface. 
289    * (I.e. the address was created using  the 
290    * getByAddress(String, byte[], NetworkInterface) method)
291    * Otherwise this method returns <code>null</code>.
292    * @since 1.5
293    */
294   public NetworkInterface getScopedInterface()
295   {
296     return nif;
297   }
298
299   /**
300    * Returns the scope ID of the address scope if it is a scoped adress using
301    * an integer to identify the scope.
302    *
303    * Otherwise this method returns 0.
304    * @since 1.5
305    */
306   public int getScopeId()
307   {
308     // check scope_id_set because some JDK-serialized objects seem to have
309     // scope_id set to a nonzero value even when scope_id_set == false
310     if( scope_id_set )
311       return scope_id; 
312     return 0;
313   }
314
315   /**
316    * Returns the IP address string in textual presentation
317    */
318   public String getHostAddress()
319   {
320     StringBuffer sbuf = new StringBuffer(40);
321
322     for (int i = 0; i < 16; i += 2)
323       {
324         int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
325
326         if (i > 0)
327           sbuf.append(':');
328
329         sbuf.append(Integer.toHexString(x));
330       }
331     if( nif != null )
332       sbuf.append( "%" + nif.getName() );
333     else if( scope_id_set )
334       sbuf.append( "%" + scope_id );
335
336     return sbuf.toString();
337   }
338
339   /**
340    * Returns a hashcode for this IP address
341    * (The hashcode is independent of scope)
342    */
343   public int hashCode()
344   {
345     return super.hashCode();
346   }
347
348   /**
349    * Compares this object against the specified object
350    */
351   public boolean equals(Object obj)
352   {
353     if (! (obj instanceof Inet6Address))
354       return false;
355
356     Inet6Address ip = (Inet6Address)obj;
357     if (ipaddress.length != ip.ipaddress.length)
358       return false;
359
360     for (int i = 0; i < ip.ipaddress.length; i++)
361       if (ipaddress[i] != ip.ipaddress[i])
362         return false;
363
364     if( ip.nif != null && nif != null )
365       return nif.equals( ip.nif );
366     if( ip.nif != nif )
367       return false;
368     if( ip.scope_id_set != scope_id_set )
369       return false;
370     if( scope_id_set )
371       return (scope_id == ip.scope_id);
372     return true;
373   }
374
375   /**
376    * Utility routine to check if the InetAddress is an
377    * IPv4 compatible IPv6 address
378    *
379    * @since 1.4
380    */
381   public boolean isIPv4CompatibleAddress()
382   {
383     if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
384         || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
385         || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
386         || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
387         || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
388         || ipaddress[11] != 0x00)
389       return false;
390
391     return true;
392   }
393
394   /**
395    * Required for 1.5-compatible serialization.
396    * @since 1.5
397    */
398   private void readObject(ObjectInputStream s)
399     throws IOException, ClassNotFoundException
400   {  
401     s.defaultReadObject();
402     try
403       {
404         if( scope_ifname_set )
405           nif = NetworkInterface.getByName( ifname );
406       }
407     catch( SocketException se )
408       {
409         // FIXME: Ignore this? or throw an IOException?
410       }
411   }
412
413   /**
414    * Required for 1.5-compatible serialization.
415    * @since 1.5
416    */
417   private void writeObject(ObjectOutputStream s)
418     throws IOException
419   {
420     if( nif != null )
421       {
422         ifname = nif.getName();
423         scope_ifname_set = true;
424       }
425     s.defaultWriteObject();
426   }
427 }