summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/asr/bin/res_mkquery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libc/asr/bin/res_mkquery.c')
-rw-r--r--src/regress/lib/libc/asr/bin/res_mkquery.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/src/regress/lib/libc/asr/bin/res_mkquery.c b/src/regress/lib/libc/asr/bin/res_mkquery.c
new file mode 100644
index 0000000000..a52023c5c0
--- /dev/null
+++ b/src/regress/lib/libc/asr/bin/res_mkquery.c
@@ -0,0 +1,319 @@
1/* $OpenBSD: res_mkquery.c,v 1.1.1.1 2012/07/13 17:49:53 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 void
46usage(void)
47{
48 extern const char * __progname;
49
50 fprintf(stderr, "usage: %s [-deq] [-t type] [host...]\n",
51 __progname);
52 exit(1);
53}
54
55int
56main(int argc, char *argv[])
57{
58 int ch, i, r;
59 uint16_t type = T_A;
60 char buf[1024], *host;
61
62 while((ch = getopt(argc, argv, "et:")) != -1) {
63 switch(ch) {
64 case 'e':
65 long_err += 1;
66 break;
67 case 't':
68 if ((type = strtotype(optarg)) == 0)
69 usage();
70 break;
71 default:
72 usage();
73 /* NOTREACHED */
74 }
75 }
76 argc -= optind;
77 argv += optind;
78
79 for (i = 0; i < argc; i++) {
80
81 if (i)
82 printf("\n");
83
84 printf("===> \"%s\"\n", argv[i]);
85 host = gethostarg(argv[i]);
86
87 errno = 0;
88 h_errno = 0;
89 gai_errno = 0;
90 rrset_errno = 0;
91
92 r = res_mkquery(QUERY, host, C_IN, type, NULL, 0, NULL, buf, sizeof(buf));
93 if (r != -1) {
94 dump_packet(buf, r);
95 printf(";; MSG SIZE %i\n", r);
96 }
97 print_errors();
98 }
99
100 return (0);
101}
102
103#define OPCODE_SHIFT 11
104#define Z_SHIFT 4
105
106static char*
107print_header(struct header *h, char *buf, size_t max)
108{
109 snprintf(buf, max,
110 "id:0x.... %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i",
111 (h->flags & QR_MASK) ? "QR":" ",
112 (int)(OPCODE(h->flags) >> OPCODE_SHIFT),
113 (h->flags & AA_MASK) ? "AA":" ",
114 (h->flags & TC_MASK) ? "TC":" ",
115 (h->flags & RD_MASK) ? "RD":" ",
116 (h->flags & RA_MASK) ? "RA":" ",
117 ((h->flags & Z_MASK) >> Z_SHIFT),
118 rcodetostr(RCODE(h->flags)),
119 h->qdcount, h->ancount, h->nscount, h->arcount);
120
121 return buf;
122}
123
124static void
125dump_packet(const void *data, size_t len)
126{
127 char buf[1024];
128 struct packed p;
129 struct header h;
130 struct query q;
131 struct rr rr;
132 int i, an, ns, ar, n;
133
134 packed_init(&p, (char *)data, len);
135
136 if (unpack_header(&p, &h) == -1) {
137 printf(";; BAD PACKET: %s\n", p.err);
138 return;
139 }
140
141 printf(";; HEADER %s\n", print_header(&h, buf, sizeof buf));
142
143 if (h.qdcount)
144 printf(";; QUERY SECTION:\n");
145 for (i = 0; i < h.qdcount; i++) {
146 if (unpack_query(&p, &q) == -1)
147 goto error;
148 printf("%s\n", print_query(&q, buf, sizeof buf));
149 }
150
151 an = 0;
152 ns = an + h.ancount;
153 ar = ns + h.nscount;
154 n = ar + h.arcount;
155
156 for (i = 0; i < n; i++) {
157 if (i == an)
158 printf("\n;; ANSWER SECTION:\n");
159 if (i == ns)
160 printf("\n;; AUTHORITY SECTION:\n");
161 if (i == ar)
162 printf("\n;; ADDITIONAL SECTION:\n");
163
164 if (unpack_rr(&p, &rr) == -1)
165 goto error;
166 printf("%s\n", print_rr(&rr, buf, sizeof buf));
167 }
168
169 if (p.offset != len)
170 printf(";; REMAINING GARBAGE %zu\n", len - p.offset);
171
172 error:
173 if (p.err)
174 printf(";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len,
175 p.err);
176}
177
178static const char *
179inet6_ntoa(struct in6_addr a)
180{
181 static char buf[256];
182 struct sockaddr_in6 si;
183
184 si.sin6_len = sizeof(si);
185 si.sin6_family = PF_INET6;
186 si.sin6_addr = a;
187
188 return print_host((struct sockaddr*)&si, buf, sizeof buf);
189}
190
191static char*
192print_rr(struct rr *rr, char *buf, size_t max)
193{
194 char *res;
195 char tmp[256];
196 char tmp2[256];
197 int r;
198
199 res = buf;
200
201 r = snprintf(buf, max, "%s %u %s %s ",
202 print_dname(rr->rr_dname, tmp, sizeof tmp),
203 rr->rr_ttl,
204 classtostr(rr->rr_class),
205 typetostr(rr->rr_type));
206 if (r == -1) {
207 buf[0] = '\0';
208 return buf;
209 }
210
211 if ((size_t)r >= max)
212 return buf;
213
214 max -= r;
215 buf += r;
216
217 switch(rr->rr_type) {
218 case T_CNAME:
219 print_dname(rr->rr.cname.cname, buf, max);
220 break;
221 case T_MX:
222 snprintf(buf, max, "%"PRIu32" %s",
223 rr->rr.mx.preference,
224 print_dname(rr->rr.mx.exchange, tmp, sizeof tmp));
225 break;
226 case T_NS:
227 print_dname(rr->rr.ns.nsname, buf, max);
228 break;
229 case T_PTR:
230 print_dname(rr->rr.ptr.ptrname, buf, max);
231 break;
232 case T_SOA:
233 snprintf(buf, max,
234 "%s %s %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32,
235 print_dname(rr->rr.soa.rname, tmp, sizeof tmp),
236 print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2),
237 rr->rr.soa.serial,
238 rr->rr.soa.refresh,
239 rr->rr.soa.retry,
240 rr->rr.soa.expire,
241 rr->rr.soa.minimum);
242 break;
243 case T_A:
244 if (rr->rr_class != C_IN)
245 goto other;
246 snprintf(buf, max, "%s", inet_ntoa(rr->rr.in_a.addr));
247 break;
248 case T_AAAA:
249 if (rr->rr_class != C_IN)
250 goto other;
251 snprintf(buf, max, "%s", inet6_ntoa(rr->rr.in_aaaa.addr6));
252 break;
253 default:
254 other:
255 snprintf(buf, max, "(rdlen=%"PRIu16 ")", rr->rr.other.rdlen);
256 break;
257 }
258
259 return (res);
260}
261
262static char*
263print_query(struct query *q, char *buf, size_t max)
264{
265 char b[256];
266
267 snprintf(buf, max, "%s %s %s",
268 print_dname(q->q_dname, b, sizeof b),
269 classtostr(q->q_class), typetostr(q->q_type));
270
271 return (buf);
272}
273
274
275static char *
276print_host(const struct sockaddr *sa, char *buf, size_t len)
277{
278 switch (sa->sa_family) {
279 case AF_INET:
280 inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, buf, len);
281 break;
282 case AF_INET6:
283 inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, buf, len);
284 break;
285 default:
286 buf[0] = '\0';
287 }
288 return (buf);
289}
290
291static char*
292print_dname(const char *_dname, char *buf, size_t max)
293{
294 const unsigned char *dname = _dname;
295 char *res;
296 size_t left, n, count;
297
298 if (_dname[0] == 0) {
299 strlcpy(buf, ".", max);
300 return buf;
301 }
302
303 res = buf;
304 left = max - 1;
305 for (n = 0; dname[0] && left; n += dname[0]) {
306 count = (dname[0] < (left - 1)) ? dname[0] : (left - 1);
307 memmove(buf, dname + 1, count);
308 dname += dname[0] + 1;
309 left -= count;
310 buf += count;
311 if (left) {
312 left -= 1;
313 *buf++ = '.';
314 }
315 }
316 buf[0] = 0;
317
318 return (res);
319}