2 * Copyright (c) 1986 Regents of the University of California
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
14 * Actually, this program is from Rutgers University, however it is
15 * based on nslookup and other pieces of named tools, so it needs
16 * that copyright notice.
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
31 #include <net/netlib.h>
32 #include <net/gen/in.h>
33 #include <net/gen/inet.h>
34 #include <net/gen/netdb.h>
35 #include <net/gen/nameser.h>
36 #include <net/gen/resolv.h>
37 #include <net/gen/socket.h>
38 #include <net/gen/tcp.h>
39 #include <net/gen/tcp_io.h>
44 #include <sys/types.h>
45 #include <arpa/nameser.h>
47 #include <sys/socket.h>
48 #include <netinet/in.h>
50 #include <sys/param.h>
71 #define NO_DATA NO_ADDRESS
80 extern struct state _res
;
81 static u8_t
*cname
= NULL
;
83 int gettype
, getdeftype
= T_A
;
86 int server_specified
= 0;
90 int main
_ARGS(( int c
, char *v
[] ));
92 static int parsetype
_ARGS(( char *s
));
93 static int parseclass
_ARGS(( char *s
));
94 static void hperror
_ARGS(( int errno
));
95 static void printanswer
_ARGS(( struct hostent
*hp
));
96 static int ListHosts
_ARGS(( char *namePtr
, int queryType
));
97 static int gethostinfo
_ARGS(( char *name
));
98 static int getdomaininfo
_ARGS(( char *name
, char *domain
));
99 static int getinfo
_ARGS(( char *name
, char *domain
, int type
));
100 static int printinfo
_ARGS(( union querybuf
*answer
, u8_t
*eom
, int filter
,
102 static char *DecodeError
_ARGS(( int result
));
103 static u8_t
*pr_rr
_ARGS(( u8_t
*cp
, u8_t
*msg
, FILE *file
, int filter
));
104 static u8_t
* pr_cdname
_ARGS(( u8_t
*cp
, u8_t
*msg
, u8_t
*name
, int namelen
));
105 static char *pr_class
_ARGS(( int class ));
106 static char *pr_type
_ARGS(( int type
));
107 static int tcpip_writeall
_ARGS(( int fd
, char *buf
, unsigned siz
));
115 register struct hostent
*hp
;
116 register char *s
, *p
;
117 register inverse
= 0;
118 register waitmode
= 0;
127 fprintf(stderr
, "Usage: host [-w] [-v] [-r] [-d] [-V] [-t querytype] [-c class] [-a] host [server]\n -w to wait forever until reply\n -v for verbose output\n -r to disable recursive processing\n -d to turn on debugging output\n -t querytype to look for a specific type of information\n -c class to look for non-Internet data\n -a is equivalent to '-v -t *'\n -V to always use a virtual circuit\n");
130 while (c
> 2 && v
[1][0] == '-') {
131 if (strcmp (v
[1], "-w") == 0) {
138 else if (strcmp (v
[1], "-r") == 0) {
139 _res
.options
&= ~RES_RECURSE
;
143 else if (strcmp (v
[1], "-d") == 0) {
144 _res
.options
|= RES_DEBUG
;
148 else if (strcmp (v
[1], "-v") == 0) {
153 else if (strcmp (v
[1], "-l") == 0) {
158 else if (strncmp (v
[1], "-t", 2) == 0) {
161 gettype
= parsetype(v
[1]);
165 else if (strncmp (v
[1], "-c", 2) == 0) {
168 getclass
= parseclass(v
[1]);
172 else if (strcmp (v
[1], "-a") == 0) {
178 else if (strcmp (v
[1], "-V") == 0) {
179 _res
.options
|= RES_USEVC
;
188 if ((p
= strchr(s
, ':')) != NULL
) *p
++ = 0;
189 isaddr
= inet_aton(s
, &addr
);
190 if (p
!= NULL
) p
[-1] = ':';
192 hp
= gethostbyname(s
);
194 fprintf(stderr
,"Error in looking up server name:\n");
198 _res
.nsaddr
= *(ipaddr_t
*)hp
->h_addr
;
199 printf("Using domain server:\n");
203 _res
.nsaddr_list
[0]= addr
;
204 _res
.nsport_list
[0]= htons(NAMESERVER_PORT
);
205 printf("Using domain server %s",
206 inet_ntoa(_res
.nsaddr
));
208 printf(" on port %d", atoi(p
));
209 _res
.nsport_list
[0]= htons(atoi(p
));
215 if (strcmp (domain
, ".") != 0 && inet_aton(domain
, &addr
)) {
216 static char ipname
[sizeof("255.255.255.255.in-addr.arpa.")];
217 sprintf(ipname
, "%d.%d.%d.%d.in-addr.arpa.",
218 ((unsigned char *) &addr
)[3],
219 ((unsigned char *) &addr
)[2],
220 ((unsigned char *) &addr
)[1],
221 ((unsigned char *) &addr
)[0]);
229 * we handle default domains ourselves, thank you
231 _res
.options
&= ~RES_DEFNAMES
;
234 exit(ListHosts(domain
, gettype
? gettype
: getdeftype
));
237 while (hp
== NULL
&& h_errno
== TRY_AGAIN
) {
239 if (oldcname
== NULL
)
240 hp
= (struct hostent
*)gethostinfo(domain
);
242 hp
= (struct hostent
*)gethostinfo((char *)oldcname
);
244 if (ncnames
-- == 0) {
245 printf("Too many cnames. Possible loop.\n");
270 if (strcmp(s
,"a") == 0)
272 if (strcmp(s
,"ns") == 0)
274 if (strcmp(s
,"md") == 0)
276 if (strcmp(s
,"mf") == 0)
278 if (strcmp(s
,"cname") == 0)
280 if (strcmp(s
,"soa") == 0)
282 if (strcmp(s
,"mb") == 0)
284 if (strcmp(s
,"mg") == 0)
286 if (strcmp(s
,"mr") == 0)
288 if (strcmp(s
,"null") == 0)
290 if (strcmp(s
,"wks") == 0)
292 if (strcmp(s
,"ptr") == 0)
294 if (strcmp(s
,"hinfo") == 0)
296 if (strcmp(s
,"minfo") == 0)
298 if (strcmp(s
,"mx") == 0)
300 if (strcmp(s
,"txt") == 0) /* Roy */
301 return(T_TXT
); /* Roy */
302 if (strcmp(s
,"uinfo") == 0)
304 if (strcmp(s
,"uid") == 0)
306 if (strcmp(s
,"gid") == 0)
308 if (strcmp(s
,"unspec") == 0)
310 if (strcmp(s
,"any") == 0)
312 if (strcmp(s
,"*") == 0)
316 fprintf(stderr
, "Invalid query type: %s\n", s
);
324 if (strcmp(s
,"in") == 0)
326 if (strcmp(s
,"chaos") == 0)
328 if (strcmp(s
,"hs") == 0)
330 if (strcmp(s
,"any") == 0)
334 fprintf(stderr
, "Invalid query class: %s\n", s
);
340 register struct hostent
*hp
;
343 register ipaddr_t
**hptr
;
345 printf("Name: %s\n", hp
->h_name
);
347 for (hptr
= (ipaddr_t
**)hp
->h_addr_list
; *hptr
; hptr
++)
348 printf(" %s", inet_ntoa(*(ipaddr_t
*)*hptr
));
349 printf("\nAliases:");
350 for (cp
= hp
->h_aliases
; cp
&& *cp
&& **cp
; cp
++)
361 fprintf(stderr
,"Host not found.\n");
364 fprintf(stderr
,"Host not found, try again.\n");
367 fprintf(stderr
,"No recovery, Host not found.\n");
370 fprintf(stderr
,"There is an entry for this host, but it doesn't have what you requested.\n");
376 typedef union querybuf
{
381 static u8_t hostbuf
[BUFSIZ
+1];
388 register char *cp
, **domain
;
393 if (strcmp(name
, ".") == 0)
394 return(getdomaininfo(name
, NULL
));
395 for (cp
= name
, n
= 0; *cp
; cp
++)
398 if (n
&& cp
[-1] == '.') {
401 hp
= getdomaininfo(name
, (char *)NULL
);
406 if (n
== 0 && (cp
= __hostalias(name
))) {
408 printf("Aliased to \"%s\"\n", cp
);
409 _res
.options
|= RES_DEFNAMES
;
410 return (getdomaininfo(cp
, (char *)NULL
));
414 _res
.defdname_list
[nDomain
][0] != 0;
416 for (domain
= _res
.dnsrch_list
[nDomain
]; *domain
; domain
++) {
418 printf("Trying domain \"%s\"\n", *domain
);
419 hp
= getdomaininfo(name
, *domain
);
425 for (domain
= _res
.dnsrch
; *domain
; domain
++) {
427 printf("Trying domain \"%s\"\n", *domain
);
428 hp
= getdomaininfo(name
, *domain
);
433 if (h_errno
!= HOST_NOT_FOUND
||
434 (_res
.options
& RES_DNSRCH
) == 0)
437 printf("Trying null domain\n");
438 return (getdomaininfo(name
, (char *)NULL
));
442 getdomaininfo(name
, domain
)
445 return getinfo(name
, domain
, gettype
? gettype
: getdeftype
);
449 getinfo(name
, domain
, type
)
455 querybuf_t buf
, answer
;
456 int n
, n1
, i
, j
, nmx
, ancount
, nscount
, arcount
, qdcount
, buflen
;
458 char host
[2*MAXDNAME
+2];
461 (void)sprintf(host
, "%.*s", MAXDNAME
, name
);
463 (void)sprintf(host
, "%.*s.%.*s", MAXDNAME
, name
, MAXDNAME
, domain
);
465 n
= res_mkquery(QUERY
, host
, getclass
, type
, (char *)NULL
, 0, NULL
,
466 (char *)&buf
, sizeof(buf
));
468 if (_res
.options
& RES_DEBUG
)
469 printf("res_mkquery failed\n");
470 h_errno
= NO_RECOVERY
;
473 n
= res_send((char *)&buf
, n
, (char *)&answer
, sizeof(answer
));
475 if (_res
.options
& RES_DEBUG
)
476 printf("res_send failed\n");
480 eom
= (u8_t
*)&answer
+ n
;
481 return(printinfo(&answer
, eom
, T_ANY
, 0));
485 printinfo(answer
, eom
, filter
, isls
)
493 int n
, n1
, i
, j
, nmx
, ancount
, nscount
, arcount
, qdcount
, buflen
;
497 * find first satisfactory answer
499 hp
= (dns_hdr_t
*) answer
;
500 ancount
= ntohs(hp
->dh_ancount
);
501 qdcount
= ntohs(hp
->dh_qdcount
);
502 nscount
= ntohs(hp
->dh_nscount
);
503 arcount
= ntohs(hp
->dh_arcount
);
504 if (_res
.options
& RES_DEBUG
|| (verbose
&& isls
== 0))
505 printf("rcode = %d (%s), ancount=%d\n",
506 hp
->dh_flag2
& DHF_RCODE
,
507 DecodeError(hp
->dh_flag2
& DHF_RCODE
), ancount
);
508 if (hp
->dh_flag2
& DHF_RCODE
!= NOERROR
||
509 (ancount
+nscount
+arcount
) == 0) {
510 switch (hp
->dh_flag2
& DHF_RCODE
) {
512 /* Check if it's an authoritive answer */
513 if (hp
->dh_flag1
& DHF_AA
) {
514 h_errno
= HOST_NOT_FOUND
;
525 * Jeeves (TOPS-20 server) still does not
526 * support MX records. For the time being,
527 * we must accept FORMERRs as the same as
531 #endif /* OLDJEEVES */
533 /* TpB - set a return error for this case. NO_DATA */
535 return(0); /* was 1,but now indicates exception */
538 #endif /* OLDJEEVES */
541 h_errno
= NO_RECOVERY
;
548 buflen
= sizeof(hostbuf
);
549 cp
= (u8_t
*)answer
+ sizeof(dns_hdr_t
);
551 cp
+= dn_skipname((u8_t
*)cp
,(u8_t
*)eom
) + QFIXEDSZ
;
552 while (--qdcount
> 0)
553 cp
+= dn_skipname((u8_t
*)cp
,(u8_t
*)eom
) + QFIXEDSZ
;
556 if (!(hp
->dh_flag1
& DHF_AA
))
557 if (verbose
&& isls
== 0)
558 printf("The following answer is not authoritative:\n");
559 while (--ancount
>= 0 && cp
&& cp
< eom
) {
560 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
562 * When we ask for address and there is a CNAME, it seems to return
563 * both the CNAME and the address. Since we trace down the CNAME
564 * chain ourselves, we don't really want to print the address at
567 if (cname
&& ! verbose
)
574 printf("For authoritative answers, see:\n");
575 while (--nscount
>= 0 && cp
&& cp
< eom
) {
576 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
580 printf("Additional information:\n");
581 while (--arcount
>= 0 && cp
&& cp
< eom
) {
582 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
588 static u8_t cnamebuf
[MAXDNAME
];
591 * Print resource record fields in human readable form.
594 pr_rr(cp
, msg
, file
, filter
)
599 int type
, class, dlen
, n
, c
, proto
, ttl
;
602 struct protoent
*protop
;
603 struct servent
*servp
;
608 if ((cp
= pr_cdname(cp
, msg
, name
, sizeof(name
))) == NULL
)
609 return (NULL
); /* compression error */
611 type
= _getshort(cp
);
612 cp
+= sizeof(u_short
);
614 class = _getshort(cp
);
615 cp
+= sizeof(u_short
);
618 cp
+= sizeof(u_long
);
620 if (filter
== type
|| filter
== T_ANY
||
621 (filter
== T_A
&& (type
== T_PTR
|| type
== T_NS
)))
628 fprintf(file
,"%s\t%d%s\t%s",
629 name
, ttl
, pr_class(class), pr_type(type
));
631 fprintf(file
,"%s%s %s",name
, pr_class(class), pr_type(type
));
637 dlen
= _getshort(cp
);
638 cp
+= sizeof(u_short
);
641 * Print type specific data, if appropriate
647 bcopy((char *)cp
, (char *)&inaddr
, sizeof(inaddr
));
650 fprintf(file
,"%c%s", punc
,
653 } else if (dlen
== 7) {
655 fprintf(file
,"%c%s", punc
,
657 fprintf(file
,", protocol = %d", cp
[4]);
658 fprintf(file
,", port = %d",
659 (cp
[5] << 8) + cp
[6]);
667 if (dn_expand(msg
, msg
+ 512, cp
, cnamebuf
,
668 sizeof(cnamebuf
)-1) >= 0) {
669 strcat((char *) cnamebuf
, ".");
670 if (gettype
!= T_CNAME
&& gettype
!= T_ANY
)
682 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
684 fprintf(file
,"%c%s",punc
, name
);
690 fprintf(file
,"%c%.*s", punc
, n
, cp
);
695 fprintf(file
,"%c%.*s", punc
, n
, cp
);
701 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
703 fprintf(file
,"\t%s", name
);
704 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
706 fprintf(file
," %s", name
);
708 fprintf(file
,"(\n\t\t\t%ld\t;serial (version)", _getlong(cp
));
709 cp
+= sizeof(u_long
);
711 fprintf(file
,"\n\t\t\t%ld\t;refresh period", _getlong(cp
));
712 cp
+= sizeof(u_long
);
714 fprintf(file
,"\n\t\t\t%ld\t;retry refresh this often", _getlong(cp
));
715 cp
+= sizeof(u_long
);
717 fprintf(file
,"\n\t\t\t%ld\t;expiration period", _getlong(cp
));
718 cp
+= sizeof(u_long
);
720 fprintf(file
,"\n\t\t\t%ld\t;minimum TTL\n\t\t\t)", _getlong(cp
));
721 cp
+= sizeof(u_long
);
727 fprintf(file
,"\t%d ",_getshort(cp
));
729 fprintf(file
," (pri=%d) by ",_getshort(cp
));
730 cp
+= sizeof(u_short
);
731 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
733 fprintf(file
, "%s", name
);
737 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
739 fprintf(file
,"%c%s",punc
, name
);
740 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
742 fprintf(file
," %s", name
);
749 fprintf(file
,"%c%.*s", punc
, n
, cp
);
757 fprintf(file
,"%c%s", punc
, cp
);
765 fprintf(file
,"%c%ld", punc
, _getlong(cp
));
771 if (dlen
< sizeof(u_long
) + 1)
773 bcopy((char *)cp
, (char *)&inaddr
, sizeof(inaddr
));
774 cp
+= sizeof(u_long
);
776 protop
= getprotobynumber(proto
);
779 fprintf(file
,"%c%s %s", punc
,
780 inet_ntoa(inaddr
), protop
->p_name
);
782 fprintf(file
,"%c%s %d", punc
,
783 inet_ntoa(inaddr
), proto
);
786 while (cp
< cp1
+ dlen
) {
792 servp
= getservbyport (htons(n
),
796 fprintf(file
, " %s", servp
->s_name
);
798 fprintf(file
, " %d", n
);
807 fprintf(file
,"%c???", punc
);
810 if (cp
!= cp1
+ dlen
)
811 fprintf(file
,"packet size error (%#x != %#x)\n", cp
, cp1
+dlen
);
817 static char nbuf
[20];
820 * Return a string for the type
828 return(verbose
? "A" : "has address");
829 case T_NS
: /* authoritative server */
832 case T_MD
: /* mail destination */
834 case T_MF
: /* mail forwarder */
837 case T_CNAME
: /* connonical name */
838 return(verbose
? "CNAME" : "is a nickname for");
839 case T_SOA
: /* start of authority zone */
841 case T_MB
: /* mailbox domain name */
843 case T_MG
: /* mail group member */
845 case T_MX
: /* mail routing info */
846 return(verbose
? "MX" : "mail is handled");
848 case T_TXT
: /* TXT - descriptive info */
849 return(verbose
? "TXT" : "descriptive text");
851 case T_MR
: /* mail rename name */
853 case T_NULL
: /* null resource record */
855 case T_WKS
: /* well known service */
857 case T_PTR
: /* domain name pointer */
859 case T_HINFO
: /* host information */
861 case T_MINFO
: /* mailbox information */
863 case T_AXFR
: /* zone transfer */
865 case T_MAILB
: /* mail box */
867 case T_MAILA
: /* mail address */
869 case T_ANY
: /* matches any type */
878 return (sprintf(nbuf
, "%d", type
) == EOF
? NULL
: nbuf
);
883 * Return a mnemonic for class
891 case C_IN
: /* internet class */
892 return(verbose
? " IN" : "");
893 case C_CHAOS
: /* chaos class */
894 return(verbose
? " CHAOS" : "");
895 case C_HS
: /* Hesiod class */
896 return(verbose
? " HS" : "");
897 case C_ANY
: /* matches any class */
900 return (sprintf(nbuf
," %d", class) == EOF
? NULL
: nbuf
);
905 pr_cdname(cp
, msg
, name
, namelen
)
912 if ((n
= dn_expand(msg
, msg
+ 512, cp
, name
, namelen
- 2)) < 0)
914 if (name
[0] == '\0') {
921 char *resultcodes
[] = {
943 ******************************************************************************
947 * Requests the name server to do a zone transfer so we
948 * find out what hosts it knows about.
951 * SUCCESS the listing was successful.
952 * ERROR the server could not be contacted because
953 * a socket could not be obtained or an error
954 * occured while receiving, or the output file
955 * could not be opened.
957 ******************************************************************************
961 ListHosts(namePtr
, queryType
)
963 int queryType
; /* e.g. T_A */
965 querybuf_t buf
, answer
;
966 dns_hdr_t
*headerPtr
;
981 char dname
[2][NAME_LEN
];
982 u8_t domain
[NAME_LEN
];
983 /* names and addresses of name servers to try */
985 char nsname
[NUMNS
][NAME_LEN
];
986 int nshaveaddr
[NUMNS
];
989 char nsipaddr
[NUMNSADDR
][IPADDRSIZE
];
1000 char *tcp_serv_name
;
1002 nwio_tcpconf_t tcpconf
;
1007 * normalize to not have trailing dot. We do string compares below
1008 * of info from name server, and it won't have trailing dots.
1010 i
= strlen(namePtr
);
1011 if (namePtr
[i
-1] == '.')
1014 if (server_specified
) {
1015 bcopy((char *)&_res
.nsaddr
, nsipaddr
[0], IPADDRSIZE
);
1021 * First we have to find out where to look. This needs a NS query,
1022 * possibly followed by looking up addresses for some of the names.
1025 msglen
= res_mkquery(QUERY
, namePtr
, C_IN
, T_NS
,
1026 (char *)0, 0, (struct rrec
*)0,
1027 (char *)&buf
, sizeof(buf
));
1030 printf("res_mkquery failed\n");
1034 msglen
= res_send((char *)&buf
,msglen
,(char *)&answer
, sizeof(answer
));
1037 printf("Unable to get to nameserver -- try again later\n");
1040 if (_res
.options
& RES_DEBUG
|| verbose
)
1041 printf("rcode = %d (%s), ancount=%d\n",
1042 answer
.qb1
.dh_flag2
& DHF_RCODE
,
1043 DecodeError(answer
.qb1
.dh_flag2
& DHF_RCODE
),
1044 ntohs(answer
.qb1
.dh_ancount
));
1047 * Analyze response to our NS lookup
1050 nscount
= ntohs(answer
.qb1
.dh_ancount
) + ntohs(answer
.qb1
.dh_nscount
) +
1051 ntohs(answer
.qb1
.dh_arcount
);
1053 if (answer
.qb1
.dh_flag2
& DHF_RCODE
!= NOERROR
|| nscount
== 0) {
1054 switch (answer
.qb1
.dh_flag2
& DHF_RCODE
) {
1056 /* Check if it's an authoritive answer */
1057 if (answer
.qb1
.dh_flag1
& DHF_AA
) {
1058 printf("No such domain\n");
1060 printf("Unable to get information about domain -- try again later.\n");
1064 printf("Unable to get information about that domain -- try again later.\n");
1067 printf("That domain exists, but seems to be a leaf node.\n");
1072 printf("Unrecoverable error looking up domain name.\n");
1078 cp
= answer
.qb2
+ sizeof(dns_hdr_t
);
1079 if (ntohs(answer
.qb1
.dh_qdcount
) > 0)
1080 cp
+= dn_skipname(cp
, answer
.qb2
+ msglen
) + QFIXEDSZ
;
1086 * Look at response from NS lookup for NS and A records.
1089 for (;nscount
; nscount
--) {
1090 cp
+= dn_expand(answer
.qb2
, answer
.qb2
+ msglen
, cp
,
1091 domain
, sizeof(domain
));
1092 type
= _getshort(cp
);
1093 cp
+= sizeof(u_short
) + sizeof(u_short
) + sizeof(u_long
);
1094 dlen
= _getshort(cp
);
1095 cp
+= sizeof(u_short
);
1097 if (dn_expand(answer
.qb2
, answer
.qb2
+ msglen
, cp
,
1098 name
, sizeof(name
)) >= 0) {
1099 if (numns
< NUMNS
&& strcasecmp((char *)domain
, namePtr
) == 0) {
1100 for (i
= 0; i
< numns
; i
++)
1101 if (strcasecmp(nsname
[i
], (char *)name
) == 0)
1102 break; /* duplicate */
1104 strncpy(nsname
[numns
], (char *)name
, sizeof(name
));
1105 nshaveaddr
[numns
] = 0;
1111 else if (type
== T_A
) {
1112 if (numnsaddr
< NUMNSADDR
)
1113 for (i
= 0; i
< numns
; i
++) {
1114 if (strcasecmp(nsname
[i
], (char *)domain
) == 0) {
1116 bcopy((char *)cp
, nsipaddr
[numnsaddr
],IPADDRSIZE
);
1126 * Usually we'll get addresses for all the servers in the additional
1127 * info section. But in case we don't, look up their addresses.
1130 for (i
= 0; i
< numns
; i
++) {
1131 if (! nshaveaddr
[i
]) {
1132 register long **hptr
;
1135 hp
= gethostbyname(nsname
[i
]);
1137 for (hptr
= (long **)hp
->h_addr_list
; *hptr
; hptr
++)
1138 if (numnsaddr
< NUMNSADDR
) {
1139 bcopy((char *)*hptr
, nsipaddr
[numnsaddr
],IPADDRSIZE
);
1144 if (_res
.options
& RES_DEBUG
|| verbose
)
1145 printf("Found %d addresses for %s by extra query\n",
1146 numaddrs
, nsname
[i
]);
1149 if (_res
.options
& RES_DEBUG
|| verbose
)
1150 printf("Found %d addresses for %s\n",
1151 nshaveaddr
[i
], nsname
[i
]);
1155 * Now nsipaddr has numnsaddr addresses for name servers that
1156 * serve the requested domain. Now try to find one that will
1157 * accept a zone transfer.
1168 * Create a query packet for the requested domain name.
1171 msglen
= res_mkquery(QUERY
, namePtr
, getclass
, T_AXFR
,
1172 (char *)0, 0, (struct rrec
*)0,
1173 (char *) &buf
, sizeof(buf
));
1175 if (_res
.options
& RES_DEBUG
) {
1176 fprintf(stderr
, "ListHosts: Res_mkquery failed\n");
1182 * Set up a virtual circuit to the server.
1185 tcp_serv_name
= getenv("TCP_DEVICE");
1187 tcp_serv_name
= TCP_DEVICE
;
1188 for (;thisns
< numnsaddr
; thisns
++)
1190 tcp_fd
= open(tcp_serv_name
, O_RDWR
);
1193 fprintf(stderr
, "unable to open '%s': %s\n", tcp_serv_name
,
1198 tcpconf
.nwtc_flags
= NWTC_EXCL
| NWTC_LP_SEL
| NWTC_SET_RA
|
1200 tcpconf
.nwtc_remaddr
= *(ipaddr_t
*)nsipaddr
[thisns
];
1201 tcpconf
.nwtc_remport
= _res
.nsport_list
[0];
1202 result
= ioctl(tcp_fd
, NWIOSTCPCONF
, &tcpconf
);
1205 fprintf(stderr
, "tcp_ioc_setconf failed: %s\n",
1210 if (_res
.options
& RES_DEBUG
|| verbose
)
1211 printf("Trying %s\n", inet_ntoa(tcpconf
.nwtc_remaddr
));
1212 clopt
.nwtcl_flags
= 0;
1213 result
= ioctl(tcp_fd
, NWIOTCPCONN
, &clopt
);
1219 "Connection failed, trying next server: %s\n",
1223 if (thisns
>= numnsaddr
) {
1224 printf("No server for that domain responded\n");
1226 fprintf(stderr
, "Error from the last server was: %s\n",
1232 * Send length & message for zone transfer
1235 len
= htons(msglen
);
1237 result
= tcpip_writeall(tcp_fd
, (char *)&len
, sizeof(len
));
1238 if (result
!= sizeof(len
))
1240 fprintf(stderr
, "write failed: %s\n", strerror(errno
));
1244 result
= tcpip_writeall(tcp_fd
, (char *)&buf
, msglen
);
1245 if (result
!= msglen
)
1247 fprintf(stderr
, "write failed: %s\n",
1257 * Read the length of the response.
1261 amtToRead
= sizeof(u_short
);
1262 while(amtToRead
> 0)
1264 result
= read(tcp_fd
, (char *)cp
, amtToRead
);
1268 amtToRead
-= result
;
1271 error
= ERR_READING_LEN
;
1275 if ((len
= htons(*(u_short
*)&buf
)) == 0) {
1276 break; /* nothing left to read */
1280 * Read the response.
1285 while(amtToRead
> 0)
1287 result
= read(tcp_fd
, (char *)cp
, amtToRead
);
1291 amtToRead
-= result
;
1294 error
= ERR_READING_MSG
;
1298 i
= buf
.qb1
.dh_flag2
& DHF_RCODE
;
1299 if (i
!= NOERROR
|| ntohs(buf
.qb1
.dh_ancount
) == 0) {
1300 if ((thisns
+1) < numnsaddr
&&
1301 (i
== SERVFAIL
|| i
== NOTIMP
|| i
== REFUSED
)) {
1302 if (_res
.options
& RES_DEBUG
|| verbose
)
1303 printf("Server failed, trying next server: %s\n",
1305 DecodeError(i
) : "Premature end of data");
1310 printf("Server failed: %s\n",
1311 i
!= NOERROR
? DecodeError(i
) : "Premature end of data");
1316 result
= printinfo(&buf
, cp
, queryType
, 1);
1318 error
= ERR_PRINTING
;
1322 cp
= buf
.qb2
+ sizeof(dns_hdr_t
);
1323 if (ntohs(buf
.qb1
.dh_qdcount
) > 0)
1324 cp
+= dn_skipname(cp
, buf
.qb2
+ len
) + QFIXEDSZ
;
1327 cp
+= dn_skipname(cp
, (u_char
*)&buf
+ len
);
1328 if ((_getshort(cp
) == T_SOA
)) {
1329 dn_expand(buf
.qb2
, buf
.qb2
+ len
, nmp
, (u8_t
*)dname
[soacnt
],
1332 if (strcmp(dname
[0], dname
[1]) == 0)
1345 case ERR_READING_LEN
:
1349 fprintf(stderr
,"*** Error during listing of %s: %s\n",
1350 namePtr
, DecodeError(result
));
1353 case ERR_READING_MSG
:
1354 headerPtr
= (dns_hdr_t
*) &buf
;
1355 fprintf(stderr
,"ListHosts: error receiving zone transfer:\n");
1357 " result: %s, answers = %d, authority = %d, additional = %d\n",
1358 resultcodes
[headerPtr
->dh_flag2
& DHF_RCODE
],
1359 ntohs(headerPtr
->dh_ancount
),
1360 ntohs(headerPtr
->dh_nscount
),
1361 ntohs(headerPtr
->dh_arcount
));
1373 case NOERROR
: return("Success"); break;
1374 case FORMERR
: return("Format error"); break;
1375 case SERVFAIL
: return("Server failed"); break;
1376 case NXDOMAIN
: return("Non-existent domain"); break;
1377 case NOTIMP
: return("Not implemented"); break;
1378 case REFUSED
: return("Query refused"); break;
1379 case NOCHANGE
: return("No change"); break;
1380 case NO_INFO
: return("No information"); break;
1381 case ERROR
: return("Unspecified error"); break;
1382 case TIME_OUT
: return("Timed out"); break;
1383 case NONAUTH
: return("Non-authoritative answer"); break;
1386 return("BAD ERROR VALUE");
1389 static int tcpip_writeall(fd
, buf
, siz
)
1401 nbytes
= write(fd
, buf
, siz
);
1404 assert(siz
>= nbytes
);