]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfc1035.c
Enable source-formatting tools to collapse multiple whitelines in the source to one.
[thirdparty/squid.git] / lib / rfc1035.c
1 /*
2 * $Id$
3 *
4 * Low level DNS protocol routines
5 * AUTHOR: Duane Wessels
6 *
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34
35 /*
36 * KNOWN BUGS:
37 *
38 * UDP replies with TC set should be retried via TCP
39 */
40
41 #include "squid.h"
42 #include "util.h"
43
44 #if HAVE_STDIO_H
45 #include <stdio.h>
46 #endif
47 #if HAVE_STRING_H
48 #include <string.h>
49 #endif
50 #if HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53 #if HAVE_MEMORY_H
54 #include <memory.h>
55 #endif
56 #if HAVE_ASSERT_H
57 #include <assert.h>
58 #endif
59 #if HAVE_NETINET_IN_H
60 #include <netinet/in.h>
61 #endif
62 #if HAVE_ARPA_INET_H
63 #include <arpa/inet.h>
64 #endif
65 #if HAVE_STRINGS_H
66 #include <strings.h>
67 #endif
68
69 #include "rfc1035.h"
70 #include "rfc2671.h"
71
72 #define RFC1035_MAXLABELSZ 63
73 #define rfc1035_unpack_error 15
74
75 #if 0
76 #define RFC1035_UNPACK_DEBUG fprintf(stderr, "unpack error at %s:%d\n", __FILE__,__LINE__)
77 #else
78 #define RFC1035_UNPACK_DEBUG (void)0
79 #endif
80
81
82
83 /*
84 * rfc1035HeaderPack()
85 *
86 * Packs a rfc1035_header structure into a buffer.
87 * Returns number of octets packed (should always be 12)
88 */
89 int
90 rfc1035HeaderPack(char *buf, size_t sz, rfc1035_message * hdr)
91 {
92 int off = 0;
93 unsigned short s;
94 unsigned short t;
95 assert(sz >= 12);
96 s = htons(hdr->id);
97 memcpy(buf + off, &s, sizeof(s));
98 off += sizeof(s);
99 t = 0;
100 t |= hdr->qr << 15;
101 t |= (hdr->opcode << 11);
102 t |= (hdr->aa << 10);
103 t |= (hdr->tc << 9);
104 t |= (hdr->rd << 8);
105 t |= (hdr->ra << 7);
106 t |= hdr->rcode;
107 s = htons(t);
108 memcpy(buf + off, &s, sizeof(s));
109 off += sizeof(s);
110 s = htons(hdr->qdcount);
111 memcpy(buf + off, &s, sizeof(s));
112 off += sizeof(s);
113 s = htons(hdr->ancount);
114 memcpy(buf + off, &s, sizeof(s));
115 off += sizeof(s);
116 s = htons(hdr->nscount);
117 memcpy(buf + off, &s, sizeof(s));
118 off += sizeof(s);
119 s = htons(hdr->arcount);
120 memcpy(buf + off, &s, sizeof(s));
121 off += sizeof(s);
122 assert(off == 12);
123 return off;
124 }
125
126 /*
127 * rfc1035LabelPack()
128 *
129 * Packs a label into a buffer. The format of
130 * a label is one octet specifying the number of character
131 * bytes to follow. Labels must be smaller than 64 octets.
132 * Returns number of octets packed.
133 */
134 static int
135 rfc1035LabelPack(char *buf, size_t sz, const char *label)
136 {
137 int off = 0;
138 size_t len = label ? strlen(label) : 0;
139 if (label)
140 assert(!strchr(label, '.'));
141 if (len > RFC1035_MAXLABELSZ)
142 len = RFC1035_MAXLABELSZ;
143 assert(sz >= len + 1);
144 *(buf + off) = (char) len;
145 off++;
146 memcpy(buf + off, label, len);
147 off += len;
148 return off;
149 }
150
151 /*
152 * rfc1035NamePack()
153 *
154 * Packs a name into a buffer. Names are packed as a
155 * sequence of labels, terminated with NULL label.
156 * Note message compression is not supported here.
157 * Returns number of octets packed.
158 */
159 static int
160 rfc1035NamePack(char *buf, size_t sz, const char *name)
161 {
162 unsigned int off = 0;
163 char *copy = xstrdup(name);
164 char *t;
165 /*
166 * NOTE: use of strtok here makes names like foo....com valid.
167 */
168 for (t = strtok(copy, "."); t; t = strtok(NULL, "."))
169 off += rfc1035LabelPack(buf + off, sz - off, t);
170 xfree(copy);
171 off += rfc1035LabelPack(buf + off, sz - off, NULL);
172 assert(off <= sz);
173 return off;
174 }
175
176 /*
177 * rfc1035QuestionPack()
178 *
179 * Packs a QUESTION section of a message.
180 * Returns number of octets packed.
181 */
182 int
183 rfc1035QuestionPack(char *buf,
184 const size_t sz,
185 const char *name,
186 const unsigned short type,
187 const unsigned short _class)
188 {
189 unsigned int off = 0;
190 unsigned short s;
191 off += rfc1035NamePack(buf + off, sz - off, name);
192 s = htons(type);
193 memcpy(buf + off, &s, sizeof(s));
194 off += sizeof(s);
195 s = htons(_class);
196 memcpy(buf + off, &s, sizeof(s));
197 off += sizeof(s);
198 assert(off <= sz);
199 return off;
200 }
201
202 /*
203 * rfc1035HeaderUnpack()
204 *
205 * Unpacks a RFC1035 message header buffer into the header fields
206 * of the rfc1035_message structure.
207 *
208 * Updates the buffer offset, which is the same as number of
209 * octects unpacked since the header starts at offset 0.
210 *
211 * Returns 0 (success) or 1 (error)
212 */
213 int
214 rfc1035HeaderUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_message * h)
215 {
216 unsigned short s;
217 unsigned short t;
218 assert(*off == 0);
219 /*
220 * The header is 12 octets. This is a bogus message if the size
221 * is less than that.
222 */
223 if (sz < 12)
224 return 1;
225 memcpy(&s, buf + (*off), sizeof(s));
226 (*off) += sizeof(s);
227 h->id = ntohs(s);
228 memcpy(&s, buf + (*off), sizeof(s));
229 (*off) += sizeof(s);
230 t = ntohs(s);
231 h->qr = (t >> 15) & 0x01;
232 h->opcode = (t >> 11) & 0x0F;
233 h->aa = (t >> 10) & 0x01;
234 h->tc = (t >> 9) & 0x01;
235 h->rd = (t >> 8) & 0x01;
236 h->ra = (t >> 7) & 0x01;
237 /*
238 * We might want to check that the reserved 'Z' bits (6-4) are
239 * all zero as per RFC 1035. If not the message should be
240 * rejected.
241 * NO! RFCs say ignore inbound reserved, they may be used in future.
242 * NEW messages need to be set 0, thats all.
243 */
244 h->rcode = t & 0x0F;
245 memcpy(&s, buf + (*off), sizeof(s));
246 (*off) += sizeof(s);
247 h->qdcount = ntohs(s);
248 memcpy(&s, buf + (*off), sizeof(s));
249 (*off) += sizeof(s);
250 h->ancount = ntohs(s);
251 memcpy(&s, buf + (*off), sizeof(s));
252 (*off) += sizeof(s);
253 h->nscount = ntohs(s);
254 memcpy(&s, buf + (*off), sizeof(s));
255 (*off) += sizeof(s);
256 h->arcount = ntohs(s);
257 assert((*off) == 12);
258 return 0;
259 }
260
261 /*
262 * rfc1035NameUnpack()
263 *
264 * Unpacks a Name in a message buffer into a char*.
265 * Note 'buf' points to the beginning of the whole message,
266 * 'off' points to the spot where the Name begins, and 'sz'
267 * is the size of the whole message. 'name' must be allocated
268 * by the caller.
269 *
270 * Supports the RFC1035 message compression through recursion.
271 *
272 * Updates the new buffer offset.
273 *
274 * Returns 0 (success) or 1 (error)
275 */
276 static int
277 rfc1035NameUnpack(const char *buf, size_t sz, unsigned int *off, unsigned short *rdlength, char *name, size_t ns, int rdepth)
278 {
279 unsigned int no = 0;
280 unsigned char c;
281 size_t len;
282 assert(ns > 0);
283 do {
284 if ((*off) >= sz) {
285 RFC1035_UNPACK_DEBUG;
286 return 1;
287 }
288 c = *(buf + (*off));
289 if (c > 191) {
290 /* blasted compression */
291 unsigned short s;
292 unsigned int ptr;
293 if (rdepth > 64) { /* infinite pointer loop */
294 RFC1035_UNPACK_DEBUG;
295 return 1;
296 }
297 memcpy(&s, buf + (*off), sizeof(s));
298 s = ntohs(s);
299 (*off) += sizeof(s);
300 /* Sanity check */
301 if ((*off) > sz) {
302 RFC1035_UNPACK_DEBUG;
303 return 1;
304 }
305 ptr = s & 0x3FFF;
306 /* Make sure the pointer is inside this message */
307 if (ptr >= sz) {
308 RFC1035_UNPACK_DEBUG;
309 return 1;
310 }
311 return rfc1035NameUnpack(buf, sz, &ptr, rdlength, name + no, ns - no, rdepth + 1);
312 } else if (c > RFC1035_MAXLABELSZ) {
313 /*
314 * "(The 10 and 01 combinations are reserved for future use.)"
315 */
316 RFC1035_UNPACK_DEBUG;
317 return 1;
318 } else {
319 (*off)++;
320 len = (size_t) c;
321 if (len == 0)
322 break;
323 if (len > (ns - no - 1)) { /* label won't fit */
324 RFC1035_UNPACK_DEBUG;
325 return 1;
326 }
327 if ((*off) + len >= sz) { /* message is too short */
328 RFC1035_UNPACK_DEBUG;
329 return 1;
330 }
331 memcpy(name + no, buf + (*off), len);
332 (*off) += len;
333 no += len;
334 *(name + (no++)) = '.';
335 if (rdlength)
336 *rdlength += len + 1;
337 }
338 } while (c > 0 && no < ns);
339 if (no)
340 *(name + no - 1) = '\0';
341 else
342 *name = '\0';
343 /* make sure we didn't allow someone to overflow the name buffer */
344 assert(no <= ns);
345 return 0;
346 }
347
348 /*
349 * rfc1035RRPack()
350 *
351 * Packs a RFC1035 Resource Record into a message buffer from 'RR'.
352 * The caller must allocate and free RR->rdata and RR->name!
353 *
354 * Updates the new message buffer.
355 *
356 * Returns the number of bytes added to the buffer or 0 for error.
357 */
358 int
359 rfc1035RRPack(char *buf, const size_t sz, const rfc1035_rr * RR)
360 {
361 unsigned int off;
362 uint16_t s;
363 uint32_t i;
364
365 off = rfc1035NamePack(buf, sz, RR->name);
366
367 /*
368 * Make sure the remaining message has enough octets for the
369 * rest of the RR fields.
370 */
371 if ((off + sizeof(s)*3 + sizeof(i) + RR->rdlength) > sz) {
372 return 0;
373 }
374 s = htons(RR->type);
375 memcpy(buf + off, &s, sizeof(s));
376 off += sizeof(s);
377 s = htons(RR->_class);
378 memcpy(buf + off, &s, sizeof(s));
379 off += sizeof(s);
380 i = htonl(RR->ttl);
381 memcpy(buf + off, &i, sizeof(i));
382 off += sizeof(i);
383 s = htons(RR->rdlength);
384 memcpy(buf + off, &s, sizeof(s));
385 off += sizeof(s);
386 memcpy(buf + off, &(RR->rdata), RR->rdlength);
387 off += RR->rdlength;
388 assert(off <= sz);
389 return off;
390 }
391
392 /*
393 * rfc1035RRUnpack()
394 *
395 * Unpacks a RFC1035 Resource Record into 'RR' from a message buffer.
396 * The caller must free RR->rdata!
397 *
398 * Updates the new message buffer offset.
399 *
400 * Returns 0 (success) or 1 (error)
401 */
402 static int
403 rfc1035RRUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_rr * RR)
404 {
405 unsigned short s;
406 unsigned int i;
407 unsigned short rdlength;
408 unsigned int rdata_off;
409 if (rfc1035NameUnpack(buf, sz, off, NULL, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) {
410 RFC1035_UNPACK_DEBUG;
411 memset(RR, '\0', sizeof(*RR));
412 return 1;
413 }
414 /*
415 * Make sure the remaining message has enough octets for the
416 * rest of the RR fields.
417 */
418 if ((*off) + 10 > sz) {
419 RFC1035_UNPACK_DEBUG;
420 memset(RR, '\0', sizeof(*RR));
421 return 1;
422 }
423 memcpy(&s, buf + (*off), sizeof(s));
424 (*off) += sizeof(s);
425 RR->type = ntohs(s);
426 memcpy(&s, buf + (*off), sizeof(s));
427 (*off) += sizeof(s);
428 RR->_class = ntohs(s);
429 memcpy(&i, buf + (*off), sizeof(i));
430 (*off) += sizeof(i);
431 RR->ttl = ntohl(i);
432 memcpy(&s, buf + (*off), sizeof(s));
433 (*off) += sizeof(s);
434 rdlength = ntohs(s);
435 if ((*off) + rdlength > sz) {
436 /*
437 * We got a truncated packet. 'dnscache' truncates UDP
438 * replies at 512 octets, as per RFC 1035.
439 */
440 RFC1035_UNPACK_DEBUG;
441 memset(RR, '\0', sizeof(*RR));
442 return 1;
443 }
444 RR->rdlength = rdlength;
445 switch (RR->type) {
446 #if DNS_CNAME
447 case RFC1035_TYPE_CNAME:
448 #endif
449 case RFC1035_TYPE_PTR:
450 RR->rdata = (char*)xmalloc(RFC1035_MAXHOSTNAMESZ);
451 rdata_off = *off;
452 RR->rdlength = 0; /* Filled in by rfc1035NameUnpack */
453 if (rfc1035NameUnpack(buf, sz, &rdata_off, &RR->rdlength, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0)) {
454 RFC1035_UNPACK_DEBUG;
455 return 1;
456 }
457 if (rdata_off > ((*off) + rdlength)) {
458 /*
459 * This probably doesn't happen for valid packets, but
460 * I want to make sure that NameUnpack doesn't go beyond
461 * the RDATA area.
462 */
463 RFC1035_UNPACK_DEBUG;
464 xfree(RR->rdata);
465 memset(RR, '\0', sizeof(*RR));
466 return 1;
467 }
468 break;
469 case RFC1035_TYPE_A:
470 default:
471 RR->rdata = (char*)xmalloc(rdlength);
472 memcpy(RR->rdata, buf + (*off), rdlength);
473 break;
474 }
475 (*off) += rdlength;
476 assert((*off) <= sz);
477 return 0;
478 }
479
480 const char *
481 rfc1035ErrorMessage(int n)
482 {
483 if (n < 0)
484 n = -n;
485 switch (n) {
486 case 0:
487 return "No error condition";
488 break;
489 case 1:
490 return "Format Error: The name server was "
491 "unable to interpret the query.";
492 break;
493 case 2:
494 return "Server Failure: The name server was "
495 "unable to process this query.";
496 break;
497 case 3:
498 return "Name Error: The domain name does "
499 "not exist.";
500 break;
501 case 4:
502 return "Not Implemented: The name server does "
503 "not support the requested kind of query.";
504 break;
505 case 5:
506 return "Refused: The name server refuses to "
507 "perform the specified operation.";
508 break;
509 case rfc1035_unpack_error:
510 return "The DNS reply message is corrupt or could "
511 "not be safely parsed.";
512 break;
513 default:
514 return "Unknown Error";
515 break;
516 }
517 }
518
519 void
520 rfc1035RRDestroy(rfc1035_rr ** rr, int n)
521 {
522 if (*rr == NULL) {
523 return;
524 }
525
526 while (n-- > 0) {
527 if ((*rr)[n].rdata)
528 xfree((*rr)[n].rdata);
529 }
530 xfree(*rr);
531 *rr = NULL;
532 }
533
534 /*
535 * rfc1035QueryUnpack()
536 *
537 * Unpacks a RFC1035 Query Record into 'query' from a message buffer.
538 *
539 * Updates the new message buffer offset.
540 *
541 * Returns 0 (success) or 1 (error)
542 */
543 static int
544 rfc1035QueryUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_query * query)
545 {
546 unsigned short s;
547 if (rfc1035NameUnpack(buf, sz, off, NULL, query->name, RFC1035_MAXHOSTNAMESZ, 0)) {
548 RFC1035_UNPACK_DEBUG;
549 memset(query, '\0', sizeof(*query));
550 return 1;
551 }
552 if (*off + 4 > sz) {
553 RFC1035_UNPACK_DEBUG;
554 memset(query, '\0', sizeof(*query));
555 return 1;
556 }
557 memcpy(&s, buf + *off, 2);
558 *off += 2;
559 query->qtype = ntohs(s);
560 memcpy(&s, buf + *off, 2);
561 *off += 2;
562 query->qclass = ntohs(s);
563 return 0;
564 }
565
566 void
567 rfc1035MessageDestroy(rfc1035_message ** msg)
568 {
569 if (!*msg)
570 return;
571 if ((*msg)->query)
572 xfree((*msg)->query);
573 if ((*msg)->answer)
574 rfc1035RRDestroy(&(*msg)->answer, (*msg)->ancount);
575 xfree(*msg);
576 *msg = NULL;
577 }
578
579 /*
580 * rfc1035QueryCompare()
581 *
582 * Compares two rfc1035_query entries
583 *
584 * Returns 0 (equal) or !=0 (different)
585 */
586 int
587 rfc1035QueryCompare(const rfc1035_query * a, const rfc1035_query * b)
588 {
589 size_t la, lb;
590 if (a->qtype != b->qtype)
591 return 1;
592 if (a->qclass != b->qclass)
593 return 1;
594 la = strlen(a->name);
595 lb = strlen(b->name);
596 if (la != lb) {
597 /* Trim root label(s) */
598 while (la > 0 && a->name[la - 1] == '.')
599 la--;
600 while (lb > 0 && b->name[lb - 1] == '.')
601 lb--;
602 }
603 if (la != lb)
604 return 1;
605
606 return strncasecmp(a->name, b->name, la);
607 }
608
609 /*
610 * rfc1035MessageUnpack()
611 *
612 * Takes the contents of a DNS reply and fills in an array
613 * of resource record structures. The records array is allocated
614 * here, and should be freed by calling rfc1035RRDestroy().
615 *
616 * Returns number of records unpacked, zero if DNS reply indicates
617 * zero answers, or an error number < 0.
618 */
619
620 int
621 rfc1035MessageUnpack(const char *buf,
622 size_t sz,
623 rfc1035_message ** answer)
624 {
625 unsigned int off = 0;
626 unsigned int i, j;
627 unsigned int nr = 0;
628 rfc1035_message *msg = NULL;
629 rfc1035_rr *recs = NULL;
630 rfc1035_query *querys = NULL;
631 msg = (rfc1035_message*)xcalloc(1, sizeof(*msg));
632 if (rfc1035HeaderUnpack(buf + off, sz - off, &off, msg)) {
633 RFC1035_UNPACK_DEBUG;
634 xfree(msg);
635 return -rfc1035_unpack_error;
636 }
637 i = (unsigned int) msg->qdcount;
638 if (i != 1) {
639 /* This can not be an answer to our queries.. */
640 RFC1035_UNPACK_DEBUG;
641 xfree(msg);
642 return -rfc1035_unpack_error;
643 }
644 querys = msg->query = (rfc1035_query*)xcalloc(i, sizeof(*querys));
645 for (j = 0; j < i; j++) {
646 if (rfc1035QueryUnpack(buf, sz, &off, &querys[j])) {
647 RFC1035_UNPACK_DEBUG;
648 rfc1035MessageDestroy(&msg);
649 return -rfc1035_unpack_error;
650 }
651 }
652 *answer = msg;
653 if (msg->rcode) {
654 RFC1035_UNPACK_DEBUG;
655 return -msg->rcode;
656 }
657 if (msg->ancount == 0)
658 return 0;
659 i = (unsigned int) msg->ancount;
660 recs = msg->answer = (rfc1035_rr*)xcalloc(i, sizeof(*recs));
661 for (j = 0; j < i; j++) {
662 if (off >= sz) { /* corrupt packet */
663 RFC1035_UNPACK_DEBUG;
664 break;
665 }
666 if (rfc1035RRUnpack(buf, sz, &off, &recs[j])) { /* corrupt RR */
667 RFC1035_UNPACK_DEBUG;
668 break;
669 }
670 nr++;
671 }
672 if (nr == 0) {
673 /*
674 * we expected to unpack some answers (ancount != 0), but
675 * didn't actually get any.
676 */
677 rfc1035MessageDestroy(&msg);
678 *answer = NULL;
679 return -rfc1035_unpack_error;
680 }
681 return nr;
682 }
683
684 /*
685 * rfc1035BuildAQuery()
686 *
687 * Builds a message buffer with a QUESTION to lookup A records
688 * for a hostname. Caller must allocate 'buf' which should
689 * probably be at least 512 octets. The 'szp' initially
690 * specifies the size of the buffer, on return it contains
691 * the size of the message (i.e. how much to write).
692 * Returns the size of the query
693 */
694 ssize_t
695 rfc1035BuildAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
696 {
697 static rfc1035_message h;
698 size_t offset = 0;
699 memset(&h, '\0', sizeof(h));
700 h.id = qid;
701 h.qr = 0;
702 h.rd = 1;
703 h.opcode = 0; /* QUERY */
704 h.qdcount = (unsigned int) 1;
705 h.arcount = (edns_sz > 0 ? 1 : 0);
706 offset += rfc1035HeaderPack(buf + offset, sz - offset, &h);
707 offset += rfc1035QuestionPack(buf + offset,
708 sz - offset,
709 hostname,
710 RFC1035_TYPE_A,
711 RFC1035_CLASS_IN);
712 if (edns_sz > 0)
713 offset += rfc2671RROptPack(buf + offset, sz - offset, edns_sz);
714 if (query) {
715 query->qtype = RFC1035_TYPE_A;
716 query->qclass = RFC1035_CLASS_IN;
717 xstrncpy(query->name, hostname, sizeof(query->name));
718 }
719 assert(offset <= sz);
720 return offset;
721 }
722
723 /*
724 * rfc1035BuildPTRQuery()
725 *
726 * Builds a message buffer with a QUESTION to lookup PTR records
727 * for an address. Caller must allocate 'buf' which should
728 * probably be at least 512 octets. The 'szp' initially
729 * specifies the size of the buffer, on return it contains
730 * the size of the message (i.e. how much to write).
731 * Returns the size of the query
732 */
733 ssize_t
734 rfc1035BuildPTRQuery(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
735 {
736 static rfc1035_message h;
737 size_t offset = 0;
738 static char rev[32];
739 unsigned int i;
740 memset(&h, '\0', sizeof(h));
741 i = (unsigned int) ntohl(addr.s_addr);
742 snprintf(rev, 32, "%u.%u.%u.%u.in-addr.arpa.",
743 i & 255,
744 (i >> 8) & 255,
745 (i >> 16) & 255,
746 (i >> 24) & 255);
747 h.id = qid;
748 h.qr = 0;
749 h.rd = 1;
750 h.opcode = 0; /* QUERY */
751 h.qdcount = (unsigned int) 1;
752 h.arcount = (edns_sz > 0 ? 1 : 0);
753 offset += rfc1035HeaderPack(buf + offset, sz - offset, &h);
754 offset += rfc1035QuestionPack(buf + offset,
755 sz - offset,
756 rev,
757 RFC1035_TYPE_PTR,
758 RFC1035_CLASS_IN);
759 if (edns_sz > 0)
760 offset += rfc2671RROptPack(buf + offset, sz - offset, edns_sz);
761 if (query) {
762 query->qtype = RFC1035_TYPE_PTR;
763 query->qclass = RFC1035_CLASS_IN;
764 xstrncpy(query->name, rev, sizeof(query->name));
765 }
766 assert(offset <= sz);
767 return offset;
768 }
769
770 /*
771 * We're going to retry a former query, but we
772 * just need a new ID for it. Lucky for us ID
773 * is the first field in the message buffer.
774 */
775 void
776 rfc1035SetQueryID(char *buf, unsigned short qid)
777 {
778 unsigned short s = htons(qid);
779 memcpy(buf, &s, sizeof(s));
780 }
781
782 #if DRIVER
783 #include <sys/socket.h>
784 int
785 main(int argc, char *argv[])
786 {
787 char input[SQUID_DNS_BUFSZ];
788 char buf[SQUID_DNS_BUFSZ];
789 char rbuf[SQUID_DNS_BUFSZ];
790 size_t sz = SQUID_DNS_BUFSZ;
791 unsigned short sid;
792 int s;
793 int rl;
794 struct sockaddr_in S;
795 if (3 != argc) {
796 fprintf(stderr, "usage: %s ip port\n", argv[0]);
797 return 1;
798 }
799 setbuf(stdout, NULL);
800 setbuf(stderr, NULL);
801 s = socket(PF_INET, SOCK_DGRAM, 0);
802 if (s < 0) {
803 perror("socket");
804 return 1;
805 }
806 memset(&S, '\0', sizeof(S));
807 S.sin_family = AF_INET;
808 S.sin_port = htons(atoi(argv[2]));
809 S.sin_addr.s_addr = inet_addr(argv[1]);
810 while (fgets(input, RFC1035_DEFAULT_PACKET_SZ, stdin)) {
811 struct in_addr junk;
812 strtok(input, "\r\n");
813 memset(buf, '\0', RFC1035_DEFAULT_PACKET_SZ);
814 sz = RFC1035_DEFAULT_PACKET_SZ;
815 if (inet_pton(AF_INET, input, &junk)) {
816 sid = rfc1035BuildPTRQuery(junk, buf, &sz);
817 } else {
818 sid = rfc1035BuildAQuery(input, buf, &sz);
819 }
820 sendto(s, buf, sz, 0, (struct sockaddr *) &S, sizeof(S));
821 do {
822 fd_set R;
823 struct timeval to;
824 FD_ZERO(&R);
825 FD_SET(s, &R);
826 to.tv_sec = 10;
827 to.tv_usec = 0;
828 rl = select(s + 1, &R, NULL, NULL, &to);
829 } while (0);
830 if (rl < 1) {
831 printf("TIMEOUT\n");
832 continue;
833 }
834 memset(rbuf, '\0', RFC1035_DEFAULT_PACKET_SZ);
835 rl = recv(s, rbuf, RFC1035_DEFAULT_PACKET_SZ, 0);
836 {
837 unsigned short rid = 0;
838 int i;
839 int n;
840 rfc1035_rr *answers = NULL;
841 n = rfc1035AnswersUnpack(rbuf,
842 rl,
843 &answers,
844 &rid);
845 if (n < 0) {
846 printf("ERROR %d\n", -n);
847 } else if (rid != sid) {
848 printf("ERROR, ID mismatch (%#hx, %#hx)\n", sid, rid);
849 } else {
850 printf("%d answers\n", n);
851 for (i = 0; i < n; i++) {
852 if (answers[i].type == RFC1035_TYPE_A) {
853 struct in_addr a;
854 char ipa_str[sizeof(a)];
855 memcpy(&a, answers[i].rdata, 4);
856 printf("A\t%d\t%s\n", answers[i].ttl, inet_ntop(AF_INET,&a,tmp,sizeof(a)));
857 } else if (answers[i].type == RFC1035_TYPE_PTR) {
858 char ptr[128];
859 strncpy(ptr, answers[i].rdata, answers[i].rdlength);
860 printf("PTR\t%d\t%s\n", answers[i].ttl, ptr);
861 } else {
862 fprintf(stderr, "can't print answer type %d\n",
863 (int) answers[i].type);
864 }
865 }
866 }
867 }
868 }
869 return 0;
870 }
871 #endif