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