]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/dns/rfc1035.cc
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
10 * Low level DNS protocol routines
14 * UDP replies with TC set should be retried via TCP
18 #include "dns/rfc1035.h"
19 #include "dns/rfc2671.h"
31 #include <netinet/in.h>
34 #include <arpa/inet.h>
40 #define RFC1035_MAXLABELSZ 63
41 #define rfc1035_unpack_error 15
44 #define RFC1035_UNPACK_DEBUG fprintf(stderr, "unpack error at %s:%d\n", __FILE__,__LINE__)
46 #define RFC1035_UNPACK_DEBUG (void)0
52 * Packs a rfc1035_header structure into a buffer.
53 * Returns number of octets packed (should always be 12)
56 rfc1035HeaderPack(char *buf
, size_t sz
, rfc1035_message
* hdr
)
63 memcpy(buf
+ off
, &s
, sizeof(s
));
67 t
|= (hdr
->opcode
<< 11);
74 memcpy(buf
+ off
, &s
, sizeof(s
));
76 s
= htons(hdr
->qdcount
);
77 memcpy(buf
+ off
, &s
, sizeof(s
));
79 s
= htons(hdr
->ancount
);
80 memcpy(buf
+ off
, &s
, sizeof(s
));
82 s
= htons(hdr
->nscount
);
83 memcpy(buf
+ off
, &s
, sizeof(s
));
85 s
= htons(hdr
->arcount
);
86 memcpy(buf
+ off
, &s
, sizeof(s
));
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.
101 rfc1035LabelPack(char *buf
, size_t sz
, const char *label
)
104 assert(!strchr(label
, '.'));
107 auto len
= strlen(label
);
108 if (len
> RFC1035_MAXLABELSZ
)
109 len
= RFC1035_MAXLABELSZ
;
110 assert(sz
>= len
+ 1);
111 *(buf
+ off
) = (char) len
;
113 memcpy(buf
+ off
, label
, len
);
121 * Packs a name into a buffer. Names are packed as a
122 * sequence of labels, terminated with NULL label.
123 * Note message compression is not supported here.
124 * Returns number of octets packed.
127 rfc1035NamePack(char *buf
, size_t sz
, const char *name
)
129 unsigned int off
= 0;
130 char *copy
= xstrdup(name
);
133 * NOTE: use of strtok here makes names like foo....com valid.
135 for (t
= strtok(copy
, "."); t
; t
= strtok(nullptr, "."))
136 off
+= rfc1035LabelPack(buf
+ off
, sz
- off
, t
);
139 // add a terminating root (i.e. zero length) label
148 * rfc1035QuestionPack()
150 * Packs a QUESTION section of a message.
151 * Returns number of octets packed.
154 rfc1035QuestionPack(char *buf
,
157 const unsigned short type
,
158 const unsigned short _class
)
160 unsigned int off
= 0;
162 off
+= rfc1035NamePack(buf
+ off
, sz
- off
, name
);
164 memcpy(buf
+ off
, &s
, sizeof(s
));
167 memcpy(buf
+ off
, &s
, sizeof(s
));
174 * rfc1035HeaderUnpack()
176 * Unpacks a RFC1035 message header buffer into the header fields
177 * of the rfc1035_message structure.
179 * Updates the buffer offset, which is the same as number of
180 * octects unpacked since the header starts at offset 0.
182 * Returns 0 (success) or 1 (error)
185 rfc1035HeaderUnpack(const char *buf
, size_t sz
, unsigned int *off
, rfc1035_message
* h
)
191 * The header is 12 octets. This is a bogus message if the size
196 memcpy(&s
, buf
+ (*off
), sizeof(s
));
199 memcpy(&s
, buf
+ (*off
), sizeof(s
));
202 h
->qr
= (t
>> 15) & 0x01;
203 h
->opcode
= (t
>> 11) & 0x0F;
204 h
->aa
= (t
>> 10) & 0x01;
205 h
->tc
= (t
>> 9) & 0x01;
206 h
->rd
= (t
>> 8) & 0x01;
207 h
->ra
= (t
>> 7) & 0x01;
209 * We might want to check that the reserved 'Z' bits (6-4) are
210 * all zero as per RFC 1035. If not the message should be
212 * NO! RFCs say ignore inbound reserved, they may be used in future.
213 * NEW messages need to be set 0, that's all.
216 memcpy(&s
, buf
+ (*off
), sizeof(s
));
218 h
->qdcount
= ntohs(s
);
219 memcpy(&s
, buf
+ (*off
), sizeof(s
));
221 h
->ancount
= ntohs(s
);
222 memcpy(&s
, buf
+ (*off
), sizeof(s
));
224 h
->nscount
= ntohs(s
);
225 memcpy(&s
, buf
+ (*off
), sizeof(s
));
227 h
->arcount
= ntohs(s
);
228 assert((*off
) == 12);
233 * rfc1035NameUnpack()
235 * Unpacks a Name in a message buffer into a char*.
236 * Note 'buf' points to the beginning of the whole message,
237 * 'off' points to the spot where the Name begins, and 'sz'
238 * is the size of the whole message. 'name' must be allocated
241 * Supports the RFC1035 message compression through recursion.
243 * Updates the new buffer offset.
245 * Returns 0 (success) or 1 (error)
248 rfc1035NameUnpack(const char *buf
, size_t sz
, unsigned int *off
, unsigned short *rdlength
, char *name
, size_t ns
, int rdepth
)
256 RFC1035_UNPACK_DEBUG
;
261 /* blasted compression */
264 if (rdepth
> 64) { /* infinite pointer loop */
265 RFC1035_UNPACK_DEBUG
;
268 /* before copying compression offset value, ensure it is inside the buffer */
269 if ((*off
) + sizeof(s
) > sz
) {
270 RFC1035_UNPACK_DEBUG
;
273 memcpy(&s
, buf
+ (*off
), sizeof(s
));
277 /* Make sure the pointer is inside this message */
279 RFC1035_UNPACK_DEBUG
;
282 return rfc1035NameUnpack(buf
, sz
, &ptr
, rdlength
, name
+ no
, ns
- no
, rdepth
+ 1);
283 } else if (c
> RFC1035_MAXLABELSZ
) {
285 * "(The 10 and 01 combinations are reserved for future use.)"
287 RFC1035_UNPACK_DEBUG
;
294 if (len
> (ns
- no
- 1)) { /* label won't fit */
295 RFC1035_UNPACK_DEBUG
;
298 if ((*off
) + len
>= sz
) { /* message is too short */
299 RFC1035_UNPACK_DEBUG
;
302 memcpy(name
+ no
, buf
+ (*off
), len
);
305 *(name
+ (no
++)) = '.';
307 *rdlength
+= len
+ 1;
309 } while (c
> 0 && no
< ns
);
311 *(name
+ no
- 1) = '\0';
314 /* make sure we didn't allow someone to overflow the name buffer */
322 * Packs a RFC1035 Resource Record into a message buffer from 'RR'.
323 * The caller must allocate and free RR->rdata and RR->name!
325 * Updates the new message buffer.
327 * Returns the number of bytes added to the buffer or 0 for error.
330 rfc1035RRPack(char *buf
, const size_t sz
, const rfc1035_rr
* RR
)
336 off
= rfc1035NamePack(buf
, sz
, RR
->name
);
339 * Make sure the remaining message has enough octets for the
340 * rest of the RR fields.
342 if ((off
+ sizeof(s
)*3 + sizeof(i
) + RR
->rdlength
) > sz
) {
346 memcpy(buf
+ off
, &s
, sizeof(s
));
348 s
= htons(RR
->_class
);
349 memcpy(buf
+ off
, &s
, sizeof(s
));
352 memcpy(buf
+ off
, &i
, sizeof(i
));
354 s
= htons(RR
->rdlength
);
355 memcpy(buf
+ off
, &s
, sizeof(s
));
357 memcpy(buf
+ off
, &(RR
->rdata
), RR
->rdlength
);
366 * Unpacks a RFC1035 Resource Record into 'RR' from a message buffer.
367 * The caller must free RR->rdata!
369 * Updates the new message buffer offset.
371 * Returns 0 (success) or 1 (error)
374 rfc1035RRUnpack(const char *buf
, size_t sz
, unsigned int *off
, rfc1035_rr
* RR
)
378 unsigned short rdlength
;
379 unsigned int rdata_off
;
380 if (rfc1035NameUnpack(buf
, sz
, off
, nullptr, RR
->name
, RFC1035_MAXHOSTNAMESZ
, 0)) {
381 RFC1035_UNPACK_DEBUG
;
382 memset(RR
, '\0', sizeof(*RR
));
386 * Make sure the remaining message has enough octets for the
387 * rest of the RR fields.
389 if ((*off
) + 10 > sz
) {
390 RFC1035_UNPACK_DEBUG
;
391 memset(RR
, '\0', sizeof(*RR
));
394 memcpy(&s
, buf
+ (*off
), sizeof(s
));
397 memcpy(&s
, buf
+ (*off
), sizeof(s
));
399 RR
->_class
= ntohs(s
);
400 memcpy(&i
, buf
+ (*off
), sizeof(i
));
403 memcpy(&s
, buf
+ (*off
), sizeof(s
));
406 if ((*off
) + rdlength
> sz
) {
408 * We got a truncated packet. 'dnscache' truncates UDP
409 * replies at 512 octets, as per RFC 1035.
411 RFC1035_UNPACK_DEBUG
;
412 memset(RR
, '\0', sizeof(*RR
));
415 RR
->rdlength
= rdlength
;
417 case RFC1035_TYPE_PTR
:
418 RR
->rdata
= (char*)xmalloc(RFC1035_MAXHOSTNAMESZ
);
420 RR
->rdlength
= 0; /* Filled in by rfc1035NameUnpack */
421 if (rfc1035NameUnpack(buf
, sz
, &rdata_off
, &RR
->rdlength
, RR
->rdata
, RFC1035_MAXHOSTNAMESZ
, 0)) {
422 RFC1035_UNPACK_DEBUG
;
425 if (rdata_off
> ((*off
) + rdlength
)) {
427 * This probably doesn't happen for valid packets, but
428 * I want to make sure that NameUnpack doesn't go beyond
431 RFC1035_UNPACK_DEBUG
;
433 memset(RR
, '\0', sizeof(*RR
));
439 RR
->rdata
= (char*)xmalloc(rdlength
);
440 memcpy(RR
->rdata
, buf
+ (*off
), rdlength
);
444 assert((*off
) <= sz
);
449 rfc1035ErrorMessage(int n
)
455 return "No error condition";
458 return "Format Error: The name server was "
459 "unable to interpret the query.";
462 return "Server Failure: The name server was "
463 "unable to process this query.";
466 return "Name Error: The domain name does "
470 return "Not Implemented: The name server does "
471 "not support the requested kind of query.";
474 return "Refused: The name server refuses to "
475 "perform the specified operation.";
477 case rfc1035_unpack_error
:
478 return "The DNS reply message is corrupt or could "
479 "not be safely parsed.";
482 return "Unknown Error";
488 rfc1035RRDestroy(rfc1035_rr
** rr
, int n
)
490 if (*rr
== nullptr) {
496 xfree((*rr
)[n
].rdata
);
503 * rfc1035QueryUnpack()
505 * Unpacks a RFC1035 Query Record into 'query' from a message buffer.
507 * Updates the new message buffer offset.
509 * Returns 0 (success) or 1 (error)
512 rfc1035QueryUnpack(const char *buf
, size_t sz
, unsigned int *off
, rfc1035_query
* query
)
515 if (rfc1035NameUnpack(buf
, sz
, off
, nullptr, query
->name
, RFC1035_MAXHOSTNAMESZ
, 0)) {
516 RFC1035_UNPACK_DEBUG
;
517 memset(query
, '\0', sizeof(*query
));
521 RFC1035_UNPACK_DEBUG
;
522 memset(query
, '\0', sizeof(*query
));
525 memcpy(&s
, buf
+ *off
, 2);
527 query
->qtype
= ntohs(s
);
528 memcpy(&s
, buf
+ *off
, 2);
530 query
->qclass
= ntohs(s
);
535 rfc1035MessageDestroy(rfc1035_message
** msg
)
540 xfree((*msg
)->query
);
542 rfc1035RRDestroy(&(*msg
)->answer
, (*msg
)->ancount
);
548 * rfc1035QueryCompare()
550 * Compares two rfc1035_query entries
552 * Returns 0 (equal) or !=0 (different)
555 rfc1035QueryCompare(const rfc1035_query
* a
, const rfc1035_query
* b
)
558 if (a
->qtype
!= b
->qtype
)
560 if (a
->qclass
!= b
->qclass
)
562 la
= strlen(a
->name
);
563 lb
= strlen(b
->name
);
565 /* Trim root label(s) */
566 while (la
> 0 && a
->name
[la
- 1] == '.')
568 while (lb
> 0 && b
->name
[lb
- 1] == '.')
574 return strncasecmp(a
->name
, b
->name
, la
);
578 * rfc1035MessageUnpack()
580 * Takes the contents of a DNS reply and fills in an array
581 * of resource record structures. The records array is allocated
582 * here, and should be freed by calling rfc1035RRDestroy().
584 * Returns number of records unpacked, zero if DNS reply indicates
585 * zero answers, or an error number < 0.
589 rfc1035MessageUnpack(const char *buf
,
591 rfc1035_message
** answer
)
593 unsigned int off
= 0;
596 rfc1035_message
*msg
= nullptr;
597 rfc1035_rr
*recs
= nullptr;
598 rfc1035_query
*querys
= nullptr;
599 msg
= (rfc1035_message
*)xcalloc(1, sizeof(*msg
));
600 if (rfc1035HeaderUnpack(buf
+ off
, sz
- off
, &off
, msg
)) {
601 RFC1035_UNPACK_DEBUG
;
603 return -rfc1035_unpack_error
;
605 i
= (unsigned int) msg
->qdcount
;
607 /* This can not be an answer to our queries.. */
608 RFC1035_UNPACK_DEBUG
;
610 return -rfc1035_unpack_error
;
612 querys
= msg
->query
= (rfc1035_query
*)xcalloc(i
, sizeof(*querys
));
613 for (j
= 0; j
< i
; j
++) {
614 if (rfc1035QueryUnpack(buf
, sz
, &off
, &querys
[j
])) {
615 RFC1035_UNPACK_DEBUG
;
616 rfc1035MessageDestroy(&msg
);
617 return -rfc1035_unpack_error
;
622 RFC1035_UNPACK_DEBUG
;
625 if (msg
->ancount
== 0)
627 i
= (unsigned int) msg
->ancount
;
628 recs
= msg
->answer
= (rfc1035_rr
*)xcalloc(i
, sizeof(*recs
));
629 for (j
= 0; j
< i
; j
++) {
630 if (off
>= sz
) { /* corrupt packet */
631 RFC1035_UNPACK_DEBUG
;
634 if (rfc1035RRUnpack(buf
, sz
, &off
, &recs
[j
])) { /* corrupt RR */
635 RFC1035_UNPACK_DEBUG
;
642 * we expected to unpack some answers (ancount != 0), but
643 * didn't actually get any.
645 rfc1035MessageDestroy(&msg
);
647 return -rfc1035_unpack_error
;
653 * rfc1035BuildAQuery()
655 * Builds a message buffer with a QUESTION to lookup A records
656 * for a hostname. Caller must allocate 'buf' which should
657 * probably be at least 512 octets. The 'szp' initially
658 * specifies the size of the buffer, on return it contains
659 * the size of the message (i.e. how much to write).
660 * Returns the size of the query
663 rfc1035BuildAQuery(const char *hostname
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, ssize_t edns_sz
)
665 static rfc1035_message h
;
667 memset(&h
, '\0', sizeof(h
));
671 h
.opcode
= 0; /* QUERY */
672 h
.qdcount
= (unsigned int) 1;
673 h
.arcount
= (edns_sz
> 0 ? 1 : 0);
674 offset
+= rfc1035HeaderPack(buf
+ offset
, sz
- offset
, &h
);
675 offset
+= rfc1035QuestionPack(buf
+ offset
,
681 offset
+= rfc2671RROptPack(buf
+ offset
, sz
- offset
, edns_sz
);
683 query
->qtype
= RFC1035_TYPE_A
;
684 query
->qclass
= RFC1035_CLASS_IN
;
685 xstrncpy(query
->name
, hostname
, sizeof(query
->name
));
687 assert(offset
<= sz
);
692 * rfc1035BuildPTRQuery()
694 * Builds a message buffer with a QUESTION to lookup PTR records
695 * for an address. Caller must allocate 'buf' which should
696 * probably be at least 512 octets. The 'szp' initially
697 * specifies the size of the buffer, on return it contains
698 * the size of the message (i.e. how much to write).
699 * Returns the size of the query
702 rfc1035BuildPTRQuery(const struct in_addr addr
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, ssize_t edns_sz
)
704 static rfc1035_message h
;
708 memset(&h
, '\0', sizeof(h
));
709 i
= (unsigned int) ntohl(addr
.s_addr
);
710 snprintf(rev
, 32, "%u.%u.%u.%u.in-addr.arpa.",
718 h
.opcode
= 0; /* QUERY */
719 h
.qdcount
= (unsigned int) 1;
720 h
.arcount
= (edns_sz
> 0 ? 1 : 0);
721 offset
+= rfc1035HeaderPack(buf
+ offset
, sz
- offset
, &h
);
722 offset
+= rfc1035QuestionPack(buf
+ offset
,
728 offset
+= rfc2671RROptPack(buf
+ offset
, sz
- offset
, edns_sz
);
730 query
->qtype
= RFC1035_TYPE_PTR
;
731 query
->qclass
= RFC1035_CLASS_IN
;
732 xstrncpy(query
->name
, rev
, sizeof(query
->name
));
734 assert(offset
<= sz
);
739 * We're going to retry a former query, but we
740 * just need a new ID for it. Lucky for us ID
741 * is the first field in the message buffer.
744 rfc1035SetQueryID(char *buf
, unsigned short qid
)
746 unsigned short s
= htons(qid
);
747 memcpy(buf
, &s
, sizeof(s
));