OSDN Git Service

Imported GNU Classpath 0.20
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / net / InetAddress.java
1 /* InetAddress.java -- Class to model an Internet address
2    Copyright (C) 1998, 1999, 2002, 2004, 2005  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.io.IOException;
42 import java.io.ObjectInputStream;
43 import java.io.ObjectOutputStream;
44 import java.io.ObjectStreamException;
45 import java.io.Serializable;
46 import java.util.StringTokenizer;
47
48 /**
49  * This class models an Internet address.  It does not have a public
50  * constructor.  Instead, new instances of this objects are created
51  * using the static methods getLocalHost(), getByName(), and
52  * getAllByName().
53  *
54  * <p>This class fulfills the function of the C style functions gethostname(),
55  * gethostbyname(), and gethostbyaddr().  It resolves Internet DNS names
56  * into their corresponding numeric addresses and vice versa.</p>
57  *
58  * @author Aaron M. Renn (arenn@urbanophile.com)
59  * @author Per Bothner
60  *
61  * @specnote This class is not final since JK 1.4
62  */
63 public class InetAddress implements Serializable
64 {
65   private static final long serialVersionUID = 3286316764910316507L;
66
67   /**
68    * The special IP address INADDR_ANY.
69    */
70   private static InetAddress inaddr_any;
71
72   /**
73    * Dummy InetAddress, used to bind socket to any (all) network interfaces.
74    */
75   static InetAddress ANY_IF;
76
77   /**
78    * Stores static localhost address object.
79    */
80   static InetAddress LOCALHOST;
81
82   static
83   {
84     // precompute the ANY_IF address
85     try
86       {
87         ANY_IF = getInaddrAny();
88
89         byte[] ip_localhost = { 127, 0, 0, 1 };
90         LOCALHOST = new Inet4Address(ip_localhost, "localhost");
91       }
92     catch (UnknownHostException uhe)
93       {
94         // Hmmm, make one up and hope that it works.
95         byte[] zeros = { 0, 0, 0, 0 };
96         ANY_IF = new Inet4Address(zeros, "0.0.0.0");
97       }
98   }
99
100   /**
101    * The Serialized Form specifies that an int 'address' is saved/restored.
102    * This class uses a byte array internally so we'll just do the conversion
103    * at serialization time and leave the rest of the algorithm as is.
104    */
105   private int address;
106
107   /**
108    * An array of octets representing an IP address.
109    */
110   transient byte[] addr;
111
112   /**
113    * The name of the host for this address.
114    */
115   String hostName;
116
117   /**
118    * The field 'family' seems to be the AF_ value.
119    * FIXME: Much of the code in the other java.net classes does not make
120    * use of this family field.  A better implementation would be to make
121    * use of getaddrinfo() and have other methods just check the family
122    * field rather than examining the length of the address each time.
123    */
124   int family;
125
126   /**
127    * Initializes this object's addr instance variable from the passed in
128    * byte array.  Note that this constructor is protected and is called
129    * only by static methods in this class.
130    *
131    * @param ipaddr The IP number of this address as an array of bytes
132    * @param hostname The hostname of this IP address.
133    */
134   InetAddress(byte[] ipaddr, String hostname)
135   {
136     addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
137     hostName = hostname;
138     
139     family = 2; /* AF_INET */
140   }
141
142   /**
143    * Returns true if this address is a multicast address, false otherwise.
144    * An address is multicast if the high four bits are "1110".  These are
145    * also known as "Class D" addresses.
146    *
147    * @return true if mulitcast, false if not
148    *
149    * @since 1.1
150    */
151   public boolean isMulticastAddress()
152   {
153     // Mask against high order bits of 1110
154     if (addr.length == 4)
155       return (addr[0] & 0xf0) == 0xe0;
156
157     return false;
158   }
159
160   /**
161    * Utility routine to check if the InetAddress in a wildcard address
162    *
163    * @since 1.4
164    */
165   public boolean isAnyLocalAddress()
166   {
167     // This is the IPv4 implementation.
168     // Any class derived from InetAddress should override this.
169     return equals(ANY_IF);
170   }
171
172   /**
173    * Utility routine to check if the InetAddress is a loopback address
174    *
175    * @since 1.4
176    */
177   public boolean isLoopbackAddress()
178   {
179     // This is the IPv4 implementation.
180     // Any class derived from InetAddress should override this.
181     return (addr[0] & 0xff) == 0x7f;
182   }
183
184   /**
185    * Utility routine to check if InetAddress is a link local address
186    *
187    * @since 1.4
188    */
189   public boolean isLinkLocalAddress()
190   {
191     // This is the IPv4 implementation.
192     // Any class derived from InetAddress should override this.
193     // XXX: This seems to not exist with IPv4 addresses
194     return false;
195   }
196
197   /**
198    * Utility routine to check if InetAddress is a site local address
199    *
200    * @since 1.4
201    */
202   public boolean isSiteLocalAddress()
203   {
204     // This is the IPv4 implementation.
205     // Any class derived from InetAddress should override this.
206
207     // 10.0.0.0/8
208     if ((addr[0] & 0xff) == 0x0a)
209       return true;
210
211     // 172.16.0.0/12
212     if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10)
213       return true;
214
215     // 192.168.0.0/16
216     if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8)
217       return true;
218
219     // XXX: Do we need to check more addresses here ?
220     return false;
221   }
222
223   /**
224    * Utility routine to check if InetAddress is a global multicast address
225    *
226    * @since 1.4
227    */
228   public boolean isMCGlobal()
229   {
230     // This is the IPv4 implementation.
231     // Any class derived from InetAddress should override this.
232     // XXX: This seems to not exist with IPv4 addresses
233     return false;
234   }
235
236   /**
237    * Utility routine to check if InetAddress is a node local multicast address.
238    *
239    * @since 1.4
240    */
241   public boolean isMCNodeLocal()
242   {
243     // This is the IPv4 implementation.
244     // Any class derived from InetAddress should override this.
245     // XXX: This seems to not exist with IPv4 addresses
246     return false;
247   }
248
249   /**
250    * Utility routine to check if InetAddress is a link local multicast address.
251    *
252    * @since 1.4
253    */
254   public boolean isMCLinkLocal()
255   {
256     // This is the IPv4 implementation.
257     // Any class derived from InetAddress should override this.
258     if (! isMulticastAddress())
259       return false;
260
261     return ((addr[0] & 0xff) == 0xe0
262             && (addr[1] & 0xff)  == 0x00
263             && (addr[2] & 0xff)  == 0x00);
264   }
265
266   /**
267    * Utility routine to check if InetAddress is a site local multicast address.
268    *
269    * @since 1.4
270    */
271   public boolean isMCSiteLocal()
272   {
273     // This is the IPv4 implementation.
274     // Any class derived from InetAddress should override this.
275     // XXX: This seems to not exist with IPv4 addresses
276     return false;
277   }
278
279   /**
280    * Utility routine to check if InetAddress is a organization local
281    * multicast address.
282    *
283    * @since 1.4
284    */
285   public boolean isMCOrgLocal()
286   {
287     // This is the IPv4 implementation.
288     // Any class derived from InetAddress should override this.
289     // XXX: This seems to not exist with IPv4 addresses
290     return false;
291   }
292
293   /**
294    * Returns the hostname for this address.  This will return the IP address
295    * as a String if there is no hostname available for this address
296    *
297    * @return The hostname for this address
298    */
299   public String getHostName()
300   {
301     if (hostName != null)
302       return hostName;
303
304     try
305       {
306         hostName = VMInetAddress.getHostByAddr(addr);
307         return hostName;
308       }
309     catch (UnknownHostException e)
310       {
311         return getHostAddress();
312       }
313   }
314
315   /**
316    * Returns the canonical hostname represented by this InetAddress
317    * 
318    * @since 1.4
319    */
320   public String getCanonicalHostName()
321   {
322     SecurityManager sm = System.getSecurityManager();
323     if (sm != null)
324       {
325         try
326           {
327             sm.checkConnect(hostName, -1);
328           }
329         catch (SecurityException e)
330           {
331             return getHostAddress();
332           }
333       }
334
335     // Try to find the FDQN now
336     InetAddress address;
337     byte[] ipaddr = getAddress();
338
339     if (ipaddr.length == 16)
340       address = new Inet6Address(getAddress(), null);
341     else
342       address = new Inet4Address(getAddress(), null);
343
344     return address.getHostName();
345   }
346
347   /**
348    * Returns the IP address of this object as a byte array.
349    *
350    * @return IP address
351    */
352   public byte[] getAddress()
353   {
354     // An experiment shows that JDK1.2 returns a different byte array each
355     // time.  This makes sense, in terms of security.
356     return (byte[]) addr.clone();
357   }
358
359   /**
360    * Returns the IP address of this object as a String.  The address is in
361    * the dotted octet notation, for example, "127.0.0.1".
362    *
363    * @return The IP address of this object in String form
364    *
365    * @since 1.0.2
366    */
367   public String getHostAddress()
368   {
369     StringBuffer sb = new StringBuffer(40);
370
371     int len = addr.length;
372     int i = 0;
373     
374     for ( ; ; )
375       {
376         sb.append(addr[i] & 0xff);
377         i++;
378         
379         if (i == len)
380           break;
381         
382         sb.append('.');
383       }
384
385     return sb.toString();
386   }
387
388   /**
389    * Returns a hash value for this address.  Useful for creating hash
390    * tables.  Overrides Object.hashCode()
391    *
392    * @return A hash value for this address.
393    */
394   public int hashCode()
395   {
396     // There hashing algorithm is not specified, but a simple experiment
397     // shows that it is equal to the address, as a 32-bit big-endian integer.
398     int hash = 0;
399     int len = addr.length;
400     int i = len > 4 ? len - 4 : 0;
401
402     for (; i < len; i++)
403       hash = (hash << 8) | (addr[i] & 0xff);
404
405     return hash;
406   }
407
408   /**
409    * Tests this address for equality against another InetAddress.  The two
410    * addresses are considered equal if they contain the exact same octets.
411    * This implementation overrides Object.equals()
412    *
413    * @param obj The address to test for equality
414    *
415    * @return true if the passed in object's address is equal to this one's,
416    * false otherwise
417    */
418   public boolean equals(Object obj)
419   {
420     if (! (obj instanceof InetAddress))
421       return false;
422
423     // "The Java Class Libraries" 2nd edition says "If a machine has
424     // multiple names instances of InetAddress for different name of
425     // that same machine are not equal.  This is because they have
426     // different host names."  This violates the description in the
427     // JDK 1.2 API documentation.  A little experimentation
428     // shows that the latter is correct.
429     byte[] addr2 = ((InetAddress) obj).addr;
430
431     if (addr.length != addr2.length)
432       return false;
433
434     for (int i = 0; i < addr.length; i++)
435       if (addr[i] != addr2[i])
436         return false;
437
438     return true;
439   }
440
441   /**
442    * Converts this address to a String.  This string contains the IP in
443    * dotted decimal form. For example: "127.0.0.1"  This method is equivalent
444    * to getHostAddress() and overrides Object.toString()
445    *
446    * @return This address in String form
447    */
448   public String toString()
449   {
450     String addr = getHostAddress();
451     String host = (hostName != null) ? hostName : "";
452     return host + "/" + addr;
453   }
454
455   /**
456    * Returns an InetAddress object given the raw IP address.
457    *
458    * The argument is in network byte order: the highest order byte of the
459    * address is in getAddress()[0].
460    *
461    * @param addr The IP address to create the InetAddress object from
462    *
463    * @exception UnknownHostException If IP address has illegal length
464    *
465    * @since 1.4
466    */
467   public static InetAddress getByAddress(byte[] addr)
468     throws UnknownHostException
469   {
470     return getByAddress(null, addr);
471   }
472
473   /**
474    * Creates an InetAddress based on the provided host name and IP address.
475    * No name service is checked for the validity of the address.
476    *
477    * @param host The hostname of the InetAddress object to create
478    * @param addr The IP address to create the InetAddress object from
479    *
480    * @exception UnknownHostException If IP address is of illegal length
481    *
482    * @since 1.4
483    */
484   public static InetAddress getByAddress(String host, byte[] addr)
485     throws UnknownHostException
486   {
487     if (addr.length == 4)
488       return new Inet4Address(addr, host);
489
490     if (addr.length == 16)
491       return new Inet6Address(addr, host);
492
493     throw new UnknownHostException("IP address has illegal length");
494   }
495
496   /**
497    * If hostname is a valid numeric IP address, return the numeric address.
498    * Otherwise, return null.
499    *
500    * @param hostname the name of the host
501    */
502   private static byte[] aton(String hostname)
503   {
504     StringTokenizer st = new StringTokenizer(hostname, ".");
505
506     if (st.countTokens() == 4)
507       {
508         int index;
509         byte[] address = new byte[4];
510
511         for (index = 0; index < 4; index++)
512           {
513             try
514               {
515                 short n = Short.parseShort(st.nextToken());
516
517                 if ((n < 0) || (n > 255))
518                   break;
519
520                 address[index] = (byte) n;
521               }
522             catch (NumberFormatException e)
523               {
524                 break;
525               }
526           }
527
528         if (index == 4)
529           return address;
530       }
531
532     return null;
533   }
534
535   /**
536    * Returns an InetAddress object representing the IP address of the given
537    * hostname.  This name can be either a hostname such as "www.urbanophile.com"
538    * or an IP address in dotted decimal format such as "127.0.0.1".  If the
539    * hostname is null or "", the hostname of the local machine is supplied by
540    * default.  This method is equivalent to returning the first element in
541    * the InetAddress array returned from GetAllByName.
542    *
543    * @param hostname The name of the desired host, or null for the local 
544    * loopback address.
545    *
546    * @return The address of the host as an InetAddress object.
547    *
548    * @exception UnknownHostException If no IP address for the host could
549    * be found
550    * @exception SecurityException If a security manager exists and its
551    * checkConnect method doesn't allow the operation
552    */
553   public static InetAddress getByName(String hostname)
554     throws UnknownHostException
555   {
556     InetAddress[] addresses = getAllByName(hostname);
557     return addresses[0];
558   }
559
560   /**
561    * Returns an array of InetAddress objects representing all the host/ip
562    * addresses of a given host, given the host's name.  This name can be
563    * either a hostname such as "www.urbanophile.com" or an IP address in
564    * dotted decimal format such as "127.0.0.1".  If the value is null, the
565    * hostname of the local machine is supplied by default.
566    *
567    * @param hostname The name of the desired host, or null for the
568    * local loopback address.
569    *
570    * @return All addresses of the host as an array of InetAddress objects.
571    *
572    * @exception UnknownHostException If no IP address for the host could
573    * be found
574    * @exception SecurityException If a security manager exists and its
575    * checkConnect method doesn't allow the operation
576    */
577   public static InetAddress[] getAllByName(String hostname)
578     throws UnknownHostException
579   {
580     SecurityManager s = System.getSecurityManager();
581     if (s != null)
582       s.checkConnect(hostname, -1);
583
584     InetAddress[] addresses;
585
586     if (hostname != null)
587       hostname = hostname.trim();
588
589     // Default to current host if necessary
590     if (hostname == null || hostname.equals(""))
591       {
592         addresses = new InetAddress[1];
593         addresses[0] = LOCALHOST;
594         return addresses;
595       }
596
597     // Not in cache, try the lookup
598     byte[][] iplist = VMInetAddress.getHostByName(hostname);
599
600     if (iplist.length == 0)
601       throw new UnknownHostException(hostname);
602
603     addresses = new InetAddress[iplist.length];
604
605     for (int i = 0; i < iplist.length; i++)
606       {
607         if (iplist[i].length != 4)
608           throw new UnknownHostException(hostname);
609
610         addresses[i] = new Inet4Address(iplist[i], hostname);
611       }
612
613     return addresses;
614   }
615
616   /**
617    * Returns the special address INADDR_ANY used for binding to a local
618    * port on all IP addresses hosted by a the local host.
619    *
620    * @return An InetAddress object representing INDADDR_ANY
621    *
622    * @exception UnknownHostException If an error occurs
623    */
624   static InetAddress getInaddrAny() throws UnknownHostException
625   {
626     if (inaddr_any == null)
627       {
628         byte[] tmp = VMInetAddress.lookupInaddrAny();
629         inaddr_any = new Inet4Address(tmp, null);
630         inaddr_any.hostName = inaddr_any.getHostName();
631       }
632
633     return inaddr_any;
634   }
635
636   /**
637    * Returns an InetAddress object representing the address of the current
638    * host.
639    *
640    * @return The local host's address
641    *
642    * @exception UnknownHostException If no IP address for the host could
643    * be found
644    */
645   public static InetAddress getLocalHost() throws UnknownHostException
646   {
647     String hostname = VMInetAddress.getLocalHostname();
648     return getByName(hostname);
649   }
650
651   /*
652    * Needed for serialization
653    */
654   private void readResolve() throws ObjectStreamException
655   {
656     // FIXME: implement this
657   }
658
659   private void readObject(ObjectInputStream ois)
660     throws IOException, ClassNotFoundException
661   {
662     ois.defaultReadObject();
663     addr = new byte[4];
664     addr[3] = (byte) address;
665
666     for (int i = 2; i >= 0; --i)
667       addr[i] = (byte) (address >>= 8);
668
669     family = 2; /* AF_INET  */
670   }
671
672   private void writeObject(ObjectOutputStream oos) throws IOException
673   {
674     // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
675     // or a 16 byte IPv6 address.
676     int len = addr.length;
677     int i = len - 4;
678
679     for (; i < len; i++)
680       address = address << 8 | (addr[i] & 0xff);
681
682     oos.defaultWriteObject();
683   }
684 }