rfc1035.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/*
10 * Low level DNS protocol routines
11 *
12 * KNOWN BUGS:
13 *
14 * UDP replies with TC set should be retried via TCP
15 */
16
17#include "squid.h"
18#include "dns/rfc1035.h"
19#include "dns/rfc2671.h"
20#include "util.h"
21
22#include <cassert>
23#include <cstring>
24#if HAVE_UNISTD_H
25#include <unistd.h>
26#endif
27#if HAVE_MEMORY_H
28#include <memory.h>
29#endif
30#if HAVE_NETINET_IN_H
31#include <netinet/in.h>
32#endif
33#if HAVE_ARPA_INET_H
34#include <arpa/inet.h>
35#endif
36#if HAVE_STRINGS_H
37#include <strings.h>
38#endif
39
40#define RFC1035_MAXLABELSZ 63
41#define rfc1035_unpack_error 15
42
43#if 0
44#define RFC1035_UNPACK_DEBUG fprintf(stderr, "unpack error at %s:%d\n", __FILE__,__LINE__)
45#else
46#define RFC1035_UNPACK_DEBUG (void)0
47#endif
48
49/*
50 * rfc1035HeaderPack()
51 *
52 * Packs a rfc1035_header structure into a buffer.
53 * Returns number of octets packed (should always be 12)
54 */
55int
56rfc1035HeaderPack(char *buf, size_t sz, rfc1035_message * hdr)
57{
58 int off = 0;
59 unsigned short s;
60 unsigned short t;
61 assert(sz >= 12);
62 s = htons(hdr->id);
63 memcpy(buf + off, &s, sizeof(s));
64 off += sizeof(s);
65 t = 0;
66 t |= hdr->qr << 15;
67 t |= (hdr->opcode << 11);
68 t |= (hdr->aa << 10);
69 t |= (hdr->tc << 9);
70 t |= (hdr->rd << 8);
71 t |= (hdr->ra << 7);
72 t |= hdr->rcode;
73 s = htons(t);
74 memcpy(buf + off, &s, sizeof(s));
75 off += sizeof(s);
76 s = htons(hdr->qdcount);
77 memcpy(buf + off, &s, sizeof(s));
78 off += sizeof(s);
79 s = htons(hdr->ancount);
80 memcpy(buf + off, &s, sizeof(s));
81 off += sizeof(s);
82 s = htons(hdr->nscount);
83 memcpy(buf + off, &s, sizeof(s));
84 off += sizeof(s);
85 s = htons(hdr->arcount);
86 memcpy(buf + off, &s, sizeof(s));
87 off += sizeof(s);
88 assert(off == 12);
89 return off;
90}
91
92/*
93 * rfc1035LabelPack()
94 *
95 * Packs a label into a buffer. The format of
96 * a label is one octet specifying the number of character
97 * bytes to follow. Labels must be smaller than 64 octets.
98 * Returns number of octets packed.
99 */
100static int
101rfc1035LabelPack(char *buf, size_t sz, const char *label)
102{
103 int off = 0;
104 size_t len = label ? strlen(label) : 0;
105 if (label)
106 assert(!strchr(label, '.'));
107 if (len > RFC1035_MAXLABELSZ)
108 len = RFC1035_MAXLABELSZ;
109 assert(sz >= len + 1);
110 *(buf + off) = (char) len;
111 off++;
112 memcpy(buf + off, label, len);
113 off += len;
114 return off;
115}
116
117/*
118 * rfc1035NamePack()
119 *
120 * Packs a name into a buffer. Names are packed as a
121 * sequence of labels, terminated with NULL label.
122 * Note message compression is not supported here.
123 * Returns number of octets packed.
124 */
125static int
126rfc1035NamePack(char *buf, size_t sz, const char *name)
127{
128 unsigned int off = 0;
129 char *copy = xstrdup(name);
130 char *t;
131 /*
132 * NOTE: use of strtok here makes names like foo....com valid.
133 */
134 for (t = strtok(copy, "."); t; t = strtok(nullptr, "."))
135 off += rfc1035LabelPack(buf + off, sz - off, t);
136 xfree(copy);
137 off += rfc1035LabelPack(buf + off, sz - off, nullptr);
138 assert(off <= sz);
139 return off;
140}
141
142/*
143 * rfc1035QuestionPack()
144 *
145 * Packs a QUESTION section of a message.
146 * Returns number of octets packed.
147 */
148int
150 const size_t sz,
151 const char *name,
152 const unsigned short type,
153 const unsigned short _class)
154{
155 unsigned int off = 0;
156 unsigned short s;
157 off += rfc1035NamePack(buf + off, sz - off, name);
158 s = htons(type);
159 memcpy(buf + off, &s, sizeof(s));
160 off += sizeof(s);
161 s = htons(_class);
162 memcpy(buf + off, &s, sizeof(s));
163 off += sizeof(s);
164 assert(off <= sz);
165 return off;
166}
167
168/*
169 * rfc1035HeaderUnpack()
170 *
171 * Unpacks a RFC1035 message header buffer into the header fields
172 * of the rfc1035_message structure.
173 *
174 * Updates the buffer offset, which is the same as number of
175 * octects unpacked since the header starts at offset 0.
176 *
177 * Returns 0 (success) or 1 (error)
178 */
179int
180rfc1035HeaderUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_message * h)
181{
182 unsigned short s;
183 unsigned short t;
184 assert(*off == 0);
185 /*
186 * The header is 12 octets. This is a bogus message if the size
187 * is less than that.
188 */
189 if (sz < 12)
190 return 1;
191 memcpy(&s, buf + (*off), sizeof(s));
192 (*off) += sizeof(s);
193 h->id = ntohs(s);
194 memcpy(&s, buf + (*off), sizeof(s));
195 (*off) += sizeof(s);
196 t = ntohs(s);
197 h->qr = (t >> 15) & 0x01;
198 h->opcode = (t >> 11) & 0x0F;
199 h->aa = (t >> 10) & 0x01;
200 h->tc = (t >> 9) & 0x01;
201 h->rd = (t >> 8) & 0x01;
202 h->ra = (t >> 7) & 0x01;
203 /*
204 * We might want to check that the reserved 'Z' bits (6-4) are
205 * all zero as per RFC 1035. If not the message should be
206 * rejected.
207 * NO! RFCs say ignore inbound reserved, they may be used in future.
208 * NEW messages need to be set 0, that's all.
209 */
210 h->rcode = t & 0x0F;
211 memcpy(&s, buf + (*off), sizeof(s));
212 (*off) += sizeof(s);
213 h->qdcount = ntohs(s);
214 memcpy(&s, buf + (*off), sizeof(s));
215 (*off) += sizeof(s);
216 h->ancount = ntohs(s);
217 memcpy(&s, buf + (*off), sizeof(s));
218 (*off) += sizeof(s);
219 h->nscount = ntohs(s);
220 memcpy(&s, buf + (*off), sizeof(s));
221 (*off) += sizeof(s);
222 h->arcount = ntohs(s);
223 assert((*off) == 12);
224 return 0;
225}
226
227/*
228 * rfc1035NameUnpack()
229 *
230 * Unpacks a Name in a message buffer into a char*.
231 * Note 'buf' points to the beginning of the whole message,
232 * 'off' points to the spot where the Name begins, and 'sz'
233 * is the size of the whole message. 'name' must be allocated
234 * by the caller.
235 *
236 * Supports the RFC1035 message compression through recursion.
237 *
238 * Updates the new buffer offset.
239 *
240 * Returns 0 (success) or 1 (error)
241 */
242static int
243rfc1035NameUnpack(const char *buf, size_t sz, unsigned int *off, unsigned short *rdlength, char *name, size_t ns, int rdepth)
244{
245 unsigned int no = 0;
246 unsigned char c;
247 size_t len;
248 assert(ns > 0);
249 do {
250 if ((*off) >= sz) {
252 return 1;
253 }
254 c = *(buf + (*off));
255 if (c > 191) {
256 /* blasted compression */
257 unsigned short s;
258 unsigned int ptr;
259 if (rdepth > 64) { /* infinite pointer loop */
261 return 1;
262 }
263 memcpy(&s, buf + (*off), sizeof(s));
264 s = ntohs(s);
265 (*off) += sizeof(s);
266 /* Sanity check */
267 if ((*off) > sz) {
269 return 1;
270 }
271 ptr = s & 0x3FFF;
272 /* Make sure the pointer is inside this message */
273 if (ptr >= sz) {
275 return 1;
276 }
277 return rfc1035NameUnpack(buf, sz, &ptr, rdlength, name + no, ns - no, rdepth + 1);
278 } else if (c > RFC1035_MAXLABELSZ) {
279 /*
280 * "(The 10 and 01 combinations are reserved for future use.)"
281 */
283 return 1;
284 } else {
285 (*off)++;
286 len = (size_t) c;
287 if (len == 0)
288 break;
289 if (len > (ns - no - 1)) { /* label won't fit */
291 return 1;
292 }
293 if ((*off) + len >= sz) { /* message is too short */
295 return 1;
296 }
297 memcpy(name + no, buf + (*off), len);
298 (*off) += len;
299 no += len;
300 *(name + (no++)) = '.';
301 if (rdlength)
302 *rdlength += len + 1;
303 }
304 } while (c > 0 && no < ns);
305 if (no)
306 *(name + no - 1) = '\0';
307 else
308 *name = '\0';
309 /* make sure we didn't allow someone to overflow the name buffer */
310 assert(no <= ns);
311 return 0;
312}
313
314/*
315 * rfc1035RRPack()
316 *
317 * Packs a RFC1035 Resource Record into a message buffer from 'RR'.
318 * The caller must allocate and free RR->rdata and RR->name!
319 *
320 * Updates the new message buffer.
321 *
322 * Returns the number of bytes added to the buffer or 0 for error.
323 */
324int
325rfc1035RRPack(char *buf, const size_t sz, const rfc1035_rr * RR)
326{
327 unsigned int off;
328 uint16_t s;
329 uint32_t i;
330
331 off = rfc1035NamePack(buf, sz, RR->name);
332
333 /*
334 * Make sure the remaining message has enough octets for the
335 * rest of the RR fields.
336 */
337 if ((off + sizeof(s)*3 + sizeof(i) + RR->rdlength) > sz) {
338 return 0;
339 }
340 s = htons(RR->type);
341 memcpy(buf + off, &s, sizeof(s));
342 off += sizeof(s);
343 s = htons(RR->_class);
344 memcpy(buf + off, &s, sizeof(s));
345 off += sizeof(s);
346 i = htonl(RR->ttl);
347 memcpy(buf + off, &i, sizeof(i));
348 off += sizeof(i);
349 s = htons(RR->rdlength);
350 memcpy(buf + off, &s, sizeof(s));
351 off += sizeof(s);
352 memcpy(buf + off, &(RR->rdata), RR->rdlength);
353 off += RR->rdlength;
354 assert(off <= sz);
355 return off;
356}
357
358/*
359 * rfc1035RRUnpack()
360 *
361 * Unpacks a RFC1035 Resource Record into 'RR' from a message buffer.
362 * The caller must free RR->rdata!
363 *
364 * Updates the new message buffer offset.
365 *
366 * Returns 0 (success) or 1 (error)
367 */
368static int
369rfc1035RRUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_rr * RR)
370{
371 unsigned short s;
372 unsigned int i;
373 unsigned short rdlength;
374 unsigned int rdata_off;
375 if (rfc1035NameUnpack(buf, sz, off, nullptr, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) {
377 memset(RR, '\0', sizeof(*RR));
378 return 1;
379 }
380 /*
381 * Make sure the remaining message has enough octets for the
382 * rest of the RR fields.
383 */
384 if ((*off) + 10 > sz) {
386 memset(RR, '\0', sizeof(*RR));
387 return 1;
388 }
389 memcpy(&s, buf + (*off), sizeof(s));
390 (*off) += sizeof(s);
391 RR->type = ntohs(s);
392 memcpy(&s, buf + (*off), sizeof(s));
393 (*off) += sizeof(s);
394 RR->_class = ntohs(s);
395 memcpy(&i, buf + (*off), sizeof(i));
396 (*off) += sizeof(i);
397 RR->ttl = ntohl(i);
398 memcpy(&s, buf + (*off), sizeof(s));
399 (*off) += sizeof(s);
400 rdlength = ntohs(s);
401 if ((*off) + rdlength > sz) {
402 /*
403 * We got a truncated packet. 'dnscache' truncates UDP
404 * replies at 512 octets, as per RFC 1035.
405 */
407 memset(RR, '\0', sizeof(*RR));
408 return 1;
409 }
410 RR->rdlength = rdlength;
411 switch (RR->type) {
412 case RFC1035_TYPE_PTR:
413 RR->rdata = (char*)xmalloc(RFC1035_MAXHOSTNAMESZ);
414 rdata_off = *off;
415 RR->rdlength = 0; /* Filled in by rfc1035NameUnpack */
416 if (rfc1035NameUnpack(buf, sz, &rdata_off, &RR->rdlength, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0)) {
418 return 1;
419 }
420 if (rdata_off > ((*off) + rdlength)) {
421 /*
422 * This probably doesn't happen for valid packets, but
423 * I want to make sure that NameUnpack doesn't go beyond
424 * the RDATA area.
425 */
427 xfree(RR->rdata);
428 memset(RR, '\0', sizeof(*RR));
429 return 1;
430 }
431 break;
432 case RFC1035_TYPE_A:
433 default:
434 RR->rdata = (char*)xmalloc(rdlength);
435 memcpy(RR->rdata, buf + (*off), rdlength);
436 break;
437 }
438 (*off) += rdlength;
439 assert((*off) <= sz);
440 return 0;
441}
442
443const char *
445{
446 if (n < 0)
447 n = -n;
448 switch (n) {
449 case 0:
450 return "No error condition";
451 break;
452 case 1:
453 return "Format Error: The name server was "
454 "unable to interpret the query.";
455 break;
456 case 2:
457 return "Server Failure: The name server was "
458 "unable to process this query.";
459 break;
460 case 3:
461 return "Name Error: The domain name does "
462 "not exist.";
463 break;
464 case 4:
465 return "Not Implemented: The name server does "
466 "not support the requested kind of query.";
467 break;
468 case 5:
469 return "Refused: The name server refuses to "
470 "perform the specified operation.";
471 break;
473 return "The DNS reply message is corrupt or could "
474 "not be safely parsed.";
475 break;
476 default:
477 return "Unknown Error";
478 break;
479 }
480}
481
482void
484{
485 if (*rr == nullptr) {
486 return;
487 }
488
489 while (n-- > 0) {
490 if ((*rr)[n].rdata)
491 xfree((*rr)[n].rdata);
492 }
493 xfree(*rr);
494 *rr = nullptr;
495}
496
497/*
498 * rfc1035QueryUnpack()
499 *
500 * Unpacks a RFC1035 Query Record into 'query' from a message buffer.
501 *
502 * Updates the new message buffer offset.
503 *
504 * Returns 0 (success) or 1 (error)
505 */
506static int
507rfc1035QueryUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_query * query)
508{
509 unsigned short s;
510 if (rfc1035NameUnpack(buf, sz, off, nullptr, query->name, RFC1035_MAXHOSTNAMESZ, 0)) {
512 memset(query, '\0', sizeof(*query));
513 return 1;
514 }
515 if (*off + 4 > sz) {
517 memset(query, '\0', sizeof(*query));
518 return 1;
519 }
520 memcpy(&s, buf + *off, 2);
521 *off += 2;
522 query->qtype = ntohs(s);
523 memcpy(&s, buf + *off, 2);
524 *off += 2;
525 query->qclass = ntohs(s);
526 return 0;
527}
528
529void
531{
532 if (!*msg)
533 return;
534 if ((*msg)->query)
535 xfree((*msg)->query);
536 if ((*msg)->answer)
537 rfc1035RRDestroy(&(*msg)->answer, (*msg)->ancount);
538 xfree(*msg);
539 *msg = nullptr;
540}
541
542/*
543 * rfc1035QueryCompare()
544 *
545 * Compares two rfc1035_query entries
546 *
547 * Returns 0 (equal) or !=0 (different)
548 */
549int
551{
552 size_t la, lb;
553 if (a->qtype != b->qtype)
554 return 1;
555 if (a->qclass != b->qclass)
556 return 1;
557 la = strlen(a->name);
558 lb = strlen(b->name);
559 if (la != lb) {
560 /* Trim root label(s) */
561 while (la > 0 && a->name[la - 1] == '.')
562 la--;
563 while (lb > 0 && b->name[lb - 1] == '.')
564 lb--;
565 }
566 if (la != lb)
567 return 1;
568
569 return strncasecmp(a->name, b->name, la);
570}
571
572/*
573 * rfc1035MessageUnpack()
574 *
575 * Takes the contents of a DNS reply and fills in an array
576 * of resource record structures. The records array is allocated
577 * here, and should be freed by calling rfc1035RRDestroy().
578 *
579 * Returns number of records unpacked, zero if DNS reply indicates
580 * zero answers, or an error number < 0.
581 */
582
583int
584rfc1035MessageUnpack(const char *buf,
585 size_t sz,
586 rfc1035_message ** answer)
587{
588 unsigned int off = 0;
589 unsigned int i, j;
590 unsigned int nr = 0;
591 rfc1035_message *msg = nullptr;
592 rfc1035_rr *recs = nullptr;
593 rfc1035_query *querys = nullptr;
594 msg = (rfc1035_message*)xcalloc(1, sizeof(*msg));
595 if (rfc1035HeaderUnpack(buf + off, sz - off, &off, msg)) {
597 xfree(msg);
598 return -rfc1035_unpack_error;
599 }
600 i = (unsigned int) msg->qdcount;
601 if (i != 1) {
602 /* This can not be an answer to our queries.. */
604 xfree(msg);
605 return -rfc1035_unpack_error;
606 }
607 querys = msg->query = (rfc1035_query*)xcalloc(i, sizeof(*querys));
608 for (j = 0; j < i; j++) {
609 if (rfc1035QueryUnpack(buf, sz, &off, &querys[j])) {
612 return -rfc1035_unpack_error;
613 }
614 }
615 *answer = msg;
616 if (msg->rcode) {
618 return -msg->rcode;
619 }
620 if (msg->ancount == 0)
621 return 0;
622 i = (unsigned int) msg->ancount;
623 recs = msg->answer = (rfc1035_rr*)xcalloc(i, sizeof(*recs));
624 for (j = 0; j < i; j++) {
625 if (off >= sz) { /* corrupt packet */
627 break;
628 }
629 if (rfc1035RRUnpack(buf, sz, &off, &recs[j])) { /* corrupt RR */
631 break;
632 }
633 nr++;
634 }
635 if (nr == 0) {
636 /*
637 * we expected to unpack some answers (ancount != 0), but
638 * didn't actually get any.
639 */
641 *answer = nullptr;
642 return -rfc1035_unpack_error;
643 }
644 return nr;
645}
646
647/*
648 * rfc1035BuildAQuery()
649 *
650 * Builds a message buffer with a QUESTION to lookup A records
651 * for a hostname. Caller must allocate 'buf' which should
652 * probably be at least 512 octets. The 'szp' initially
653 * specifies the size of the buffer, on return it contains
654 * the size of the message (i.e. how much to write).
655 * Returns the size of the query
656 */
657ssize_t
658rfc1035BuildAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
659{
660 static rfc1035_message h;
661 size_t offset = 0;
662 memset(&h, '\0', sizeof(h));
663 h.id = qid;
664 h.qr = 0;
665 h.rd = 1;
666 h.opcode = 0; /* QUERY */
667 h.qdcount = (unsigned int) 1;
668 h.arcount = (edns_sz > 0 ? 1 : 0);
669 offset += rfc1035HeaderPack(buf + offset, sz - offset, &h);
670 offset += rfc1035QuestionPack(buf + offset,
671 sz - offset,
672 hostname,
675 if (edns_sz > 0)
676 offset += rfc2671RROptPack(buf + offset, sz - offset, edns_sz);
677 if (query) {
678 query->qtype = RFC1035_TYPE_A;
679 query->qclass = RFC1035_CLASS_IN;
680 xstrncpy(query->name, hostname, sizeof(query->name));
681 }
682 assert(offset <= sz);
683 return offset;
684}
685
686/*
687 * rfc1035BuildPTRQuery()
688 *
689 * Builds a message buffer with a QUESTION to lookup PTR records
690 * for an address. Caller must allocate 'buf' which should
691 * probably be at least 512 octets. The 'szp' initially
692 * specifies the size of the buffer, on return it contains
693 * the size of the message (i.e. how much to write).
694 * Returns the size of the query
695 */
696ssize_t
697rfc1035BuildPTRQuery(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
698{
699 static rfc1035_message h;
700 size_t offset = 0;
701 static char rev[32];
702 unsigned int i;
703 memset(&h, '\0', sizeof(h));
704 i = (unsigned int) ntohl(addr.s_addr);
705 snprintf(rev, 32, "%u.%u.%u.%u.in-addr.arpa.",
706 i & 255,
707 (i >> 8) & 255,
708 (i >> 16) & 255,
709 (i >> 24) & 255);
710 h.id = qid;
711 h.qr = 0;
712 h.rd = 1;
713 h.opcode = 0; /* QUERY */
714 h.qdcount = (unsigned int) 1;
715 h.arcount = (edns_sz > 0 ? 1 : 0);
716 offset += rfc1035HeaderPack(buf + offset, sz - offset, &h);
717 offset += rfc1035QuestionPack(buf + offset,
718 sz - offset,
719 rev,
722 if (edns_sz > 0)
723 offset += rfc2671RROptPack(buf + offset, sz - offset, edns_sz);
724 if (query) {
725 query->qtype = RFC1035_TYPE_PTR;
726 query->qclass = RFC1035_CLASS_IN;
727 xstrncpy(query->name, rev, sizeof(query->name));
728 }
729 assert(offset <= sz);
730 return offset;
731}
732
733/*
734 * We're going to retry a former query, but we
735 * just need a new ID for it. Lucky for us ID
736 * is the first field in the message buffer.
737 */
738void
739rfc1035SetQueryID(char *buf, unsigned short qid)
740{
741 unsigned short s = htons(qid);
742 memcpy(buf, &s, sizeof(s));
743}
744
#define assert(EX)
Definition: assert.h:17
unsigned short _class
Definition: rfc1035.h:41
char * rdata
Definition: rfc1035.h:44
char name[RFC1035_MAXHOSTNAMESZ]
Definition: rfc1035.h:39
unsigned short type
Definition: rfc1035.h:40
unsigned short rdlength
Definition: rfc1035.h:43
unsigned int ttl
Definition: rfc1035.h:42
#define xfree
#define xstrdup
#define xmalloc
static int rfc1035LabelPack(char *buf, size_t sz, const char *label)
Definition: rfc1035.cc:101
static int rfc1035NamePack(char *buf, size_t sz, const char *name)
Definition: rfc1035.cc:126
void rfc1035SetQueryID(char *buf, unsigned short qid)
Definition: rfc1035.cc:739
void rfc1035RRDestroy(rfc1035_rr **rr, int n)
Definition: rfc1035.cc:483
int rfc1035HeaderUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_message *h)
Definition: rfc1035.cc:180
static int rfc1035RRUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_rr *RR)
Definition: rfc1035.cc:369
int rfc1035MessageUnpack(const char *buf, size_t sz, rfc1035_message **answer)
Definition: rfc1035.cc:584
#define RFC1035_MAXLABELSZ
Definition: rfc1035.cc:40
ssize_t rfc1035BuildPTRQuery(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query *query, ssize_t edns_sz)
Definition: rfc1035.cc:697
static int rfc1035NameUnpack(const char *buf, size_t sz, unsigned int *off, unsigned short *rdlength, char *name, size_t ns, int rdepth)
Definition: rfc1035.cc:243
int rfc1035QueryCompare(const rfc1035_query *a, const rfc1035_query *b)
Definition: rfc1035.cc:550
const char * rfc1035ErrorMessage(int n)
Definition: rfc1035.cc:444
static int rfc1035QueryUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_query *query)
Definition: rfc1035.cc:507
void rfc1035MessageDestroy(rfc1035_message **msg)
Definition: rfc1035.cc:530
ssize_t rfc1035BuildAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query *query, ssize_t edns_sz)
Definition: rfc1035.cc:658
#define rfc1035_unpack_error
Definition: rfc1035.cc:41
int rfc1035QuestionPack(char *buf, const size_t sz, const char *name, const unsigned short type, const unsigned short _class)
Definition: rfc1035.cc:149
int rfc1035HeaderPack(char *buf, size_t sz, rfc1035_message *hdr)
Definition: rfc1035.cc:56
#define RFC1035_UNPACK_DEBUG
Definition: rfc1035.cc:46
int rfc1035RRPack(char *buf, const size_t sz, const rfc1035_rr *RR)
Definition: rfc1035.cc:325
#define RFC1035_TYPE_PTR
Definition: rfc1035.h:95
#define RFC1035_TYPE_A
Definition: rfc1035.h:93
#define RFC1035_CLASS_IN
Definition: rfc1035.h:96
#define RFC1035_MAXHOSTNAMESZ
Definition: rfc1035.h:32
int rfc2671RROptPack(char *buf, size_t sz, ssize_t edns_sz)
Definition: rfc2671.cc:14
unsigned short ancount
Definition: rfc1035.h:65
unsigned short nscount
Definition: rfc1035.h:66
unsigned int rd
Definition: rfc1035.h:61
unsigned int tc
Definition: rfc1035.h:60
unsigned short qdcount
Definition: rfc1035.h:64
unsigned int opcode
Definition: rfc1035.h:58
unsigned int rcode
Definition: rfc1035.h:63
unsigned int aa
Definition: rfc1035.h:59
rfc1035_rr * answer
Definition: rfc1035.h:69
unsigned short id
Definition: rfc1035.h:56
unsigned int ra
Definition: rfc1035.h:62
unsigned int qr
Definition: rfc1035.h:57
rfc1035_query * query
Definition: rfc1035.h:68
unsigned short arcount
Definition: rfc1035.h:67
unsigned short qclass
Definition: rfc1035.h:51
char name[RFC1035_MAXHOSTNAMESZ]
Definition: rfc1035.h:49
unsigned short qtype
Definition: rfc1035.h:50
int unsigned int
Definition: stub_fd.cc:19
int const char size_t
Definition: stub_liblog.cc:83
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors