diff options
Diffstat (limited to 'contrib/bind/bin/nslookup/list.c')
-rw-r--r-- | contrib/bind/bin/nslookup/list.c | 622 |
1 files changed, 622 insertions, 0 deletions
diff --git a/contrib/bind/bin/nslookup/list.c b/contrib/bind/bin/nslookup/list.c new file mode 100644 index 0000000..6d23e57 --- /dev/null +++ b/contrib/bind/bin/nslookup/list.c @@ -0,0 +1,622 @@ +/* + * Copyright (c) 1985, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static char sccsid[] = "@(#)list.c 5.23 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: list.c,v 8.13 1997/11/18 00:32:33 halley Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * list.c -- + * + * Routines to obtain info from name and finger servers. + * + * Adapted from 4.3BSD BIND ns_init.c and from finger.c. + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +#include "res.h" + +extern char *_res_resultcodes[]; /* res_debug.c */ +extern char *pager; + +typedef union { + HEADER qb1; + u_char qb2[PACKETSZ]; +} querybuf; + +extern HostInfo *defaultPtr; +extern HostInfo curHostInfo; +extern int curHostValid; +extern int queryType; +extern int queryClass; + +static int sockFD = -1; +int ListSubr(); + +/* + * During a listing to a file, hash marks are printed + * every HASH_SIZE records. + */ + +#define HASH_SIZE 50 + + +/* + ******************************************************************************* + * + * ListHosts -- + * ListHostsByType -- + * + * Requests the name server to do a zone transfer so we + * find out what hosts it knows about. + * + * For ListHosts, there are five types of output: + * - Internet addresses (default) + * - cpu type and operating system (-h option) + * - canonical and alias names (-a option) + * - well-known service names (-s option) + * - ALL records (-d option) + * ListHostsByType prints records of the default type or of a speicific + * type. + * + * To see all types of information sorted by name, do the following: + * ls -d domain.edu > file + * view file + * + * 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. + * + ******************************************************************************* + */ + +void +ListHostsByType(char *string, int putToFile) { + char *namePtr, name[NAME_LEN], option[NAME_LEN]; + int i, qtype, result; + + /* + * Parse the command line. It maybe of the form "ls -t domain" + * or "ls -t type domain". + */ + + i = sscanf(string, " ls -t %s %s", option, name); + if (putToFile && i == 2 && name[0] == '>') + i--; + if (i == 2) { + qtype = StringToType(option, -1, stderr); + if (qtype == -1) + return; + namePtr = name; + } else if (i == 1) { + namePtr = option; + qtype = queryType; + } else { + fprintf(stderr, "*** ls: invalid request %s\n", string); + return; + } + result = ListSubr(qtype, namePtr, putToFile ? string : NULL); + if (result != SUCCESS) + fprintf(stderr, "*** Can't list domain %s: %s\n", + namePtr, DecodeError(result)); +} + +void +ListHosts(char *string, int putToFile) { + char *namePtr, name[NAME_LEN], option[NAME_LEN]; + int i, qtype, result; + + /* + * Parse the command line. It maybe of the form "ls domain", + * "ls -X domain". + */ + i = sscanf(string, " ls %s %s", option, name); + if (putToFile && i == 2 && name[0] == '>') + i--; + if (i == 2) { + if (strcmp("-a", option) == 0) + qtype = T_CNAME; + else if (strcmp("-h", option) == 0) + qtype = T_HINFO; + else if (strcmp("-m", option) == 0) + qtype = T_MX; + else if (strcmp("-p", option) == 0) + qtype = T_PX; + else if (strcmp("-s", option) == 0) + qtype = T_WKS; + else if (strcmp("-d", option) == 0) + qtype = T_ANY; + else if (strcmp("-n", option) == 0) + qtype = T_NAPTR; + else + qtype = T_A; + namePtr = name; + } else if (i == 1) { + namePtr = option; + qtype = T_A; + } else { + fprintf(stderr, "*** ls: invalid request %s\n",string); + return; + } + result = ListSubr(qtype, namePtr, putToFile ? string : NULL); + if (result != SUCCESS) + fprintf(stderr, "*** Can't list domain %s: %s\n", + namePtr, DecodeError(result)); +} + +int +ListSubr(int qtype, char *domain, char *cmd) { + static u_char *answer = NULL; + static int answerLen = 0; + + ns_msg handle; + querybuf buf; + struct sockaddr_in sin; + HEADER *headerPtr; + int msglen, amtToRead, numRead, n, count, soacnt; + u_int len; + int numAnswers = 0; + int numRecords = 0; + u_char tmp[INT16SZ], *cp; + char soaname[2][NAME_LEN], file[NAME_LEN]; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error = NO_ERRORS; + + /* + * Create a query packet for the requested domain name. + */ + msglen = res_mkquery(QUERY, domain, queryClass, T_AXFR, + NULL, 0, 0, buf.qb2, sizeof buf); + if (msglen < 0) { + if (_res.options & RES_DEBUG) + fprintf(stderr, "*** ls: res_mkquery failed\n"); + return (ERROR); + } + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(nsport); + + /* + * Check to see if we have the address of the server or the + * address of a server who knows about this domain. + * + * For now, just use the first address in the list. XXX. + */ + + if (defaultPtr->addrList != NULL) + sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0]; + else + sin.sin_addr = *(struct in_addr *) + defaultPtr->servers[0]->addrList[0]; + + /* + * Set up a virtual circuit to the server. + */ + sockFD = socket(AF_INET, SOCK_STREAM, 0); + if (sockFD < 0) { + perror("ls: socket"); + return (ERROR); + } + if (connect(sockFD, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + int e; + + if (errno == ECONNREFUSED) + e = NO_RESPONSE; + else { + perror("ls: connect"); + e = ERROR; + } + (void) close(sockFD); + sockFD = -1; + return (e); + } + + /* + * Send length & message for zone transfer + */ + ns_put16(msglen, tmp); + if (write(sockFD, (char *)tmp, INT16SZ) != INT16SZ || + write(sockFD, (char *)buf.qb2, msglen) != msglen) { + perror("ls: write"); + (void) close(sockFD); + sockFD = -1; + return(ERROR); + } + + fprintf(stdout,"[%s]\n", (defaultPtr->addrList != NULL) + ? defaultPtr->name : defaultPtr->servers[0]->name); + + if (cmd == NULL) { + filePtr = stdout; + } else { + filePtr = OpenFile(cmd, file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", + file); + (void) close(sockFD); + sockFD = -1; + return (ERROR); + } + fprintf(filePtr, "> %s\n", cmd); + fprintf(filePtr, "[%s]\n", (defaultPtr->addrList != NULL) + ? defaultPtr->name : defaultPtr->servers[0]->name); + } + + soacnt = 0; + while (soacnt < 2) { + /* + * Read the length of the response. + */ + + cp = tmp; amtToRead = INT16SZ; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_LEN; + break; + } + + len = ns_get16(tmp); + if (len == 0) + break; /* nothing left to read */ + + /* + * If the server sent too much data to fit the existing + * buffer, allocate a new one. + */ + if (len > (u_int)answerLen) { + if (answerLen != 0) + free(answer); + answerLen = len; + answer = (u_char *)Malloc(answerLen); + } + + /* + * Read the response. + */ + amtToRead = len; cp = answer; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_MSG; + break; + } + + if (ns_initparse(answer, cp - answer, &handle) < 0) { + perror("ns_initparse"); + error = ERR_PRINTING; + break; + } + if (ns_msg_getflag(handle, ns_f_rcode) != ns_r_noerror || + ns_msg_count(handle, ns_s_an) == 0) { + /* Signalled protocol error, or empty message. */ + error = ERR_PRINTING; + break; + } + + for (;;) { + static char origin[NS_MAXDNAME], name_ctx[NS_MAXDNAME]; + const char *name; + char buf[2048]; /* XXX need to malloc/realloc. */ + ns_rr rr; + + if (ns_parserr(&handle, ns_s_an, -1, &rr)) { + if (errno != ENODEV) { + perror("ns_parserr"); + error = ERR_PRINTING; + } + break; + } + name = ns_rr_name(rr); + if (origin[0] == '\0' && name[0] != '\0') { + fprintf(filePtr, "$ORIGIN %s.\n", name); + strcpy(origin, name); + } + if (qtype == T_ANY || ns_rr_type(rr) == qtype) { + if (ns_sprintrr(&handle, &rr, name_ctx, origin, + buf, sizeof buf) < 0) { + perror("ns_sprintrr"); + error = ERR_PRINTING; + break; + } + strcpy(name_ctx, name); + numAnswers++; + fputs(buf, filePtr); + fputc('\n', filePtr); + } + if (ns_rr_type(rr) == T_SOA) { + strcpy(soaname[soacnt], name); + if (soacnt == 0) + soacnt = 1; + else if (strcasecmp(soaname[0], + soaname[1]) == 0) { + soacnt = 2; + } + } + } + if (error != NO_ERRORS) + break; + numAnswers++; + if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) { + fprintf(stdout, "#"); + fflush(stdout); + } + } + + if (cmd != NULL) + fprintf(stdout, "%sReceived %d answer%s (%d record%s).\n", + (numAnswers >= HASH_SIZE) ? "\n" : "", + numAnswers, (numAnswers != 1) ? "s" : "", + numRecords, (numRecords != 1) ? "s" : ""); + + (void) close(sockFD); + sockFD = -1; + if (cmd != NULL && filePtr != NULL) { + fclose(filePtr); + filePtr = NULL; + } + + switch (error) { + case NO_ERRORS: + return (SUCCESS); + + case ERR_READING_LEN: + return (ERROR); + + case ERR_PRINTING: + return (ERROR); + + case ERR_READING_MSG: + headerPtr = (HEADER *) answer; + fprintf(stderr,"*** ls: error receiving zone transfer:\n"); + fprintf(stderr, + " result: %s, answers = %d, authority = %d, additional = %d\n", + _res_resultcodes[headerPtr->rcode], + ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), + ntohs(headerPtr->arcount)); + return (ERROR); + default: + return (ERROR); + } +} + +/* + ******************************************************************************* + * + * ViewList -- + * + * A hack to view the output of the ls command in sorted + * order using more. + * + ******************************************************************************* + */ + +ViewList(string) + char *string; +{ + char file[PATH_MAX]; + char command[PATH_MAX]; + + sscanf(string, " view %s", file); + (void)sprintf(command, "grep \"^ \" %s | sort | %s", file, pager); + system(command); +} + +/* + ******************************************************************************* + * + * Finger -- + * + * Connects with the finger server for the current host + * to request info on the specified person (long form) + * who is on the system (short form). + * + * Results: + * SUCCESS the finger server was contacted. + * ERROR the server could not be contacted because + * a socket could not be obtained or connected + * to or the service could not be found. + * + ******************************************************************************* + */ + +Finger(string, putToFile) + char *string; + int putToFile; +{ + struct servent *sp; + struct sockaddr_in sin; + FILE *f; + int c; + int lastc; + char name[NAME_LEN]; + char file[NAME_LEN]; + + /* + * We need a valid current host info to get an inet address. + */ + if (!curHostValid) { + fprintf(stderr, "Finger: no current host defined.\n"); + return (ERROR); + } + + if (sscanf(string, " finger %s", name) == 1) { + if (putToFile && (name[0] == '>')) { + name[0] = '\0'; + } + } else { + name[0] = '\0'; + } + + sp = getservbyname("finger", "tcp"); + if (sp == 0) { + fprintf(stderr, "Finger: unknown service\n"); + return (ERROR); + } + + memset(&sin, 0, sizeof sin); + sin.sin_family = curHostInfo.addrType; + sin.sin_port = sp->s_port; + memcpy(&sin.sin_addr, curHostInfo.addrList[0], curHostInfo.addrLen); + + /* + * Set up a virtual circuit to the host. + */ + + sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0); + if (sockFD < 0) { + fflush(stdout); + perror("finger: socket"); + return (ERROR); + } + + if (connect(sockFD, (struct sockaddr *)&sin, sizeof (sin)) < 0) { + fflush(stdout); + perror("finger: connect"); + close(sockFD); + sockFD = -1; + return (ERROR); + } + + if (!putToFile) { + filePtr = stdout; + } else { + filePtr = OpenFile(string, file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", file); + close(sockFD); + sockFD = -1; + return(ERROR); + } + fprintf(filePtr,"> %s\n", string); + } + fprintf(filePtr, "[%s]\n", curHostInfo.name); + + if (name[0] != '\0') { + write(sockFD, "/W ", 3); + } + write(sockFD, name, strlen(name)); + write(sockFD, "\r\n", 2); + f = fdopen(sockFD, "r"); + lastc = '\n'; + while ((c = getc(f)) != EOF) { + switch (c) { + case 0210: + case 0211: + case 0212: + case 0214: + c -= 0200; + break; + case 0215: + c = '\n'; + break; + } + putc(lastc = c, filePtr); + } + if (lastc != '\n') { + putc('\n', filePtr); + } + putc('\n', filePtr); + + close(sockFD); + sockFD = -1; + + if (putToFile) { + fclose(filePtr); + filePtr = NULL; + } + return (SUCCESS); +} + +ListHost_close() +{ + if (sockFD != -1) { + (void) close(sockFD); + sockFD = -1; + } +} |