3 * $Id: rfc1035.c,v 1.27 2002/09/15 06:40:54 robertc Exp $
5 * Low level DNS protocol routines
6 * AUTHOR: Duane Wessels
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
39 * UDP replies with TC set should be retried via TCP
57 #include <sys/types.h>
63 #include <netinet/in.h>
66 #include <arpa/inet.h>
75 #define RFC1035_MAXLABELSZ 63
76 #define rfc1035_unpack_error 15
79 #define RFC1035_UNPACK_DEBUG fprintf(stderr, "unpack error at %s:%d\n", __FILE__,__LINE__)
81 #define RFC1035_UNPACK_DEBUG (void)0
85 typedef struct _rfc1035_header rfc1035_header
;
88 const char *rfc1035_error_message
;
89 struct _rfc1035_header
{
92 unsigned int opcode
:4;
98 unsigned short qdcount
;
99 unsigned short ancount
;
100 unsigned short nscount
;
101 unsigned short arcount
;
104 static const char *Alphanum
=
105 "abcdefghijklmnopqrstuvwxyz"
106 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
111 * rfc1035HeaderPack()
113 * Packs a rfc1035_header structure into a buffer.
114 * Returns number of octets packed (should always be 12)
117 rfc1035HeaderPack(char *buf
, size_t sz
, rfc1035_header
* hdr
)
124 memcpy(buf
+ off
, &s
, sizeof(s
));
128 t
|= (hdr
->opcode
<< 11);
129 t
|= (hdr
->aa
<< 10);
135 memcpy(buf
+ off
, &s
, sizeof(s
));
137 s
= htons(hdr
->qdcount
);
138 memcpy(buf
+ off
, &s
, sizeof(s
));
140 s
= htons(hdr
->ancount
);
141 memcpy(buf
+ off
, &s
, sizeof(s
));
143 s
= htons(hdr
->nscount
);
144 memcpy(buf
+ off
, &s
, sizeof(s
));
146 s
= htons(hdr
->arcount
);
147 memcpy(buf
+ off
, &s
, sizeof(s
));
156 * Packs a label into a buffer. The format of
157 * a label is one octet specifying the number of character
158 * bytes to follow. Labels must be smaller than 64 octets.
159 * Returns number of octets packed.
162 rfc1035LabelPack(char *buf
, size_t sz
, const char *label
)
165 size_t len
= label
? strlen(label
) : 0;
167 assert(!strchr(label
, '.'));
168 if (len
> RFC1035_MAXLABELSZ
)
169 len
= RFC1035_MAXLABELSZ
;
170 assert(sz
>= len
+ 1);
171 *(buf
+ off
) = (char) len
;
173 memcpy(buf
+ off
, label
, len
);
181 * Packs a name into a buffer. Names are packed as a
182 * sequence of labels, terminated with NULL label.
183 * Note message compression is not supported here.
184 * Returns number of octets packed.
187 rfc1035NamePack(char *buf
, size_t sz
, const char *name
)
190 char *copy
= strdup(name
);
193 * NOTE: use of strtok here makes names like foo....com valid.
195 for (t
= strtok(copy
, "."); t
; t
= strtok(NULL
, "."))
196 off
+= rfc1035LabelPack(buf
+ off
, sz
- off
, t
);
198 off
+= rfc1035LabelPack(buf
+ off
, sz
- off
, NULL
);
204 * rfc1035QuestionPack()
206 * Packs a QUESTION section of a message.
207 * Returns number of octets packed.
210 rfc1035QuestionPack(char *buf
,
214 unsigned short _class
)
218 off
+= rfc1035NamePack(buf
+ off
, sz
- off
, name
);
220 memcpy(buf
+ off
, &s
, sizeof(s
));
223 memcpy(buf
+ off
, &s
, sizeof(s
));
230 * rfc1035HeaderUnpack()
232 * Unpacks a RFC1035 message header buffer into a rfc1035_header
235 * Updates the buffer offset, which is the same as number of
236 * octects unpacked since the header starts at offset 0.
238 * Returns 0 (success) or 1 (error)
241 rfc1035HeaderUnpack(const char *buf
, size_t sz
, off_t
* off
, rfc1035_header
* h
)
247 * The header is 12 octets. This is a bogus message if the size
252 memcpy(&s
, buf
+ (*off
), sizeof(s
));
255 memcpy(&s
, buf
+ (*off
), sizeof(s
));
258 h
->qr
= (t
>> 15) & 0x01;
259 h
->opcode
= (t
>> 11) & 0x0F;
260 h
->aa
= (t
>> 10) & 0x01;
261 h
->tc
= (t
>> 9) & 0x01;
262 h
->rd
= (t
>> 8) & 0x01;
263 h
->ra
= (t
>> 7) & 0x01;
265 * We might want to check that the reserved 'Z' bits (6-4) are
266 * all zero as per RFC 1035. If not the message should be
270 memcpy(&s
, buf
+ (*off
), sizeof(s
));
272 h
->qdcount
= ntohs(s
);
273 memcpy(&s
, buf
+ (*off
), sizeof(s
));
275 h
->ancount
= ntohs(s
);
276 memcpy(&s
, buf
+ (*off
), sizeof(s
));
278 h
->nscount
= ntohs(s
);
279 memcpy(&s
, buf
+ (*off
), sizeof(s
));
281 h
->arcount
= ntohs(s
);
282 assert((*off
) == 12);
287 * rfc1035NameUnpack()
289 * Unpacks a Name in a message buffer into a char*.
290 * Note 'buf' points to the beginning of the whole message,
291 * 'off' points to the spot where the Name begins, and 'sz'
292 * is the size of the whole message. 'name' must be allocated
295 * Supports the RFC1035 message compression through recursion.
297 * Updates the new buffer offset.
299 * Returns 0 (success) or 1 (error)
302 rfc1035NameUnpack(const char *buf
, size_t sz
, off_t
* off
, char *name
, size_t ns
, int rdepth
)
312 /* blasted compression */
315 if (rdepth
> 64) /* infinite pointer loop */
317 memcpy(&s
, buf
+ (*off
), sizeof(s
));
324 /* Make sure the pointer is inside this message */
327 return rfc1035NameUnpack(buf
, sz
, &ptr
, name
+ no
, ns
- no
, rdepth
+ 1);
328 } else if (c
> RFC1035_MAXLABELSZ
) {
330 * "(The 10 and 01 combinations are reserved for future use.)"
338 if (len
> (ns
- no
- 1)) /* label won't fit */
340 if ((*off
) + len
> sz
) /* message is too short */
342 memcpy(name
+ no
, buf
+ (*off
), len
);
345 *(name
+ (no
++)) = '.';
347 } while (c
> 0 && no
< ns
);
348 *(name
+ no
- 1) = '\0';
349 /* make sure we didn't allow someone to overflow the name buffer */
357 * Unpacks a RFC1035 Resource Record into 'RR' from a message buffer.
358 * The caller must free RR->rdata!
360 * Updates the new message buffer offset.
362 * Returns 0 (success) or 1 (error)
365 rfc1035RRUnpack(const char *buf
, size_t sz
, off_t
* off
, rfc1035_rr
* RR
)
370 if (rfc1035NameUnpack(buf
, sz
, off
, RR
->name
, RFC1035_MAXHOSTNAMESZ
, 0)) {
371 RFC1035_UNPACK_DEBUG
;
372 memset(RR
, '\0', sizeof(*RR
));
376 * Make sure the remaining message has enough octets for the
377 * rest of the RR fields.
379 if ((*off
) + 10 > sz
) {
380 RFC1035_UNPACK_DEBUG
;
381 memset(RR
, '\0', sizeof(*RR
));
384 memcpy(&s
, buf
+ (*off
), sizeof(s
));
387 memcpy(&s
, buf
+ (*off
), sizeof(s
));
389 RR
->_class
= ntohs(s
);
390 memcpy(&i
, buf
+ (*off
), sizeof(i
));
393 memcpy(&s
, buf
+ (*off
), sizeof(s
));
395 if ((*off
) + ntohs(s
) > sz
) {
397 * We got a truncated packet. 'dnscache' truncates UDP
398 * replies at 512 octets, as per RFC 1035.
400 RFC1035_UNPACK_DEBUG
;
401 memset(RR
, '\0', sizeof(*RR
));
404 RR
->rdlength
= ntohs(s
);
406 case RFC1035_TYPE_PTR
:
407 RR
->rdata
= malloc(RFC1035_MAXHOSTNAMESZ
);
409 if (rfc1035NameUnpack(buf
, sz
, &rdata_off
, RR
->rdata
, RFC1035_MAXHOSTNAMESZ
, 0))
411 if (rdata_off
!= ((*off
) + RR
->rdlength
)) {
413 * This probably doesn't happen for valid packets, but
414 * I want to make sure that NameUnpack doesn't go beyond
417 RFC1035_UNPACK_DEBUG
;
418 memset(RR
, '\0', sizeof(*RR
));
424 RR
->rdata
= malloc(RR
->rdlength
);
425 memcpy(RR
->rdata
, buf
+ (*off
), RR
->rdlength
);
428 (*off
) += RR
->rdlength
;
429 assert((*off
) <= sz
);
433 static unsigned short
436 static unsigned short qid
= 0x0001;
443 rfc1035SetErrno(int n
)
445 switch (rfc1035_errno
= n
) {
447 rfc1035_error_message
= "No error condition";
450 rfc1035_error_message
= "Format Error: The name server was "
451 "unable to interpret the query.";
454 rfc1035_error_message
= "Server Failure: The name server was "
455 "unable to process this query.";
458 rfc1035_error_message
= "Name Error: The domain name does "
462 rfc1035_error_message
= "Not Implemented: The name server does "
463 "not support the requested kind of query.";
466 rfc1035_error_message
= "Refused: The name server refuses to "
467 "perform the specified operation.";
469 case rfc1035_unpack_error
:
470 rfc1035_error_message
= "The DNS reply message is corrupt or could "
471 "not be safely parsed.";
474 rfc1035_error_message
= "Unknown Error";
480 rfc1035RRDestroy(rfc1035_rr
* rr
, int n
)
493 * rfc1035AnswersUnpack()
495 * Takes the contents of a DNS reply and fills in an array
496 * of resource record structures. The records array is allocated
497 * here, and should be freed by calling rfc1035RRDestroy().
499 * Returns number of records unpacked, zero if DNS reply indicates
500 * zero answers, or an error number < 0.
504 rfc1035AnswersUnpack(const char *buf
,
506 rfc1035_rr
** records
,
515 memset(&hdr
, '\0', sizeof(hdr
));
516 if (rfc1035HeaderUnpack(buf
+ off
, sz
- off
, &off
, &hdr
)) {
517 RFC1035_UNPACK_DEBUG
;
518 rfc1035SetErrno(rfc1035_unpack_error
);
519 return -rfc1035_unpack_error
;
523 rfc1035_error_message
= NULL
;
525 RFC1035_UNPACK_DEBUG
;
526 rfc1035SetErrno((int) hdr
.rcode
);
527 return -rfc1035_errno
;
529 i
= (int) hdr
.qdcount
;
533 l
= (int) (unsigned char) *(buf
+ off
);
535 if (l
> 191) { /* compression */
538 } else if (l
> RFC1035_MAXLABELSZ
) {
539 /* illegal combination of compression bits */
540 RFC1035_UNPACK_DEBUG
;
541 rfc1035SetErrno(rfc1035_unpack_error
);
542 return -rfc1035_unpack_error
;
546 } while (l
> 0); /* a zero-length label terminates */
547 off
+= 4; /* qtype, qclass */
549 RFC1035_UNPACK_DEBUG
;
550 rfc1035SetErrno(rfc1035_unpack_error
);
551 return -rfc1035_unpack_error
;
554 i
= (int) hdr
.ancount
;
557 recs
= calloc(i
, sizeof(*recs
));
559 if (off
>= sz
) { /* corrupt packet */
560 RFC1035_UNPACK_DEBUG
;
563 if (rfc1035RRUnpack(buf
, sz
, &off
, &recs
[i
])) { /* corrupt RR */
564 RFC1035_UNPACK_DEBUG
;
571 * we expected to unpack some answers (ancount != 0), but
572 * didn't actually get any.
575 rfc1035SetErrno(rfc1035_unpack_error
);
576 return -rfc1035_unpack_error
;
583 * rfc1035BuildAQuery()
585 * Builds a message buffer with a QUESTION to lookup A records
586 * for a hostname. Caller must allocate 'buf' which should
587 * probably be at least 512 octets. The 'szp' initially
588 * specifies the size of the buffer, on return it contains
589 * the size of the message (i.e. how much to write).
590 * Return value is the query ID.
593 rfc1035BuildAQuery(const char *hostname
, char *buf
, size_t * szp
)
595 static rfc1035_header h
;
598 memset(&h
, '\0', sizeof(h
));
599 /* the first char of hostname must be alphanmeric */
600 if (NULL
== strchr(Alphanum
, *hostname
)) {
607 h
.opcode
= 0; /* QUERY */
608 h
.qdcount
= (unsigned int) 1;
609 offset
+= rfc1035HeaderPack(buf
+ offset
, sz
- offset
, &h
);
610 offset
+= rfc1035QuestionPack(buf
+ offset
,
615 assert(offset
<= sz
);
616 *szp
= (size_t) offset
;
621 * rfc1035BuildPTRQuery()
623 * Builds a message buffer with a QUESTION to lookup PTR records
624 * for an address. Caller must allocate 'buf' which should
625 * probably be at least 512 octets. The 'szp' initially
626 * specifies the size of the buffer, on return it contains
627 * the size of the message (i.e. how much to write).
628 * Return value is the query ID.
631 rfc1035BuildPTRQuery(const struct in_addr addr
, char *buf
, size_t * szp
)
633 static rfc1035_header h
;
638 memset(&h
, '\0', sizeof(h
));
639 i
= (unsigned int) ntohl(addr
.s_addr
);
640 snprintf(rev
, 32, "%u.%u.%u.%u.in-addr.arpa.",
648 h
.opcode
= 0; /* QUERY */
649 h
.qdcount
= (unsigned int) 1;
650 offset
+= rfc1035HeaderPack(buf
+ offset
, sz
- offset
, &h
);
651 offset
+= rfc1035QuestionPack(buf
+ offset
,
656 assert(offset
<= sz
);
662 * We're going to retry a former query, but we
663 * just need a new ID for it. Lucky for us ID
664 * is the first field in the message buffer.
667 rfc1035RetryQuery(char *buf
)
669 unsigned short qid
= rfc1035Qid();
670 unsigned short s
= htons(qid
);
671 memcpy(buf
, &s
, sizeof(s
));
676 #include <sys/socket.h>
677 #include <sys/time.h>
679 main(int argc
, char *argv
[])
688 struct sockaddr_in S
;
690 fprintf(stderr
, "usage: %s ip port\n", argv
[0]);
693 setbuf(stdout
, NULL
);
694 setbuf(stderr
, NULL
);
695 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
700 memset(&S
, '\0', sizeof(S
));
701 S
.sin_family
= AF_INET
;
702 S
.sin_port
= htons(atoi(argv
[2]));
703 S
.sin_addr
.s_addr
= inet_addr(argv
[1]);
704 while (fgets(input
, 512, stdin
)) {
706 strtok(input
, "\r\n");
707 memset(buf
, '\0', 512);
709 if (inet_aton(input
, &junk
)) {
710 sid
= rfc1035BuildPTRQuery(junk
, buf
, &sz
);
712 sid
= rfc1035BuildAQuery(input
, buf
, &sz
);
714 sendto(s
, buf
, sz
, 0, (struct sockaddr
*) &S
, sizeof(S
));
722 rl
= select(s
+ 1, &R
, NULL
, NULL
, &to
);
728 memset(rbuf
, '\0', 512);
729 rl
= recv(s
, rbuf
, 512, 0);
731 unsigned short rid
= 0;
734 rfc1035_rr
*answers
= NULL
;
735 n
= rfc1035AnswersUnpack(rbuf
,
740 printf("ERROR %d\n", rfc1035_errno
);
741 } else if (rid
!= sid
) {
742 printf("ERROR, ID mismatch (%#hx, %#hx)\n", sid
, rid
);
744 printf("%d answers\n", n
);
745 for (i
= 0; i
< n
; i
++) {
746 if (answers
[i
].type
== RFC1035_TYPE_A
) {
748 memcpy(&a
, answers
[i
].rdata
, 4);
749 printf("A\t%d\t%s\n", answers
[i
].ttl
, inet_ntoa(a
));
750 } else if (answers
[i
].type
== RFC1035_TYPE_PTR
) {
752 strncpy(ptr
, answers
[i
].rdata
, answers
[i
].rdlength
);
753 printf("PTR\t%d\t%s\n", answers
[i
].ttl
, ptr
);
755 fprintf(stderr
, "can't print answer type %d\n",
756 (int) answers
[i
].type
);