OSDN Git Service

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