1 /*
2 Copyright (c) 2011 Verisign, Inc. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the authors may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 */
28
29 #include "functions.h"
30
31 #include <iostream>
32 #include <cstdlib>
33 #include <stdio.h>
34 #include <string.h>
35 #include <vantages/dns_defs.h>
36 #include <vantages/dns_resolver.h>
37 #include <vantages/dns_packet.h>
38 #include <vantages/dns_opt.h>
39 #include <vantages/dns_a.h>
40 #include <vantages/dns_err.h>
41 #include <vantages/dns_name.h>
42
43
44 #define NUM_OPCODE 16
45 #define NUM_AA 2
46 #define NUM_TC 2
47 #define NUM_RD 2
48 #define NUM_RA 2
49 #define NUM_Z 2
50 #define NUM_AD 2
51 #define NUM_CD 2
52 #define NUM_RCODE 2
53
54 #define NUM_QNAME 2
55 #define NUM_QCLASS 9
56 #define NUM_QTYPE 24
57
58 #define DNS_CLASS_RESERVED 0
59 #define DNS_CLASS_IN 1
60 #define DNS_CLASS_UNASSIGNED 2
61 #define DNS_CLASS_CH 3
62 #define DNS_CLASS_HS 4
63 #define DNS_CLASS_NONE 254
64 #define DNS_CLASS_ANY 255
65 #define DNS_CLASS_RESERVED_PRIVATE 65280
66 #define DNS_CLASS_RESERVED1 65535
67
68 #define DNS_RR_UNASSIGNED 32770
69 #define DNS_RR_PRIVATE 65280
70 #define DNS_RR_RESERVED 65535
71
72 // Important to always update this if anything about
73 // the way the responses are output is modified
74 #define RESPONSE_COLLECTOR_VERSION "0.1"
75
main(int argc,char ** argv)76 int main(int argc, char** argv) {
77 int retries = 1;
78 int timeout = 5;
79
80 if (argc == 1) {
81 fprintf(stdout, "Usage: \n\nresponse_collector \"$DNS_SERVER_NAME\" $SERVER_IP_ADDRESS [timeout=5] [retries=1]\n\nor\n\n");
82 fprintf(stdout, "response_collector \"$VENDOR | $PRODUCT | $VERSION\" $SERVER_IP_ADDRESS [timeout=5] [retries=1]\n\nor\n\n");
83 fprintf(stdout, "response_collector --show-queries\n\n\n");
84
85 exit(1);
86 }
87
88 bool showQueries = (strcmp(argv[1], "--show-queries") == false);
89 if (argc == 2 && !showQueries) {
90 fprintf(stderr, "Error: Invalid command line argument\n");
91
92 exit(1);
93 }
94
95 unsigned int ip_address;
96 if (argc > 2) {
97 ip_address = str_to_ip(argv[2]);
98
99 //0.0.0.0 address will always fail
100 if (ip_address == 0) {
101 exit(1);
102 }
103 if (argc >= 4) {
104 timeout = atoi(argv[3]);
105 if (argc >= 5) {
106 retries = atoi(argv[4]);
107 }
108 }
109 }
110
111
112 DnsResolver oRes;
113 oRes.setRetries(retries);
114 oRes.setTimeout(timeout);
115
116 if (!showQueries) {
117 oRes.setNameserver(ip_address);
118 }
119 std::string sA = ".";
120 DnsName oName(sA);
121
122 DnsRR *pQuestionRR = DnsRR::question(oName, DNS_RR_A);
123 pQuestionRR->set_class(DNS_CLASS_IN);
124
125 DnsPacket oQuest(true, -1);
126 oQuest.addQuestion(*pQuestionRR);
127
128 int count = 0;
129 unsigned opcode;
130 unsigned aa;
131 unsigned tc;
132 unsigned rd;
133 unsigned ra;
134 unsigned z;
135 unsigned ad;
136 unsigned cd;
137 unsigned rcode_index;
138 rcode_t rcodes[NUM_RCODE] = {DNS_NOERROR, DNS_NOTIMP};
139
140
141 if (showQueries) {
142 fprintf(stdout, "ver %s\n", RESPONSE_COLLECTOR_VERSION);
143 } else {
144 fprintf(stdout, "%s\n", argv[1]);
145 }
146
147 for (opcode = 0; opcode < NUM_OPCODE; opcode++) {
148 for (aa = 0; aa < NUM_AA; aa++) {
149 for (tc = 0; tc < NUM_TC; tc++) {
150 for (rd = 0; rd < NUM_RD; rd++) {
151 for (ra = 0; ra < NUM_RA; ra++) {
152 for (z = 0; z < NUM_Z; z++) {
153 for (ad = 0; ad < NUM_AD; ad++) {
154 for (cd = 0; cd < NUM_CD; cd++) {
155 for (rcode_index = 0; rcode_index < NUM_RCODE; rcode_index++) {
156 DnsPacket oResp(true);
157
158 oQuest.getHeader().setOpcode(opcode);
159 oQuest.getHeader().set_aa(aa);
160 oQuest.getHeader().set_tc(tc);
161 oQuest.getHeader().set_rd(rd);
162 oQuest.getHeader().set_ra(ra);
163 oQuest.getHeader().set_z(z);
164 oQuest.getHeader().set_ad(ad);
165 oQuest.getHeader().set_cd(cd);
166 oQuest.getHeader().set_rcode(rcodes[rcode_index]);
167
168 if (showQueries) {
169 printHeader(oQuest.getHeader());
170 printNameClassType(oQuest);
171 continue;
172 }
173
174 oRes.send(oQuest, oResp);
175 if (!oResp.getHeader().getResponse()) {
176 printHeader(oQuest.getHeader());
177 } else {
178 printHeader(oResp.getHeader());
179 }
180 count++;
181 }
182 }
183 }
184 }
185 }
186 }
187 }
188 }
189 }
190
191
192 std::string qnames[NUM_QNAME] = {".", "jjjjjjjjjjjj"};
193 unsigned qclasses[NUM_QCLASS] = {DNS_CLASS_RESERVED, DNS_CLASS_IN,
194 DNS_CLASS_UNASSIGNED, DNS_CLASS_CH, DNS_CLASS_HS, DNS_CLASS_NONE,
195 DNS_CLASS_ANY, DNS_CLASS_RESERVED_PRIVATE, DNS_CLASS_RESERVED1};
196 unsigned qtypes[NUM_QTYPE] = {DNS_RR_A, DNS_RR_NS, DNS_RR_MD, DNS_RR_CNAME,
197 DNS_RR_SOA, DNS_RR_HINFO, DNS_RR_AAAA, DNS_RR_NXT, DNS_RR_A6, DNS_RR_DNAME,
198 DNS_RR_SINK, DNS_RR_SSHFP, DNS_RR_RRSIG, DNS_RR_NSEC, DNS_RR_DNSKEY,
199 DNS_RR_NSEC3, DNS_RR_NSEC3PARAM, DNS_RR_TKEY, DNS_RR_TSIG, DNS_RR_IXFR,
200 DNS_RR_AXFR, DNS_RR_UNASSIGNED, DNS_RR_PRIVATE, DNS_RR_RESERVED};
201
202
203 for (int i = 0; i < NUM_QNAME; i++) {
204 for (int j = 0; j < NUM_QCLASS; j++) {
205 for (int k = 0; k < NUM_QTYPE; k++) {
206
207 DnsPacket oResp(true);
208 DnsPacket oQuest(true, -1);
209
210 DnsResolver oRes;
211 oRes.setRetries(retries);
212 oRes.setTimeout(timeout);
213 if (!showQueries) {
214 oRes.setNameserver(str_to_ip(argv[2]));
215 }
216 std::string sA = qnames[i];
217 DnsName oName(sA);
218
219 DnsRR *pQuestionRR = DnsRR::question(oName, qtypes[k]);
220 pQuestionRR->set_class(qclasses[j]);
221 oQuest.addQuestion(*pQuestionRR);
222
223 if (showQueries) {
224 printHeader(oQuest.getHeader());
225 printNameClassType(oQuest);
226 continue;
227 }
228
229
230 oRes.send(oQuest, oResp);
231 if (!oResp.getHeader().getResponse()) {
232 printHeader(oQuest.getHeader());
233 } else {
234 printHeader(oResp.getHeader());
235 }
236 count++;
237 }
238 }
239 }
240
241
242 return 0;
243 }