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.kerberos.shared.messages.value.types.HostAddrType;
029 import org.apache.directory.shared.asn1.AbstractAsn1Object;
030 import org.apache.directory.shared.asn1.ber.tlv.TLV;
031 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
032 import org.apache.directory.shared.asn1.ber.tlv.Value;
033 import org.apache.directory.shared.asn1.codec.EncoderException;
034 import org.apache.directory.shared.ldap.util.StringTools;
035 import org.slf4j.Logger;
036 import org.slf4j.LoggerFactory;
037
038
039 /**
040 * Provides host address information.
041 *
042 * The ASN.1 grammaor for this structure is :
043 *
044 * HostAddress ::= SEQUENCE {
045 * addr-type [0] Int32,
046 * address [1] OCTET STRING
047 * }
048 *
049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
050 * @version $Rev: 642496 $, $Date: 2008-03-29 05:09:22 +0200 (Sat, 29 Mar 2008) $
051 */
052 public class HostAddress extends AbstractAsn1Object
053 {
054 /** The logger */
055 private static final Logger LOG = LoggerFactory.getLogger( HostAddress.class );
056
057 /** Speedup for logs */
058 private static final boolean IS_DEBUG = LOG.isDebugEnabled();
059
060 /** The host address type. One of :
061 * Address Type Value
062 *
063 * IPv4 2
064 * Directional 3
065 * ChaosNet 5
066 * XNS 6
067 * ISO 7
068 * DECNET Phase IV 12
069 * AppleTalk DDP 16
070 * NetBios 20
071 * IPv6 24
072 */
073 private HostAddrType addrType;
074
075 /** The address */
076 private byte[] address;
077
078 // Storage for computed lengths
079 private transient int addrTypeLength;
080 private transient int addressLength;
081 private transient int hostAddressLength;
082 private transient int hostAddressSeqLength;
083
084
085 /**
086 * Creates a new instance of HostAddress.
087 *
088 * @param addrType
089 * @param address
090 */
091 public HostAddress( HostAddrType addrType, byte[] address )
092 {
093 this.addrType = addrType;
094 this.address = address;
095 }
096
097
098 /**
099 * Creates a new instance of HostAddress.
100 *
101 * @param internetAddress
102 */
103 public HostAddress( InetAddress internetAddress )
104 {
105 addrType = HostAddrType.ADDRTYPE_INET;
106 byte[] newAddress = internetAddress.getAddress();
107 address = new byte[newAddress.length];
108 System.arraycopy( newAddress, 0, address, 0, newAddress.length );
109 }
110
111
112 /**
113 * Returns whether one {@link HostAddress} is equal to another.
114 *
115 * @param that The {@link HostAddress} to compare with
116 * @return true if the {@link HostAddress}'s are equal.
117 */
118 public boolean equals( Object that )
119 {
120 if ( this == that )
121 {
122 return true;
123 }
124
125 if ( !(that instanceof HostAddress ) )
126 {
127 return false;
128 }
129
130 HostAddress hostAddress = (HostAddress)that;
131
132 if ( addrType != hostAddress.addrType || ( address != null && hostAddress.address == null )
133 || ( address == null && hostAddress.address != null ) )
134 {
135 return false;
136 }
137
138 if ( address != null && hostAddress.address != null )
139 {
140 if ( address.length != hostAddress.address.length )
141 {
142 return false;
143 }
144
145 for ( int ii = 0; ii < address.length; ii++ )
146 {
147 if ( address[ii] != hostAddress.address[ii] )
148 {
149 return false;
150 }
151 }
152 }
153
154 return true;
155 }
156
157
158 /**
159 * Get the bytes for this address.
160 *
161 * @return The bytes of this address.
162 */
163 public byte[] getAddress()
164 {
165 return address;
166 }
167
168
169 /**
170 * Set the address
171 *
172 * @param addresse The address
173 */
174 public void setAddress( byte[] addresse )
175 {
176 this.address = addresse;
177 }
178
179
180 /**
181 * Compute the host address length
182 *
183 * HostAddress :
184 *
185 * 0x30 L1 hostAddress sequence
186 * |
187 * +--> 0xA0 L2 addrType tag
188 * | |
189 * | +--> 0x02 L2-1 addrType (int)
190 * |
191 * +--> 0xA1 L3 address tag
192 * |
193 * +--> 0x04 L3-1 address (OCTET STRING)
194 *
195 * where L1 = L2 + length(0xA0) + length(L2) +
196 * L3 + length(0xA1) + length(L3)
197 * and
198 * L2 = L2-1 + length(0x02) + length( L2-1)
199 * L3 = L3-1 + length(0x04) + length( L3-1)
200 */
201 public int computeLength()
202 {
203 // Compute the keyType. The Length will always be contained in 1 byte
204 addrTypeLength = 1 + 1 + Value.getNbBytes( addrType.getOrdinal() );
205 hostAddressLength = 1 + TLV.getNbBytes( addrTypeLength ) + addrTypeLength;
206
207 // Compute the keyValue
208 if ( address == null )
209 {
210 addressLength = 1 + 1;
211 }
212 else
213 {
214 addressLength = 1 + TLV.getNbBytes( address.length ) + address.length;
215 }
216
217 hostAddressLength += 1 + TLV.getNbBytes( addressLength ) + addressLength;
218
219 // Compute the whole sequence length
220 hostAddressSeqLength = 1 + Value.getNbBytes( hostAddressLength ) + hostAddressLength;
221
222 return hostAddressSeqLength;
223 }
224
225
226 /**
227 * Encode the HostAddress message to a PDU.
228 *
229 * HostAddress :
230 *
231 * 0x30 LL
232 * 0xA0 LL
233 * 0x02 0x01 addr-type
234 * 0xA1 LL
235 * 0x04 LL address
236 *
237 * @param buffer The buffer where to put the PDU. It should have been allocated
238 * before, with the right size.
239 * @return The constructed PDU.
240 */
241 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
242 {
243 if ( buffer == null )
244 {
245 throw new EncoderException( "Cannot put a PDU in a null buffer !" );
246 }
247
248 try
249 {
250 // The HostAddress SEQ Tag
251 buffer.put( UniversalTag.SEQUENCE_TAG );
252 buffer.put( TLV.getBytes( hostAddressLength ) );
253
254 // The addr-type, first the tag, then the value
255 buffer.put( ( byte ) 0xA0 );
256 buffer.put( TLV.getBytes( addrTypeLength ) );
257 Value.encode( buffer, addrType.getOrdinal() );
258
259 // The address, first the tag, then the value
260 buffer.put( ( byte ) 0xA1 );
261 buffer.put( TLV.getBytes( addressLength ) );
262 Value.encode( buffer, address );
263 }
264 catch ( BufferOverflowException boe )
265 {
266 LOG.error(
267 "Cannot encode the HostAddress object, the PDU size is {} when only {} bytes has been allocated", 1
268 + TLV.getNbBytes( hostAddressLength ) + hostAddressLength, buffer.capacity() );
269 throw new EncoderException( "The PDU buffer size is too small !" );
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 }