OSDN Git Service

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