]> git.saurik.com Git - apple/libresolv.git/blob - dns_util.c
libresolv-65.tar.gz
[apple/libresolv.git] / dns_util.c
1 /*
2 * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <netdb.h>
30 #include <stdarg.h>
31 #include <sys/stat.h>
32 #include <sys/dir.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <ifaddrs.h>
37 #include <net/if.h>
38 #include <pthread.h>
39 #include <netinet/in.h>
40 #include <arpa/nameser.h>
41 #include <resolv.h>
42 #include "dns.h"
43 #include "dns_util.h"
44 #include "dns_private.h"
45 #include "res_private.h"
46
47 #define DNS_RESOLVER_DIR "/etc/resolver"
48
49 #define DNS_PRIVATE_HANDLE_TYPE_SUPER 0
50 #define DNS_PRIVATE_HANDLE_TYPE_PLAIN 1
51 #define DNS_DEFAULT_RECEIVE_SIZE 8192
52 #define DNS_MAX_RECEIVE_SIZE 65536
53
54 #define SDNS_DEFAULT_STAT_LATENCY 10
55
56 #define DNS_FLAGS_QR_MASK 0x8000
57 #define DNS_FLAGS_QR_QUERY 0x0000
58
59 #define DNS_FLAGS_OPCODE_MASK 0x7800
60
61 #define DNS_FLAGS_RCODE_MASK 0x000f
62
63 #define DNS_FLAGS_AA 0x0400
64 #define DNS_FLAGS_TC 0x0200
65 #define DNS_FLAGS_RD 0x0100
66 #define DNS_FLAGS_RA 0x0080
67
68 #define DNS_SOCK_UDP 0
69 #define DNS_SOCK_TCP_UNCONNECTED 1
70 #define DNS_SOCK_TCP_CONNECTED 2
71
72 #define INET_NTOP_AF_INET_OFFSET 4
73 #define INET_NTOP_AF_INET6_OFFSET 8
74
75 #define MAXPACKET 1024
76
77 extern void res_client_close(res_state res);
78 extern int __res_nquery(res_state statp, const char *name, int class, int type, u_char *answer, int anslen);
79 extern int dns_res_send(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz, struct sockaddr *from, int *fromlen);
80 extern void _check_cache(sdns_handle_t *sdns);
81 extern int _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, uint32_t recurse, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, int *min);
82 extern int _pdns_search(sdns_handle_t *sdns, pdns_handle_t *pdns, const char *name, uint32_t class, uint32_t type, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen);
83 static pthread_mutex_t _dnsPrintLock = PTHREAD_MUTEX_INITIALIZER;
84
85 static void
86 _dns_print_lock(void)
87 {
88 pthread_mutex_lock(&_dnsPrintLock);
89 }
90
91 static void
92 _dns_print_unlock(void)
93 {
94 pthread_mutex_unlock(&_dnsPrintLock);
95 }
96
97
98 static uint8_t
99 _dns_parse_uint8(char **p)
100 {
101 uint8_t v;
102
103 v = (uint8_t)**p;
104 *p += 1;
105 return v;
106 }
107
108 static uint16_t
109 _dns_parse_uint16(char **p)
110 {
111 uint16_t *x, v;
112
113 x = (uint16_t *)*p;
114 v = ntohs(*x);
115 *p += 2;
116 return v;
117 }
118
119 static uint32_t
120 _dns_parse_uint32(char **p)
121 {
122 uint32_t *x, v;
123
124 x = (uint32_t *)*p;
125 v = ntohl(*x);
126 *p += 4;
127 return v;
128 }
129
130 static uint8_t
131 _dns_cname_length(char *s)
132 {
133 uint8_t l;
134
135 if (s == NULL) return 1;
136 l = strlen(s);
137 while ((s[l - 1] == '.') && (l > 1)) l--;
138 return l;
139 }
140
141 static void
142 _dns_insert_cname(char *s, char *p)
143 {
144 int i;
145 uint8_t len, dlen;
146
147 if (s == NULL)
148 {
149 *p = 0;
150 return;
151 }
152
153 if (!strcmp(s, "."))
154 {
155 p[0] = 1;
156 p[1] = '.';
157 p[2] = 0;
158 return;
159 }
160
161 len = _dns_cname_length(s);
162
163 p[0] = '.';
164 memmove(p + 1, s, len);
165 p[len + 1] = '.';
166
167 dlen = 0;
168
169 for (i = len + 1; i >= 0; i--)
170 {
171 if (p[i] == '.')
172 {
173 p[i] = dlen;
174 dlen = 0;
175 }
176 else dlen++;
177 }
178 }
179
180 static char *
181 _dns_parse_string(const char *p, char **x, int32_t *remaining)
182 {
183 char *str;
184 uint8_t len;
185
186 if (*remaining < 1) return NULL;
187 *remaining -= 1;
188
189 len = (uint8_t)**x;
190 *x += 1;
191
192 if (*remaining < len) return NULL;
193 *remaining -= len;
194
195 str = malloc(len + 1);
196 memmove(str, *x, len);
197 str[len] = '\0';
198 *x += len;
199
200 return str;
201 }
202
203 static char *
204 _dns_parse_domain_name(const char *p, char **x, int32_t *remaining)
205 {
206 uint8_t *v8;
207 uint16_t *v16, skip;
208 uint16_t i, j, dlen, len;
209 int more, compressed;
210 char *name, *start, *y, *z;
211
212 if (*remaining < 1) return NULL;
213
214 z = *x + *remaining;
215 start = *x;
216 compressed = 0;
217 more = 1;
218 name = malloc(1);
219 name[0] = '\0';
220 len = 1;
221 j = 0;
222 skip = 0;
223
224 while (more == 1)
225 {
226 if ((*x + 1) > z)
227 {
228 free(name);
229 return NULL;
230 }
231
232 v8 = (uint8_t *)*x;
233 dlen = *v8;
234
235 if ((dlen & 0xc0) == 0xc0)
236 {
237 if ((*x + 2) > z)
238 {
239 free(name);
240 return NULL;
241 }
242
243 v16 = (uint16_t *)*x;
244
245 y = (char *)p + (ntohs(*v16) & 0x3fff);
246 if ((*x == y) || (y > z))
247 {
248 free(name);
249 return NULL;
250 }
251
252 *x = y;
253 if (compressed == 0) skip += 2;
254 compressed = 1;
255 continue;
256 }
257
258 if ((*x + 1) > z)
259 {
260 free(name);
261 return NULL;
262 }
263
264 *x += 1;
265
266 if (dlen > 0)
267 {
268 len += dlen;
269 name = realloc(name, len);
270 }
271
272 if ((*x + dlen) > z)
273 {
274 free(name);
275 return NULL;
276 }
277
278 for (i = 0; i < dlen; i++)
279 {
280 name[j++] = **x;
281 *x += 1;
282 }
283
284 name[j] = '\0';
285 if (compressed == 0) skip += (dlen + 1);
286
287 if (dlen == 0) more = 0;
288 else
289 {
290 if ((*x + 1) > z)
291 {
292 free(name);
293 return NULL;
294 }
295
296 v8 = (uint8_t *)*x;
297 if (*v8 != 0)
298 {
299 len += 1;
300 name = realloc(name, len);
301 name[j++] = '.';
302 name[j] = '\0';
303 }
304 }
305 }
306
307 if ((start + skip) > z)
308 {
309 free(name);
310 return NULL;
311 }
312
313 *x = start + skip;
314 *remaining -= skip;
315
316 return name;
317 }
318
319 dns_resource_record_t *
320 _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining)
321 {
322 uint32_t size, bx, mi;
323 uint16_t rdlen;
324 uint8_t byte, i;
325 dns_resource_record_t *r;
326 char *eor;
327
328 if (*remaining < 1) return NULL;
329
330 r = (dns_resource_record_t *)calloc(1, sizeof(dns_resource_record_t));
331
332 r->name = _dns_parse_domain_name(p, x, remaining);
333 if (r->name == NULL)
334 {
335 dns_free_resource_record(r);
336 return NULL;
337 }
338
339 if (*remaining < 10)
340 {
341 dns_free_resource_record(r);
342 return NULL;
343 }
344
345 r->dnstype = _dns_parse_uint16(x);
346 r->dnsclass = _dns_parse_uint16(x);
347 r->ttl = _dns_parse_uint32(x);
348 rdlen = _dns_parse_uint16(x);
349
350 *remaining -= 10;
351
352 if (*remaining < rdlen)
353 {
354 dns_free_resource_record(r);
355 return NULL;
356 }
357
358 eor = *x;
359 r->data.A = NULL;
360
361 switch (r->dnstype)
362 {
363 case ns_t_a:
364 if (*remaining < 4)
365 {
366 dns_free_resource_record(r);
367 return NULL;
368 }
369
370 *remaining -= 4;
371
372 size = sizeof(dns_address_record_t);
373 r->data.A = (dns_address_record_t *)calloc(1, size);
374 r->data.A->addr.s_addr = htonl(_dns_parse_uint32(x));
375 break;
376
377 case ns_t_aaaa:
378 if (*remaining < 16)
379 {
380 dns_free_resource_record(r);
381 return NULL;
382 }
383
384 *remaining -= 16;
385
386 size = sizeof(dns_in6_address_record_t);
387 r->data.AAAA = (dns_in6_address_record_t *)calloc(1, size);
388 r->data.AAAA->addr.__u6_addr.__u6_addr32[0] = htonl(_dns_parse_uint32(x));
389 r->data.AAAA->addr.__u6_addr.__u6_addr32[1] = htonl(_dns_parse_uint32(x));
390 r->data.AAAA->addr.__u6_addr.__u6_addr32[2] = htonl(_dns_parse_uint32(x));
391 r->data.AAAA->addr.__u6_addr.__u6_addr32[3] = htonl(_dns_parse_uint32(x));
392 break;
393
394 case ns_t_ns:
395 case ns_t_md:
396 case ns_t_mf:
397 case ns_t_cname:
398 case ns_t_mb:
399 case ns_t_mg:
400 case ns_t_mr:
401 case ns_t_ptr:
402 size = sizeof(dns_domain_name_record_t);
403 r->data.CNAME = (dns_domain_name_record_t *)calloc(1,size);
404 r->data.CNAME->name = _dns_parse_domain_name(p, x, remaining);
405 if (r->data.CNAME->name == NULL)
406 {
407 dns_free_resource_record(r);
408 return NULL;
409 }
410 break;
411
412 case ns_t_soa:
413 size = sizeof(dns_SOA_record_t);
414 r->data.SOA = (dns_SOA_record_t *)calloc(1, size);
415
416 r->data.SOA->mname = _dns_parse_domain_name(p, x, remaining);
417 if (r->data.SOA->mname == NULL)
418 {
419 dns_free_resource_record(r);
420 return NULL;
421 }
422
423 r->data.SOA->rname = _dns_parse_domain_name(p, x, remaining);
424 if (r->data.SOA->rname == NULL)
425 {
426 dns_free_resource_record(r);
427 return NULL;
428 }
429
430 if (*remaining < 20)
431 {
432 dns_free_resource_record(r);
433 return NULL;
434 }
435
436 *remaining -= 20;
437
438 r->data.SOA->serial = _dns_parse_uint32(x);
439 r->data.SOA->refresh = _dns_parse_uint32(x);
440 r->data.SOA->retry = _dns_parse_uint32(x);
441 r->data.SOA->expire = _dns_parse_uint32(x);
442 r->data.SOA->minimum = _dns_parse_uint32(x);
443 break;
444
445 case ns_t_wks:
446 if (*remaining < 5)
447 {
448 dns_free_resource_record(r);
449 return NULL;
450 }
451
452 *remaining -= rdlen;
453
454 size = sizeof(dns_WKS_record_t);
455 r->data.WKS = (dns_WKS_record_t *)calloc(1, size);
456
457 r->data.WKS->addr.s_addr = htonl(_dns_parse_uint32(x));
458 r->data.WKS->protocol = _dns_parse_uint8(x);
459 size = rdlen - 5;
460 r->data.WKS->maplength = size * 8;
461 r->data.WKS->map = NULL;
462 if (size == 0) break;
463
464 r->data.WKS->map = (uint8_t *)calloc(1, r->data.WKS->maplength);
465 mi = 0;
466 for (bx = 0; bx < size; bx++)
467 {
468 byte = _dns_parse_uint8(x);
469 for (i = 128; i >= 1; i = i/2)
470 {
471 if (byte & i) r->data.WKS->map[mi] = 0xff;
472 else r->data.WKS->map[mi] = 0;
473 mi++;
474 }
475 }
476 break;
477
478 case ns_t_hinfo:
479 size = sizeof(dns_HINFO_record_t);
480 r->data.HINFO = (dns_HINFO_record_t *)calloc(1, size);
481
482 r->data.HINFO->cpu = _dns_parse_string(p, x, remaining);
483 if (r->data.HINFO->cpu == NULL)
484 {
485 dns_free_resource_record(r);
486 return NULL;
487 }
488
489 r->data.HINFO->os = _dns_parse_string(p, x, remaining);
490 if (r->data.HINFO->os == NULL)
491 {
492 dns_free_resource_record(r);
493 return NULL;
494 }
495
496 break;
497
498 case ns_t_minfo:
499 size = sizeof(dns_MINFO_record_t);
500 r->data.MINFO = (dns_MINFO_record_t *)calloc(1, size);
501
502 r->data.MINFO->rmailbx = _dns_parse_domain_name(p, x, remaining);
503 if (r->data.MINFO->rmailbx == NULL)
504 {
505 dns_free_resource_record(r);
506 return NULL;
507 }
508
509 r->data.MINFO->emailbx = _dns_parse_domain_name(p, x, remaining);
510 if (r->data.MINFO->emailbx == NULL)
511 {
512 dns_free_resource_record(r);
513 return NULL;
514 }
515
516 break;
517
518 case ns_t_mx:
519 if (*remaining < 2)
520 {
521 dns_free_resource_record(r);
522 return NULL;
523 }
524
525 *remaining -= 2;
526
527 size = sizeof(dns_MX_record_t);
528 r->data.MX = (dns_MX_record_t *)calloc(1, size);
529
530 r->data.MX->preference = _dns_parse_uint16(x);
531 r->data.MX->name = _dns_parse_domain_name(p, x, remaining);
532 if (r->data.MX->name == NULL)
533 {
534 dns_free_resource_record(r);
535 return NULL;
536 }
537
538 break;
539
540 case ns_t_txt:
541 size = sizeof(dns_TXT_record_t);
542 r->data.TXT = (dns_TXT_record_t *)malloc(size);
543 r->data.TXT->string_count = 0;
544 r->data.TXT->strings = NULL;
545
546 while (*x < (eor + rdlen))
547 {
548 if (r->data.TXT->string_count == 0)
549 {
550 r->data.TXT->strings = (char **)calloc(1, sizeof(char *));
551 }
552 else
553 {
554 r->data.TXT->strings = (char **)realloc(r->data.TXT->strings, (r->data.TXT->string_count + 1) * sizeof(char *));
555 }
556
557 r->data.TXT->strings[r->data.TXT->string_count] = _dns_parse_string(p, x, remaining);
558 if (r->data.TXT->strings[r->data.TXT->string_count] == NULL)
559 {
560 dns_free_resource_record(r);
561 return NULL;
562 }
563 r->data.TXT->string_count++;
564 }
565
566 break;
567
568 case ns_t_rp:
569 size = sizeof(dns_RP_record_t);
570 r->data.RP = (dns_RP_record_t *)calloc(1, size);
571
572 r->data.RP->mailbox = _dns_parse_domain_name(p, x, remaining);
573 if (r->data.RP->mailbox == NULL)
574 {
575 dns_free_resource_record(r);
576 return NULL;
577 }
578
579 r->data.RP->txtdname = _dns_parse_domain_name(p, x, remaining);
580 if (r->data.RP->txtdname == NULL)
581 {
582 dns_free_resource_record(r);
583 return NULL;
584 }
585
586 break;
587
588 case ns_t_afsdb:
589 if (*remaining < 4)
590 {
591 dns_free_resource_record(r);
592 return NULL;
593 }
594
595 *remaining -= 4;
596 size = sizeof(dns_AFSDB_record_t);
597 r->data.AFSDB = (dns_AFSDB_record_t *)calloc(1, size);
598
599 r->data.AFSDB->subtype = _dns_parse_uint32(x);
600 r->data.AFSDB->hostname = _dns_parse_domain_name(p, x, remaining);
601 if (r->data.AFSDB->hostname == NULL)
602 {
603 dns_free_resource_record(r);
604 return NULL;
605 }
606
607 break;
608
609 case ns_t_x25:
610 size = sizeof(dns_X25_record_t);
611 r->data.X25 = (dns_X25_record_t *)calloc(1, size);
612
613 r->data.X25->psdn_address = _dns_parse_string(p, x, remaining);
614 if (r->data.X25->psdn_address == NULL)
615 {
616 dns_free_resource_record(r);
617 return NULL;
618 }
619
620 break;
621
622 case ns_t_isdn:
623 size = sizeof(dns_ISDN_record_t);
624 r->data.ISDN = (dns_ISDN_record_t *)calloc(1, size);
625
626 r->data.ISDN->isdn_address = _dns_parse_string(p, x, remaining);
627 if (r->data.ISDN->isdn_address == NULL)
628 {
629 dns_free_resource_record(r);
630 return NULL;
631 }
632
633 if (*x < (eor + rdlen))
634 {
635 r->data.ISDN->subaddress = _dns_parse_string(p, x, remaining);
636 if (r->data.ISDN->subaddress == NULL)
637 {
638 dns_free_resource_record(r);
639 return NULL;
640 }
641 }
642 else
643 {
644 r->data.ISDN->subaddress = NULL;
645 }
646
647 break;
648
649 case ns_t_rt:
650 if (*remaining < 2)
651 {
652 dns_free_resource_record(r);
653 return NULL;
654 }
655
656 *remaining -= 2;
657
658 size = sizeof(dns_RT_record_t);
659 r->data.RT = (dns_RT_record_t *)calloc(1, size);
660
661 r->data.RT->preference = _dns_parse_uint16(x);
662 r->data.RT->intermediate = _dns_parse_domain_name(p, x, remaining);
663 if (r->data.RT->intermediate == NULL)
664 {
665 dns_free_resource_record(r);
666 return NULL;
667 }
668
669 break;
670
671 case ns_t_loc:
672 if (*remaining < 16)
673 {
674 dns_free_resource_record(r);
675 return NULL;
676 }
677
678 *remaining -= 16;
679
680 size = sizeof(dns_LOC_record_t);
681 r->data.LOC = (dns_LOC_record_t *)calloc(1, size);
682
683 r->data.LOC->version = _dns_parse_uint8(x);
684 r->data.LOC->size = _dns_parse_uint8(x);
685 r->data.LOC->horizontal_precision = _dns_parse_uint8(x);
686 r->data.LOC->vertical_precision = _dns_parse_uint8(x);
687 r->data.LOC->latitude = _dns_parse_uint32(x);
688 r->data.LOC->longitude = _dns_parse_uint32(x);
689 r->data.LOC->altitude = _dns_parse_uint32(x);
690 break;
691
692 case ns_t_srv:
693 if (*remaining < 6)
694 {
695 dns_free_resource_record(r);
696 return NULL;
697 }
698
699 *remaining -= 6;
700
701 size = sizeof(dns_SRV_record_t);
702 r->data.SRV = (dns_SRV_record_t *)calloc(1, size);
703
704 r->data.SRV->priority = _dns_parse_uint16(x);
705 r->data.SRV->weight = _dns_parse_uint16(x);
706 r->data.SRV->port = _dns_parse_uint16(x);
707 r->data.SRV->target = _dns_parse_domain_name(p, x, remaining);
708 if (r->data.SRV->target == NULL)
709 {
710 dns_free_resource_record(r);
711 return NULL;
712 }
713
714 break;
715
716 case ns_t_null:
717 default:
718 *remaining -= rdlen;
719
720 size = sizeof(dns_raw_resource_record_t);
721 r->data.DNSNULL = (dns_raw_resource_record_t *)calloc(1, size);
722
723 r->data.DNSNULL->length = rdlen;
724 r->data.DNSNULL->data = calloc(1, rdlen);
725 memmove(r->data.DNSNULL->data, *x, rdlen);
726 *x += rdlen;
727 break;
728 }
729
730 *x = eor + rdlen;
731 return r;
732 }
733
734 dns_resource_record_t *
735 dns_parse_resource_record(const char *buf, uint32_t len)
736 {
737 char *x;
738 int32_t remaining;
739
740 remaining = len;
741 x = (char *)buf;
742 return _dns_parse_resource_record_internal(buf, &x, &remaining);
743 }
744
745 dns_question_t *
746 _dns_parse_question_internal(const char *p, char **x, int32_t *remaining)
747 {
748 dns_question_t *q;
749
750 if (x == NULL) return NULL;
751 if (*x == NULL) return NULL;
752 if (*remaining < 1) return NULL;
753
754 q = (dns_question_t *)calloc(1, sizeof(dns_question_t));
755
756 q->name = _dns_parse_domain_name(p, x, remaining);
757 if (q->name == NULL)
758 {
759 free(q);
760 return NULL;
761 }
762
763 if (*remaining < 4)
764 {
765 free(q->name);
766 free(q);
767 return NULL;
768 }
769
770 *remaining = *remaining - 4;
771
772 q->dnstype = _dns_parse_uint16(x);
773 q->dnsclass = _dns_parse_uint16(x);
774
775 return q;
776 }
777
778 dns_question_t *
779 dns_parse_question(const char *buf, uint32_t len)
780 {
781 char *x;
782 int32_t remaining;
783
784 remaining = len;
785 x = (char *)buf;
786 return _dns_parse_question_internal(buf, &x, &remaining);
787 }
788
789
790 dns_reply_t *
791 dns_parse_packet(const char *p, uint32_t len)
792 {
793 dns_reply_t *r;
794 dns_header_t *h;
795 char *x;
796 uint32_t i, size;
797 int32_t remaining;
798
799 if (p == NULL) return NULL;
800 if (len < NS_HFIXEDSZ) return NULL;
801
802 x = (char *)p;
803
804 r = (dns_reply_t *)calloc(1, sizeof(dns_reply_t));
805
806 r->header = (dns_header_t *)calloc(1, sizeof(dns_header_t));
807 h = r->header;
808
809 h->xid = _dns_parse_uint16(&x);
810 h->flags = _dns_parse_uint16(&x);
811 h->qdcount = _dns_parse_uint16(&x);
812 h->ancount = _dns_parse_uint16(&x);
813 h->nscount = _dns_parse_uint16(&x);
814 h->arcount = _dns_parse_uint16(&x);
815
816 remaining = len - NS_HFIXEDSZ;
817
818 size = sizeof(dns_question_t *);
819 r->question = (dns_question_t **)calloc(h->qdcount, size);
820 for (i = 0; i < h->qdcount; i++)
821 {
822 r->question[i] = _dns_parse_question_internal(p, &x, &remaining);
823 if (r->question[i] ==NULL)
824 {
825 h->qdcount = 0;
826 if (i > 0) h->qdcount = i - 1;
827 h->ancount = 0;
828 h->nscount = 0;
829 h->arcount = 0;
830 dns_free_reply(r);
831 return NULL;
832 }
833 }
834
835 size = sizeof(dns_resource_record_t *);
836
837 r->answer = (dns_resource_record_t **)calloc(h->ancount, size);
838 for (i = 0; i < h->ancount; i++)
839 {
840 r->answer[i] = _dns_parse_resource_record_internal(p, &x, &remaining);
841 if (r->answer[i] == NULL)
842 {
843 h->ancount = 0;
844 if (i > 0) h->ancount = i - 1;
845 h->nscount = 0;
846 h->arcount = 0;
847 dns_free_reply(r);
848 return NULL;
849 }
850 }
851
852 r->authority = (dns_resource_record_t **)calloc(h->nscount, size);
853 for (i = 0; i < h->nscount; i++)
854 {
855 r->authority[i] = _dns_parse_resource_record_internal(p, &x, &remaining);
856 if (r->authority[i] == NULL)
857 {
858 h->nscount = 0;
859 if (i > 0) h->nscount = i - 1;
860 h->arcount = 0;
861 dns_free_reply(r);
862 return NULL;
863 }
864 }
865
866 r->additional = (dns_resource_record_t **)calloc(h->arcount, size);
867 for (i = 0; i < h->arcount; i++)
868 {
869 r->additional[i] = _dns_parse_resource_record_internal(p, &x, &remaining);
870 if (r->additional[i] == NULL)
871 {
872 h->arcount = 0;
873 if (i > 0) h->arcount = i - 1;
874 dns_free_reply(r);
875 return NULL;
876 }
877 }
878
879 return r;
880 }
881
882 void
883 dns_free_resource_record(dns_resource_record_t *r)
884 {
885 int i;
886
887 free(r->name);
888
889 switch (r->dnstype)
890 {
891 case ns_t_a:
892 if (r->data.A != NULL) free(r->data.A);
893 break;
894
895 case ns_t_aaaa:
896 if (r->data.AAAA != NULL) free(r->data.AAAA);
897 break;
898
899 case ns_t_ns:
900 case ns_t_md:
901 case ns_t_mf:
902 case ns_t_cname:
903 case ns_t_mb:
904 case ns_t_mg:
905 case ns_t_mr:
906 case ns_t_ptr:
907 if (r->data.CNAME != NULL)
908 {
909 if (r->data.CNAME->name != NULL) free(r->data.CNAME->name);
910 free(r->data.CNAME);
911 }
912 break;
913
914 case ns_t_soa:
915 if (r->data.SOA != NULL)
916 {
917 if (r->data.SOA->mname != NULL) free(r->data.SOA->mname);
918 if (r->data.SOA->rname != NULL) free(r->data.SOA->rname);
919 free(r->data.SOA);
920 }
921 break;
922
923 case ns_t_wks:
924 if (r->data.WKS != NULL)
925 {
926 if (r->data.WKS->map != NULL) free(r->data.WKS->map);
927 free(r->data.WKS);
928 }
929 break;
930
931 case ns_t_hinfo:
932 if (r->data.HINFO != NULL)
933 {
934 if (r->data.HINFO->cpu != NULL) free(r->data.HINFO->cpu);
935 if (r->data.HINFO->os != NULL) free(r->data.HINFO->os);
936 free(r->data.HINFO);
937 }
938 break;
939
940 case ns_t_minfo:
941 if (r->data.MINFO != NULL)
942 {
943 if (r->data.MINFO->rmailbx != NULL) free(r->data.MINFO->rmailbx);
944 if (r->data.MINFO->emailbx != NULL) free(r->data.MINFO->emailbx);
945 free(r->data.MINFO);
946 }
947 break;
948
949 case ns_t_mx:
950 if (r->data.MX != NULL)
951 {
952 if (r->data.MX->name != NULL) free(r->data.MX->name);
953 free(r->data.MX);
954 }
955 break;
956
957
958 case ns_t_txt:
959 if (r->data.TXT != NULL)
960 {
961 for (i = 0; i < r->data.TXT->string_count; i++) free(r->data.TXT->strings[i]);
962 if (r->data.TXT->strings != NULL) free(r->data.TXT->strings);
963 free(r->data.TXT);
964 }
965 break;
966
967 case ns_t_rp:
968 if (r->data.RP != NULL)
969 {
970 if (r->data.RP->mailbox != NULL) free(r->data.RP->mailbox);
971 if (r->data.RP->txtdname != NULL) free(r->data.RP->txtdname);
972 free(r->data.RP);
973 }
974 break;
975
976 case ns_t_afsdb:
977 if (r->data.AFSDB != NULL)
978 {
979 if (r->data.AFSDB->hostname != NULL) free(r->data.AFSDB->hostname);
980 free(r->data.AFSDB);
981 }
982 break;
983
984 case ns_t_x25:
985 if (r->data.X25 != NULL)
986 {
987 if (r->data.X25->psdn_address != NULL) free(r->data.X25->psdn_address);
988 free(r->data.X25);
989 }
990 break;
991
992 case ns_t_isdn:
993 if (r->data.ISDN != NULL)
994 {
995 if (r->data.ISDN->isdn_address != NULL) free(r->data.ISDN->isdn_address);
996 if (r->data.ISDN->subaddress != NULL) free(r->data.ISDN->subaddress);
997 free(r->data.ISDN);
998 }
999 break;
1000
1001 case ns_t_rt:
1002 if (r->data.RT != NULL)
1003 {
1004 if (r->data.RT->intermediate != NULL) free(r->data.RT->intermediate);
1005 free(r->data.RT);
1006 }
1007 break;
1008
1009 case ns_t_loc:
1010 if (r->data.LOC != NULL) free(r->data.LOC);
1011 break;
1012
1013 case ns_t_srv:
1014 if (r->data.SRV != NULL)
1015 {
1016 if (r->data.SRV->target != NULL) free(r->data.SRV->target);
1017 free(r->data.SRV);
1018 }
1019 break;
1020
1021 case ns_t_invalid:
1022 break;
1023
1024 case ns_t_null:
1025 default:
1026 if (r->data.DNSNULL != NULL)
1027 {
1028 if (r->data.DNSNULL->data != NULL) free(r->data.DNSNULL->data);
1029 free(r->data.DNSNULL);
1030 }
1031 break;
1032 }
1033
1034 free(r);
1035 }
1036
1037 void
1038 dns_free_reply(dns_reply_t *r)
1039 {
1040 uint32_t i;
1041
1042 if (r == NULL) return;
1043 if (r->header != NULL)
1044 {
1045 for (i = 0; i < r->header->qdcount; i++)
1046 {
1047 free(r->question[i]->name);
1048 free(r->question[i]);
1049 }
1050
1051 for (i = 0; i < r->header->ancount; i++) dns_free_resource_record(r->answer[i]);
1052 for (i = 0; i < r->header->nscount; i++) dns_free_resource_record(r->authority[i]);
1053 for (i = 0; i < r->header->arcount; i++) dns_free_resource_record(r->additional[i]);
1054
1055 free(r->header);
1056 }
1057
1058 if (r->question != NULL) free(r->question);
1059 if (r->answer != NULL) free(r->answer);
1060 if (r->authority != NULL) free(r->authority);
1061 if (r->additional != NULL) free(r->additional);
1062
1063 if (r->server != NULL) free(r->server);
1064
1065 free(r);
1066 }
1067
1068 static void
1069 _dns_append_question(dns_question_t *q, char **s, uint16_t *l)
1070 {
1071 uint16_t len, *p;
1072 char *x;
1073
1074 if (q == NULL) return;
1075
1076 len = *l + _dns_cname_length(q->name) + 2 + 4;
1077 *s = realloc(*s, len);
1078
1079 _dns_insert_cname(q->name, (char *)*s + *l);
1080 *l = len;
1081
1082 x = *s + (len - 4);
1083
1084 p = (uint16_t *)x;
1085 *p = htons(q->dnstype);
1086 x += 2;
1087
1088 p = (uint16_t *)x;
1089 *p = htons(q->dnsclass);
1090
1091 }
1092
1093 static void
1094 _dns_append_resource_record(dns_resource_record_t *r, char **s, uint16_t *l)
1095 {
1096 uint16_t clen, len, *p, extra, rdlen;
1097 uint32_t *p2;
1098 char *x;
1099
1100 if (r == NULL) return;
1101
1102 extra = 10;
1103 switch (r->dnstype)
1104 {
1105 case ns_t_a:
1106 extra += 4;
1107 break;
1108 case ns_t_ptr:
1109 extra += 2;
1110 clen = _dns_cname_length(r->data.PTR->name);
1111 extra += clen;
1112 break;
1113 default: break;
1114 }
1115
1116 len = *l + _dns_cname_length(r->name) + 2 + extra;
1117 *s = realloc(*s, len);
1118
1119 _dns_insert_cname(r->name, (char *)*s + *l);
1120 *l = len;
1121
1122 x = *s + (len - extra);
1123
1124 p = (uint16_t *)x;
1125 *p = htons(r->dnstype);
1126 x += 2;
1127
1128 p = (uint16_t *)x;
1129 *p = htons(r->dnsclass);
1130 x += 2;
1131
1132 p2 = (uint32_t *)x;
1133 *p2 = htonl(r->ttl);
1134 x += 4;
1135
1136 switch (r->dnstype)
1137 {
1138 case ns_t_a:
1139 rdlen = 4;
1140 p = (uint16_t *)x;
1141 *p = htons(rdlen);
1142 x += 2;
1143
1144 p2 = (uint32_t *)x;
1145 *p2 = htons(r->data.A->addr.s_addr);
1146 x += 4;
1147 return;
1148
1149 case ns_t_ptr:
1150 clen = _dns_cname_length(r->data.PTR->name) + 2;
1151 p = (uint16_t *)x;
1152 *p = htons(clen);
1153 x += 2;
1154 _dns_insert_cname(r->data.PTR->name, x);
1155 x += clen;
1156 return;
1157
1158 default: return;
1159 }
1160 }
1161
1162 char *
1163 dns_build_reply(dns_reply_t *dnsr, uint16_t *rl)
1164 {
1165 uint16_t i, len;
1166 dns_header_t *h;
1167 char *s, *x;
1168
1169 if (dnsr == NULL) return NULL;
1170
1171 len = NS_HFIXEDSZ;
1172
1173 s = malloc(len);
1174 x = s + len;
1175
1176 memset(s, 0, len);
1177 *rl = len;
1178
1179 h = (dns_header_t *)s;
1180
1181 h->xid = htons(dnsr->header->xid);
1182 h->flags = htons(dnsr->header->flags);
1183 h->qdcount = htons(dnsr->header->qdcount);
1184 h->ancount = htons(dnsr->header->ancount);
1185 h->nscount = htons(dnsr->header->nscount);
1186 h->arcount = htons(dnsr->header->arcount);
1187
1188 for (i = 0; i < dnsr->header->qdcount; i++)
1189 {
1190 _dns_append_question(dnsr->question[i], &s, rl);
1191 }
1192
1193 for (i = 0; i < dnsr->header->ancount; i++)
1194 {
1195 _dns_append_resource_record(dnsr->answer[i], &s, rl);
1196 }
1197
1198 for (i = 0; i < dnsr->header->nscount; i++)
1199 {
1200 _dns_append_resource_record(dnsr->authority[i], &s, rl);
1201 }
1202
1203 for (i = 0; i < dnsr->header->arcount; i++)
1204 {
1205 _dns_append_resource_record(dnsr->additional[i], &s, rl);
1206 }
1207
1208 return s;
1209 }
1210
1211 void
1212 dns_free_question(dns_question_t *q)
1213 {
1214 if (q == NULL) return;
1215 if (q->name != NULL) free(q->name);
1216 free(q);
1217 }
1218
1219 void
1220 dns_set_buffer_size(dns_handle_t d, uint32_t len)
1221 {
1222 dns_private_handle_t *dns;
1223 if (d == NULL) return;
1224
1225 dns = (dns_private_handle_t *)d;
1226 if (dns->recvsize == len) return;
1227
1228 if (dns->recvbuf != NULL)
1229 {
1230 free(dns->recvbuf);
1231 dns->recvbuf = NULL;
1232 }
1233
1234 dns->recvsize = len;
1235 if (dns->recvsize > DNS_MAX_RECEIVE_SIZE) dns->recvsize = DNS_MAX_RECEIVE_SIZE;
1236
1237 if (dns->recvsize > 0) dns->recvbuf = malloc(dns->recvsize);
1238 }
1239
1240 uint32_t
1241 dns_get_buffer_size(dns_handle_t d)
1242 {
1243 dns_private_handle_t *dns;
1244 if (d == NULL) return 0;
1245
1246 dns = (dns_private_handle_t *)d;
1247 return dns->recvsize;
1248 }
1249
1250 dns_reply_t *
1251 dns_lookup_soa_min(dns_handle_t d, const char *name, uint32_t class, uint32_t type, int *min)
1252 {
1253 dns_private_handle_t *dns;
1254 dns_reply_t *r;
1255 int len;
1256 struct sockaddr_storage *from;
1257 uint32_t fromlen;
1258
1259 if (d == NULL) return NULL;
1260 if (name == NULL) return NULL;
1261
1262 dns = (dns_private_handle_t *)d;
1263 if (min != NULL) *min = -1;
1264
1265 if (dns->recvbuf == NULL)
1266 {
1267 if (dns->recvsize == 0) dns->recvsize = DNS_DEFAULT_RECEIVE_SIZE;
1268
1269 dns->recvbuf = malloc(dns->recvsize);
1270 if (dns->recvbuf == NULL) return NULL;
1271 }
1272
1273 fromlen = sizeof(struct sockaddr_storage);
1274 from = (struct sockaddr_storage *)calloc(1, sizeof(struct sockaddr_storage));
1275 len = -1;
1276
1277 if (dns->handle_type == DNS_PRIVATE_HANDLE_TYPE_SUPER)
1278 {
1279 _check_cache(dns->sdns);
1280 len = _sdns_search(dns->sdns, name, class, type, 0, 1, dns->recvbuf, dns->recvsize, (struct sockaddr *)from, &fromlen, min);
1281 }
1282 else
1283 {
1284 /* NB. Minumium SOA TTL values are NOT provided when the caller passes a DNS_PRIVATE_HANDLE_TYPE_PLAIN handle */
1285 len = _pdns_search(dns->sdns, dns->pdns, name, class, type, dns->recvbuf, dns->recvsize, (struct sockaddr *)from, &fromlen);
1286 }
1287
1288 if (len <= 0)
1289 {
1290 free(from);
1291 return NULL;
1292 }
1293
1294 r = dns_parse_packet(dns->recvbuf, len);
1295
1296 if (r == NULL) free(from);
1297 else r->server = (struct sockaddr *)from;
1298
1299 return r;
1300 }
1301
1302 dns_reply_t *
1303 dns_lookup(dns_handle_t d, const char *name, uint32_t class, uint32_t type)
1304 {
1305 int unused = 0;
1306
1307 return dns_lookup_soa_min(d, name, class, type, &unused);
1308 }
1309
1310 /*
1311 * DNS printing utilities
1312 */
1313
1314 static char *
1315 coord_ntoa(int32_t coord, uint32_t islat)
1316 {
1317 int32_t deg, min, sec, secfrac;
1318 static char buf[64];
1319 char dir;
1320
1321 coord = coord - 0x80000000;
1322 dir = 'N';
1323
1324 if ((islat == 1) && (coord < 0))
1325 {
1326 dir = 'S';
1327 coord = -coord;
1328 }
1329
1330 if (islat == 0)
1331 {
1332 dir = 'E';
1333 if (coord < 0)
1334 {
1335 dir = 'W';
1336 coord = -coord;
1337 }
1338 }
1339
1340 secfrac = coord % 1000;
1341 coord = coord / 1000;
1342 sec = coord % 60;
1343 coord = coord / 60;
1344 min = coord % 60;
1345 coord = coord / 60;
1346 deg = coord;
1347
1348 sprintf(buf, "%d %.2d %.2d.%.3d %c", deg, min, sec, secfrac, dir);
1349 return buf;
1350 }
1351
1352 static char *
1353 alt_ntoa(int32_t alt)
1354 {
1355 int32_t ref, m, frac, sign;
1356 static char buf[128];
1357
1358 ref = 100000 * 100;
1359 sign = 1;
1360
1361 if (alt < ref)
1362 {
1363 alt = ref - alt;
1364 sign = -1;
1365 }
1366 else
1367 {
1368 alt = alt - ref;
1369 }
1370
1371 frac = alt % 100;
1372 m = (alt / 100) * sign;
1373
1374 sprintf(buf, "%d.%.2d", m, frac);
1375 return buf;
1376 }
1377
1378 static unsigned int
1379 poweroften[10] =
1380 { 1,
1381 10,
1382 100,
1383 1000,
1384 10000,
1385 100000,
1386 1000000,
1387 10000000,
1388 100000000,
1389 1000000000
1390 };
1391
1392 static char *
1393 precsize_ntoa(uint8_t prec)
1394 {
1395 static char buf[19];
1396 unsigned long val;
1397 int mantissa, exponent;
1398
1399 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1400 exponent = (int)((prec >> 0) & 0x0f) % 10;
1401
1402 val = mantissa * poweroften[exponent];
1403
1404 sprintf(buf, "%ld.%.2ld", val/100, val%100);
1405 return buf;
1406 }
1407
1408 const char *
1409 dns_type_string(uint16_t t)
1410 {
1411 switch (t)
1412 {
1413 case ns_t_a: return "A ";
1414 case ns_t_ns: return "NS ";
1415 case ns_t_md: return "MD ";
1416 case ns_t_mf: return "MF ";
1417 case ns_t_cname: return "CNAME";
1418 case ns_t_soa: return "SOA ";
1419 case ns_t_mb: return "MB ";
1420 case ns_t_mg: return "MG ";
1421 case ns_t_mr: return "MR ";
1422 case ns_t_null: return "NULL ";
1423 case ns_t_wks: return "WKS ";
1424 case ns_t_ptr: return "PTR ";
1425 case ns_t_hinfo: return "HINFO";
1426 case ns_t_minfo: return "MINFO";
1427 case ns_t_mx: return "MX ";
1428 case ns_t_txt: return "TXT ";
1429 case ns_t_rp: return "PR ";
1430 case ns_t_afsdb: return "AFSDB";
1431 case ns_t_x25: return "X25 ";
1432 case ns_t_isdn: return "ISDN ";
1433 case ns_t_rt: return "RT ";
1434 case ns_t_nsap: return "NSAP ";
1435 case ns_t_nsap_ptr: return "NSPTR";
1436 case ns_t_sig: return "SIG ";
1437 case ns_t_key: return "KEY ";
1438 case ns_t_px: return "PX ";
1439 case ns_t_gpos: return "GPOS ";
1440 case ns_t_aaaa: return "AAAA ";
1441 case ns_t_loc: return "LOC ";
1442 case ns_t_nxt: return "NXT ";
1443 case ns_t_eid: return "EID ";
1444 case ns_t_nimloc: return "NIMLC";
1445 case ns_t_srv: return "SRV ";
1446 case ns_t_atma: return "ATMA ";
1447 case ns_t_naptr: return "NAPTR";
1448 case ns_t_kx: return "KX ";
1449 case ns_t_cert: return "CERT ";
1450 case ns_t_a6: return "A6 ";
1451 case ns_t_dname: return "DNAME";
1452 case ns_t_sink: return "SINK ";
1453 case ns_t_opt: return "OPT ";
1454 case ns_t_tkey: return "TKEY ";
1455 case ns_t_tsig: return "TSIG ";
1456 case ns_t_ixfr: return "IXFR ";
1457 case ns_t_axfr: return "AXFR ";
1458 case ns_t_mailb: return "MAILB";
1459 case ns_t_maila: return "MAILA";
1460 case ns_t_any: return "ANY ";
1461 case ns_t_zxfr: return "ZXFR ";
1462 default: return "?????";
1463 }
1464
1465 return "?????";
1466 }
1467
1468 int32_t
1469 dns_type_number(const char *t, uint16_t *n)
1470 {
1471 if (t == NULL) return -1;
1472
1473 if (!strcasecmp(t, "A")) { *n = ns_t_a; return 0; }
1474 if (!strcasecmp(t, "NS")) { *n = ns_t_ns; return 0; }
1475 if (!strcasecmp(t, "MD")) { *n = ns_t_md; return 0; }
1476 if (!strcasecmp(t, "MF")) { *n = ns_t_mf; return 0; }
1477 if (!strcasecmp(t, "CNAME")) { *n = ns_t_cname; return 0; }
1478 if (!strcasecmp(t, "SOA")) { *n = ns_t_soa; return 0; }
1479 if (!strcasecmp(t, "MB")) { *n = ns_t_mb; return 0; }
1480 if (!strcasecmp(t, "MG")) { *n = ns_t_mg; return 0; }
1481 if (!strcasecmp(t, "MR")) { *n = ns_t_mr; return 0; }
1482 if (!strcasecmp(t, "NULL")) { *n = ns_t_null; return 0; }
1483 if (!strcasecmp(t, "WKS")) { *n = ns_t_wks; return 0; }
1484 if (!strcasecmp(t, "PTR")) { *n = ns_t_ptr; return 0; }
1485 if (!strcasecmp(t, "HINFO")) { *n = ns_t_hinfo; return 0; }
1486 if (!strcasecmp(t, "MINFO")) { *n = ns_t_minfo; return 0; }
1487 if (!strcasecmp(t, "MX")) { *n = ns_t_mx; return 0; }
1488 if (!strcasecmp(t, "TXT")) { *n = ns_t_txt; return 0; }
1489 if (!strcasecmp(t, "RP")) { *n = ns_t_rp; return 0; }
1490 if (!strcasecmp(t, "AFSDB")) { *n = ns_t_afsdb; return 0; }
1491 if (!strcasecmp(t, "X25")) { *n = ns_t_x25; return 0; }
1492 if (!strcasecmp(t, "ISDN")) { *n = ns_t_isdn; return 0; }
1493 if (!strcasecmp(t, "RT")) { *n = ns_t_rt; return 0; }
1494 if (!strcasecmp(t, "NSAP")) { *n = ns_t_nsap; return 0; }
1495 if (!strcasecmp(t, "NSPTR")) { *n = ns_t_nsap_ptr; return 0; }
1496 if (!strcasecmp(t, "NSAP_PTR")){ *n = ns_t_nsap_ptr; return 0; }
1497 if (!strcasecmp(t, "SIG")) { *n = ns_t_sig; return 0; }
1498 if (!strcasecmp(t, "KEY")) { *n = ns_t_key; return 0; }
1499 if (!strcasecmp(t, "PX")) { *n = ns_t_px; return 0; }
1500 if (!strcasecmp(t, "GPOS")) { *n = ns_t_gpos; return 0; }
1501 if (!strcasecmp(t, "AAAA")) { *n = ns_t_aaaa; return 0; }
1502 if (!strcasecmp(t, "LOC")) { *n = ns_t_loc; return 0; }
1503 if (!strcasecmp(t, "NXT")) { *n = ns_t_nxt; return 0; }
1504 if (!strcasecmp(t, "EID")) { *n = ns_t_eid; return 0; }
1505 if (!strcasecmp(t, "NIMLOC")) { *n = ns_t_nimloc; return 0; }
1506 if (!strcasecmp(t, "SRV")) { *n = ns_t_srv; return 0; }
1507 if (!strcasecmp(t, "ATMA")) { *n = ns_t_atma; return 0; }
1508 if (!strcasecmp(t, "NAPTR")) { *n = ns_t_naptr; return 0; }
1509 if (!strcasecmp(t, "KX")) { *n = ns_t_kx; return 0; }
1510 if (!strcasecmp(t, "CERT")) { *n = ns_t_cert; return 0; }
1511 if (!strcasecmp(t, "A6")) { *n = ns_t_a6; return 0; }
1512 if (!strcasecmp(t, "DNAME")) { *n = ns_t_dname; return 0; }
1513 if (!strcasecmp(t, "SINK")) { *n = ns_t_sink; return 0; }
1514 if (!strcasecmp(t, "OPT")) { *n = ns_t_opt; return 0; }
1515 if (!strcasecmp(t, "TKEY")) { *n = ns_t_tkey; return 0; }
1516 if (!strcasecmp(t, "TSIG")) { *n = ns_t_tsig; return 0; }
1517 if (!strcasecmp(t, "IXFR")) { *n = ns_t_ixfr; return 0; }
1518 if (!strcasecmp(t, "AXFR")) { *n = ns_t_axfr; return 0; }
1519 if (!strcasecmp(t, "MAILB")) { *n = ns_t_mailb; return 0; }
1520 if (!strcasecmp(t, "MAILA")) { *n = ns_t_maila; return 0; }
1521 if (!strcasecmp(t, "ANY")) { *n = ns_t_any; return 0; }
1522 if (!strcasecmp(t, "ZXFR")) { *n = ns_t_zxfr; return 0; }
1523
1524 return -1;
1525 }
1526
1527 const char *
1528 dns_class_string(uint16_t c)
1529 {
1530 switch (c)
1531 {
1532 case ns_c_in: return "IN";
1533 case ns_c_2: return "CS";
1534 case ns_c_chaos: return "CH";
1535 case ns_c_hs: return "HS";
1536 case ns_c_none: return "NONE";
1537 case ns_c_any: return "ANY";
1538 default: return "??";
1539 }
1540
1541 return "??";
1542 }
1543
1544 int32_t
1545 dns_class_number(const char *c, uint16_t *n)
1546 {
1547 if (c == NULL) return -1;
1548
1549 if (!strcasecmp(c, "IN")) { *n = ns_c_in; return 0; }
1550 if (!strcasecmp(c, "CS")) { *n = ns_c_2; return 0; }
1551 if (!strcasecmp(c, "CH")) { *n = ns_c_chaos; return 0; }
1552 if (!strcasecmp(c, "HS")) { *n = ns_c_hs; return 0; }
1553 if (!strcasecmp(c, "NONE")) { *n = ns_c_none; return 0; }
1554 if (!strcasecmp(c, "ANY")) { *n = ns_c_any; return 0; }
1555
1556 return -1;
1557 }
1558
1559 static void
1560 _dns_print_question_lock(const dns_question_t *q, FILE *f, int lockit)
1561 {
1562 if (lockit != 0) _dns_print_lock();
1563 fprintf(f, "%s %s %s\n", q->name, dns_class_string(q->dnsclass), dns_type_string(q->dnstype));
1564 if (lockit != 0) _dns_print_unlock();
1565 }
1566
1567 void
1568 dns_print_question(const dns_question_t *q, FILE *f)
1569 {
1570 _dns_print_question_lock(q, f, 1);
1571 }
1572
1573 static void
1574 _dns_print_resource_record_lock(const dns_resource_record_t *r, FILE *f, int lockit)
1575 {
1576 struct protoent *p;
1577 struct servent *s;
1578 uint32_t i, len;
1579 uint8_t x;
1580 struct sockaddr_in6 s6;
1581 char pbuf[64];
1582
1583 if (lockit != 0) _dns_print_lock();
1584
1585 fprintf(f, "%s %s %s ", r->name, dns_class_string(r->dnsclass), dns_type_string(r->dnstype));
1586 fprintf(f, "%u", r->ttl);
1587
1588 switch (r->dnstype)
1589 {
1590 case ns_t_a:
1591 fprintf(f, " %s", inet_ntoa(r->data.A->addr));
1592 break;
1593
1594 case ns_t_aaaa:
1595 memset(&s6, 0, sizeof(struct sockaddr_in6));
1596 s6.sin6_len = sizeof(struct sockaddr_in6);
1597 s6.sin6_family = AF_INET6;
1598 s6.sin6_addr = r->data.AAAA->addr;
1599 fprintf(f, " %s", inet_ntop(AF_INET6, (char *)(&s6) + INET_NTOP_AF_INET6_OFFSET, pbuf, 64));
1600 break;
1601
1602 case ns_t_md:
1603 case ns_t_mf:
1604 case ns_t_cname:
1605 case ns_t_mb:
1606 case ns_t_mg:
1607 case ns_t_mr:
1608 case ns_t_ptr:
1609 case ns_t_ns:
1610 fprintf(f, " %s", r->data.CNAME->name);
1611 break;
1612
1613 case ns_t_soa:
1614 fprintf(f, " %s %s %u %u %u %u %u",
1615 r->data.SOA->mname, r->data.SOA->rname,
1616 r->data.SOA->serial, r->data.SOA->refresh, r->data.SOA->retry,
1617 r->data.SOA->expire, r->data.SOA->minimum);
1618 break;
1619
1620 case ns_t_wks:
1621 fprintf(f, " %s", inet_ntoa(r->data.WKS->addr));
1622 p = getprotobynumber(r->data.WKS->protocol);
1623 if (p != NULL)
1624 {
1625 fprintf(f, " %s", p->p_name);
1626
1627 for (i = 0; i < r->data.WKS->maplength; i++)
1628 {
1629 if (r->data.WKS->map[i])
1630 {
1631 s = getservbyport(i, p->p_name);
1632 if (s == NULL) fprintf(f, " %u", i);
1633 else fprintf(f, " %s", s->s_name);
1634 }
1635 }
1636 }
1637 else fprintf(f, " UNKNOWN PROTOCOL %u", r->data.WKS->protocol);
1638 break;
1639
1640 case ns_t_hinfo:
1641 fprintf(f, " %s %s", r->data.HINFO->cpu, r->data.HINFO->os);
1642 break;
1643
1644 case ns_t_minfo:
1645 fprintf(f, " %s %s", r->data.MINFO->rmailbx, r->data.MINFO->emailbx);
1646 break;
1647
1648 case ns_t_mx:
1649 fprintf(f, " %u %s", r->data.MX->preference, r->data.MX->name);
1650 break;
1651
1652 case ns_t_txt:
1653 for (i = 0; i < r->data.TXT->string_count; i++)
1654 {
1655 fprintf(f, " \"%s\"", r->data.TXT->strings[i]);
1656 }
1657 break;
1658
1659 case ns_t_rp:
1660 fprintf(f, " %s %s", r->data.RP->mailbox, r->data.RP->txtdname);
1661 break;
1662
1663 case ns_t_afsdb:
1664 fprintf(f, " %u %s", r->data.AFSDB->subtype,
1665 r->data.AFSDB->hostname);
1666 break;
1667
1668 case ns_t_x25:
1669 fprintf(f, " %s", r->data.X25->psdn_address);
1670 break;
1671
1672 case ns_t_isdn:
1673 fprintf(f, " %s", r->data.ISDN->isdn_address);
1674 if (r->data.ISDN->subaddress != NULL)
1675 fprintf(f, " %s", r->data.ISDN->subaddress);
1676 break;
1677
1678 case ns_t_rt:
1679 fprintf(f, " %hu %s", r->data.RT->preference,
1680 r->data.RT->intermediate);
1681 break;
1682
1683 case ns_t_loc:
1684 fprintf(f, " %s", coord_ntoa(r->data.LOC->latitude, 1));
1685 fprintf(f, " %s", coord_ntoa(r->data.LOC->longitude, 0));
1686 fprintf(f, " %sm", alt_ntoa(r->data.LOC->altitude));
1687 fprintf(f, " %sm", precsize_ntoa(r->data.LOC->size));
1688 fprintf(f, " %sm", precsize_ntoa(r->data.LOC->horizontal_precision));
1689 fprintf(f, " %sm", precsize_ntoa(r->data.LOC->vertical_precision));
1690 break;
1691
1692 case ns_t_srv:
1693 fprintf(f, " %hu %hu %hu %s",
1694 r->data.SRV->priority, r->data.SRV->weight,
1695 r->data.SRV->port, r->data.SRV->target);
1696 break;
1697
1698 case ns_t_null:
1699 default:
1700 len = r->data.DNSNULL->length;
1701 fprintf(f, " %u ", len);
1702 for (i = 0; i < len; i++)
1703 {
1704 x = r->data.DNSNULL->data[i];
1705 fprintf(f, "%x", x);
1706 }
1707
1708 fprintf(f, " (");
1709
1710 len = r->data.DNSNULL->length;
1711 for (i = 0; i < len; i++)
1712 {
1713 x = r->data.DNSNULL->data[i];
1714 if (isascii(x)) fprintf(f, "%c", x);
1715 else fprintf(f, " ");
1716 }
1717 fprintf(f, ")\n");
1718
1719 }
1720
1721 fprintf(f, "\n");
1722
1723 if (lockit != 0) _dns_print_unlock();
1724 }
1725
1726 void
1727 dns_print_resource_record(const dns_resource_record_t *r, FILE *f)
1728 {
1729 _dns_print_resource_record_lock(r, f, 1);
1730 }
1731
1732 void
1733 dns_print_reply(const dns_reply_t *r, FILE *f, uint16_t mask)
1734 {
1735 uint16_t i;
1736 dns_header_t *h;
1737 char scratch[1024];
1738 uint32_t offset, iface;
1739
1740 _dns_print_lock();
1741
1742 if (r == NULL)
1743 {
1744 fprintf(f, "-nil-\n");
1745 _dns_print_unlock();
1746 return;
1747 }
1748
1749 if (r->status != DNS_STATUS_OK)
1750 {
1751 if (r->status == DNS_STATUS_TIMEOUT)
1752 fprintf(f, "Timeout\n");
1753 else if (r->status == DNS_STATUS_SEND_FAILED)
1754 fprintf(f, "Send failed\n");
1755 else if (r->status == DNS_STATUS_RECEIVE_FAILED)
1756 fprintf(f, "Receive failed\n");
1757 else fprintf(f, "status %u\n", r->status);
1758
1759 _dns_print_unlock();
1760 return;
1761 }
1762
1763 h = r->header;
1764
1765 if (mask & DNS_PRINT_XID)
1766 {
1767 fprintf(f, "Xid: %u\n", h->xid);
1768 }
1769
1770 if (mask & DNS_PRINT_QR)
1771 {
1772 if ((h->flags & DNS_FLAGS_QR_MASK) == DNS_FLAGS_QR_QUERY)
1773 fprintf(f, "QR: Query\n");
1774 else
1775 fprintf(f, "QR: Reply\n");
1776 }
1777
1778 if (mask & DNS_PRINT_SERVER)
1779 {
1780 if (r->server == NULL)
1781 {
1782 fprintf(f, "Server: -nil-\n");
1783 }
1784 else
1785 {
1786 offset = INET_NTOP_AF_INET_OFFSET;
1787 if (r->server->sa_family == AF_INET6) offset = INET_NTOP_AF_INET6_OFFSET;
1788
1789 fprintf(f, "Server: %s", inet_ntop(r->server->sa_family, (char *)(r->server) + offset, scratch, 1024));
1790 if (r->server->sa_family == AF_INET)
1791 {
1792 memcpy(&iface, (((struct sockaddr_in *)(r->server))->sin_zero), 4);
1793 if (iface > 0) fprintf(f, "%%%s", if_indextoname(iface, scratch));
1794 }
1795 else if (r->server->sa_family == AF_INET6)
1796 {
1797 iface = ((struct sockaddr_in6 *)(r->server))->sin6_scope_id;
1798 if (iface > 0) fprintf(f, "%%%s", if_indextoname(iface, scratch));
1799 }
1800 fprintf(f, "\n");
1801 }
1802 }
1803
1804 if (mask & DNS_PRINT_OPCODE)
1805 {
1806 fprintf(f, "Opcode: ");
1807 switch (h->flags & DNS_FLAGS_OPCODE_MASK)
1808 {
1809 case ns_o_query: fprintf(f, "Standard\n"); break;
1810 case ns_o_iquery: fprintf(f, "Inverse\n"); break;
1811 case ns_o_status: fprintf(f, "Status\n"); break;
1812 case ns_o_notify: fprintf(f, "Notify\n"); break;
1813 case ns_o_update: fprintf(f, "Update\n"); break;
1814 default:
1815 fprintf(f, "Reserved (%hu)\n",
1816 (uint16_t)((h->flags & DNS_FLAGS_OPCODE_MASK) >> 11));
1817 }
1818 }
1819
1820 if (mask & DNS_PRINT_AA)
1821 {
1822 if (h->flags & DNS_FLAGS_AA) fprintf(f, "AA: Authoritative\n");
1823 else fprintf(f, "AA: Non-Authoritative\n");
1824 }
1825
1826 if (mask & DNS_PRINT_TC)
1827 {
1828 if (h->flags & DNS_FLAGS_TC) fprintf(f, "TC: Truncated\n");
1829 else fprintf(f, "TC: Non-Truncated\n");
1830 }
1831
1832 if (mask & DNS_PRINT_RD)
1833 {
1834 if (h->flags & DNS_FLAGS_RD) fprintf(f, "RD: Recursion desired\n");
1835 else fprintf(f, "RD: No recursion desired\n");
1836 }
1837
1838 if (mask & DNS_PRINT_RA)
1839 {
1840 if (h->flags & DNS_FLAGS_RA) fprintf(f, "RA: Recursion available\n");
1841 else fprintf(f, "RA: No recursion available \n");
1842 }
1843
1844 if (mask & DNS_PRINT_RCODE)
1845 {
1846 fprintf(f, "Rcode: ");
1847 switch (h->flags & DNS_FLAGS_RCODE_MASK)
1848 {
1849 case ns_r_noerror:
1850 fprintf(f, "No error\n");
1851 break;
1852 case ns_r_formerr:
1853 fprintf(f, "Format error \n");
1854 break;
1855 case ns_r_servfail:
1856 fprintf(f, "Server failure\n");
1857 break;
1858 case ns_r_nxdomain:
1859 fprintf(f, "Name error \n");
1860 break;
1861 case ns_r_notimpl:
1862 fprintf(f, "Not implemented\n");
1863 break;
1864 case ns_r_refused:
1865 fprintf(f, "Refused\n");
1866 break;
1867 case ns_r_yxdomain:
1868 fprintf(f, "Name exists\n");
1869 break;
1870 case ns_r_yxrrset:
1871 fprintf(f, "RR Set exists\n");
1872 break;
1873 case ns_r_nxrrset:
1874 fprintf(f, "RR Set does not exist\n");
1875 break;
1876 case ns_r_notauth:
1877 fprintf(f, "Not authoritative\n");
1878 break;
1879 case ns_r_notzone:
1880 fprintf(f, "Record zone does not match section zone\n");
1881 break;
1882 case ns_r_badvers:
1883 fprintf(f, "Invalid EDNS version or TSIG signature\n");
1884 break;
1885 case ns_r_badkey:
1886 fprintf(f, "Invalid key\n");
1887 break;
1888 case ns_r_badtime:
1889 fprintf(f, "Invalid time\n");
1890 break;
1891 default:
1892 fprintf(f, "Reserved (%hu)\n",(uint16_t)(h->flags & DNS_FLAGS_RCODE_MASK));
1893 }
1894 }
1895
1896 if (mask & DNS_PRINT_QUESTION)
1897 {
1898 fprintf(f, "Question (%hu):\n", h->qdcount);
1899 for (i = 0; i < h->qdcount; i++)
1900 _dns_print_question_lock(r->question[i], f, 0);
1901 }
1902
1903 if (mask & DNS_PRINT_ANSWER)
1904 {
1905 fprintf(f, "Answer (%hu):\n", h->ancount);
1906 for (i = 0; i < h->ancount; i++)
1907 _dns_print_resource_record_lock(r->answer[i], f, 0);
1908 }
1909
1910 if (mask & DNS_PRINT_AUTHORITY)
1911 {
1912 fprintf(f, "Authority (%hu):\n", h->nscount);
1913 for (i = 0; i < h->nscount; i++)
1914 _dns_print_resource_record_lock(r->authority[i], f, 0);
1915 }
1916
1917 if (mask & DNS_PRINT_ADDITIONAL)
1918 {
1919 fprintf(f, "Additional records (%hu):\n", h->arcount);
1920 for (i = 0; i < h->arcount; i++)
1921 _dns_print_resource_record_lock(r->additional[i], f, 0);
1922 }
1923
1924 _dns_print_unlock();
1925 }
1926
1927 static void
1928 _pdns_print_handle(pdns_handle_t *pdns, FILE *f)
1929 {
1930 uint32_t i, offset;
1931 struct in_addr a;
1932 char scratch[1024];
1933 struct sockaddr *sa;
1934 res_state r;
1935
1936 if (pdns == NULL)
1937 {
1938 fprintf(f, "-nil-\n");
1939 return;
1940 }
1941
1942 if (pdns->name == NULL) fprintf(f, "Name: -nil-\n");
1943 else fprintf(f, "Name: %s\n", pdns->name);
1944
1945 fprintf(f, "Flags:");
1946 if (pdns->flags == 0) fprintf(f, " None\n");
1947 else
1948 {
1949 if (pdns->flags & DNS_FLAG_DEBUG) fprintf(f, " Debug");
1950 if (pdns->flags & DNS_FLAG_CHECK_RESOLVER_DIR) fprintf(f, " DirCheck");
1951 if (pdns->flags & DNS_FLAG_HAVE_IPV6_SERVER) fprintf(f, " IPv6");
1952 if (pdns->flags & DNS_FLAG_OK_TO_SKIP_AAAA) fprintf(f, " SkipAAAA");
1953 if (pdns->flags & DNS_FLAG_DEFAULT_RESOLVER) fprintf(f, " Default");
1954 fprintf(f, "\n");
1955 }
1956
1957 r = pdns->res;
1958 if (r == NULL) return;
1959
1960 if (r->defdname[0] != '\0') fprintf(f, "Domain: %s\n", r->defdname);
1961 fprintf(f, "Search Order: %d\n", pdns->search_order);
1962 fprintf(f, "Total Timeout: %d\n", pdns->total_timeout);
1963 fprintf(f, "Retry Timeout: %d\n", pdns->res->retrans);
1964 fprintf(f, "Retry Attempts: %d\n", pdns->res->retry);
1965
1966 fprintf(f, "Server%s:\n", (r->nscount == 1) ? "" : "s");
1967 for (i = 0; i < r->nscount; i++)
1968 {
1969 sa = get_nsaddr(r, i);
1970 offset = INET_NTOP_AF_INET_OFFSET;
1971 if (sa->sa_family == AF_INET6) offset = INET_NTOP_AF_INET6_OFFSET;
1972 fprintf(f, " %u: %s", i, inet_ntop(sa->sa_family, (char *)sa + offset, scratch, 1024));
1973 fprintf(f, "\n");
1974 }
1975
1976 if (pdns->search_count > 0)
1977 {
1978 fprintf(f, "Search List:\n");
1979 for (i = 0; i < pdns->search_count; i++)
1980 fprintf(f, " %u: %s\n", i, pdns->search_list[i]);
1981 }
1982
1983 if (r->sort_list[0].addr.s_addr != 0)
1984 {
1985 fprintf(f, "Sortlist:\n");
1986 for (i = 0; (r->sort_list[i].addr.s_addr != 0); i++)
1987 {
1988 fprintf(f, " %u: ", i);
1989 a.s_addr = r->sort_list[i].addr.s_addr;
1990 fprintf(f, "%s/", inet_ntoa(a));
1991 a.s_addr = r->sort_list[i].mask;
1992 fprintf(f, "%s\n", inet_ntoa(a));
1993 }
1994 }
1995 }
1996
1997 static void
1998 _sdns_print_handle(sdns_handle_t *sdns, FILE *f)
1999 {
2000 int i;
2001
2002 if (sdns == NULL)
2003 {
2004 fprintf(f, "-nil-\n");
2005 return;
2006 }
2007
2008 for (i = 0; i < sdns->client_count; i++)
2009 {
2010 fprintf(f, "DNS client %d\n", i);
2011 _pdns_print_handle(sdns->client[i], f);
2012 fprintf(f, "\n");
2013 }
2014
2015 fprintf(f, "resolver dir mod time = %u\n", sdns->modtime);
2016 fprintf(f, "resolver dir stat time = %u\n", sdns->stattime);
2017 fprintf(f, "resolver dir stat latency = %u\n", sdns->stat_latency);
2018 }
2019
2020 void
2021 dns_print_handle(dns_handle_t d, FILE *f)
2022 {
2023 dns_private_handle_t *dns;
2024
2025 _dns_print_lock();
2026
2027 if (d == NULL)
2028 {
2029 fprintf(f, "-nil-\n");
2030 _dns_print_unlock();
2031 return;
2032 }
2033
2034 dns = (dns_private_handle_t *)d;
2035
2036 if (dns->handle_type == DNS_PRIVATE_HANDLE_TYPE_SUPER)
2037 {
2038 _sdns_print_handle(dns->sdns, f);
2039 }
2040 else
2041 {
2042 _pdns_print_handle(dns->pdns, f);
2043 }
2044
2045 _dns_print_unlock();
2046 }
2047
2048 void
2049 dns_all_server_addrs(dns_handle_t d, struct sockaddr ***addrs, uint32_t *count)
2050 {
2051 int i, j, k, n, found;
2052 dns_private_handle_t *dns;
2053 pdns_handle_t *pdns;
2054 struct sockaddr *sa;
2055 struct sockaddr_storage **l;
2056 res_state r;
2057
2058 *addrs = NULL;
2059 *count = 0;
2060 l = NULL;
2061 n = 0;
2062
2063 if (d == NULL) return;
2064
2065 dns = (dns_private_handle_t *)d;
2066
2067 if (dns->handle_type != DNS_PRIVATE_HANDLE_TYPE_SUPER) return;
2068
2069 if (dns->sdns == NULL) return;
2070
2071 /* Just to initialize / validate clients */
2072 i = dns_search_list_count(d);
2073
2074 for (i = 0; i < dns->sdns->client_count; i++)
2075 {
2076 pdns = dns->sdns->client[i];
2077 if (pdns == NULL) continue;
2078
2079 r = pdns->res;
2080 if (r == NULL) continue;
2081
2082 for (j = 0; j < r->nscount; j++)
2083 {
2084 sa = get_nsaddr(r, j);
2085 found = 0;
2086 for (k = 0; (found == 0) && (k < n); k++)
2087 {
2088 if (memcmp(l[k], sa, sa->sa_len) == 0) found = 1;
2089 }
2090 if (found == 1) continue;
2091
2092 if (n == 0)
2093 {
2094 l = (struct sockaddr_storage **)calloc(1, sizeof(struct sockaddr_storage *));
2095 }
2096 else
2097 {
2098 l = (struct sockaddr_storage **)reallocf(l, (n + 1) * sizeof(struct sockaddr_storage *));
2099 }
2100
2101 if (l == NULL) return;
2102
2103 l[n] = (struct sockaddr_storage *)calloc(1, sizeof(struct sockaddr_storage));
2104 if (l[n] == NULL) return;
2105
2106 memset(l[n], 0, sizeof(struct sockaddr_storage));
2107 memcpy(l[n], sa, sa->sa_len);
2108 n++;
2109 }
2110 }
2111
2112 *addrs = (struct sockaddr **)l;
2113 *count = n;
2114 }
2115
2116 int
2117 dns_res_once(struct sockaddr *server, struct timeval *timeout, int options, const char *name, int class, int type, u_char *res, int *reslen)
2118 {
2119 res_state statp;
2120 int n, fromlen, status;
2121 struct sockaddr_storage from;
2122 u_char buf[MAXPACKET];
2123
2124 if (server == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT;
2125 if (name == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT;
2126 if (res == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT;
2127 if (reslen == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT;
2128
2129 fromlen = sizeof(struct sockaddr_storage);
2130
2131 statp = res_state_new();
2132 statp->retry = 1;
2133 statp->options = options;
2134 statp->id = res_randomid();
2135 if (timeout == NULL) statp->retrans = 5;
2136 else statp->retrans = timeout->tv_sec;
2137
2138 statp->ndots = 1;
2139 statp->_vcsock = -1;
2140 statp->nscount = 1;
2141
2142 strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
2143 strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
2144 strcpy(statp->_u._ext.ext->bsuffix, "ip6.arpa");
2145
2146 if (server->sa_family == AF_INET6)
2147 {
2148 memcpy(&(statp->_u._ext.ext->nsaddrs[0]), server, sizeof(struct sockaddr_in6));
2149 statp->nsaddr_list[0].sin_family = 0;
2150 }
2151 else
2152 {
2153 memcpy(&(statp->_u._ext.ext->nsaddrs[0]), server, sizeof(struct sockaddr_in));
2154 memcpy(&(statp->nsaddr_list[0]), server, sizeof(struct sockaddr_in));
2155 }
2156
2157 n = res_nmkquery(statp, ns_o_query, name, class, type, NULL, 0, NULL, buf, sizeof(buf));
2158
2159 status = dns_res_send(statp, buf, n, res, reslen, (struct sockaddr *)&from, &fromlen);
2160
2161 res_client_close(statp);
2162
2163 return status;
2164 }