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 **************************************************************************/ 29package gov.nist.core; 30 31import java.net.*; 32 33/* 34 * IPv6 Support added by Emil Ivov (emil_ivov@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@yahoo.com> IPV6 Support. <br/> 48 * 49 * 50 * 51 52 * Marc Bednarek <bednarek@nist.gov> (Bugfixes).<br/> 53 * 54 */ 55public 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@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