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.
19 #if _MINIX && !defined(__NBSD_LIBC)
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>
57 #include <sys/ioctl.h>
58 #include <sys/ioc_net.h>
59 #include <net/netlib.h>
60 #include <net/gen/in.h>
61 #include <net/gen/tcp.h>
62 #include <net/gen/tcp_io.h>
81 #define NO_DATA NO_ADDRESS
93 static struct __res_state orig
;
96 extern struct state _res
;
98 static u8_t
*cname
= NULL
;
100 int gettype
, getdeftype
= T_A
;
103 int server_specified
= 0;
107 int main( int c
, char *v
[] );
109 static int parsetype( char *s
);
110 static int parseclass( char *s
);
111 static void hperror( int err_no
);
112 static void printanswer( struct hostent
*hp
);
113 static int ListHosts( char *namePtr
, int queryType
);
114 static int gethostinfo( char *name
);
115 static int getdomaininfo( char *name
, char *domain
);
116 static int getinfo( char *name
, char *domain
, int type
);
117 static int printinfo( union querybuf
*answer
, u8_t
*eom
, int filter
, int
119 static char *DecodeError( int result
);
120 static u8_t
*pr_rr( u8_t
*cp
, u8_t
*msg
, FILE *file
, int filter
);
121 static u8_t
* pr_cdname( u8_t
*cp
, u8_t
*msg
, u8_t
*name
, int namelen
);
122 static char *pr_class( int class );
123 static char *pr_type( int type
);
124 static int tcpip_writeall( int fd
, char *buf
, unsigned siz
);
136 register struct hostent
*hp
;
137 register char *s
, *p
;
138 register inverse
= 0;
139 register waitmode
= 0;
148 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");
151 while (c
> 2 && v
[1][0] == '-') {
152 if (strcmp (v
[1], "-w") == 0) {
159 else if (strcmp (v
[1], "-r") == 0) {
160 _res
.options
&= ~RES_RECURSE
;
164 else if (strcmp (v
[1], "-d") == 0) {
165 _res
.options
|= RES_DEBUG
;
169 else if (strcmp (v
[1], "-v") == 0) {
174 else if (strcmp (v
[1], "-l") == 0) {
179 else if (strncmp (v
[1], "-t", 2) == 0) {
182 gettype
= parsetype(v
[1]);
186 else if (strncmp (v
[1], "-c", 2) == 0) {
189 getclass
= parseclass(v
[1]);
193 else if (strcmp (v
[1], "-a") == 0) {
199 else if (strcmp (v
[1], "-V") == 0) {
200 _res
.options
|= RES_USEVC
;
209 if ((p
= strchr(s
, ':')) != NULL
) *p
++ = 0;
210 isaddr
= inet_aton(s
, &addr
);
211 if (p
!= NULL
) p
[-1] = ':';
213 hp
= gethostbyname(s
);
215 fprintf(stderr
,"Error in looking up server name:\n");
220 memcpy(&_res
.nsaddr
.sin_addr
, hp
->h_addr
, NS_INADDRSZ
);
222 _res
.nsaddr
= *(ipaddr_t
*)hp
->h_addr
;
224 printf("Using domain server:\n");
229 _res
.nsaddr
.sin_family
= AF_INET
;
230 _res
.nsaddr
.sin_addr
= addr
;
231 _res
.nsaddr
.sin_port
= htons(NAMESERVER_PORT
);
232 printf("Using domain server %s:\n",
233 inet_ntoa(_res
.nsaddr
.sin_addr
));
236 _res
.nsaddr_list
[0]= addr
;
237 _res
.nsport_list
[0]= htons(NAMESERVER_PORT
);
238 printf("Using domain server %s",
239 inet_ntoa(_res
.nsaddr
));
241 printf(" on port %d", atoi(p
));
242 _res
.nsport_list
[0]= htons(atoi(p
));
249 if (strcmp (domain
, ".") != 0 && inet_aton(domain
, &addr
)) {
250 static char ipname
[sizeof("255.255.255.255.in-addr.arpa.")];
251 sprintf(ipname
, "%d.%d.%d.%d.in-addr.arpa.",
252 ((unsigned char *) &addr
)[3],
253 ((unsigned char *) &addr
)[2],
254 ((unsigned char *) &addr
)[1],
255 ((unsigned char *) &addr
)[0]);
263 * we handle default domains ourselves, thank you
265 _res
.options
&= ~RES_DEFNAMES
;
268 exit(ListHosts(domain
, gettype
? gettype
: getdeftype
));
271 while (hp
== NULL
&& h_errno
== TRY_AGAIN
) {
273 if (oldcname
== NULL
)
274 hp
= (struct hostent
*)gethostinfo(domain
);
276 hp
= (struct hostent
*)gethostinfo((char *)oldcname
);
278 if (ncnames
-- == 0) {
279 printf("Too many cnames. Possible loop.\n");
304 if (strcmp(s
,"a") == 0)
306 if (strcmp(s
,"ns") == 0)
308 if (strcmp(s
,"md") == 0)
310 if (strcmp(s
,"mf") == 0)
312 if (strcmp(s
,"cname") == 0)
314 if (strcmp(s
,"soa") == 0)
316 if (strcmp(s
,"mb") == 0)
318 if (strcmp(s
,"mg") == 0)
320 if (strcmp(s
,"mr") == 0)
322 if (strcmp(s
,"null") == 0)
324 if (strcmp(s
,"wks") == 0)
326 if (strcmp(s
,"ptr") == 0)
328 if (strcmp(s
,"hinfo") == 0)
330 if (strcmp(s
,"minfo") == 0)
332 if (strcmp(s
,"mx") == 0)
334 if (strcmp(s
,"txt") == 0) /* Roy */
335 return(T_TXT
); /* Roy */
336 if (strcmp(s
,"uinfo") == 0)
338 if (strcmp(s
,"uid") == 0)
340 if (strcmp(s
,"gid") == 0)
342 if (strcmp(s
,"unspec") == 0)
344 if (strcmp(s
,"any") == 0)
346 if (strcmp(s
,"*") == 0)
350 fprintf(stderr
, "Invalid query type: %s\n", s
);
358 if (strcmp(s
,"in") == 0)
360 if (strcmp(s
,"chaos") == 0)
362 if (strcmp(s
,"hs") == 0)
364 if (strcmp(s
,"any") == 0)
368 fprintf(stderr
, "Invalid query class: %s\n", s
);
374 register struct hostent
*hp
;
378 struct in_addr
**hptr
;
380 register ipaddr_t
**hptr
;
383 printf("Name: %s\n", hp
->h_name
);
386 for (hptr
= (struct in_addr
**)hp
->h_addr_list
; *hptr
; hptr
++)
387 printf(" %s", inet_ntoa(**hptr
));
389 for (hptr
= (ipaddr_t
**)hp
->h_addr_list
; *hptr
; hptr
++)
390 printf(" %s", inet_ntoa(*(ipaddr_t
*)*hptr
));
392 printf("\nAliases:");
393 for (cp
= hp
->h_aliases
; cp
&& *cp
&& **cp
; cp
++)
404 fprintf(stderr
,"Host not found.\n");
407 fprintf(stderr
,"Host not found, try again.\n");
410 fprintf(stderr
,"No recovery, Host not found.\n");
413 fprintf(stderr
,"There is an entry for this host, but it doesn't have what you requested.\n");
418 typedef union querybuf
{
423 static u8_t hostbuf
[BUFSIZ
+1];
430 register char *cp
, **domain
;
435 if (strcmp(name
, ".") == 0)
436 return(getdomaininfo(name
, NULL
));
437 for (cp
= name
, n
= 0; *cp
; cp
++)
440 if (n
&& cp
[-1] == '.') {
443 hp
= getdomaininfo(name
, (char *)NULL
);
448 if (n
== 0 && (cp
= __hostalias(name
))) {
450 printf("Aliased to \"%s\"\n", cp
);
451 _res
.options
|= RES_DEFNAMES
;
452 return (getdomaininfo(cp
, (char *)NULL
));
456 _res
.defdname_list
[nDomain
][0] != 0;
458 for (domain
= _res
.dnsrch_list
[nDomain
]; *domain
; domain
++) {
460 printf("Trying domain \"%s\"\n", *domain
);
461 hp
= getdomaininfo(name
, *domain
);
467 for (domain
= _res
.dnsrch
; *domain
; domain
++) {
469 printf("Trying domain \"%s\"\n", *domain
);
470 hp
= getdomaininfo(name
, *domain
);
475 if (h_errno
!= HOST_NOT_FOUND
||
476 (_res
.options
& RES_DNSRCH
) == 0)
479 printf("Trying null domain\n");
480 return (getdomaininfo(name
, (char *)NULL
));
484 getdomaininfo(name
, domain
)
487 return getinfo(name
, domain
, gettype
? gettype
: getdeftype
);
491 getinfo(name
, domain
, type
)
497 querybuf_t buf
, answer
;
498 int n
, n1
, i
, j
, nmx
, ancount
, nscount
, arcount
, qdcount
, buflen
;
500 char host
[2*MAXDNAME
+2];
503 (void)sprintf(host
, "%.*s", MAXDNAME
, name
);
505 (void)sprintf(host
, "%.*s.%.*s", MAXDNAME
, name
, MAXDNAME
, domain
);
507 n
= res_mkquery(QUERY
, host
, getclass
, type
, (char *)NULL
, 0, NULL
,
508 (char *)&buf
, sizeof(buf
));
510 if (_res
.options
& RES_DEBUG
)
511 printf("res_mkquery failed\n");
512 h_errno
= NO_RECOVERY
;
515 n
= res_send((char *)&buf
, n
, (char *)&answer
, sizeof(answer
));
517 if (_res
.options
& RES_DEBUG
)
518 printf("res_send failed\n");
522 eom
= (u8_t
*)&answer
+ n
;
523 return(printinfo(&answer
, eom
, T_ANY
, 0));
527 printinfo(answer
, eom
, filter
, isls
)
535 int n
, n1
, i
, j
, nmx
, ancount
, nscount
, arcount
, qdcount
, buflen
;
539 * find first satisfactory answer
541 hp
= (HEADER
*) answer
;
542 ancount
= ntohs(hp
->dh_ancount
);
543 qdcount
= ntohs(hp
->dh_qdcount
);
544 nscount
= ntohs(hp
->dh_nscount
);
545 arcount
= ntohs(hp
->dh_arcount
);
546 if (_res
.options
& RES_DEBUG
|| (verbose
&& isls
== 0))
547 printf("rcode = %d (%s), ancount=%d\n",
550 DecodeError(hp
->rcode
),
552 hp
->dh_flag2
& DHF_RCODE
,
553 DecodeError(hp
->dh_flag2
& DHF_RCODE
),
558 hp
->rcode
!= NOERROR
||
560 hp
->dh_flag2
& DHF_RCODE
!= NOERROR
||
562 (ancount
+nscount
+arcount
) == 0) {
567 hp
->dh_flag2
& DHF_RCODE
571 /* Check if it's an authoritive answer */
576 hp
->dh_flag1
& DHF_AA
579 h_errno
= HOST_NOT_FOUND
;
590 * Jeeves (TOPS-20 server) still does not
591 * support MX records. For the time being,
592 * we must accept FORMERRs as the same as
596 #endif /* OLDJEEVES */
598 /* TpB - set a return error for this case. NO_DATA */
600 return(0); /* was 1,but now indicates exception */
603 #endif /* OLDJEEVES */
606 h_errno
= NO_RECOVERY
;
613 buflen
= sizeof(hostbuf
);
614 cp
= (u8_t
*)answer
+ sizeof(HEADER
);
616 cp
+= dn_skipname((u8_t
*)cp
,(u8_t
*)eom
) + QFIXEDSZ
;
617 while (--qdcount
> 0)
618 cp
+= dn_skipname((u8_t
*)cp
,(u8_t
*)eom
) + QFIXEDSZ
;
625 (hp
->dh_flag1
& DHF_AA
)
628 if (verbose
&& isls
== 0)
629 printf("The following answer is not authoritative:\n");
630 while (--ancount
>= 0 && cp
&& cp
< eom
) {
631 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
633 * When we ask for address and there is a CNAME, it seems to return
634 * both the CNAME and the address. Since we trace down the CNAME
635 * chain ourselves, we don't really want to print the address at
638 if (cname
&& ! verbose
)
645 printf("For authoritative answers, see:\n");
646 while (--nscount
>= 0 && cp
&& cp
< eom
) {
647 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
651 printf("Additional information:\n");
652 while (--arcount
>= 0 && cp
&& cp
< eom
) {
653 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
659 static u8_t cnamebuf
[MAXDNAME
];
662 * Print resource record fields in human readable form.
665 pr_rr(cp
, msg
, file
, filter
)
670 int type
, class, dlen
, n
, c
, proto
, ttl
;
672 struct in_addr inaddr
;
677 struct protoent
*protop
;
678 struct servent
*servp
;
683 if ((cp
= pr_cdname(cp
, msg
, name
, sizeof(name
))) == NULL
)
684 return (NULL
); /* compression error */
686 type
= _getshort(cp
);
687 cp
+= sizeof(u_short
);
689 class = _getshort(cp
);
690 cp
+= sizeof(u_short
);
693 cp
+= sizeof(u_long
);
695 if (filter
== type
|| filter
== T_ANY
||
696 (filter
== T_A
&& (type
== T_PTR
|| type
== T_NS
)))
703 fprintf(file
,"%s\t%d%s\t%s",
704 name
, ttl
, pr_class(class), pr_type(type
));
706 fprintf(file
,"%s%s %s",name
, pr_class(class), pr_type(type
));
712 dlen
= _getshort(cp
);
713 cp
+= sizeof(u_short
);
716 * Print type specific data, if appropriate
722 bcopy((char *)cp
, (char *)&inaddr
, sizeof(inaddr
));
725 fprintf(file
,"%c%s", punc
,
728 } else if (dlen
== 7) {
730 fprintf(file
,"%c%s", punc
,
732 fprintf(file
,", protocol = %d", cp
[4]);
733 fprintf(file
,", port = %d",
734 (cp
[5] << 8) + cp
[6]);
742 if (dn_expand(msg
, msg
+ 512, cp
, cnamebuf
,
743 sizeof(cnamebuf
)-1) >= 0) {
744 strcat((char *) cnamebuf
, ".");
745 if (gettype
!= T_CNAME
&& gettype
!= T_ANY
)
757 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
759 fprintf(file
,"%c%s",punc
, name
);
765 fprintf(file
,"%c%.*s", punc
, n
, cp
);
770 fprintf(file
,"%c%.*s", punc
, n
, cp
);
776 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
778 fprintf(file
,"\t%s", name
);
779 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
781 fprintf(file
," %s", name
);
783 fprintf(file
,"(\n\t\t\t%ld\t;serial (version)", _getlong(cp
));
784 cp
+= sizeof(u_long
);
786 fprintf(file
,"\n\t\t\t%ld\t;refresh period", _getlong(cp
));
787 cp
+= sizeof(u_long
);
789 fprintf(file
,"\n\t\t\t%ld\t;retry refresh this often", _getlong(cp
));
790 cp
+= sizeof(u_long
);
792 fprintf(file
,"\n\t\t\t%ld\t;expiration period", _getlong(cp
));
793 cp
+= sizeof(u_long
);
795 fprintf(file
,"\n\t\t\t%ld\t;minimum TTL\n\t\t\t)", _getlong(cp
));
796 cp
+= sizeof(u_long
);
802 fprintf(file
,"\t%d ",_getshort(cp
));
804 fprintf(file
," (pri=%d) by ",_getshort(cp
));
805 cp
+= sizeof(u_short
);
806 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
808 fprintf(file
, "%s", name
);
812 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
814 fprintf(file
,"%c%s",punc
, name
);
815 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
817 fprintf(file
," %s", name
);
824 fprintf(file
,"%c%.*s", punc
, n
, cp
);
832 fprintf(file
,"%c%s", punc
, cp
);
840 fprintf(file
,"%c%ld", punc
, _getlong(cp
));
846 if (dlen
< sizeof(u_long
) + 1)
848 bcopy((char *)cp
, (char *)&inaddr
, sizeof(inaddr
));
849 cp
+= sizeof(u_long
);
851 protop
= getprotobynumber(proto
);
854 fprintf(file
,"%c%s %s", punc
,
855 inet_ntoa(inaddr
), protop
->p_name
);
857 fprintf(file
,"%c%s %d", punc
,
858 inet_ntoa(inaddr
), proto
);
861 while (cp
< cp1
+ dlen
) {
867 servp
= getservbyport (htons(n
),
871 fprintf(file
, " %s", servp
->s_name
);
873 fprintf(file
, " %d", n
);
882 fprintf(file
,"%c???", punc
);
885 if (cp
!= cp1
+ dlen
)
886 fprintf(file
,"packet size error (%#x != %#x)\n", cp
, cp1
+dlen
);
892 static char nbuf
[20];
895 * Return a string for the type
903 return(verbose
? "A" : "has address");
904 case T_NS
: /* authoritative server */
907 case T_MD
: /* mail destination */
909 case T_MF
: /* mail forwarder */
912 case T_CNAME
: /* connonical name */
913 return(verbose
? "CNAME" : "is a nickname for");
914 case T_SOA
: /* start of authority zone */
916 case T_MB
: /* mailbox domain name */
918 case T_MG
: /* mail group member */
920 case T_MX
: /* mail routing info */
921 return(verbose
? "MX" : "mail is handled");
923 case T_TXT
: /* TXT - descriptive info */
924 return(verbose
? "TXT" : "descriptive text");
926 case T_MR
: /* mail rename name */
928 case T_NULL
: /* null resource record */
930 case T_WKS
: /* well known service */
932 case T_PTR
: /* domain name pointer */
934 case T_HINFO
: /* host information */
936 case T_MINFO
: /* mailbox information */
938 case T_AXFR
: /* zone transfer */
940 case T_MAILB
: /* mail box */
942 case T_MAILA
: /* mail address */
944 case T_ANY
: /* matches any type */
955 return (sprintf(nbuf
, "%d", type
) == EOF
? NULL
: nbuf
);
960 * Return a mnemonic for class
968 case C_IN
: /* internet class */
969 return(verbose
? " IN" : "");
970 case C_CHAOS
: /* chaos class */
971 return(verbose
? " CHAOS" : "");
972 case C_HS
: /* Hesiod class */
973 return(verbose
? " HS" : "");
974 case C_ANY
: /* matches any class */
977 return (sprintf(nbuf
," %d", class) == EOF
? NULL
: nbuf
);
982 pr_cdname(cp
, msg
, name
, namelen
)
989 if ((n
= dn_expand(msg
, msg
+ 512, cp
, name
, namelen
- 2)) < 0)
991 if (name
[0] == '\0') {
998 char *resultcodes
[] = {
1020 ******************************************************************************
1024 * Requests the name server to do a zone transfer so we
1025 * find out what hosts it knows about.
1028 * SUCCESS the listing was successful.
1029 * ERROR the server could not be contacted because
1030 * a socket could not be obtained or an error
1031 * occured while receiving, or the output file
1032 * could not be opened.
1034 ******************************************************************************
1038 ListHosts(namePtr
, queryType
)
1040 int queryType
; /* e.g. T_A */
1042 querybuf_t buf
, answer
;
1057 u8_t name
[NAME_LEN
];
1058 char dname
[2][NAME_LEN
];
1059 u8_t domain
[NAME_LEN
];
1060 /* names and addresses of name servers to try */
1062 char nsname
[NUMNS
][NAME_LEN
];
1063 int nshaveaddr
[NUMNS
];
1064 #define IPADDRSIZE 4
1065 #define NUMNSADDR 16
1066 char nsipaddr
[NUMNSADDR
][IPADDRSIZE
];
1076 } error
= NO_ERRORS
;
1077 char *tcp_serv_name
;
1079 nwio_tcpconf_t tcpconf
;
1084 * normalize to not have trailing dot. We do string compares below
1085 * of info from name server, and it won't have trailing dots.
1087 i
= strlen(namePtr
);
1088 if (namePtr
[i
-1] == '.')
1091 if (server_specified
) {
1092 bcopy((char *)&_res
.nsaddr
, nsipaddr
[0], IPADDRSIZE
);
1098 * First we have to find out where to look. This needs a NS query,
1099 * possibly followed by looking up addresses for some of the names.
1102 msglen
= res_mkquery(QUERY
, namePtr
, C_IN
, T_NS
,
1103 (char *)0, 0, (struct rrec
*)0,
1104 (char *)&buf
, sizeof(buf
));
1107 printf("res_mkquery failed\n");
1111 msglen
= res_send((char *)&buf
,msglen
,(char *)&answer
, sizeof(answer
));
1114 printf("Unable to get to nameserver -- try again later\n");
1117 if (_res
.options
& RES_DEBUG
|| verbose
)
1118 printf("rcode = %d (%s), ancount=%d\n",
1121 DecodeError(answer
.qb1
.rcode
),
1122 ntohs(answer
.qb1
.ancount
)
1124 answer
.qb1
.dh_flag2
& DHF_RCODE
,
1125 DecodeError(answer
.qb1
.dh_flag2
& DHF_RCODE
),
1126 ntohs(answer
.qb1
.dh_ancount
)
1131 * Analyze response to our NS lookup
1135 nscount
= ntohs(answer
.qb1
.ancount
) +
1136 ntohs(answer
.qb1
.nscount
) +
1137 ntohs(answer
.qb1
.arcount
);
1139 nscount
= ntohs(answer
.qb1
.dh_ancount
) + ntohs(answer
.qb1
.dh_nscount
) +
1140 ntohs(answer
.qb1
.dh_arcount
);
1146 answer
.qb1
.rcode
!= NOERROR
|| nscount
== 0
1148 answer
.qb1
.dh_flag2
& DHF_RCODE
!= NOERROR
|| nscount
== 0
1155 answer
.qb1
.dh_flag2
& DHF_RCODE
1159 /* Check if it's an authoritive answer */
1164 answer
.qb1
.dh_flag1
& DHF_AA
1168 printf("No such domain\n");
1170 printf("Unable to get information about domain -- try again later.\n");
1174 printf("Unable to get information about that domain -- try again later.\n");
1177 printf("That domain exists, but seems to be a leaf node.\n");
1182 printf("Unrecoverable error looking up domain name.\n");
1188 cp
= answer
.qb2
+ sizeof(HEADER
);
1189 if (ntohs(answer
.qb1
.dh_qdcount
) > 0)
1190 cp
+= dn_skipname(cp
, answer
.qb2
+ msglen
) + QFIXEDSZ
;
1196 * Look at response from NS lookup for NS and A records.
1199 for (;nscount
; nscount
--) {
1200 cp
+= dn_expand(answer
.qb2
, answer
.qb2
+ msglen
, cp
,
1201 domain
, sizeof(domain
));
1202 type
= _getshort(cp
);
1203 cp
+= sizeof(u_short
) + sizeof(u_short
) + sizeof(u_long
);
1204 dlen
= _getshort(cp
);
1205 cp
+= sizeof(u_short
);
1207 if (dn_expand(answer
.qb2
, answer
.qb2
+ msglen
, cp
,
1208 name
, sizeof(name
)) >= 0) {
1209 if (numns
< NUMNS
&& strcasecmp((char *)domain
, namePtr
) == 0) {
1210 for (i
= 0; i
< numns
; i
++)
1211 if (strcasecmp(nsname
[i
], (char *)name
) == 0)
1212 break; /* duplicate */
1214 strncpy(nsname
[numns
], (char *)name
, sizeof(name
));
1215 nshaveaddr
[numns
] = 0;
1221 else if (type
== T_A
) {
1222 if (numnsaddr
< NUMNSADDR
)
1223 for (i
= 0; i
< numns
; i
++) {
1224 if (strcasecmp(nsname
[i
], (char *)domain
) == 0) {
1226 bcopy((char *)cp
, nsipaddr
[numnsaddr
],IPADDRSIZE
);
1236 * Usually we'll get addresses for all the servers in the additional
1237 * info section. But in case we don't, look up their addresses.
1240 for (i
= 0; i
< numns
; i
++) {
1241 if (! nshaveaddr
[i
]) {
1242 register long **hptr
;
1245 hp
= gethostbyname(nsname
[i
]);
1247 for (hptr
= (long **)hp
->h_addr_list
; *hptr
; hptr
++)
1248 if (numnsaddr
< NUMNSADDR
) {
1249 bcopy((char *)*hptr
, nsipaddr
[numnsaddr
],IPADDRSIZE
);
1254 if (_res
.options
& RES_DEBUG
|| verbose
)
1255 printf("Found %d addresses for %s by extra query\n",
1256 numaddrs
, nsname
[i
]);
1259 if (_res
.options
& RES_DEBUG
|| verbose
)
1260 printf("Found %d addresses for %s\n",
1261 nshaveaddr
[i
], nsname
[i
]);
1265 * Now nsipaddr has numnsaddr addresses for name servers that
1266 * serve the requested domain. Now try to find one that will
1267 * accept a zone transfer.
1278 * Create a query packet for the requested domain name.
1281 msglen
= res_mkquery(QUERY
, namePtr
, getclass
, T_AXFR
,
1282 (char *)0, 0, (struct rrec
*)0,
1283 (char *) &buf
, sizeof(buf
));
1285 if (_res
.options
& RES_DEBUG
) {
1286 fprintf(stderr
, "ListHosts: Res_mkquery failed\n");
1292 * Set up a virtual circuit to the server.
1295 tcp_serv_name
= getenv("TCP_DEVICE");
1297 tcp_serv_name
= TCP_DEVICE
;
1298 for (;thisns
< numnsaddr
; thisns
++)
1300 tcp_fd
= open(tcp_serv_name
, O_RDWR
);
1303 fprintf(stderr
, "unable to open '%s': %s\n", tcp_serv_name
,
1308 tcpconf
.nwtc_flags
= NWTC_EXCL
| NWTC_LP_SEL
| NWTC_SET_RA
|
1310 tcpconf
.nwtc_remaddr
= *(ipaddr_t
*)nsipaddr
[thisns
];
1312 tcpconf
.nwtc_remport
= _res
.nsaddr
.sin_port
;
1314 tcpconf
.nwtc_remport
= _res
.nsport_list
[0];
1316 result
= ioctl(tcp_fd
, NWIOSTCPCONF
, &tcpconf
);
1319 fprintf(stderr
, "tcp_ioc_setconf failed: %s\n",
1324 if (_res
.options
& RES_DEBUG
|| verbose
)
1325 printf("Trying %s\n", inet_ntoa(tcpconf
.nwtc_remaddr
));
1326 clopt
.nwtcl_flags
= 0;
1327 result
= ioctl(tcp_fd
, NWIOTCPCONN
, &clopt
);
1333 "Connection failed, trying next server: %s\n",
1337 if (thisns
>= numnsaddr
) {
1338 printf("No server for that domain responded\n");
1340 fprintf(stderr
, "Error from the last server was: %s\n",
1346 * Send length & message for zone transfer
1349 len
= htons(msglen
);
1351 result
= tcpip_writeall(tcp_fd
, (char *)&len
, sizeof(len
));
1352 if (result
!= sizeof(len
))
1354 fprintf(stderr
, "write failed: %s\n", strerror(errno
));
1358 result
= tcpip_writeall(tcp_fd
, (char *)&buf
, msglen
);
1359 if (result
!= msglen
)
1361 fprintf(stderr
, "write failed: %s\n",
1371 * Read the length of the response.
1375 amtToRead
= sizeof(u_short
);
1376 while(amtToRead
> 0)
1378 result
= read(tcp_fd
, (char *)cp
, amtToRead
);
1382 amtToRead
-= result
;
1385 error
= ERR_READING_LEN
;
1389 if ((len
= htons(*(u_short
*)&buf
)) == 0) {
1390 break; /* nothing left to read */
1394 * Read the response.
1399 while(amtToRead
> 0)
1401 result
= read(tcp_fd
, (char *)cp
, amtToRead
);
1405 amtToRead
-= result
;
1408 error
= ERR_READING_MSG
;
1415 i
= buf
.qb1
.dh_flag2
& DHF_RCODE
;
1417 if (i
!= NOERROR
|| ntohs(buf
.qb1
.dh_ancount
) == 0) {
1418 if ((thisns
+1) < numnsaddr
&&
1419 (i
== SERVFAIL
|| i
== NOTIMP
|| i
== REFUSED
)) {
1420 if (_res
.options
& RES_DEBUG
|| verbose
)
1421 printf("Server failed, trying next server: %s\n",
1423 DecodeError(i
) : "Premature end of data");
1428 printf("Server failed: %s\n",
1429 i
!= NOERROR
? DecodeError(i
) : "Premature end of data");
1434 result
= printinfo(&buf
, cp
, queryType
, 1);
1436 error
= ERR_PRINTING
;
1440 cp
= buf
.qb2
+ sizeof(HEADER
);
1441 if (ntohs(buf
.qb1
.dh_qdcount
) > 0)
1442 cp
+= dn_skipname(cp
, buf
.qb2
+ len
) + QFIXEDSZ
;
1445 cp
+= dn_skipname(cp
, (u_char
*)&buf
+ len
);
1446 if ((_getshort(cp
) == T_SOA
)) {
1447 dn_expand(buf
.qb2
, buf
.qb2
+ len
, nmp
, (u8_t
*)dname
[soacnt
],
1450 if (strcmp(dname
[0], dname
[1]) == 0)
1463 case ERR_READING_LEN
:
1467 fprintf(stderr
,"*** Error during listing of %s: %s\n",
1468 namePtr
, DecodeError(result
));
1471 case ERR_READING_MSG
:
1472 headerPtr
= (HEADER
*) &buf
;
1473 fprintf(stderr
,"ListHosts: error receiving zone transfer:\n");
1475 " result: %s, answers = %d, authority = %d, additional = %d\n",
1477 resultcodes
[headerPtr
->rcode
],
1479 resultcodes
[headerPtr
->dh_flag2
& DHF_RCODE
],
1481 ntohs(headerPtr
->dh_ancount
),
1482 ntohs(headerPtr
->dh_nscount
),
1483 ntohs(headerPtr
->dh_arcount
));
1495 case NOERROR
: return("Success"); break;
1496 case FORMERR
: return("Format error"); break;
1497 case SERVFAIL
: return("Server failed"); break;
1498 case NXDOMAIN
: return("Non-existent domain"); break;
1499 case NOTIMP
: return("Not implemented"); break;
1500 case REFUSED
: return("Query refused"); break;
1501 case NOCHANGE
: return("No change"); break;
1502 case NO_INFO
: return("No information"); break;
1503 case ERROR
: return("Unspecified error"); break;
1504 case TIME_OUT
: return("Timed out"); break;
1505 case NONAUTH
: return("Non-authoritative answer"); break;
1508 return("BAD ERROR VALUE");
1511 static int tcpip_writeall(fd
, buf
, siz
)
1523 nbytes
= write(fd
, buf
, siz
);
1526 assert(siz
>= nbytes
);