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.shared.kerberos.components;
21  
22  
23  import java.net.Inet6Address;
24  import java.net.InetAddress;
25  import java.net.UnknownHostException;
26  import java.nio.BufferOverflowException;
27  import java.nio.ByteBuffer;
28  import java.util.Arrays;
29  
30  import org.apache.directory.api.asn1.Asn1Object;
31  import org.apache.directory.api.asn1.EncoderException;
32  import org.apache.directory.api.asn1.ber.tlv.BerValue;
33  import org.apache.directory.api.asn1.ber.tlv.TLV;
34  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
35  import org.apache.directory.api.util.Strings;
36  import org.apache.directory.server.i18n.I18n;
37  import org.apache.directory.shared.kerberos.codec.types.HostAddrType;
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  
41  
42  /**
43   * Provides host address information.
44   * 
45   * The ASN.1 grammar for this structure is :
46   * <pre>
47   * HostAddress     ::= SEQUENCE  {
48   *        addr-type       [0] Int32,
49   *        address         [1] OCTET STRING
50   * }
51   * </pre>
52   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
53   */
54  public class HostAddress implements Asn1Object
55  {
56      /** The logger */
57      private static final Logger LOG = LoggerFactory.getLogger( HostAddress.class );
58  
59      /** Speedup for logs */
60      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
61  
62      /** The host address type. One of :
63       *    Address Type                   Value
64       *
65       *    IPv4                             2
66       *    Directional                      3
67       *    ChaosNet                         5
68       *    XNS                              6
69       *    ISO                              7
70       *    DECNET Phase IV                 12
71       *    AppleTalk DDP                   16
72       *    NetBios                         20
73       *    IPv6                            24
74       */
75      private HostAddrType addrType;
76  
77      /** The address */
78      private byte[] address;
79  
80      // Storage for computed lengths
81      private int addrTypeLength;
82      private int addressLength;
83      private int hostAddressLength;
84      private int hostAddressSeqLength;
85  
86  
87      /**
88       * Creates an empty HostAdress instance
89       */
90      public HostAddress()
91      {
92      }
93  
94  
95      /**
96       * Creates a new instance of HostAddress.
97       *
98       * @param addrType The type of address
99       * @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/../../org/apache/directory/shared/kerberos/components/HostAddress.html#HostAddress">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      *  +--&gt; 0xA0 L2 addrType tag
217      *  |     |
218      *  |     +--&gt; 0x02 L2-1 addrType (int)
219      *  |
220      *  +--&gt; 0xA1 L3 address tag
221      *        |
222      *        +--&gt; 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 }