OSDN Git Service

8d834a6fd28ab5b7fc40eaa4a2c7e2f02cc423be
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / net / Inet6Address.java
1 /* Inet6Address.java --
2    Copyright (C) 2002, 2003, 2004  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    * Create an Inet6Address object
97    *
98    * @param addr The IP address
99    * @param host The hostname
100    */
101   Inet6Address(byte[] addr, String host)
102   {
103     super(addr, host);
104     // Super constructor clones the addr.  Get a reference to the clone.
105     this.ipaddress = this.addr;
106     ifname = null;
107     scope_ifname_set = scope_id_set = false;
108     scope_id = 0;
109     nif = null;
110   }
111
112   /**
113    * Utility routine to check if the InetAddress is an IP multicast address
114    *
115    * @since 1.1
116    */
117   public boolean isMulticastAddress()
118   {
119     return ipaddress[0] == 0xFF;
120   }
121
122   /**
123    * Utility routine to check if the InetAddress in a wildcard address
124    *
125    * @since 1.4
126    */
127   public boolean isAnyLocalAddress()
128   {
129     byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
130
131     return Arrays.equals(ipaddress, anylocal);
132   }
133
134   /**
135    * Utility routine to check if the InetAddress is a loopback address
136    *
137    * @since 1.4
138    */
139   public boolean isLoopbackAddress()
140   {
141     byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
142
143     return Arrays.equals(ipaddress, loopback);
144   }
145
146   /**
147    * Utility routine to check if the InetAddress is an link local address
148    *
149    * @since 1.4
150    */
151   public boolean isLinkLocalAddress()
152   {
153     return ipaddress[0] == 0xFA;
154   }
155
156   /**
157    * Utility routine to check if the InetAddress is a site local address
158    *
159    * @since 1.4
160    */
161   public boolean isSiteLocalAddress()
162   {
163     return ipaddress[0] == 0xFB;
164   }
165
166   /**
167    * Utility routine to check if the multicast address has global scope
168    *
169    * @since 1.4
170    */
171   public boolean isMCGlobal()
172   {
173     if (! isMulticastAddress())
174       return false;
175
176     return (ipaddress[1] & 0x0F) == 0xE;
177   }
178
179   /**
180    * Utility routine to check if the multicast address has node scope
181    *
182    * @since 1.4
183    */
184   public boolean isMCNodeLocal()
185   {
186     if (! isMulticastAddress())
187       return false;
188
189     return (ipaddress[1] & 0x0F) == 0x1;
190   }
191
192   /**
193    * Utility routine to check if the multicast address has link scope
194    *
195    * @since 1.4
196    */
197   public boolean isMCLinkLocal()
198   {
199     if (! isMulticastAddress())
200       return false;
201
202     return (ipaddress[1] & 0x0F) == 0x2;
203   }
204
205   /**
206    * Utility routine to check if the multicast address has site scope
207    *
208    * @since 1.4
209    */
210   public boolean isMCSiteLocal()
211   {
212     if (! isMulticastAddress())
213       return false;
214
215     return (ipaddress[1] & 0x0F) == 0x5;
216   }
217
218   /**
219    * Utility routine to check if the multicast address has organization scope
220    *
221    * @since 1.4
222    */
223   public boolean isMCOrgLocal()
224   {
225     if (! isMulticastAddress())
226       return false;
227
228     return (ipaddress[1] & 0x0F) == 0x8;
229   }
230
231   /**
232    * Returns the raw IP address of this InetAddress object. The result is in
233    * network byte order: the highest order byte of the address is i
234    * n getAddress()[0]
235    */
236   public byte[] getAddress()
237   {
238     return (byte[]) ipaddress.clone();
239   }
240
241   /**
242    * Creates a scoped Inet6Address where the scope has an integer id.
243    *
244    * @throws UnkownHostException if the address is an invalid number of bytes.
245    * @since 1.5
246    */  
247   public static Inet6Address getByAddress(String host, byte[] addr, 
248                                           int scopeId)
249     throws UnknownHostException
250   {
251     if( addr.length != 16 )
252       throw new UnknownHostException("Illegal address length: " + addr.length
253                                      + " bytes.");
254     Inet6Address ip = new Inet6Address( addr, host );
255     ip.scope_id = scopeId;
256     ip.scope_id_set = true;
257     return ip;
258   }
259
260   /**
261    * Creates a scoped Inet6Address where the scope is a given
262    * NetworkInterface.
263    *
264    * @throws UnkownHostException if the address is an invalid number of bytes.
265    * @since 1.5
266    */  
267   public static Inet6Address getByAddress(String host, byte[] addr, 
268                                           NetworkInterface nif)
269     throws UnknownHostException
270   {
271     if( addr.length != 16 )
272       throw new UnknownHostException("Illegal address length: " + addr.length
273                                      + " bytes.");
274     Inet6Address ip = new Inet6Address( addr, host );
275     ip.nif = nif;
276
277     return ip;
278   }
279
280   /**
281    * Returns the <code>NetworkInterface</code> of the address scope
282    * if it is a scoped address and the scope is given in the form of a
283    * NetworkInterface. 
284    * (I.e. the address was created using  the 
285    * getByAddress(String, byte[], NetworkInterface) method)
286    * Otherwise this method returns <code>null</code>.
287    * @since 1.5
288    */
289   public NetworkInterface getScopedInterface()
290   {
291     return nif;
292   }
293
294   /**
295    * Returns the scope ID of the address scope if it is a scoped adress using
296    * an integer to identify the scope.
297    *
298    * Otherwise this method returns 0.
299    * @since 1.5
300    */
301   public int getScopeId()
302   {
303     // check scope_id_set because some JDK-serialized objects seem to have
304     // scope_id set to a nonzero value even when scope_id_set == false
305     if( scope_id_set )
306       return scope_id; 
307     return 0;
308   }
309
310   /**
311    * Returns the IP address string in textual presentation
312    */
313   public String getHostAddress()
314   {
315     StringBuffer sbuf = new StringBuffer(40);
316
317     for (int i = 0; i < 16; i += 2)
318       {
319         int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
320
321         if (i > 0)
322           sbuf.append(':');
323
324         sbuf.append(Integer.toHexString(x));
325       }
326     if( nif != null )
327       sbuf.append( "%" + nif.getName() );
328     else if( scope_id_set )
329       sbuf.append( "%" + scope_id );
330
331     return sbuf.toString();
332   }
333
334   /**
335    * Returns a hashcode for this IP address
336    * (The hashcode is independent of scope)
337    */
338   public int hashCode()
339   {
340     return super.hashCode();
341   }
342
343   /**
344    * Compares this object against the specified object
345    */
346   public boolean equals(Object obj)
347   {
348     if (! (obj instanceof Inet6Address))
349       return false;
350
351     Inet6Address ip = (Inet6Address)obj;
352     if (ipaddress.length != ip.ipaddress.length)
353       return false;
354
355     for (int i = 0; i < ip.ipaddress.length; i++)
356       if (ipaddress[i] != ip.ipaddress[i])
357         return false;
358
359     if( ip.nif != null && nif != null )
360       return nif.equals( ip.nif );
361     if( ip.nif != nif )
362       return false;
363     if( ip.scope_id_set != scope_id_set )
364       return false;
365     if( scope_id_set )
366       return (scope_id == ip.scope_id);
367     return true;
368   }
369
370   /**
371    * Utility routine to check if the InetAddress is an
372    * IPv4 compatible IPv6 address
373    *
374    * @since 1.4
375    */
376   public boolean isIPv4CompatibleAddress()
377   {
378     if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
379         || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
380         || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
381         || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
382         || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
383         || ipaddress[11] != 0x00)
384       return false;
385
386     return true;
387   }
388
389   /**
390    * Required for 1.5-compatible serialization.
391    * @since 1.5
392    */
393   private void readObject(ObjectInputStream s)
394     throws IOException, ClassNotFoundException
395   {  
396     s.defaultReadObject();
397     try
398       {
399         if( scope_ifname_set )
400           nif = NetworkInterface.getByName( ifname );
401       }
402     catch( SocketException se )
403       {
404         // FIXME: Ignore this? or throw an IOException?
405       }
406   }
407
408   /**
409    * Required for 1.5-compatible serialization.
410    * @since 1.5
411    */
412   private void writeObject(ObjectOutputStream s)
413     throws IOException
414   {
415     if( nif != null )
416       {
417         ifname = nif.getName();
418         scope_ifname_set = true;
419       }
420     s.defaultWriteObject();
421   }
422 }