4 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
20 static const char rcsid
[] = "Id: dig8.c,v 1.4 2009/03/03 23:49:07 tbox Exp";
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
59 * Permission to use, copy, modify, and distribute this software for any
60 * purpose with or without fee is hereby granted, provided that the above
61 * copyright notice and this permission notice appear in all copies, and that
62 * the name of Digital Equipment Corporation not be used in advertising or
63 * publicity pertaining to distribution of the document or software without
64 * specific, written prior permission.
66 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
67 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
68 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
69 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
70 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
71 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
72 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
77 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
78 * Portions Copyright (c) 1996-1999 by Internet Software Consortium
80 * Permission to use, copy, modify, and distribute this software for any
81 * purpose with or without fee is hereby granted, provided that the above
82 * copyright notice and this permission notice appear in all copies.
84 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
85 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
86 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
87 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
88 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
89 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
90 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
93 /*********************** Notes for the BIND 4.9 release (Paul Vixie, DEC)
94 * dig 2.0 was written by copying sections of libresolv.a and nslookup
95 * and modifying them to be more useful for a general lookup utility.
96 * as of BIND 4.9, the changes needed to support dig have mostly been
97 * incorporated into libresolv.a and nslookup; dig now links against
98 * some of nslookup's .o files rather than #including them or maintaining
99 * local copies of them.
101 * while merging dig back into the BIND release, i made a number of
102 * structural changes. for one thing, i put all of dig's private
103 * library routines into this file rather than maintaining them in
104 * separate, #included, files. i don't like to #include ".c" files.
105 * i removed all calls to "bcopy", replacing them with structure
106 * assignments. i removed all "extern"'s of standard functions,
107 * replacing them with #include's of standard header files. this
108 * version of dig is probably as portable as the rest of BIND.
110 * i had to remove the query-time and packet-count statistics since
111 * the current libresolv.a is a lot harder to modify to maintain these
112 * than the 4.8 one (used in the original dig) was. for consolation,
113 * i added a "usage" message with extensive help text.
115 * to save my (limited, albeit) sanity, i ran "indent" over the source.
116 * i also added the standard berkeley/DEC copyrights, since this file now
117 * contains a fair amount of non-USC code. note that the berkeley and
118 * DEC copyrights do not prohibit redistribution, with or without fee;
119 * we add them only to protect ourselves (you have to claim copyright
120 * in order to disclaim liability and warranty).
122 * Paul Vixie, Palo Alto, CA, April 1993
123 ****************************************************************************
125 ******************************************************************
126 * DiG -- Domain Information Groper *
128 * dig.c - Version 2.1 (7/12/94) ("BIND takeover") *
130 * Developed by: Steve Hotz & Paul Mockapetris *
131 * USC Information Sciences Institute (USC-ISI) *
132 * Marina del Rey, California *
136 * Version 2.0 (9/1/90) *
137 * o renamed difftime() difftv() to avoid *
138 * clash with ANSI C *
139 * o fixed incorrect # args to strcmp,gettimeofday *
140 * o incorrect length specified to strncmp *
141 * o fixed broken -sticky -envsa -envset functions *
142 * o print options/flags redefined & modified *
144 * Version 2.0.beta (5/9/90) *
145 * o output format - helpful to `doc` *
147 * o release to beta testers *
149 * Version 1.1.beta (10/26/89) *
150 * o hanging zone transer (when REFUSED) fixed *
151 * o trailing dot added to domain names in RDATA *
154 * Version 1.0.tmp (8/27/89) *
155 * o Error in prnttime() fixed *
156 * o no longer dumps core on large pkts *
157 * o zone transfer (axfr) added *
158 * o -x added for inverse queries *
159 * (i.e. "dig -x 128.9.0.32") *
160 * o give address of default server *
161 * o accept broadcast to server @255.255.255.255 *
163 * Version 1.0 (3/27/89) *
164 * o original release *
166 * DiG is Public Domain, and may be used for any purpose as *
167 * long as this notice is not removed. *
168 ******************************************************************/
172 #include "port_before.h"
174 #include <sys/types.h>
175 #include <sys/param.h>
176 #include <sys/file.h>
177 #include <sys/stat.h>
178 #include <sys/socket.h>
179 #include <sys/time.h>
180 #include <sys/wait.h>
182 #include <netinet/in.h>
183 #include <arpa/inet.h>
184 #include <arpa/nameser.h>
198 #include <time.h> /* time(2), ctime(3) */
200 #include "port_after.h"
209 #define VSTRING "8.4"
211 #define PRF_DEF (RES_PRF_STATS | RES_PRF_CMD | RES_PRF_QUES | \
212 RES_PRF_ANS | RES_PRF_AUTH | RES_PRF_ADD | \
213 RES_PRF_HEAD1 | RES_PRF_HEAD2 | RES_PRF_TTLID | \
214 RES_PRF_HEADX | RES_PRF_REPLY | RES_PRF_TRUNC)
215 #define PRF_MIN (RES_PRF_QUES | RES_PRF_ANS | RES_PRF_HEAD1 | \
216 RES_PRF_HEADX | RES_PRF_REPLY | RES_PRF_TRUNC)
217 #define PRF_ZONE (RES_PRF_STATS | RES_PRF_CMD | RES_PRF_QUES | \
218 RES_PRF_ANS | RES_PRF_AUTH | RES_PRF_ADD | \
219 RES_PRF_TTLID | RES_PRF_REPLY | RES_PRF_TRUNC)
221 #ifndef MAXHOSTNAMELEN
222 #define MAXHOSTNAMELEN 256
225 #define SAVEENV "DiG.env"
226 #define DIG_MAXARGS 30
229 #define DIG_PING "ping"
232 #define DIG_TAIL "tail"
235 #define DIG_PINGFMT "%s -s %s 56 3 | %s -3"
238 static int eecode
= 0;
240 static char myhostname
[MAXHOSTNAMELEN
];
241 static struct sockaddr_in myaddress
;
242 static struct sockaddr_in6 myaddress6
;
243 static u_int32_t ixfr_serial
;
244 static char ubuf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123")];
246 /* stuff for nslookup modules */
247 struct __res_state res
;
250 HostInfo
*defaultPtr
= NULL
;
251 HostInfo curHostInfo
, defaultRec
;
252 int curHostValid
= FALSE
;
253 int queryType
, queryClass
;
254 extern int StringToClass(), StringToType(); /* subr.c */
255 #if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD)
257 void yyrestart(FILE *f
);
258 void yyrestart(FILE *f
) { UNUSED(f
); }
261 /* end of nslookup stuff */
265 static void Usage(void);
266 static int setopt(const char *);
267 static void res_re_init(void);
268 static int xstrtonum(char *);
269 static int printZone(ns_type
, const char *,
270 const struct sockaddr_in
*, ns_tsig_key
*);
271 static int print_axfr(FILE *output
, const u_char
*msg
,
273 static struct timeval
difftv(struct timeval
, struct timeval
);
274 static void prnttime(struct timeval
);
275 static void stackarg(char *, char **);
276 static void reverse6(char *, struct in6_addr
*);
281 main(int argc
, char **argv
) {
282 short port
= htons(NAMESERVER_PORT
);
284 /* Wierd stuff for SPARC alignment, hurts nothing else. */
287 u_char packet_
[PACKETSZ
];
289 #define header (packet_.header_)
290 #define packet (packet_.packet_)
299 char *addrc
, *addrend
, *addrbegin
;
302 struct timeval tv1
, tv2
, start_time
, end_time
, query_time
;
309 ns_type xfr
= ns_t_invalid
;
310 int bytes_out
, bytes_in
;
313 char domain
[MAXDNAME
];
314 char msg
[120], **vtmp
;
315 char *args
[DIG_MAXARGS
];
317 int once
= 1, dofile
= 0; /* batch -vs- interactive control */
321 int envset
=0, envsave
=0;
322 struct __res_state res_x
, res_t
;
327 char *keyfile
= NULL
, *keyname
= NULL
;
328 const char *pingfmt
= NULL
;
333 res
.pfcode
= PRF_DEF
;
335 memset(domain
, 0, sizeof domain
);
336 gethostname(myhostname
, (sizeof myhostname
));
338 myaddress
.sin_len
= sizeof(struct sockaddr_in
);
340 myaddress
.sin_family
= AF_INET
;
341 myaddress
.sin_addr
.s_addr
= INADDR_ANY
;
342 myaddress
.sin_port
= 0; /*INPORT_ANY*/;
345 myaddress6
.sin6_len
= sizeof(struct sockaddr_in6
);
347 myaddress6
.sin6_family
= AF_INET6
;
348 myaddress6
.sin6_addr
= in6addr_any
;
349 myaddress6
.sin6_port
= 0; /*INPORT_ANY*/;
354 * If LOCALDEF in environment, should point to file
355 * containing local favourite defaults. Also look for file
356 * DiG.env (i.e. SAVEENV) in local directory.
359 if ((((afile
= (char *) getenv("LOCALDEF")) != (char *) NULL
) &&
360 ((fp
= open(afile
, O_RDONLY
)) > 0)) ||
361 ((fp
= open(SAVEENV
, O_RDONLY
)) > 0)) {
362 read(fp
, (char *)&res_x
, (sizeof res_x
));
367 * Check for batch-mode DiG; also pre-scan for 'help'.
371 while (*vtmp
!= NULL
) {
372 if (strcmp(*vtmp
, "-h") == 0 ||
373 strcmp(*vtmp
, "-help") == 0 ||
374 strcmp(*vtmp
, "-usage") == 0 ||
375 strcmp(*vtmp
, "help") == 0) {
380 if (strcmp(*vtmp
, "-f") == 0) {
382 if ((qfp
= fopen(*++vtmp
, "r")) == NULL
) {
389 if (ax
- args
== DIG_MAXARGS
) {
390 fprintf(stderr
, "dig: too many arguments\n");
398 gettimeofday(&tv1
, NULL
);
401 * Main section: once if cmd-line query
402 * while !EOF if batch mode
405 while ((dofile
&& fgets(fileq
, sizeof fileq
, qfp
) != NULL
) ||
408 if (*fileq
== '\n' || *fileq
== '#' || *fileq
==';') {
409 printf("%s", fileq
); /* echo but otherwise ignore */
410 continue; /* blank lines and comments */
414 * "Sticky" requests that before current parsing args
415 * return to current "working" environment (X******).
418 printf(";; (using sticky settings)\n");
423 * Concat cmd-line and file args.
429 queryClass
= ns_c_in
;
434 sprintf(cmd
, "\n; <<>> DiG %s (libbind %d) <<>> ",
437 /* argc = ax - args; */
439 * More cmd-line options than anyone should ever have to
442 while (*(++argv
) != NULL
&& **argv
!= '\0') {
443 if (strlen(cmd
) + strlen(*argv
) + 2 > sizeof (cmd
)) {
445 "Argument too large for input buffer\n");
461 ixfr_serial
= strtoul(*argv
+1, NULL
, 0);
464 if (strncmp(*argv
, "-nost", 5) == 0) {
467 } else if (strncmp(*argv
, "-st", 3) == 0) {
470 } else if (strncmp(*argv
, "-envsa", 6) == 0) {
473 } else if (strncmp(*argv
, "-envse", 6) == 0) {
479 switch (argv
[0][1]) {
482 printf("; no arg for -T?\n");
488 printf("; no arg for -c?\n");
489 else if ((tmp
= atoi(*argv
))
490 || *argv
[0] == '0') {
492 } else if ((tmp
= StringToClass(*argv
,
498 "; invalid class specified\n"
504 printf("; no arg for -t?\n");
505 else if ((tmp
= atoi(*argv
))
507 if (ns_t_xfr_p(tmp
)) {
513 } else if ((tmp
= StringToType(*argv
,
516 if (ns_t_xfr_p(tmp
)) {
524 "; invalid type specified\n"
533 if ((addrc
= *++argv
) == NULL
) {
534 printf("; no arg for -x?\n");
537 r
= inet_pton(AF_INET6
, addrc
, &in6
);
539 reverse6(domain
, &in6
);
542 addrend
= addrc
+ strlen(addrc
);
546 while ((addrbegin
= strrchr(addrc
,'.'))) {
547 strcat(domain
, addrbegin
+1);
551 strcat(domain
, addrc
);
552 strcat(domain
, ".in-addr.arpa.");
555 if (argv
[0][2] != '\0')
556 port
= htons(atoi(argv
[0]+2));
557 else if (*++argv
== NULL
)
558 printf("; no arg for -p?\n");
560 port
= htons(atoi(*argv
));
563 if (argv
[0][2] != '\0') {
564 strcpy(pingstr
, argv
[0]+2);
566 "%s %s 56 3 | %s -3";
568 strcpy(pingstr
, DIG_PING
);
569 pingfmt
= DIG_PINGFMT
;
573 if (argv
[0][2] != '\0')
574 res
.ndots
= atoi(argv
[0]+2);
575 else if (*++argv
== NULL
)
576 printf("; no arg for -n?\n");
578 res
.ndots
= atoi(*argv
);
583 if (argv
[0][2] != '\0')
585 else if (*++argv
== NULL
) {
586 printf("; no arg for -b?\n");
590 if ((p
= strchr(a
, ':')) != NULL
) {
592 lport
= htons(atoi(p
));
595 if (inet_pton(AF_INET6
, a
,
596 &myaddress6
.sin6_addr
) == 1) {
597 myaddress6
.sin6_port
= lport
;
598 } else if (!inet_aton(a
,
599 &myaddress
.sin_addr
)) {
604 myaddress
.sin_port
= lport
;
608 /* -k keydir:keyname */
610 if (argv
[0][2] != '\0')
612 else if (*++argv
== NULL
) {
613 printf("; no arg for -k?\n");
618 keyname
= strchr(keyfile
, ':');
619 if (keyname
== NULL
) {
621 "key option argument should be keydir:keyname\n");
630 if ((tmp
= StringToType(*argv
, -1, NULL
)) != -1) {
631 if ((T_ANY
== tmp
) && anyflag
++) {
635 if (ns_t_xfr_p(tmp
) &&
637 (res
.options
& RES_USEVC
) != 0)
639 res
.pfcode
= PRF_ZONE
;
645 } else if ((tmp
= StringToClass(*argv
, -1, NULL
))
649 memset(domain
, 0, sizeof domain
);
650 sprintf(domain
,"%s",*argv
);
652 } /* while argv remains */
654 /* process key options */
658 char buf
[BUFSIZ
], *p
;
660 int file_major
, file_minor
, alg
;
662 fp
= fopen(keyfile
, "r");
667 /* Now read the header info from the file. */
668 i
= fread(buf
, 1, BUFSIZ
, fp
);
677 n
=strlen(p
); /* get length of strings */
678 n1
=strlen("Private-key-format: v");
680 strncmp(buf
, "Private-key-format: v", n1
)) {
681 fprintf(stderr
, "Invalid key file format\n");
682 exit(1); /* not a match */
684 p
+=n1
; /* advance pointer */
685 sscanf((char *)p
, "%d.%d", &file_major
, &file_minor
);
686 /* should do some error checking with these someday */
687 while (*p
++!='\n'); /* skip to end of line */
689 n
=strlen(p
); /* get length of strings */
690 n1
=strlen("Algorithm: ");
691 if (n1
> n
|| strncmp(p
, "Algorithm: ", n1
)) {
692 fprintf(stderr
, "Invalid key file format\n");
693 exit(1); /* not a match */
695 p
+=n1
; /* advance pointer */
696 if (sscanf((char *)p
, "%d", &alg
)!=1) {
697 fprintf(stderr
, "Invalid key file format\n");
700 while (*p
++!='\n'); /* skip to end of line */
702 n
=strlen(p
); /* get length of strings */
704 if (n1
> n
|| strncmp(p
, "Key: ", n1
)) {
705 fprintf(stderr
, "Invalid key file format\n");
706 exit(1); /* not a match */
708 p
+=n1
; /* advance pointer */
710 while (*pp
++!='\n'); /* skip to end of line,
714 key
.data
=malloc(1024*sizeof(char));
715 key
.len
=b64_pton(p
, key
.data
, 1024);
717 strcpy(key
.name
, keyname
);
718 strcpy(key
.alg
, "HMAC-MD5.SIG-ALG.REG.INT");
720 /* use the dst* routines to parse the key files
722 * This requires that both the .key and the .private
723 * files exist in your cwd, so the keyfile parmeter
724 * here is assumed to be a path in which the
725 * K*.{key,private} files exist.
728 char cwd
[PATH_MAX
+1];
730 if (getcwd(cwd
, PATH_MAX
)==NULL
) {
731 perror("unable to get current directory");
734 if (chdir(keyfile
)<0) {
736 "unable to chdir to %s: %s\n", keyfile
,
742 dst_key
= dst_read_key(keyname
,
743 0 /* not used for priv keys */,
744 KEY_HMAC_MD5
, DST_PRIVATE
);
747 "dst_read_key: error reading key\n");
750 key
.data
=malloc(1024*sizeof(char));
751 dst_key_to_buffer(dst_key
, key
.data
, 1024);
752 key
.len
=dst_key
->dk_key_size
;
754 strcpy(key
.name
, keyname
);
755 strcpy(key
.alg
, "HMAC-MD5.SIG-ALG.REG.INT");
758 fprintf(stderr
, "unable to chdir to %s: %s\n",
759 cwd
, strerror(errno
));
765 if (res
.pfcode
& 0x80000)
766 printf("; pfcode: %08lx, options: %08lx\n",
767 (unsigned long)res
.pfcode
,
768 (unsigned long)res
.options
);
771 * Current env. (after this parse) is to become the
772 * new "working" environmnet. Used in conj. with sticky.
780 * Current env. (after this parse) is to become the
781 * new default saved environmnet. Save in user specified
782 * file if exists else is SAVEENV (== "DiG.env").
785 afile
= (char *) getenv("LOCALDEF");
788 O_WRONLY
|O_CREAT
|O_TRUNC
,
789 S_IREAD
|S_IWRITE
)) > 0))
792 O_WRONLY
|O_CREAT
|O_TRUNC
,
793 S_IREAD
|S_IWRITE
)) > 0)) {
794 write(fp
, (char *)&res
, (sizeof res
));
800 if (res
.pfcode
& RES_PRF_CMD
)
806 * Find address of server to query. If not dot-notation, then
807 * try to resolve domain-name (if so, save and turn off print
808 * options, this domain-query is not the one we want. Restore
809 * user options when done.
810 * Things get a bit wierd since we need to use resolver to be
811 * able to "put the resolver to work".
816 union res_sockaddr_union u
[MAXNS
];
817 struct addrinfo
*answer
= NULL
;
818 struct addrinfo
*cur
= NULL
;
819 struct addrinfo hint
;
821 memset(u
, 0, sizeof(u
));
825 res
.options
= RES_DEFAULT
;
826 memset(&hint
, 0, sizeof(hint
));
827 hint
.ai_socktype
= SOCK_DGRAM
;
828 if (!getaddrinfo(srv
, NULL
, &hint
, &answer
)) {
833 cur
= cur
->ai_next
) {
834 if (nscount
== MAXNS
)
836 switch (cur
->ai_addr
->sa_family
) {
839 *(struct sockaddr_in6
*)cur
->ai_addr
;
840 u
[nscount
++].sin6
.sin6_port
=
845 *(struct sockaddr_in
*)cur
->ai_addr
;
846 u
[nscount
++].sin
.sin_port
=
852 res_setservers(&res
, u
, nscount
);
853 freeaddrinfo(answer
);
858 "; Bad server: %s -- using default server and timer opts\n",
863 printf("; (%d server%s found)\n",
864 res
.nscount
, (res
.nscount
==1)?"":"s");
868 if (ns_t_xfr_p(xfr
)) {
871 union res_sockaddr_union u
[MAXNS
];
872 nscount
= res_getservers(&res
, u
, MAXNS
);
873 for (i
= 0; i
< nscount
; i
++) {
877 x
= printZone(xfr
, domain
,
881 x
= printZone(xfr
, domain
,
884 if (res
.pfcode
& RES_PRF_STATS
) {
885 exectime
= time(NULL
);
886 printf(";; FROM: %s to SERVER: %s\n",
890 printf(";; WHEN: %s", ctime(&exectime
));
899 if (*domain
&& !qtypeSet
) {
904 bytes_out
= n
= res_nmkquery(&res
, QUERY
, domain
,
905 queryClass
, queryType
,
907 packet
, sizeof packet
);
910 printf(";; res_nmkquery: buffer too small\n\n");
914 if (queryType
== T_IXFR
) {
915 HEADER
*hp
= (HEADER
*) packet
;
916 u_char
*cpp
= packet
+ bytes_out
;
918 hp
->nscount
= htons(1+ntohs(hp
->nscount
));
919 n
= dn_comp(domain
, cpp
,
920 (sizeof packet
) - (cpp
- packet
),
923 PUTSHORT(T_SOA
, cpp
); /* type */
924 PUTSHORT(C_IN
, cpp
); /* class */
925 PUTLONG(0, cpp
); /* ttl */
926 PUTSHORT(22, cpp
); /* dlen */
927 *cpp
++ = 0; /* mname */
928 *cpp
++ = 0; /* rname */
929 PUTLONG(ixfr_serial
, cpp
);
930 PUTLONG(0xDEAD, cpp
); /* Refresh */
931 PUTLONG(0xBEEF, cpp
); /* Retry */
932 PUTLONG(0xABCD, cpp
); /* Expire */
933 PUTLONG(0x1776, cpp
); /* Min TTL */
934 bytes_out
= n
= cpp
- packet
;
937 #if defined(RES_USE_EDNS0) && defined(RES_USE_DNSSEC)
939 (res
.options
& (RES_USE_EDNS0
|RES_USE_DNSSEC
)) != 0)
940 bytes_out
= n
= res_nopt(&res
, n
, packet
,
941 sizeof(packet
), 4096);
945 if (res
.pfcode
& RES_PRF_HEAD1
)
946 fp_resstat(&res
, stdout
);
947 (void) gettimeofday(&start_time
, NULL
);
949 n
= res_nsendsigned(&res
, packet
, n
, &key
,
950 answer
.b
, sizeof(answer
.b
));
952 n
= res_nsend(&res
, packet
, n
,
953 answer
.b
, sizeof(answer
.b
));
954 if ((bytes_in
= n
) < 0) {
958 strcpy(msg
, ";; res_nsendsigned");
960 strcpy(msg
, ";; res_nsend");
971 (void) gettimeofday(&end_time
, NULL
);
973 if (res
.pfcode
& RES_PRF_STATS
) {
974 union res_sockaddr_union u
[MAXNS
];
976 (void) res_getservers(&res
, u
, MAXNS
);
977 query_time
= difftv(start_time
, end_time
);
978 printf(";; Total query time: ");
979 prnttime(query_time
);
981 exectime
= time(NULL
);
982 printf(";; FROM: %s to SERVER: %s\n", myhostname
,
983 p_sockun(u
[RES_GETLAST(res
)],
984 ubuf
, sizeof(ubuf
)));
985 printf(";; WHEN: %s", ctime(&exectime
));
986 printf(";; MSG SIZE sent: %d rcvd: %d\n",
987 bytes_out
, bytes_in
);
992 * Argh ... not particularly elegant. Should put in *real* ping code.
993 * Would necessitate root priviledges for icmp port though!
995 if (*pingstr
&& srv
!= NULL
) {
996 sprintf(doping
, pingfmt
, pingstr
, srv
, DIG_TAIL
);
1002 * Fairly crude method and low overhead method of keeping two
1003 * batches started at different sites somewhat synchronized.
1005 gettimeofday(&tv2
, NULL
);
1006 delay
= (int)(tv2
.tv_sec
- tv1
.tv_sec
);
1008 sleep(wait
- delay
);
1020 usage: dig [@server] [domain] [q-type] [q-class] {q-opt} {d-opt} [%comment]\n\
1022 domain are names in the Domain Name System\n\
1023 q-class is one of (in,any,...) [default: in]\n\
1024 q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default: a]\n\
1028 -x dot-notation-address (shortcut to in-addr.arpa lookups)\n\
1029 -f file (batch mode input file name)\n\
1030 -T time (batch mode time delay, per query)\n\
1031 -p port (nameserver is on this port) [53]\n\
1032 -b addr[:port] (bind AXFR to this tcp address) [*]\n\
1033 -P[ping-string] (see man page)\n\
1034 -t query-type (synonym for q-type)\n\
1035 -c query-class (synonym for q-class)\n\
1036 -k keydir:keyname (sign the query with this TSIG key)\n\
1037 -envsav,-envset (see man page)\n\
1038 -[no]stick (see man page)\n\
1041 d-opt is of the form ``+keyword=value'' where keyword is one of:\n\
1042 [no]debug [no]d2 [no]recurse retry=# time=# [no]ko [no]vc\n\
1043 [no]defname [no]search domain=NAME [no]ignore [no]primary\n\
1044 [no]aaonly [no]cmd [no]stats [no]Header [no]header [no]trunc\n\
1045 [no]ttlid [no]cl [no]qr [no]reply [no]ques [no]answer\n\
1046 [no]author [no]addit [no]dnssec pfdef pfmin\n\
1047 pfset=# pfand=# pfor=#\n\
1050 notes: defname and search don't work; use fully-qualified names.\n\
1051 this is DiG version %s (libbind %d)\n\
1052 Id: dig8.c,v 1.4 2009/03/03 23:49:07 tbox Exp\n", VSTRING
, __RES
);
1056 setopt(const char *string
) {
1057 char option
[NAME_LEN
], *ptr
;
1060 i
= pickString(string
, option
, sizeof option
);
1062 fprintf(stderr
, ";*** Invalid option: %s\n", string
);
1064 /* this is ugly, but fixing the caller to behave
1065 properly with an error return value would require a major
1070 if (strncmp(option
, "aa", 2) == 0) { /* aaonly */
1071 res
.options
|= RES_AAONLY
;
1072 } else if (strncmp(option
, "noaa", 4) == 0) {
1073 res
.options
&= ~RES_AAONLY
;
1074 } else if (strncmp(option
, "deb", 3) == 0) { /* debug */
1075 res
.options
|= RES_DEBUG
;
1076 } else if (strncmp(option
, "nodeb", 5) == 0) {
1077 res
.options
&= ~(RES_DEBUG
| RES_DEBUG2
);
1078 } else if (strncmp(option
, "ko", 2) == 0) { /* keepopen */
1079 res
.options
|= (RES_STAYOPEN
| RES_USEVC
);
1080 } else if (strncmp(option
, "noko", 4) == 0) {
1081 res
.options
&= ~RES_STAYOPEN
;
1082 } else if (strncmp(option
, "d2", 2) == 0) { /* d2 (more debug) */
1083 res
.options
|= (RES_DEBUG
| RES_DEBUG2
);
1084 } else if (strncmp(option
, "nod2", 4) == 0) {
1085 res
.options
&= ~RES_DEBUG2
;
1086 } else if (strncmp(option
, "def", 3) == 0) { /* defname */
1087 res
.options
|= RES_DEFNAMES
;
1088 } else if (strncmp(option
, "nodef", 5) == 0) {
1089 res
.options
&= ~RES_DEFNAMES
;
1090 } else if (strncmp(option
, "dn", 2) == 0) { /* dnssec */
1091 res
.options
|= RES_USE_DNSSEC
;
1092 } else if (strncmp(option
, "nodn", 4) == 0) {
1093 res
.options
&= ~RES_USE_DNSSEC
;
1094 } else if (strncmp(option
, "sea", 3) == 0) { /* search list */
1095 res
.options
|= RES_DNSRCH
;
1096 } else if (strncmp(option
, "nosea", 5) == 0) {
1097 res
.options
&= ~RES_DNSRCH
;
1098 } else if (strncmp(option
, "do", 2) == 0) { /* domain */
1099 ptr
= strchr(option
, '=');
1101 i
= pickString(++ptr
, res
.defdname
, sizeof res
.defdname
);
1102 if (i
== 0) { /* value's too long or non-existant. This actually
1103 shouldn't happen due to pickString()
1105 fprintf(stderr
, "*** Invalid domain: %s\n", ptr
) ;
1106 exit(9); /* see comment at previous call to exit()*/
1109 } else if (strncmp(option
, "ti", 2) == 0) { /* timeout */
1110 ptr
= strchr(option
, '=');
1112 sscanf(++ptr
, "%d", &res
.retrans
);
1113 } else if (strncmp(option
, "ret", 3) == 0) { /* retry */
1114 ptr
= strchr(option
, '=');
1116 sscanf(++ptr
, "%d", &res
.retry
);
1117 } else if (strncmp(option
, "i", 1) == 0) { /* ignore */
1118 res
.options
|= RES_IGNTC
;
1119 } else if (strncmp(option
, "noi", 3) == 0) {
1120 res
.options
&= ~RES_IGNTC
;
1121 } else if (strncmp(option
, "pr", 2) == 0) { /* primary */
1122 res
.options
|= RES_PRIMARY
;
1123 } else if (strncmp(option
, "nop", 3) == 0) {
1124 res
.options
&= ~RES_PRIMARY
;
1125 } else if (strncmp(option
, "rec", 3) == 0) { /* recurse */
1126 res
.options
|= RES_RECURSE
;
1127 } else if (strncmp(option
, "norec", 5) == 0) {
1128 res
.options
&= ~RES_RECURSE
;
1129 } else if (strncmp(option
, "v", 1) == 0) { /* vc */
1130 res
.options
|= RES_USEVC
;
1131 } else if (strncmp(option
, "nov", 3) == 0) {
1132 res
.options
&= ~RES_USEVC
;
1133 } else if (strncmp(option
, "pfset", 5) == 0) {
1134 ptr
= strchr(option
, '=');
1136 res
.pfcode
= xstrtonum(++ptr
);
1137 } else if (strncmp(option
, "pfand", 5) == 0) {
1138 ptr
= strchr(option
, '=');
1140 res
.pfcode
= res
.pfcode
& xstrtonum(++ptr
);
1141 } else if (strncmp(option
, "pfor", 4) == 0) {
1142 ptr
= strchr(option
, '=');
1144 res
.pfcode
|= xstrtonum(++ptr
);
1145 } else if (strncmp(option
, "pfmin", 5) == 0) {
1146 res
.pfcode
= PRF_MIN
;
1147 } else if (strncmp(option
, "pfdef", 5) == 0) {
1148 res
.pfcode
= PRF_DEF
;
1149 } else if (strncmp(option
, "an", 2) == 0) { /* answer section */
1150 res
.pfcode
|= RES_PRF_ANS
;
1151 } else if (strncmp(option
, "noan", 4) == 0) {
1152 res
.pfcode
&= ~RES_PRF_ANS
;
1153 } else if (strncmp(option
, "qu", 2) == 0) { /* question section */
1154 res
.pfcode
|= RES_PRF_QUES
;
1155 } else if (strncmp(option
, "noqu", 4) == 0) {
1156 res
.pfcode
&= ~RES_PRF_QUES
;
1157 } else if (strncmp(option
, "au", 2) == 0) { /* authority section */
1158 res
.pfcode
|= RES_PRF_AUTH
;
1159 } else if (strncmp(option
, "noau", 4) == 0) {
1160 res
.pfcode
&= ~RES_PRF_AUTH
;
1161 } else if (strncmp(option
, "ad", 2) == 0) { /* addition section */
1162 res
.pfcode
|= RES_PRF_ADD
;
1163 } else if (strncmp(option
, "noad", 4) == 0) {
1164 res
.pfcode
&= ~RES_PRF_ADD
;
1165 } else if (strncmp(option
, "tt", 2) == 0) { /* TTL & ID */
1166 res
.pfcode
|= RES_PRF_TTLID
;
1167 } else if (strncmp(option
, "nott", 4) == 0) {
1168 res
.pfcode
&= ~RES_PRF_TTLID
;
1169 } else if (strncmp(option
, "tr", 2) == 0) { /* TTL & ID */
1170 res
.pfcode
|= RES_PRF_TRUNC
;
1171 } else if (strncmp(option
, "notr", 4) == 0) {
1172 res
.pfcode
&= ~RES_PRF_TRUNC
;
1173 } else if (strncmp(option
, "he", 2) == 0) { /* head flags stats */
1174 res
.pfcode
|= RES_PRF_HEAD2
;
1175 } else if (strncmp(option
, "nohe", 4) == 0) {
1176 res
.pfcode
&= ~RES_PRF_HEAD2
;
1177 } else if (strncmp(option
, "H", 1) == 0) { /* header all */
1178 res
.pfcode
|= RES_PRF_HEADX
;
1179 } else if (strncmp(option
, "noH", 3) == 0) {
1180 res
.pfcode
&= ~(RES_PRF_HEADX
);
1181 } else if (strncmp(option
, "qr", 2) == 0) { /* query */
1182 res
.pfcode
|= RES_PRF_QUERY
;
1183 } else if (strncmp(option
, "noqr", 4) == 0) {
1184 res
.pfcode
&= ~RES_PRF_QUERY
;
1185 } else if (strncmp(option
, "rep", 3) == 0) { /* reply */
1186 res
.pfcode
|= RES_PRF_REPLY
;
1187 } else if (strncmp(option
, "norep", 5) == 0) {
1188 res
.pfcode
&= ~RES_PRF_REPLY
;
1189 } else if (strncmp(option
, "cm", 2) == 0) { /* command line */
1190 res
.pfcode
|= RES_PRF_CMD
;
1191 } else if (strncmp(option
, "nocm", 4) == 0) {
1192 res
.pfcode
&= ~RES_PRF_CMD
;
1193 } else if (strncmp(option
, "cl", 2) == 0) { /* class mnemonic */
1194 res
.pfcode
|= RES_PRF_CLASS
;
1195 } else if (strncmp(option
, "nocl", 4) == 0) {
1196 res
.pfcode
&= ~RES_PRF_CLASS
;
1197 } else if (strncmp(option
, "st", 2) == 0) { /* stats*/
1198 res
.pfcode
|= RES_PRF_STATS
;
1199 } else if (strncmp(option
, "nost", 4) == 0) {
1200 res
.pfcode
&= ~RES_PRF_STATS
;
1202 fprintf(stderr
, "; *** Invalid option: %s\n", option
);
1210 * Force a reinitialization when the domain is changed.
1214 static char localdomain
[] = "LOCALDOMAIN";
1215 u_long pfcode
= res
.pfcode
, options
= res
.options
;
1216 unsigned ndots
= res
.ndots
;
1217 int retrans
= res
.retrans
, retry
= res
.retry
;
1221 * This is ugly but putenv() is more portable than setenv().
1223 buf
= malloc((sizeof localdomain
) + strlen(res
.defdname
) +10/*fuzz*/);
1224 sprintf(buf
, "%s=%s", localdomain
, res
.defdname
);
1225 putenv(buf
); /* keeps the argument, so we won't free it */
1227 res
.pfcode
= pfcode
;
1228 res
.options
= options
;
1230 res
.retrans
= retrans
;
1235 * convert char string (decimal, octal, or hex) to integer
1238 xstrtonum(char *p
) {
1249 if (isupper((unsigned char)*p
))
1255 if (isdigit((unsigned char)*p
)) {
1257 } else if (isxdigit((unsigned char)*p
)) {
1261 "; *** Bad char in numeric string..ignored\n");
1266 "; *** Bad char in numeric string..ignored\n");
1278 u_char qb2
[PACKETSZ
];
1282 printZone(ns_type xfr
, const char *zone
, const struct sockaddr_in
*sin
,
1285 static u_char
*answer
= NULL
;
1286 static int answerLen
= 0;
1289 int msglen
, amtToRead
, numRead
, result
, sockFD
, len
;
1290 int count
, type
, rlen
, done
, n
;
1291 int numAnswers
, numRecords
, soacnt
;
1292 u_char
*cp
, tmp
[NS_INT16SZ
];
1293 char dname
[2][NS_MAXDNAME
];
1294 enum { NO_ERRORS
, ERR_READING_LEN
, ERR_READING_MSG
, ERR_PRINTING
}
1299 ns_tcp_tsig_state tsig_state
;
1300 int tsig_ret
, tsig_required
, tsig_present
;
1307 fprintf(stderr
, ";; %s - transfer type not supported\n",
1313 * Create a query packet for the requested zone name.
1315 msglen
= res_nmkquery(&res
, ns_o_query
, zone
,
1316 queryClass
, ns_t_axfr
, NULL
,
1317 0, 0, buf
.qb2
, sizeof buf
);
1319 if (res
.options
& RES_DEBUG
)
1320 fprintf(stderr
, ";; res_nmkquery failed\n");
1325 * Sign the message if a key was sent
1328 newmsg
= (u_char
*)&buf
;
1332 int bufsize
, siglen
;
1336 /* ns_sign() also calls dst_init(), but there is no harm
1341 bufsize
= msglen
+ 1024;
1342 newmsg
= (u_char
*) malloc(bufsize
);
1343 if (newmsg
== NULL
) {
1347 memcpy(newmsg
, (u_char
*)&buf
, msglen
);
1350 if (strcmp(key
->alg
, NS_TSIG_ALG_HMAC_MD5
) != 0)
1353 dstkey
= dst_buffer_to_key(key
->name
, KEY_HMAC_MD5
,
1354 NS_KEY_TYPE_AUTH_ONLY
,
1356 key
->data
, key
->len
);
1357 if (dstkey
== NULL
) {
1364 siglen
= sizeof(sig
);
1366 ret
= ns_sign(newmsg
, &newmsglen
, bufsize
, NOERROR
, dstkey
, NULL
, 0,
1371 if (ret
== NS_TSIG_ERROR_NO_SPACE
)
1377 ns_verify_tcp_init(dstkey
, sig
, siglen
, &tsig_state
);
1381 * Set up a virtual circuit to the server.
1383 if ((sockFD
= socket(sin
->sin_family
, SOCK_STREAM
, 0)) < 0) {
1386 perror(";; socket");
1390 switch (sin
->sin_family
) {
1392 if (bind(sockFD
, (struct sockaddr
*)&myaddress
,
1393 sizeof myaddress
) < 0){
1396 fprintf(stderr
, ";; bind(%s port %u): %s\n",
1397 inet_ntoa(myaddress
.sin_addr
),
1398 ntohs(myaddress
.sin_port
),
1400 (void) close(sockFD
);
1404 if (connect(sockFD
, (const struct sockaddr
*)sin
,
1408 perror(";; connect");
1409 (void) close(sockFD
);
1415 if (bind(sockFD
, (struct sockaddr
*)&myaddress6
,
1416 sizeof myaddress6
) < 0){
1420 fprintf(stderr
, ";; bind(%s port %u): %s\n",
1421 inet_ntop(AF_INET6
, &myaddress6
.sin6_addr
,
1423 ntohs(myaddress6
.sin6_port
),
1425 (void) close(sockFD
);
1429 if (connect(sockFD
, (const struct sockaddr
*)sin
,
1430 sizeof(struct sockaddr_in6
)) < 0) {
1433 perror(";; connect");
1434 (void) close(sockFD
);
1442 * Send length & message for zone transfer
1445 ns_put16(newmsglen
, tmp
);
1446 if (write(sockFD
, (char *)tmp
, NS_INT16SZ
) != NS_INT16SZ
||
1447 write(sockFD
, (char *)newmsg
, newmsglen
) != newmsglen
) {
1452 (void) close(sockFD
);
1459 * If we're compressing, push a gzip into the pipeline.
1461 if (xfr
== ns_t_zxfr
) {
1462 enum { rd
= 0, wr
= 1 };
1469 (void) close(sockFD
);
1478 (void) close(sockFD
);
1481 } else if (zpid
== 0) {
1483 (void) close(z
[rd
]);
1484 (void) dup2(sockFD
, STDIN_FILENO
);
1485 (void) close(sockFD
);
1486 (void) dup2(z
[wr
], STDOUT_FILENO
);
1487 (void) close(z
[wr
]);
1488 execlp("gzip", "gzip", "-d", "-v", NULL
);
1489 perror(";; child: execlp(gunzip)");
1493 (void) close(z
[wr
]);
1494 (void) dup2(z
[rd
], sockFD
);
1495 (void) close(z
[rd
]);
1505 for (done
= 0; !done
; (void)NULL
) {
1507 * Read the length of the response.
1511 amtToRead
= INT16SZ
;
1512 while (amtToRead
> 0 &&
1513 (numRead
= read(sockFD
, cp
, amtToRead
)) > 0) {
1515 amtToRead
-= numRead
;
1518 error
= ERR_READING_LEN
;
1522 len
= ns_get16(tmp
);
1524 break; /* nothing left to read */
1527 * The server sent too much data to fit the existing buffer --
1528 * allocate a new one.
1530 if (len
> answerLen
) {
1534 answer
= (u_char
*)malloc(answerLen
);
1538 * Read the response.
1543 while (amtToRead
> 0 &&
1544 (numRead
= read(sockFD
, cp
, amtToRead
)) > 0) {
1546 amtToRead
-= numRead
;
1549 error
= ERR_READING_MSG
;
1553 result
= print_axfr(stdout
, answer
, len
);
1555 error
= ERR_PRINTING
;
1558 numRecords
+= htons(((HEADER
*)answer
)->ancount
);
1562 cp
= answer
+ HFIXEDSZ
;
1564 for (count
= ntohs(((HEADER
*)answer
)->qdcount
);
1567 n
= dn_skipname(cp
, answer
+ len
);
1569 error
= ERR_PRINTING
;
1574 if (cp
> answer
+ len
) {
1575 error
= ERR_PRINTING
;
1581 for (count
= ntohs(((HEADER
*)answer
)->ancount
);
1584 n
= dn_expand(answer
, answer
+ len
, cp
,
1585 dname
[soacnt
], sizeof dname
[0]);
1587 error
= ERR_PRINTING
;
1592 if (cp
+ 3 * INT16SZ
+ INT32SZ
> answer
+ len
) {
1593 error
= ERR_PRINTING
;
1599 cp
+= INT32SZ
; /* ttl */
1602 if (cp
> answer
+ len
) {
1603 error
= ERR_PRINTING
;
1607 if (type
== T_SOA
&& soacnt
++ &&
1608 ns_samename(dname
[0], dname
[1]) == 1) {
1619 if (ns_find_tsig(answer
, answer
+ len
) != NULL
)
1623 if (numAnswers
== 1 || soacnt
> 1)
1627 tsig_ret
= ns_verify_tcp(answer
, &len
, &tsig_state
,
1629 if (tsig_ret
== 0) {
1631 printf("; TSIG ok\n");
1634 printf("; TSIG invalid\n");
1639 printf(";; Received %d answer%s (%d record%s).\n",
1640 numAnswers
, (numAnswers
!= 1) ? "s" : "",
1641 numRecords
, (numRecords
!= 1) ? "s" : "");
1643 (void) close(sockFD
);
1647 * If we were uncompressing, reap the uncompressor.
1649 if (xfr
== ns_t_zxfr
) {
1653 pid
= wait(&status
);
1661 fprintf(stderr
, ";; wrong pid (%lu != %lu)\n",
1662 (u_long
)pid
, (u_long
)zpid
);
1665 printf(";; pid %lu: exit %d, signal %d, core %c\n",
1666 (u_long
)pid
, WEXITSTATUS(status
),
1667 WIFSIGNALED(status
) ? WTERMSIG(status
) : 0,
1668 WCOREDUMP(status
) ? 't' : 'f');
1675 case ERR_READING_LEN
:
1681 case ERR_READING_MSG
:
1690 print_axfr(FILE *file
, const u_char
*msg
, size_t msglen
) {
1693 if (ns_initparse(msg
, msglen
, &handle
) < 0) {
1694 fprintf(file
, ";; ns_initparse: %s\n", strerror(errno
));
1695 return (ns_r_formerr
);
1697 if (ns_msg_getflag(handle
, ns_f_rcode
) != ns_r_noerror
)
1698 return (ns_msg_getflag(handle
, ns_f_rcode
));
1701 * We are looking for info from answer resource records.
1702 * If there aren't any, return with an error. We assume
1703 * there aren't any question records.
1705 if (ns_msg_count(handle
, ns_s_an
) == 0)
1708 #ifdef PROTOCOLDEBUG
1709 printf(";;; (message of %d octets has %d answers)\n",
1710 msglen
, ns_msg_count(handle
, ns_s_an
));
1713 static char origin
[NS_MAXDNAME
], name_ctx
[NS_MAXDNAME
];
1715 char buf
[2048]; /* XXX need to malloc/realloc. */
1718 if (ns_parserr(&handle
, ns_s_an
, -1, &rr
)) {
1719 if (errno
!= ENODEV
) {
1720 fprintf(file
, ";; ns_parserr: %s\n",
1726 name
= ns_rr_name(rr
);
1727 if (origin
[0] == '\0' && name
[0] != '\0') {
1728 if (strcmp(name
, ".") != 0)
1729 strcpy(origin
, name
);
1730 fprintf(file
, "$ORIGIN %s.\n", origin
);
1731 if (strcmp(name
, ".") == 0)
1732 strcpy(origin
, name
);
1733 if (res
.pfcode
& RES_PRF_TRUNC
)
1734 strcpy(name_ctx
, "@");
1736 if (ns_sprintrr(&handle
, &rr
,
1737 (res
.pfcode
& RES_PRF_TRUNC
) ? name_ctx
: NULL
,
1738 (res
.pfcode
& RES_PRF_TRUNC
) ? origin
: NULL
,
1739 buf
, sizeof buf
) < 0) {
1740 fprintf(file
, ";; ns_sprintrr: %s\n", strerror(errno
));
1743 strcpy(name_ctx
, name
);
1750 static struct timeval
1751 difftv(struct timeval a
, struct timeval b
) {
1752 static struct timeval diff
;
1754 diff
.tv_sec
= b
.tv_sec
- a
.tv_sec
;
1755 if ((diff
.tv_usec
= b
.tv_usec
- a
.tv_usec
) < 0) {
1757 diff
.tv_usec
+= 1000000;
1763 prnttime(struct timeval t
) {
1764 printf("%lu msec", (u_long
)(t
.tv_sec
* 1000 + (t
.tv_usec
/ 1000)));
1768 * Take arguments appearing in simple string (from file or command line)
1772 stackarg(char *l
, char **y
) {
1788 while (!isspace((unsigned char)*l
))
1799 reverse6(char *domain
, struct in6_addr
*in6
) {
1800 sprintf(domain
, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa",
1801 in6
->s6_addr
[15] & 0x0f, (in6
->s6_addr
[15] >> 4) & 0x0f,
1802 in6
->s6_addr
[14] & 0x0f, (in6
->s6_addr
[14] >> 4) & 0x0f,
1803 in6
->s6_addr
[13] & 0x0f, (in6
->s6_addr
[13] >> 4) & 0x0f,
1804 in6
->s6_addr
[12] & 0x0f, (in6
->s6_addr
[12] >> 4) & 0x0f,
1805 in6
->s6_addr
[11] & 0x0f, (in6
->s6_addr
[11] >> 4) & 0x0f,
1806 in6
->s6_addr
[10] & 0x0f, (in6
->s6_addr
[10] >> 4) & 0x0f,
1807 in6
->s6_addr
[9] & 0x0f, (in6
->s6_addr
[9] >> 4) & 0x0f,
1808 in6
->s6_addr
[8] & 0x0f, (in6
->s6_addr
[8] >> 4) & 0x0f,
1809 in6
->s6_addr
[7] & 0x0f, (in6
->s6_addr
[7] >> 4) & 0x0f,
1810 in6
->s6_addr
[6] & 0x0f, (in6
->s6_addr
[6] >> 4) & 0x0f,
1811 in6
->s6_addr
[5] & 0x0f, (in6
->s6_addr
[5] >> 4) & 0x0f,
1812 in6
->s6_addr
[4] & 0x0f, (in6
->s6_addr
[4] >> 4) & 0x0f,
1813 in6
->s6_addr
[3] & 0x0f, (in6
->s6_addr
[3] >> 4) & 0x0f,
1814 in6
->s6_addr
[2] & 0x0f, (in6
->s6_addr
[2] >> 4) & 0x0f,
1815 in6
->s6_addr
[1] & 0x0f, (in6
->s6_addr
[1] >> 4) & 0x0f,
1816 in6
->s6_addr
[0] & 0x0f, (in6
->s6_addr
[0] >> 4) & 0x0f);