Source code: com/act365/net/dns/DNSWriter.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 DNSWriter writes DNS messages to a byte stream.
33 */
34
35 public class DNSWriter {
36
37 public final static int QUERY = 0 ,
38 RESPONSE = 1 ,
39 STANDARD_QUERY = 0 ,
40 INVERSE_QUERY = 1 ,
41 SERVER_STATUS_REQUEST = 2 ,
42 AUTHORITATIVE_ANSWER = 1 ,
43 TRUNCATED = 1 ,
44 RECURSION_DESIRED = 1 ,
45 ITERATIVE_QUERY = 0 ,
46 RECURSIVE_QUERY = 1 ,
47 RECURSION_AVAILABLE = 1 ,
48 NO_ERROR = 0 ,
49 NAME_ERROR = 3 ;
50
51 static int write( Query query , byte[] buffer , int offset ){
52
53 final int length = query.query_name.length + 4 ;
54
55 int i = -1 ;
56
57 while( ++ i < query.query_name.length ){
58 buffer[ i + offset ] = query.query_name[ i ];
59 }
60
61 SocketUtils.shortToBytes( query.query_type , buffer , offset + query.query_name.length );
62 SocketUtils.shortToBytes( query.query_class , buffer , offset + query.query_name.length + 2 );
63
64 return length ;
65 }
66
67 static int write( ResourceRecord record , byte[] buffer , int offset ){
68
69 final int length = record.domain_name.length + 10 + record.data.length ;
70
71 int i = -1 ;
72
73 while( ++ i < record.domain_name.length ){
74 buffer[ i + offset ] = record.domain_name[i];
75 }
76
77 SocketUtils.shortToBytes( record.type , buffer , offset + record.domain_name.length );
78 SocketUtils.shortToBytes( record.resource_class , buffer , offset + record.domain_name.length + 2 );
79 SocketUtils.intToBytes( record.time_to_live , buffer , offset + record.domain_name.length + 4 );
80 SocketUtils.shortToBytes( (short) record.data.length , buffer , offset + record.domain_name.length + 8 );
81
82 i = record.domain_name.length + 10 - 1 ;
83
84 while( ++ i < length ){
85 buffer[ i + offset ] = record.data[ i - record.domain_name.length - 10 ];
86 }
87
88 return length ;
89 }
90
91 static byte[] write( DNSMessage message ){
92
93 int length = 12 ;
94
95 int i = -1 ;
96
97 while( ++ i < message.questions.length ){
98 length += message.questions[ i ].length();
99 }
100
101 i = -1 ;
102
103 while( ++ i < message.answers.length ){
104 length += message.answers[ i ].length();
105 }
106
107 i = -1 ;
108
109 while( ++ i < message.authority_records.length ){
110 length += message.authority_records[ i ].length();
111 }
112
113 i = -1 ;
114
115 while( ++ i < message.additional_records.length ){
116 length += message.additional_records[ i ].length();
117 }
118
119 byte[] buffer = new byte[ length ];
120
121 SocketUtils.shortToBytes( message.identification , buffer , 0 );
122 SocketUtils.shortToBytes( message.flags , buffer , 2 );
123 SocketUtils.shortToBytes( (short) message.questions.length , buffer , 4 );
124 SocketUtils.shortToBytes( (short) message.answers.length , buffer , 6 );
125 SocketUtils.shortToBytes( (short) message.authority_records.length , buffer , 8 );
126 SocketUtils.shortToBytes( (short) message.additional_records.length , buffer , 10 );
127
128 length = 12 ;
129
130 i = -1 ;
131
132 while( ++ i < message.questions.length ){
133 length += write( message.questions[ i ] , buffer , length );
134 }
135
136 i = -1 ;
137
138 while( ++ i < message.answers.length ){
139 length += write( message.answers[ i ] , buffer , length );
140 }
141
142 i = -1 ;
143
144 while( ++ i < message.authority_records.length ){
145 length += write( message.authority_records[ i ] , buffer , length );
146 }
147
148 i = -1 ;
149
150 while( ++ i < message.additional_records.length ){
151 length += write( message.additional_records[ i ] , buffer , length );
152 }
153
154 return buffer ;
155 }
156
157 /**
158 Generates a standard DNS Query.
159 */
160
161 public static byte[] write( short identification ,
162 boolean recursion_desired ,
163 String domain ) throws Exception {
164
165 short flags = 0 ;
166
167 flags &= (byte)( QUERY << 15 );
168 flags &= (byte)( STANDARD_QUERY << 11 );
169
170 if( recursion_desired ){
171 flags &= (byte)( RECURSION_DESIRED << 8 );
172 }
173
174 Query[] questions = new Query[ 1 ];
175
176 questions[ 0 ] = new Query( domain );
177
178 DNSMessage message = new DNSMessage();
179
180 message.identification = identification ;
181 message.flags = flags ;
182 message.questions = questions ;
183 message.answers = new ResourceRecord[ 0 ];
184 message.authority_records = new ResourceRecord[ 0 ];
185 message.additional_records = new ResourceRecord[ 0 ];
186
187 return write( message );
188 }
189 }
190