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

Quick Search    Search Deep

Source code: com/strangeberry/rendezvous/DNSIncoming.java


1   // Copyright (C) 2002  Strangeberry Inc.
2   // @(#)DNSIncoming.java, 1.23, 01/13/2003
3   //
4   // This library is free software; you can redistribute it and/or
5   // modify it under the terms of the GNU Lesser General Public
6   // License as published by the Free Software Foundation; either
7   // version 2.1 of the License, or (at your option) any later version.
8   // 
9   // This library is distributed in the hope that it will be useful,
10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  // Lesser General Public License for more details.
13  // 
14  // You should have received a copy of the GNU Lesser General Public
15  // License along with this library; if not, write to the Free Software
16  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  
18  package com.strangeberry.rendezvous;
19  
20  import java.io.*;
21  import java.net.*;
22  import java.util.*;
23  
24  /**
25   * Parse an incoming DNS message into its components.
26   *
27   * @author  Arthur van Hoff
28   * @version   1.18, 10/14/2002
29   */
30  final class DNSIncoming extends DNSConstants
31  {
32      final static Vector EMPTY = new Vector();
33      
34      DatagramPacket packet;
35      int off;
36      int len;
37      byte data[];
38  
39      int id;
40      int flags;
41      int numQuestions;
42      int numAnswers;
43      int numAuthorities;
44      int numAdditionals;
45  
46      Vector questions;
47      Vector answers;
48  
49      /**
50       * Parse a message from a datagram packet.
51       */
52      DNSIncoming(DatagramPacket packet) throws IOException
53      {
54    this.packet = packet;
55    this.data = packet.getData();
56    this.len = packet.getLength();
57    this.off = packet.getOffset();
58    this.questions = EMPTY;
59    this.answers = EMPTY;
60  
61    try {
62        id = readUnsignedShort();
63        flags = readUnsignedShort();
64        numQuestions = readUnsignedShort();
65        numAnswers = readUnsignedShort();
66        numAuthorities = readUnsignedShort();
67        numAdditionals = readUnsignedShort();
68  
69        // parse questions
70        if (numQuestions > 0) {
71      questions = new Vector(numQuestions);
72      for (int i = 0 ; i < numQuestions ; i++) {
73          DNSQuestion question = new DNSQuestion(readName(), readUnsignedShort(), readUnsignedShort());
74          questions.add(question);
75      }
76        }
77  
78        // parse answers
79        int n = numAnswers + numAuthorities + numAdditionals;
80        if (n > 0) {
81      answers = new Vector(n);
82      for (int i = 0 ; i < n ; i++) {
83          String domain = readName();
84          int type = readUnsignedShort();
85          int clazz = readUnsignedShort();
86          int ttl = readInt();
87          int len = readUnsignedShort();
88          int end = off + len;
89          DNSRecord rec = null;
90  
91          switch (type) {
92            case TYPE_A:
93        rec = new DNSRecord.Address(domain, type, clazz, ttl, readInt());
94        break;
95            case TYPE_CNAME:
96            case TYPE_PTR:
97        rec = new DNSRecord.Pointer(domain, type, clazz, ttl, readName());
98        break;
99            case TYPE_TXT:
100       rec = new DNSRecord.Text(domain, type, clazz, ttl, readBytes(off, len));
101       break;
102           case TYPE_SRV:
103       rec = new DNSRecord.Service(domain, type, clazz, ttl,
104             readUnsignedShort(), readUnsignedShort(), readUnsignedShort(), readName());
105       break;
106         }
107         if (rec != null) {
108       answers.add(rec);
109         }
110         off = end;
111     }
112       }
113   } catch (IOException e) {
114       print(true);
115       throw e;
116   } 
117     }
118 
119     /**
120      * Check if the message is a query.
121      */
122     boolean isQuery()
123     {
124   return (flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY;
125     }
126 
127     /**
128      * Check if the message is a response.
129      */
130     boolean isResponse()
131     {
132   return (flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE;
133     }
134 
135     int get(int off) throws IOException
136     {
137   if ((off < 0) || (off >= len)) {
138       throw new IOException("parser error: offset=" + off);
139   }
140   return data[off] & 0xFF;
141     }
142 
143     int readUnsignedShort() throws IOException
144     {
145   return (get(off++) << 8) + get(off++);
146     }
147 
148     int readInt() throws IOException
149     {
150   return (readUnsignedShort() << 16) + readUnsignedShort();
151     }
152 
153     byte[] readBytes(int off, int len) throws IOException
154     {
155   byte bytes[] = new byte[len];
156   System.arraycopy(data, off, bytes, 0, len);
157   return bytes;
158     }
159 
160     void readUTF(StringBuffer buf, int off, int len) throws IOException
161     {
162   for (int end = off + len ; off < end ; ) {
163       int ch = get(off++);
164       switch (ch >> 4) {
165         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
166     // 0xxxxxxx
167     break;
168         case 12: case 13:
169     // 110x xxxx   10xx xxxx
170     ch = ((ch & 0x1F) << 6) | (get(off++) & 0x3F);
171     break;
172         case 14:
173     // 1110 xxxx  10xx xxxx  10xx xxxx
174     ch = ((ch & 0x0f) << 12) | ((get(off++) & 0x3F) << 6) | (get(off++) & 0x3F);
175     break;
176         default:
177     // 10xx xxxx,  1111 xxxx
178     ch = ((ch & 0x3F) << 4) | (get(off++) & 0x0f);
179     break;
180       }
181       buf.append((char)ch);
182   }
183     }
184 
185     String readName() throws IOException
186     {
187   StringBuffer buf = new StringBuffer();
188   int off = this.off;
189   int next = -1;
190 
191   while (true) {
192       int len = get(off++);
193       if (len == 0) {
194     break;
195       }
196       switch (len & 0xC0) {
197         case 0x00:
198     //buf.append("[" + off + "]");
199     readUTF(buf, off, len);
200     off += len;
201     buf.append('.');
202     break;
203         case 0xC0:
204     //buf.append("<" + (off - 1) + ">");
205     if (next < 0) {
206         next = off + 1;
207     }
208     off = ((len & 0x3F) << 8) | get(off++);
209     break;
210         default:
211     throw new IOException("bad domain name: '" + buf + "' at " + off);
212       }
213   }
214   this.off = (next >= 0) ? next : off;
215   return buf.toString();
216     }
217 
218     /**
219      * Debugging.
220      */
221     void print(boolean dump)
222     {
223   System.out.println(toString());
224   for (Enumeration e = questions.elements() ; e.hasMoreElements() ;) {
225       System.out.println("    " + e.nextElement());
226   }
227   for (Enumeration e = answers.elements() ; e.hasMoreElements() ;) {
228       System.out.println("    " + e.nextElement());
229   }
230   if (dump) {
231       for (int off = 0, len = packet.getLength() ; off < len ; off += 32) {
232     int n = Math.min(32, len - off);
233     if (off < 10) {
234         System.out.print(' ');
235     }
236     if (off < 100) {
237         System.out.print(' ');
238     }
239     System.out.print(off);
240     System.out.print(':');
241     for (int i = 0 ; i < n ; i++) {
242         if ((i % 8) == 0) {
243       System.out.print(' ');
244         }
245         System.out.print(Integer.toHexString((data[off + i] & 0xF0) >> 4));
246         System.out.print(Integer.toHexString((data[off + i] & 0x0F) >> 0));
247     }
248     System.out.println();
249     System.out.print("    ");
250     for (int i = 0 ; i < n ; i++) {
251         if ((i % 8) == 0) {
252       System.out.print(' ');
253         }
254         System.out.print(' ');
255         int ch = data[off + i] & 0xFF;
256         System.out.print(((ch > ' ') && (ch < 127)) ? (char)ch : '.');
257     }
258     System.out.println();
259 
260     // limit message size
261     if (off+32 >= 256) {
262         System.out.println("....");
263         break;
264     }
265       }
266   }
267     }
268 
269     public String toString()
270     {
271   StringBuffer buf = new StringBuffer();
272   buf.append(isQuery() ? "dns[query," : "dns[response,");
273   buf.append(packet.getAddress().getHostAddress());
274   buf.append(':');
275   buf.append(packet.getPort());
276   buf.append(",len=" + packet.getLength());
277   buf.append(",id=0x" + Integer.toHexString(id));
278   if (flags != 0) {
279       buf.append(",flags=0x" + Integer.toHexString(flags));
280       if ((flags & FLAGS_QR_RESPONSE) != 0) {
281     buf.append(":r");
282       }
283       if ((flags & FLAGS_AA) != 0) {
284     buf.append(":aa");
285       }
286       if ((flags & FLAGS_TC) != 0) {
287     buf.append(":rc");
288       }
289   }
290   if (numQuestions > 0) {
291       buf.append(",questions=" + numQuestions);
292   }
293   if (numAnswers > 0) {
294       buf.append(",answers=" + numAnswers);
295   }
296   if (numAuthorities > 0) {
297       buf.append(",authorities=" + numAuthorities);
298   }
299   if (numAdditionals > 0) {
300       buf.append(",additionals=" + numAdditionals);
301   }
302   buf.append("]");
303   return buf.toString();
304     }
305 }