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 }