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