View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.kerberos.shared.messages.value;
21  
22  
23  import java.net.InetAddress;
24  import java.net.UnknownHostException;
25  import java.nio.BufferOverflowException;
26  import java.nio.ByteBuffer;
27  
28  import org.apache.directory.server.kerberos.shared.messages.value.types.HostAddrType;
29  import org.apache.directory.shared.asn1.AbstractAsn1Object;
30  import org.apache.directory.shared.asn1.ber.tlv.TLV;
31  import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
32  import org.apache.directory.shared.asn1.ber.tlv.Value;
33  import org.apache.directory.shared.asn1.codec.EncoderException;
34  import org.apache.directory.shared.ldap.util.StringTools;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  
39  /**
40   * Provides host address information.
41   * 
42   * The ASN.1 grammaor for this structure is :
43   * 
44   * HostAddress     ::= SEQUENCE  {
45   *        addr-type       [0] Int32,
46   *        address         [1] OCTET STRING
47   * }
48   * 
49   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
50   * @version $Rev: 642496 $, $Date: 2008-03-29 04:09:22 +0100 (Sa, 29 Mär 2008) $
51   */
52  public class HostAddress extends AbstractAsn1Object
53  {
54      /** The logger */
55      private static final Logger LOG = LoggerFactory.getLogger( HostAddress.class );
56  
57      /** Speedup for logs */
58      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
59  
60      /** The host address type. One of :
61       *    Address Type                   Value
62       *
63       *    IPv4                             2
64       *    Directional                      3
65       *    ChaosNet                         5
66       *    XNS                              6
67       *    ISO                              7
68       *    DECNET Phase IV                 12
69       *    AppleTalk DDP                   16
70       *    NetBios                         20
71       *    IPv6                            24
72       */
73      private HostAddrType addrType;
74  
75      /** The address */
76      private byte[] address;
77  
78      // Storage for computed lengths
79      private transient int addrTypeLength;
80      private transient int addressLength;
81      private transient int hostAddressLength;
82      private transient int hostAddressSeqLength;
83  
84  
85      /**
86       * Creates a new instance of HostAddress.
87       *
88       * @param addrType
89       * @param address
90       */
91      public HostAddress( HostAddrType addrType, byte[] address )
92      {
93          this.addrType = addrType;
94          this.address = address;
95      }
96  
97  
98      /**
99       * 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 }