📄 list.c
字号:
/* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */#ifndef lintstatic char sccsid[] = "@(#)list.c 1.1 92/07/30 SMI from UCB 5.10 2/17/88";#endif /* not lint *//* ******************************************************************************* * * list.c -- * * Routines to obtain info from name and finger servers. * * Adapted from 4.3BSD BIND ns_init.c and from /usr/src/ucb/finger.c * ******************************************************************************* */#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <stdio.h>#include <strings.h>#include <ctype.h>#include <arpa/nameser.h>#include <resolv.h>#include "res.h"/* * Imported from res_debug.c */extern char *_res_resultcodes[];typedef union { HEADER qb1; char qb2[PACKETSZ];} querybuf;extern u_long inet_addr();extern HostInfo *defaultPtr;extern HostInfo curHostInfo;extern int curHostValid;/* * During a listing to a file, hash marks are printed * every HASH_SIZE records. */#define HASH_SIZE 50/* ******************************************************************************* * * ListHosts -- * * Requests the name server to do a zone transfer so we * find out what hosts it knows about. * * 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) * * To see all three types of information in sorted order, * do the following: * ls domain.edu > file * ls -a domain.edu >> file * ls -h domain.edu >> file * ls -s 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. * ******************************************************************************* */intListHosts(string, putToFile) char *string; int putToFile;{ querybuf buf; struct sockaddr_in sin; HEADER *headerPtr; int queryType; int msglen; int amtToRead; int numRead; int i; int numAnswers = 0; int result; int soacnt = 0; u_short len; char *cp, *nmp; char name[NAME_LEN]; char dname[2][NAME_LEN]; char option[NAME_LEN]; char file[NAME_LEN]; char *namePtr; enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING, } error = NO_ERRORS; /* * /* * Parse the command line. It maybe of the form "ls domain", * "ls -a domain" or "ls -h domain". */ i = sscanf(string, " ls %s %s", option, name); if (putToFile && i == 2 && name[0] == '>') { i--; } if (i == 2) { if (strcmp("-a", option) == 0) { queryType = T_CNAME; } else if (strcmp("-h", option) == 0) { queryType = T_HINFO; } else if (strcmp("-m", option) == 0) { queryType = T_MX; } else if (strcmp("-s", option) == 0) { queryType = T_WKS; } else if (strcmp("-d", option) == 0) { queryType = T_ANY; } else { queryType = T_A; } namePtr = name; } else if (i == 1) { namePtr = option; queryType = T_A; } else { fprintf(stderr, "ListHosts: invalid request %s\n",string); return(ERROR); } /* * Create a query packet for the requested domain name. * */ msglen = res_mkquery(QUERY, namePtr, C_IN, T_AXFR, (char *)0, 0, (char *)0, (char *) &buf, sizeof(buf)); if (msglen < 0) { if (_res.options & RES_DEBUG) { fprintf(stderr, "ListHosts: Res_mkquery failed\n"); } return (ERROR); } bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(NAMESERVER_PORT); /* * 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. */ 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. */ if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("ListHosts"); return(ERROR); } if (connect(sockFD, &sin, sizeof(sin)) < 0) { perror("ListHosts"); (void) close(sockFD); sockFD = -1; return(ERROR); } /* * Send length & message for zone transfer */ len = htons(msglen); if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) || write(sockFD, (char *) &buf, msglen) != msglen) { perror("ListHosts"); (void) close(sockFD); sockFD = -1; return(ERROR); } fprintf(stdout,"[%s]\n", (defaultPtr->addrList != NULL) ? defaultPtr->name : defaultPtr->servers[0]->name); if (!putToFile) { filePtr = stdout; } else { filePtr = OpenFile(string, 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", string); fprintf(filePtr,"[%s]\n", (defaultPtr->addrList != NULL) ? defaultPtr->name : defaultPtr->servers[0]->name); } fprintf(filePtr, "%-30s", "Host or domain name"); switch(queryType) { case T_ANY: fprintf(filePtr, " %-30s\n", "Resource record info"); break; case T_A: fprintf(filePtr, " %-30s\n", "Internet address"); break; case T_HINFO: fprintf(filePtr, " %-10s %s\n", "CPU", "OS"); break; case T_CNAME: fprintf(filePtr, " %-30s\n", "Alias"); break; case T_MX: fprintf(filePtr, " %3s %s\n", "Metric", "Host"); break; case T_WKS: fprintf(filePtr, " %-4s %s\n", "Protocol", "Services"); } while (1) { /* * Read the length of the response. */ cp = (char *) &buf; amtToRead = sizeof(u_short); while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){ cp += numRead; amtToRead -= numRead; } if (numRead <= 0) { error = ERR_READING_LEN; break; } if ((len = htons(*(u_short *)&buf)) == 0) { break; /* nothing left to read */ } /* * Read the response. */ amtToRead = len; cp = (char *) &buf; while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){ cp += numRead; amtToRead -= numRead; } if (numRead <= 0) { error = ERR_READING_MSG; break; } result = PrintListInfo(filePtr, (char *) &buf, cp, queryType); if (result != SUCCESS) { error = ERR_PRINTING; break; } numAnswers++; if (putToFile && ((numAnswers % HASH_SIZE) == 0)) { fprintf(stdout, "#"); fflush(stdout); } cp = buf.qb2 + sizeof(HEADER); if (ntohs(buf.qb1.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, dname[soacnt], sizeof(dname[0])); if (soacnt) { if (strcmp(dname[0], dname[1]) == 0) break; } else soacnt++; } } if (putToFile) { fprintf(stdout, "%sReceived %d record%s.\n", (numAnswers >= HASH_SIZE) ? "\n" : "", numAnswers, (numAnswers > 1) ? "s" : ""); } (void) close(sockFD); sockFD = -1; if (putToFile) { fclose(filePtr); filePtr = NULL; } 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 = (HEADER *) &buf; fprintf(stderr,"ListHosts: 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); }}/* ******************************************************************************* * * PrintListInfo -- * * Used by the ListInfo routine to print the answer * received from the name server. Only the desired * information is printed. * * Results: * SUCCESS the answer was printed without a problem. * NO_INFO the answer packet did not contain an answer. * ERROR the answer was malformed. * Misc. errors returned in the packet header. * ******************************************************************************* */#define NAME_FORMAT " %-30s"#define STRIP_DOMAIN(string) if((dot = index(string, '.')) != NULL) *dot = '\0'PrintListInfo(file, msg, eom, queryType) FILE *file; char *msg, *eom; int queryType;{ register char *cp; HEADER *headerPtr; int type, class, dlen, nameLen; u_long ttl; int n; struct in_addr inaddr; char name[NAME_LEN]; char name2[NAME_LEN]; char *dot; /* * Read the header fields. */ headerPtr = (HEADER *)msg; cp = msg + sizeof(HEADER); if (headerPtr->rcode != NOERROR) { return(headerPtr->rcode); } /* * We are looking for info from answer resource records.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -