home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / InetAddress.java < prev    next >
Text File  |  1997-10-02  |  18KB  |  541 lines

  1. /*
  2.  * @(#)InetAddress.java    1.43 97/07/16
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22.  
  23. package java.net;
  24.  
  25. import java.util.Hashtable;
  26.  
  27. /**
  28.  * This class represents an Internet Protocol (IP) address. 
  29.  * <p>
  30.  * Applications should use the methods <code>getLocalHost</code>, 
  31.  * <code>getByName</code>, or <code>getAllByName</code> to 
  32.  * create a new <code>InetAddress</code> instance. 
  33.  *
  34.  * @author  Chris Warth
  35.  * @version 1.43, 07/16/97
  36.  * @see     java.net.InetAddress#getAllByName(java.lang.String)
  37.  * @see     java.net.InetAddress#getByName(java.lang.String)
  38.  * @see     java.net.InetAddress#getLocalHost()
  39.  * @since   JDK1.0
  40.  */
  41. public final 
  42. class InetAddress implements java.io.Serializable {
  43.     String hostName;
  44.     int address;    // Currently we only deal effectively with 32-bit addresses. 
  45.             // However this field can be expanded to be a byte array 
  46.             // or a 64-bit quantity without too much effort.
  47.     int family;
  48.  
  49.     /** use serialVersionUID from JDK 1.0.2 for interoperability */
  50.     private static final long serialVersionUID = 3286316764910316507L;
  51.  
  52.     /*
  53.      * Load net library into runtime.
  54.      */
  55.     static {
  56.     System.loadLibrary("net");
  57.     }
  58.  
  59.     /** 
  60.      * Constructor for the Socket.accept() method.
  61.      * This creates an empty InetAddress, which is filled in by
  62.      * the accept() method.  This InetAddress, however, is not
  63.      * put in the address cache, since it is not created by name.
  64.      */
  65.     InetAddress() {
  66.       family = impl.getInetFamily();
  67.     }
  68.  
  69.     /**
  70.      * Creates an InetAddress with the specified host name and IP address.
  71.      * @param hostName the specified host name
  72.      * @param addr the specified IP address.  The address is expected in 
  73.      *          network byte order.
  74.      * @exception UnknownHostException If the address is unknown.
  75.      */
  76.     InetAddress(String hostName, byte addr[]) {
  77.     this.hostName = new String(hostName);
  78.     this.family = impl.getInetFamily();
  79.     /*
  80.      * We must be careful here to maintain the network byte
  81.      * order of the address.  As it comes in, the most
  82.      * significant byte of the address is in addr[0].  It
  83.      * actually doesn't matter what order they end up in the
  84.      * array, as long as it is documented and consistent.
  85.      */
  86.     address  = addr[3] & 0xFF;
  87.     address |= ((addr[2] << 8) & 0xFF00);
  88.     address |= ((addr[1] << 16) & 0xFF0000);
  89.     address |= ((addr[0] << 24) & 0xFF000000);
  90.     }
  91.  
  92.     /**
  93.      * Utility routine to check if the InetAddress is a 
  94.      * IP multicast address. IP multicast address is a Class D
  95.      * address i.e first four bits of the address are 1110.
  96.      * @since   JDK1.1
  97.      */
  98.     public boolean isMulticastAddress() {
  99.     return ((address & 0xf0000000) == 0xe0000000);
  100.     }
  101.  
  102.     /**
  103.      * Returns the fully qualified host name for this address.
  104.      * If the host is equal to null, then this address refers to any
  105.      * of the local machine's available network addresses.
  106.      *
  107.      * @return  the fully qualified host name for this address.
  108.      * @since   JDK1.0
  109.      */
  110.     public String getHostName() {
  111.     if (hostName == null) {
  112.         try {
  113.         hostName = new String(impl.getHostByAddr(address));
  114.         InetAddress[] arr = (InetAddress[])addressCache.get(hostName);
  115.         if(arr != null) {
  116.             for(int i = 0; i < arr.length; i++) {
  117.             if(hostName.equalsIgnoreCase(arr[i].hostName) && 
  118.                address != arr[i].address) {
  119.                 /* This means someone's playing funny games with DNS
  120.                  * This hostName used to have one IP address, now it 
  121.                  * has another.  At any rate, don't let them "see" 
  122.                  * the new hostName, and don't cache it either.
  123.                  */
  124.                 hostName = getHostAddress();
  125.                 break;
  126.             }
  127.             }
  128.         } else { 
  129.             /* hostname wasn't in cache before.  It's a real hostname,
  130.              * not "%d.%d.%d.%d" so cache it
  131.              */
  132.             arr = new InetAddress[1];
  133.             arr[0] = this;
  134.             addressCache.put(hostName, arr);
  135.         }
  136.         /* finally check to see if calling code is allowed to know
  137.          * the hostname for this IP address, ie, connect to the host
  138.          */
  139.         SecurityManager sec = System.getSecurityManager();
  140.         if (sec != null && !sec.getInCheck()) {
  141.             sec.checkConnect(hostName, -1);
  142.         }
  143.         } catch (SecurityException e) {
  144.         hostName = getHostAddress();
  145.         } catch (UnknownHostException e) {
  146.         hostName = getHostAddress();
  147.         }
  148.     }
  149.     return hostName;
  150.     }
  151.  
  152.     /**
  153.      * Returns the raw IP address of this <code>InetAddress</code> 
  154.      * object. The result is in network byte order: the highest order 
  155.      * byte of the address is in <code>getAddress()[0]</code>. 
  156.      *
  157.      * @return  the raw IP address of this object.
  158.      * @since   JDK1.0
  159.      */
  160.     public byte[] getAddress() {    
  161.     byte[] addr = new byte[4];
  162.  
  163.     addr[0] = (byte) ((address >>> 24) & 0xFF);
  164.     addr[1] = (byte) ((address >>> 16) & 0xFF);
  165.     addr[2] = (byte) ((address >>> 8) & 0xFF);
  166.     addr[3] = (byte) (address & 0xFF);
  167.     return addr;
  168.     }
  169.  
  170.     /**
  171.      * Returns the IP address string "%d.%d.%d.%d"
  172.      * @return raw IP address in a string format
  173.      * @since   JDK1.1
  174.      */
  175.     public String getHostAddress() {    
  176.          return ((address >>> 24) & 0xFF) + "." +
  177.                 ((address >>> 16) & 0xFF) + "." +
  178.                 ((address >>>  8) & 0xFF) + "." +
  179.                 ((address >>>  0) & 0xFF);
  180.      }
  181.  
  182.  
  183.     /**
  184.      * Returns a hashcode for this IP address.
  185.      *
  186.      * @return  a hash code value for this IP address. 
  187.      * @since   JDK1.0
  188.      */
  189.     public int hashCode() {
  190.     return address;
  191.     }
  192.  
  193.     /**
  194.      * Compares this object against the specified object.
  195.      * The result is <code>true</code> if and only if the argument is 
  196.      * not <code>null</code> and it represents the same IP address as 
  197.      * this object. 
  198.      * <p>
  199.      * Two instances of <code>InetAddress</code> represent the same IP 
  200.      * address if the length of the byte arrays returned by 
  201.      * <code>getAddress</code> is the same for both, and each of the 
  202.      * array components is the same for the byte arrays. 
  203.      *
  204.      * @param   obj   the object to compare against.
  205.      * @return  <code>true</code> if the objects are the same;
  206.      *          <code>false</code> otherwise.
  207.      * @see     java.net.InetAddress#getAddress()
  208.      * @since   JDK1.0
  209.      */
  210.     public boolean equals(Object obj) {
  211.     return (obj != null) && (obj instanceof InetAddress) &&
  212.         (((InetAddress)obj).address == address);
  213.     }
  214.  
  215.     /**
  216.      * Converts this IP address to a <code>String</code>.
  217.      *
  218.      * @return  a string representation of this IP address.
  219.      * @since   JDK1.0
  220.      */
  221.     public String toString() {
  222.     return getHostName() + "/" + getHostAddress();
  223.     }
  224.  
  225.     /* 
  226.      * Cached addresses - our own litle nis, not! 
  227.      *
  228.      * Do not purge cache of numerical IP addresses, since 
  229.      * duplicate dynamic DNS name lookups can leave the system
  230.      * vulnerable to hostname spoofing attacks.  Once a hostname
  231.      * has been looked up in DNS and entered into the Java cache, 
  232.      * from then on, the hostname is translated to IP address only
  233.      * via the cache.
  234.      */
  235.     static Hashtable        addressCache = new Hashtable();
  236.     static InetAddress        unknownAddress;
  237.     static InetAddress        anyLocalAddress;
  238.     static InetAddress      localHost;
  239.     static InetAddress[]    unknown_array; // put THIS in cache
  240.     static InetAddressImpl  impl;
  241.  
  242.     /* 
  243.      * generic localHost to give back to applets 
  244.      * - private so not API delta
  245.      */
  246.     private static InetAddress      loopbackHost;
  247.  
  248.     static {
  249.  
  250.     /*
  251.      * Property "impl.prefix" will be prepended to the classname of the
  252.      * implementation object we instantiate, to which we delegate the real work 
  253.      * (like native methods).  This property can vary across implementations
  254.      * of the java.* classes.  The default is an empty String "".
  255.      */
  256.  
  257.     String prefix = System.getProperty("impl.prefix", "");
  258.     try {
  259.         impl = null;
  260.         impl = (InetAddressImpl)(Class.forName("java.net." + prefix + "InetAddressImpl")
  261.                            .newInstance());
  262.     } catch (ClassNotFoundException e) {
  263.         System.err.println("Class not found: java.net." + prefix + 
  264.                    "InetAddressImpl:\ncheck impl.prefix property " +
  265.                    "in your properties file.");
  266.     } catch (InstantiationException e) {
  267.         System.err.println("Could not instantiate: java.net." + prefix + 
  268.                    "InetAddressImpl:\ncheck impl.prefix property " +
  269.                    "in your properties file.");
  270.     } catch (IllegalAccessException e) {
  271.         System.err.println("Cannot access class: java.net." + prefix + 
  272.                    "InetAddressImpl:\ncheck impl.prefix property " +
  273.                    "in your properties file.");
  274.     }
  275.  
  276.     if (impl == null) {
  277.         try {
  278.         impl = (InetAddressImpl)(Class.forName("java.net.InetAddressImpl")
  279.                      .newInstance());
  280.         } catch (Exception e) {
  281.         throw new Error("System property impl.prefix incorrect");
  282.         }
  283.     }
  284.  
  285.     unknownAddress = new InetAddress();
  286.     anyLocalAddress = new InetAddress();
  287.     impl.makeAnyLocalAddress(anyLocalAddress);
  288.     byte[] IP = new byte[4];
  289.     IP[0] = 0x7F;
  290.     IP[1] = 0x00;
  291.     IP[2] = 0x00;
  292.     IP[3] = 0x01;
  293.     loopbackHost = new InetAddress("localhost", IP);
  294.  
  295.     /* find the local host name */
  296.     try {
  297.         localHost = new InetAddress();
  298.         localHost.hostName = impl.getLocalHostName();
  299.         /* we explicitly leave the address of the local host
  300.          * uninitialized.  A DNS lookup in this, the static
  301.          * initializer, will cause a machine disconnected
  302.          * from the network to hang - it'll be trying to query
  303.          * a DNS server that isn't there.
  304.          *
  305.          * Instead, we just get the hostname of the local host.
  306.          * The native code for this just calls gethostname()
  307.          * which should be pretty innocuous - it shouldn't try
  308.          * to contact a DNS server.  If any application
  309.          * calls InetAddress.getLocalHost(), we initialize
  310.          * the local host's address there if not already initialized.
  311.          *
  312.          * Note that for this to work it is also essential that
  313.          * the localHost InetAddress is _NOT_ put into the address cache
  314.          * here in the static initializer (which happens if we call
  315.          * getByName() from the static initializer).  It _IS_ OK
  316.          * to put it in the addressCache after initialization.
  317.          *
  318.          * The unitialized state of the localHost's address is -1,
  319.          * or IP address 255.255.255.255 which we know cannot be
  320.          * a legal host address.
  321.          */
  322.         localHost.address = -1;
  323.     } catch (Exception ex) { /* this shouldn't happen */
  324.         localHost = unknownAddress;
  325.     }
  326.  
  327.     /* cache the name/address pair "0.0.0.0"/0.0.0.0 */
  328.     String unknownByAddr = new String("0.0.0.0");
  329.     unknown_array = new InetAddress[1];
  330.     unknown_array[0] = new InetAddress(unknownByAddr, unknownAddress.getAddress());
  331.     addressCache.put(unknownByAddr, unknown_array);
  332.     }
  333.  
  334.     /**
  335.      * Determines the IP address of a host, given the host's name. The 
  336.      * host name can either be a machine name, such as 
  337.      * "<code>java.sun.com</code>", or a string representing its IP 
  338.      * address, such as "<code>206.26.48.100</code>". 
  339.      *
  340.      * @param      host   the specified host, or <code>null</code> for the
  341.      *                    local host.
  342.      * @return     an IP address for the given host name.
  343.      * @exception  UnknownHostException  if no IP address for the
  344.      *               <code>host</code> could be found.
  345.      * @since      JDK1.0
  346.      */
  347.     public static InetAddress getByName(String host)
  348.     throws UnknownHostException {
  349.     Object obj = null;
  350.     if (host == null || host.length() == 0) {
  351.         return loopbackHost;
  352.     }
  353.  
  354.         if (!Character.isDigit(host.charAt(0))) {
  355.         return getAllByName0(host)[0];
  356.     } else {
  357.         /* The string (probably) represents a numerical IP address.
  358.          * Parse it into an int, don't do uneeded reverese lookup,
  359.          * leave hostName null, don't cache.  If it isn't an IP address,
  360.          * (i.e., not "%d.%d.%d.%d") or if any element > 0xFF, 
  361.          * we treat it as a hostname, and lookup that way.
  362.          * This seems to be 100% compliant to the RFC1123 spec: 
  363.          * a partial hostname like 3com.domain4 is technically valid.
  364.          */
  365.  
  366.         int IP = 0x00;
  367.         int hitDots = 0;
  368.         char[] data = host.toCharArray();
  369.  
  370.         for(int i = 0; i < data.length; i++) {
  371.         char c = data[i];
  372.         if (c < 48 || c > 57) { // !digit
  373.             return getAllByName0(host)[0];
  374.         }
  375.         int b = 0x00;
  376.         while(c != '.') {
  377.             if (c < 48 || c > 57) { // !digit
  378.             return getAllByName0(host)[0];
  379.             }
  380.             b = b*10 + c - '0';
  381.  
  382.             if (++i >= data.length)
  383.             break;
  384.             c = data[i];
  385.         }
  386.         if(b > 0xFF) { /* bogus - bigger than a byte */
  387.             return getAllByName0(host)[0];
  388.         }
  389.         IP = (IP << 8) + b;
  390.         hitDots++;
  391.         }
  392.  
  393.         if(hitDots != 4 || host.endsWith(".")) {
  394.         return getAllByName0(host)[0];
  395.         }
  396.  
  397.         InetAddress in = new InetAddress();
  398.         in.address = IP;
  399.         in.hostName = null;
  400.         return in;
  401.     }
  402.  
  403.     }
  404.  
  405.     /** 
  406.      * Determines all the IP addresses of a host, given the host's name. 
  407.      * The host name can either be a machine name, such as 
  408.      * "<code>java.sun.com</code>", or a string representing 
  409.      * its IP address, such as "<code>206.26.48.100</code>". 
  410.      *
  411.      * @param      host   the name of the host.
  412.      * @return     an array of all the IP addresses for a given host name.
  413.      * @exception  UnknownHostException  if no IP address for the
  414.      *               <code>host</code> could be found.
  415.      * @since      JDK1.0
  416.      */
  417.     public static InetAddress getAllByName(String host)[]
  418.     throws UnknownHostException {
  419.  
  420.     if (host == null || host.length() == 0) {
  421.         throw new UnknownHostException("empty string");
  422.     }
  423.  
  424.     if(Character.isDigit(host.charAt(0))) {
  425.         InetAddress[] ret = new InetAddress[1];
  426.         ret[0] = getByName(host);
  427.         return ret;
  428.     } else {
  429.         return getAllByName0(host);
  430.     }
  431.     }
  432.  
  433.     private static InetAddress[] getAllByName0 (String host) 
  434.     throws UnknownHostException  {
  435.     /* If it gets here it is presumed to be a hostname */
  436.     /* Cache.get can return: null, unknownAddress, or InetAddress[] */
  437.         Object obj = null;
  438.     Object objcopy = null;
  439.  
  440.     /* make sure the connection to the host is allowed, before we
  441.      * give out a hostname
  442.      */
  443.     SecurityManager security = System.getSecurityManager();
  444.     if (security != null && !security.getInCheck()) {
  445.         security.checkConnect(host, -1);
  446.     }
  447.  
  448.     synchronized (addressCache) {
  449.         obj = addressCache.get(host);
  450.  
  451.     /* If no entry in cache, then do the host lookup */
  452.     
  453.         if (obj == null) {
  454.         try {
  455.             /*
  456.              * Do not put the call to lookup() inside the
  457.              * constructor.  if you do you will still be
  458.              * allocating space when the lookup fails.
  459.              */
  460.             byte[][] byte_array = impl.lookupAllHostAddr(host);
  461.             InetAddress[] addr_array = new InetAddress[byte_array.length];
  462.  
  463.             for (int i = 0; i < byte_array.length; i++) {
  464.             byte addr[] = byte_array[i];
  465.             addr_array[i] = new InetAddress(host, addr);
  466.             }
  467.             obj = addr_array;
  468.         } catch (UnknownHostException e) {
  469.             obj  = unknown_array;
  470.         }
  471.         addressCache.put(host, obj);
  472.         }
  473.     } /* end synchronized block */
  474.  
  475.     if (obj == unknown_array) {
  476.         /*
  477.          * We currently cache the fact that a host is unknown.
  478.          */
  479.         throw new UnknownHostException(host);
  480.     }
  481.  
  482.     /* Make a copy of the InetAddress array */
  483.     try {
  484.           objcopy = ((InetAddress [])obj).clone();
  485.           // the following line is a hack, to ensure that the code
  486.           // can compile for both the broken compiler and the fixed one.
  487.           if (objcopy == null) 
  488.           throw new CloneNotSupportedException();
  489.     } catch (CloneNotSupportedException cnse) {
  490.           cnse.printStackTrace();
  491.     }
  492.  
  493.     return (InetAddress [])objcopy;
  494.     }
  495.  
  496.     /**
  497.      * Returns the local host.
  498.      *
  499.      * @return     the IP address of the local host.
  500.      * @exception  UnknownHostException  if no IP address for the
  501.      *               <code>host</code> could be found.
  502.      * @since      JDK1.0
  503.      */
  504.     public static InetAddress getLocalHost() throws UnknownHostException {
  505.         if (localHost.equals(unknownAddress)) {
  506.         throw new UnknownHostException();
  507.     }
  508.  
  509.     /* If the localhost's address is not initialized yet, initialize
  510.      * it.  It is no longer initialized in the static initializer 
  511.      * (see comment there).
  512.      */
  513.  
  514.     if (localHost.address == -1) {
  515.         localHost = getAllByName(localHost.hostName)[0];
  516.         /* This puts it in the address cache as well */
  517.     }
  518.  
  519.         /* make sure the connection to the host is allowed: if yes,
  520.      * return the "real" localHost; if not, return loopback "127.0.0.1"   
  521.      */
  522.     SecurityManager security = System.getSecurityManager();
  523.     try {
  524.         if (security != null && !security.getInCheck()) 
  525.         security.checkConnect(localHost.getHostName(), -1);
  526.     } catch (java.lang.SecurityException e) {
  527.         return loopbackHost;
  528.     }
  529.     return localHost;
  530.     }
  531. }
  532.  
  533. class InetAddressImpl {
  534.     native String getLocalHostName() throws UnknownHostException;
  535.     native void makeAnyLocalAddress(InetAddress addr);
  536.     native byte[][]
  537.         lookupAllHostAddr(String hostname) throws UnknownHostException;
  538.     native String getHostByAddr(int addr) throws UnknownHostException;
  539.     native int getInetFamily();
  540. }
  541.