Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/act365/net/dns/DNSReader.java


1   /*
2     * JSocket Wrench
3     * 
4     * Copyright (C) act365.com October 2003
5     * 
6     * Web site: http://www.act365.com/wrench
7     * E-mail: developers@act365.com
8     * 
9     * The JSocket Wrench library adds support for low-level Internet protocols
10    * to the Java programming language.
11    * 
12    * This program is free software; you can redistribute it and/or modify it 
13    * under the terms of the GNU General Public License as published by the Free 
14    * Software Foundation; either version 2 of the License, or (at your option) 
15    * any later version.
16    *  
17    * This program is distributed in the hope that it will be useful, 
18    * but WITHOUT ANY WARRANTY; without even the implied warranty of 
19    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
20    * Public License for more details.
21    * 
22    * You should have received a copy of the GNU General Public License along with 
23    * this program; if not, write to the Free Software Foundation, Inc., 
24    * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25    */
26  
27  package com.act365.net.dns ;
28  
29  import com.act365.net.*;
30  
31  /**
32   * Reads DNS messages from bytestreams.
33   */
34  
35  public class DNSReader {
36  
37    int headerLength ;
38  
39    /**
40     Constructs a parser to decode DNS bytestreams. 
41     @param headerLength length of the transport header, e.g. 8 for UDP or 20 for TCP
42    */
43  
44    public DNSReader( int headerLength ){
45      this.headerLength = headerLength ;
46    }
47  
48    /**
49     Extracts a domain name string from a DNS message, even if compressed.
50    */
51  
52    int domainName( byte[] buffer , int offset , StringBuffer name ) throws Exception {
53  
54      final int start = offset ;
55  
56      byte next = buffer[ offset ++ ];
57  
58      int inext = next >= 0 ? next : 0xffffff00 ^ next ;
59  
60      while( inext != 0x00 ){
61        if( inext >>> 6 == 0x03 ){
62          StringBuffer compressed = new StringBuffer();
63          int compressed_offset = ( inext & 0x3F ) << 8 ;
64          next = buffer[ offset ++ ];
65          inext = next >= 0 ? next : 0xffffff00 ^ next ;
66          compressed_offset |= inext ;
67          domainName( buffer , compressed_offset + headerLength , compressed );
68          name.append( compressed.toString() );
69          break;
70        } else {
71          name.append( new String( buffer , offset , inext , "UTF8" ) );
72          offset += inext ;
73        }
74        next = buffer[ offset ++ ];
75        inext = next >= 0 ? next : 0xffffff00 ^ next ;
76        if( inext > 0 ){
77          name.append('.');
78        }
79      }
80  
81      return offset - start ;
82    }
83  
84    /**
85     Converts the data in a ResourceRecord object into an appropriate string.
86    */
87  
88    String dataString( byte[] buffer , int offset , int count , short type ) throws Exception {
89  
90      StringBuffer name = new StringBuffer();
91  
92      final int start = offset ;
93  
94      switch( type ){
95  
96        case DNSMessage.A :
97  
98          while( offset < start + count ){
99            int datum = buffer[ offset ];
100           name.append( datum >= 0 ? datum : 0xffffff00 ^ datum );
101           if( offset ++ < start + count - 1 ){
102             name.append('.');
103           }
104         }
105  
106         break;
107 
108       case DNSMessage.NS :
109       case DNSMessage.CNAME :
110       case DNSMessage.PTR :
111 
112         domainName( buffer , offset , name );
113 
114         break;
115 
116       default:
117 
118     }
119         
120     return name.toString();
121   }
122 
123   /**
124    Reads all of the information from a DNS response.
125   */
126 
127   public DNSMessage read( byte[] buffer ) throws Exception {
128 
129     DNSMessage message = new DNSMessage();
130 
131     message.identification = SocketUtils.shortFromBytes( buffer , headerLength );
132     message.flags = SocketUtils.shortFromBytes( buffer , headerLength + 2 );
133 
134     short n_questions  = SocketUtils.shortFromBytes( buffer , headerLength + 4 ) ,
135           n_answers    = SocketUtils.shortFromBytes( buffer , headerLength + 6 ) ,
136           n_authority  = SocketUtils.shortFromBytes( buffer , headerLength + 8 ) ,
137           n_additional = SocketUtils.shortFromBytes( buffer , headerLength + 10 );
138 
139     message.questions = new Query[ n_questions ];
140     message.answers = new ResourceRecord[ n_answers ];
141     message.authority_records = new ResourceRecord[ n_authority ];
142     message.additional_records = new ResourceRecord[ n_additional ];
143 
144     int i = -1 , j , offset = headerLength + 12 ;
145 
146     StringBuffer name ;
147 
148     String datastring ;
149 
150     byte[] namebuffer , databuffer ;
151 
152     short type_value , class_value , data_length ;
153 
154     int time_to_live ;
155 
156     while( ++ i < n_questions ){
157       name = new StringBuffer();
158       offset += domainName( buffer , offset , name );
159       namebuffer = name.toString().getBytes("UTF8");
160       type_value = SocketUtils.shortFromBytes( buffer , offset );
161       offset += 2 ;
162       class_value = SocketUtils.shortFromBytes( buffer , offset ); 
163       offset += 2 ;
164 
165       message.questions[ i ] = new Query( namebuffer , type_value , class_value , name.toString() );
166     }
167 
168     i = -1 ;
169 
170     while( ++ i < n_answers ){
171       name = new StringBuffer();
172       offset += domainName( buffer , offset , name );
173       namebuffer = name.toString().getBytes("UTF8");
174       type_value = SocketUtils.shortFromBytes( buffer , offset );
175       offset += 2 ;
176       class_value = SocketUtils.shortFromBytes( buffer , offset ); 
177       offset += 2 ;
178       time_to_live = SocketUtils.intFromBytes( buffer , offset );
179       offset += 4 ;
180       data_length = SocketUtils.shortFromBytes( buffer , offset );
181       offset += 2 ;
182       datastring = dataString( buffer , offset , data_length , type_value );
183       databuffer = new byte[ data_length ];
184       j = -1 ;
185       while( ++ j < data_length ){
186         databuffer[ j ] = buffer[ offset ++ ];
187       }
188 
189       message.answers[ i ] = new ResourceRecord( namebuffer , 
190                                                  type_value , 
191                                                  class_value ,
192                                                  time_to_live ,
193                                                  databuffer ,
194                                                  datastring );
195     }
196 
197     i = -1 ;
198 
199     while( ++ i < n_authority ){
200       name = new StringBuffer();
201       offset += domainName( buffer , offset , name );
202       namebuffer = name.toString().getBytes("UTF8");
203       type_value = SocketUtils.shortFromBytes( buffer , offset );
204       offset += 2 ;
205       class_value = SocketUtils.shortFromBytes( buffer , offset ); 
206       offset += 2 ;
207       time_to_live = SocketUtils.intFromBytes( buffer , offset );
208       offset += 4 ;
209       data_length = SocketUtils.shortFromBytes( buffer , offset );
210       offset += 2 ;
211       datastring = dataString( buffer , offset , data_length , type_value );
212       databuffer = new byte[ data_length ];
213       j = -1 ;
214       while( ++ j < data_length ){
215         databuffer[ j ] = buffer[ offset ++ ];
216       }
217 
218       message.authority_records[ i ] = new ResourceRecord( namebuffer , 
219                                                            type_value , 
220                                                            class_value ,
221                                                            time_to_live ,
222                                                            databuffer ,
223                                                            datastring );
224     }
225 
226     i = -1 ;
227 
228     while( ++ i < n_additional ){
229       name = new StringBuffer();
230       offset += domainName( buffer , offset , name );
231       namebuffer = name.toString().getBytes("UTF8");
232       type_value = SocketUtils.shortFromBytes( buffer , offset );
233       offset += 2 ;
234       class_value = SocketUtils.shortFromBytes( buffer , offset ); 
235       offset += 2 ;
236       time_to_live = SocketUtils.intFromBytes( buffer , offset );
237       offset += 4 ;
238       data_length = SocketUtils.shortFromBytes( buffer , offset );
239       offset += 2 ;
240       datastring = dataString( buffer , offset , data_length , type_value );
241       databuffer = new byte[ data_length ];
242       j = -1 ;
243       while( ++ j < data_length ){
244         databuffer[ j ] = buffer[ offset ++ ];
245       }
246 
247       message.additional_records[ i ] = new ResourceRecord( namebuffer , 
248                                                             type_value , 
249                                                             class_value ,
250                                                             time_to_live ,
251                                                             databuffer ,
252                                                             datastring );
253     }
254       
255     return message ;
256   }
257 }
258 
259