001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.shared.kerberos.components; 021 022 023import java.net.Inet6Address; 024import java.net.InetAddress; 025import java.net.UnknownHostException; 026import java.nio.BufferOverflowException; 027import java.nio.ByteBuffer; 028import java.util.Arrays; 029 030import org.apache.directory.api.asn1.Asn1Object; 031import org.apache.directory.api.asn1.EncoderException; 032import org.apache.directory.api.asn1.ber.tlv.BerValue; 033import org.apache.directory.api.asn1.ber.tlv.TLV; 034import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 035import org.apache.directory.api.util.Strings; 036import org.apache.directory.server.i18n.I18n; 037import org.apache.directory.shared.kerberos.codec.types.HostAddrType; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041 042/** 043 * Provides host address information. 044 * 045 * The ASN.1 grammar for this structure is : 046 * <pre> 047 * HostAddress ::= SEQUENCE { 048 * addr-type [0] Int32, 049 * address [1] OCTET STRING 050 * } 051 * </pre> 052 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 053 */ 054public class HostAddress implements Asn1Object 055{ 056 /** The logger */ 057 private static final Logger LOG = LoggerFactory.getLogger( HostAddress.class ); 058 059 /** Speedup for logs */ 060 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 061 062 /** The host address type. One of : 063 * Address Type Value 064 * 065 * IPv4 2 066 * Directional 3 067 * ChaosNet 5 068 * XNS 6 069 * ISO 7 070 * DECNET Phase IV 12 071 * AppleTalk DDP 16 072 * NetBios 20 073 * IPv6 24 074 */ 075 private HostAddrType addrType; 076 077 /** The address */ 078 private byte[] address; 079 080 // Storage for computed lengths 081 private int addrTypeLength; 082 private int addressLength; 083 private int hostAddressLength; 084 private int hostAddressSeqLength; 085 086 087 /** 088 * Creates an empty HostAdress instance 089 */ 090 public HostAddress() 091 { 092 } 093 094 095 /** 096 * Creates a new instance of HostAddress. 097 * 098 * @param addrType The type of address 099 * @param address The address 100 */ 101 public HostAddress( HostAddrType addrType, byte[] address ) 102 { 103 this.addrType = addrType; 104 this.address = address; 105 } 106 107 108 /** 109 * Creates a new instance of HostAddress. 110 * 111 * @param internetAddress The Inet form address 112 */ 113 public HostAddress( InetAddress internetAddress ) 114 { 115 addrType = ( internetAddress instanceof Inet6Address ) ? HostAddrType.ADDRTYPE_INET6 : HostAddrType.ADDRTYPE_INET; 116 byte[] newAddress = internetAddress.getAddress(); 117 address = new byte[newAddress.length]; 118 System.arraycopy( newAddress, 0, address, 0, newAddress.length ); 119 } 120 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override 126 public int hashCode() 127 { 128 int hash = 37; 129 hash = hash * 17 + addrType.hashCode(); 130 131 if ( address != null ) 132 { 133 hash = hash * 17 + Arrays.hashCode( address ); 134 } 135 136 return hash; 137 } 138 139 140 /** 141 * Returns whether one {@link HostAddress} is equal to another. 142 * 143 * @param that The {@link HostAddress} to compare with 144 * @return true if the {@link HostAddress}'s are equal. 145 */ 146 @Override 147 public boolean equals( Object that ) 148 { 149 if ( this == that ) 150 { 151 return true; 152 } 153 154 if ( !( that instanceof HostAddress ) ) 155 { 156 return false; 157 } 158 159 HostAddress hostAddress = ( HostAddress ) that; 160 161 if ( addrType != hostAddress.addrType || ( address != null && hostAddress.address == null ) 162 || ( address == null && hostAddress.address != null ) ) 163 { 164 return false; 165 } 166 167 if ( address != null && hostAddress.address != null ) 168 { 169 if ( address.length != hostAddress.address.length ) 170 { 171 return false; 172 } 173 174 for ( int ii = 0; ii < address.length; ii++ ) 175 { 176 if ( address[ii] != hostAddress.address[ii] ) 177 { 178 return false; 179 } 180 } 181 } 182 183 return true; 184 } 185 186 187 /** 188 * Get the bytes for this address. 189 * 190 * @return The bytes of this address. 191 */ 192 public byte[] getAddress() 193 { 194 return address; 195 } 196 197 198 /** 199 * Set the address 200 * 201 * @param addresse The address 202 */ 203 public void setAddress( byte[] addresse ) 204 { 205 this.address = addresse; 206 } 207 208 209 /** 210 * Compute the host address length 211 * <pre> 212 * HostAddress : 213 * 214 * 0x30 L1 hostAddress sequence 215 * | 216 * +--> 0xA0 L2 addrType tag 217 * | | 218 * | +--> 0x02 L2-1 addrType (int) 219 * | 220 * +--> 0xA1 L3 address tag 221 * | 222 * +--> 0x04 L3-1 address (OCTET STRING) 223 * 224 * where L1 = L2 + length(0xA0) + length(L2) + 225 * L3 + length(0xA1) + length(L3) 226 * and 227 * L2 = L2-1 + length(0x02) + length( L2-1) 228 * L3 = L3-1 + length(0x04) + length( L3-1) 229 * </pre> 230 */ 231 public int computeLength() 232 { 233 // Compute the keyType. The Length will always be contained in 1 byte 234 addrTypeLength = 1 + 1 + BerValue.getNbBytes( addrType.getValue() ); 235 hostAddressLength = 1 + TLV.getNbBytes( addrTypeLength ) + addrTypeLength; 236 237 // Compute the keyValue 238 if ( address == null ) 239 { 240 addressLength = 1 + 1; 241 } 242 else 243 { 244 addressLength = 1 + TLV.getNbBytes( address.length ) + address.length; 245 } 246 247 hostAddressLength += 1 + TLV.getNbBytes( addressLength ) + addressLength; 248 249 // Compute the whole sequence length 250 hostAddressSeqLength = 1 + TLV.getNbBytes( hostAddressLength ) + hostAddressLength; 251 252 return hostAddressSeqLength; 253 } 254 255 256 /** 257 * Encode the HostAddress message to a PDU. 258 * <pre> 259 * HostAddress : 260 * 261 * 0x30 LL 262 * 0xA0 LL 263 * 0x02 0x01 addr-type 264 * 0xA1 LL 265 * 0x04 LL address 266 * </pre> 267 * @param buffer The buffer where to put the PDU. It should have been allocated 268 * before, with the right size. 269 * @return The constructed PDU. 270 */ 271 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 272 { 273 if ( buffer == null ) 274 { 275 throw new EncoderException( I18n.err( I18n.ERR_148 ) ); 276 } 277 278 try 279 { 280 // The HostAddress SEQ Tag 281 buffer.put( UniversalTag.SEQUENCE.getValue() ); 282 buffer.put( TLV.getBytes( hostAddressLength ) ); 283 284 // The addr-type, first the tag, then the value 285 buffer.put( ( byte ) 0xA0 ); 286 buffer.put( TLV.getBytes( addrTypeLength ) ); 287 BerValue.encode( buffer, addrType.getValue() ); 288 289 // The address, first the tag, then the value 290 buffer.put( ( byte ) 0xA1 ); 291 buffer.put( TLV.getBytes( addressLength ) ); 292 BerValue.encode( buffer, address ); 293 } 294 catch ( BufferOverflowException boe ) 295 { 296 LOG.error( I18n.err( I18n.ERR_143, 1 + TLV.getNbBytes( hostAddressLength ) 297 + hostAddressLength, buffer.capacity() ) ); 298 throw new EncoderException( I18n.err( I18n.ERR_138 ), boe ); 299 } 300 301 if ( IS_DEBUG ) 302 { 303 LOG.debug( "Checksum encoding : {}", Strings.dumpBytes( buffer.array() ) ); 304 LOG.debug( "Checksum initial value : {}", this ); 305 } 306 307 return buffer; 308 } 309 310 311 /** 312 * Returns the {@link HostAddrType} of this {@link HostAddress}. 313 * 314 * @return The {@link HostAddrType}. 315 */ 316 public HostAddrType getAddrType() 317 { 318 return addrType; 319 } 320 321 322 /** 323 * Set the addr-type field 324 * 325 * @param addrType The address type 326 */ 327 public void setAddrType( HostAddrType addrType ) 328 { 329 this.addrType = addrType; 330 } 331 332 333 /** 334 * Set the addr-type field 335 * 336 * @param addrType The address type 337 */ 338 public void setAddrType( int addrType ) 339 { 340 this.addrType = HostAddrType.getTypeByOrdinal( addrType ); 341 } 342 343 344 /** 345 * {@inheritDoc} 346 */ 347 public String toString() 348 { 349 try 350 { 351 return InetAddress.getByAddress( address ).getHostAddress(); 352 } 353 catch ( UnknownHostException uhe ) 354 { 355 return "Unknow host : " + Strings.utf8ToString( address ); 356 } 357 } 358}