📄 host.c
字号:
* ListHosts -- * * Requests the name server to do a zone transfer so we * find out what hosts it knows about. * * Results: * SUCCESS the listing was successful. * ERROR the server could not be contacted because * a socket could not be obtained or an error * occured while receiving, or the output file * could not be opened. * ****************************************************************************** */static intListHosts(namePtr, queryType) char *namePtr; int queryType; /* e.g. T_A */{ querybuf_t buf, answer; dns_hdr_t *headerPtr; int msglen; int amtToRead; int numRead; int i; int numAnswers = 0; int result; int soacnt = 0; u_short len; int dlen; int type; int nscount; u8_t *cp, *nmp; u8_t name[NAME_LEN]; char dname[2][NAME_LEN]; u8_t domain[NAME_LEN];/* names and addresses of name servers to try */#define NUMNS 8 char nsname[NUMNS][NAME_LEN]; int nshaveaddr[NUMNS];#define IPADDRSIZE 4#define NUMNSADDR 16 char nsipaddr[NUMNSADDR][IPADDRSIZE]; int numns; int numnsaddr; int thisns; struct hostent *hp; enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } error = NO_ERRORS; char *tcp_serv_name; int tcp_fd; nwio_tcpconf_t tcpconf; nwio_tcpcl_t clopt; int terrno;/* * normalize to not have trailing dot. We do string compares below * of info from name server, and it won't have trailing dots. */ i = strlen(namePtr); if (namePtr[i-1] == '.') namePtr[i-1] = 0; if (server_specified) { bcopy((char *)&_res.nsaddr, nsipaddr[0], IPADDRSIZE); numnsaddr = 1; } else {/* * First we have to find out where to look. This needs a NS query, * possibly followed by looking up addresses for some of the names. */ msglen = res_mkquery(QUERY, namePtr, C_IN, T_NS, (char *)0, 0, (struct rrec *)0, (char *)&buf, sizeof(buf)); if (msglen < 0) { printf("res_mkquery failed\n"); return (ERROR); } msglen = res_send((char *)&buf,msglen,(char *)&answer, sizeof(answer)); if (msglen < 0) { printf("Unable to get to nameserver -- try again later\n"); return (ERROR); } if (_res.options & RES_DEBUG || verbose) printf("rcode = %d (%s), ancount=%d\n", answer.qb1.dh_flag2 & DHF_RCODE, DecodeError(answer.qb1.dh_flag2 & DHF_RCODE), ntohs(answer.qb1.dh_ancount));/* * Analyze response to our NS lookup */ nscount = ntohs(answer.qb1.dh_ancount) + ntohs(answer.qb1.dh_nscount) + ntohs(answer.qb1.dh_arcount); if (answer.qb1.dh_flag2 & DHF_RCODE != NOERROR || nscount == 0) { switch (answer.qb1.dh_flag2 & DHF_RCODE) { case NXDOMAIN: /* Check if it's an authoritive answer */ if (answer.qb1.dh_flag1 & DHF_AA) { printf("No such domain\n"); } else { printf("Unable to get information about domain -- try again later.\n"); } break; case SERVFAIL: printf("Unable to get information about that domain -- try again later.\n"); break; case NOERROR: printf("That domain exists, but seems to be a leaf node.\n"); break; case FORMERR: case NOTIMP: case REFUSED: printf("Unrecoverable error looking up domain name.\n"); break; } return (0); } cp = answer.qb2 + sizeof(dns_hdr_t); if (ntohs(answer.qb1.dh_qdcount) > 0) cp += dn_skipname(cp, answer.qb2 + msglen) + QFIXEDSZ; numns = 0; numnsaddr = 0;/* * Look at response from NS lookup for NS and A records. */ for (;nscount; nscount--) { cp += dn_expand(answer.qb2, answer.qb2 + msglen, cp, domain, sizeof(domain)); type = _getshort(cp); cp += sizeof(u_short) + sizeof(u_short) + sizeof(u_long); dlen = _getshort(cp); cp += sizeof(u_short); if (type == T_NS) { if (dn_expand(answer.qb2, answer.qb2 + msglen, cp, name, sizeof(name)) >= 0) { if (numns < NUMNS && strcasecmp((char *)domain, namePtr) == 0) { for (i = 0; i < numns; i++) if (strcasecmp(nsname[i], (char *)name) == 0) break; /* duplicate */ if (i >= numns) { strncpy(nsname[numns], (char *)name, sizeof(name)); nshaveaddr[numns] = 0; numns++; } } } } else if (type == T_A) { if (numnsaddr < NUMNSADDR) for (i = 0; i < numns; i++) { if (strcasecmp(nsname[i], (char *)domain) == 0) { nshaveaddr[i]++; bcopy((char *)cp, nsipaddr[numnsaddr],IPADDRSIZE); numnsaddr++; break; } } } cp += dlen; }/* * Usually we'll get addresses for all the servers in the additional * info section. But in case we don't, look up their addresses. */ for (i = 0; i < numns; i++) { if (! nshaveaddr[i]) { register long **hptr; int numaddrs = 0; hp = gethostbyname(nsname[i]); if (hp) { for (hptr = (long **)hp->h_addr_list; *hptr; hptr++) if (numnsaddr < NUMNSADDR) { bcopy((char *)*hptr, nsipaddr[numnsaddr],IPADDRSIZE); numnsaddr++; numaddrs++; } } if (_res.options & RES_DEBUG || verbose) printf("Found %d addresses for %s by extra query\n", numaddrs, nsname[i]); } else if (_res.options & RES_DEBUG || verbose) printf("Found %d addresses for %s\n", nshaveaddr[i], nsname[i]); } }/* * Now nsipaddr has numnsaddr addresses for name servers that * serve the requested domain. Now try to find one that will * accept a zone transfer. */ thisns = 0;again: numAnswers = 0; soacnt = 0; /* * Create a query packet for the requested domain name. * */ msglen = res_mkquery(QUERY, namePtr, getclass, T_AXFR, (char *)0, 0, (struct rrec *)0, (char *) &buf, sizeof(buf)); if (msglen < 0) { if (_res.options & RES_DEBUG) { fprintf(stderr, "ListHosts: Res_mkquery failed\n"); } return (ERROR); } /* * Set up a virtual circuit to the server. */ tcp_serv_name= getenv("TCP_DEVICE"); if (!tcp_serv_name) tcp_serv_name= TCP_DEVICE; for (;thisns < numnsaddr; thisns++) { tcp_fd= open(tcp_serv_name, O_RDWR); if (tcp_fd == -1) { fprintf(stderr, "unable to open '%s': %s\n", tcp_serv_name, strerror(errno)); return ERROR; } tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP; tcpconf.nwtc_remaddr= *(ipaddr_t *)nsipaddr[thisns]; tcpconf.nwtc_remport= HTONS(NAMESERVER_PORT); result= ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf); if (result == -1) { fprintf(stderr, "tcp_ioc_setconf failed: %s\n", strerror(errno)); close(tcp_fd); return ERROR; } if (_res.options & RES_DEBUG || verbose) printf("Trying %s\n", inet_ntoa(tcpconf.nwtc_remaddr)); clopt.nwtcl_flags= 0; result= ioctl(tcp_fd, NWIOTCPCONN, &clopt); if (result == 0) break; terrno= errno; if (verbose) fprintf(stderr, "Connection failed, trying next server: %s\n", strerror(errno)); close(tcp_fd); } if (thisns >= numnsaddr) { printf("No server for that domain responded\n"); if (!verbose) fprintf(stderr, "Error from the last server was: %s\n", strerror(terrno)); return(ERROR); } /* * Send length & message for zone transfer */ len = htons(msglen); result= tcpip_writeall(tcp_fd, (char *)&len, sizeof(len)); if (result != sizeof(len)) { fprintf(stderr, "write failed: %s\n", strerror(errno)); close(tcp_fd); return ERROR; } result= tcpip_writeall(tcp_fd, (char *)&buf, msglen); if (result != msglen) { fprintf(stderr, "write failed: %s\n", strerror(errno)); close(tcp_fd); return ERROR; } filePtr = stdout; while (1) { /* * Read the length of the response. */ cp = (u8_t *) &buf; amtToRead = sizeof(u_short); while(amtToRead > 0) { result = read(tcp_fd, (char *)cp, amtToRead); if (result <= 0) break; cp += result; amtToRead -= result; } if (amtToRead) { error = ERR_READING_LEN; break; } if ((len = htons(*(u_short *)&buf)) == 0) { break; /* nothing left to read */ } /* * Read the response. */ amtToRead = len; cp = (u8_t *) &buf; while(amtToRead > 0) { result = read(tcp_fd, (char *)cp, amtToRead); if (result<= 0) break; cp += result; amtToRead -= result; } if (amtToRead) { error = ERR_READING_MSG; break; } i = buf.qb1.dh_flag2 & DHF_RCODE; if (i != NOERROR || ntohs(buf.qb1.dh_ancount) == 0) { if ((thisns+1) < numnsaddr && (i == SERVFAIL || i == NOTIMP || i == REFUSED)) { if (_res.options & RES_DEBUG || verbose) printf("Server failed, trying next server: %s\n", i != NOERROR ? DecodeError(i) : "Premature end of data"); close(tcp_fd); thisns++; goto again; } printf("Server failed: %s\n", i != NOERROR ? DecodeError(i) : "Premature end of data"); break; } result = printinfo(&buf, cp, queryType, 1); if (! result) { error = ERR_PRINTING; break; } numAnswers++; cp = buf.qb2 + sizeof(dns_hdr_t); if (ntohs(buf.qb1.dh_qdcount) > 0) cp += dn_skipname(cp, buf.qb2 + len) + QFIXEDSZ; nmp = cp; cp += dn_skipname(cp, (u_char *)&buf + len); if ((_getshort(cp) == T_SOA)) { dn_expand(buf.qb2, buf.qb2 + len, nmp, (u8_t *)dname[soacnt], sizeof(dname[0])); if (soacnt) { if (strcmp(dname[0], dname[1]) == 0) break; } else soacnt++; } } close(tcp_fd); switch (error) { case NO_ERRORS: return (SUCCESS); case ERR_READING_LEN: return(ERROR); case ERR_PRINTING: fprintf(stderr,"*** Error during listing of %s: %s\n", namePtr, DecodeError(result)); return(result); case ERR_READING_MSG: headerPtr = (dns_hdr_t *) &buf; fprintf(stderr,"ListHosts: error receiving zone transfer:\n"); fprintf(stderr, " result: %s, answers = %d, authority = %d, additional = %d\n", resultcodes[headerPtr->dh_flag2 & DHF_RCODE], ntohs(headerPtr->dh_ancount), ntohs(headerPtr->dh_nscount), ntohs(headerPtr->dh_arcount)); return(ERROR); default: return(ERROR); }}static char *DecodeError(result) int result;{ switch(result) { case NOERROR: return("Success"); break; case FORMERR: return("Format error"); break; case SERVFAIL: return("Server failed"); break; case NXDOMAIN: return("Non-existent domain"); break; case NOTIMP: return("Not implemented"); break; case REFUSED: return("Query refused"); break; case NOCHANGE: return("No change"); break; case NO_INFO: return("No information"); break; case ERROR: return("Unspecified error"); break; case TIME_OUT: return("Timed out"); break; case NONAUTH: return("Non-authoritative answer"); break; default: break; } return("BAD ERROR VALUE"); }static int tcpip_writeall(fd, buf, siz)int fd;char *buf;unsigned siz;{ unsigned siz_org; int nbytes; siz_org= siz; while (siz) { nbytes= write(fd, buf, siz); if (nbytes == -1) return nbytes; assert(siz >= nbytes); buf += nbytes; siz -= nbytes; } return siz_org;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -