summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/asr/bin/res_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libc/asr/bin/res_query.c')
-rw-r--r--src/regress/lib/libc/asr/bin/res_query.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/regress/lib/libc/asr/bin/res_query.c b/src/regress/lib/libc/asr/bin/res_query.c
new file mode 100644
index 0000000000..fd96f1de22
--- /dev/null
+++ b/src/regress/lib/libc/asr/bin/res_query.c
@@ -0,0 +1,354 @@
1/* $OpenBSD: res_query.c,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ */
2/*
3 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/types.h>
19#include <sys/socket.h>
20
21#include <netinet/in.h>
22#include <arpa/nameser.h>
23#include <arpa/inet.h>
24
25#include <err.h>
26#include <errno.h>
27#include <getopt.h>
28#include <inttypes.h>
29#include <resolv.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "common.h"
35
36/* in asr.c but we don't want them exposed right now */
37static void dump_packet(const void *, size_t);
38
39static char *print_query(struct query *, char *, size_t);
40static char *print_rr(struct rr *, char *, size_t);
41static char *print_host(const struct sockaddr *, char *, size_t);
42static char* print_dname(const char *, char *, size_t);
43
44
45static int
46msec(struct timeval start, struct timeval end)
47{
48 return (int)((end.tv_sec - start.tv_sec) * 1000
49 + (end.tv_usec - start.tv_usec) / 1000);
50}
51
52static void
53usage(void)
54{
55 extern const char * __progname;
56
57 fprintf(stderr, "usage: %s [-deq] [-t type] [host...]\n",
58 __progname);
59 exit(1);
60}
61
62int
63main(int argc, char *argv[])
64{
65 struct timeval start, end;
66 time_t when;
67 int ch, i, qflag, dflag, r;
68 uint16_t type = T_A;
69 char buf[1024], *host;
70
71 dflag = 0;
72 qflag = 0;
73
74 while((ch = getopt(argc, argv, "deqt:")) != -1) {
75 switch(ch) {
76 case 'd':
77 dflag = 1;
78 break;
79 case 'e':
80 long_err += 1;
81 break;
82 case 'q':
83 qflag = 1;
84 break;
85 case 't':
86 if ((type = strtotype(optarg)) == 0)
87 usage();
88 break;
89 default:
90 usage();
91 /* NOTREACHED */
92 }
93 }
94 argc -= optind;
95 argv += optind;
96
97 for (i = 0; i < argc; i++) {
98
99 if (i)
100 printf("\n");
101
102 printf("===> \"%s\"\n", argv[i]);
103 host = gethostarg(argv[i]);
104
105 errno = 0;
106 h_errno = 0;
107 gai_errno = 0;
108 rrset_errno = 0;
109
110 if (gettimeofday(&start, NULL) != 0)
111 err(1, "gettimeofday");
112
113 if (qflag)
114 r = res_query(host, C_IN, type, buf, sizeof(buf));
115 else
116 r = res_search(host, C_IN, type, buf, sizeof(buf));
117
118 if (gettimeofday(&end, NULL) != 0)
119 err(1, "gettimeofday");
120
121 if (r != -1) {
122 dump_packet(buf, r);
123 printf("\n");
124 if (dflag) {
125 printf(";; Query time: %d msec\n",
126 msec(start, end));
127 when = time(NULL);
128 printf(";; WHEN: %s", ctime(&when));
129 }
130 printf(";; MSG SIZE rcvd: %i\n", r);
131 }
132 print_errors();
133 }
134
135 return (0);
136}
137
138#define OPCODE_SHIFT 11
139#define Z_SHIFT 4
140
141static char*
142print_header(struct header *h, char *buf, size_t max)
143{
144 snprintf(buf, max,
145 "id:0x.... %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i",
146 (h->flags & QR_MASK) ? "QR":" ",
147 (int)(OPCODE(h->flags) >> OPCODE_SHIFT),
148 (h->flags & AA_MASK) ? "AA":" ",
149 (h->flags & TC_MASK) ? "TC":" ",
150 (h->flags & RD_MASK) ? "RD":" ",
151 (h->flags & RA_MASK) ? "RA":" ",
152 ((h->flags & Z_MASK) >> Z_SHIFT),
153 rcodetostr(RCODE(h->flags)),
154 h->qdcount, h->ancount, h->nscount, h->arcount);
155
156 return buf;
157}
158
159static void
160dump_packet(const void *data, size_t len)
161{
162 char buf[1024];
163 struct packed p;
164 struct header h;
165 struct query q;
166 struct rr rr;
167 int i, an, ns, ar, n;
168
169 packed_init(&p, (char *)data, len);
170
171 if (unpack_header(&p, &h) == -1) {
172 printf(";; BAD PACKET: %s\n", p.err);
173 return;
174 }
175
176 printf(";; HEADER %s\n", print_header(&h, buf, sizeof buf));
177
178 if (h.qdcount)
179 printf(";; QUERY SECTION:\n");
180 for (i = 0; i < h.qdcount; i++) {
181 if (unpack_query(&p, &q) == -1)
182 goto error;
183 printf("%s\n", print_query(&q, buf, sizeof buf));
184 }
185
186 an = 0;
187 ns = an + h.ancount;
188 ar = ns + h.nscount;
189 n = ar + h.arcount;
190
191 for (i = 0; i < n; i++) {
192 if (i == an)
193 printf("\n;; ANSWER SECTION:\n");
194 if (i == ns)
195 printf("\n;; AUTHORITY SECTION:\n");
196 if (i == ar)
197 printf("\n;; ADDITIONAL SECTION:\n");
198
199 if (unpack_rr(&p, &rr) == -1)
200 goto error;
201 printf("%s\n", print_rr(&rr, buf, sizeof buf));
202 }
203
204 if (p.offset != len)
205 printf(";; REMAINING GARBAGE %zu\n", len - p.offset);
206
207 error:
208 if (p.err)
209 printf(";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len,
210 p.err);
211}
212
213static const char *
214inet6_ntoa(struct in6_addr a)
215{
216 static char buf[256];
217 struct sockaddr_in6 si;
218
219 si.sin6_len = sizeof(si);
220 si.sin6_family = PF_INET6;
221 si.sin6_addr = a;
222
223 return print_host((struct sockaddr*)&si, buf, sizeof buf);
224}
225
226static char*
227print_rr(struct rr *rr, char *buf, size_t max)
228{
229 char *res;
230 char tmp[256];
231 char tmp2[256];
232 int r;
233
234 res = buf;
235
236 r = snprintf(buf, max, "%s %u %s %s ",
237 print_dname(rr->rr_dname, tmp, sizeof tmp),
238 rr->rr_ttl,
239 classtostr(rr->rr_class),
240 typetostr(rr->rr_type));
241 if (r == -1) {
242 buf[0] = '\0';
243 return buf;
244 }
245
246 if ((size_t)r >= max)
247 return buf;
248
249 max -= r;
250 buf += r;
251
252 switch(rr->rr_type) {
253 case T_CNAME:
254 print_dname(rr->rr.cname.cname, buf, max);
255 break;
256 case T_MX:
257 snprintf(buf, max, "%"PRIu32" %s",
258 rr->rr.mx.preference,
259 print_dname(rr->rr.mx.exchange, tmp, sizeof tmp));
260 break;
261 case T_NS:
262 print_dname(rr->rr.ns.nsname, buf, max);
263 break;
264 case T_PTR:
265 print_dname(rr->rr.ptr.ptrname, buf, max);
266 break;
267 case T_SOA:
268 snprintf(buf, max,
269 "%s %s %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32,
270 print_dname(rr->rr.soa.rname, tmp, sizeof tmp),
271 print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2),
272 rr->rr.soa.serial,
273 rr->rr.soa.refresh,
274 rr->rr.soa.retry,
275 rr->rr.soa.expire,
276 rr->rr.soa.minimum);
277 break;
278 case T_A:
279 if (rr->rr_class != C_IN)
280 goto other;
281 snprintf(buf, max, "%s", inet_ntoa(rr->rr.in_a.addr));
282 break;
283 case T_AAAA:
284 if (rr->rr_class != C_IN)
285 goto other;
286 snprintf(buf, max, "%s", inet6_ntoa(rr->rr.in_aaaa.addr6));
287 break;
288 default:
289 other:
290 snprintf(buf, max, "(rdlen=%"PRIu16 ")", rr->rr.other.rdlen);
291 break;
292 }
293
294 return (res);
295}
296
297static char*
298print_query(struct query *q, char *buf, size_t max)
299{
300 char b[256];
301
302 snprintf(buf, max, "%s %s %s",
303 print_dname(q->q_dname, b, sizeof b),
304 classtostr(q->q_class), typetostr(q->q_type));
305
306 return (buf);
307}
308
309
310static char *
311print_host(const struct sockaddr *sa, char *buf, size_t len)
312{
313 switch (sa->sa_family) {
314 case AF_INET:
315 inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, buf, len);
316 break;
317 case AF_INET6:
318 inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, buf, len);
319 break;
320 default:
321 buf[0] = '\0';
322 }
323 return (buf);
324}
325
326static char*
327print_dname(const char *_dname, char *buf, size_t max)
328{
329 const unsigned char *dname = _dname;
330 char *res;
331 size_t left, n, count;
332
333 if (_dname[0] == 0) {
334 strlcpy(buf, ".", max);
335 return buf;
336 }
337
338 res = buf;
339 left = max - 1;
340 for (n = 0; dname[0] && left; n += dname[0]) {
341 count = (dname[0] < (left - 1)) ? dname[0] : (left - 1);
342 memmove(buf, dname + 1, count);
343 dname += dname[0] + 1;
344 left -= count;
345 buf += count;
346 if (left) {
347 left -= 1;
348 *buf++ = '.';
349 }
350 }
351 buf[0] = 0;
352
353 return (res);
354}