]> git.saurik.com Git - apple/libresolv.git/blob - dns_util.c
libresolv-19.tar.gz
[apple/libresolv.git] / dns_util.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <netdb.h>
31 #include <stdarg.h>
32 #include <sys/stat.h>
33 #include <sys/dir.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <ifaddrs.h>
38 #include <net/if.h>
39 #include <pthread.h>
40 #include <netinet/in.h>
41 #include <arpa/nameser.h>
42 #include <resolv.h>
43 #include "dns.h"
44 #include "dns_util.h"
45 #include "dns_private.h"
46 #include "res_private.h"
47
48 #define DNS_RESOLVER_DIR "/etc/resolver"
49
50 #define DNS_PRIVATE_HANDLE_TYPE_SUPER 0
51 #define DNS_PRIVATE_HANDLE_TYPE_PLAIN 1
52 #define DNS_DEFAULT_RECEIVE_SIZE 8192
53 #define DNS_MAX_RECEIVE_SIZE 65536
54
55 #define SDNS_DEFAULT_STAT_LATENCY 10
56
57 #define DNS_FLAGS_QR_MASK 0x8000
58 #define DNS_FLAGS_QR_QUERY 0x0000
59
60 #define DNS_FLAGS_OPCODE_MASK 0x7800
61
62 #define DNS_FLAGS_RCODE_MASK 0x000f
63
64 #define DNS_FLAGS_AA 0x0400
65 #define DNS_FLAGS_TC 0x0200
66 #define DNS_FLAGS_RD 0x0100
67 #define DNS_FLAGS_RA 0x0080
68
69 #define DNS_SOCK_UDP 0
70 #define DNS_SOCK_TCP_UNCONNECTED 1
71 #define DNS_SOCK_TCP_CONNECTED 2
72
73 #define INET_NTOP_AF_INET_OFFSET 4
74 #define INET_NTOP_AF_INET6_OFFSET 8
75
76 #define MAXPACKET 1024
77
78 extern void res_client_close(res_state res);
79 extern int __res_nquery(res_state statp, const char *name, int class, int type, u_char *answer, int anslen);
80 extern int dns_res_send(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz, struct sockaddr *from, int *fromlen);
81 extern void _check_cache(sdns_handle_t *sdns);
82 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);
83 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);
84 static pthread_mutex_t _dnsPrintLock = PTHREAD_MUTEX_INITIALIZER;
85
86 static void
87 _dns_print_lock(void)
88 {
89 pthread_mutex_lock(&_dnsPrintLock);
90 }
91
92 static void
93 _dns_print_unlock(void)
94 {
95 pthread_mutex_unlock(&_dnsPrintLock);
96 }
97
98
99 static uint8_t
100 _dns_parse_uint8(char **p)
101 {
102 uint8_t v;
103
104 v = (uint8_t)**p;
105 *p += 1;
106 return v;
107 }
108
109 static uint16_t
110 _dns_parse_uint16(char **p)
111 {
112 uint16_t *x, v;
113
114 x = (uint16_t *)*p;
115 v = ntohs(*x);
116 *p += 2;
117 return v;
118 }
119
120 static uint32_t
121 _dns_parse_uint32(char **p)
122 {
123 uint32_t *x, v;
124
125 x = (uint32_t *)*p;
126 v = ntohl(*x);
127 *p += 4;
128 return v;
129 }
130
131 static uint8_t
132 _dns_cname_length(char *s)
133 {
134 uint8_t l;
135
136 if (s == NULL) return 1;
137 l = strlen(s);
138 while ((s[l - 1] == '.') && (l > 1)) l--;
139 return l;
140 }
141
142 static void
143 _dns_insert_cname(char *s, char *p)
144 {
145 int i;
146 uint8_t len, dlen;
147
148 if (s == NULL)
149 {
150 *p = 0;
151 return;
152 }
153
154 if (!strcmp(s, "."))
155 {
156 p[0] = 1;
157 p[1] = '.';
158 p[2] = 0;
159 return;
160 }
161
162 len = _dns_cname_length(s);
163
164 p[0] = '.';
165 memmove(p + 1, s, len);
166 p[len + 1] = '.';
167
168 dlen = 0;
169
170 for (i = len + 1; i >= 0; i--)
171 {
172 if (p[i] == '.')
173 {
174 p[i] = dlen;
175 dlen = 0;
176 }
177 else dlen++;
178 }
179 }
180
181 static char *
182 _dns_parse_string(const char *p, char **x, int32_t *remaining)
183 {
184 char *str;
185 uint8_t len;
186
187 if (*remaining < 1) return NULL;
188 *remaining -= 1;
189
190 len = (uint8_t)**x;
191 *x += 1;
192
193 if (*remaining < len) return NULL;
194 *remaining -= len;
195
196 str = malloc(len + 1);
197 memmove(str, *x, len);
198 str[len] = '\0';
199 *x += len;
200
201 return str;
202 }
203
204 static char *
205 _dns_parse_domain_name(const char *p, char **x, int32_t *remaining)
206 {
207 uint8_t *v8;
208 uint16_t *v16, skip;
209 uint16_t i, j, dlen, len;
210 int more, compressed;
211 char *name, *start, *y, *z;
212
213 if (*remaining < 1) return NULL;
214
215 z = *x + *remaining;
216 start = *x;
217 compressed = 0;
218 more = 1;
219 name = malloc(1);
220 name[0] = '\0';
221 len = 1;
222 j = 0;
223 skip = 0;
224
225 while (more == 1)
226 {
227 if ((*x + 1) > z)
228 {
229 free(name);
230 return NULL;
231 }
232
233 v8 = (uint8_t *)*x;
234 dlen = *v8;
235
236 if ((dlen & 0xc0) == 0xc0)
237 {
238 if ((*x + 2) > z)
239 {
240 free(name);
241 return NULL;
242 }
243
244 v16 = (uint16_t *)*x;
245
246 y = (char *)p + (ntohs(*v16) & 0x3fff);
247 if ((*x == y) || (y > z))
248 {
249 free(name);
250 return NULL;
251 }
252
253 *x = y;
254 if (compressed == 0) skip += 2;
255 compressed = 1;
256 continue;
257 }
258
259 if ((*x + 1) > z)
260 {
261 free(name);
262 return NULL;
263 }
264
265 *x += 1;
266
267 if (dlen > 0)
268 {
269 len += dlen;
270 name = realloc(name, len);
271 }
272
273 if ((*x + dlen) > z)
274 {
275 free(name);
276 return NULL;
277 }
278
279 for (i = 0; i < dlen; i++)
280 {
281 name[j++] = **x;
282 *x += 1;
283 }
284
285 name[j] = '\0';
286 if (compressed == 0) skip += (dlen + 1);
287
288 if (dlen == 0) more = 0;
289 else
290 {
291 if ((*x + 1) > z)
292 {
293 free(name);
294 return NULL;
295 }
296
297 v8 = (uint8_t *)*x;
298 if (*v8 != 0)
299 {
300 len += 1;
301 name = realloc(name, len);
302 name[j++] = '.';
303 name[j] = '\0';
304 }
305 }
306 }
307
308 if ((start + skip) > z)
309 {
310 free(name);
311 return NULL;
312 }
313
314 *x = start + skip;
315 *remaining -= skip;
316
317 return name;
318 }
319
320 dns_resource_record_t *
321 _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining)
322 {
323 uint32_t size, bx, mi;
324 uint16_t rdlen;
325 uint8_t byte, i;
326 dns_resource_record_t *r;
327 char *eor;
328
329 if (*remaining < 1) return NULL;
330
331 r = (dns_resource_record_t *)calloc(1, sizeof(dns_resource_record_t));
332
333 r->name = _dns_parse_domain_name(p, x, remaining);
334 if (r->name == NULL)
335 {
336 free(r);
337 return NULL;
338 }
339
340 if (*remaining < 10)
341 {
342 free(r);
343 return NULL;
344 }
345
346 r->dnstype = _dns_parse_uint16(x);
347 r->dnsclass = _dns_parse_uint16(x);
348 r->ttl = _dns_parse_uint32(x);
349 rdlen = _dns_parse_uint16(x);
350
351 *remaining -= 10;
352
353 eor = *x;
354 r->data.A = NULL;
355
356 switch (r->dnstype)
357 {
358 case ns_t_a:
359 if (*remaining < 4)
360 {
361 free(r);
362 return NULL;
363 }
364
365 *remaining -= 4;
366
367 size = sizeof(dns_address_record_t);
368 r->data.A = (dns_address_record_t *)calloc(1, size);
369 r->data.A->addr.s_addr = htonl(_dns_parse_uint32(x));
370 break;
371
372 case ns_t_aaaa:
373 if (*remaining < 16)
374 {
375 free(r);
376 return NULL;
377 }
378
379 *remaining -= 16;
380
381 size = sizeof(dns_in6_address_record_t);
382 r->data.AAAA = (dns_in6_address_record_t *)calloc(1, size);
383 r->data.AAAA->addr.__u6_addr.__u6_addr32[0] = htonl(_dns_parse_uint32(x));
384 r->data.AAAA->addr.__u6_addr.__u6_addr32[1] = htonl(_dns_parse_uint32(x));
385 r->data.AAAA->addr.__u6_addr.__u6_addr32[2] = htonl(_dns_parse_uint32(x));
386 r->data.AAAA->addr.__u6_addr.__u6_addr32[3] = htonl(_dns_parse_uint32(x));
387 break;
388
389 case ns_t_ns:
390 case ns_t_md:
391 case ns_t_mf:
392 case ns_t_cname:
393 case ns_t_mb:
394 case ns_t_mg:
395 case ns_t_mr:
396 case ns_t_ptr:
397 size = sizeof(dns_domain_name_record_t);
398 r->data.CNAME = (dns_domain_name_record_t *)calloc(1,size);
399 r->data.CNAME->name = _dns_parse_domain_name(p, x, remaining);
400 if (r->data.CNAME->name == NULL)
401 {
402 free(r->data.CNAME);
403 free(r);
404 return NULL;
405 }
406 break;
407
408 case ns_t_soa:
409 size = sizeof(dns_SOA_record_t);
410 r->data.SOA = (dns_SOA_record_t *)calloc(1, size);
411
412 r->data.SOA->mname = _dns_parse_domain_name(p, x, remaining);
413 if (r->data.SOA->mname == NULL)
414 {
415 free(r->data.SOA);
416 free(r);
417 return NULL;
418 }
419
420 r->data.SOA->rname = _dns_parse_domain_name(p, x, remaining);
421 if (r->data.SOA->rname == NULL)
422 {
423 free(r->data.SOA->mname);
424 free(r->data.SOA);
425 free(r);
426 return NULL;
427 }
428
429 if (*remaining < 20)
430 {
431 free(r->data.SOA->mname);
432 free(r->data.SOA->rname);
433 free(r->data.SOA);
434 free(r);
435 return NULL;
436 }
437
438 *remaining -= 20;
439
440 r->data.SOA->serial = _dns_parse_uint32(x);
441 r->data.SOA->refresh = _dns_parse_uint32(x);
442 r->data.SOA->retry = _dns_parse_uint32(x);
443 r->data.SOA->expire = _dns_parse_uint32(x);
444 r->data.SOA->minimum = _dns_parse_uint32(x);
445 break;
446
447 case ns_t_wks:
448 if (*remaining < 5)
449 {
450 free(r);
451 return NULL;
452 }
453
454 *remaining -= rdlen;
455
456 size = sizeof(dns_WKS_record_t);
457 r->data.WKS = (dns_WKS_record_t *)calloc(1, size);
458
459 r->data.WKS->addr.s_addr = htonl(_dns_parse_uint32(x));
460 r->data.WKS->protocol = _dns_parse_uint8(x);
461 size = rdlen - 5;
462 r->data.WKS->maplength = size * 8;
463 r->data.WKS->map = NULL;
464 if (size == 0) break;
465
466 r->data.WKS->map = (uint8_t *)calloc(1, r->data.WKS->maplength);
467 mi = 0;
468 for (bx = 0; bx < size; bx++)
469 {
470 byte = _dns_parse_uint8(x);
471 for (i = 128; i >= 1; i = i/2)
472 {
473 if (byte & i) r->data.WKS->map[mi] = 0xff;
474 else r->data.WKS->map[mi] = 0;
475 mi++;
476 }
477 }
478 break;
479
480 case ns_t_hinfo:
481 size = sizeof(dns_HINFO_record_t);
482 r->data.HINFO = (dns_HINFO_record_t *)calloc(1, size);
483
484 r->data.HINFO->cpu = _dns_parse_string(p, x, remaining);
485 if (r->data.HINFO->cpu == NULL)
486 {
487 free(r->data.HINFO);
488 free(r);
489 return NULL;
490 }
491
492 r->data.HINFO->os = _dns_parse_string(p, x, remaining);
493 if (r->data.HINFO->os == NULL)
494 {
495 free(r->data.HINFO->cpu);
496 free(r->data.HINFO);
497 free(r);
498 return NULL;
499 }
500
501 break;
502
503 case ns_t_minfo:
504 size = sizeof(dns_MINFO_record_t);
505 r->data.MINFO = (dns_MINFO_record_t *)calloc(1, size);
506
507 r->data.MINFO->rmailbx = _dns_parse_domain_name(p, x, remaining);
508 if (r->data.MINFO->rmailbx == NULL)
509 {
510 free(r->data.MINFO);
511 free(r);
512 return NULL;
513 }
514
515 r->data.MINFO->emailbx = _dns_parse_domain_name(p, x, remaining);
516 if (r->data.MINFO->emailbx == NULL)
517 {
518 free(r->data.MINFO->rmailbx);
519 free(r->data.MINFO);
520 free(r);
521 return NULL;
522 }
523
524 break;
525
526 case ns_t_mx:
527 if (*remaining < 2)
528 {
529 free(r);
530 return NULL;
531 }
532
533 *remaining -= 2;
534
535 size = sizeof(dns_MX_record_t);
536 r->data.MX = (dns_MX_record_t *)calloc(1, size);
537
538 r->data.MX->preference = _dns_parse_uint16(x);
539 r->data.MX->name = _dns_parse_domain_name(p, x, remaining);
540 if (r->data.MX->name == NULL)
541 {
542 free(r->data.MX);
543 free(r);
544 return NULL;
545 }
546
547 break;
548
549 case ns_t_txt:
550 size = sizeof(dns_TXT_record_t);
551 r->data.TXT = (dns_TXT_record_t *)malloc(size);
552 r->data.TXT->string_count = 0;
553 r->data.TXT->strings = NULL;
554
555 while (*x < (eor + rdlen))
556 {
557 if (r->data.TXT->string_count == 0)
558 {
559 r->data.TXT->strings = (char **)calloc(1, sizeof(char *));
560 }
561 else
562 {
563 r->data.TXT->strings = (char **)realloc(r->data.TXT->strings, (r->data.TXT->string_count + 1) * sizeof(char *));
564 }
565
566 r->data.TXT->strings[r->data.TXT->string_count] = _dns_parse_string(p, x, remaining);
567 if (r->data.TXT->strings[r->data.TXT->string_count] == NULL)
568 {
569 free(r->data.TXT->strings);
570 free(r->data.TXT);
571 free(r);
572 return NULL;
573 }
574 r->data.TXT->string_count++;
575 }
576
577 break;
578
579 case ns_t_rp:
580 size = sizeof(dns_RP_record_t);
581 r->data.RP = (dns_RP_record_t *)calloc(1, size);
582
583 r->data.RP->mailbox = _dns_parse_domain_name(p, x, remaining);
584 if (r->data.RP->mailbox == NULL)
585 {
586 free(r->data.RP);
587 free(r);
588 return NULL;
589 }
590
591 r->data.RP->txtdname = _dns_parse_domain_name(p, x, remaining);
592 if (r->data.RP->txtdname == NULL)
593 {
594 free(r->data.RP->mailbox);
595 free(r->data.RP);
596 free(r);
597 return NULL;
598 }
599
600 break;
601
602 case ns_t_afsdb:
603 if (*remaining < 4)
604 {
605 free(r);
606 return NULL;
607 }
608
609 *remaining -= 4;
610 size = sizeof(dns_AFSDB_record_t);
611 r->data.AFSDB = (dns_AFSDB_record_t *)calloc(1, size);
612
613 r->data.AFSDB->subtype = _dns_parse_uint32(x);
614 r->data.AFSDB->hostname = _dns_parse_domain_name(p, x, remaining);
615 if (r->data.AFSDB->hostname == NULL)
616 {
617 free(r->data.AFSDB);
618 free(r);
619 return NULL;
620 }
621
622 break;
623
624 case ns_t_x25:
625 size = sizeof(dns_X25_record_t);
626 r->data.X25 = (dns_X25_record_t *)calloc(1, size);
627
628 r->data.X25->psdn_address = _dns_parse_string(p, x, remaining);
629 if (r->data.X25->psdn_address == NULL)
630 {
631 free(r->data.X25);
632 free(r);
633 return NULL;
634 }
635
636 break;
637
638 case ns_t_isdn:
639 size = sizeof(dns_ISDN_record_t);
640 r->data.ISDN = (dns_ISDN_record_t *)calloc(1, size);
641
642 r->data.ISDN->isdn_address = _dns_parse_string(p, x, remaining);
643 if (r->data.ISDN->isdn_address == NULL)
644 {
645 free(r->data.ISDN);
646 free(r);
647 return NULL;
648 }
649
650 if (*x < (eor + rdlen))
651 {
652 r->data.ISDN->subaddress = _dns_parse_string(p, x, remaining);
653 if (r->data.ISDN->subaddress == NULL)
654 {
655 free(r->data.ISDN->isdn_address);
656 free(r->data.ISDN);
657 free(r);
658 return NULL;
659 }
660 }
661 else
662 {
663 r->data.ISDN->subaddress = NULL;
664 }
665
666 break;
667
668 case ns_t_rt:
669 if (*remaining < 2)
670 {
671 free(r);
672 return NULL;
673 }
674
675 *remaining -= 2;
676
677 size = sizeof(dns_RT_record_t);
678 r->data.RT = (dns_RT_record_t *)calloc(1, size);
679
680 r->data.RT->preference = _dns_parse_uint16(x);
681 r->data.RT->intermediate = _dns_parse_domain_name(p, x, remaining);
682 if (r->data.RT->intermediate == NULL)
683 {
684 free(r->data.RT);
685 free(r);
686 return NULL;
687 }
688
689 break;
690
691 case ns_t_loc:
692 if (*remaining < 16)
693 {
694 free(r);
695 return NULL;
696 }
697
698 *remaining -= 16;
699
700 size = sizeof(dns_LOC_record_t);
701 r->data.LOC = (dns_LOC_record_t *)calloc(1, size);
702
703 r->data.LOC->version = _dns_parse_uint8(x);
704 r->data.LOC->size = _dns_parse_uint8(x);
705 r->data.LOC->horizontal_precision = _dns_parse_uint8(x);
706 r->data.LOC->vertical_precision = _dns_parse_uint8(x);
707 r->data.LOC->latitude = _dns_parse_uint32(x);
708 r->data.LOC->longitude = _dns_parse_uint32(x);
709 r->data.LOC->altitude = _dns_parse_uint32(x);
710 break;
711
712 case ns_t_srv:
713 if (*remaining < 6)
714 {
715 free(r);
716 return NULL;
717 }
718
719 *remaining -= 6;
720
721 size = sizeof(dns_SRV_record_t);
722 r->data.SRV = (dns_SRV_record_t *)calloc(1, size);
723
724 r->data.SRV->priority = _dns_parse_uint16(x);
725 r->data.SRV->weight = _dns_parse_uint16(x);
726 r->data.SRV->port = _dns_parse_uint16(x);
727 r->data.SRV->target = _dns_parse_domain_name(p, x, remaining);
728 if (r->data.SRV->target == NULL)
729 {
730 free(r->data.SRV);
731 free(r);
732 return NULL;
733 }
734
735 break;
736
737 case ns_t_null:
738 default:
739 if (*remaining < rdlen)
740 {
741 free(r);
742 return NULL;
743 }
744
745 *remaining -= rdlen;
746
747 size = sizeof(dns_raw_resource_record_t);
748 r->data.DNSNULL = (dns_raw_resource_record_t *)calloc(1, size);
749
750 r->data.DNSNULL->length = rdlen;
751 r->data.DNSNULL->data = calloc(1, rdlen);
752 memmove(r->data.DNSNULL->data, *x, rdlen);
753 *x += rdlen;
754 break;
755 }
756
757 *x = eor + rdlen;
758 return r;
759 }
760
761 dns_resource_record_t *
762 dns_parse_resource_record(const char *buf, uint32_t len)
763 {
764 char *x;
765 int32_t remaining;
766
767 remaining = len;
768 x = (char *)buf;
769 return _dns_parse_resource_record_internal(buf, &x, &remaining);
770 }
771
772 dns_question_t *
773 _dns_parse_question_internal(const char *p, char **x, int32_t *remaining)
774 {
775 dns_question_t *q;
776
777 if (x == NULL) return NULL;
778 if (*x == NULL) return NULL;
779 if (*remaining < 1) return NULL;
780
781 q = (dns_question_t *)calloc(1, sizeof(dns_question_t));
782
783 q->name = _dns_parse_domain_name(p, x, remaining);
784 if (q->name == NULL)
785 {
786 free(q);
787 return NULL;
788 }
789
790 if (*remaining < 4)
791 {
792 free(q->name);
793 free(q);
794 return NULL;
795 }
796
797 *remaining = *remaining - 4;
798
799 q->dnstype = _dns_parse_uint16(x);
800 q->dnsclass = _dns_parse_uint16(x);
801
802 return q;
803 }
804
805 dns_question_t *
806 dns_parse_question(const char *buf, uint32_t len)
807 {
808 char *x;
809 int32_t remaining;
810
811 remaining = len;
812 x = (char *)buf;
813 return _dns_parse_question_internal(buf, &x, &remaining);
814 }
815
816
817 dns_reply_t *
818 dns_parse_packet(const char *p, uint32_t len)
819 {
820 dns_reply_t *r;
821 dns_header_t *h;
822 char *x;
823 uint32_t i, size;
824 int32_t remaining;
825
826 if (p == NULL) return NULL;
827 if (len < NS_HFIXEDSZ) return NULL;
828
829 x = (char *)p;
830
831 r = (dns_reply_t *)calloc(1, sizeof(dns_reply_t));
832
833 r->header = (dns_header_t *)calloc(1, sizeof(dns_header_t));
834 h = r->header;
835
836 h->xid = _dns_parse_uint16(&x);
837 h->flags = _dns_parse_uint16(&x);
838 h->qdcount = _dns_parse_uint16(&x);
839 h->ancount = _dns_parse_uint16(&x);
840 h->nscount = _dns_parse_uint16(&x);
841 h->arcount = _dns_parse_uint16(&x);
842
843 remaining = len - NS_HFIXEDSZ;
844
845 size = sizeof(dns_question_t *);
846 r->question = (dns_question_t **)calloc(h->qdcount, size);
847 for (i = 0; i < h->qdcount; i++)
848 {
849 r->question[i] = _dns_parse_question_internal(p, &x, &remaining);
850 if (r->question[i] ==NULL)
851 {
852 h->qdcount = 0;
853 if (i > 0) h->qdcount = i - 1;
854 h->ancount = 0;
855 h->nscount = 0;
856 h->arcount = 0;
857 dns_free_reply(r);
858 return NULL;
859 }
860 }
861
862 size = sizeof(dns_resource_record_t *);
863
864 r->answer = (dns_resource_record_t **)calloc(h->ancount, size);
865 for (i = 0; i < h->ancount; i++)
866 {
867 r->answer[i] = _dns_parse_resource_record_internal(p, &x, &remaining);
868 if (r->answer[i] == NULL)
869 {
870 h->ancount = 0;
871 if (i > 0) h->ancount = i - 1;
872 h->nscount = 0;
873 h->arcount = 0;
874 dns_free_reply(r);
875 return NULL;
876 }
877 }
878
879 r->authority = (dns_resource_record_t **)calloc(h->nscount, size);
880 for (i = 0; i < h->nscount; i++)
881 {
882 r->authority[i] = _dns_parse_resource_record_internal(p, &x, &remaining);
883 if (r->authority[i] == NULL)
884 {
885 h->nscount = 0;
886 if (i > 0) h->nscount = i - 1;
887 h->arcount = 0;
888 dns_free_reply(r);
889 return NULL;
890 }
891 }
892
893 r->additional = (dns_resource_record_t **)calloc(h->arcount, size);
894 for (i = 0; i < h->arcount; i++)
895 {
896 r->additional[i] = _dns_parse_resource_record_internal(p, &x, &remaining);
897 if (r->additional[i] == NULL)
898 {
899 h->arcount = 0;
900 if (i > 0) h->arcount = i - 1;
901 dns_free_reply(r);
902 return NULL;
903 }
904 }
905
906 return r;
907 }
908
909 void
910 dns_free_resource_record(dns_resource_record_t *r)
911 {
912 int i;
913
914 free(r->name);
915
916 switch (r->dnstype)
917 {
918 case ns_t_a:
919 free(r->data.A);
920 break;
921
922 case ns_t_aaaa:
923 free(r->data.AAAA);
924 break;
925
926 case ns_t_ns:
927 case ns_t_md:
928 case ns_t_mf:
929 case ns_t_cname:
930 case ns_t_mb:
931 case ns_t_mg:
932 case ns_t_mr:
933 case ns_t_ptr:
934 free(r->data.CNAME->name);
935 free(r->data.CNAME);
936 break;
937
938 case ns_t_soa:
939 free(r->data.SOA->mname);
940 free(r->data.SOA->rname);
941 free(r->data.SOA);
942 break;
943
944 case ns_t_wks:
945 free(r->data.WKS->map);
946 free(r->data.WKS);
947 break;
948
949 case ns_t_hinfo:
950 free(r->data.HINFO->cpu);
951 free(r->data.HINFO->os);
952 free(r->data.HINFO);
953 break;
954
955 case ns_t_minfo:
956 free(r->data.MINFO->rmailbx);
957 free(r->data.MINFO->emailbx);
958 free(r->data.MINFO);
959 break;
960
961 case ns_t_mx:
962 free(r->data.MX->name);
963 free(r->data.MX);
964 break;
965
966
967 case ns_t_txt:
968 for (i=0; i<r->data.TXT->string_count; i++)
969 {
970 free(r->data.TXT->strings[i]);
971 }
972 if (r->data.TXT->strings != NULL)
973 free(r->data.TXT->strings);
974 free(r->data.TXT);
975 break;
976
977 case ns_t_rp:
978 free(r->data.RP->mailbox);
979 free(r->data.RP->txtdname);
980 free(r->data.RP);
981 break;
982
983 case ns_t_afsdb:
984 free(r->data.AFSDB->hostname);
985 free(r->data.AFSDB);
986 break;
987
988 case ns_t_x25:
989 free(r->data.X25->psdn_address);
990 free(r->data.X25);
991 break;
992
993 case ns_t_isdn:
994 free(r->data.ISDN->isdn_address);
995 if (r->data.ISDN->subaddress != NULL)
996 free(r->data.ISDN->subaddress);
997 free(r->data.ISDN);
998 break;
999
1000 case ns_t_rt:
1001 free(r->data.RT->intermediate);
1002 free(r->data.RT);
1003 break;
1004
1005 case ns_t_loc:
1006 free(r->data.LOC);
1007 break;
1008
1009 case ns_t_srv:
1010 free(r->data.SRV->target);
1011 free(r->data.SRV);
1012 break;
1013
1014 case ns_t_null:
1015 default:
1016 free(r->data.DNSNULL->data);
1017 free(r->data.DNSNULL);
1018 break;
1019 }
1020
1021 free(r);
1022 }
1023
1024 void
1025 dns_free_reply(dns_reply_t *r)
1026 {
1027 uint32_t i;
1028
1029 if (r == NULL) return;
1030 if (r->header != NULL)
1031 {
1032 for (i = 0; i < r->header->qdcount; i++)
1033 {
1034 free(r->question[i]->name);
1035 free(r->question[i]);
1036 }
1037
1038 for (i = 0; i < r->header->ancount; i++) dns_free_resource_record(r->answer[i]);
1039 for (i = 0; i < r->header->nscount; i++) dns_free_resource_record(r->authority[i]);
1040 for (i = 0; i < r->header->arcount; i++) dns_free_resource_record(r->additional[i]);
1041
1042 free(r->header);
1043 }
1044
1045 if (r->question != NULL) free(r->question);
1046 if (r->answer != NULL) free(r->answer);
1047 if (r->authority != NULL) free(r->authority);
1048 if (r->additional != NULL) free(r->additional);
1049
1050 if (r->server != NULL) free(r->server);
1051
1052 free(r);
1053 }
1054
1055 static void
1056 _dns_append_question(dns_question_t *q, char **s, uint16_t *l)
1057 {
1058 uint16_t len, *p;
1059 char *x;
1060
1061 if (q == NULL) return;
1062
1063 len = *l + _dns_cname_length(q->name) + 2 + 4;
1064 *s = realloc(*s, len);
1065
1066 _dns_insert_cname(q->name, (char *)*s + *l);
1067 *l = len;
1068
1069 x = *s + (len - 4);
1070
1071 p = (uint16_t *)x;
1072 *p = htons(q->dnstype);
1073 x += 2;
1074
1075 p = (uint16_t *)x;
1076 *p = htons(q->dnsclass);
1077
1078 }
1079
1080 static void
1081 _dns_append_resource_record(dns_resource_record_t *r, char **s, uint16_t *l)
1082 {
1083 uint16_t clen, len, *p, extra, rdlen;
1084 uint32_t *p2;
1085 char *x;
1086
1087 if (r == NULL) return;
1088
1089 extra = 10;
1090 switch (r->dnstype)
1091 {
1092 case ns_t_a:
1093 extra += 4;
1094 break;
1095 case ns_t_ptr:
1096 extra += 2;
1097 clen = _dns_cname_length(r->data.PTR->name);
1098 extra += clen;
1099 break;
1100 default: break;
1101 }
1102
1103 len = *l + _dns_cname_length(r->name) + 2 + extra;
1104 *s = realloc(*s, len);
1105
1106 _dns_insert_cname(r->name, (char *)*s + *l);
1107 *l = len;
1108
1109 x = *s + (len - extra);
1110
1111 p = (uint16_t *)x;
1112 *p = htons(r->dnstype);
1113 x += 2;
1114
1115 p = (uint16_t *)x;
1116 *p = htons(r->dnsclass);
1117 x += 2;
1118
1119 p2 = (uint32_t *)x;
1120 *p2 = htonl(r->ttl);
1121 x += 4;
1122
1123 switch (r->dnstype)
1124 {
1125 case ns_t_a:
1126 rdlen = 4;
1127 p = (uint16_t *)x;
1128 *p = htons(rdlen);
1129 x += 2;
1130
1131 p2 = (uint32_t *)x;
1132 *p2 = htons(r->data.A->addr.s_addr);
1133 x += 4;
1134 return;
1135
1136 case ns_t_ptr:
1137 clen = _dns_cname_length(r->data.PTR->name) + 2;
1138 p = (uint16_t *)x;
1139 *p = htons(clen);
1140 x += 2;
1141 _dns_insert_cname(r->data.PTR->name, x);
1142 x += clen;
1143 return;
1144
1145 default: return;
1146 }
1147 }
1148
1149 char *
1150 dns_build_reply(dns_reply_t *dnsr, uint16_t *rl)
1151 {
1152 uint16_t i, len;
1153 dns_header_t *h;
1154 char *s, *x;
1155
1156 if (dnsr == NULL) return NULL;
1157
1158 len = NS_HFIXEDSZ;
1159
1160 s = malloc(len);
1161 x = s + len;
1162
1163 memset(s, 0, len);
1164 *rl = len;
1165
1166 h = (dns_header_t *)s;
1167
1168 h->xid = htons(dnsr->header->xid);
1169 h->flags = htons(dnsr->header->flags);
1170 h->qdcount = htons(dnsr->header->qdcount);
1171 h->ancount = htons(dnsr->header->ancount);
1172 h->nscount = htons(dnsr->header->nscount);
1173 h->arcount = htons(dnsr->header->arcount);
1174
1175 for (i = 0; i < dnsr->header->qdcount; i++)
1176 {
1177 _dns_append_question(dnsr->question[i], &s, rl);
1178 }
1179
1180 for (i = 0; i < dnsr->header->ancount; i++)
1181 {
1182 _dns_append_resource_record(dnsr->answer[i], &s, rl);
1183 }
1184
1185 for (i = 0; i < dnsr->header->nscount; i++)
1186 {
1187 _dns_append_resource_record(dnsr->authority[i], &s, rl);
1188 }
1189
1190 for (i = 0; i < dnsr->header->arcount; i++)
1191 {
1192 _dns_append_resource_record(dnsr->additional[i], &s, rl);
1193 }
1194
1195 return s;
1196 }
1197
1198 void
1199 dns_free_question(dns_question_t *q)
1200 {
1201 if (q == NULL) return;
1202 if (q->name != NULL) free(q->name);
1203 free(q);
1204 }
1205
1206 void
1207 dns_set_buffer_size(dns_handle_t d, uint32_t len)
1208 {
1209 dns_private_handle_t *dns;
1210 if (d == NULL) return;
1211
1212 dns = (dns_private_handle_t *)d;
1213 if (dns->recvsize == len) return;
1214
1215 if (dns->recvbuf != NULL)
1216 {
1217 free(dns->recvbuf);
1218 dns->recvbuf = NULL;
1219 }
1220
1221 dns->recvsize = len;
1222 if (dns->recvsize > DNS_MAX_RECEIVE_SIZE) dns->recvsize = DNS_MAX_RECEIVE_SIZE;
1223
1224 if (dns->recvsize > 0) dns->recvbuf = malloc(dns->recvsize);
1225 }
1226
1227 uint32_t
1228 dns_get_buffer_size(dns_handle_t d)
1229 {
1230 dns_private_handle_t *dns;
1231 if (d == NULL) return 0;
1232
1233 dns = (dns_private_handle_t *)d;
1234 return dns->recvsize;
1235 }
1236
1237 dns_reply_t *
1238 dns_lookup_soa_min(dns_handle_t d, const char *name, uint32_t class, uint32_t type, int *min)
1239 {
1240 dns_private_handle_t *dns;
1241 dns_reply_t *r;
1242 int len;
1243 struct sockaddr_storage *from;
1244 uint32_t fromlen;
1245
1246 if (d == NULL) return NULL;
1247 if (name == NULL) return NULL;
1248
1249 dns = (dns_private_handle_t *)d;
1250 if (min != NULL) *min = -1;
1251
1252 if (dns->recvbuf == NULL)
1253 {
1254 if (dns->recvsize == 0) dns->recvsize = DNS_DEFAULT_RECEIVE_SIZE;
1255
1256 dns->recvbuf = malloc(dns->recvsize);
1257 if (dns->recvbuf == NULL) return NULL;
1258 }
1259
1260 fromlen = sizeof(struct sockaddr_storage);
1261 from = (struct sockaddr_storage *)calloc(1, sizeof(struct sockaddr_storage));
1262 len = -1;
1263
1264 if (dns->handle_type == DNS_PRIVATE_HANDLE_TYPE_SUPER)
1265 {
1266 _check_cache(dns->sdns);
1267 len = _sdns_search(dns->sdns, name, class, type, 0, 1, dns->recvbuf, dns->recvsize, (struct sockaddr *)from, &fromlen, min);
1268 }
1269 else
1270 {
1271 /* NB. Minumium SOA TTL values are NOT provided when the caller passes a DNS_PRIVATE_HANDLE_TYPE_PLAIN handle */
1272 len = _pdns_search(dns->sdns, dns->pdns, name, class, type, dns->recvbuf, dns->recvsize, (struct sockaddr *)from, &fromlen);
1273 }
1274
1275 if (len <= 0)
1276 {
1277 free(from);
1278 return NULL;
1279 }
1280
1281 r = dns_parse_packet(dns->recvbuf, len);
1282
1283 if (r == NULL) free(from);
1284 else r->server = (struct sockaddr *)from;
1285
1286 return r;
1287 }
1288
1289 dns_reply_t *
1290 dns_lookup(dns_handle_t d, const char *name, uint32_t class, uint32_t type)
1291 {
1292 int unused = 0;
1293
1294 return dns_lookup_soa_min(d, name, class, type, &unused);
1295 }
1296
1297 /*
1298 * DNS printing utilities
1299 */
1300
1301 static char *
1302 coord_ntoa(int32_t coord, uint32_t islat)
1303 {
1304 int32_t deg, min, sec, secfrac;
1305 static char buf[64];
1306 char dir;
1307
1308 coord = coord - 0x80000000;
1309 dir = 'N';
1310
1311 if ((islat == 1) && (coord < 0))
1312 {
1313 dir = 'S';
1314 coord = -coord;
1315 }
1316
1317 if (islat == 0)
1318 {
1319 dir = 'E';
1320 if (coord < 0)
1321 {
1322 dir = 'W';
1323 coord = -coord;
1324 }
1325 }
1326
1327 secfrac = coord % 1000;
1328 coord = coord / 1000;
1329 sec = coord % 60;
1330 coord = coord / 60;
1331 min = coord % 60;
1332 coord = coord / 60;
1333 deg = coord;
1334
1335 sprintf(buf, "%d %.2d %.2d.%.3d %c", deg, min, sec, secfrac, dir);
1336 return buf;
1337 }
1338
1339 static char *
1340 alt_ntoa(int32_t alt)
1341 {
1342 int32_t ref, m, frac, sign;
1343 static char buf[128];
1344
1345 ref = 100000 * 100;
1346 sign = 1;
1347
1348 if (alt < ref)
1349 {
1350 alt = ref - alt;
1351 sign = -1;
1352 }
1353 else
1354 {
1355 alt = alt - ref;
1356 }
1357
1358 frac = alt % 100;
1359 m = (alt / 100) * sign;
1360
1361 sprintf(buf, "%d.%.2d", m, frac);
1362 return buf;
1363 }
1364
1365 static unsigned int
1366 poweroften[10] =
1367 { 1,
1368 10,
1369 100,
1370 1000,
1371 10000,
1372 100000,
1373 1000000,
1374 10000000,
1375 100000000,
1376 1000000000
1377 };
1378
1379 static char *
1380 precsize_ntoa(uint8_t prec)
1381 {
1382 static char buf[19];
1383 unsigned long val;
1384 int mantissa, exponent;
1385
1386 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1387 exponent = (int)((prec >> 0) & 0x0f) % 10;
1388
1389 val = mantissa * poweroften[exponent];
1390
1391 sprintf(buf, "%ld.%.2ld", val/100, val%100);
1392 return buf;
1393 }
1394
1395 const char *
1396 dns_type_string(uint16_t t)
1397 {
1398 switch (t)
1399 {
1400 case ns_t_a: return "A ";
1401 case ns_t_ns: return "NS ";
1402 case ns_t_md: return "MD ";
1403 case ns_t_mf: return "MF ";
1404 case ns_t_cname: return "CNAME";
1405 case ns_t_soa: return "SOA ";
1406 case ns_t_mb: return "MB ";
1407 case ns_t_mg: return "MG ";
1408 case ns_t_mr: return "MR ";
1409 case ns_t_null: return "NULL ";
1410 case ns_t_wks: return "WKS ";
1411 case ns_t_ptr: return "PTR ";
1412 case ns_t_hinfo: return "HINFO";
1413 case ns_t_minfo: return "MINFO";
1414 case ns_t_mx: return "MX ";
1415 case ns_t_txt: return "TXT ";
1416 case ns_t_rp: return "PR ";
1417 case ns_t_afsdb: return "AFSDB";
1418 case ns_t_x25: return "X25 ";
1419 case ns_t_isdn: return "ISDN ";
1420 case ns_t_rt: return "RT ";
1421 case ns_t_nsap: return "NSAP ";
1422 case ns_t_nsap_ptr: return "NSPTR";
1423 case ns_t_sig: return "SIG ";
1424 case ns_t_key: return "KEY ";
1425 case ns_t_px: return "PX ";
1426 case ns_t_gpos: return "GPOS ";
1427 case ns_t_aaaa: return "AAAA ";
1428 case ns_t_loc: return "LOC ";
1429 case ns_t_nxt: return "NXT ";
1430 case ns_t_eid: return "EID ";
1431 case ns_t_nimloc: return "NIMLC";
1432 case ns_t_srv: return "SRV ";
1433 case ns_t_atma: return "ATMA ";
1434 case ns_t_naptr: return "NAPTR";
1435 case ns_t_kx: return "KX ";
1436 case ns_t_cert: return "CERT ";
1437 case ns_t_a6: return "A6 ";
1438 case ns_t_dname: return "DNAME";
1439 case ns_t_sink: return "SINK ";
1440 case ns_t_opt: return "OPT ";
1441 case ns_t_tkey: return "TKEY ";
1442 case ns_t_tsig: return "TSIG ";
1443 case ns_t_ixfr: return "IXFR ";
1444 case ns_t_axfr: return "AXFR ";
1445 case ns_t_mailb: return "MAILB";
1446 case ns_t_maila: return "MAILA";
1447 case ns_t_any: return "ANY ";
1448 case ns_t_zxfr: return "ZXFR ";
1449 default: return "?????";
1450 }
1451
1452 return "?????";
1453 }
1454
1455 int32_t
1456 dns_type_number(const char *t, uint16_t *n)
1457 {
1458 if (t == NULL) return -1;
1459
1460 if (!strcasecmp(t, "A")) { *n = ns_t_a; return 0; }
1461 if (!strcasecmp(t, "NS")) { *n = ns_t_ns; return 0; }
1462 if (!strcasecmp(t, "MD")) { *n = ns_t_md; return 0; }
1463 if (!strcasecmp(t, "MF")) { *n = ns_t_mf; return 0; }
1464 if (!strcasecmp(t, "CNAME")) { *n = ns_t_cname; return 0; }
1465 if (!strcasecmp(t, "SOA")) { *n = ns_t_soa; return 0; }
1466 if (!strcasecmp(t, "MB")) { *n = ns_t_mb; return 0; }
1467 if (!strcasecmp(t, "MG")) { *n = ns_t_mg; return 0; }
1468 if (!strcasecmp(t, "MR")) { *n = ns_t_mr; return 0; }
1469 if (!strcasecmp(t, "NULL")) { *n = ns_t_null; return 0; }
1470 if (!strcasecmp(t, "WKS")) { *n = ns_t_wks; return 0; }
1471 if (!strcasecmp(t, "PTR")) { *n = ns_t_ptr; return 0; }
1472 if (!strcasecmp(t, "HINFO")) { *n = ns_t_hinfo; return 0; }
1473 if (!strcasecmp(t, "MINFO")) { *n = ns_t_minfo; 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 }