wisner@ims.alaska.edu (Bill Wisner) (04/23/91)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 2)." # Contents: include/arpa/nameser.h named/gethostnamadr.c res_debug.c # res_query.c res_send.c # Wrapped by wisner@hayes on Mon Apr 22 18:43:58 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'include/arpa/nameser.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'include/arpa/nameser.h'\" else echo shar: Extracting \"'include/arpa/nameser.h'\" \(7620 characters\) sed "s/^X//" >'include/arpa/nameser.h' <<'END_OF_FILE' X/* X * Copyright (c) 1983, 1989 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: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: ``This product includes software X * developed by the University of California, Berkeley and its contributors'' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * @(#)nameser.h 5.24 (Berkeley) 6/1/90 X */ X X/* X * Define constants based on rfc883 X */ X#define PACKETSZ 512 /* maximum packet size */ X#define MAXDNAME 256 /* maximum domain name */ X#define MAXCDNAME 255 /* maximum compressed domain name */ X#define MAXLABEL 63 /* maximum length of domain label */ X /* Number of bytes of fixed size data in query structure */ X#define QFIXEDSZ 4 X /* number of bytes of fixed size data in resource record */ X#define RRFIXEDSZ 10 X X/* X * Internet nameserver port number X */ X#define NAMESERVER_PORT 53 X X/* X * Currently defined opcodes X */ X#define QUERY 0x0 /* standard query */ X#define IQUERY 0x1 /* inverse query */ X#define STATUS 0x2 /* nameserver status query */ X/*#define xxx 0x3 /* 0x3 reserved */ X /* non standard */ X#define UPDATEA 0x9 /* add resource record */ X#define UPDATED 0xa /* delete a specific resource record */ X#define UPDATEDA 0xb /* delete all nemed resource record */ X#define UPDATEM 0xc /* modify a specific resource record */ X#define UPDATEMA 0xd /* modify all named resource record */ X X#define ZONEINIT 0xe /* initial zone transfer */ X#define ZONEREF 0xf /* incremental zone referesh */ X X/* X * Currently defined response codes X */ X#define NOERROR 0 /* no error */ X#define FORMERR 1 /* format error */ X#define SERVFAIL 2 /* server failure */ X#define NXDOMAIN 3 /* non existent domain */ X#define NOTIMP 4 /* not implemented */ X#define REFUSED 5 /* query refused */ X /* non standard */ X#define NOCHANGE 0xf /* update failed to change db */ X X/* X * Type values for resources and queries X */ X#define T_A 1 /* host address */ X#define T_NS 2 /* authoritative server */ X#define T_MD 3 /* mail destination */ X#define T_MF 4 /* mail forwarder */ X#define T_CNAME 5 /* connonical name */ X#define T_SOA 6 /* start of authority zone */ X#define T_MB 7 /* mailbox domain name */ X#define T_MG 8 /* mail group member */ X#define T_MR 9 /* mail rename name */ X#define T_NULL 10 /* null resource record */ X#define T_WKS 11 /* well known service */ X#define T_PTR 12 /* domain name pointer */ X#define T_HINFO 13 /* host information */ X#define T_MINFO 14 /* mailbox information */ X#define T_MX 15 /* mail routing information */ X#define T_TXT 16 /* text strings */ X /* non standard */ X#define T_UINFO 100 /* user (finger) information */ X#define T_UID 101 /* user ID */ X#define T_GID 102 /* group ID */ X#define T_UNSPEC 103 /* Unspecified format (binary data) */ X /* Query type values which do not appear in resource records */ X#define T_AXFR 252 /* transfer zone of authority */ X#define T_MAILB 253 /* transfer mailbox records */ X#define T_MAILA 254 /* transfer mail agent records */ X#define T_ANY 255 /* wildcard match */ X X/* X * Values for class field X */ X X#define C_IN 1 /* the arpa internet */ X#define C_CHAOS 3 /* for chaos net at MIT */ X#define C_HS 4 /* for Hesiod name server at MIT */ X /* Query class values which do not appear in resource records */ X#define C_ANY 255 /* wildcard match */ X X/* X * Status return codes for T_UNSPEC conversion routines X */ X#define CONV_SUCCESS 0 X#define CONV_OVERFLOW -1 X#define CONV_BADFMT -2 X#define CONV_BADCKSUM -3 X#define CONV_BADBUFLEN -4 X X#ifndef BYTE_ORDER X#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */ X#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ X#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */ X X#if defined(vax) || defined(ns32000) || defined(sun386) || defined(MIPSEL) || \ X defined(BIT_ZERO_ON_RIGHT) X#define BYTE_ORDER LITTLE_ENDIAN X X#endif X#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ X defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ X defined(MIPSEB) || defined (BIT_ZERO_ON_LEFT) X#define BYTE_ORDER BIG_ENDIAN X#endif X#endif /* BYTE_ORDER */ X X#ifndef BYTE_ORDER X /* you must determine what the correct bit order is for your compiler */ X UNDEFINED_BIT_ORDER; X#endif X/* X * Structure for query header, the order of the fields is machine and X * compiler dependent, in our case, the bits within a byte are assignd X * least significant first, while the order of transmition is most X * significant first. This requires a somewhat confusing rearrangement. X */ X Xtypedef struct { X u_short id; /* query identification number */ X#if BYTE_ORDER == BIG_ENDIAN X /* fields in third byte */ X u_char qr:1; /* response flag */ X u_char opcode:4; /* purpose of message */ X u_char aa:1; /* authoritive answer */ X u_char tc:1; /* truncated message */ X u_char rd:1; /* recursion desired */ X /* fields in fourth byte */ X u_char ra:1; /* recursion available */ X u_char pr:1; /* primary server required (non standard) */ X u_char unused:2; /* unused bits */ X u_char rcode:4; /* response code */ X#endif X#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN X /* fields in third byte */ X u_char rd:1; /* recursion desired */ X u_char tc:1; /* truncated message */ X u_char aa:1; /* authoritive answer */ X u_char opcode:4; /* purpose of message */ X u_char qr:1; /* response flag */ X /* fields in fourth byte */ X u_char rcode:4; /* response code */ X u_char unused:2; /* unused bits */ X u_char pr:1; /* primary server required (non standard) */ X u_char ra:1; /* recursion available */ X#endif X /* remaining bytes */ X u_short qdcount; /* number of question entries */ X u_short ancount; /* number of answer entries */ X u_short nscount; /* number of authority entries */ X u_short arcount; /* number of resource entries */ X} HEADER; X X/* X * Defines for handling compressed domain names X */ X#define INDIR_MASK 0xc0 X X/* X * Structure for passing resource records around. X */ Xstruct rrec { X short r_zone; /* zone number */ X short r_class; /* class number */ X short r_type; /* type number */ X u_long r_ttl; /* time to live */ X int r_size; /* size of data area */ X char *r_data; /* pointer to data */ X}; X Xextern u_short _getshort(); Xextern u_long _getlong(); X X/* X * Inline versions of get/put short/long. X * Pointer is advanced; we assume that both arguments X * are lvalues and will already be in registers. X * cp MUST be u_char *. X */ X#define GETSHORT(s, cp) { \ X (s) = *(cp)++ << 8; \ X (s) |= *(cp)++; \ X} X X#define GETLONG(l, cp) { \ X (l) = *(cp)++ << 8; \ X (l) |= *(cp)++; (l) <<= 8; \ X (l) |= *(cp)++; (l) <<= 8; \ X (l) |= *(cp)++; \ X} X X X#define PUTSHORT(s, cp) { \ X *(cp)++ = (s) >> 8; \ X *(cp)++ = (s); \ X} X X/* X * Warning: PUTLONG destroys its first argument. X */ X#define PUTLONG(l, cp) { \ X (cp)[3] = l; \ X (cp)[2] = (l >>= 8); \ X (cp)[1] = (l >>= 8); \ X (cp)[0] = l >> 8; \ X (cp) += sizeof(u_long); \ X} END_OF_FILE if test 7620 -ne `wc -c <'include/arpa/nameser.h'`; then echo shar: \"'include/arpa/nameser.h'\" unpacked with wrong size! fi # end of 'include/arpa/nameser.h' fi if test -f 'named/gethostnamadr.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'named/gethostnamadr.c'\" else echo shar: Extracting \"'named/gethostnamadr.c'\" \(9872 characters\) sed "s/^X//" >'named/gethostnamadr.c' <<'END_OF_FILE' X/* X * Copyright (c) 1985, 1988 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 the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley. The name of the X * University may not be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)gethostnamadr.c 6.39.1 (Berkeley) 1/4/90"; X#endif /* LIBC_SCCS and not lint */ X X#include <sys/param.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <ctype.h> X#include <netdb.h> X#include <stdio.h> X#include <errno.h> X#include <arpa/inet.h> X#include <arpa/nameser.h> X#include <resolv.h> X X#define MAXALIASES 35 X#define MAXADDRS 35 X Xstatic char *h_addr_ptrs[MAXADDRS + 1]; X Xstatic struct hostent host; Xstatic char *host_aliases[MAXALIASES]; Xstatic char hostbuf[BUFSIZ+1]; Xstatic struct in_addr host_addr; Xstatic char HOSTDB[] = "/etc/hosts"; Xstatic FILE *hostf = NULL; Xstatic char hostaddr[MAXADDRS]; Xstatic char *host_addrs[2]; Xstatic int stayopen = 0; Xchar *strpbrk(); X X#if PACKETSZ > 1024 X#define MAXPACKET PACKETSZ X#else X#define MAXPACKET 1024 X#endif X Xtypedef union { X HEADER hdr; X u_char buf[MAXPACKET]; X} querybuf; X Xtypedef union { X long al; X char ac; X} align; X X Xint h_errno; Xextern errno; X Xstatic struct hostent * Xgetanswer(answer, anslen, iquery) X querybuf *answer; X int anslen; X int iquery; X{ X register HEADER *hp; X register u_char *cp; X register int n; X u_char *eom; X char *bp, **ap; X int type, class, buflen, ancount, qdcount; X int haveanswer, getclass = C_ANY; X char **hap; X X eom = answer->buf + anslen; X /* X * find first satisfactory answer X */ X hp = &answer->hdr; X ancount = ntohs(hp->ancount); X qdcount = ntohs(hp->qdcount); X bp = hostbuf; X buflen = sizeof(hostbuf); X cp = answer->buf + sizeof(HEADER); X if (qdcount) { X if (iquery) { X if ((n = dn_expand((char *)answer->buf, eom, X cp, bp, buflen)) < 0) { X h_errno = NO_RECOVERY; X return ((struct hostent *) NULL); X } X cp += n + QFIXEDSZ; X host.h_name = bp; X n = strlen(bp) + 1; X bp += n; X buflen -= n; X } else X cp += dn_skipname(cp, eom) + QFIXEDSZ; X while (--qdcount > 0) X cp += dn_skipname(cp, eom) + QFIXEDSZ; X } else if (iquery) { X if (hp->aa) X h_errno = HOST_NOT_FOUND; X else X h_errno = TRY_AGAIN; X return ((struct hostent *) NULL); X } X ap = host_aliases; X *ap = NULL; X host.h_aliases = host_aliases; X hap = h_addr_ptrs; X *hap = NULL; X#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ X host.h_addr_list = h_addr_ptrs; X#endif X haveanswer = 0; X while (--ancount >= 0 && cp < eom) { X if ((n = dn_expand((char *)answer->buf, 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 n = _getshort(cp); X cp += sizeof(u_short); X if (type == T_CNAME) { X cp += n; X if (ap >= &host_aliases[MAXALIASES-1]) X continue; X *ap++ = bp; X n = strlen(bp) + 1; X bp += n; X buflen -= n; X continue; X } X if (iquery && type == T_PTR) { X if ((n = dn_expand((char *)answer->buf, eom, X cp, bp, buflen)) < 0) { X cp += n; X continue; X } X cp += n; X host.h_name = bp; X return(&host); X } X if (iquery || type != T_A) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("unexpected answer type %d, size %d\n", X type, n); X#endif X cp += n; X continue; X } X if (haveanswer) { X if (n != host.h_length) { X cp += n; X continue; X } X if (class != getclass) { X cp += n; X continue; X } X } else { X host.h_length = n; X getclass = class; X host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; X if (!iquery) { X host.h_name = bp; X bp += strlen(bp) + 1; X } X } X X bp += sizeof(align) - ((u_long)bp % sizeof(align)); X X if (bp + n >= &hostbuf[sizeof(hostbuf)]) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("size (%d) too big\n", n); X#endif X break; X } X bcopy(cp, *hap++ = bp, n); X bp +=n; X cp += n; X haveanswer++; X } X if (haveanswer) { X *ap = NULL; X#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ X *hap = NULL; X#else X host.h_addr = h_addr_ptrs[0]; X#endif X return (&host); X } else { X h_errno = TRY_AGAIN; X return ((struct hostent *) NULL); X } X} X Xstruct hostent * Xgethostbyname(name) X char *name; X{ X querybuf buf; X register char *cp; X register int cc; X int n; X struct hostent *hp; X extern struct hostent *_gethtbyname(); X X /* X * disallow names consisting only of digits/dots, unless X * they end in a dot. X */ X if (isdigit(name[0])) X for (cp = name;; ++cp) { X if (!*cp) { X if (*--cp == '.') X break; X /* X * All-numeric, no dot at the end. X * Fake up a hostent as if we'd actually X * done a lookup. What if someone types X * 255.255.255.255? The test below will X * succeed spuriously... ??? X */ X if ((host_addr.s_addr = inet_addr(name)) == -1) { X h_errno = HOST_NOT_FOUND; X return((struct hostent *) NULL); X } X host.h_name = name; X host.h_aliases = host_aliases; X host_aliases[0] = NULL; X host.h_addrtype = AF_INET; X host.h_length = sizeof(u_long); X h_addr_ptrs[0] = (char *)&host_addr; X h_addr_ptrs[1] = (char *)0; X#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ X host.h_addr_list = h_addr_ptrs; X#else X host.h_addr = h_addr_ptrs[0]; X#endif X return (&host); X } X if (!isdigit(*cp) && *cp != '.') X break; X } X X if ((_res.options & RES_INIT) == 0 && res_init() == -1) X return((struct hostent *) NULL); X X cc = 0; X while (_res.order[cc] != RES_SERVICE_NONE) { X switch (_res.order[cc]) { X case RES_SERVICE_BIND: X if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("res_search failed\n"); X#endif X if (errno == ECONNREFUSED) X return (_gethtbyname(name)); X } else X return (getanswer(&buf, n, 0)); X break; X case RES_SERVICE_LOCAL: X hp = _gethtbyname(name); X if (hp) X return(hp); X } X cc++; X } X return((struct hostent *) NULL); X} X Xstruct hostent * Xgethostbyaddr(addr, len, type) X char *addr; X int len, type; X{ X int n; X querybuf buf; X register int cc; X register struct hostent *hp; X char qbuf[MAXDNAME]; X extern struct hostent *_gethtbyaddr(); X X if (type != AF_INET) X return ((struct hostent *) NULL); X X if ((_res.options & RES_INIT) == 0 && res_init() == -1) X return((struct hostent *) NULL); X X cc = 0; X while (_res.order[cc] != RES_SERVICE_NONE) { X switch (_res.order[cc]) { X case RES_SERVICE_BIND: X (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", X ((unsigned)addr[3] & 0xff), X ((unsigned)addr[2] & 0xff), X ((unsigned)addr[1] & 0xff), X ((unsigned)addr[0] & 0xff)); X n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); X if (n < 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("res_query failed\n"); X#endif X if (errno == ECONNREFUSED) X return (_gethtbyaddr(addr, len, type)); X break; X } X hp = getanswer(&buf, n, 1); X if (hp == NULL) X return ((struct hostent *) NULL); X hp->h_addrtype = type; X hp->h_length = len; X h_addr_ptrs[0] = (char *)&host_addr; X h_addr_ptrs[1] = (char *)0; X host_addr = *(struct in_addr *)addr; X#if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ X hp->h_addr = h_addr_ptrs[0]; X#endif X return(hp); X break; X case RES_SERVICE_LOCAL: X hp = _gethtbyaddr(addr, len, type); X if (hp) X return hp; X } X cc++; X } X return((struct hostent *)NULL); X} X X_sethtent(f) X int f; X{ X if (hostf == NULL) X hostf = fopen(HOSTDB, "r" ); X else X rewind(hostf); X stayopen |= f; X} X X_endhtent() X{ X if (hostf && !stayopen) { X (void) fclose(hostf); X hostf = NULL; X } X} X Xstruct hostent * X_gethtent() X{ X char *p; X register char *cp, **q; X X if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) X return (NULL); Xagain: X if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) X return (NULL); X if (*p == '#') X goto again; X cp = strpbrk(p, "#\n"); X if (cp == NULL) X goto again; X *cp = '\0'; X cp = strpbrk(p, " \t"); X if (cp == NULL) X goto again; X *cp++ = '\0'; X /* THIS STUFF IS INTERNET SPECIFIC */ X#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ X host.h_addr_list = host_addrs; X#endif X host.h_addr = hostaddr; X *((u_long *)host.h_addr) = inet_addr(p); X host.h_length = sizeof (u_long); X host.h_addrtype = AF_INET; X while (*cp == ' ' || *cp == '\t') X cp++; X host.h_name = cp; X q = host.h_aliases = host_aliases; X cp = strpbrk(cp, " \t"); X if (cp != NULL) X *cp++ = '\0'; X while (cp && *cp) { X if (*cp == ' ' || *cp == '\t') { X cp++; X continue; X } X if (q < &host_aliases[MAXALIASES - 1]) X *q++ = cp; X cp = strpbrk(cp, " \t"); X if (cp != NULL) X *cp++ = '\0'; X } X *q = NULL; X return (&host); X} X Xstruct hostent * X_gethtbyname(name) X char *name; X{ X register struct hostent *p; X register char **cp; X X _sethtent(0); X while (p = _gethtent()) { X if (strcasecmp(p->h_name, name) == 0) X break; X for (cp = p->h_aliases; *cp != 0; cp++) X if (strcasecmp(*cp, name) == 0) X goto found; X } Xfound: X _endhtent(); X return (p); X} X Xstruct hostent * X_gethtbyaddr(addr, len, type) X char *addr; X int len, type; X{ X register struct hostent *p; X X _sethtent(0); X while (p = _gethtent()) X if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) X break; X _endhtent(); X return (p); X} END_OF_FILE if test 9872 -ne `wc -c <'named/gethostnamadr.c'`; then echo shar: \"'named/gethostnamadr.c'\" unpacked with wrong size! fi # end of 'named/gethostnamadr.c' fi if test -f 'res_debug.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'res_debug.c'\" else echo shar: Extracting \"'res_debug.c'\" \(10432 characters\) sed "s/^X//" >'res_debug.c' <<'END_OF_FILE' X/*- X * Copyright (c) 1985, 1990 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted provided X * that: (1) source distributions retain this entire copyright notice and X * comment, and (2) distributions including binaries display the following X * acknowledgement: ``This product includes software developed by the X * University of California, Berkeley and its contributors'' in the X * documentation or other materials provided with the distribution and in X * all advertising materials mentioning features or use of this software. X * Neither the name of the University nor the names of its contributors may X * be used to endorse or promote products derived from this software without X * specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * @(#)res_debug.c 5.30 (Berkeley) 6/27/90 X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)res_debug.c 5.30 (Berkeley) 6/27/90"; X#endif /* LIBC_SCCS and not lint */ X X#include <sys/types.h> X#include <netinet/in.h> X#include <stdio.h> X#include <arpa/nameser.h> X Xextern char *p_cdname(), *p_rr(), *p_type(), *p_class(), *p_time(); Xextern char *inet_ntoa(); X Xchar *_res_opcodes[] = { X "QUERY", X "IQUERY", X "CQUERYM", X "CQUERYU", X "4", X "5", X "6", X "7", X "8", X "UPDATEA", X "UPDATED", X "UPDATEDA", X "UPDATEM", X "UPDATEMA", X "ZONEINIT", X "ZONEREF", X}; X Xchar *_res_resultcodes[] = { X "NOERROR", X "FORMERR", X "SERVFAIL", X "NXDOMAIN", X "NOTIMP", X "REFUSED", X "6", X "7", X "8", X "9", X "10", X "11", X "12", X "13", X "14", X "NOCHANGE", X}; X Xp_query(msg) X char *msg; X{ X fp_query(msg,stdout); X} X X/* X * Print the contents of a query. X * This is intended to be primarily a debugging routine. X */ Xfp_query(msg,file) X char *msg; X FILE *file; X{ X register char *cp; X register HEADER *hp; X register int n; X X /* X * Print header fields. X */ X hp = (HEADER *)msg; X cp = msg + sizeof(HEADER); 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," qr"); X if (hp->aa) X fprintf(file," aa"); X if (hp->tc) X fprintf(file," tc"); X if (hp->rd) X fprintf(file," rd"); X if (hp->ra) X fprintf(file," ra"); X if (hp->pr) X fprintf(file," pr"); X fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount)); X fprintf(file,", ancount = %d", ntohs(hp->ancount)); X fprintf(file,", nscount = %d", ntohs(hp->nscount)); X fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount)); 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 = p_cdname(cp, msg, file); X if (cp == NULL) X return; X fprintf(file,", type = %s", p_type(_getshort(cp))); X cp += sizeof(u_short); X fprintf(file,", class = %s\n\n", p_class(_getshort(cp))); X cp += sizeof(u_short); 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,"\t"); X cp = p_rr(cp, msg, 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,"NAME SERVERS:\n"); X while (--n >= 0) { X fprintf(file,"\t"); X cp = p_rr(cp, msg, 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,"\t"); X cp = p_rr(cp, msg, file); X if (cp == NULL) X return; X } X } X} X Xchar * Xp_cdname(cp, msg, file) X char *cp, *msg; X FILE *file; X{ X char name[MAXDNAME]; X int n; X X if ((n = dn_expand(msg, msg + 512, cp, name, sizeof(name))) < 0) X return (NULL); X if (name[0] == '\0') { X name[0] = '.'; X name[1] = '\0'; X } X fputs(name, file); X return (cp + n); X} X X/* X * Print resource record fields in human readable form. X */ Xchar * Xp_rr(cp, msg, file) X char *cp, *msg; X FILE *file; X{ X int type, class, dlen, n, c; X struct in_addr inaddr; X char *cp1, *cp2; X X if ((cp = p_cdname(cp, msg, file)) == NULL) X return (NULL); /* compression error */ X fprintf(file,"\n\ttype = %s", p_type(type = _getshort(cp))); X cp += sizeof(u_short); X fprintf(file,", class = %s", p_class(class = _getshort(cp))); X cp += sizeof(u_short); X fprintf(file,", ttl = %s", p_time(_getlong(cp))); X cp += sizeof(u_long); X fprintf(file,", dlen = %d\n", dlen = _getshort(cp)); X cp += sizeof(u_short); X cp1 = cp; X /* X * Print type specific data, if appropriate X */ X switch (type) { X case T_A: X switch (class) { X case C_IN: X case C_HS: X bcopy(cp, (char *)&inaddr, sizeof(inaddr)); X if (dlen == 4) { X fprintf(file,"\tinternet address = %s\n", X inet_ntoa(inaddr)); X cp += dlen; X } else if (dlen == 7) { X fprintf(file,"\tinternet 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 cp += dlen; X } X break; X case T_CNAME: X case T_MB: X case T_MG: X case T_MR: X case T_NS: X case T_PTR: X fprintf(file,"\tdomain name = "); X cp = p_cdname(cp, msg, file); X fprintf(file,"\n"); X break; X X case T_HINFO: X if (n = *cp++) { X fprintf(file,"\tCPU=%.*s\n", 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 = p_cdname(cp, msg, file); X fprintf(file,"\n\tmail addr = "); X cp = p_cdname(cp, msg, file); X fprintf(file,"\n\tserial = %ld", _getlong(cp)); X cp += sizeof(u_long); X fprintf(file,"\n\trefresh = %s", p_time(_getlong(cp))); X cp += sizeof(u_long); X fprintf(file,"\n\tretry = %s", p_time(_getlong(cp))); X cp += sizeof(u_long); X fprintf(file,"\n\texpire = %s", p_time(_getlong(cp))); X cp += sizeof(u_long); X fprintf(file,"\n\tmin = %s\n", p_time(_getlong(cp))); X cp += sizeof(u_long); X break; X X case T_MX: X fprintf(file,"\tpreference = %ld,",_getshort(cp)); X cp += sizeof(u_short); X fprintf(file," name = "); X cp = p_cdname(cp, msg, file); X break; X X case T_TXT: X (void) fputs("\t\"", file); X cp2 = cp1 + dlen; X while (cp < cp2) { X if (n = (unsigned char) *cp++) { X for (c = n; c > 0 && cp < cp2; c--) X if (*cp == '\n') { X (void) putc('\\', file); X (void) putc(*cp++, file); X } else X (void) putc(*cp++, file); X } X } X (void) fputs("\"\n", file); X break; X X case T_MINFO: X fprintf(file,"\trequests = "); X cp = p_cdname(cp, msg, file); X fprintf(file,"\n\terrors = "); X cp = p_cdname(cp, msg, 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%ld\n", _getlong(cp)); X cp += sizeof(int); X } X break; X X case T_WKS: X if (dlen < sizeof(u_long) + 1) X break; X bcopy(cp, (char *)&inaddr, sizeof(inaddr)); X cp += sizeof(u_long); X fprintf(file,"\tinternet 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#ifdef ALLOW_T_UNSPEC X case T_UNSPEC: X { X int NumBytes = 8; X char *DataPtr; X int i; X X if (dlen < NumBytes) NumBytes = dlen; X fprintf(file, "\tFirst %d bytes of hex data:", X NumBytes); X for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++) X fprintf(file, " %x", *DataPtr); X fputs("\n", file); X cp += dlen; X } X break; X#endif /* ALLOW_T_UNSPEC */ 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 cp = NULL; X } X fprintf(file,"\n"); X return (cp); X} X Xstatic char nbuf[40]; X X/* X * Return a string for the type X */ Xchar * Xp_type(type) X int type; X{ X switch (type) { X case T_A: X return("A"); X case T_NS: /* authoritative server */ X return("NS"); X case T_CNAME: /* canonical name */ X return("CNAME"); X case T_SOA: /* start of authority zone */ X return("SOA"); X case T_MB: /* mailbox domain name */ X return("MB"); X case T_MG: /* mail group member */ X return("MG"); X case T_MR: /* mail rename name */ X return("MR"); X case T_NULL: /* null resource record */ X return("NULL"); X case T_WKS: /* well known service */ X return("WKS"); X case T_PTR: /* domain name pointer */ X return("PTR"); X case T_HINFO: /* host information */ X return("HINFO"); X case T_MINFO: /* mailbox information */ X return("MINFO"); X case T_MX: /* mail routing info */ X return("MX"); X case T_TXT: /* text */ X return("TXT"); X case T_AXFR: /* zone transfer */ X return("AXFR"); X case T_MAILB: /* mail box */ X return("MAILB"); X case T_MAILA: /* mail address */ X return("MAILA"); X case T_ANY: /* matches any type */ X return("ANY"); X case T_UINFO: X return("UINFO"); X case T_UID: X return("UID"); X case T_GID: X return("GID"); X#ifdef ALLOW_T_UNSPEC X case T_UNSPEC: X return("UNSPEC"); X#endif /* ALLOW_T_UNSPEC */ X default: X (void)sprintf(nbuf, "%d", type); X return(nbuf); X } X} X X/* X * Return a mnemonic for class X */ Xchar * Xp_class(class) X int class; X{ X X switch (class) { X case C_IN: /* internet class */ X return("IN"); X case C_HS: /* hesiod class */ X return("HS"); X case C_ANY: /* matches any class */ X return("ANY"); X default: X (void)sprintf(nbuf, "%d", class); X return(nbuf); X } X} X X/* X * Return a mnemonic for a time to live X */ Xchar * Xp_time(value) X u_long value; X{ X int secs, mins, hours; X register char *p; X X if (value == 0) { X strcpy(nbuf, "0 secs"); X return(nbuf); X } X X secs = value % 60; X value /= 60; X mins = value % 60; X value /= 60; X hours = value % 24; X value /= 24; X X#define PLURALIZE(x) x, (x == 1) ? "" : "s" X p = nbuf; X if (value) { X (void)sprintf(p, "%d day%s", PLURALIZE(value)); X while (*++p); X } X if (hours) { X if (value) X *p++ = ' '; X (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); X while (*++p); X } X if (mins) { X if (value || hours) X *p++ = ' '; X (void)sprintf(p, "%d min%s", PLURALIZE(mins)); X while (*++p); X } X if (secs || ! (value || hours || mins)) { X if (value || hours || mins) X *p++ = ' '; X (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); X } X return(nbuf); X} END_OF_FILE if test 10432 -ne `wc -c <'res_debug.c'`; then echo shar: \"'res_debug.c'\" unpacked with wrong size! fi # end of 'res_debug.c' fi if test -f 'res_query.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'res_query.c'\" else echo shar: Extracting \"'res_query.c'\" \(7583 characters\) sed "s/^X//" >'res_query.c' <<'END_OF_FILE' X/* X * Copyright (c) 1988 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: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: ``This product includes software X * developed by the University of California, Berkeley and its contributors'' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)res_query.c 5.7 (Berkeley) 6/1/90"; X#endif /* LIBC_SCCS and not lint */ X X#include <sys/param.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <ctype.h> X#include <netdb.h> X#include <stdio.h> X#include <errno.h> X#include <string.h> X#include <arpa/inet.h> X#include <arpa/nameser.h> X#include <resolv.h> X X#if PACKETSZ > 1024 X#define MAXPACKET PACKETSZ X#else X#define MAXPACKET 1024 X#endif X Xextern int errno; Xint h_errno; X X/* X * Formulate a normal query, send, and await answer. X * Returned answer is placed in supplied buffer "answer". X * Perform preliminary check of answer, returning success only X * if no error is indicated and the answer count is nonzero. X * Return the size of the response on success, -1 on error. X * Error number is left in h_errno. X * Caller must parse answer and determine whether it answers the question. X */ Xres_query(name, class, type, answer, anslen) X char *name; /* domain name */ X int class, type; /* class and type of query */ X u_char *answer; /* buffer to put answer */ X int anslen; /* size of answer buffer */ X{ X char buf[MAXPACKET]; X HEADER *hp; X int n; X X if ((_res.options & RES_INIT) == 0 && res_init() == -1) X return (-1); X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("res_query(%s, %d, %d)\n", name, class, type); X#endif X n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL, X buf, sizeof(buf)); X X if (n <= 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("res_query: mkquery failed\n"); X#endif X h_errno = NO_RECOVERY; X return (n); X } X n = res_send(buf, n, answer, anslen); X if (n < 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("res_query: send error\n"); X#endif X h_errno = TRY_AGAIN; X return(n); X } X X hp = (HEADER *) answer; X if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("rcode = %d, ancount=%d\n", hp->rcode, X ntohs(hp->ancount)); X#endif X switch (hp->rcode) { X case NXDOMAIN: X h_errno = HOST_NOT_FOUND; X break; X case SERVFAIL: X h_errno = TRY_AGAIN; X break; X case NOERROR: X h_errno = NO_DATA; X break; X case FORMERR: X case NOTIMP: X case REFUSED: X default: X h_errno = NO_RECOVERY; X break; X } X return (-1); X } X return(n); X} X X/* X * Formulate a normal query, send, and retrieve answer in supplied buffer. X * Return the size of the response on success, -1 on error. X * If enabled, implement search rules until answer or unrecoverable failure X * is detected. Error number is left in h_errno. X * Only useful for queries in the same name hierarchy as the local host X * (not, for example, for host address-to-name lookups in domain in-addr.arpa). X */ Xres_search(name, class, type, answer, anslen) X char *name; /* domain name */ X int class, type; /* class and type of query */ X u_char *answer; /* buffer to put answer */ X int anslen; /* size of answer */ X{ X register char *cp, **domain; X int n, ret, got_nodata = 0; X char *hostalias(); X X if ((_res.options & RES_INIT) == 0 && res_init() == -1) X return (-1); X X errno = 0; X h_errno = HOST_NOT_FOUND; /* default, if we never query */ X for (cp = name, n = 0; *cp; cp++) X if (*cp == '.') X n++; X if (n == 0 && (cp = hostalias(name))) X return (res_query(cp, class, type, answer, anslen)); X X /* X * We do at least one level of search if X * - there is no dot and RES_DEFNAME is set, or X * - there is at least one dot, there is no trailing dot, X * and RES_DNSRCH is set. X */ X if ((n == 0 && _res.options & RES_DEFNAMES) || X (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH)) X for (domain = _res.dnsrch; *domain; domain++) { X ret = res_querydomain(name, *domain, class, type, X answer, anslen); X if (ret > 0) X return (ret); X /* X * If no server present, give up. X * If name isn't found in this domain, X * keep trying higher domains in the search list X * (if that's enabled). X * On a NO_DATA error, keep trying, otherwise X * a wildcard entry of another type could keep us X * from finding this entry higher in the domain. X * If we get some other error (negative answer or X * server failure), then stop searching up, X * but try the input name below in case it's fully-qualified. X */ X if (errno == ECONNREFUSED) { X h_errno = TRY_AGAIN; X return (-1); X } X if (h_errno == NO_DATA) X got_nodata++; X if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) || X (_res.options & RES_DNSRCH) == 0) X break; X } X /* X * If the search/default failed, try the name as fully-qualified, X * but only if it contained at least one dot (even trailing). X * This is purely a heuristic; we assume that any reasonable query X * about a top-level domain (for servers, SOA, etc) will not use X * res_search. X */ X if (n && (ret = res_querydomain(name, (char *)NULL, class, type, X answer, anslen)) > 0) X return (ret); X if (got_nodata) X h_errno = NO_DATA; X return (-1); X} X X/* X * Perform a call on res_query on the concatenation of name and domain, X * removing a trailing dot from name if domain is NULL. X */ Xres_querydomain(name, domain, class, type, answer, anslen) X char *name, *domain; X int class, type; /* class and type of query */ X u_char *answer; /* buffer to put answer */ X int anslen; /* size of answer */ X{ X char nbuf[2*MAXDNAME+2]; X char *longname = nbuf; X int n; X X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("res_querydomain(%s, %s, %d, %d)\n", X name, domain, class, type); X#endif X if (domain == NULL) { X /* X * Check for trailing '.'; X * copy without '.' if present. X */ X n = strlen(name) - 1; X if (name[n] == '.' && n < sizeof(nbuf) - 1) { X bcopy(name, nbuf, n); X nbuf[n] = '\0'; X } else X longname = name; X } else X (void)sprintf(nbuf, "%.*s.%.*s", X MAXDNAME, name, MAXDNAME, domain); X X return (res_query(longname, class, type, answer, anslen)); X} X Xchar * Xhostalias(name) X register char *name; X{ X register char *C1, *C2; X FILE *fp; X char *file, *getenv(), *strcpy(), *strncpy(); X char buf[BUFSIZ]; X static char abuf[MAXDNAME]; X X file = getenv("HOSTALIASES"); X if (file == NULL || (fp = fopen(file, "r")) == NULL) X return (NULL); X buf[sizeof(buf) - 1] = '\0'; X while (fgets(buf, sizeof(buf), fp)) { X for (C1 = buf; *C1 && !isspace(*C1); ++C1); X if (!*C1) X break; X *C1 = '\0'; X if (!strcasecmp(buf, name)) { X while (isspace(*++C1)); X if (!*C1) X break; X for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); X abuf[sizeof(abuf) - 1] = *C2 = '\0'; X (void)strncpy(abuf, C1, sizeof(abuf) - 1); X fclose(fp); X return (abuf); X } X } X fclose(fp); X return (NULL); X} END_OF_FILE if test 7583 -ne `wc -c <'res_query.c'`; then echo shar: \"'res_query.c'\" unpacked with wrong size! fi # end of 'res_query.c' fi if test -f 'res_send.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'res_send.c'\" else echo shar: Extracting \"'res_send.c'\" \(10025 characters\) sed "s/^X//" >'res_send.c' <<'END_OF_FILE' X/* X * Copyright (c) 1985, 1989 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: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: ``This product includes software X * developed by the University of California, Berkeley and its contributors'' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)res_send.c 6.25 (Berkeley) 6/1/90"; X#endif /* LIBC_SCCS and not lint */ X X/* X * Send query to name server and wait for reply. X */ X X#include <sys/param.h> X#include <sys/time.h> X#include <sys/socket.h> X#include <sys/uio.h> X#include <netinet/in.h> X#include <stdio.h> X#include <errno.h> X#include <arpa/nameser.h> X#include <resolv.h> X Xextern int errno; X Xstatic int s = -1; /* socket used for communications */ Xstatic struct sockaddr no_addr; X X X#ifndef FD_SET X#define NFDBITS 32 X#define FD_SETSIZE 32 X#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) X#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) X#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) X#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) X#endif X Xres_send(buf, buflen, answer, anslen) X char *buf; X int buflen; X char *answer; X int anslen; X{ X register int n; X int try, v_circuit, resplen, ns; X int gotsomewhere = 0, connected = 0; X int connreset = 0; X u_short id, len; X char *cp; X fd_set dsmask; X struct timeval timeout; X HEADER *hp = (HEADER *) buf; X HEADER *anhp = (HEADER *) answer; X struct iovec iov[2]; X int terrno = ETIMEDOUT; X char junk[512]; X X#ifdef DEBUG X if (_res.options & RES_DEBUG) { X printf("res_send()\n"); X p_query(buf); X } X#endif DEBUG X if (!(_res.options & RES_INIT)) X if (res_init() == -1) { X return(-1); X } X v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; X id = hp->id; X /* X * Send request, RETRY times, or until successful X */ X for (try = 0; try < _res.retry; try++) { X for (ns = 0; ns < _res.nscount; ns++) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("Querying server (# %d) address = %s\n", ns+1, X inet_ntoa(_res.nsaddr_list[ns].sin_addr)); X#endif DEBUG X usevc: X if (v_circuit) { X int truncated = 0; X X /* X * Use virtual circuit; X * at most one attempt per server. X */ X try = _res.retry; X if (s < 0) { X s = socket(AF_INET, SOCK_STREAM, 0); X if (s < 0) { X terrno = errno; X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("socket (vc) failed"); X#endif DEBUG X continue; X } X if (connect(s, &(_res.nsaddr_list[ns]), X sizeof(struct sockaddr)) < 0) { X terrno = errno; X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("connect failed"); X#endif DEBUG X (void) close(s); X s = -1; X continue; X } X } X /* X * Send length & message X */ X len = htons((u_short)buflen); X iov[0].iov_base = (caddr_t)&len; X iov[0].iov_len = sizeof(len); X iov[1].iov_base = buf; X iov[1].iov_len = buflen; X if (writev(s, iov, 2) != sizeof(len) + buflen) { X terrno = errno; X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("write failed"); X#endif DEBUG X (void) close(s); X s = -1; X continue; X } X /* X * Receive length & response X */ X cp = answer; X len = sizeof(short); X while (len != 0 && X (n = read(s, (char *)cp, (int)len)) > 0) { X cp += n; X len -= n; X } X if (n <= 0) { X terrno = errno; X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("read failed"); X#endif DEBUG X (void) close(s); X s = -1; X /* X * A long running process might get its TCP X * connection reset if the remote server was X * restarted. Requery the server instead of X * trying a new one. When there is only one X * server, this means that a query might work X * instead of failing. We only allow one reset X * per query to prevent looping. X */ X if (terrno == ECONNRESET && !connreset) { X connreset = 1; X ns--; X } X continue; X } X cp = answer; X if ((resplen = ntohs(*(u_short *)cp)) > anslen) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X fprintf(stderr, "response truncated\n"); X#endif DEBUG X len = anslen; X truncated = 1; X } else X len = resplen; X while (len != 0 && X (n = read(s, (char *)cp, (int)len)) > 0) { X cp += n; X len -= n; X } X if (n <= 0) { X terrno = errno; X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("read failed"); X#endif DEBUG X (void) close(s); X s = -1; X continue; X } X if (truncated) { X /* X * Flush rest of answer X * so connection stays in synch. X */ X anhp->tc = 1; X len = resplen - anslen; X while (len != 0) { X n = (len > sizeof(junk) ? X sizeof(junk) : len); X if ((n = read(s, junk, n)) > 0) X len -= n; X else X break; X } X } X } else { X /* X * Use datagrams. X */ X if (s < 0) { X s = socket(AF_INET, SOCK_DGRAM, 0); X if (s < 0) { X terrno = errno; X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("socket (dg) failed"); X#endif DEBUG X continue; X } X } X#if BSD >= 43 X /* X * I'm tired of answering this question, so: X * On a 4.3BSD+ machine (client and server, X * actually), sending to a nameserver datagram X * port with no nameserver will cause an X * ICMP port unreachable message to be returned. X * If our datagram socket is "connected" to the X * server, we get an ECONNREFUSED error on the next X * socket operation, and select returns if the X * error message is received. We can thus detect X * the absence of a nameserver without timing out. X * If we have sent queries to at least two servers, X * however, we don't want to remain connected, X * as we wish to receive answers from the first X * server to respond. X */ X if (_res.nscount == 1 || (try == 0 && ns == 0)) { X /* X * Don't use connect if we might X * still receive a response X * from another server. X */ X if (connected == 0) { X if (connect(s, &_res.nsaddr_list[ns], X sizeof(struct sockaddr)) < 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("connect"); X#endif DEBUG X continue; X } X connected = 1; X } X if (send(s, buf, buflen, 0) != buflen) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("send"); X#endif DEBUG X continue; X } X } else { X /* X * Disconnect if we want to listen X * for responses from more than one server. X */ X if (connected) { X (void) connect(s, &no_addr, X sizeof(no_addr)); X connected = 0; X } X#endif BSD X if (sendto(s, buf, buflen, 0, X &_res.nsaddr_list[ns], X sizeof(struct sockaddr)) != buflen) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("sendto"); X#endif DEBUG X continue; X } X#if BSD >= 43 X } X#endif X X /* X * Wait for reply X */ X timeout.tv_sec = (_res.retrans << try); X if (try > 0) X timeout.tv_sec /= _res.nscount; X if (timeout.tv_sec <= 0) X timeout.tv_sec = 1; X timeout.tv_usec = 0; Xwait: X FD_ZERO(&dsmask); X FD_SET(s, &dsmask); X n = select(s+1, &dsmask, (fd_set *)NULL, X (fd_set *)NULL, &timeout); X if (n < 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("select"); X#endif DEBUG X continue; X } X if (n == 0) { X /* X * timeout X */ X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("timeout\n"); X#endif DEBUG X#if BSD >= 43 X gotsomewhere = 1; X#endif X continue; X } X if ((resplen = recv(s, answer, anslen, 0)) <= 0) { X#ifdef DEBUG X if (_res.options & RES_DEBUG) X perror("recvfrom"); X#endif DEBUG X continue; X } X gotsomewhere = 1; X if (id != anhp->id) { X /* X * response from old query, ignore it X */ X#ifdef DEBUG X if (_res.options & RES_DEBUG) { X printf("old answer:\n"); X p_query(answer); X } X#endif DEBUG X goto wait; X } X if (!(_res.options & RES_IGNTC) && anhp->tc) { X /* X * get rest of answer; X * use TCP with same server. X */ X#ifdef DEBUG X if (_res.options & RES_DEBUG) X printf("truncated answer\n"); X#endif DEBUG X (void) close(s); X s = -1; X v_circuit = 1; X goto usevc; X } X } X#ifdef DEBUG X if (_res.options & RES_DEBUG) { X printf("got answer:\n"); X p_query(answer); X } X#endif DEBUG X /* X * If using virtual circuits, we assume that the first server X * is preferred * over the rest (i.e. it is on the local X * machine) and only keep that one open. X * If we have temporarily opened a virtual circuit, X * or if we haven't been asked to keep a socket open, X * close the socket. X */ X if ((v_circuit && X ((_res.options & RES_USEVC) == 0 || ns != 0)) || X (_res.options & RES_STAYOPEN) == 0) { X (void) close(s); X s = -1; X } X return (resplen); X } X } X if (s >= 0) { X (void) close(s); X s = -1; X } X if (v_circuit == 0) X if (gotsomewhere == 0) X errno = ECONNREFUSED; /* no nameservers found */ X else X errno = ETIMEDOUT; /* no answer obtained */ X else X errno = terrno; X return (-1); X} X X/* X * This routine is for closing the socket if a virtual circuit is used and X * the program wants to close it. This provides support for endhostent() X * which expects to close the socket. X * X * This routine is not expected to be user visible. X */ X_res_close() X{ X if (s != -1) { X (void) close(s); X s = -1; X } X} END_OF_FILE if test 10025 -ne `wc -c <'res_send.c'`; then echo shar: \"'res_send.c'\" unpacked with wrong size! fi # end of 'res_send.c' fi echo shar: End of archive 2 \(of 2\). cp /dev/null ark2isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0