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 <arpa/nameser.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
26 #include <sys/param.h>
33 #include <sys/ioctl.h>
34 #include <sys/ioc_net.h>
35 #include <net/netlib.h>
36 #include <net/gen/in.h>
37 #include <net/gen/tcp.h>
38 #include <net/gen/tcp_io.h>
56 #define NO_DATA NO_ADDRESS
67 static struct __res_state orig
;
68 static u8_t
*cname
= NULL
;
70 int gettype
, getdeftype
= T_A
;
73 int server_specified
= 0;
77 int main( int c
, char *v
[] );
79 static int parsetype( char *s
);
80 static int parseclass( char *s
);
81 static void hperror( int err_no
);
82 static void printanswer( struct hostent
*hp
);
83 static int ListHosts( char *namePtr
, int queryType
);
84 static int gethostinfo( char *name
);
85 static int getdomaininfo( char *name
, char *domain
);
86 static int getinfo( char *name
, char *domain
, int type
);
87 static int printinfo( union querybuf
*answer
, u8_t
*eom
, int filter
, int
89 static char *DecodeError( int result
);
90 static u8_t
*pr_rr( u8_t
*cp
, u8_t
*msg
, FILE *file
, int filter
);
91 static u8_t
* pr_cdname( u8_t
*cp
, u8_t
*msg
, u8_t
*name
, int namelen
);
92 static char *pr_class( int class );
93 static char *pr_type( int type
);
94 static int tcpip_writeall( int fd
, char *buf
, unsigned siz
);
103 register struct hostent
*hp
;
104 register char *s
, *p
;
105 register int inverse
= 0;
106 register int waitmode
= 0;
115 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");
118 while (c
> 2 && v
[1][0] == '-') {
119 if (strcmp (v
[1], "-w") == 0) {
126 else if (strcmp (v
[1], "-r") == 0) {
127 _res
.options
&= ~RES_RECURSE
;
131 else if (strcmp (v
[1], "-d") == 0) {
132 _res
.options
|= RES_DEBUG
;
136 else if (strcmp (v
[1], "-v") == 0) {
141 else if (strcmp (v
[1], "-l") == 0) {
146 else if (strncmp (v
[1], "-t", 2) == 0) {
149 gettype
= parsetype(v
[1]);
153 else if (strncmp (v
[1], "-c", 2) == 0) {
156 getclass
= parseclass(v
[1]);
160 else if (strcmp (v
[1], "-a") == 0) {
166 else if (strcmp (v
[1], "-V") == 0) {
167 _res
.options
|= RES_USEVC
;
176 if ((p
= strchr(s
, ':')) != NULL
) *p
++ = 0;
177 isaddr
= inet_aton(s
, &addr
);
178 if (p
!= NULL
) p
[-1] = ':';
180 hp
= gethostbyname(s
);
182 fprintf(stderr
,"Error in looking up server name:\n");
186 memcpy(&_res
.nsaddr
.sin_addr
, hp
->h_addr
, NS_INADDRSZ
);
187 printf("Using domain server:\n");
191 _res
.nsaddr
.sin_family
= AF_INET
;
192 _res
.nsaddr
.sin_addr
= addr
;
193 _res
.nsaddr
.sin_port
= htons(NAMESERVER_PORT
);
194 printf("Using domain server %s:\n",
195 inet_ntoa(_res
.nsaddr
.sin_addr
));
200 if (strcmp (domain
, ".") != 0 && inet_aton(domain
, &addr
)) {
201 static char ipname
[sizeof("255.255.255.255.in-addr.arpa.")];
202 sprintf(ipname
, "%d.%d.%d.%d.in-addr.arpa.",
203 ((unsigned char *) &addr
)[3],
204 ((unsigned char *) &addr
)[2],
205 ((unsigned char *) &addr
)[1],
206 ((unsigned char *) &addr
)[0]);
214 * we handle default domains ourselves, thank you
216 _res
.options
&= ~RES_DEFNAMES
;
219 exit(ListHosts(domain
, gettype
? gettype
: getdeftype
));
222 while (hp
== NULL
&& h_errno
== TRY_AGAIN
) {
224 if (oldcname
== NULL
)
225 hp
= (struct hostent
*)gethostinfo(domain
);
227 hp
= (struct hostent
*)gethostinfo((char *)oldcname
);
229 if (ncnames
-- == 0) {
230 printf("Too many cnames. Possible loop.\n");
255 if (strcmp(s
,"a") == 0)
257 if (strcmp(s
,"ns") == 0)
259 if (strcmp(s
,"md") == 0)
261 if (strcmp(s
,"mf") == 0)
263 if (strcmp(s
,"cname") == 0)
265 if (strcmp(s
,"soa") == 0)
267 if (strcmp(s
,"mb") == 0)
269 if (strcmp(s
,"mg") == 0)
271 if (strcmp(s
,"mr") == 0)
273 if (strcmp(s
,"null") == 0)
275 if (strcmp(s
,"wks") == 0)
277 if (strcmp(s
,"ptr") == 0)
279 if (strcmp(s
,"hinfo") == 0)
281 if (strcmp(s
,"minfo") == 0)
283 if (strcmp(s
,"mx") == 0)
285 if (strcmp(s
,"txt") == 0) /* Roy */
286 return(T_TXT
); /* Roy */
287 if (strcmp(s
,"uinfo") == 0)
289 if (strcmp(s
,"uid") == 0)
291 if (strcmp(s
,"gid") == 0)
293 if (strcmp(s
,"unspec") == 0)
295 if (strcmp(s
,"any") == 0)
297 if (strcmp(s
,"*") == 0)
301 fprintf(stderr
, "Invalid query type: %s\n", s
);
309 if (strcmp(s
,"in") == 0)
311 if (strcmp(s
,"chaos") == 0)
313 if (strcmp(s
,"hs") == 0)
315 if (strcmp(s
,"any") == 0)
319 fprintf(stderr
, "Invalid query class: %s\n", s
);
325 register struct hostent
*hp
;
328 struct in_addr
**hptr
;
330 printf("Name: %s\n", hp
->h_name
);
332 for (hptr
= (struct in_addr
**)hp
->h_addr_list
; *hptr
; hptr
++)
333 printf(" %s", inet_ntoa(**hptr
));
334 printf("\nAliases:");
335 for (cp
= hp
->h_aliases
; cp
&& *cp
&& **cp
; cp
++)
346 fprintf(stderr
,"Host not found.\n");
349 fprintf(stderr
,"Host not found, try again.\n");
352 fprintf(stderr
,"No recovery, Host not found.\n");
355 fprintf(stderr
,"There is an entry for this host, but it doesn't have what you requested.\n");
360 typedef union querybuf
{
365 static u8_t hostbuf
[BUFSIZ
+1];
372 register char *cp
, **domain
;
377 if (strcmp(name
, ".") == 0)
378 return(getdomaininfo(name
, NULL
));
379 for (cp
= name
, n
= 0; *cp
; cp
++)
382 if (n
&& cp
[-1] == '.') {
385 hp
= getdomaininfo(name
, (char *)NULL
);
390 if (n
== 0 && (cp
= __hostalias(name
))) {
392 printf("Aliased to \"%s\"\n", cp
);
393 _res
.options
|= RES_DEFNAMES
;
394 return (getdomaininfo(cp
, (char *)NULL
));
398 _res
.defdname_list
[nDomain
][0] != 0;
400 for (domain
= _res
.dnsrch_list
[nDomain
]; *domain
; domain
++) {
402 printf("Trying domain \"%s\"\n", *domain
);
403 hp
= getdomaininfo(name
, *domain
);
409 for (domain
= _res
.dnsrch
; *domain
; domain
++) {
411 printf("Trying domain \"%s\"\n", *domain
);
412 hp
= getdomaininfo(name
, *domain
);
417 if (h_errno
!= HOST_NOT_FOUND
||
418 (_res
.options
& RES_DNSRCH
) == 0)
421 printf("Trying null domain\n");
422 return (getdomaininfo(name
, (char *)NULL
));
426 getdomaininfo(name
, domain
)
429 return getinfo(name
, domain
, gettype
? gettype
: getdeftype
);
433 getinfo(name
, domain
, type
)
439 querybuf_t buf
, answer
;
440 int n
, n1
, i
, j
, nmx
, ancount
, nscount
, arcount
, qdcount
, buflen
;
441 char host
[2*MAXDNAME
+2];
444 (void)sprintf(host
, "%.*s", MAXDNAME
, name
);
446 (void)sprintf(host
, "%.*s.%.*s", MAXDNAME
, name
, MAXDNAME
, domain
);
448 n
= res_mkquery(QUERY
, host
, getclass
, type
, (char *)NULL
, 0, NULL
,
449 (char *)&buf
, sizeof(buf
));
451 if (_res
.options
& RES_DEBUG
)
452 printf("res_mkquery failed\n");
453 h_errno
= NO_RECOVERY
;
456 n
= res_send((char *)&buf
, n
, (char *)&answer
, sizeof(answer
));
458 if (_res
.options
& RES_DEBUG
)
459 printf("res_send failed\n");
463 eom
= (u8_t
*)&answer
+ n
;
464 return(printinfo(&answer
, eom
, T_ANY
, 0));
468 printinfo(answer
, eom
, filter
, isls
)
476 int nmx
, ancount
, nscount
, arcount
, qdcount
, buflen
;
479 * find first satisfactory answer
481 hp
= (HEADER
*) answer
;
482 ancount
= ntohs(hp
->ancount
);
483 qdcount
= ntohs(hp
->qdcount
);
484 nscount
= ntohs(hp
->nscount
);
485 arcount
= ntohs(hp
->arcount
);
486 if (_res
.options
& RES_DEBUG
|| (verbose
&& isls
== 0))
487 printf("rcode = %d (%s), ancount=%d\n",
489 DecodeError(hp
->rcode
),
491 if (hp
->rcode
!= NOERROR
|| (ancount
+nscount
+arcount
) == 0) {
494 /* Check if it's an authoritive answer */
496 h_errno
= HOST_NOT_FOUND
;
507 * Jeeves (TOPS-20 server) still does not
508 * support MX records. For the time being,
509 * we must accept FORMERRs as the same as
513 #endif /* OLDJEEVES */
515 /* TpB - set a return error for this case. NO_DATA */
517 return(0); /* was 1,but now indicates exception */
520 #endif /* OLDJEEVES */
523 h_errno
= NO_RECOVERY
;
530 buflen
= sizeof(hostbuf
);
531 cp
= (u8_t
*)answer
+ sizeof(HEADER
);
533 cp
+= dn_skipname((u8_t
*)cp
,(u8_t
*)eom
) + QFIXEDSZ
;
534 while (--qdcount
> 0)
535 cp
+= dn_skipname((u8_t
*)cp
,(u8_t
*)eom
) + QFIXEDSZ
;
539 if (verbose
&& isls
== 0)
540 printf("The following answer is not authoritative:\n");
541 while (--ancount
>= 0 && cp
&& cp
< eom
) {
542 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
544 * When we ask for address and there is a CNAME, it seems to return
545 * both the CNAME and the address. Since we trace down the CNAME
546 * chain ourselves, we don't really want to print the address at
549 if (cname
&& ! verbose
)
556 printf("For authoritative answers, see:\n");
557 while (--nscount
>= 0 && cp
&& cp
< eom
) {
558 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
562 printf("Additional information:\n");
563 while (--arcount
>= 0 && cp
&& cp
< eom
) {
564 cp
= pr_rr(cp
, (u8_t
*)answer
, stdout
, filter
);
570 static u8_t cnamebuf
[MAXDNAME
];
573 * Print resource record fields in human readable form.
576 pr_rr(cp
, msg
, file
, filter
)
581 int type
, class, dlen
, n
, c
, proto
, ttl
;
582 struct in_addr inaddr
;
584 struct protoent
*protop
;
585 struct servent
*servp
;
590 if ((cp
= pr_cdname(cp
, msg
, name
, sizeof(name
))) == NULL
)
591 return (NULL
); /* compression error */
593 type
= _getshort(cp
);
594 cp
+= sizeof(u_short
);
596 class = _getshort(cp
);
597 cp
+= sizeof(u_short
);
600 cp
+= sizeof(u_long
);
602 if (filter
== type
|| filter
== T_ANY
||
603 (filter
== T_A
&& (type
== T_PTR
|| type
== T_NS
)))
610 fprintf(file
,"%s\t%d%s\t%s",
611 name
, ttl
, pr_class(class), pr_type(type
));
613 fprintf(file
,"%s%s %s",name
, pr_class(class), pr_type(type
));
620 dlen
= _getshort(cp
);
621 cp
+= sizeof(u_short
);
624 * Print type specific data, if appropriate
630 bcopy((char *)cp
, (char *)&inaddr
, sizeof(inaddr
));
633 fprintf(file
,"%c%s", punc
,
636 } else if (dlen
== 7) {
638 fprintf(file
,"%c%s", punc
,
640 fprintf(file
,", protocol = %d", cp
[4]);
641 fprintf(file
,", port = %d",
642 (cp
[5] << 8) + cp
[6]);
650 if (dn_expand(msg
, msg
+ 512, cp
, cnamebuf
,
651 sizeof(cnamebuf
)-1) >= 0) {
652 strcat((char *) cnamebuf
, ".");
653 if (gettype
!= T_CNAME
&& gettype
!= T_ANY
)
665 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
667 fprintf(file
,"%c%s",punc
, name
);
673 fprintf(file
,"%c%.*s", punc
, n
, cp
);
678 fprintf(file
,"%c%.*s", punc
, n
, cp
);
684 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
686 fprintf(file
,"\t%s", name
);
687 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
689 fprintf(file
," %s", name
);
691 fprintf(file
,"(\n\t\t\t%d\t;serial (version)", _getlong(cp
));
692 cp
+= sizeof(u_long
);
694 fprintf(file
,"\n\t\t\t%d\t;refresh period", _getlong(cp
));
695 cp
+= sizeof(u_long
);
697 fprintf(file
,"\n\t\t\t%d\t;retry refresh this often", _getlong(cp
));
698 cp
+= sizeof(u_long
);
700 fprintf(file
,"\n\t\t\t%d\t;expiration period", _getlong(cp
));
701 cp
+= sizeof(u_long
);
703 fprintf(file
,"\n\t\t\t%d\t;minimum TTL\n\t\t\t)", _getlong(cp
));
704 cp
+= sizeof(u_long
);
710 fprintf(file
,"\t%d ",_getshort(cp
));
712 fprintf(file
," (pri=%d) by ",_getshort(cp
));
714 cp
+= sizeof(u_short
);
715 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
717 fprintf(file
, "%s", name
);
721 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
723 fprintf(file
,"%c%s",punc
, name
);
724 cp
= pr_cdname(cp
, msg
, name
, sizeof(name
));
726 fprintf(file
," %s", name
);
733 fprintf(file
,"%c%.*s", punc
, n
, cp
);
739 if (dlen
< sizeof(u_long
) + 1)
741 bcopy((char *)cp
, (char *)&inaddr
, sizeof(inaddr
));
742 cp
+= sizeof(u_long
);
744 protop
= getprotobynumber(proto
);
747 fprintf(file
,"%c%s %s", punc
,
748 inet_ntoa(inaddr
), protop
->p_name
);
750 fprintf(file
,"%c%s %d", punc
,
751 inet_ntoa(inaddr
), proto
);
754 while (cp
< cp1
+ dlen
) {
760 servp
= getservbyport (htons(n
),
764 fprintf(file
, " %s", servp
->s_name
);
766 fprintf(file
, " %d", n
);
775 fprintf(file
,"%c???", punc
);
778 if (cp
!= cp1
+ dlen
)
779 fprintf(file
,"packet size error (%#x != %#x)\n", cp
, cp1
+dlen
);
785 static char nbuf
[20];
788 * Return a string for the type
796 return(verbose
? "A" : "has address");
797 case T_NS
: /* authoritative server */
800 case T_MD
: /* mail destination */
802 case T_MF
: /* mail forwarder */
805 case T_CNAME
: /* connonical name */
806 return(verbose
? "CNAME" : "is a nickname for");
807 case T_SOA
: /* start of authority zone */
809 case T_MB
: /* mailbox domain name */
811 case T_MG
: /* mail group member */
813 case T_MX
: /* mail routing info */
814 return(verbose
? "MX" : "mail is handled");
816 case T_TXT
: /* TXT - descriptive info */
817 return(verbose
? "TXT" : "descriptive text");
819 case T_MR
: /* mail rename name */
821 case T_NULL
: /* null resource record */
823 case T_WKS
: /* well known service */
825 case T_PTR
: /* domain name pointer */
827 case T_HINFO
: /* host information */
829 case T_MINFO
: /* mailbox information */
831 case T_AXFR
: /* zone transfer */
833 case T_MAILB
: /* mail box */
835 case T_MAILA
: /* mail address */
837 case T_ANY
: /* matches any type */
840 return (sprintf(nbuf
, "%d", type
) == EOF
? NULL
: nbuf
);
845 * Return a mnemonic for class
853 case C_IN
: /* internet class */
854 return(verbose
? " IN" : "");
855 case C_CHAOS
: /* chaos class */
856 return(verbose
? " CHAOS" : "");
857 case C_HS
: /* Hesiod class */
858 return(verbose
? " HS" : "");
859 case C_ANY
: /* matches any class */
862 return (sprintf(nbuf
," %d", class) == EOF
? NULL
: nbuf
);
867 pr_cdname(cp
, msg
, name
, namelen
)
874 if ((n
= dn_expand(msg
, msg
+ 512, cp
, name
, namelen
- 2)) < 0)
876 if (name
[0] == '\0') {
883 char *resultcodes
[] = {
905 ******************************************************************************
909 * Requests the name server to do a zone transfer so we
910 * find out what hosts it knows about.
913 * SUCCESS the listing was successful.
914 * ERROR the server could not be contacted because
915 * a socket could not be obtained or an error
916 * occured while receiving, or the output file
917 * could not be opened.
919 ******************************************************************************
923 ListHosts(namePtr
, queryType
)
925 int queryType
; /* e.g. T_A */
927 querybuf_t buf
, answer
;
943 char dname
[2][NAME_LEN
];
944 u8_t domain
[NAME_LEN
];
945 /* names and addresses of name servers to try */
947 char nsname
[NUMNS
][NAME_LEN
];
948 int nshaveaddr
[NUMNS
];
951 char nsipaddr
[NUMNSADDR
][IPADDRSIZE
];
964 nwio_tcpconf_t tcpconf
;
969 * normalize to not have trailing dot. We do string compares below
970 * of info from name server, and it won't have trailing dots.
973 if (namePtr
[i
-1] == '.')
976 if (server_specified
) {
977 bcopy((char *)&_res
.nsaddr
, nsipaddr
[0], IPADDRSIZE
);
983 * First we have to find out where to look. This needs a NS query,
984 * possibly followed by looking up addresses for some of the names.
987 msglen
= res_mkquery(QUERY
, namePtr
, C_IN
, T_NS
,
988 (char *)0, 0, (struct rrec
*)0,
989 (char *)&buf
, sizeof(buf
));
992 printf("res_mkquery failed\n");
996 msglen
= res_send((char *)&buf
,msglen
,(char *)&answer
, sizeof(answer
));
999 printf("Unable to get to nameserver -- try again later\n");
1002 if (_res
.options
& RES_DEBUG
|| verbose
)
1003 printf("rcode = %d (%s), ancount=%d\n",
1005 DecodeError(answer
.qb1
.rcode
),
1006 ntohs(answer
.qb1
.ancount
));
1009 * Analyze response to our NS lookup
1012 nscount
= ntohs(answer
.qb1
.ancount
) +
1013 ntohs(answer
.qb1
.nscount
) +
1014 ntohs(answer
.qb1
.arcount
);
1017 if (answer
.qb1
.rcode
!= NOERROR
|| nscount
== 0) {
1018 switch (answer
.qb1
.rcode
) {
1020 /* Check if it's an authoritive answer */
1021 if (answer
.qb1
.aa
) {
1022 printf("No such domain\n");
1024 printf("Unable to get information about domain -- try again later.\n");
1028 printf("Unable to get information about that domain -- try again later.\n");
1031 printf("That domain exists, but seems to be a leaf node.\n");
1036 printf("Unrecoverable error looking up domain name.\n");
1042 cp
= answer
.qb2
+ sizeof(HEADER
);
1043 if (ntohs(answer
.qb1
.qdcount
) > 0)
1044 cp
+= dn_skipname(cp
, answer
.qb2
+ msglen
) + QFIXEDSZ
;
1050 * Look at response from NS lookup for NS and A records.
1053 for (;nscount
; nscount
--) {
1054 cp
+= dn_expand(answer
.qb2
, answer
.qb2
+ msglen
, cp
,
1055 domain
, sizeof(domain
));
1056 type
= _getshort(cp
);
1057 cp
+= sizeof(u_short
) + sizeof(u_short
) + sizeof(u_long
);
1058 dlen
= _getshort(cp
);
1059 cp
+= sizeof(u_short
);
1061 if (dn_expand(answer
.qb2
, answer
.qb2
+ msglen
, cp
,
1062 name
, sizeof(name
)) >= 0) {
1063 if (numns
< NUMNS
&& strcasecmp((char *)domain
, namePtr
) == 0) {
1064 for (i
= 0; i
< numns
; i
++)
1065 if (strcasecmp(nsname
[i
], (char *)name
) == 0)
1066 break; /* duplicate */
1068 strncpy(nsname
[numns
], (char *)name
, sizeof(name
));
1069 nshaveaddr
[numns
] = 0;
1075 else if (type
== T_A
) {
1076 if (numnsaddr
< NUMNSADDR
)
1077 for (i
= 0; i
< numns
; i
++) {
1078 if (strcasecmp(nsname
[i
], (char *)domain
) == 0) {
1080 bcopy((char *)cp
, nsipaddr
[numnsaddr
],IPADDRSIZE
);
1090 * Usually we'll get addresses for all the servers in the additional
1091 * info section. But in case we don't, look up their addresses.
1094 for (i
= 0; i
< numns
; i
++) {
1095 if (! nshaveaddr
[i
]) {
1096 register long **hptr
;
1099 hp
= gethostbyname(nsname
[i
]);
1101 for (hptr
= (long **)hp
->h_addr_list
; *hptr
; hptr
++)
1102 if (numnsaddr
< NUMNSADDR
) {
1103 bcopy((char *)*hptr
, nsipaddr
[numnsaddr
],IPADDRSIZE
);
1108 if (_res
.options
& RES_DEBUG
|| verbose
)
1109 printf("Found %d addresses for %s by extra query\n",
1110 numaddrs
, nsname
[i
]);
1113 if (_res
.options
& RES_DEBUG
|| verbose
)
1114 printf("Found %d addresses for %s\n",
1115 nshaveaddr
[i
], nsname
[i
]);
1119 * Now nsipaddr has numnsaddr addresses for name servers that
1120 * serve the requested domain. Now try to find one that will
1121 * accept a zone transfer.
1132 * Create a query packet for the requested domain name.
1135 msglen
= res_mkquery(QUERY
, namePtr
, getclass
, T_AXFR
,
1136 (char *)0, 0, (struct rrec
*)0,
1137 (char *) &buf
, sizeof(buf
));
1139 if (_res
.options
& RES_DEBUG
) {
1140 fprintf(stderr
, "ListHosts: Res_mkquery failed\n");
1146 * Set up a virtual circuit to the server.
1149 tcp_serv_name
= getenv("TCP_DEVICE");
1151 tcp_serv_name
= TCP_DEVICE
;
1152 for (;thisns
< numnsaddr
; thisns
++)
1154 tcp_fd
= open(tcp_serv_name
, O_RDWR
);
1157 fprintf(stderr
, "unable to open '%s': %s\n", tcp_serv_name
,
1162 tcpconf
.nwtc_flags
= NWTC_EXCL
| NWTC_LP_SEL
| NWTC_SET_RA
|
1164 tcpconf
.nwtc_remaddr
= *(ipaddr_t
*)nsipaddr
[thisns
];
1165 tcpconf
.nwtc_remport
= _res
.nsaddr
.sin_port
;
1166 result
= ioctl(tcp_fd
, NWIOSTCPCONF
, &tcpconf
);
1169 fprintf(stderr
, "tcp_ioc_setconf failed: %s\n",
1174 if (_res
.options
& RES_DEBUG
|| verbose
)
1175 printf("Trying %s\n", inet_ntoa(tcpconf
.nwtc_remaddr
));
1176 clopt
.nwtcl_flags
= 0;
1177 result
= ioctl(tcp_fd
, NWIOTCPCONN
, &clopt
);
1183 "Connection failed, trying next server: %s\n",
1187 if (thisns
>= numnsaddr
) {
1188 printf("No server for that domain responded\n");
1190 fprintf(stderr
, "Error from the last server was: %s\n",
1196 * Send length & message for zone transfer
1199 len
= htons(msglen
);
1201 result
= tcpip_writeall(tcp_fd
, (char *)&len
, sizeof(len
));
1202 if (result
!= sizeof(len
))
1204 fprintf(stderr
, "write failed: %s\n", strerror(errno
));
1208 result
= tcpip_writeall(tcp_fd
, (char *)&buf
, msglen
);
1209 if (result
!= msglen
)
1211 fprintf(stderr
, "write failed: %s\n",
1221 * Read the length of the response.
1225 amtToRead
= sizeof(u_short
);
1226 while(amtToRead
> 0)
1228 result
= read(tcp_fd
, (char *)cp
, amtToRead
);
1232 amtToRead
-= result
;
1235 error
= ERR_READING_LEN
;
1239 if ((len
= htons(*(u_short
*)&buf
)) == 0) {
1240 break; /* nothing left to read */
1244 * Read the response.
1249 while(amtToRead
> 0)
1251 result
= read(tcp_fd
, (char *)cp
, amtToRead
);
1255 amtToRead
-= result
;
1258 error
= ERR_READING_MSG
;
1264 if (i
!= NOERROR
|| ntohs(buf
.qb1
.ancount
) == 0) {
1265 if ((thisns
+1) < numnsaddr
&&
1266 (i
== SERVFAIL
|| i
== NOTIMP
|| i
== REFUSED
)) {
1267 if (_res
.options
& RES_DEBUG
|| verbose
)
1268 printf("Server failed, trying next server: %s\n",
1270 DecodeError(i
) : "Premature end of data");
1275 printf("Server failed: %s\n",
1276 i
!= NOERROR
? DecodeError(i
) : "Premature end of data");
1281 result
= printinfo(&buf
, cp
, queryType
, 1);
1283 error
= ERR_PRINTING
;
1287 cp
= buf
.qb2
+ sizeof(HEADER
);
1288 if (ntohs(buf
.qb1
.qdcount
) > 0)
1289 cp
+= dn_skipname(cp
, buf
.qb2
+ len
) + QFIXEDSZ
;
1292 cp
+= dn_skipname(cp
, (u_char
*)&buf
+ len
);
1293 if ((_getshort(cp
) == T_SOA
)) {
1294 dn_expand(buf
.qb2
, buf
.qb2
+ len
, nmp
, (u8_t
*)dname
[soacnt
],
1297 if (strcmp(dname
[0], dname
[1]) == 0)
1310 case ERR_READING_LEN
:
1314 fprintf(stderr
,"*** Error during listing of %s: %s\n",
1315 namePtr
, DecodeError(result
));
1318 case ERR_READING_MSG
:
1319 headerPtr
= (HEADER
*) &buf
;
1320 fprintf(stderr
,"ListHosts: error receiving zone transfer:\n");
1322 " result: %s, answers = %d, authority = %d, additional = %d\n",
1323 resultcodes
[headerPtr
->rcode
],
1324 ntohs(headerPtr
->ancount
),
1325 ntohs(headerPtr
->nscount
),
1326 ntohs(headerPtr
->arcount
));
1338 case NOERROR
: return("Success"); break;
1339 case FORMERR
: return("Format error"); break;
1340 case SERVFAIL
: return("Server failed"); break;
1341 case NXDOMAIN
: return("Non-existent domain"); break;
1342 case NOTIMP
: return("Not implemented"); break;
1343 case REFUSED
: return("Query refused"); break;
1344 case NOCHANGE
: return("No change"); break;
1345 case NO_INFO
: return("No information"); break;
1346 case ERROR
: return("Unspecified error"); break;
1347 case TIME_OUT
: return("Timed out"); break;
1348 case NONAUTH
: return("Non-authoritative answer"); break;
1351 return("BAD ERROR VALUE");
1354 static int tcpip_writeall(fd
, buf
, siz
)
1366 nbytes
= write(fd
, buf
, siz
);
1369 assert(siz
>= nbytes
);