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 */ 020 package org.apache.directory.server.kerberos.shared.messages.value; 021 022 023 import java.net.InetAddress; 024 import java.net.UnknownHostException; 025 import java.nio.BufferOverflowException; 026 import java.nio.ByteBuffer; 027 028 import org.apache.directory.server.i18n.I18n; 029 import org.apache.directory.server.kerberos.shared.messages.value.types.HostAddrType; 030 import org.apache.directory.shared.asn1.AbstractAsn1Object; 031 import org.apache.directory.shared.asn1.ber.tlv.TLV; 032 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag; 033 import org.apache.directory.shared.asn1.ber.tlv.Value; 034 import org.apache.directory.shared.asn1.codec.EncoderException; 035 import org.apache.directory.shared.ldap.util.StringTools; 036 import org.slf4j.Logger; 037 import org.slf4j.LoggerFactory; 038 039 040 /** 041 * Provides host address information. 042 * 043 * The ASN.1 grammaor for this structure is : 044 * 045 * HostAddress ::= SEQUENCE { 046 * addr-type [0] Int32, 047 * address [1] OCTET STRING 048 * } 049 * 050 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 051 * @version $Rev: 902575 $, $Date: 2010-01-24 15:38:06 +0100 (Sun, 24 Jan 2010) $ 052 */ 053 public class HostAddress extends AbstractAsn1Object 054 { 055 /** The logger */ 056 private static final Logger LOG = LoggerFactory.getLogger( HostAddress.class ); 057 058 /** Speedup for logs */ 059 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 060 061 /** The host address type. One of : 062 * Address Type Value 063 * 064 * IPv4 2 065 * Directional 3 066 * ChaosNet 5 067 * XNS 6 068 * ISO 7 069 * DECNET Phase IV 12 070 * AppleTalk DDP 16 071 * NetBios 20 072 * IPv6 24 073 */ 074 private HostAddrType addrType; 075 076 /** The address */ 077 private byte[] address; 078 079 // Storage for computed lengths 080 private transient int addrTypeLength; 081 private transient int addressLength; 082 private transient int hostAddressLength; 083 private transient int hostAddressSeqLength; 084 085 086 /** 087 * Creates a new instance of HostAddress. 088 * 089 * @param addrType 090 * @param address 091 */ 092 public HostAddress( HostAddrType addrType, byte[] address ) 093 { 094 this.addrType = addrType; 095 this.address = address; 096 } 097 098 099 /** 100 * Creates a new instance of HostAddress. 101 * 102 * @param internetAddress 103 */ 104 public HostAddress( InetAddress internetAddress ) 105 { 106 addrType = HostAddrType.ADDRTYPE_INET; 107 byte[] newAddress = internetAddress.getAddress(); 108 address = new byte[newAddress.length]; 109 System.arraycopy( newAddress, 0, address, 0, newAddress.length ); 110 } 111 112 113 /** 114 * Returns whether one {@link HostAddress} is equal to another. 115 * 116 * @param that The {@link HostAddress} to compare with 117 * @return true if the {@link HostAddress}'s are equal. 118 */ 119 public boolean equals( Object that ) 120 { 121 if ( this == that ) 122 { 123 return true; 124 } 125 126 if ( !(that instanceof HostAddress ) ) 127 { 128 return false; 129 } 130 131 HostAddress hostAddress = (HostAddress)that; 132 133 if ( addrType != hostAddress.addrType || ( address != null && hostAddress.address == null ) 134 || ( address == null && hostAddress.address != null ) ) 135 { 136 return false; 137 } 138 139 if ( address != null && hostAddress.address != null ) 140 { 141 if ( address.length != hostAddress.address.length ) 142 { 143 return false; 144 } 145 146 for ( int ii = 0; ii < address.length; ii++ ) 147 { 148 if ( address[ii] != hostAddress.address[ii] ) 149 { 150 return false; 151 } 152 } 153 } 154 155 return true; 156 } 157 158 159 /** 160 * Get the bytes for this address. 161 * 162 * @return The bytes of this address. 163 */ 164 public byte[] getAddress() 165 { 166 return address; 167 } 168 169 170 /** 171 * Set the address 172 * 173 * @param addresse The address 174 */ 175 public void setAddress( byte[] addresse ) 176 { 177 this.address = addresse; 178 } 179 180 181 /** 182 * Compute the host address length 183 * 184 * HostAddress : 185 * 186 * 0x30 L1 hostAddress sequence 187 * | 188 * +--> 0xA0 L2 addrType tag 189 * | | 190 * | +--> 0x02 L2-1 addrType (int) 191 * | 192 * +--> 0xA1 L3 address tag 193 * | 194 * +--> 0x04 L3-1 address (OCTET STRING) 195 * 196 * where L1 = L2 + length(0xA0) + length(L2) + 197 * L3 + length(0xA1) + length(L3) 198 * and 199 * L2 = L2-1 + length(0x02) + length( L2-1) 200 * L3 = L3-1 + length(0x04) + length( L3-1) 201 */ 202 public int computeLength() 203 { 204 // Compute the keyType. The Length will always be contained in 1 byte 205 addrTypeLength = 1 + 1 + Value.getNbBytes( addrType.getOrdinal() ); 206 hostAddressLength = 1 + TLV.getNbBytes( addrTypeLength ) + addrTypeLength; 207 208 // Compute the keyValue 209 if ( address == null ) 210 { 211 addressLength = 1 + 1; 212 } 213 else 214 { 215 addressLength = 1 + TLV.getNbBytes( address.length ) + address.length; 216 } 217 218 hostAddressLength += 1 + TLV.getNbBytes( addressLength ) + addressLength; 219 220 // Compute the whole sequence length 221 hostAddressSeqLength = 1 + Value.getNbBytes( hostAddressLength ) + hostAddressLength; 222 223 return hostAddressSeqLength; 224 } 225 226 227 /** 228 * Encode the HostAddress message to a PDU. 229 * 230 * HostAddress : 231 * 232 * 0x30 LL 233 * 0xA0 LL 234 * 0x02 0x01 addr-type 235 * 0xA1 LL 236 * 0x04 LL address 237 * 238 * @param buffer The buffer where to put the PDU. It should have been allocated 239 * before, with the right size. 240 * @return The constructed PDU. 241 */ 242 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 243 { 244 if ( buffer == null ) 245 { 246 throw new EncoderException( I18n.err( I18n.ERR_148 ) ); 247 } 248 249 try 250 { 251 // The HostAddress SEQ Tag 252 buffer.put( UniversalTag.SEQUENCE_TAG ); 253 buffer.put( TLV.getBytes( hostAddressLength ) ); 254 255 // The addr-type, first the tag, then the value 256 buffer.put( ( byte ) 0xA0 ); 257 buffer.put( TLV.getBytes( addrTypeLength ) ); 258 Value.encode( buffer, addrType.getOrdinal() ); 259 260 // The address, first the tag, then the value 261 buffer.put( ( byte ) 0xA1 ); 262 buffer.put( TLV.getBytes( addressLength ) ); 263 Value.encode( buffer, address ); 264 } 265 catch ( BufferOverflowException boe ) 266 { 267 LOG.error( I18n.err( I18n.ERR_143, 1 + TLV.getNbBytes( hostAddressLength ) 268 + hostAddressLength, buffer.capacity() ) ); 269 throw new EncoderException( I18n.err( I18n.ERR_138 ) ); 270 } 271 272 if ( IS_DEBUG ) 273 { 274 LOG.debug( "Checksum encoding : {}", StringTools.dumpBytes( buffer.array() ) ); 275 LOG.debug( "Checksum initial value : {}", toString() ); 276 } 277 278 return buffer; 279 } 280 281 282 /** 283 * Returns the {@link HostAddrType} of this {@link HostAddress}. 284 * 285 * @return The {@link HostAddrType}. 286 */ 287 public HostAddrType getAddrType() 288 { 289 return addrType; 290 } 291 292 293 /** 294 * Set the addr-type field 295 * 296 * @param addrType The address type 297 */ 298 public void setAddrType( HostAddrType addrType ) 299 { 300 this.addrType = addrType; 301 } 302 303 304 /** 305 * Set the addr-type field 306 * 307 * @param addrType The address type 308 */ 309 public void setAddrType( int addrType ) 310 { 311 this.addrType = HostAddrType.getTypeByOrdinal( addrType ); 312 } 313 314 315 /** 316 * @see Object#toString() 317 */ 318 public String toString() 319 { 320 String result = ""; 321 322 try 323 { 324 result = InetAddress.getByAddress( address ).getHostAddress(); 325 } 326 catch ( UnknownHostException uhe ) 327 { 328 // Allow default to return. 329 } 330 331 return result; 332 } 333 }