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