home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- char copyright[] =
- "@(#) Portions Copyright (c) 1985,1989\n\
- Regents of the University of California.\n\
- All rights reserved.\n";
- #endif /* not lint */
-
- /*
- *******************************************************************************
- *
- * main.c --
- *
- * Main routine and some action routines for the name server
- * lookup program.
- *
- * Andrew Cherenson
- * U.C. Berkeley Computer Science Div.
- * CS298-26, Fall 1985
- *
- *******************************************************************************
- */
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <netdb.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <stdio.h>
- #include <arpa/nameser.h>
- #include <arpa/inet.h>
- #include <resolv.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include "res.h"
-
- #ifdef ultrix
- #define nsaddr_list(i) ns_list[(i)].addr
- #else
- #define nsaddr_list(i) nsaddr_list[(i)]
- #endif
- /*
- * Default Internet address of the current host.
- */
-
- #if BSD < 43
- #define LOCALHOST "127.0.0.1"
- #endif
-
-
- /*
- * Name of a top-level name server. Can be changed with
- * the "set root" command.
- */
-
- #ifndef ROOT_SERVER
- #define ROOT_SERVER "ns.nic.ddn.mil."
- #endif
- char rootServerName[NAME_LEN] = ROOT_SERVER;
-
-
- /*
- * Import the state information from the resolver library.
- */
-
- extern struct state _res;
-
-
- /*
- * Info about the most recently queried host.
- */
-
- HostInfo curHostInfo;
-
-
- /*
- * Info about the default name server.
- */
-
- HostInfo *defaultPtr = NULL;
- char defaultServer[NAME_LEN];
- struct in_addr defaultAddr;
-
- int hasprinted = 0;
- int hasloaded = 0;
- int explicitserver = 0;
- char *vdomain;
- /*
- * Initial name server query type is Address.
- */
-
- int queryType = T_ANY;
- int queryClass = C_IN;
-
- /*
- * Stuff for Interrupt (control-C) signal handler.
- */
-
- FILE *filePtr = stdout;
-
- static void CvtAddrToPtr();
-
-
- /*
- *******************************************************************************
- *
- * main --
- *
- * Initializes the resolver library and determines the address
- * of the initial name server.
- *
- *******************************************************************************
- */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char *wantedHost = NULL;
- int result;
- int i;
- extern int h_errno;
-
- /*
- * Initialize the resolver library routines.
- */
-
- if (res_init() == -1) {
- fprintf(stderr,"*** Can't initialize resolver.\n");
- exit(1);
- }
-
- /*
- * Allocate space for the default server's host info and
- * find the server's address and name. If the resolver library
- * already has some addresses for a potential name server,
- * then use them. Otherwise, see if the current host has a server.
- * Command line arguments may override the choice of initial server.
- */
-
- defaultPtr = (HostInfo *) calloc(1, sizeof(HostInfo));
-
- ++argv; --argc; /* skip prog name */
-
-
- if (_res.nscount == 0) {
- LocalServer(defaultPtr);
- } else {
- for (i = 0; i < _res.nscount; i++) {
- if (_res.nsaddr_list(i).sin_addr.s_addr == INADDR_ANY) {
- LocalServer(defaultPtr);
- break;
- } else {
- result = GetHostInfoByAddr(&(_res.nsaddr_list(i).sin_addr),
- &(_res.nsaddr_list(i).sin_addr),
- defaultPtr);
- if (result != SUCCESS) {
- fprintf(stderr,
- "*** Can't find server name for address %s: %s\n",
- inet_ntoa(_res.nsaddr_list(i).sin_addr),
- DecodeError(result));
- } else {
- defaultAddr = _res.nsaddr_list(i).sin_addr;
- break;
- }
- }
- }
-
- /*
- * If we have exhausted the list, tell the user about the
- * command line argument to specify an address.
- */
-
- if (i == _res.nscount) {
- fprintf(stderr, "*** Default servers are not available\n");
- exit(1);
- }
-
- }
- strcpy(defaultServer, defaultPtr->name);
-
-
- #ifdef DEBUG
- #ifdef DEBUG2
- _res.options |= RES_DEBUG2;
- #endif
- _res.options |= RES_DEBUG;
- _res.retry = 2;
- #endif
-
- (void)InitTables();
- vdomain = _res.defdname;
-
- while (argc)
- {
- (void) DoCommand (*argv);
- ++argv; --argc;
- }
- if(!hasprinted)
- DoCommand("print");
-
- exit(0);
- }
-
-
- LocalServer(defaultPtr)
- HostInfo *defaultPtr;
- {
- char hostName[NAME_LEN];
- #if BSD < 43
- int result;
- #endif
-
- gethostname(hostName, sizeof(hostName));
-
- #if BSD < 43
- defaultAddr.s_addr = inet_addr(LOCALHOST);
- result = GetHostInfoByName(&defaultAddr, C_IN, T_A,
- hostName, defaultPtr, 1);
- if (result != SUCCESS) {
- fprintf(stderr,
- "*** Can't find initialize address for server %s: %s\n",
- defaultServer, DecodeError(result));
- exit(1);
- }
- #else
- defaultAddr.s_addr = htonl(INADDR_ANY);
- (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, "0.0.0.0", defaultPtr, 1);
- free(defaultPtr->name);
- defaultPtr->name = calloc(1, sizeof(hostName)+1);
- strcpy(defaultPtr->name, hostName);
- #endif
- }
-
-
- /*
- *******************************************************************************
- *
- * Usage --
- *
- * Lists the proper methods to run the program and exits.
- *
- *******************************************************************************
- */
-
- Usage()
- {
- fprintf(stderr, "Usage:\n");
- fprintf(stderr,
- " ns2tab [style={aliases,elm,group,hosts,lelm,nrgroup,pwupd}] [domain=...]\n");
- fprintf(stderr,
- " [load] [print]\n");
- exit(1);
- }
-
- /*
- *******************************************************************************
- *
- * IsAddr --
- *
- * Returns TRUE if the string looks like an Internet address.
- * A string with a trailing dot is not an address, even if it looks
- * like one.
- *
- * XXX doesn't treat 255.255.255.255 as an address.
- *
- *******************************************************************************
- */
-
- Boolean
- IsAddr(host, addrPtr)
- char *host;
- unsigned long *addrPtr; /* If return TRUE, contains IP address */
- {
- register char *cp;
- unsigned long addr;
-
- if (isdigit(host[0])) {
- /* Make sure it has only digits and dots. */
- for (cp = host; *cp; ++cp) {
- if (!isdigit(*cp) && *cp != '.')
- return FALSE;
- }
- /* If it has a trailing dot, don't treat it as an address. */
- if (*--cp != '.') {
- if ((addr = inet_addr(host)) != (unsigned long) -1) {
- *addrPtr = addr;
- return TRUE;
- #if 0
- } else {
- /* XXX Check for 255.255.255.255 case */
- #endif
- }
- }
- }
- return FALSE;
- }
-
-
- /*
- *******************************************************************************
- *
- * DOCommand --
- *
- * This routine is used to change the state information
- * that affect the lookups. The command format is
- * keyword[=value]
- * Most keywords can be abbreviated. Parsing is very simplistic--
- * A value must not be separated from its keyword by white space.
- *
- * Valid keywords: Meaning:
- * [no]d2 turn on/off extra debugging mode.
- * [no]debug turn on/off debugging mode.
- * [no]defname use/don't use default domain name.
- * [no]search use/don't use domain search list.
- * domain=NAME set default domain name to NAME.
- * [no]ignore ignore/don't ignore trunc. errors.
- * query=value set default query type to value,
- * value is one of the query types in RFC883
- * without the leading T_. (e.g., A, HINFO)
- * [no]recurse use/don't use recursive lookup.
- * retry=# set number of retries to #.
- * root=NAME change root server to NAME.
- * time=# set timeout length to #.
- * [no]vc use/don't use virtual circuit.
- * port TCP/UDP port to server.
- *
- * Deprecated:
- * [no]primary use/don't use primary server.
- *
- * Results:
- * SUCCESS the command was parsed correctly.
- * ERROR the command was not parsed correctly.
- *
- *******************************************************************************
- */
-
- int
- DoCommand(option)
- register char *option;
- {
- char type[NAME_LEN];
- char *ptr;
- int tmp;
-
- if (*option == 0) {
- fprintf(stderr, "*** Invalid flag\n");
- return(ERROR);
- } else {
- if (strncmp(option, "out", 3) == 0) {
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- if(filePtr != stdout) fclose(filePtr);
- if(!(filePtr = fopen(++ptr,"w")))
- filePtr = stdout;
- }
- } else if (strncmp(option, "ser", 3) == 0) {
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- SetDefaultServer(++ptr,1);
- explicitserver = 0;
- }
- } else if (strncmp(option, "expli", 3) == 0) {
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- SetDefaultServer(++ptr,1);
- explicitserver = 1;
- }
- } else if (strncmp(option, "d2", 2) == 0) { /* d2 (more debug) */
- _res.options |= (RES_DEBUG | RES_DEBUG2);
- } else if (strncmp(option, "nod2", 4) == 0) {
- _res.options &= ~RES_DEBUG2;
- printf("d2 mode disabled; still in debug mode\n");
- } else if (strncmp(option, "def", 3) == 0) { /* defname */
- _res.options |= RES_DEFNAMES;
- } else if (strncmp(option, "nodef", 5) == 0) {
- _res.options &= ~RES_DEFNAMES;
- } else if (strncmp(option, "domain", 3) == 0) { /* domain */
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- sscanf(++ptr, "%s", _res.defdname);
- res_re_init();
- vdomain = _res.defdname;
- hasloaded = 0;
- #if 0
- DoCommand("load");
- #endif
- }
- } else if (strncmp(option, "suffix", 3) == 0) { /* domain */
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- vdomain = ++ptr;
- }
- } else if (strncmp(option, "loa", 3) == 0) { /* load! */
- LoadHosts(_res.defdname);
- hasloaded = 1;
- } else if (strncmp(option, "prin", 4) == 0) { /* print! */
- if(!hasloaded)
- DoCommand("load");
- PrintStyle(filePtr);
- } else if (strncmp(option, "sty", 3) == 0) { /* style */
- ptr = strchr(option, '=');
- if (ptr != NULL)
- {
- SetStyle(++ptr);
- } /* if */
- } else if (strncmp(option, "deb", 1) == 0) { /* debug */
- _res.options |= RES_DEBUG;
- } else if (strncmp(option, "nodeb", 5) == 0) {
- _res.options &= ~(RES_DEBUG | RES_DEBUG2);
- } else if (strncmp(option, "ig", 2) == 0) { /* ignore */
- _res.options |= RES_IGNTC;
- } else if (strncmp(option, "noig", 4) == 0) {
- _res.options &= ~RES_IGNTC;
- #ifdef deprecated
- } else if (strncmp(option, "pri", 3) == 0) { /* primary */
- _res.options |= RES_PRIMARY;
- } else if (strncmp(option, "nopri", 5) == 0) {
- _res.options &= ~RES_PRIMARY;
- #endif
- } else if (strncmp(option, "cl", 2) == 0) { /* query class */
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- sscanf(++ptr, "%s", type);
- queryClass = StringToClass(type, queryClass);
- }
- } else if (strncmp(option, "rec", 3) == 0) { /* recurse */
- _res.options |= RES_RECURSE;
- } else if (strncmp(option, "norec", 5) == 0) {
- _res.options &= ~RES_RECURSE;
- } else if (strncmp(option, "ret", 3) == 0) { /* retry */
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- sscanf(++ptr, "%d", &tmp);
- if (tmp >= 0) {
- _res.retry = tmp;
- }
- }
- } else if (strncmp(option, "ro", 2) == 0) { /* root */
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- sscanf(++ptr, "%s", rootServerName);
- }
- } else if (strncmp(option, "sea", 3) == 0) { /* search list */
- _res.options |= RES_DNSRCH;
- } else if (strncmp(option, "nosea", 5) == 0) {
- _res.options &= ~RES_DNSRCH;
- } else if (strncmp(option, "srchl", 5) == 0) { /* domain search list */
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- res_dnsrch(++ptr);
- }
- } else if (strncmp(option, "ti", 2) == 0) { /* timeout */
- ptr = strchr(option, '=');
- if (ptr != NULL) {
- sscanf(++ptr, "%d", &tmp);
- if (tmp >= 0) {
- _res.retrans = tmp;
- }
- }
- } else {
- fprintf(stderr, "*** Invalid option: %s\n", option);
- return(ERROR);
- }
- }
- return(SUCCESS);
- }
-
- #ifndef MAXDFLSRCH
- #define MAXDFLSRCH 3
- #endif
- /*
- * Fake a reinitialization when the domain is changed.
- */
- res_re_init()
- {
- register char *cp, **pp;
- int n;
-
- /* find components of local domain that might be searched */
- pp = _res.dnsrch;
- *pp++ = _res.defdname;
- for (cp = _res.defdname, n = 0; *cp; cp++)
- if (*cp == '.')
- n++;
- cp = _res.defdname;
- for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; n--) {
- cp = strchr(cp, '.');
- *pp++ = ++cp;
- }
- *pp = 0;
- _res.options |= RES_INIT;
- }
-
- #define SRCHLIST_SEP '/'
-
- res_dnsrch(cp)
- register char *cp;
- {
- register char **pp;
- int n;
-
- (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
- if ((cp = strchr(_res.defdname, '\n')) != NULL)
- *cp = '\0';
- /*
- * Set search list to be blank-separated strings
- * on rest of line.
- */
- cp = _res.defdname;
- pp = _res.dnsrch;
- *pp++ = cp;
- for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
- if (*cp == SRCHLIST_SEP) {
- *cp = '\0';
- n = 1;
- } else if (n) {
- *pp++ = cp;
- n = 0;
- }
- }
- if ((cp = strchr(pp[-1], SRCHLIST_SEP)) != NULL) {
- *cp = '\0';
- }
- *pp = NULL;
- }
-
- #undef SRCHLIST_SEP
-
- /*
- *******************************************************************************
- *
- * CvtAddrToPtr --
- *
- * Convert a dotted-decimal Internet address into the standard
- * PTR format (reversed address with .in-arpa. suffix).
- *
- * Assumes the argument buffer is large enougth to hold the result.
- *
- *******************************************************************************
- */
-
- static void
- CvtAddrToPtr(name)
- char *name;
- {
- char *p;
- int ip[4];
- struct in_addr addr;
-
- if (IsAddr(name, &addr.s_addr)) {
- p = inet_ntoa(addr);
- if (sscanf(p, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4) {
- sprintf(name, "%d.%d.%d.%d.in-addr.arpa.",
- ip[3], ip[2], ip[1], ip[0]);
- }
- }
- }
-
- #if 0
- int
- SetServer(serv)
- char *serv;
- {
- int i;
- struct in_addr addr;
- struct hostent *hp;
-
- /*
- * Use an explicit name server. If the hostname lookup fails,
- * default to the server(s) in resolv.conf.
- */
-
- addr.s_addr = inet_addr(serv);
- if (addr.s_addr != (unsigned long)-1) {
- _res.nscount = 1;
- _res.nsaddr.sin_addr = addr;
- } else {
- hp = gethostbyname(serv);
- if (hp == NULL) {
- fprintf(stderr, "*** Can't find server address for '%s': ",
- serv);
- herror((char *)NULL);
- fputc('\n', stderr);
- return 0;
- }
- else
- {
- #if BSD < 43
- bcopy(hp->h_addr, (char *)&_res.nsaddr.sin_addr, hp->h_length);
- _res.nscount = 1;
- #else
- for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) {
- bcopy(hp->h_addr_list[i],
- (char *)&_res.nsaddr_list(i).sin_addr,
- hp->h_length);
- }
- _res.nscount = i;
- #endif
- }
- }
- return 1;
- }
- #endif
- /*
- *******************************************************************************
- *
- * SetDefaultServer --
- *
- * Changes the default name server to the one specified by
- * the first argument. The command "server name" uses the current
- * default server to lookup the info for "name". The command
- * "lserver name" uses the original server to lookup "name".
- *
- * Side effects:
- * This routine will cause a core dump if the allocation requests fail.
- *
- * Results:
- * SUCCESS The default server was changed successfully.
- * NONAUTH The server was changed but addresses of
- * other servers who know about the requested server
- * were returned.
- * Errors No info about the new server was found or
- * requests to the current server timed-out.
- *
- *******************************************************************************
- */
-
- int
- SetDefaultServer(string, local)
- char *string;
- Boolean local;
- {
- register HostInfo *newDefPtr;
- struct in_addr *servAddrPtr;
- struct in_addr addr;
- char newServer[NAME_LEN];
- int result;
- int i;
-
- strcpy(newServer,string);
- /*
- * Allocate space for a HostInfo variable for the new server. Don't
- * overwrite the old HostInfo struct because info about the new server
- * might not be found and we need to have valid default server info.
- */
-
- newDefPtr = (HostInfo *) calloc(1, sizeof(HostInfo));
-
-
- /*
- * A 'local' lookup uses the original server that the program was
- * initialized with.
- *
- * Check to see if we have the address of the server or the
- * address of a server who knows about this domain.
- * XXX For now, just use the first address in the list.
- */
-
- if (local) {
- servAddrPtr = &defaultAddr;
- } else if (defaultPtr->addrList != NULL) {
- servAddrPtr = (struct in_addr *) defaultPtr->addrList[0];
- } else {
- servAddrPtr = (struct in_addr *) defaultPtr->servers[0]->addrList[0];
- }
-
- result = ERROR;
- if (IsAddr(newServer, &addr.s_addr)) {
- result = GetHostInfoByAddr(servAddrPtr, &addr, newDefPtr);
- /* If we can't get the name, fall through... */
- }
- if (result != SUCCESS && result != NONAUTH) {
- result = GetHostInfoByName(servAddrPtr, C_IN, T_A,
- newServer, newDefPtr, 1);
- }
-
- if (result == SUCCESS || result == NONAUTH) {
- /*
- * Found info about the new server. Free the resources for
- * the old server.
- */
-
- FreeHostInfoPtr(defaultPtr);
- free((char *)defaultPtr);
- defaultPtr = newDefPtr;
- strcpy(defaultServer, defaultPtr->name);
- return(SUCCESS);
- } else {
- fprintf(stderr, "*** Can't find address for server %s: %s\n",
- newServer, DecodeError(result));
- free((char *)newDefPtr);
-
- return(result);
- }
- }
-