OSDN Git Service

2005-04-26 Michael Koch <konqueror@gmx.de>
[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, 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., 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] & 0xff) == 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
202     // 10.0.0.0/8
203     if ((addr[0] & 0xff) == 0x0a)
204       return true;
205
206     // 172.16.0.0/12
207     if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10)
208       return true;
209
210     // 192.168.0.0/16
211     if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8)
212       return true;
213
214     // XXX: Do we need to check more addresses here ?
215     return false;
216   }
217
218   /**
219    * Utility routine to check if InetAddress is a global multicast address
220    *
221    * @since 1.4
222    */
223   public boolean isMCGlobal()
224   {
225     // This is the IPv4 implementation.
226     // Any class derived from InetAddress should override this.
227     // XXX: This seems to not exist with IPv4 addresses
228     return false;
229   }
230
231   /**
232    * Utility routine to check if InetAddress is a node local multicast address.
233    *
234    * @since 1.4
235    */
236   public boolean isMCNodeLocal()
237   {
238     // This is the IPv4 implementation.
239     // Any class derived from InetAddress should override this.
240     // XXX: This seems to not exist with IPv4 addresses
241     return false;
242   }
243
244   /**
245    * Utility routine to check if InetAddress is a link local multicast address.
246    *
247    * @since 1.4
248    */
249   public boolean isMCLinkLocal()
250   {
251     // This is the IPv4 implementation.
252     // Any class derived from InetAddress should override this.
253     if (! isMulticastAddress())
254       return false;
255
256     return ((addr[0] & 0xff) == 0xe0
257             && (addr[1] & 0xff)  == 0x00
258             && (addr[2] & 0xff)  == 0x00);
259   }
260
261   /**
262    * Utility routine to check if InetAddress is a site local multicast address.
263    *
264    * @since 1.4
265    */
266   public boolean isMCSiteLocal()
267   {
268     // This is the IPv4 implementation.
269     // Any class derived from InetAddress should override this.
270     // XXX: This seems to not exist with IPv4 addresses
271     return false;
272   }
273
274   /**
275    * Utility routine to check if InetAddress is a organization local
276    * multicast address.
277    *
278    * @since 1.4
279    */
280   public boolean isMCOrgLocal()
281   {
282     // This is the IPv4 implementation.
283     // Any class derived from InetAddress should override this.
284     // XXX: This seems to not exist with IPv4 addresses
285     return false;
286   }
287
288   /**
289    * Returns the hostname for this address.  This will return the IP address
290    * as a String if there is no hostname available for this address
291    *
292    * @return The hostname for this address
293    */
294   public String getHostName()
295   {
296     if (hostName != null)
297       return hostName;
298
299     // Lookup hostname and set field.
300     lookup (null, this, false);
301     
302     return hostName;
303   }
304
305   /**
306    * Returns the canonical hostname represented by this InetAddress
307    * 
308    * @since 1.4
309    */
310   public String getCanonicalHostName()
311   {
312     SecurityManager sm = System.getSecurityManager();
313     if (sm != null)
314       {
315         try
316           {
317             sm.checkConnect(hostName, -1);
318           }
319         catch (SecurityException e)
320           {
321             return getHostAddress();
322           }
323       }
324
325     // Try to find the FDQN now
326     InetAddress address;
327     byte[] ipaddr = getAddress();
328
329     if (ipaddr.length == 16)
330       address = new Inet6Address(getAddress(), null);
331     else
332       address = new Inet4Address(getAddress(), null);
333
334     return address.getHostName();
335   }
336
337   /**
338    * Returns the IP address of this object as a byte array.
339    *
340    * @return IP address
341    */
342   public byte[] getAddress()
343   {
344     // An experiment shows that JDK1.2 returns a different byte array each
345     // time.  This makes sense, in terms of security.
346     return (byte[]) addr.clone();
347   }
348
349   /* Helper function due to a CNI limitation.  */
350   private static InetAddress[] allocArray (int count)
351   {
352     return new InetAddress [count];
353   }
354
355   /* Helper function due to a CNI limitation.  */
356   private static SecurityException checkConnect (String hostname)
357   {
358     SecurityManager s = System.getSecurityManager();
359     
360     if (s == null)
361       return null;
362     
363     try
364       {
365         s.checkConnect (hostname, -1);
366         return null;
367       }
368     catch (SecurityException ex)
369       {
370         return ex;
371       }
372   }
373
374   /**
375    * Returns the IP address of this object as a String.  The address is in
376    * the dotted octet notation, for example, "127.0.0.1".
377    *
378    * @return The IP address of this object in String form
379    *
380    * @since 1.0.2
381    */
382   public String getHostAddress()
383   {
384     StringBuffer sb = new StringBuffer(40);
385
386     int len = addr.length;
387     int i = 0;
388     
389     if (len == 16)
390       { // An IPv6 address.
391         for ( ; ; i += 2)
392           {
393             if (i >= 16)
394               return sb.toString();
395             
396             int x = ((addr [i] & 0xFF) << 8) | (addr [i + 1] & 0xFF);
397             boolean empty = sb.length() == 0;
398             
399             if (empty)
400               {
401                 if (i == 10 && x == 0xFFFF)
402                   { // IPv4-mapped IPv6 address.
403                     sb.append (":FFFF:");
404                     break;  // Continue as IPv4 address;
405                   }
406                 else if (i == 12)
407                   { // IPv4-compatible IPv6 address.
408                     sb.append (':');
409                     break;  // Continue as IPv4 address.
410                   }
411                 else if (i > 0)
412                   sb.append ("::");
413               }
414             else
415               sb.append (':');
416             
417             if (x != 0 || i >= 14)
418               sb.append (Integer.toHexString (x).toUpperCase());
419           }
420       }
421     
422     for ( ; ; )
423       {
424         sb.append(addr[i] & 0xff);
425         i++;
426         
427         if (i == len)
428           break;
429         
430         sb.append('.');
431       }
432
433     return sb.toString();
434   }
435
436   /**
437    * Returns a hash value for this address.  Useful for creating hash
438    * tables.  Overrides Object.hashCode()
439    *
440    * @return A hash value for this address.
441    */
442   public int hashCode()
443   {
444     // There hashing algorithm is not specified, but a simple experiment
445     // shows that it is equal to the address, as a 32-bit big-endian integer.
446     int hash = 0;
447     int len = addr.length;
448     int i = len > 4 ? len - 4 : 0;
449
450     for (; i < len; i++)
451       hash = (hash << 8) | (addr[i] & 0xff);
452
453     return hash;
454   }
455
456   /**
457    * Tests this address for equality against another InetAddress.  The two
458    * addresses are considered equal if they contain the exact same octets.
459    * This implementation overrides Object.equals()
460    *
461    * @param obj The address to test for equality
462    *
463    * @return true if the passed in object's address is equal to this one's,
464    * false otherwise
465    */
466   public boolean equals(Object obj)
467   {
468     if (! (obj instanceof InetAddress))
469       return false;
470
471     // "The Java Class Libraries" 2nd edition says "If a machine has
472     // multiple names instances of InetAddress for different name of
473     // that same machine are not equal.  This is because they have
474     // different host names."  This violates the description in the
475     // JDK 1.2 API documentation.  A little experimentation
476     // shows that the latter is correct.
477     byte[] addr2 = ((InetAddress) obj).addr;
478
479     if (addr.length != addr2.length)
480       return false;
481
482     for (int i = 0; i < addr.length; i++)
483       if (addr[i] != addr2[i])
484         return false;
485
486     return true;
487   }
488
489   /**
490    * Converts this address to a String.  This string contains the IP in
491    * dotted decimal form. For example: "127.0.0.1"  This method is equivalent
492    * to getHostAddress() and overrides Object.toString()
493    *
494    * @return This address in String form
495    */
496   public String toString()
497   {
498     String addr = getHostAddress();
499     String host = (hostName != null) ? hostName : "";
500     return host + "/" + addr;
501   }
502
503   /**
504    * Returns an InetAddress object given the raw IP address.
505    *
506    * The argument is in network byte order: the highest order byte of the
507    * address is in getAddress()[0].
508    *
509    * @param addr The IP address to create the InetAddress object from
510    *
511    * @exception UnknownHostException If IP address has illegal length
512    *
513    * @since 1.4
514    */
515   public static InetAddress getByAddress(byte[] addr)
516     throws UnknownHostException
517   {
518     return getByAddress(null, addr);
519   }
520
521   /**
522    * Creates an InetAddress based on the provided host name and IP address.
523    * No name service is checked for the validity of the address.
524    *
525    * @param host The hostname of the InetAddress object to create
526    * @param addr The IP address to create the InetAddress object from
527    *
528    * @exception UnknownHostException If IP address is of illegal length
529    *
530    * @since 1.4
531    */
532   public static InetAddress getByAddress(String host, byte[] addr)
533     throws UnknownHostException
534   {
535     if (addr.length == 4)
536       return new Inet4Address(addr, host);
537
538     if (addr.length == 16)
539       return new Inet6Address(addr, host);
540
541     throw new UnknownHostException("IP address has illegal length");
542   }
543
544   /**
545    * If hostname  is a valid numeric IP address, return the numeric address.
546    * Otherwise, return null.
547    *
548    * @param hostname the name of the host
549    */
550   private static native byte[] aton(String hostname);
551
552   /**
553    * Looks up all addresses of a given host.
554    *
555    * @param hostname the host to lookup
556    * @param ipaddr FIXME
557    * @param all FIXME
558    *
559    * @return an array with all found addresses
560    */
561   private static native InetAddress[] lookup (String hostname,
562                                               InetAddress ipaddr, boolean all);
563
564   /**
565    * Returns tha family type of an IP address.
566    *
567    * @param addr the IP address
568    *
569    * @return the family
570    */
571   private static native int getFamily (byte[] ipaddr);
572
573   /**
574    * Returns an InetAddress object representing the IP address of the given
575    * hostname.  This name can be either a hostname such as "www.urbanophile.com"
576    * or an IP address in dotted decimal format such as "127.0.0.1".  If the
577    * hostname is null or "", the hostname of the local machine is supplied by
578    * default.  This method is equivalent to returning the first element in
579    * the InetAddress array returned from GetAllByName.
580    *
581    * @param hostname The name of the desired host, or null for the local 
582    * loopback address.
583    *
584    * @return The address of the host as an InetAddress object.
585    *
586    * @exception UnknownHostException If no IP address for the host could
587    * be found
588    * @exception SecurityException If a security manager exists and its
589    * checkConnect method doesn't allow the operation
590    */
591   public static InetAddress getByName(String hostname)
592     throws UnknownHostException
593   {
594     // If null or the empty string is supplied, the loopback address
595     // is returned. Note that this is permitted without a security check.
596     if (hostname == null || hostname.length() == 0)
597       return loopback;
598
599     SecurityManager s = System.getSecurityManager();
600     if (s != null)
601       s.checkConnect(hostname, -1);
602
603     // Assume that the host string is an IP address
604     byte[] address = aton(hostname);
605     if (address != null)
606       {
607         if (address.length == 4)
608           return new Inet4Address (address, null);
609         else if (address.length == 16)
610           {
611             if ((address [10] == 0xFF) && (address [11] == 0xFF))
612               {
613                 byte[] ip4addr = new byte [4];
614                 ip4addr [0] = address [12];
615                 ip4addr [1] = address [13];
616                 ip4addr [2] = address [14];
617                 ip4addr [3] = address [15];
618                 return new Inet4Address (ip4addr, null);
619               }
620             return new Inet6Address (address, null);
621           }
622         else
623           throw new UnknownHostException ("Address has invalid length");
624       }
625
626     // Try to resolve the host by DNS
627     InetAddress result = new InetAddress(null, null);
628     lookup (hostname, result, false);
629     return result;
630   }
631
632   /**
633    * Returns an array of InetAddress objects representing all the host/ip
634    * addresses of a given host, given the host's name.  This name can be
635    * either a hostname such as "www.urbanophile.com" or an IP address in
636    * dotted decimal format such as "127.0.0.1".  If the value is null, the
637    * hostname of the local machine is supplied by default.
638    *
639    * @param hostname The name of the desired host, or null for the
640    * local loopback address.
641    *
642    * @return All addresses of the host as an array of InetAddress objects.
643    *
644    * @exception UnknownHostException If no IP address for the host could
645    * be found
646    * @exception SecurityException If a security manager exists and its
647    * checkConnect method doesn't allow the operation
648    */
649   public static InetAddress[] getAllByName(String hostname)
650     throws UnknownHostException
651   {
652     // If null or the empty string is supplied, the loopback address
653     // is returned. Note that this is permitted without a security check.
654     if (hostname == null || hostname.length() == 0)
655       return new InetAddress[] {loopback};
656
657     SecurityManager s = System.getSecurityManager();
658     if (s != null)
659       s.checkConnect(hostname, -1);
660
661     // Check if hostname is an IP address
662     byte[] address = aton (hostname);
663     if (address != null)
664       {
665         InetAddress[] result = new InetAddress [1];
666         result [0] = new InetAddress (address, null);
667         return result;
668       }
669
670     // Try to resolve the hostname by DNS
671     return lookup (hostname, null, true);
672   }
673
674   /**
675    * This native method looks up the hostname of the local machine
676    * we are on.  If the actual hostname cannot be determined, then the
677    * value "localhost" will be used.  This native method wrappers the
678    * "gethostname" function.
679    *
680    * @return The local hostname.
681    */
682   private static native String getLocalHostname();
683
684   /**
685    * Returns an InetAddress object representing the address of the current
686    * host.
687    *
688    * @return The local host's address
689    *
690    * @exception UnknownHostException If no IP address for the host could
691    * be found
692    */
693   public static InetAddress getLocalHost() throws UnknownHostException
694   {
695     SecurityManager s = System.getSecurityManager();
696     
697     // Experimentation shows that JDK1.2 does cache the result.
698     // However, if there is a security manager, and the cached result
699     // is other than "localhost", we need to check again.
700     if (localhost == null
701         || (s != null && ! localhost.isLoopbackAddress()))
702       getLocalHost (s);
703     
704     return localhost;
705   }
706
707   private static synchronized void getLocalHost (SecurityManager s)
708     throws UnknownHostException
709   {
710     // Check the localhost cache again, now that we've synchronized.
711     if (s == null && localhost != null)
712       return;
713     
714     String hostname = getLocalHostname();
715     
716     if (s != null)
717       {
718         // "The Java Class Libraries" suggests that if the security
719         // manager disallows getting the local host name, then
720         // we use the loopback host.
721         // However, the JDK 1.2 API claims to throw SecurityException,
722         // which seems to suggest SecurityException is *not* caught.
723         // In this case, experimentation shows that former is correct.
724         try
725           {
726             // This is wrong, if the name returned from getLocalHostname()
727             // is not a fully qualified name.  FIXME.
728             s.checkConnect (hostname, -1);
729           }
730         catch (SecurityException ex)
731           {
732             hostname = null;
733           }
734       }
735     
736     if (hostname != null && hostname.length() != 0)
737       {
738         try
739           {
740             localhost = new InetAddress (null, null);
741             lookup (hostname, localhost, false);
742           }
743         catch (Exception ex)
744           {
745           }
746       }
747     else
748       throw new UnknownHostException();
749     
750     if (localhost == null)
751       localhost = new InetAddress (loopbackAddress, "localhost");
752   }
753
754   /**
755    * Needed for serialization
756    */
757   private void readResolve() throws ObjectStreamException
758   {
759     // FIXME: implement this
760   }
761
762   private void readObject(ObjectInputStream ois)
763     throws IOException, ClassNotFoundException
764   {
765     ois.defaultReadObject();
766     addr = new byte[4];
767     addr[3] = (byte) address;
768
769     for (int i = 2; i >= 0; --i)
770       addr[i] = (byte) (address >>= 8);
771
772     // Ignore family from serialized data.  Since the saved address is 32 bits
773     // the deserialized object will have an IPv4 address i.e. AF_INET family.
774     // FIXME: An alternative is to call the aton method on the deserialized
775     // hostname to get a new address.  The Serialized Form doc is silent
776     // on how these fields are used.
777     family = getFamily (addr);
778   }
779
780   private void writeObject(ObjectOutputStream oos) throws IOException
781   {
782     // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
783     // or a 16 byte IPv6 address.
784     int len = addr.length;
785     int i = len - 4;
786
787     for (; i < len; i++)
788       address = address << 8 | (((int) addr[i]) & 0xFF);
789
790     oos.defaultWriteObject();
791   }
792 }