Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!bcm!soma!masscomp-request From: sob@cortex.neuro.bcm.tmc.edu (Stan Barber) Newsgroups: comp.sys.masscomp Subject: name server resolver library for MASSCOMP (part 2 of 7) Message-ID: <3470@soma.bcm.tmc.edu> Date: 5 Jul 88 00:59:43 GMT Sender: masscomp@soma.bcm.tmc.edu Lines: 1481 Approved: masscomp@soma.bcm.tmc.edu If you are on the internet and want your Masscomp to understand the Domain Name Service, here is the first step. This is the resolver library. This code is based on BIND 4.8 with all patches to date. Enjoy. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # tools/nslookup/Makefile # tools/nslookup/commands.l # tools/nslookup/debug.c # tools/nslookup/getinfo.c # This archive created: Mon Jul 4 20:27:53 1988 export PATH; PATH=/bin:/usr/bin:$PATH if test ! -d 'tools' then echo shar: "creating directory 'tools'" mkdir 'tools' fi echo shar: "entering directory 'tools'" cd 'tools' if test ! -d 'nslookup' then echo shar: "creating directory 'nslookup'" mkdir 'nslookup' fi echo shar: "entering directory 'nslookup'" cd 'nslookup' echo shar: "extracting 'Makefile'" '(1666 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^ X//' << \SHAR_EOF > 'Makefile' X# X# Copyright (c) 1987 Regents of the University of California. X# All rights reserved. X# X# Redistribution and use in source and binary forms are permitted X# provided that this notice is preserved and that due credit is given X# to the University of California at Berkeley. The name of the University X# may not be used to endorse or promote products derived from this X# software without specific prior written permission. This software X# is provided ``as is'' without express or implied warranty. X# X# from @(#)Makefile 5.16 (Berkeley) 2/20/88 X# XSHELL=/bin/sh XCFLAGS= -O -DSYS5 -DEXOS -I../../include -I/usr/include/NET-5000 XRES= ../../res/libresolv.a XLIBC= /lib/libc.a XLIBS= -ll ${RES} -lsocket XCSRCS= main.c getinfo.c debug.c send.c skip.c list.c subr.c XSRCS= ${CSRCS} commands.c XOBJS= main.o getinfo.o debug.o send.o skip.o list.o subr.o commands.o X X.SUFFIXES: .1 .0 X X.1.0: X ../manroff $*.1 > $*.0 X Xnslookup: ${OBJS} ${LIBC} X ${CC} -o $@ ${OBJS} ${LIBS} X Xclean: FRC X rm -f ${OBJS} core nslookup commands.c nslookup.0 lex.yy.c lex.yy.o X Xdepend: ${SRCS} FRC X ../mkdep ${CFLAGS} ${SRCS} X Xinstall: nslookup.0 FRC X ../installit -s -o bin -g bin -m 755 nslookup ${DESTDIR}/usr/local/nslookup X ../installit -c -o bin -g bin -m 444 nslookup.help ${DESTDIR}/usr/local/nslookup.help X ../installit -c -o bin -g bin -m 444 nslookup.0 ${DESTDIR}/usr/local/man/cat1/nslookup.0 X Xlint: ${SRCS} FRC X lint ${CFLAGS} ${SRCS} X Xtags: ${CSRCS} FRC X ctags ${CSRCS} X XFRC: X X# DO NOT DELETE THIS LINE -- mkdep uses it. X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. X Xmain.c: Xgetinfo.c: Xdebug.c: Xsend.c: Xskip.c: Xlist.c: Xsubr.c: Xcommands.c: X X# IF YOU PUT ANYTHING HERE IT WILL GO AWAY SHAR_EOF if test 1666 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 1666 characters)' fi fi echo shar: "extracting 'commands.l'" '(3974 characters)' if test -f 'commands.l' then echo shar: "will not over-write existing file 'commands.l'" else sed 's/^ X//' << \SHAR_EOF > 'commands.l' X%{ X/* X ******************************************************************************* X * X * Copyright (c) 1985 Regents of the University of California. X * All rights reserved. The Berkeley software License Agreement X * specifies the terms and conditions for redistribution. X * X * @(#)commands.l 5.6 (Berkeley) 11/20/87 X * X * commands.l X * X * Andrew Cherenson CS298-26 Fall 1985 X * X * Lex input file for the nslookup program command interpreter. X * When a sequence is recognized, the associated action X * routine is called. The action routine may need to X * parse the string for additional information. X * X * Recognized commands: (identifiers are shown in uppercase) X * X * server NAME - set default server to NAME, using default server X * lserver NAME - set default server to NAME, using initial server X * finger [NAME] - finger the optional NAME X * root - set default server to the root X * ls NAME - list the domain NAME X * view FILE - sorts and view the file with more X * set OPTION - set an option X * help - print help information X * ? - print help information X * opt[ions] - print options, current server, host X * NAME - print info about the host/domain NAME X * using default server. X * NAME1 NAME2 - as above, but use NAME2 as server X * X * X * yylex Results: X * 0 upon end-of-file. X * 1 after each command. X * X ******************************************************************************* X */ X X#include "res.h" Xextern char rootServerName[]; X X%} XWS [ \t] XLET [A-Za-z0-9.*] XNAME [A-Za-z0-9.*=_/-] X%% X^{WS}*server{WS}+{LET}{NAME}*{WS}*$ { X /* X * 0 == use current server to find X * the new one. X * 1 == use original server to find X * the new one. X */ X SetDefaultServer(yytext, 0); X return(1); X } X^{WS}*lserver{WS}+{LET}{NAME}*{WS}*$ { X SetDefaultServer(yytext, 1); X return(1); X } X^{WS}*root{WS}*$ { X SetDefaultServer(rootServerName, 1); X return(1); X } X^{WS}*finger({WS}+{LET}{NAME}*)?{WS}+>>?{WS}*{NAME}+{WS}*$ { X /* X * 2nd arg. X * 0 == output to stdout X * 1 == output to file X */ X Finger(yytext, 1); X return(1); X } X^{WS}*finger({WS}+{LET}{NAME}*)?{WS}*$ { X Finger(yytext, 0); X return(1); X } X^{WS}*view{WS}+{NAME}+{WS}*$ { X ViewList(yytext); X return(1); X } X^{WS}*ls{WS}+(("-a"|"-h"|"-m"|"-s"|"-d"){WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { X /* X * 2nd arg. X * 0 == output to stdout X * 1 == output to file X */ X ListHosts(yytext, 1); X return(1); X } X^{WS}*ls{WS}+(("-a"|"-h"|"-m"|"-s"|"-d"){WS}+)?{LET}{NAME}*{WS}*$ { X ListHosts(yytext, 0); X return(1); X } X^{WS}*set{WS}+{NAME}+{WS}*$ { X SetOption(yytext); X return(1); X } X^{WS}*help{WS}*$ { X extern void PrintHelp(); X X PrintHelp(); X return(1); X } X^{WS}*"?"{WS}*$ { X PrintHelp(); X return(1); X } X^{WS}*opt(ions)?{WS}*$ { X ShowOptions(TRUE); X return(1); X } X^{WS}*{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { X /* X * 0 == output to stdout X * 1 == output to file X */ X LookupHost(yytext, 1); X return(1); X } X^{WS}*{LET}{NAME}*{WS}*$ { X LookupHost(yytext, 0); X return(1); X } X^{WS}*{LET}{NAME}*{WS}+{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { X /* X * 0 == output to stdout X * 1 == output to file X */ X LookupHostWithServer(yytext, 1); X return(1); X } X^{WS}*{LET}{NAME}*{WS}+{LET}{NAME}*{WS}*$ { X LookupHostWithServer(yytext, 0); X return(1); X } X^{WS}*\n { X return(1); X } X^.*\n { X printf("Unrecognized command: %s", X yytext); X return(1); X } X\n { ; } X%% SHAR_EOF if test 3974 -ne "`wc -c < 'commands.l'`" then echo shar: "error transmitting 'commands.l'" '(should have been 3974 characters)' fi fi echo shar: "extracting 'debug.c'" '(8484 characters)' if test -f 'debug.c' then echo shar: "will not over-write existing file 'debug.c'" else sed 's/^ X//' << \SHAR_EOF > 'debug.c' X/* X * Copyright (c) 1985 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#)debug.c 5.11 (Berkeley) 4/5/88"; X#endif /* not lint */ X X/* X ******************************************************************************* X * X * debug.c -- X * X * Routines to print out packets received from a name server query. X * X * Modified version of 4.3BSD BIND res_debug.c 5.6 9/14/85 X * X ******************************************************************************* X */ X X#includeX#ifdef EXOS X#include X#endif X#include X#include X#include X#include X#include "res.h" X Xextern char ctime(); X X/* X * Imported from res_debug.c X */ Xextern char *_res_resultcodes[]; Xextern char *_res_opcodes[]; X X/* X * Used to highlight the start of a record when printing it. X */ X#define INDENT " -> " X X X X/* X * Print the contents of a query. X * This is intended to be primarily a debugging routine. X */ X XPrint_query(msg, eom, printHeader) X char *msg, *eom; X int printHeader; X{ X Fprint_query(msg, eom, printHeader,stdout); X} X XFprint_query(msg, eom, printHeader,file) X char *msg, *eom; X int printHeader; X FILE *file; X{ X register char *cp; X register HEADER *hp; X register int n; X short class; X short type; X X /* X * Print header fields. X */ X hp = (HEADER *)msg; X cp = msg + sizeof(HEADER); X if (printHeader || (_res.options & RES_DEBUG2)) { X fprintf(file," HEADER:\n"); X fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); X fprintf(file,", id = %d", ntohs(hp->id)); X fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); X fprintf(file,"\theader flags: "); X if (hp->qr) { X fprintf(file," response"); X } else { X fprintf(file," query"); X } X if (hp->aa) X fprintf(file,", auth. answer"); X if (hp->tc) X fprintf(file,", truncation"); X if (hp->rd) X fprintf(file,", want recursion"); X if (hp->ra) X fprintf(file,", recursion avail."); X if (hp->pr) X fprintf(file,", primary"); X fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount)); X fprintf(file,", answers = %d", ntohs(hp->ancount)); X fprintf(file,", auth. records = %d", ntohs(hp->nscount)); X fprintf(file,", additional = %d\n\n", ntohs(hp->arcount)); X } X X /* X * Print question records. X */ X if (n = ntohs(hp->qdcount)) { X fprintf(file," QUESTIONS:\n"); X while (--n >= 0) { X fprintf(file,"\t"); X cp = Print_cdname(cp, msg, eom, file); X if (cp == NULL) X return; X type = _getshort(cp); X cp += sizeof(u_short); X class = _getshort(cp); X cp += sizeof(u_short); X fprintf(file,", type = %s", p_type(type)); X fprintf(file,", class = %s\n", p_class(class)); X } X } X /* X * Print authoritative answer records X */ X if (n = ntohs(hp->ancount)) { X fprintf(file," ANSWERS:\n"); X while (--n >= 0) { X fprintf(file, INDENT); X cp = Print_rr(cp, msg, eom, file); X if (cp == NULL) X return; X } X } X /* X * print name server records X */ X if (n = ntohs(hp->nscount)) { X fprintf(file," AUTHORITY RECORDS:\n"); X while (--n >= 0) { X fprintf(file, INDENT); X cp = Print_rr(cp, msg, eom, file); X if (cp == NULL) X return; X } X } X /* X * print additional records X */ X if (n = ntohs(hp->arcount)) { X fprintf(file," ADDITIONAL RECORDS:\n"); X while (--n >= 0) { X fprintf(file, INDENT); X cp = Print_rr(cp, msg, eom, file); X if (cp == NULL) X return; X } X } X fprintf(file,"\n------------\n"); X X} X X Xchar * XPrint_cdname_sub(cp, msg, eom, file, format) X char *cp, *msg, *eom; X FILE *file; X int format; X{ X int n; X char name[MAXDNAME]; X extern char *strcpy(); X X if ((n = dn_expand(msg, eom, cp, name, sizeof(name))) < 0) X return (NULL); X if (name[0] == '\0') { X (void) strcpy(name, "(root)"); X } X if (format) { X fprintf(file, "%-30s", name); X } else { X fputs(name, file); X } X return (cp + n); X} X Xchar * XPrint_cdname(cp, msg, eom, file) X char *cp, *msg, *eom; X FILE *file; X{ X return(Print_cdname_sub(cp, msg, eom, file, 0)); X} X Xchar * XPrint_cdname2(cp, msg, eom, file) X char *cp, *msg, *eom; X FILE *file; X{ X return(Print_cdname_sub(cp, msg, eom, file, 1)); X} X X/* X * Print resource record fields in human readable form. X */ Xchar * XPrint_rr(cp, msg, eom, file) X char *cp, *msg, *eom; X FILE *file; X{ X int type, class, dlen, n, c; X long ttl; X struct in_addr inaddr; X char *cp1; X X if ((cp = Print_cdname(cp, msg, eom, file)) == NULL) { X fprintf(file, "(name truncated?)\n"); X return (NULL); /* compression error */ X } X X type = _getshort(cp); X cp += sizeof(u_short); X class = _getshort(cp); X cp += sizeof(u_short); X ttl = _getlong(cp); X cp += sizeof(u_long); X dlen = _getshort(cp); X cp += sizeof(u_short); X X if (_res.options & RES_DEBUG2) { X fprintf(file,"\n\ttype = %s, class = %s, ttl = %u, dlen = %d", X p_type(type), p_class(class), ttl, dlen); X fprintf(file,"\n"); X } X X cp1 = cp; X X /* X * Print type specific data, if appropriate X */ X switch (type) { X case T_A: X switch (class) { X case C_IN: X#ifdef SYS5 X (void)memcpy((char *)&inaddr, cp, sizeof(inaddr)); X#else X bcopy(cp, (char *)&inaddr, sizeof(inaddr)); X#endif X if (dlen == 4) { X fprintf(file,"\tinet address = %s\n", X inet_ntoa(inaddr)); X cp += dlen; X } else if (dlen == 7) { X fprintf(file,"\tinet address = %s", X inet_ntoa(inaddr)); X fprintf(file,", protocol = %d", cp[4]); X fprintf(file,", port = %d\n", X (cp[5] << 8) + cp[6]); X cp += dlen; X } X break; X default: X fprintf(file,"\taddress, class = %d, len = %d\n", X class, dlen); X } X break; X X case T_CNAME: X fprintf(file,"\tcanonical name = "); X goto doname; X X case T_MX: X fprintf(file,"\tpreference = %d",_getshort(cp)); X cp += sizeof(u_short); X fprintf(file,", mail exchanger = "); X goto doname; X X case T_MG: X fprintf(file,"\tmail group member = "); X goto doname; X case T_MB: X fprintf(file,"\tmail box = "); X goto doname; X case T_MR: X fprintf(file,"\tmailbox rename = "); X goto doname; X case T_NS: X fprintf(file,"\tnameserver = "); X goto doname; X case T_PTR: X fprintf(file,"\thost name = "); Xdoname: X cp = Print_cdname(cp, msg, eom, file); X fprintf(file,"\n"); X break; X X case T_HINFO: X if (n = *cp++) { X fprintf(file,"\tCPU=%.*s", n, cp); X cp += n; X } X if (n = *cp++) { X fprintf(file,"\tOS=%.*s\n", n, cp); X cp += n; X } X break; X X case T_SOA: X fprintf(file,"\torigin = "); X cp = Print_cdname(cp, msg, eom, file); X fprintf(file,"\n\tmail addr = "); X cp = Print_cdname(cp, msg, eom, file); X fprintf(file,"\n\tserial=%ld", _getlong(cp)); X cp += sizeof(u_long); X fprintf(file,", refresh=%ld", _getlong(cp)); X cp += sizeof(u_long); X fprintf(file,", retry=%ld", _getlong(cp)); X cp += sizeof(u_long); X fprintf(file,", expire=%ld", _getlong(cp)); X cp += sizeof(u_long); X fprintf(file,", min=%ld\n", _getlong(cp)); X cp += sizeof(u_long); X break; X X case T_MINFO: X fprintf(file,"\trequests = "); X cp = Print_cdname(cp, msg, eom, file); X fprintf(file,"\n\terrors = "); X cp = Print_cdname(cp, msg, eom, file); X break; X X case T_UINFO: X fprintf(file,"\t%s\n", cp); X cp += dlen; X break; X X case T_UID: X case T_GID: X if (dlen == 4) { X fprintf(file,"\t%cid %ld\n", type == T_UID ? 'u' : 'g', X _getlong(cp)); X cp += sizeof(int); X } else X fprintf(file,"\t%cid of length %ld?\n", X type == T_UID ? 'u' : 'g', dlen); X break; X X case T_WKS: X if (dlen < sizeof(u_long) + 1) X break; X#ifdef SYS5 X (void)memcpy((char *)&inaddr, cp, sizeof(inaddr)); X#else X bcopy(cp, (char *)&inaddr, sizeof(inaddr)); X#endif X cp += sizeof(u_long); X fprintf(file,"\tinet address = %s, protocol = %d\n\t", X inet_ntoa(inaddr), *cp++); X n = 0; X while (cp < cp1 + dlen) { X c = *cp++; X do { X if (c & 0200) X fprintf(file," %d", n); X c <<= 1; X } while (++n & 07); X } X putc('\n',file); X break; X X case T_NULL: X fprintf(file, "(type NULL, dlen %d)\n", dlen); X break; X X default: X fprintf(file,"\t???\n"); X cp += dlen; X } X if (cp != cp1 + dlen) X fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen); X return (cp); X} SHAR_EOF if test 8484 -ne "`wc -c < 'debug.c'`" then echo shar: "error transmitting 'debug.c'" '(should have been 8484 characters)' fi fi echo shar: "extracting 'getinfo.c'" '(19262 characters)' if test -f 'getinfo.c' then echo shar: "will not over-write existing file 'getinfo.c'" else sed 's/^ X//' << \SHAR_EOF > 'getinfo.c' X/* X * Copyright (c) 1985 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#)getinfo.c 5.16 (Berkeley) 3/11/88"; X#endif /* not lint */ X X/* X ******************************************************************************* X * X * getinfo.c -- X * X * Routines to create requests to name servers X * and interpret the answers. X * X * Adapted from 4.3BSD BIND gethostnamadr.c X * X ******************************************************************************* X */ X X#include X#ifdef EXOS X#include X#endif X#include X#include X#include X#include X#include X#include X#include "res.h" X Xextern char *_res_resultcodes[]; Xextern char *res_skip(); X X#define MAXALIASES 35 X#define MAXADDRS 35 X#define MAXDOMAINS 35 X#define MAXSERVERS 10 X Xstatic char *addr_list[MAXADDRS + 1]; X Xstatic char *host_aliases[MAXALIASES]; Xstatic int host_aliases_len[MAXALIASES]; Xstatic char hostbuf[BUFSIZ+1]; X Xtypedef struct { X char *name; X char *domain[MAXDOMAINS]; X int numDomains; X char *address[MAXADDRS]; X int numAddresses; X} ServerTable; X XServerTable server[MAXSERVERS]; X Xtypedef union { X HEADER qb1; X char qb2[PACKETSZ]; X} querybuf; X Xstatic union { X long al; X char ac; X} align; X X X/* X ******************************************************************************* X * X * GetAnswer -- X * X * Interprets an answer packet and retrieves the following X * information: X * X * Results: X * SUCCESS the info was retrieved. X * NO_INFO the packet did not contain an answer. X * NONAUTH non-authoritative information was found. X * ERROR the answer was malformed. X * Other errors returned in the packet header. X * X ******************************************************************************* X */ X Xstatic int XGetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isserver) X struct in_addr *nsAddrPtr; X char *msg; X int queryType; X int msglen; X int iquery; X register HostInfo *hostPtr; X int isserver; X{ X register HEADER *headerPtr; X register char *cp; X querybuf answer; X char *eom, *bp, **aliasPtr; X char **addrPtr; X char *namePtr; X char *dnamePtr; X int type, class; X int qdcount, ancount, arcount, nscount, buflen; X int haveanswer, getclass; X int numAliases = 0; X int numAddresses = 0; X int n, i, j; X int len; X int dlen; X int status; X int numServers; X int found; X X X /* X * If the hostPtr was used before, free up X * the calloc'd areas. X */ X FreeHostInfoPtr(hostPtr); X X status = SendRequest(nsAddrPtr, msg, msglen, (char *) &answer, X sizeof(answer), &n, !isserver); X X if (status != SUCCESS) { X if (_res.options & RES_DEBUG2) X printf("SendRequest failed\n"); X return (status); X } X eom = (char *) &answer + n; X X headerPtr = (HEADER *) &answer; X qdcount = ntohs(headerPtr->qdcount); X ancount = ntohs(headerPtr->ancount); X arcount = ntohs(headerPtr->arcount); X nscount = ntohs(headerPtr->nscount); X X if (headerPtr->rcode != NOERROR) { X if (_res.options & RES_DEBUG && !isserver) { X printf( X "Failed: %s, num. answers = %d, ns = %d, additional = %d\n", X _res_resultcodes[headerPtr->rcode], ancount, nscount, X arcount); X } X return (headerPtr->rcode); X } X X /* X * If there are no answer, n.s. or additional records X * then return with an error. X */ X if (ancount == 0 && nscount == 0 && arcount == 0) { X return (NO_INFO); X } X X X bp = hostbuf; X buflen = sizeof(hostbuf); X cp = (char *) &answer + sizeof(HEADER); X X /* X * For inverse queries, the desired information is returned X * in the question section. If there are no question records, X * return with an error. X * X */ X if (qdcount) { X if (iquery) { X if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) { X return (ERROR); X } X cp += n + QFIXEDSZ; X len = strlen(bp) + 1; X hostPtr->name = Calloc((unsigned)1, (unsigned)len); X#ifdef SYS5 X (void)memcpy(hostPtr->name, bp, len); X#else X bcopy(bp, hostPtr->name, len); X#endif X } else { X cp += dn_skipname(cp, eom) + QFIXEDSZ; X } X while (--qdcount > 0) { X cp += dn_skipname(cp, eom) + QFIXEDSZ; X } X } else if (iquery) { X return (NO_INFO); X } X X aliasPtr = host_aliases; X addrPtr = addr_list; X haveanswer = 0; X X /* X * Scan through the answer resource records. X * Answers for address query types are saved. X * Other query type answers are just printed. X */ X if (isserver == 0 && !headerPtr->aa && headerPtr->ancount) X printf("Non-authoritative answer:\n"); X while (--ancount >= 0 && cp < eom) { X if (queryType != T_A) { X if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) { X return(ERROR); X } X continue; X } else { X if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { X return(ERROR); X } X cp += n; X type = _getshort(cp); X cp += sizeof(u_short); X class = _getshort(cp); X cp += sizeof(u_short) + sizeof(u_long); X dlen = _getshort(cp); X cp += sizeof(u_short); X if (type == T_CNAME) { X /* X * Found an alias. X */ X cp += dlen; X if (aliasPtr >= &host_aliases[MAXALIASES-1]) X continue; X *aliasPtr++ = bp; X n = strlen(bp) + 1; X host_aliases_len[numAliases] = n; X numAliases++; X bp += n; X buflen -= n; X continue; X } else if (type == T_PTR) { X /* X * Found a "pointer" to the real name. X */ X if((n= dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0){ X cp += n; X continue; X } X cp += n; X len = strlen(bp) + 1; X hostPtr->name = Calloc((unsigned)1, (unsigned)len); X#ifdef SYS5 X (void)memcpy(hostPtr->name, bp, len); X#else X bcopy(bp, hostPtr->name, len); X#endif X haveanswer = 1; X break; X } else if (type != T_A) { X cp += dlen; X continue; X } X if (haveanswer) { X if (n != hostPtr->addrLen) { X cp += dlen; X continue; X } X if (class != getclass) { X cp += dlen; X continue; X } X } else { X hostPtr->addrLen = dlen; X getclass = class; X hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC; X if (!iquery) { X len = strlen(bp) + 1; X hostPtr->name = Calloc((unsigned)1, (unsigned)len); X#ifdef SYS5 X (void)memcpy(hostPtr->name, bp, len); X#else X bcopy(bp, hostPtr->name, len); X#endif X } X } X bp += (((u_long)bp) % sizeof(align)); X X if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) { X if (_res.options & RES_DEBUG) X printf("Size (%d) too big\n", dlen); X break; X } X#ifdef SYS5 X (void)memcpy(*addrPtr++ = bp, cp, dlen); X#else X bcopy(cp, *addrPtr++ = bp, dlen); X#endif X bp +=dlen; X cp += dlen; X numAddresses++; X haveanswer = 1; X } X } X X if (queryType == T_A && haveanswer) { X X /* X * Go through the alias and address lists and return them X * in the hostPtr variable. X */ X X if (numAliases > 0) { X hostPtr->aliases = (char **) Calloc((unsigned)1+numAliases, X sizeof(char *)); X for (i = 0; i < numAliases; i++) { X hostPtr->aliases[i] = Calloc((unsigned)1, (unsigned)host_aliases_len[i]); X#ifdef SYS5 X (void)memcpy( hostPtr->aliases[i], host_aliases[i], X#else X bcopy(host_aliases[i], hostPtr->aliases[i], X#endif X host_aliases_len[i]); X } X hostPtr->aliases[i] = NULL; X } X if (numAddresses > 0) { X hostPtr->addrList = (char **) Calloc((unsigned)1+numAddresses, X sizeof(char *)); X for (i = 0; i < numAddresses; i++) { X hostPtr->addrList[i] = Calloc((unsigned)1, (unsigned)hostPtr->addrLen); X#ifdef SYS5 X (void)memcpy( hostPtr->addrList[i], addr_list[i], X#else X bcopy(addr_list[i], hostPtr->addrList[i], X#endif X hostPtr->addrLen); X } X hostPtr->addrList[i] = NULL; X } X hostPtr->servers= NULL; X return (SUCCESS); X } X X /* X * At this point, for the T_A query type, only empty answers remain. X * For other query types, additional information might be found X * in the additional resource records part. X */ X X cp = res_skip((char *) &answer, 2, eom); X X numServers = 0; X while (--nscount >= 0 && cp < eom) { X /* X * Go through the NS records and retrieve the X * names of hosts that server the requested domain, X * their addresses and other domains they might serve. X */ X X if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { X return(ERROR); X } X cp += n; X len = strlen(bp) + 1; X dnamePtr = Calloc((unsigned)1, (unsigned)len); /* domain name */ X#ifdef SYS5 X (void)memcpy(dnamePtr, bp, len); X#else X bcopy(bp, dnamePtr, len); X#endif X type = _getshort(cp); X cp += sizeof(u_short); X class = _getshort(cp); X cp += sizeof(u_short) + sizeof(u_long); X dlen = _getshort(cp); X cp += sizeof(u_short); X X if (type != T_NS) { X cp += dlen; X } else { X if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { X return(ERROR); X } X cp += n; X len = strlen(bp) + 1; X namePtr = Calloc((unsigned)1, (unsigned)len); /* server host name */ X#ifdef SYS5 X (void)memcpy(namePtr, bp, len); X#else X bcopy(bp, namePtr, len); X#endif X /* X * Store the information keyed by the server host name. X */ X found = FALSE; X for (j = 0; j < numServers; j++) { X if (strcmp(namePtr, server[j].name) == 0) { X found = TRUE; X free(namePtr); X break; X } X } X if (found) { X server[j].numDomains++; X if (server[j].numDomains <= MAXDOMAINS) { X server[j].domain[server[j].numDomains-1] = dnamePtr; X } X } else { X if (numServers > MAXSERVERS) { X break; X } X numServers++; X server[numServers -1].name = namePtr; X server[numServers -1].domain[0] = dnamePtr; X server[numServers -1].numDomains = 1; X server[numServers -1].numAddresses = 0; X } X } X } X X if (!headerPtr->aa && (queryType != T_A) && arcount > 0) { X printf("Authoritative answers can be found from:\n"); X } X X /* X * Additional resource records contain addresses of X * servers. X */ X cp = res_skip((char *) &answer, 3, eom); X while (--arcount >= 0 && cp < eom) { X /* X * If we don't need to save the record, just print it. X */ X if (queryType != T_A) { X if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) { X return(ERROR); X } X continue; X X } else { X if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) X break; X cp += n; X type = _getshort(cp); X cp += sizeof(u_short); X class = _getshort(cp); X cp += sizeof(u_short) + sizeof(u_long); X dlen = _getshort(cp); X cp += sizeof(u_short); X X if (type != T_A) { X cp += dlen; X continue; X } else { X for (j = 0; j < numServers; j++) { X if (strcmp(bp, server[j].name) == 0) { X server[j].numAddresses++; X if (server[j].numAddresses <= MAXADDRS) { X server[j].address[server[j].numAddresses-1]=Calloc((unsigned)1,(unsigned)dlen); X#ifdef SYS5 X (void)memcpy(server[j].address[server[j].numAddresses-1], X cp, dlen); X#else X bcopy(cp,server[j].address[server[j].numAddresses-1], X dlen); X#endif X break; X } X } X } X cp += dlen; X } X } X } X X /* X * If we are returning name server info, transfer it to X * the hostPtr. X * X */ X if (numServers > 0) { X hostPtr->servers = (ServerInfo **) Calloc((unsigned)numServers+1, X sizeof(ServerInfo *)); X for (i = 0; i < numServers; i++) { X hostPtr->servers[i] = (ServerInfo *) Calloc((unsigned)1, sizeof(ServerInfo)); X hostPtr->servers[i]->name = server[i].name; X X X hostPtr->servers[i]->domains = (char **) X Calloc((unsigned)server[i].numDomains+1,sizeof(char *)); X for (j = 0; j < server[i].numDomains; j++) { X hostPtr->servers[i]->domains[j] = server[i].domain[j]; X } X hostPtr->servers[i]->domains[j] = NULL; X X X hostPtr->servers[i]->addrList = (char **) X Calloc((unsigned)server[i].numAddresses+1,sizeof(char *)); X for (j = 0; j < server[i].numAddresses; j++) { X hostPtr->servers[i]->addrList[j] = server[i].address[j]; X } X hostPtr->servers[i]->addrList[j] = NULL; X X } X hostPtr->servers[i] = NULL; X } X X X if (queryType != T_A) { X return(SUCCESS); X } else { X return(NONAUTH); X } X} X X/* X ******************************************************************************* X * X * GetHostInfo -- X * X * Retrieves host name, address and alias information X * for a domain. X * X * Results: X * ERROR - res_mkquery failed. X * + return values from GetAnswer() X * X ******************************************************************************* X */ X Xint XGetHostInfo(nsAddrPtr, queryClass, queryType, name, hostPtr, isserver) X struct in_addr *nsAddrPtr; X int queryClass; X int queryType; X char *name; X HostInfo *hostPtr; X int isserver; X{ X int n; X int result; X register char *cp, **domain; X querybuf buf; X extern char *Calloc(), *hostalias(); X X /* catch explicit addresses */ X if (isdigit(*name) && (queryType == T_A)) { X long ina; X X ina = inet_addr(name); X X if (ina == -1) X return(ERROR); X X hostPtr->name = Calloc((unsigned)strlen(name)+3,1); X (void)sprintf(hostPtr->name,"[%s]",name); X hostPtr->aliases = 0; X hostPtr->servers = 0; X hostPtr->addrType = AF_INET; X hostPtr->addrLen = 4; X hostPtr->addrList = (char **)Calloc((unsigned)2,sizeof(char *)); X hostPtr->addrList[0] = Calloc(sizeof(long),sizeof(char)); X#ifdef SYS5 X (void)memcpy(hostPtr->addrList[0],(char *)&ina,sizeof(ina)); X#else X bcopy((char *)&ina,hostPtr->addrList[0],sizeof(ina)); X#endif X hostPtr->addrList[1] = 0; X X return(SUCCESS); X } X X for (cp = name, n = 0; *cp; cp++) X if (*cp == '.') X n++; X if ((n && *--cp == '.') || X (isserver == 0 && (_res.options & RES_DEFNAMES) == 0)) { X int defflag = _res.options & RES_DEFNAMES; X X _res.options &= ~RES_DEFNAMES; X if (n && *cp == '.') X *cp = 0; X result = GetHostDomain(nsAddrPtr, queryClass, queryType, X name, (char *)NULL, hostPtr, isserver); X if (n && *cp == 0) X *cp = '.'; X if (defflag) X _res.options |= RES_DEFNAMES; X return (result); X } X if (n == 0 && (cp = hostalias(name))) X return (GetHostDomain(nsAddrPtr, queryClass, queryType, X cp, (char *)NULL, hostPtr, isserver)); X for (domain = _res.dnsrch; *domain; domain++) { X result = GetHostDomain(nsAddrPtr, queryClass, queryType, X name, *domain, hostPtr, isserver); X if ((result != NXDOMAIN && result != NO_INFO) || X (_res.options & RES_DNSRCH) == 0) X return (result); X } X if (n) X return (GetHostDomain(nsAddrPtr, queryClass, queryType, X name, (char *)NULL, hostPtr, isserver)); X return (result); X} X XGetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isserver) X struct in_addr *nsAddrPtr; X int queryClass; X int queryType; X char *name, *domain; X HostInfo *hostPtr; X int isserver; X{ X querybuf buf; X char nbuf[2*MAXDNAME+2]; X int n; X X if (domain) { X (void)sprintf(nbuf, "%.*s.%.*s", X MAXDNAME, name, MAXDNAME, domain); X name = nbuf; X } X n = res_mkquery(QUERY, name, queryClass, queryType, X (char *)0, 0, (char *)0, (char *) &buf, sizeof(buf)); X if (n < 0) { X if (_res.options & RES_DEBUG) { X printf("Res_mkquery failed\n"); X } X return (ERROR); X } X X n = GetAnswer(nsAddrPtr, queryType, (char *) &buf, n, 0, hostPtr, X isserver); X X /* X * GetAnswer didn't find a name, so set it to the specified one. X */ X if (n == NONAUTH) { X if (hostPtr->name == NULL) { X int len = strlen(name) + 1; X hostPtr->name = Calloc((unsigned)len, sizeof(char)); X#ifdef SYS5 X (void)memcpy(hostPtr->name, name, len); X#else X bcopy(name, hostPtr->name, len); X#endif X X } X } X return(n); X} X X X/* X ******************************************************************************* X * X * FindHostInfo -- X * X * Performs an inverse query to find the host name X * that corresponds to the given address. X * X * Results: X * ERROR - res_mkquery failed. X * + return values from GetAnswer() X * X ******************************************************************************* X */ X Xint XFindHostInfo(nsAddrPtr, address, len, hostPtr) X struct in_addr *nsAddrPtr; X struct in_addr *address; X int len; X HostInfo *hostPtr; X{ X int n; X querybuf buf; X X n = res_mkquery(IQUERY, (char *)0, C_IN, T_A, X (char *)address, len, (char *)0, (char *) &buf, sizeof(buf)); X if (n < 0) { X if (_res.options & RES_DEBUG) { X printf("Res_mkquery failed\n"); X } X return (ERROR); X } X return(GetAnswer(nsAddrPtr, T_A, (char *) &buf, n, 1, hostPtr, 1)); X} X X/* X ******************************************************************************* X * X * FreeHostInfoPtr -- X * X * Deallocates all the calloc'd areas for a HostInfo X * variable. X * X ******************************************************************************* X */ X Xvoid XFreeHostInfoPtr(hostPtr) X HostInfo *hostPtr; X{ X int i, j; X X if (hostPtr->name != NULL) { X free(hostPtr->name); X hostPtr->name = NULL; X } X X if (hostPtr->aliases != NULL) { X i = 0; X while (hostPtr->aliases[i] != NULL) { X free(hostPtr->aliases[i]); X i++; X } X free((char *)hostPtr->aliases); X hostPtr->aliases = NULL; X } X X if (hostPtr->addrList != NULL) { X i = 0; X while (hostPtr->addrList[i] != NULL) { X free(hostPtr->addrList[i]); X i++; X } X free((char *)hostPtr->addrList); X hostPtr->addrList = NULL; X } X X if (hostPtr->servers != NULL) { X i = 0; X while (hostPtr->servers[i] != NULL) { X X if (hostPtr->servers[i]->name != NULL) { X free(hostPtr->servers[i]->name); X } X X if (hostPtr->servers[i]->domains != NULL) { X j = 0; X while (hostPtr->servers[i]->domains[j] != NULL) { X free(hostPtr->servers[i]->domains[j]); X j++; X } X free((char *)hostPtr->servers[i]->domains); X } X X if (hostPtr->servers[i]->addrList != NULL) { X j = 0; X while (hostPtr->servers[i]->addrList[j] != NULL) { X free(hostPtr->servers[i]->addrList[j]); X j++; X } X free((char *)hostPtr->servers[i]->addrList); X } X free((char *)hostPtr->servers[i]); X i++; X } X free((char *)hostPtr->servers); X hostPtr->servers = NULL; X } X} X X/* X ******************************************************************************* X * X * GetHostList -- X * X * Performs a completion query when given an incomplete X * name. X * X * Still under development. X * X ******************************************************************************* X */ X X#if notdef X Xint XGetHostList(nsAddrPtr, queryType, name, defaultName, hostPtr) X struct in_addr *nsAddrPtr; X int queryType; X char *name, *defaultName; X HostInfo *hostPtr; X{ X int n; X querybuf buf; X X n = res_mkquery(CQUERYM, name, C_IN, T_A, defaultName, 0, (char *)0, X (char *) &buf, sizeof(buf)); X if (n < 0) { X if (_res.options & RES_DEBUG) X printf("Res_mkquery failed\n"); X return (ERROR); X } X return(GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, 1)); X} X#endif notdef SHAR_EOF if test 19262 -ne "`wc -c < 'getinfo.c'`" then echo shar: "error transmitting 'getinfo.c'" '(should have been 19262 characters)' fi fi exit 0 # End of shell archive