Home | History | Annotate | Download | only in core
      1 /*
      2 * Conditions Of Use
      3 *
      4 * This software was developed by employees of the National Institute of
      5 * Standards and Technology (NIST), an agency of the Federal Government.
      6 * Pursuant to title 15 Untied States Code Section 105, works of NIST
      7 * employees are not subject to copyright protection in the United States
      8 * and are considered to be in the public domain.  As a result, a formal
      9 * license is not needed to use the software.
     10 *
     11 * This software is provided by NIST as a service and is expressly
     12 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
     13 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
     14 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
     15 * AND DATA ACCURACY.  NIST does not warrant or make any representations
     16 * regarding the use of the software or the results thereof, including but
     17 * not limited to the correctness, accuracy, reliability or usefulness of
     18 * the software.
     19 *
     20 * Permission to use this software is contingent upon your acceptance
     21 * of the terms of this agreement
     22 *
     23 * .
     24 *
     25 */
     26 /***************************************************************************
     27  * Product of NIST/ITL Advanced Networking Technologies Division(ANTD).   *
     28  **************************************************************************/
     29 package gov.nist.core;
     30 
     31 import java.net.*;
     32 
     33 /*
     34  * IPv6 Support added by Emil Ivov (emil_ivov (at) yahoo.com)<br/>
     35  * Network Research Team (http://www-r2.u-strasbg.fr))<br/>
     36  * Louis Pasteur University - Strasbourg - France<br/>
     37  *
     38  * Frank Feif reported a bug.
     39  *
     40  *
     41  */
     42 /**
     43  * Stores hostname.
     44  * @version 1.2
     45  *
     46  * @author M. Ranganathan
     47  * @author Emil Ivov <emil_ivov (at) yahoo.com> IPV6 Support. <br/>
     48  *
     49  *
     50  *
     51 
     52  * Marc Bednarek <bednarek (at) nist.gov> (Bugfixes).<br/>
     53  *
     54  */
     55 public class Host extends GenericObject {
     56 
     57     /**
     58      * Determines whether or not we should tolerate and strip address scope
     59      * zones from IPv6 addresses. Address scope zones are sometimes returned
     60      * at the end of IPv6 addresses generated by InetAddress.getHostAddress().
     61      * They are however not part of the SIP semantics so basically this method
     62      * determines whether or not the parser should be stripping them (as
     63      * opposed simply being blunt and throwing an exception).
     64      */
     65     private boolean stripAddressScopeZones = false;
     66 
     67     private static final long serialVersionUID = -7233564517978323344L;
     68     protected static final int HOSTNAME = 1;
     69     protected static final int IPV4ADDRESS = 2;
     70     protected static final int IPV6ADDRESS = 3;
     71 
     72     /** hostName field
     73      */
     74     protected String hostname;
     75 
     76     /** address field
     77      */
     78 
     79     protected int addressType;
     80 
     81     private InetAddress inetAddress;
     82 
     83     /** default constructor
     84      */
     85     public Host() {
     86         addressType = HOSTNAME;
     87 
     88         stripAddressScopeZones
     89             = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES");
     90     }
     91 
     92     /** Constructor given host name or IP address.
     93      */
     94     public Host(String hostName) throws IllegalArgumentException {
     95         if (hostName == null)
     96             throw new IllegalArgumentException("null host name");
     97 
     98         stripAddressScopeZones
     99             = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES");
    100 
    101         setHost(hostName, IPV4ADDRESS);
    102     }
    103 
    104     /** constructor
    105      * @param name String to set
    106      * @param addrType int to set
    107      */
    108     public Host(String name, int addrType) {
    109         stripAddressScopeZones
    110             = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES");
    111 
    112         setHost(name, addrType);
    113     }
    114 
    115     /**
    116      * Return the host name in encoded form.
    117      * @return String
    118      */
    119     public String encode() {
    120         return encode(new StringBuffer()).toString();
    121     }
    122 
    123     public StringBuffer encode(StringBuffer buffer) {
    124         if (addressType == IPV6ADDRESS && !isIPv6Reference(hostname)) {
    125             buffer.append('[').append(hostname).append(']');
    126         } else {
    127             buffer.append(hostname);
    128         }
    129         return buffer;
    130     }
    131 
    132     /**
    133      * Compare for equality of hosts.
    134      * Host names are compared by textual equality. No dns lookup
    135      * is performed.
    136      * @param obj Object to set
    137      * @return boolean
    138      */
    139     public boolean equals(Object obj) {
    140         if ( obj == null ) return false;
    141         if (!this.getClass().equals(obj.getClass())) {
    142             return false;
    143         }
    144         Host otherHost = (Host) obj;
    145         return otherHost.hostname.equals(hostname);
    146 
    147     }
    148 
    149     /** get the HostName field
    150      * @return String
    151      */
    152     public String getHostname() {
    153         return hostname;
    154     }
    155 
    156     /** get the Address field
    157      * @return String
    158      */
    159     public String getAddress() {
    160         return hostname;
    161     }
    162 
    163     /**
    164      * Convenience function to get the raw IP destination address
    165      * of a SIP message as a String.
    166      * @return String
    167      */
    168     public String getIpAddress() {
    169         String rawIpAddress = null;
    170         if (hostname == null)
    171             return null;
    172         if (addressType == HOSTNAME) {
    173             try {
    174                 if (inetAddress == null)
    175                     inetAddress = InetAddress.getByName(hostname);
    176                 rawIpAddress = inetAddress.getHostAddress();
    177             } catch (UnknownHostException ex) {
    178                 dbgPrint("Could not resolve hostname " + ex);
    179             }
    180         } else {
    181             rawIpAddress = hostname;
    182         }
    183         return rawIpAddress;
    184     }
    185 
    186     /**
    187      * Set the hostname member.
    188      * @param h String to set
    189      */
    190     public void setHostname(String h) {
    191         setHost(h, HOSTNAME);
    192     }
    193 
    194     /** Set the IP Address.
    195      *@param address is the address string to set.
    196      */
    197     public void setHostAddress(String address) {
    198         setHost(address, IPV4ADDRESS);
    199     }
    200 
    201     /**
    202      * Sets the host address or name of this object.
    203      *
    204      * @param host that host address/name value
    205      * @param type determines whether host is an address or a host name
    206      */
    207     private void setHost(String host, int type){
    208         //set inetAddress to null so that it would be reinited
    209         //upon next call to getInetAddress()
    210         inetAddress = null;
    211 
    212         if (isIPv6Address(host))
    213             addressType = IPV6ADDRESS;
    214         else
    215             addressType = type;
    216 
    217         // Null check bug fix sent in by jpaulo (at) ipb.pt
    218         if (host != null){
    219             hostname = host.trim();
    220 
    221             //if this is an FQDN, make it lowercase to simplify processing
    222             if(addressType == HOSTNAME)
    223                 hostname = hostname.toLowerCase();
    224 
    225             //remove address scope zones if this is an IPv6 address as they
    226             //are not allowed by the RFC
    227             int zoneStart = -1;
    228             if(addressType == IPV6ADDRESS
    229                 && stripAddressScopeZones
    230                 && (zoneStart = hostname.indexOf('%'))!= -1){
    231 
    232                 hostname = hostname.substring(0, zoneStart);
    233             }
    234         }
    235     }
    236 
    237     /**
    238      * Set the address member
    239      * @param address address String to set
    240      */
    241     public void setAddress(String address) {
    242         this.setHostAddress(address);
    243     }
    244 
    245     /** Return true if the address is a DNS host name
    246      *  (and not an IPV4 address)
    247      *@return true if the hostname is a DNS name
    248      */
    249     public boolean isHostname() {
    250         return addressType == HOSTNAME;
    251     }
    252 
    253     /** Return true if the address is a DNS host name
    254      *  (and not an IPV4 address)
    255      *@return true if the hostname is host address.
    256      */
    257     public boolean isIPAddress() {
    258         return addressType != HOSTNAME;
    259     }
    260 
    261     /** Get the inet address from this host.
    262      * Caches the inet address returned from dns lookup to avoid
    263      * lookup delays.
    264      *
    265      *@throws UnkownHostexception when the host name cannot be resolved.
    266      */
    267     public InetAddress getInetAddress() throws java.net.UnknownHostException {
    268         if (hostname == null)
    269             return null;
    270         if (inetAddress != null)
    271             return inetAddress;
    272         inetAddress = InetAddress.getByName(hostname);
    273         return inetAddress;
    274 
    275     }
    276 
    277     //----- IPv6
    278     /**
    279      * Verifies whether the <code>address</code> could
    280      * be an IPv6 address
    281      */
    282     private boolean isIPv6Address(String address) {
    283         return (address != null && address.indexOf(':') != -1);
    284     }
    285 
    286     /**
    287      * Verifies whether the ipv6reference, i.e. whether it enclosed in
    288      * square brackets
    289      */
    290     public static boolean isIPv6Reference(String address) {
    291         return address.charAt(0) == '['
    292             && address.charAt(address.length() - 1) == ']';
    293     }
    294 
    295     @Override
    296     public int hashCode() {
    297         return this.getHostname().hashCode();
    298 
    299     }
    300 }
    301