Incorporated from BIND-4.9.3-BETA9.
authorroland <roland>
Thu, 28 Jul 1994 21:56:20 +0000 (21:56 +0000)
committerroland <roland>
Thu, 28 Jul 1994 21:56:20 +0000 (21:56 +0000)
resolv/res_comp.c
resolv/res_debug.c
resolv/res_init.c
resolv/res_mkquery.c
resolv/res_query.c
resolv/res_send.c
resolv/resolv.h
resolv/sethostent.c

index f8890f3..ae40d63 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * ++Copyright++ 1985
+ * ++Copyright++ 1985, 1993
  * -
  * -
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1993
+ *    The Regents of the University of California.  All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_comp.c 6.22 (Berkeley) 3/19/91";
+static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
-#include <arpa/nameser.h>
 #include <netinet/in.h>
 #include <netinet/in.h>
-#include <resolv.h>
+#include <arpa/nameser.h>
+
 #include <stdio.h>
 #include <stdio.h>
-#include "../conf/portability.h"
+#include <resolv.h>
+#include <ctype.h>
 
 
-static int dn_find();
+#if defined(BSD) && (BSD >= 199103)
+# include <unistd.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+static int     dn_find __P((u_char *exp_dn, u_char *msg,
+                            u_char **dnptrs, u_char **lastdnptr));
 
 /*
  * Expand compressed domain name 'comp_dn' to full domain name.
 
 /*
  * Expand compressed domain name 'comp_dn' to full domain name.
@@ -74,18 +83,20 @@ static int dn_find();
  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  * Return size of compressed name or -1 if there was an error.
  */
  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  * Return size of compressed name or -1 if there was an error.
  */
+int
 dn_expand(msg, eomorig, comp_dn, exp_dn, length)
        const u_char *msg, *eomorig, *comp_dn;
 dn_expand(msg, eomorig, comp_dn, exp_dn, length)
        const u_char *msg, *eomorig, *comp_dn;
-       u_char *exp_dn;
+       char *exp_dn;
        int length;
 {
        int length;
 {
-       register u_char *cp, *dn;
+       register const u_char *cp;
+       register char *dn;
        register int n, c;
        register int n, c;
-       u_char *eom;
+       char *eom;
        int len = -1, checked = 0;
 
        dn = exp_dn;
        int len = -1, checked = 0;
 
        dn = exp_dn;
-       cp = (u_char *)comp_dn;
+       cp = comp_dn;
        eom = exp_dn + length;
        /*
         * fetch next label in domain name
        eom = exp_dn + length;
        /*
         * fetch next label in domain name
@@ -119,7 +130,7 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
                case INDIR_MASK:
                        if (len < 0)
                                len = cp - comp_dn + 1;
                case INDIR_MASK:
                        if (len < 0)
                                len = cp - comp_dn + 1;
-                       cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+                       cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
                        if (cp < msg || cp >= eomorig)  /* out of range */
                                return(-1);
                        checked += 2;
                        if (cp < msg || cp >= eomorig)  /* out of range */
                                return(-1);
                        checked += 2;
@@ -137,6 +148,9 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
                }
        }
        *dn = '\0';
                }
        }
        *dn = '\0';
+       for (dn = exp_dn; (c = *dn) != '\0'; dn++)
+               if (isascii(c) && isspace(c))
+                       return (-1);
        if (len < 0)
                len = cp - comp_dn;
        return (len);
        if (len < 0)
                len = cp - comp_dn;
        return (len);
@@ -154,8 +168,9 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  * is NULL, we don't update the list.
  */
  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  * is NULL, we don't update the list.
  */
+int
 dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
 dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
-       const u_char *exp_dn;
+       const char *exp_dn;
        u_char *comp_dn, **dnptrs, **lastdnptr;
        int length;
 {
        u_char *comp_dn, **dnptrs, **lastdnptr;
        int length;
 {
@@ -167,6 +182,7 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
        dn = (u_char *)exp_dn;
        cp = comp_dn;
        eob = cp + length;
        dn = (u_char *)exp_dn;
        cp = comp_dn;
        eob = cp + length;
+       lpp = cpp = NULL;
        if (dnptrs != NULL) {
                if ((msg = *dnptrs++) != NULL) {
                        for (cpp = dnptrs; *cpp != NULL; cpp++)
        if (dnptrs != NULL) {
                if ((msg = *dnptrs++) != NULL) {
                        for (cpp = dnptrs; *cpp != NULL; cpp++)
@@ -232,31 +248,44 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
 /*
  * Skip over a compressed domain name. Return the size or -1.
  */
 /*
  * Skip over a compressed domain name. Return the size or -1.
  */
+int
 __dn_skipname(comp_dn, eom)
        const u_char *comp_dn, *eom;
 {
 __dn_skipname(comp_dn, eom)
        const u_char *comp_dn, *eom;
 {
-       register u_char *cp;
+       register const u_char *cp;
        register int n;
 
        register int n;
 
-       cp = (u_char *)comp_dn;
+       cp = comp_dn;
        while (cp < eom && (n = *cp++)) {
                /*
                 * check for indirection
                 */
                switch (n & INDIR_MASK) {
        while (cp < eom && (n = *cp++)) {
                /*
                 * check for indirection
                 */
                switch (n & INDIR_MASK) {
-               case 0:         /* normal case, n == len */
+               case 0:                 /* normal case, n == len */
                        cp += n;
                        continue;
                        cp += n;
                        continue;
-               default:        /* illegal type */
-                       return (-1);
                case INDIR_MASK:        /* indirection */
                        cp++;
                case INDIR_MASK:        /* indirection */
                        cp++;
+                       break;
+               default:                /* illegal type */
+                       return -1;
                }
                break;
        }
                }
                break;
        }
+       if (cp > eom)
+               return -1;
        return (cp - comp_dn);
 }
 
        return (cp - comp_dn);
 }
 
+static int
+mklower(ch)
+       register int ch;
+{
+       if (isascii(ch) && isupper(ch))
+               return (tolower(ch));
+       return (ch);
+}
+
 /*
  * Search for expanded name from a list of previously compressed names.
  * Return the offset from msg if found or -1.
 /*
  * Search for expanded name from a list of previously compressed names.
  * Return the offset from msg if found or -1.
@@ -286,7 +315,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
                                                goto next;
                                        if (*dn == '\\')
                                                dn++;
                                                goto next;
                                        if (*dn == '\\')
                                                dn++;
-                                       if (*dn++ != *cp++)
+                                       if (mklower(*dn++) != mklower(*cp++))
                                                goto next;
                                }
                                if ((n = *dn++) == '\0' && *cp == '\0')
                                                goto next;
                                }
                                if ((n = *dn++) == '\0' && *cp == '\0')
@@ -317,32 +346,32 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
  * used by sendmail.
  */
 
  * used by sendmail.
  */
 
-u_short
+u_int16_t
 _getshort(msgp)
 _getshort(msgp)
-       register u_char *msgp;
+       register const u_char *msgp;
 {
 {
-       register u_short u;
+       register u_int16_t u;
 
        GETSHORT(u, msgp);
 
        GETSHORT(u, msgp);
-       return u;
+       return (u);
 }
 
 u_int32_t
 _getlong(msgp)
 }
 
 u_int32_t
 _getlong(msgp)
-       register u_char *msgp;
+       register const u_char *msgp;
 {
        register u_int32_t u;
 
        GETLONG(u, msgp);
 {
        register u_int32_t u;
 
        GETLONG(u, msgp);
-       return u;
+       return (u);
 }
 
 void
 #if defined(__STDC__) || defined(__cplusplus)
 }
 
 void
 #if defined(__STDC__) || defined(__cplusplus)
-__putshort(register u_short s, register u_char *msgp)
+__putshort(register u_int16_t s, register u_char *msgp)        /* must match proto */
 #else
 __putshort(s, msgp)
 #else
 __putshort(s, msgp)
-       register u_short s;
+       register u_int16_t s;
        register u_char *msgp;
 #endif
 {
        register u_char *msgp;
 #endif
 {
@@ -356,3 +385,36 @@ __putlong(l, msgp)
 {
        PUTLONG(l, msgp);
 }
 {
        PUTLONG(l, msgp);
 }
+
+#ifdef ultrix
+/* ultrix 4.0 had some icky packaging in its libc.a.  alias for it here.
+ * there is more gunk of this kind over in res_debug.c.
+ */
+#undef putshort
+void
+#if defined(__STDC__) || defined(__cplusplus)
+putshort(register u_short s, register u_char *msgp)
+#else
+putshort(s, msgp)
+       register u_short s;
+       register u_char *msgp;
+#endif
+{
+       __putshort(s, msgp);
+}
+#undef putlong
+void
+putlong(l, msgp)
+       register u_int32_t l;
+       register u_char *msgp;
+{
+       __putlong(l, msgp);
+}
+#undef dn_skipname
+dn_skipname(comp_dn, eom)
+       const u_char *comp_dn, *eom;
+{
+       return __dn_skipname(comp_dn, eom);
+}
+#endif /* Ultrix 4.0 hackery */
index 15e7169..c16bea8 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * ++Copyright++ 1985, 1990
+ * ++Copyright++ 1985, 1990, 1993
  * -
  * -
- * Copyright (c) 1985, 1990 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1990, 1993
+ *    The Regents of the University of California.  All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,7 +54,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_debug.c        5.36 (Berkeley) 3/6/91";
+static char sccsid[] = "@(#)res_debug.c        8.1 (Berkeley) 6/4/93";
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
@@ -62,16 +62,20 @@ static char rcsid[] = "$Id$";
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
-#include <resolv.h>
+
 #include <stdio.h>
 #include <stdio.h>
-#include "../conf/portability.h"
+#include <resolv.h>
+#if defined(BSD) && (BSD >= 199103)
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
 
 
-void __fp_query();
-char *__p_class(), *__p_time(), *__p_type();
-char *p_cdname(), *p_fqname(), *p_rr();
-static char *p_option __P((u_int32_t));
+#if defined(USE_OPTIONS_H)
+# include "../conf/options.h"
+#endif
 
 
-char *_res_opcodes[] = {
+const char *_res_opcodes[] = {
        "QUERY",
        "IQUERY",
        "CQUERYM",
        "QUERY",
        "IQUERY",
        "CQUERYM",
@@ -90,7 +94,7 @@ char *_res_opcodes[] = {
        "ZONEREF",
 };
 
        "ZONEREF",
 };
 
-char *_res_resultcodes[] = {
+const char *_res_resultcodes[] = {
        "NOERROR",
        "FORMERR",
        "SERVFAIL",
        "NOERROR",
        "FORMERR",
        "SERVFAIL",
@@ -111,116 +115,131 @@ char *_res_resultcodes[] = {
 
 static char retbuf[16];
 
 
 static char retbuf[16];
 
-static char *
+static const char *
 dewks(wks)
        int wks;
 {
        switch (wks) {
 dewks(wks)
        int wks;
 {
        switch (wks) {
-       case 5: return("rje");
-       case 7: return("echo");
-       case 9: return("discard");
-       case 11: return("systat");
-       case 13: return("daytime");
-       case 15: return("netstat");
-       case 17: return("qotd");
-       case 19: return("chargen");
-       case 20: return("ftp-data");
-       case 21: return("ftp");
-       case 23: return("telnet");
-       case 25: return("smtp");
-       case 37: return("time");
-       case 39: return("rlp");
-       case 42: return("name");
-       case 43: return("whois");
-       case 53: return("domain");
-       case 57: return("apts");
-       case 59: return("apfs");
-       case 67: return("bootps");
-       case 68: return("bootpc");
-       case 69: return("tftp");
-       case 77: return("rje");
-       case 79: return("finger");
-       case 87: return("link");
-       case 95: return("supdup");
-       case 100: return("newacct");
-       case 101: return("hostnames");
-       case 102: return("iso-tsap");
-       case 103: return("x400");
-       case 104: return("x400-snd");
-       case 105: return("csnet-ns");
-       case 109: return("pop-2");
-       case 111: return("sunrpc");
-       case 113: return("auth");
-       case 115: return("sftp");
-       case 117: return("uucp-path");
-       case 119: return("nntp");
-       case 121: return("erpc");
-       case 123: return("ntp");
-       case 133: return("statsrv");
-       case 136: return("profile");
-       case 144: return("NeWS");
-       case 161: return("snmp");
-       case 162: return("snmp-trap");
-       case 170: return("print-srv");
-       default: (void) sprintf(retbuf, "%d", wks); return(retbuf);
+       case 5: return "rje";
+       case 7: return "echo";
+       case 9: return "discard";
+       case 11: return "systat";
+       case 13: return "daytime";
+       case 15: return "netstat";
+       case 17: return "qotd";
+       case 19: return "chargen";
+       case 20: return "ftp-data";
+       case 21: return "ftp";
+       case 23: return "telnet";
+       case 25: return "smtp";
+       case 37: return "time";
+       case 39: return "rlp";
+       case 42: return "name";
+       case 43: return "whois";
+       case 53: return "domain";
+       case 57: return "apts";
+       case 59: return "apfs";
+       case 67: return "bootps";
+       case 68: return "bootpc";
+       case 69: return "tftp";
+       case 77: return "rje";
+       case 79: return "finger";
+       case 87: return "link";
+       case 95: return "supdup";
+       case 100: return "newacct";
+       case 101: return "hostnames";
+       case 102: return "iso-tsap";
+       case 103: return "x400";
+       case 104: return "x400-snd";
+       case 105: return "csnet-ns";
+       case 109: return "pop-2";
+       case 111: return "sunrpc";
+       case 113: return "auth";
+       case 115: return "sftp";
+       case 117: return "uucp-path";
+       case 119: return "nntp";
+       case 121: return "erpc";
+       case 123: return "ntp";
+       case 133: return "statsrv";
+       case 136: return "profile";
+       case 144: return "NeWS";
+       case 161: return "snmp";
+       case 162: return "snmp-trap";
+       case 170: return "print-srv";
+       default: (void) sprintf(retbuf, "%d", wks); return (retbuf);
        }
 }
 
        }
 }
 
-static char *
+static const char *
 deproto(protonum)
        int protonum;
 {
        switch (protonum) {
 deproto(protonum)
        int protonum;
 {
        switch (protonum) {
-       case 1: return("icmp");
-       case 2: return("igmp");
-       case 3: return("ggp");
-       case 5: return("st");
-       case 6: return("tcp");
-       case 7: return("ucl");
-       case 8: return("egp");
-       case 9: return("igp");
-       case 11: return("nvp-II");
-       case 12: return("pup");
-       case 16: return("chaos");
-       case 17: return("udp");
-       default: (void) sprintf(retbuf, "%d", protonum); return(retbuf);
+       case 1: return "icmp";
+       case 2: return "igmp";
+       case 3: return "ggp";
+       case 5: return "st";
+       case 6: return "tcp";
+       case 7: return "ucl";
+       case 8: return "egp";
+       case 9: return "igp";
+       case 11: return "nvp-II";
+       case 12: return "pup";
+       case 16: return "chaos";
+       case 17: return "udp";
+       default: (void) sprintf(retbuf, "%d", protonum); return (retbuf);
        }
 }
 
        }
 }
 
-static char *
+static const u_char *
 do_rrset(msg, cp, cnt, pflag, file, hs)
        int cnt, pflag;
 do_rrset(msg, cp, cnt, pflag, file, hs)
        int cnt, pflag;
-       char *cp,*msg, *hs;
+       const u_char *cp, *msg;
+       const char *hs;
        FILE *file;
 {
        int n;
        FILE *file;
 {
        int n;
-       char *t1, *t2, *list[100],**tt;
        int sflag;
        int sflag;
+
        /*
        /*
-        * Print  answer records
+        * Print answer records.
         */
        sflag = (_res.pfcode & pflag);
        if (n = ntohs(cnt)) {
         */
        sflag = (_res.pfcode & pflag);
        if (n = ntohs(cnt)) {
-               *list=NULL;
-               if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+               if ((!_res.pfcode) ||
+                   ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
                        fprintf(file, hs);
                while (--n >= 0) {
                        cp = p_rr(cp, msg, file);
                        fprintf(file, hs);
                while (--n >= 0) {
                        cp = p_rr(cp, msg, file);
-                       if ((cp-msg) > PACKETSZ)
+                       if ((cp - msg) > PACKETSZ)
                                return (NULL);
                }
                                return (NULL);
                }
-               if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+               if ((!_res.pfcode) ||
+                   ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
                        putc('\n', file);
        }
                        putc('\n', file);
        }
-       return(cp);
+       return (cp);
 }
 
 }
 
+void
 __p_query(msg)
 __p_query(msg)
-       char *msg;
+       const u_char *msg;
 {
        __fp_query(msg, stdout);
 }
 
 {
        __fp_query(msg, stdout);
 }
 
+#ifdef ultrix
+/* ultrix 4.0's packaging has some icky packaging.  alias for it here.
+ * there is more junk of this kind over in res_comp.c.
+ */
+void
+p_query(msg)
+       const u_char *msg;
+{
+       __p_query(msg);
+}
+#endif
+
 /*
  * Print the current options.
  * This is intended to be primarily a debugging routine.
 /*
  * Print the current options.
  * This is intended to be primarily a debugging routine.
@@ -230,15 +249,14 @@ __fp_resstat(statp, file)
        struct __res_state *statp;
        FILE *file;
 {
        struct __res_state *statp;
        FILE *file;
 {
-       int bit;
+       register u_long mask;
 
        fprintf(file, ";; res options:");
        if (!statp)
                statp = &_res;
 
        fprintf(file, ";; res options:");
        if (!statp)
                statp = &_res;
-       for (bit = 0;  bit < 32;  bit++) {      /* XXX 32 - bad assumption! */
-               if (statp->options & (1<<bit))
-                       fprintf(file, " %s", p_option(1<<bit));
-       }
+       for (mask = 1;  mask != 0;  mask <<= 1)
+               if (statp->options & mask)
+                       fprintf(file, " %s", p_option(mask));
        putc('\n', file);
 }
 
        putc('\n', file);
 }
 
@@ -247,21 +265,26 @@ __fp_resstat(statp, file)
  * This is intended to be primarily a debugging routine.
  */
 void
  * This is intended to be primarily a debugging routine.
  */
 void
-__fp_query(msg,file)
-       char *msg;
+__fp_nquery(msg, len, file)
+       const u_char *msg;
+       int len;
        FILE *file;
 {
        FILE *file;
 {
-       register char *cp;
-       register HEADER *hp;
+       register const u_char *cp, *endMark;
+       register const HEADER *hp;
        register int n;
 
        register int n;
 
+#define TruncTest(x) if (x >= endMark) goto trunc
+#define        ErrorTest(x) if (x == NULL) goto error
+
        /*
         * Print header fields.
         */
        hp = (HEADER *)msg;
        /*
         * Print header fields.
         */
        hp = (HEADER *)msg;
-       cp = msg + sizeof(HEADER);
+       cp = msg + HFIXEDSZ;
+       endMark = cp + len;
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
-               fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
+               fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
                        _res_opcodes[hp->opcode],
                        _res_resultcodes[hp->rcode],
                        ntohs(hp->id));
                        _res_opcodes[hp->opcode],
                        _res_resultcodes[hp->rcode],
                        ntohs(hp->id));
@@ -271,29 +294,28 @@ __fp_query(msg,file)
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
                fprintf(file,"; flags:");
                if (hp->qr)
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
                fprintf(file,"; flags:");
                if (hp->qr)
-                       fprintf(file," qr");
+                       fprintf(file, " qr");
                if (hp->aa)
                if (hp->aa)
-                       fprintf(file," aa");
+                       fprintf(file, " aa");
                if (hp->tc)
                if (hp->tc)
-                       fprintf(file," tc");
+                       fprintf(file, " tc");
                if (hp->rd)
                if (hp->rd)
-                       fprintf(file," rd");
+                       fprintf(file, " rd");
                if (hp->ra)
                if (hp->ra)
-                       fprintf(file," ra");
+                       fprintf(file, " ra");
                if (hp->pr)
                if (hp->pr)
-                       fprintf(file," pr");
+                       fprintf(file, " pr");
        }
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
        }
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
-               fprintf(file,"; Ques: %d", ntohs(hp->qdcount));
-               fprintf(file,", Ans: %d", ntohs(hp->ancount));
-               fprintf(file,", Auth: %d", ntohs(hp->nscount));
-               fprintf(file,", Addit: %d\n", ntohs(hp->arcount));
+               fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
+               fprintf(file, ", Ans: %d", ntohs(hp->ancount));
+               fprintf(file, ", Auth: %d", ntohs(hp->nscount));
+               fprintf(file, ", Addit: %d", ntohs(hp->arcount));
        }
        }
-#if 0
-       if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) {
+       if ((!_res.pfcode) || (_res.pfcode & 
+               (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
                putc('\n',file);
        }
                putc('\n',file);
        }
-#endif
        /*
         * Print question records.
         */
        /*
         * Print question records.
         */
@@ -302,73 +324,99 @@ __fp_query(msg,file)
                        fprintf(file,";; QUESTIONS:\n");
                while (--n >= 0) {
                        fprintf(file,";;\t");
                        fprintf(file,";; QUESTIONS:\n");
                while (--n >= 0) {
                        fprintf(file,";;\t");
+                       TruncTest(cp);
                        cp = p_cdname(cp, msg, file);
                        cp = p_cdname(cp, msg, file);
-                       if (cp == NULL)
-                               return;
+                       ErrorTest(cp);
+                       TruncTest(cp);
                        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
                                fprintf(file, ", type = %s",
                        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
                                fprintf(file, ", type = %s",
-                                       __p_type(_getshort(cp)));
-                       cp += sizeof(u_short);
+                                       __p_type(_getshort((u_char*)cp)));
+                       cp += INT16SZ;
+                       TruncTest(cp);
                        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
                        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
-                               fprintf(file, ", class = %s\n\n",
-                                       __p_class(_getshort(cp)));
-                       cp += sizeof(u_short);
+                               fprintf(file, ", class = %s\n",
+                                       __p_class(_getshort((u_char*)cp)));
+                       cp += INT16SZ;
+                       putc('\n', file);
                }
        }
        /*
         * Print authoritative answer records
         */
                }
        }
        /*
         * Print authoritative answer records
         */
+       TruncTest(cp);
        cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file,
                      ";; ANSWERS:\n");
        cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file,
                      ";; ANSWERS:\n");
-       if (cp == NULL)
-               return;
+       ErrorTest(cp);
 
        /*
         * print name server records
         */
 
        /*
         * print name server records
         */
+       TruncTest(cp);
        cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file,
                      ";; AUTHORITY RECORDS:\n");
        cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file,
                      ";; AUTHORITY RECORDS:\n");
-       if (!cp)
-               return;
+       ErrorTest(cp);
 
 
+       TruncTest(cp);
        /*
         * print additional records
         */
        cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file,
                      ";; ADDITIONAL RECORDS:\n");
        /*
         * print additional records
         */
        cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file,
                      ";; ADDITIONAL RECORDS:\n");
-       if (!cp)
-               return;
+       ErrorTest(cp);
+       return;
+ trunc:
+       fprintf(file, "\n;; ...truncated\n");
+       return;
+ error:
+       fprintf(file, "\n;; ...malformed\n");
 }
 
 }
 
-char *
-p_cdname(cp, msg, file)
-       char *cp, *msg;
+void
+__fp_query(msg, file)
+       const u_char *msg;
+       FILE *file;
+{
+       fp_nquery(msg, PACKETSZ, file);
+}
+
+const u_char *
+__p_cdnname(cp, msg, len, file)
+       const u_char *cp, *msg;
+       int len;
        FILE *file;
 {
        char name[MAXDNAME];
        int n;
 
        FILE *file;
 {
        char name[MAXDNAME];
        int n;
 
-       if ((n = dn_expand((u_char *)msg, (u_char *)msg + 512, (u_char *)cp,
-           (u_char *)name, sizeof(name))) < 0)
+       if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
                return (NULL);
                return (NULL);
-       if (name[0] == '\0') {
+       if (name[0] == '\0')
                putc('.', file);
                putc('.', file);
-       } else {
+       else
                fputs(name, file);
                fputs(name, file);
-       }
        return (cp + n);
 }
 
        return (cp + n);
 }
 
-char *
-p_fqname(cp, msg, file)
-       char *cp, *msg;
+const u_char *
+__p_cdname(cp, msg, file)
+       const u_char *cp, *msg;
+       FILE *file;
+{
+       return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+/* XXX:        the rest of these functions need to become length-limited, too. (vix)
+ */
+
+const u_char *
+__p_fqname(cp, msg, file)
+       const u_char *cp, *msg;
        FILE *file;
 {
        char name[MAXDNAME];
        int n, len;
 
        FILE *file;
 {
        char name[MAXDNAME];
        int n, len;
 
-       if ((n = dn_expand((u_char *)msg, (u_char *)msg + 512, (u_char *)cp,
-           (u_char *)name, sizeof(name))) < 0)
+       if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
                return (NULL);
        if (name[0] == '\0') {
                putc('.', file);
                return (NULL);
        if (name[0] == '\0') {
                putc('.', file);
@@ -380,32 +428,30 @@ p_fqname(cp, msg, file)
        return (cp + n);
 }
 
        return (cp + n);
 }
 
-
-
 /*
  * Print resource record fields in human readable form.
  */
 /*
  * Print resource record fields in human readable form.
  */
-char *
-p_rr(cp, msg, file)
-       char *cp, *msg;
+const u_char *
+__p_rr(cp, msg, file)
+       const u_char *cp, *msg;
        FILE *file;
 {
        int type, class, dlen, n, c;
        struct in_addr inaddr;
        FILE *file;
 {
        int type, class, dlen, n, c;
        struct in_addr inaddr;
-       char *cp1, *cp2;
+       const u_char *cp1, *cp2;
        u_int32_t tmpttl, t;
        int lcnt;
 
        if ((cp = p_fqname(cp, msg, file)) == NULL)
                return (NULL);                  /* compression error */
        u_int32_t tmpttl, t;
        int lcnt;
 
        if ((cp = p_fqname(cp, msg, file)) == NULL)
                return (NULL);                  /* compression error */
-       type = _getshort(cp);
-       cp += sizeof(u_short);
-       class = _getshort(cp);
-       cp += sizeof(u_short);
-       tmpttl = _getlong(cp);
-       cp += sizeof(u_int32_t);
-       dlen = _getshort(cp);
-       cp += sizeof(u_short);
+       type = _getshort((u_char*)cp);
+       cp += INT16SZ;
+       class = _getshort((u_char*)cp);
+       cp += INT16SZ;
+       tmpttl = _getlong((u_char*)cp);
+       cp += INT32SZ;
+       dlen = _getshort((u_char*)cp);
+       cp += INT16SZ;
        cp1 = cp;
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
                fprintf(file, "\t%lu", tmpttl);
        cp1 = cp;
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
                fprintf(file, "\t%lu", tmpttl);
@@ -420,7 +466,7 @@ p_rr(cp, msg, file)
                switch (class) {
                case C_IN:
                case C_HS:
                switch (class) {
                case C_IN:
                case C_HS:
-                       bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+                       bcopy(cp, (char *)&inaddr, INADDRSZ);
                        if (dlen == 4) {
                                fprintf(file,"\t%s", inet_ntoa(inaddr));
                                cp += dlen;
                        if (dlen == 4) {
                                fprintf(file,"\t%s", inet_ntoa(inaddr));
                                cp += dlen;
@@ -430,11 +476,11 @@ p_rr(cp, msg, file)
                                u_short port;
 
                                address = inet_ntoa(inaddr);
                                u_short port;
 
                                address = inet_ntoa(inaddr);
-                               cp += sizeof(inaddr);
+                               cp += INADDRSZ;
                                protocol = *(u_char*)cp;
                                cp += sizeof(u_char);
                                protocol = *(u_char*)cp;
                                cp += sizeof(u_char);
-                               port = _getshort(cp);
-                               cp += sizeof(u_short);
+                               port = _getshort((u_char*)cp);
+                               cp += INT16SZ;
                                fprintf(file, "\t%s\t; proto %d, port %d",
                                        address, protocol, port);
                        }
                                fprintf(file, "\t%s\t; proto %d, port %d",
                                        address, protocol, port);
                        }
@@ -454,6 +500,7 @@ p_rr(cp, msg, file)
                break;
 
        case T_HINFO:
                break;
 
        case T_HINFO:
+       case T_ISDN:
                if (n = *cp++) {
                        fprintf(file,"\t%.*s", n, cp);
                        cp += n;
                if (n = *cp++) {
                        fprintf(file,"\t%.*s", n, cp);
                        cp += n;
@@ -470,25 +517,28 @@ p_rr(cp, msg, file)
                putc(' ', file);
                cp = p_fqname(cp, msg, file);   /* mail addr */
                fputs(" (\n", file);
                putc(' ', file);
                cp = p_fqname(cp, msg, file);   /* mail addr */
                fputs(" (\n", file);
-               t = _getlong(cp);  cp += sizeof(u_int32_t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
                fprintf(file,"\t\t\t%lu\t; serial\n", t);
                fprintf(file,"\t\t\t%lu\t; serial\n", t);
-               t = _getlong(cp);  cp += sizeof(u_int32_t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
                fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t));
                fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t));
-               t = _getlong(cp);  cp += sizeof(u_int32_t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
                fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t));
                fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t));
-               t = _getlong(cp);  cp += sizeof(u_int32_t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
                fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t));
                fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t));
-               t = _getlong(cp);  cp += sizeof(u_int32_t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
                fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t));
                break;
 
        case T_MX:
                fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t));
                break;
 
        case T_MX:
-               fprintf(file,"\t%d ", _getshort(cp));
-               cp += sizeof(u_short);
+       case T_AFSDB:
+       case T_RT:
+               fprintf(file,"\t%d ", _getshort((u_char*)cp));
+               cp += INT16SZ;
                cp = p_fqname(cp, msg, file);
                break;
 
        case T_TXT:
                cp = p_fqname(cp, msg, file);
                break;
 
        case T_TXT:
+       case T_X25:
                (void) fputs("\t\"", file);
                cp2 = cp1 + dlen;
                while (cp < cp2) {
                (void) fputs("\t\"", file);
                cp2 = cp1 + dlen;
                while (cp < cp2) {
@@ -504,6 +554,11 @@ p_rr(cp, msg, file)
                putc('"', file);
                break;
 
                putc('"', file);
                break;
 
+       case T_NSAP:
+               (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
+               cp += dlen;
+               break;
+
        case T_MINFO:
        case T_RP:
                putc('\t', file);
        case T_MINFO:
        case T_RP:
                putc('\t', file);
@@ -514,23 +569,23 @@ p_rr(cp, msg, file)
 
        case T_UINFO:
                putc('\t', file);
 
        case T_UINFO:
                putc('\t', file);
-               fputs(cp, file);
+               fputs((char *)cp, file);
                cp += dlen;
                break;
 
        case T_UID:
        case T_GID:
                if (dlen == 4) {
                cp += dlen;
                break;
 
        case T_UID:
        case T_GID:
                if (dlen == 4) {
-                       fprintf(file,"\t%u", _getlong(cp));
-                       cp += sizeof(int32_t);
+                       fprintf(file,"\t%u", _getlong((u_char*)cp));
+                       cp += INT32SZ;
                }
                break;
 
        case T_WKS:
                }
                break;
 
        case T_WKS:
-               if (dlen < sizeof(u_int32_t) + 1)
+               if (dlen < INT32SZ + 1)
                        break;
                        break;
-               bcopy(cp, (char *)&inaddr, sizeof(inaddr));
-               cp += sizeof(u_int32_t);
+               bcopy(cp, (char *)&inaddr, INADDRSZ);
+               cp += INT32SZ;
                fprintf(file, "\t%s %s ( ",
                        inet_ntoa(inaddr),
                        deproto((int) *cp));
                fprintf(file, "\t%s %s ( ",
                        inet_ntoa(inaddr),
                        deproto((int) *cp));
@@ -559,7 +614,7 @@ p_rr(cp, msg, file)
        case T_UNSPEC:
                {
                        int NumBytes = 8;
        case T_UNSPEC:
                {
                        int NumBytes = 8;
-                       char *DataPtr;
+                       u_char *DataPtr;
                        int i;
 
                        if (dlen < NumBytes) NumBytes = dlen;
                        int i;
 
                        if (dlen < NumBytes) NumBytes = dlen;
@@ -594,92 +649,66 @@ static    char nbuf[40];
 /*
  * Return a string for the type
  */
 /*
  * Return a string for the type
  */
-char *
+const char *
 __p_type(type)
        int type;
 {
        switch (type) {
 __p_type(type)
        int type;
 {
        switch (type) {
-       case T_A:
-               return("A");
-       case T_NS:              /* authoritative server */
-               return("NS");
-       case T_CNAME:           /* canonical name */
-               return("CNAME");
-       case T_SOA:             /* start of authority zone */
-               return("SOA");
-       case T_MB:              /* mailbox domain name */
-               return("MB");
-       case T_MG:              /* mail group member */
-               return("MG");
-       case T_MR:              /* mail rename name */
-               return("MR");
-       case T_NULL:            /* null resource record */
-               return("NULL");
-       case T_WKS:             /* well known service */
-               return("WKS");
-       case T_PTR:             /* domain name pointer */
-               return("PTR");
-       case T_HINFO:           /* host information */
-               return("HINFO");
-       case T_MINFO:           /* mailbox information */
-               return("MINFO");
-       case T_MX:              /* mail routing info */
-               return("MX");
-       case T_TXT:             /* text */
-               return("TXT");
-       case T_RP:              /* responsible person */
-               return("RP");
-       case T_AXFR:            /* zone transfer */
-               return("AXFR");
-       case T_MAILB:           /* mail box */
-               return("MAILB");
-       case T_MAILA:           /* mail address */
-               return("MAILA");
-       case T_ANY:             /* matches any type */
-               return("ANY");
-       case T_UINFO:
-               return("UINFO");
-       case T_UID:
-               return("UID");
-       case T_GID:
-               return("GID");
+       case T_A:       return "A";
+       case T_NS:      return "NS";
+       case T_CNAME:   return "CNAME";
+       case T_SOA:     return "SOA";
+       case T_MB:      return "MB";
+       case T_MG:      return "MG";
+       case T_MR:      return "MR";
+       case T_NULL:    return "NULL";
+       case T_WKS:     return "WKS";
+       case T_PTR:     return "PTR";
+       case T_HINFO:   return "HINFO";
+       case T_MINFO:   return "MINFO";
+       case T_MX:      return "MX";
+       case T_TXT:     return "TXT";
+       case T_NSAP:    return "NSAP";
+       case T_RP:      return "RP";
+       case T_AFSDB:   return "AFSDB";
+       case T_X25:     return "X25";
+       case T_ISDN:    return "ISDN";
+       case T_RT:      return "RT";
+       case T_AXFR:    return "AXFR";
+       case T_MAILB:   return "MAILB";
+       case T_MAILA:   return "MAILA";
+       case T_ANY:     return "ANY";
+       case T_UINFO:   return "UINFO";
+       case T_UID:     return "UID";
+       case T_GID:     return "GID";
 #ifdef ALLOW_T_UNSPEC
 #ifdef ALLOW_T_UNSPEC
-       case T_UNSPEC:
-               return("UNSPEC");
+       case T_UNSPEC:  return "UNSPEC";
 #endif /* ALLOW_T_UNSPEC */
 #endif /* ALLOW_T_UNSPEC */
-       default:
-               (void)sprintf(nbuf, "%d", type);
-               return(nbuf);
+       default:        (void)sprintf(nbuf, "%d", type); return (nbuf);
        }
 }
 
 /*
  * Return a mnemonic for class
  */
        }
 }
 
 /*
  * Return a mnemonic for class
  */
-char *
+const char *
 __p_class(class)
        int class;
 {
 __p_class(class)
        int class;
 {
-
        switch (class) {
        switch (class) {
-       case C_IN:              /* internet class */
-               return("IN");
-       case C_HS:              /* hesiod class */
-               return("HS");
-       case C_ANY:             /* matches any class */
-               return("ANY");
-       default:
-               (void)sprintf(nbuf, "%d", class);
-               return(nbuf);
+       case C_IN:      return("IN");
+       case C_HS:      return("HS");
+       case C_ANY:     return("ANY");
+       default:        (void)sprintf(nbuf, "%d", class); return (nbuf);
        }
 }
 
 /*
  * Return a mnemonic for an option
  */
        }
 }
 
 /*
  * Return a mnemonic for an option
  */
-static char *
-p_option(option)
-       u_int32_t option;
+const char *
+__p_option(option)
+       u_long option;
 {
        switch (option) {
        case RES_INIT:          return "init";
 {
        switch (option) {
        case RES_INIT:          return "init";
@@ -692,6 +721,8 @@ p_option(option)
        case RES_DEFNAMES:      return "defnam";
        case RES_STAYOPEN:      return "styopn";
        case RES_DNSRCH:        return "dnsrch";
        case RES_DEFNAMES:      return "defnam";
        case RES_STAYOPEN:      return "styopn";
        case RES_DNSRCH:        return "dnsrch";
+       case RES_INSECURE1:     return "insecure1";
+       case RES_INSECURE2:     return "insecure2";
        default:                sprintf(nbuf, "?0x%x?", option); return nbuf;
        }
 }
        default:                sprintf(nbuf, "?0x%x?", option); return nbuf;
        }
 }
@@ -708,7 +739,7 @@ __p_time(value)
 
        if (value == 0) {
                strcpy(nbuf, "0 secs");
 
        if (value == 0) {
                strcpy(nbuf, "0 secs");
-               return(nbuf);
+               return (nbuf);
        }
 
        secs = value % 60;
        }
 
        secs = value % 60;
@@ -743,5 +774,5 @@ __p_time(value)
                        *p++ = ' ';
                (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
        }
                        *p++ = ' ';
                (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
        }
-       return(nbuf);
+       return (nbuf);
 }
 }
index f3bcebc..b6b1368 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * ++Copyright++ 1985, 1989
+ * ++Copyright++ 1985, 1989, 1993
  * -
  * -
- * Copyright (c) 1985, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,7 +54,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_init.c 6.15 (Berkeley) 2/24/91";
+static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
@@ -63,36 +63,56 @@ static char rcsid[] = "$Id$";
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
-#include <resolv.h>
+
 #include <stdio.h>
 #include <stdio.h>
-#include "../conf/portability.h"
+#include <ctype.h>
+#include <resolv.h>
+#if defined(BSD) && (BSD >= 199103)
+# include <unistd.h>
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include "../conf/options.h"
+#endif
+
+static void res_setoptions __P((char *, char *));
+
+#ifdef RESOLVSORT
+static u_int32_t net_mask __P((struct in_addr));
+#endif
 
 
+#if !defined(isascii)  /* XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
 
 /*
 
 /*
- * Resolver state default settings
+ * Resolver state default settings.
  */
 
  */
 
-struct __res_state _res = {
-       RES_TIMEOUT,                    /* retransmition time interval */
-       4,                              /* number of times to retransmit */
-       RES_DEFAULT,                    /* options flags */
-       1,                              /* number of name servers */
-};
+struct __res_state _res;
 
 /*
  * Set up default settings.  If the configuration file exist, the values
  * there will have precedence.  Otherwise, the server address is set to
 
 /*
  * Set up default settings.  If the configuration file exist, the values
  * there will have precedence.  Otherwise, the server address is set to
- * 127.0.0.1 and the default domain name comes from the gethostname().
+ * INADDR_ANY and the default domain name comes from the gethostname().
  *
  *
- * Previous resolver versions used INADDR_ANY rather than IN_LOOPBACKNET.
- * This has bad side-effects in the kernel since 0.0.0.0 means "any interface"
- * and the first one found may or may not be the loopback interface.
- * If it is a point-to-point interface, then the SLIP or PPP or DDCMP state
- * must be "up" in order for the packets to loop correctly.  This is deemed
- * "bad".  
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server.  It
+ * was later decided that since the recommended practice is to always 
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
  *
  *
- * The configuration file should only be used if you want to redefine your
- * domain or run without a server on your machine.
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain.  If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
  *
  * Return 0 if completes successfully, -1 on error
  */
  *
  * Return 0 if completes successfully, -1 on error
  */
@@ -100,24 +120,79 @@ res_init()
 {
        register FILE *fp;
        register char *cp, **pp;
 {
        register FILE *fp;
        register char *cp, **pp;
-       register int n;
+       register int n, dots;
        char buf[BUFSIZ];
        int nserv = 0;    /* number of nameserver records read from file */
        int haveenv = 0;
        int havesearch = 0;
        char buf[BUFSIZ];
        int nserv = 0;    /* number of nameserver records read from file */
        int haveenv = 0;
        int havesearch = 0;
+#ifdef RESOLVSORT
+       int nsort = 0;
+       char *net;
+#endif
 
 
+       /*
+        * These four fields used to be statically initialized.  This made
+        * it hard to use this code in a shared library.  It is necessary,
+        * now that we're doing dynamic initialization here, that we preserve
+        * the old semantics: if an application modifies one of these three
+        * fields of _res before res_init() is called, res_init() will not
+        * alter them.  Of course, if an application is setting them to
+        * _zero_ before calling res_init(), hoping to override what used
+        * to be the static default, we can't detect it and unexpected results
+        * will follow.  Zero for any of these fields would make no sense,
+        * so one can safely assume that the applications were already getting
+        * unexpected results.
+        */
+       if (!_res.retrans)
+               _res.retrans = RES_TIMEOUT;
+       if (!_res.retry)
+               _res.retry = 4;
+       if (!_res.options)
+               _res.options = RES_DEFAULT;
+
+#ifdef USELOOPBACK
        _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
        _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+       _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+#endif
        _res.nsaddr.sin_family = AF_INET;
        _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
        _res.nscount = 1;
        _res.nsaddr.sin_family = AF_INET;
        _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
        _res.nscount = 1;
+       _res.ndots = 1;
        _res.pfcode = 0;
 
        /* Allow user to override the local domain definition */
        if ((cp = getenv("LOCALDOMAIN")) != NULL) {
        _res.pfcode = 0;
 
        /* Allow user to override the local domain definition */
        if ((cp = getenv("LOCALDOMAIN")) != NULL) {
-               (void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
-               if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
-                       *cp = '\0';
+               (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
                haveenv++;
                haveenv++;
+
+               /*
+                * Set search list to be blank-separated strings
+                * from rest of env value.  Permits users of LOCALDOMAIN
+                * to still have a search list, and anyone to set the
+                * one that they want to use as an individual (even more
+                * important now that the rfc1535 stuff restricts searches)
+                */
+               cp = _res.defdname;
+               pp = _res.dnsrch;
+               *pp++ = cp;
+               for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+                       if (*cp == '\n')        /* silly backwards compat */
+                               break;
+                       else if (*cp == ' ' || *cp == '\t') {
+                               *cp = 0;
+                               n = 1;
+                       } else if (n) {
+                               *pp++ = cp;
+                               n = 0;
+                               havesearch = 1;
+                       }
+               }
+               /* null terminate last domain if there are excess */
+               while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+                       cp++;
+               *cp = '\0';
+               *pp++ = 0;
        }
 
        if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
        }
 
        if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
@@ -162,7 +237,9 @@ res_init()
                    cp = _res.defdname;
                    pp = _res.dnsrch;
                    *pp++ = cp;
                    cp = _res.defdname;
                    pp = _res.dnsrch;
                    *pp++ = cp;
-                   for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+                   for (n = 0;
+                        *cp && pp < _res.dnsrch + MAXDNSRCH;
+                        cp++) {
                            if (*cp == ' ' || *cp == '\t') {
                                    *cp = 0;
                                    n = 1;
                            if (*cp == ' ' || *cp == '\t') {
                                    *cp = 0;
                                    n = 1;
@@ -196,33 +273,167 @@ res_init()
                    }
                    continue;
                }
                    }
                    continue;
                }
+#ifdef RESOLVSORT
+               if (!strncmp(buf, "sortlist", sizeof("sortlist") -1)) {
+                   struct in_addr a;
+
+                   cp = buf + sizeof("sortlist") - 1;
+                   while (nsort < MAXRESOLVSORT) {
+                       while (*cp == ' ' || *cp == '\t')
+                           cp++;
+                       if (*cp == '\0' || *cp == '\n' || *cp == ';')
+                           break;
+                       net = cp;
+                       while (*cp && *cp != '/' &&
+                           isascii(*cp) && !isspace(*cp))
+                               cp++;
+                       n = *cp;
+                       *cp = 0;
+                       if (inet_aton(net, &a)) {
+                           _res.sort_list[nsort].addr = a;
+                           if (n == '/') {
+                               *cp++ = n;
+                               net = cp;
+                               while (*cp && isascii(*cp) && !isspace(*cp))
+                                   cp++;
+                               n = *cp;
+                               *cp = 0;
+                               if (inet_aton(net, &a)) {
+                                   _res.sort_list[nsort].mask = a.s_addr;
+                               } else {
+                                   _res.sort_list[nsort].mask = 
+                                       net_mask(_res.sort_list[nsort].addr);
+                               }
+                           } else {
+                               _res.sort_list[nsort].mask = 
+                                   net_mask(_res.sort_list[nsort].addr);
+                           }
+                           nsort++;
+                       }
+                       *cp++ = n;
+                   }
+                   continue;
+               }
+#endif
+               if (!strncmp(buf, "options", sizeof("options") -1)) {
+                   res_setoptions(buf + sizeof("options") - 1, "conf");
+                   continue;
+               }
            }
            if (nserv > 1) 
                _res.nscount = nserv;
            }
            if (nserv > 1) 
                _res.nscount = nserv;
+#ifdef RESOLVSORT
+           _res.nsort = nsort;
+#endif
            (void) fclose(fp);
            (void) fclose(fp);
-       }
+       } /*if(fopen)*/
        if (_res.defdname[0] == 0) {
        if (_res.defdname[0] == 0) {
-               if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
-                  (cp = strchr(buf, '.')))
+               if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+                  (cp = strchr(buf, '.'))) {
                        (void)strcpy(_res.defdname, cp + 1);
                        (void)strcpy(_res.defdname, cp + 1);
+               }
        }
 
        /* find components of local domain that might be searched */
        if (havesearch == 0) {
                pp = _res.dnsrch;
                *pp++ = _res.defdname;
        }
 
        /* find components of local domain that might be searched */
        if (havesearch == 0) {
                pp = _res.dnsrch;
                *pp++ = _res.defdname;
-               for (cp = _res.defdname, n = 0; *cp; cp++)
-                       if (*cp == '.')
-                               n++;
+               *pp = NULL;
+
+#ifndef RFC1535
+               dots = 0;
+               for (cp = _res.defdname;  *cp;  cp++)
+                       dots += (*cp == '.');
+
                cp = _res.defdname;
                cp = _res.defdname;
-               for (;
-                    n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
-                    n--) {
-                       cp = strchr(cp, '.');
-                       *pp++ = ++cp;
+               while (pp < _res.dnsrch + MAXDFLSRCH) {
+                       if (dots < LOCALDOMAINPARTS) {
+                               break;
+                       }
+                       cp = strchr(cp, '.') + 1;    /* we know there is one */
+                       *pp++ = cp;
+                       dots--;
                }
                }
-               *pp++ = 0;
+               *pp = NULL;
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG) {
+                       printf(";; res_init()... default dnsrch list:\n");
+                       for (pp = _res.dnsrch;  *pp;  pp++) {
+                               printf(";;\t%s\n", *pp);
+                       }
+                       printf(";;\t..END..\n");
+               }
+#endif /*DEBUG*/
+#endif /*!RFC1535*/
+       }
+
+       if ((cp = getenv("RES_OPTIONS")) != NULL) {
+               res_setoptions(cp, "env");
        }
        _res.options |= RES_INIT;
        return (0);
 }
        }
        _res.options |= RES_INIT;
        return (0);
 }
+
+
+static void
+res_setoptions(options, source)
+       char *options, *source;
+{
+       char *cp = options;
+       int i;
+
+#ifdef DEBUG
+       if (_res.options & RES_DEBUG) {
+               printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+                      options, source);
+       }
+#endif
+       while (*cp) {
+               /* skip leading and inner runs of spaces */
+               while (*cp == ' ' || *cp == '\t')
+                       cp++;
+               /* search for and process individual options */
+               if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) {
+                       i = atoi(cp + sizeof("ndots:") - 1);
+                       if (i <= RES_MAXNDOTS)
+                               _res.ndots = i;
+                       else
+                               _res.ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+                       if (_res.options & RES_DEBUG) {
+                               printf(";;\tndots=%d\n", _res.ndots);
+                       }
+#endif
+               } else if (!strncmp(cp, "debug", sizeof("debug")-1)) {
+#ifdef DEBUG
+                       if (!(_res.options & RES_DEBUG)) {
+                               printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+                                      options, source);
+                               _res.options |= RES_DEBUG;
+                       }
+                       printf(";;\tdebug\n");
+#endif
+               } else {
+                       /* XXX - print a warning here? */
+               }
+               /* skip to next run of spaces */
+               while (*cp && *cp != ' ' && *cp != '\t')
+                       cp++;
+       }
+}
+
+#ifdef RESOLVSORT
+static u_int32_t
+net_mask(in)           /* XXX - should really use system's version of this */
+       struct in_addr in;
+{
+        register u_int32_t i = ntohl(in.s_addr);
+
+        if (IN_CLASSA(i))
+                return (htonl(IN_CLASSA_NET));
+        else if (IN_CLASSB(i))
+                return (htonl(IN_CLASSB_NET));
+        else
+                return (htonl(IN_CLASSC_NET));
+}
+#endif
index 8d0e768..ade1ed2 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * ++Copyright++ 1985
+ * ++Copyright++ 1985, 1993
  * -
  * -
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1993
+ *    The Regents of the University of California.  All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_mkquery.c      6.16 (Berkeley) 3/6/91";
+static char sccsid[] = "@(#)res_mkquery.c      8.1 (Berkeley) 6/4/93";
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
-#include <resolv.h>
+
 #include <stdio.h>
 #include <stdio.h>
-#include "../conf/portability.h"
+#include <resolv.h>
+#if defined(BSD) && (BSD >= 199103)
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
 
 /*
  * Form all types of queries.
  * Returns the size of the result or -1.
  */
 
 /*
  * Form all types of queries.
  * Returns the size of the result or -1.
  */
+int
 res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
        int op;                 /* opcode of query */
 res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
        int op;                 /* opcode of query */
-       const char *dname;              /* domain name */
+       const char *dname;      /* domain name */
        int class, type;        /* class and type of query */
        int class, type;        /* class and type of query */
-       const char *data;               /* resource record data */
+       const u_char *data;     /* resource record data */
        int datalen;            /* length of data */
        int datalen;            /* length of data */
-       const char *newrr_in;   /* new rr for modify or append */
-       char *buf;              /* buffer to put query */
+       const u_char *newrr_in; /* new rr for modify or append */
+       u_char *buf;            /* buffer to put query */
        int buflen;             /* size of buffer */
 {
        register HEADER *hp;
        int buflen;             /* size of buffer */
 {
        register HEADER *hp;
-       register char *cp;
+       register u_char *cp;
        register int n;
        struct rrec *newrr = (struct rrec *) newrr_in;
        register int n;
        struct rrec *newrr = (struct rrec *) newrr_in;
-       char *dnptrs[10], **dpp, **lastdnptr;
+       u_char *dnptrs[20], **dpp, **lastdnptr;
 
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
 
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
@@ -93,21 +103,21 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
        /*
         * Initialize header fields.
         */
        /*
         * Initialize header fields.
         */
-       if ((buf == NULL) || (buflen < sizeof(HEADER)))
+       if ((buf == NULL) || (buflen < HFIXEDSZ))
                return(-1);
                return(-1);
-       bzero(buf, sizeof(HEADER));
+       bzero(buf, HFIXEDSZ);
        hp = (HEADER *) buf;
        hp->id = htons(++_res.id);
        hp->opcode = op;
        hp->pr = (_res.options & RES_PRIMARY) != 0;
        hp->rd = (_res.options & RES_RECURSE) != 0;
        hp->rcode = NOERROR;
        hp = (HEADER *) buf;
        hp->id = htons(++_res.id);
        hp->opcode = op;
        hp->pr = (_res.options & RES_PRIMARY) != 0;
        hp->rd = (_res.options & RES_RECURSE) != 0;
        hp->rcode = NOERROR;
-       cp = buf + sizeof(HEADER);
-       buflen -= sizeof(HEADER);
+       cp = buf + HFIXEDSZ;
+       buflen -= HFIXEDSZ;
        dpp = dnptrs;
        *dpp++ = buf;
        *dpp++ = NULL;
        dpp = dnptrs;
        *dpp++ = buf;
        *dpp++ = NULL;
-       lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
+       lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
        /*
         * perform opcode specific processing
         */
        /*
         * perform opcode specific processing
         */
@@ -115,15 +125,14 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
        case QUERY:
                if ((buflen -= QFIXEDSZ) < 0)
                        return(-1);
        case QUERY:
                if ((buflen -= QFIXEDSZ) < 0)
                        return(-1);
-               if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen,
-                   (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
+               if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
                        return (-1);
                cp += n;
                buflen -= n;
                        return (-1);
                cp += n;
                buflen -= n;
-               __putshort(type, (u_char *)cp);
-               cp += sizeof(u_short);
-               __putshort(class, (u_char *)cp);
-               cp += sizeof(u_short);
+               __putshort(type, cp);
+               cp += INT16SZ;
+               __putshort(class, cp);
+               cp += INT16SZ;
                hp->qdcount = htons(1);
                if (op == QUERY || data == NULL)
                        break;
                hp->qdcount = htons(1);
                if (op == QUERY || data == NULL)
                        break;
@@ -131,19 +140,19 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
                 * Make an additional record for completion domain.
                 */
                buflen -= RRFIXEDSZ;
                 * Make an additional record for completion domain.
                 */
                buflen -= RRFIXEDSZ;
-               if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen,
-                   (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
+               n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+               if (n < 0)
                        return (-1);
                cp += n;
                buflen -= n;
                        return (-1);
                cp += n;
                buflen -= n;
-               __putshort(T_NULL, (u_char *)cp);
-               cp += sizeof(u_short);
-               __putshort(class, (u_char *)cp);
-               cp += sizeof(u_short);
-               __putlong(0, (u_char *)cp);
-               cp += sizeof(u_int32_t);
-               __putshort(0, (u_char *)cp);
-               cp += sizeof(u_short);
+               __putshort(T_NULL, cp);
+               cp += INT16SZ;
+               __putshort(class, cp);
+               cp += INT16SZ;
+               __putlong(0, cp);
+               cp += INT32SZ;
+               __putshort(0, cp);
+               cp += INT16SZ;
                hp->arcount = htons(1);
                break;
 
                hp->arcount = htons(1);
                break;
 
@@ -154,14 +163,14 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
                if (buflen < 1 + RRFIXEDSZ + datalen)
                        return (-1);
                *cp++ = '\0';   /* no domain name */
                if (buflen < 1 + RRFIXEDSZ + datalen)
                        return (-1);
                *cp++ = '\0';   /* no domain name */
-               __putshort(type, (u_char *)cp);
-               cp += sizeof(u_short);
-               __putshort(class, (u_char *)cp);
-               cp += sizeof(u_short);
-               __putlong(0, (u_char *)cp);
-               cp += sizeof(u_int32_t);
-               __putshort(datalen, (u_char *)cp);
-               cp += sizeof(u_short);
+               __putshort(type, cp);
+               cp += INT16SZ;
+               __putshort(class, cp);
+               cp += INT16SZ;
+               __putlong(0, cp);
+               cp += INT32SZ;
+               __putshort(datalen, cp);
+               cp += INT16SZ;
                if (datalen) {
                        bcopy(data, cp, datalen);
                        cp += datalen;
                if (datalen) {
                        bcopy(data, cp, datalen);
                        cp += datalen;
@@ -189,13 +198,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
                        return (-1);
                cp += n;
                __putshort(type, cp);
                        return (-1);
                cp += n;
                __putshort(type, cp);
-                cp += sizeof(u_short);
+                cp += INT16SZ;
                 __putshort(class, cp);
                 __putshort(class, cp);
-                cp += sizeof(u_short);
+                cp += INT16SZ;
                __putlong(0, cp);
                __putlong(0, cp);
-               cp += sizeof(u_int32_t);
+               cp += INT32SZ;
                __putshort(datalen, cp);
                __putshort(datalen, cp);
-                cp += sizeof(u_short);
+                cp += INT16SZ;
                if (datalen) {
                        bcopy(data, cp, datalen);
                        cp += datalen;
                if (datalen) {
                        bcopy(data, cp, datalen);
                        cp += datalen;
@@ -212,13 +221,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
                        return (-1);
                cp += n;
                __putshort(newrr->r_type, cp);
                        return (-1);
                cp += n;
                __putshort(newrr->r_type, cp);
-                cp += sizeof(u_short);
+                cp += INT16SZ;
                 __putshort(newrr->r_class, cp);
                 __putshort(newrr->r_class, cp);
-                cp += sizeof(u_short);
+                cp += INT16SZ;
                __putlong(0, cp);
                __putlong(0, cp);
-               cp += sizeof(u_int32_t);
+               cp += INT32SZ;
                __putshort(newrr->r_size, cp);
                __putshort(newrr->r_size, cp);
-                cp += sizeof(u_short);
+                cp += INT16SZ;
                if (newrr->r_size) {
                        bcopy(newrr->r_data, cp, newrr->r_size);
                        cp += newrr->r_size;
                if (newrr->r_size) {
                        bcopy(newrr->r_data, cp, newrr->r_size);
                        cp += newrr->r_size;
index 782e183..7d552df 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * ++Copyright++ 1988
+ * ++Copyright++ 1988, 1993
  * -
  * -
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *    The Regents of the University of California.  All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,7 +54,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_query.c        5.11 (Berkeley) 3/6/91";
+static char sccsid[] = "@(#)res_query.c        8.1 (Berkeley) 6/4/93";
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
@@ -62,12 +62,22 @@ static char rcsid[] = "$Id$";
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
+
+#include <stdio.h>
 #include <netdb.h>
 #include <resolv.h>
 #include <netdb.h>
 #include <resolv.h>
-#include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
 #include <ctype.h>
 #include <errno.h>
-#include "../conf/portability.h"
+#if defined(BSD) && (BSD >= 199306)
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
 
 #if PACKETSZ > 1024
 #define MAXPACKET      PACKETSZ
 
 #if PACKETSZ > 1024
 #define MAXPACKET      PACKETSZ
@@ -75,6 +85,7 @@ static char rcsid[] = "$Id$";
 #define MAXPACKET      1024
 #endif
 
 #define MAXPACKET      1024
 #endif
 
+char *__hostalias __P((const char *));
 int h_errno;
 
 /*
 int h_errno;
 
 /*
@@ -84,27 +95,31 @@ int h_errno;
  * if no error is indicated and the answer count is nonzero.
  * Return the size of the response on success, -1 on error.
  * Error number is left in h_errno.
  * if no error is indicated and the answer count is nonzero.
  * Return the size of the response on success, -1 on error.
  * Error number is left in h_errno.
+ *
  * Caller must parse answer and determine whether it answers the question.
  */
  * Caller must parse answer and determine whether it answers the question.
  */
+int
 res_query(name, class, type, answer, anslen)
 res_query(name, class, type, answer, anslen)
-       char *name;             /* domain name */
+       const char *name;       /* domain name */
        int class, type;        /* class and type of query */
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer buffer */
 {
        int class, type;        /* class and type of query */
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer buffer */
 {
-       char buf[MAXPACKET];
-       HEADER *hp;
+       u_char buf[MAXPACKET];
+       register HEADER *hp = (HEADER *) answer;
        int n;
 
        int n;
 
+       hp->rcode = NOERROR;    /* default */
+
        if ((_res.options & RES_INIT) == 0 && res_init() == -1)
                return (-1);
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
                printf(";; res_query(%s, %d, %d)\n", name, class, type);
 #endif
        if ((_res.options & RES_INIT) == 0 && res_init() == -1)
                return (-1);
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
                printf(";; res_query(%s, %d, %d)\n", name, class, type);
 #endif
-       n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
-           buf, sizeof(buf));
 
 
+       n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
+                       buf, sizeof(buf));
        if (n <= 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
        if (n <= 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
@@ -113,17 +128,16 @@ res_query(name, class, type, answer, anslen)
                h_errno = NO_RECOVERY;
                return (n);
        }
                h_errno = NO_RECOVERY;
                return (n);
        }
-       n = res_send(buf, n, (char *)answer, anslen);
+       n = res_send(buf, n, answer, anslen);
        if (n < 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
                        printf(";; res_query: send error\n");
 #endif
                h_errno = TRY_AGAIN;
        if (n < 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
                        printf(";; res_query: send error\n");
 #endif
                h_errno = TRY_AGAIN;
-               return(n);
+               return (n);
        }
 
        }
 
-       hp = (HEADER *) answer;
        if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
        if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
@@ -149,86 +163,148 @@ res_query(name, class, type, answer, anslen)
                }
                return (-1);
        }
                }
                return (-1);
        }
-       return(n);
+       return (n);
 }
 
 /*
  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  * Return the size of the response on success, -1 on error.
  * If enabled, implement search rules until answer or unrecoverable failure
 }
 
 /*
  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  * Return the size of the response on success, -1 on error.
  * If enabled, implement search rules until answer or unrecoverable failure
- * is detected.  Error number is left in h_errno.
- * Only useful for queries in the same name hierarchy as the local host
- * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
+ * is detected.  Error code, if any, is left in h_errno.
  */
 int
 res_search(name, class, type, answer, anslen)
  */
 int
 res_search(name, class, type, answer, anslen)
-       char *name;             /* domain name */
+       const char *name;       /* domain name */
        int class, type;        /* class and type of query */
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer */
 {
        int class, type;        /* class and type of query */
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer */
 {
-       register char *cp, **domain;
-       int n, ret, got_nodata = 0;
-       char *__hostalias();
+       register const char *cp, * const *domain;
+       HEADER *hp = (HEADER *) answer;
+       u_int dots;
+       int trailing_dot, ret, saved_herrno;
+       int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
 
        if ((_res.options & RES_INIT) == 0 && res_init() == -1)
                return (-1);
 
        errno = 0;
        h_errno = HOST_NOT_FOUND;       /* default, if we never query */
 
        if ((_res.options & RES_INIT) == 0 && res_init() == -1)
                return (-1);
 
        errno = 0;
        h_errno = HOST_NOT_FOUND;       /* default, if we never query */
-       for (cp = name, n = 0;  *cp;  cp++)
-               if (*cp == '.')
-                       n++;
-       if (n == 0 && (cp = __hostalias(name)))
+       dots = 0;
+       for (cp = name;  *cp;  cp++)
+               dots += (*cp == '.');
+       trailing_dot = 0;
+       if ((cp > name) && (*--cp == '.'))
+               trailing_dot++;
+
+       /*
+        * if there aren't any dots, it could be a user-level alias
+        */
+       if ((!dots) && (cp = __hostalias(name)))
                return (res_query(cp, class, type, answer, anslen));
 
        /*
                return (res_query(cp, class, type, answer, anslen));
 
        /*
+        * If there are dots in the name already, let's just give it a try
+        * 'as is'.  The threshold can be set with the "ndots" option.
+        */
+       saved_herrno = -1;
+       if (dots >= _res.ndots) {
+               ret = res_querydomain(name, NULL, class, type, answer, anslen);
+               if (ret > 0)
+                       return (ret);
+               saved_herrno = h_errno;
+               tried_as_is++;
+       }
+
+       /*
         * We do at least one level of search if
         *      - there is no dot and RES_DEFNAME is set, or
         *      - there is at least one dot, there is no trailing dot,
         *        and RES_DNSRCH is set.
         */
         * We do at least one level of search if
         *      - there is no dot and RES_DEFNAME is set, or
         *      - there is at least one dot, there is no trailing dot,
         *        and RES_DNSRCH is set.
         */
-       if ((n == 0 && _res.options & RES_DEFNAMES) ||
-          (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
-            for (domain = _res.dnsrch; *domain; domain++) {
-               ret = res_querydomain(name, *domain, class, type,
-                   answer, anslen);
+       if (((!dots) && _res.options & RES_DEFNAMES) ||
+           (dots && (!trailing_dot) && _res.options & RES_DNSRCH)
+           ) {
+               int done = 0;
+
+               for (domain = (const char * const *)_res.dnsrch;
+                    *domain && !done;
+                    domain++) {
+
+                       ret = res_querydomain(name, *domain, class, type,
+                                             answer, anslen);
+                       if (ret > 0)
+                               return (ret);
+
+                       /*
+                        * If no server present, give up.
+                        * If name isn't found in this domain,
+                        * keep trying higher domains in the search list
+                        * (if that's enabled).
+                        * On a NO_DATA error, keep trying, otherwise
+                        * a wildcard entry of another type could keep us
+                        * from finding this entry higher in the domain.
+                        * If we get some other error (negative answer or
+                        * server failure), then stop searching up,
+                        * but try the input name below in case it's
+                        * fully-qualified.
+                        */
+                       if (errno == ECONNREFUSED) {
+                               h_errno = TRY_AGAIN;
+                               return (-1);
+                       }
+
+                       switch (h_errno) {
+                       case NO_DATA:
+                               got_nodata++;
+                               /* FALLTHROUGH */
+                       case HOST_NOT_FOUND:
+                               /* keep trying */
+                               break;
+                       case TRY_AGAIN:
+                               if (hp->rcode == SERVFAIL) {
+                                       /* try next search element, if any */
+                                       got_servfail++;
+                                       break;
+                               }
+                               /* FALLTHROUGH */
+                       default:
+                               /* anything else implies that we're done */
+                               done++;
+                       }
+
+                       /* if we got here for some reason other than DNSRCH,
+                        * we only wanted one iteration of the loop, so stop.
+                        */
+                       if (!(_res.options & RES_DNSRCH))
+                               done++;
+               }
+       }
+
+       /* if we have not already tried the name "as is", do that now.
+        * note that we do this regardless of how many dots were in the
+        * name or whether it ends with a dot.
+        */
+       if (!tried_as_is) {
+               ret = res_querydomain(name, NULL, class, type, answer, anslen);
                if (ret > 0)
                        return (ret);
                if (ret > 0)
                        return (ret);
-               /*
-                * If no server present, give up.
-                * If name isn't found in this domain,
-                * keep trying higher domains in the search list
-                * (if that's enabled).
-                * On a NO_DATA error, keep trying, otherwise
-                * a wildcard entry of another type could keep us
-                * from finding this entry higher in the domain.
-                * If we get some other error (negative answer or
-                * server failure), then stop searching up,
-                * but try the input name below in case it's fully-qualified.
-                */
-               if (errno == ECONNREFUSED) {
-                       h_errno = TRY_AGAIN;
-                       return (-1);
-               }
-               if (h_errno == NO_DATA)
-                       got_nodata++;
-               if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
-                   (_res.options & RES_DNSRCH) == 0)
-                       break;
+               saved_herrno = h_errno;
        }
        }
-       /*
-        * If the search/default failed, try the name as fully-qualified,
-        * but only if it contained at least one dot (even trailing).
-        * This is purely a heuristic; we assume that any reasonable query
-        * about a top-level domain (for servers, SOA, etc) will not use
-        * res_search.
+
+       /* if we got here, we didn't satisfy the search.
+        * if we did an initial full query, return that query's h_errno
+        * (note that we wouldn't be here if that query had succeeded).
+        * else if we ever got a nodata, send that back as the reason.
+        * else send back meaningless h_errno, that being the one from
+        * the last DNSRCH we did.
         */
         */
-       if (n && (ret = res_querydomain(name, (char *)NULL, class, type,
-           answer, anslen)) > 0)
-               return (ret);
-       if (got_nodata)
+       if (saved_herrno != -1)
+               h_errno = saved_herrno;
+       else if (got_nodata)
                h_errno = NO_DATA;
                h_errno = NO_DATA;
+       else if (got_servfail)
+               h_errno = TRY_AGAIN;
        return (-1);
 }
 
        return (-1);
 }
 
@@ -236,20 +312,21 @@ res_search(name, class, type, answer, anslen)
  * Perform a call on res_query on the concatenation of name and domain,
  * removing a trailing dot from name if domain is NULL.
  */
  * Perform a call on res_query on the concatenation of name and domain,
  * removing a trailing dot from name if domain is NULL.
  */
+int
 res_querydomain(name, domain, class, type, answer, anslen)
 res_querydomain(name, domain, class, type, answer, anslen)
-       char *name, *domain;
+       const char *name, *domain;
        int class, type;        /* class and type of query */
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer */
 {
        char nbuf[2*MAXDNAME+2];
        int class, type;        /* class and type of query */
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer */
 {
        char nbuf[2*MAXDNAME+2];
-       char *longname = nbuf;
+       const char *longname = nbuf;
        int n;
 
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
                printf(";; res_querydomain(%s, %s, %d, %d)\n",
        int n;
 
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
                printf(";; res_querydomain(%s, %s, %d, %d)\n",
-                   name, domain, class, type);
+                      name, domain?domain:"<Nil>", class, type);
 #endif
        if (domain == NULL) {
                /*
 #endif
        if (domain == NULL) {
                /*
@@ -257,14 +334,15 @@ res_querydomain(name, domain, class, type, answer, anslen)
                 * copy without '.' if present.
                 */
                n = strlen(name) - 1;
                 * copy without '.' if present.
                 */
                n = strlen(name) - 1;
-               if (name[n] == '.' && n < sizeof(nbuf) - 1) {
+               if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
                        bcopy(name, nbuf, n);
                        nbuf[n] = '\0';
                } else
                        longname = name;
                        bcopy(name, nbuf, n);
                        nbuf[n] = '\0';
                } else
                        longname = name;
-       } else
-               (void)sprintf(nbuf, "%.*s.%.*s",
-                   MAXDNAME, name, MAXDNAME, domain);
+       } else {
+               sprintf(nbuf, "%.*s.%.*s",
+                       MAXDNAME, name, MAXDNAME, domain);
+       }
 
        return (res_query(longname, class, type, answer, anslen));
 }
 
        return (res_query(longname, class, type, answer, anslen));
 }
@@ -273,9 +351,9 @@ char *
 __hostalias(name)
        register const char *name;
 {
 __hostalias(name)
        register const char *name;
 {
-       register char *C1, *C2;
+       register char *cp1, *cp2;
        FILE *fp;
        FILE *fp;
-       char *file, *getenv(), *strcpy(), *strncpy();
+       char *file;
        char buf[BUFSIZ];
        static char abuf[MAXDNAME];
 
        char buf[BUFSIZ];
        static char abuf[MAXDNAME];
 
@@ -284,17 +362,17 @@ __hostalias(name)
                return (NULL);
        buf[sizeof(buf) - 1] = '\0';
        while (fgets(buf, sizeof(buf), fp)) {
                return (NULL);
        buf[sizeof(buf) - 1] = '\0';
        while (fgets(buf, sizeof(buf), fp)) {
-               for (C1 = buf; *C1 && !isspace(*C1); ++C1);
-               if (!*C1)
+               for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1);
+               if (!*cp1)
                        break;
                        break;
-               *C1 = '\0';
+               *cp1 = '\0';
                if (!strcasecmp(buf, name)) {
                if (!strcasecmp(buf, name)) {
-                       while (isspace(*++C1));
-                       if (!*C1)
+                       while (isspace(*++cp1));
+                       if (!*cp1)
                                break;
                                break;
-                       for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
-                       abuf[sizeof(abuf) - 1] = *C2 = '\0';
-                       (void)strncpy(abuf, C1, sizeof(abuf) - 1);
+                       for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2);
+                       abuf[sizeof(abuf) - 1] = *cp2 = '\0';
+                       (void)strncpy(abuf, cp1, sizeof(abuf) - 1);
                        fclose(fp);
                        return (abuf);
                }
                        fclose(fp);
                        return (abuf);
                }
index 65763fd..9a3bafe 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * ++Copyright++ 1985, 1989
+ * ++Copyright++ 1985, 1989, 1993
  * -
  * -
- * Copyright (c) 1985, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_send.c 6.27 (Berkeley) 2/24/91";
+static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
+       /* change this to "0"
+        * if you talk to a lot
+        * of multi-homed SunOS
+        * ("broken") name servers.
+        */
+#define        CHECK_SRVR_ADDR 1       /* XXX - should be in options.h */
+
 /*
  * Send query to name server and wait for reply.
  */
 /*
  * Send query to name server and wait for reply.
  */
@@ -69,15 +76,29 @@ static char rcsid[] = "$Id$";
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
+
 #include <stdio.h>
 #include <errno.h>
 #include <resolv.h>
 #include <stdio.h>
 #include <errno.h>
 #include <resolv.h>
-#include "../conf/portability.h"
+#if defined(BSD) && (BSD >= 199306)
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
+
+void _res_close __P((void));
 
 static int s = -1;     /* socket used for communications */
 
 static int s = -1;     /* socket used for communications */
-static struct sockaddr no_addr;
+static int connected = 0;      /* is the socket connected */
+static int vc = 0;     /* is the socket a virtual ciruit? */
 
 #ifndef FD_SET
 
 #ifndef FD_SET
+/* XXX - should be in portability.h */
 #define        NFDBITS         32
 #define        FD_SETSIZE      32
 #define        FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
 #define        NFDBITS         32
 #define        FD_SETSIZE      32
 #define        FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
@@ -86,121 +107,310 @@ static struct sockaddr no_addr;
 #define FD_ZERO(p)     bzero((char *)(p), sizeof(*(p)))
 #endif
 
 #define FD_ZERO(p)     bzero((char *)(p), sizeof(*(p)))
 #endif
 
-res_send(buf, buflen, answer, anslen)
-       const char *buf;
-       int buflen;
-       char *answer;
-       int anslen;
-{
-       register int n;
-       int try, v_circuit, resplen, ns;
-       int gotsomewhere = 0, connected = 0;
-       int connreset = 0;
-       u_short id, len;
-       char *cp;
-       fd_set dsmask;
-       struct timeval timeout;
-       HEADER *hp = (HEADER *) buf;
-       HEADER *anhp = (HEADER *) answer;
-       u_int badns;            /* XXX NSMAX can't exceed #/bits per this */
-       struct iovec iov[2];
-       int terrno = ETIMEDOUT;
-       char junk[512];
-
-#ifdef DEBUG
-       if ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY)) {
-               printf(";; res_send()\n");
-               __p_query(buf);
+#ifndef DEBUG
+#   define Dprint(cond, args) /*empty*/
+#   define DprintQ(cond, args, query) /*empty*/
+#   define Aerror(file, string, error, address) /*empty*/
+#   define Perror(file, string, error) /*empty*/
+#else
+#   define Dprint(cond, args) if (cond) {fprintf args;} else {}
+#   define DprintQ(cond, args, query) if (cond) {\
+                       fprintf args;\
+                       __p_query(query);\
+               } else {}
+    static void
+    Aerror(file, string, error, address)
+       FILE *file;
+       char *string;
+       int error;
+       struct sockaddr_in address;
+    {
+       int save = errno;
+
+       if (_res.options & RES_DEBUG) {
+               fprintf(file, "res_send: %s ([%s].%d): %s\n",
+                       string,
+                       inet_ntoa(address.sin_addr),
+                       address.sin_port,
+                       strerror(error));
+       }
+       errno = save;
+    }
+    static void
+    Perror(file, string, error)
+       FILE *file;
+       char *string;
+       int error;
+    {
+       int save = errno;
+
+       if (_res.options & RES_DEBUG) {
+               fprintf(file, "res_send: %s: %s\n",
+                       string, strerror(error));
        }
        }
+       errno = save;
+    }
 #endif
 #endif
-       if (!(_res.options & RES_INIT))
-               if (res_init() == -1) {
-                       return(-1);
+
+static res_send_qhook Qhook = NULL;
+static res_send_rhook Rhook = NULL;
+
+void
+res_send_setqhook(hook)
+       res_send_qhook hook;
+{
+       Qhook = hook;
+}
+
+void
+res_send_setrhook(hook)
+       res_send_rhook hook;
+{
+       Rhook = hook;
+}
+
+/* int
+ * our_server(ina)
+ *     looks up "ina" in _res.ns_addr_list[]
+ * returns:
+ *     0  : not found
+ *     >0 : found
+ * author:
+ *     paul vixie, 29may94
+ */
+static int
+our_server(inp)
+       const struct sockaddr_in *inp;
+{
+       struct sockaddr_in ina;
+       register int ns, ret;
+
+       ina = *inp;
+       ret = 0;
+       for (ns = 0;  ns < _res.nscount;  ns++) {
+               register const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
+
+               if (srv->sin_family == ina.sin_family &&
+                   srv->sin_port == ina.sin_port &&
+                   (srv->sin_addr.s_addr == INADDR_ANY ||
+                    srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
+                       ret++;
+                       break;
                }
                }
+       }
+       return (ret);
+}
+
+/* int
+ * name_in_query(name, type, class, buf, eom)
+ *     look for (name,type,class) in the query section of packet (buf,eom)
+ * returns:
+ *     -1 : format error
+ *     0  : not found
+ *     >0 : found
+ */
+static int
+name_in_query(name, type, class, buf, eom)
+       const char *name;
+       register int type, class;
+       const u_char *buf, *eom;
+{
+       register const u_char *cp = buf + HFIXEDSZ;
+       int qdcount = ntohs(((HEADER*)buf)->qdcount);
+
+       while (qdcount-- > 0) {
+               char tname[MAXDNAME+1];
+               register int n, ttype, tclass;
+
+               n = dn_expand(buf, eom, cp, tname, sizeof tname);
+               if (n < 0)
+                       return (-1);
+               cp += n;
+               ttype = _getshort(cp);  cp += INT16SZ;
+               tclass = _getshort(cp); cp += INT16SZ;
+               if (ttype == type &&
+                   tclass == class &&
+                   strcasecmp(tname, name) == 0)
+                       return (1);
+       }
+       return (0);
+}
+
+/* int
+ * queries_match(buf1, eom1, buf2, eom2)
+ *     is there a 1:1 mapping of (name,type,class)
+ *     in (buf1,eom1) and (buf2,eom2)?
+ * returns:
+ *     -1 : format error
+ *     0  : not a 1:1 mapping
+ *     >0 : is a 1:1 mapping
+ */
+static int
+queries_match(buf1, eom1, buf2, eom2)
+       const u_char *buf1, *eom1;
+       const u_char *buf2, *eom2;
+{
+       register const u_char *cp = buf1 + HFIXEDSZ;
+       int qdcount = ntohs(((HEADER*)buf1)->qdcount);
+
+       if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
+               return (0);
+       while (qdcount-- > 0) {
+               char tname[MAXDNAME+1];
+               register int n, ttype, tclass;
+
+               n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+               if (n < 0)
+                       return (-1);
+               cp += n;
+               ttype = _getshort(cp);  cp += INT16SZ;
+               tclass = _getshort(cp); cp += INT16SZ;
+               if (!name_in_query(tname, ttype, tclass, buf2, eom2))
+                       return (0);
+       }
+       return (1);
+}
+
+int
+res_send(buf, buflen, ans, anssiz)
+       const u_char    *buf;
+       int             buflen;
+       u_char          *ans;
+       int             anssiz;
+{
+       HEADER          *hp = (HEADER *) buf;
+       HEADER          *anhp = (HEADER *) ans;
+       int             gotsomewhere = 0,
+                       connreset = 0,
+                       terrno = ETIMEDOUT;
+
+       register int    n;
+       int             try, v_circuit, resplen, ns;
+       u_int           badns;  /* XXX NSMAX can't exceed #/bits in this var */
+
+       DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
+               (stdout, ";; res_send()\n"), buf);
+       if (!(_res.options & RES_INIT)) {
+               if (res_init() == -1)
+                       return (-1);
+       }
        v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
        v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
-       id = hp->id;
        badns = 0;
        badns = 0;
+
        /*
         * Send request, RETRY times, or until successful
         */
        for (try = 0; try < _res.retry; try++) {
            for (ns = 0; ns < _res.nscount; ns++) {
        /*
         * Send request, RETRY times, or until successful
         */
        for (try = 0; try < _res.retry; try++) {
            for (ns = 0; ns < _res.nscount; ns++) {
-               if (badns & (1<<ns))
-                       continue;
-#ifdef DEBUG
-               if (_res.options & RES_DEBUG)
-                       printf(";; Querying server (# %d) address = %s\n",
-                              ns+1,
-                              inet_ntoa(_res.nsaddr_list[ns].sin_addr));
-#endif
-       usevc:
+               struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+    same_ns:
+               if (badns & (1<<ns)) {
+                       _res_close();
+                       goto next_ns;
+               }
+
+               if (Qhook) {
+                       int done = 0, loops = 0;
+
+                       do {
+                               res_sendhookact act;
+
+                               act = (*Qhook)(&nsap,
+                                              &buf,
+                                              &buflen,
+                                              ans,
+                                              anssiz,
+                                              &resplen);
+                               switch (act) {
+                               case res_goahead:
+                                       done = 1;
+                                       break;
+                               case res_nextns:
+                                       _res_close();
+                                       goto next_ns;
+                               case res_done:
+                                       return (resplen);
+                               case res_modified:
+                                       /* give the hook another try */
+                                       if (++loops < 42) /*doug adams*/
+                                               break;
+                                       /*FALLTHROUGH*/
+                               case res_error:
+                                       /*FALLTHROUGH*/
+                               default:
+                                       return (-1);
+                               }
+                       } while (!done);
+               }
+
+               Dprint(_res.options & RES_DEBUG,
+                      (stdout, ";; Querying server (# %d) address = %s\n",
+                       ns+1, inet_ntoa(nsap->sin_addr)));
+
                if (v_circuit) {
                if (v_circuit) {
-                       int truncated = 0;
+                       int             truncated;
+                       struct iovec    iov[2];
+                       u_short         len;
+                       u_char          *cp;
 
                        /*
                         * Use virtual circuit;
                         * at most one attempt per server.
                         */
                        try = _res.retry;
 
                        /*
                         * Use virtual circuit;
                         * at most one attempt per server.
                         */
                        try = _res.retry;
-                       if (s < 0) {
-                               s = socket(AF_INET, SOCK_STREAM, 0);
+                       truncated = 0;
+                       if ((s < 0) || (!vc)) {
+                               if (s >= 0)
+                                       _res_close();
+
+                               s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);
                                if (s < 0) {
                                        terrno = errno;
                                if (s < 0) {
                                        terrno = errno;
-#ifdef DEBUG
-                                       if (_res.options & RES_DEBUG)
-                                           perror("socket (vc) failed");
-#endif
-                                       continue;
+                                       Perror(stderr, "socket(vc)", errno);
+                                       return (-1);
                                }
                                if (connect(s,
                                }
                                if (connect(s,
-                                   (struct sockaddr *)&(_res.nsaddr_list[ns]),
-                                   sizeof(struct sockaddr)) < 0) {
+                                           (struct sockaddr *)nsap,
+                                           sizeof(struct sockaddr))
+                                   < 0) {
                                        terrno = errno;
                                        terrno = errno;
-#ifdef DEBUG
-                                       if (_res.options & RES_DEBUG)
-                                           perror("connect failed");
-#endif
-                                       (void) close(s);
-                                       s = -1;
-                                       continue;
+                                       Aerror(stderr, "connect/vc",
+                                              errno, *nsap);
+                                       badns |= (1<<ns);
+                                       _res_close();
+                                       goto next_ns;
                                }
                                }
+                               vc = 1;
                        }
                        /*
                         * Send length & message
                         */
                        }
                        /*
                         * Send length & message
                         */
-                       len = htons((u_short)buflen);
+                       putshort((u_short)buflen, (u_char*)&len);
                        iov[0].iov_base = (caddr_t)&len;
                        iov[0].iov_base = (caddr_t)&len;
-                       iov[0].iov_len = sizeof(len);
-                       iov[1].iov_base = (char *)buf;
+                       iov[0].iov_len = INT16SZ;
+                       iov[1].iov_base = (caddr_t)buf;
                        iov[1].iov_len = buflen;
                        iov[1].iov_len = buflen;
-                       if (writev(s, iov, 2) != sizeof(len) + buflen) {
+                       if (writev(s, iov, 2) != (INT16SZ + buflen)) {
                                terrno = errno;
                                terrno = errno;
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       perror("write failed");
-#endif
-                               (void) close(s);
-                               s = -1;
-                               continue;
+                               Perror(stderr, "write failed", errno);
+                               badns |= (1<<ns);
+                               _res_close();
+                               goto next_ns;
                        }
                        /*
                         * Receive length & response
                         */
                        }
                        /*
                         * Receive length & response
                         */
-                       cp = answer;
-                       len = sizeof(short);
-                       while (len != 0 &&
-                           (n = read(s, (char *)cp, (int)len)) > 0) {
+                       cp = ans;
+                       len = INT16SZ;
+                       while ((n = read(s, (char *)cp, (int)len)) > 0) {
                                cp += n;
                                cp += n;
-                               len -= n;
+                               if ((len -= n) <= 0)
+                                       break;
                        }
                        if (n <= 0) {
                                terrno = errno;
                        }
                        if (n <= 0) {
                                terrno = errno;
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       perror("read failed");
-#endif
-                               (void) close(s);
-                               s = -1;
+                               Perror(stderr, "read failed", errno);
+                               _res_close();
                                /*
                                 * A long running process might get its TCP
                                 * connection reset if the remote server was
                                /*
                                 * A long running process might get its TCP
                                 * connection reset if the remote server was
@@ -212,35 +422,33 @@ res_send(buf, buflen, answer, anslen)
                                 */
                                if (terrno == ECONNRESET && !connreset) {
                                        connreset = 1;
                                 */
                                if (terrno == ECONNRESET && !connreset) {
                                        connreset = 1;
-                                       ns--;
+                                       _res_close();
+                                       goto same_ns;
                                }
                                }
-                               continue;
+                               _res_close();
+                               goto next_ns;
                        }
                        }
-                       cp = answer;
-                       if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       fprintf(stderr,
-                                               ";; response truncated\n");
-#endif
-                               len = anslen;
+                       resplen = _getshort(ans);
+                       if (resplen > anssiz) {
+                               Dprint(_res.options & RES_DEBUG,
+                                      (stdout, ";; response truncated\n")
+                                      );
                                truncated = 1;
                                truncated = 1;
+                               len = anssiz;
                        } else
                                len = resplen;
                        } else
                                len = resplen;
+                       cp = ans;
                        while (len != 0 &&
                        while (len != 0 &&
-                          (n = read(s, (char *)cp, (int)len)) > 0) {
+                              (n = read(s, (char *)cp, (int)len)) > 0
+                              ) {
                                cp += n;
                                len -= n;
                        }
                        if (n <= 0) {
                                terrno = errno;
                                cp += n;
                                len -= n;
                        }
                        if (n <= 0) {
                                terrno = errno;
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       perror("read failed");
-#endif
-                               (void) close(s);
-                               s = -1;
-                               continue;
+                               Perror(stderr, "read(vc)", errno);
+                               _res_close();
+                               goto next_ns;
                        }
                        if (truncated) {
                                /*
                        }
                        if (truncated) {
                                /*
@@ -248,10 +456,13 @@ res_send(buf, buflen, answer, anslen)
                                 * so connection stays in synch.
                                 */
                                anhp->tc = 1;
                                 * so connection stays in synch.
                                 */
                                anhp->tc = 1;
-                               len = resplen - anslen;
+                               len = resplen - anssiz;
                                while (len != 0) {
                                while (len != 0) {
-                                       n = (len > sizeof(junk) ?
-                                           sizeof(junk) : len);
+                                       char junk[512];
+
+                                       n = (len > sizeof(junk)
+                                            ? sizeof(junk)
+                                            : len);
                                        if ((n = read(s, junk, n)) > 0)
                                                len -= n;
                                        else
                                        if ((n = read(s, junk, n)) > 0)
                                                len -= n;
                                        else
@@ -262,20 +473,23 @@ res_send(buf, buflen, answer, anslen)
                        /*
                         * Use datagrams.
                         */
                        /*
                         * Use datagrams.
                         */
-                       if (s < 0) {
-                               s = socket(AF_INET, SOCK_DGRAM, 0);
+                       struct timeval  timeout;
+                       fd_set          dsmask;
+                       struct sockaddr_in from;
+                       int             fromlen;
+
+                       if ((s < 0) || vc) {
+                               if (vc)
+                                       _res_close();
+                               s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
                                if (s < 0) {
                                if (s < 0) {
-                                       terrno = errno;
-#ifdef DEBUG
-                                       if (_res.options & RES_DEBUG)
-                                           perror("socket (dg) failed");
-#endif
-                                       continue;
+ bad_dg_sock:                          terrno = errno;
+                                       Perror(stderr, "socket(dg)", errno);
+                                       return (-1);
                                }
                                }
+                               connected = 0;
                        }
                        }
-#if    BSD >= 43
                        /*
                        /*
-                        * I'm tired of answering this question, so:
                         * On a 4.3BSD+ machine (client and server,
                         * actually), sending to a nameserver datagram
                         * port with no nameserver will cause an
                         * On a 4.3BSD+ machine (client and server,
                         * actually), sending to a nameserver datagram
                         * port with no nameserver will cause an
@@ -292,30 +506,29 @@ res_send(buf, buflen, answer, anslen)
                         */
                        if (_res.nscount == 1 || (try == 0 && ns == 0)) {
                                /*
                         */
                        if (_res.nscount == 1 || (try == 0 && ns == 0)) {
                                /*
-                                * Don't use connect if we might
-                                * still receive a response
-                                * from another server.
+                                * Connect only if we are sure we won't
+                                * receive a response from another server.
                                 */
                                 */
-                               if (connected == 0) {
+                               if (!connected) {
                                        if (connect(s,
                                        if (connect(s,
-                                                   (struct sockaddr *)
-                                                        &_res.nsaddr_list[ns],
+                                                   (struct sockaddr *)nsap,
                                                    sizeof(struct sockaddr)
                                                    sizeof(struct sockaddr)
-                                                   ) < 0) {
-#ifdef DEBUG
-                                               if (_res.options & RES_DEBUG)
-                                                       perror("connect");
-#endif
-                                               continue;
+                                                   ) < 0
+                                           ) {
+                                               Aerror(stderr,
+                                                      "connect(dg)",
+                                                      errno, *nsap);
+                                               badns |= (1<<ns);
+                                               _res_close();
+                                               goto next_ns;
                                        }
                                        connected = 1;
                                }
                                if (send(s, buf, buflen, 0) != buflen) {
                                        }
                                        connected = 1;
                                }
                                if (send(s, buf, buflen, 0) != buflen) {
-#ifdef DEBUG
-                                       if (_res.options & RES_DEBUG)
-                                               perror("send");
-#endif
-                                       continue;
+                                       Perror(stderr, "send", errno);
+                                       badns |= (1<<ns);
+                                       _res_close();
+                                       goto next_ns;
                                }
                        } else {
                                /*
                                }
                        } else {
                                /*
@@ -323,23 +536,39 @@ res_send(buf, buflen, answer, anslen)
                                 * for responses from more than one server.
                                 */
                                if (connected) {
                                 * for responses from more than one server.
                                 */
                                if (connected) {
-                                       (void) connect(s, &no_addr,
-                                           sizeof(no_addr));
+#if defined(BSD) && (BSD >= 199103)
+                                       struct sockaddr_in no_addr;
+
+                                       no_addr.sin_family = AF_INET;
+                                       no_addr.sin_addr.s_addr = INADDR_ANY;
+                                       no_addr.sin_port = 0;
+                                       (void) connect(s,
+                                                      (struct sockaddr *)
+                                                       &no_addr,
+                                                      sizeof(no_addr));
+#else
+                                       int s1 = socket(AF_INET, SOCK_DGRAM,
+                                                       PF_UNSPEC);
+                                       if (s1 < 0)
+                                               goto bad_dg_sock;
+                                       (void) dup2(s1, s);
+                                       (void) close(s1);
+                                       Dprint(_res.options & RES_DEBUG,
+                                              (stdout, ";; new DG socket\n"))
+#endif
                                        connected = 0;
                                        connected = 0;
+                                       errno = 0;
                                }
                                }
-#endif /* BSD */
                                if (sendto(s, buf, buflen, 0,
                                if (sendto(s, buf, buflen, 0,
-                                   (struct sockaddr *)&_res.nsaddr_list[ns],
-                                   sizeof(struct sockaddr)) != buflen) {
-#ifdef DEBUG
-                                       if (_res.options & RES_DEBUG)
-                                               perror("sendto");
-#endif
-                                       continue;
+                                          (struct sockaddr *)nsap,
+                                          sizeof(struct sockaddr))
+                                   != buflen) {
+                                       Aerror(stderr, "sendto", errno, *nsap);
+                                       badns |= (1<<ns);
+                                       _res_close();
+                                       goto next_ns;
                                }
                                }
-#if    BSD >= 43
                        }
                        }
-#endif
 
                        /*
                         * Wait for reply
 
                        /*
                         * Wait for reply
@@ -350,115 +579,162 @@ res_send(buf, buflen, answer, anslen)
                        if ((long) timeout.tv_sec <= 0)
                                timeout.tv_sec = 1;
                        timeout.tv_usec = 0;
                        if ((long) timeout.tv_sec <= 0)
                                timeout.tv_sec = 1;
                        timeout.tv_usec = 0;
-wait:
+    wait:
                        FD_ZERO(&dsmask);
                        FD_SET(s, &dsmask);
                        n = select(s+1, &dsmask, (fd_set *)NULL,
                        FD_ZERO(&dsmask);
                        FD_SET(s, &dsmask);
                        n = select(s+1, &dsmask, (fd_set *)NULL,
-                               (fd_set *)NULL, &timeout);
+                                  (fd_set *)NULL, &timeout);
                        if (n < 0) {
                        if (n < 0) {
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       perror("select");
-#endif
-                               continue;
+                               Perror(stderr, "select", errno);
+                               _res_close();
+                               goto next_ns;
                        }
                        if (n == 0) {
                                /*
                                 * timeout
                                 */
                        }
                        if (n == 0) {
                                /*
                                 * timeout
                                 */
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       printf(";; timeout\n");
-#endif
-#if BSD >= 43
+                               Dprint(_res.options & RES_DEBUG,
+                                      (stdout, ";; timeout\n")
+                                      );
                                gotsomewhere = 1;
                                gotsomewhere = 1;
-#endif
-                               continue;
+                               _res_close();
+                               goto next_ns;
                        }
                        }
-                       if ((resplen = recv(s, answer, anslen, 0)) <= 0) {
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       perror("recvfrom");
-#endif
-                               continue;
+                       fromlen = sizeof(struct sockaddr_in);
+                       resplen = recvfrom(s, ans, anssiz, 0,
+                                          (struct sockaddr *)&from, &fromlen);
+                       if (resplen <= 0) {
+                               Perror(stderr, "recvfrom", errno);
+                               _res_close();
+                               goto next_ns;
                        }
                        gotsomewhere = 1;
                        }
                        gotsomewhere = 1;
-                       if (id != anhp->id) {
+                       if (hp->id != anhp->id) {
                                /*
                                /*
-                                * response from old query, ignore it
+                                * response from old query, ignore it.
+                                * XXX - potential security hazard could
+                                *       be detected here.
                                 */
                                 */
-#ifdef DEBUG
-                               if ((_res.options & RES_DEBUG) ||
-                                   (_res.pfcode & RES_PRF_REPLY)) {
-                                       printf(";; old answer:\n");
-                                       __p_query(answer);
-                               }
+                               DprintQ((_res.options & RES_DEBUG) ||
+                                       (_res.pfcode & RES_PRF_REPLY),
+                                       (stdout, ";; old answer:\n"),
+                                       ans);
+                               goto wait;
+                       }
+#if CHECK_SRVR_ADDR
+                       if (!(_res.options & RES_INSECURE1) &&
+                           !our_server(&from)) {
+                               /*
+                                * response from wrong server? ignore it.
+                                * XXX - potential security hazard could
+                                *       be detected here.
+                                */
+                               DprintQ((_res.options & RES_DEBUG) ||
+                                       (_res.pfcode & RES_PRF_REPLY),
+                                       (stdout, ";; not our server:\n"),
+                                       ans);
+                               goto wait;
+                       }
 #endif
 #endif
+                       if (!(_res.options & RES_INSECURE2) &&
+                           !queries_match(buf, buf + buflen,
+                                          ans, ans + anssiz)) {
+                               /*
+                                * response contains wrong query? ignore it.
+                                * XXX - potential security hazard could
+                                *       be detected here.
+                                */
+                               DprintQ((_res.options & RES_DEBUG) ||
+                                       (_res.pfcode & RES_PRF_REPLY),
+                                       (stdout, ";; wrong query name:\n"),
+                                       ans);
                                goto wait;
                        }
                                goto wait;
                        }
-                       if (anhp->rcode == SERVFAIL
-                           || anhp->rcode == NOTIMP
-                           || anhp->rcode == REFUSED) {
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG) {
-                                       printf("server rejected query:\n");
-                                       __p_query(answer);
-                               }
-#endif DEBUG
+                       if (anhp->rcode == SERVFAIL ||
+                           anhp->rcode == NOTIMP ||
+                           anhp->rcode == REFUSED) {
+                               DprintQ(_res.options & RES_DEBUG,
+                                       (stdout, "server rejected query:\n"),
+                                       ans);
                                badns |= (1<<ns);
                                badns |= (1<<ns);
-                               continue;
+                               _res_close();
+                               goto next_ns;
                        }
                        if (!(_res.options & RES_IGNTC) && anhp->tc) {
                                /*
                                 * get rest of answer;
                                 * use TCP with same server.
                                 */
                        }
                        if (!(_res.options & RES_IGNTC) && anhp->tc) {
                                /*
                                 * get rest of answer;
                                 * use TCP with same server.
                                 */
-#ifdef DEBUG
-                               if (_res.options & RES_DEBUG)
-                                       printf(";; truncated answer\n");
-#endif
-                               (void) close(s);
-                               s = -1;
+                               Dprint(_res.options & RES_DEBUG,
+                                      (stdout, ";; truncated answer\n")
+                                      );
                                v_circuit = 1;
                                v_circuit = 1;
-                               goto usevc;
+                               _res_close();
+                               goto same_ns;
                        }
                        }
-               }
-#ifdef DEBUG
-               if (_res.options & RES_DEBUG)
-                       printf(";; got answer:\n");
-               if ((_res.options & RES_DEBUG)
-                   || (_res.pfcode & RES_PRF_REPLY)) {
-                       __p_query(answer);
-               }
-#endif
+               } /*if vc/dg*/
+               DprintQ((_res.options & RES_DEBUG) ||
+                       (_res.pfcode & RES_PRF_REPLY),
+                       (stdout, ";; got answer:\n"),
+                       ans);
                /*
                 * If using virtual circuits, we assume that the first server
                /*
                 * If using virtual circuits, we assume that the first server
-                * is preferred over the rest (i.e. it is on the local
+                * is preferred over the rest (i.e. it is on the local
                 * machine) and only keep that one open.
                 * If we have temporarily opened a virtual circuit,
                 * or if we haven't been asked to keep a socket open,
                 * close the socket.
                 */
                 * machine) and only keep that one open.
                 * If we have temporarily opened a virtual circuit,
                 * or if we haven't been asked to keep a socket open,
                 * close the socket.
                 */
-               if ((v_circuit &&
-                   ((_res.options & RES_USEVC) == 0 || ns != 0)) ||
-                   (_res.options & RES_STAYOPEN) == 0) {
-                       (void) close(s);
-                       s = -1;
+               if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
+                   !(_res.options & RES_STAYOPEN)) {
+                       _res_close();
+               }
+               if (Rhook) {
+                       int done = 0, loops = 0;
+
+                       do {
+                               res_sendhookact act;
+
+                               act = (*Rhook)(nsap,
+                                              buf,
+                                              buflen,
+                                              ans,
+                                              anssiz,
+                                              &resplen);
+                               switch (act) {
+                               case res_goahead:
+                               case res_done:
+                                       done = 1;
+                                       break;
+                               case res_nextns:
+                                       _res_close();
+                                       goto next_ns;
+                               case res_modified:
+                                       /* give the hook another try */
+                                       if (++loops < 42) /*doug adams*/
+                                               break;
+                                       /*FALLTHROUGH*/
+                               case res_error:
+                                       /*FALLTHROUGH*/
+                               default:
+                                       return (-1);
+                               }
+                       } while (!done);
+
                }
                return (resplen);
                }
                return (resplen);
-          }
-       }
-       if (s >= 0) {
-               (void) close(s);
-               s = -1;
-       }
-       if (v_circuit == 0)
-               if (gotsomewhere == 0)
+    next_ns: ;
+          } /*foreach ns*/
+       } /*foreach retry*/
+       _res_close();
+       if (!v_circuit) {
+               if (!gotsomewhere)
                        errno = ECONNREFUSED;   /* no nameservers found */
                else
                        errno = ETIMEDOUT;      /* no answer obtained */
                        errno = ECONNREFUSED;   /* no nameservers found */
                else
                        errno = ETIMEDOUT;      /* no answer obtained */
-       else
+       } else {
                errno = terrno;
                errno = terrno;
+       }
        return (-1);
 }
 
        return (-1);
 }
 
@@ -469,10 +745,13 @@ wait:
  *
  * This routine is not expected to be user visible.
  */
  *
  * This routine is not expected to be user visible.
  */
+void
 _res_close()
 {
 _res_close()
 {
-       if (s != -1) {
+       if (s >= 0) {
                (void) close(s);
                s = -1;
                (void) close(s);
                s = -1;
+               connected = 0;
+               vc = 0;
        }
 }
        }
 }
index b8f1f65..aa3efa0 100644 (file)
@@ -1,13 +1,8 @@
 /*
 /*
- *     @(#)resolv.h    5.15 (Berkeley) 4/3/91
- *     $Id$
- */
-
-/*
- * ++Copyright++ 1983, 1987, 1989
+ * ++Copyright++ 1983, 1987, 1989, 1993
  * -
  * -
- * Copyright (c) 1983, 1987, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1983, 1987, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * --Copyright--
  */
 
  * --Copyright--
  */
 
+/*
+ *     @(#)resolv.h    8.1 (Berkeley) 6/2/93
+ *     $Id$
+ */
+
 #ifndef _RESOLV_H_
 #define        _RESOLV_H_
 
 #ifndef _RESOLV_H_
 #define        _RESOLV_H_
 
 #include <stdio.h>
 
 /*
 #include <stdio.h>
 
 /*
+ * revision information.  this is the release date in YYYYMMDD format.
+ * it can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__RES > 19931104)".  do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define        __RES   19940415
+
+/*
  * Resolver configuration file.
  * Normally not present, but may contain the address of the
  * inital name server(s) to query and the domain search list.
  * Resolver configuration file.
  * Normally not present, but may contain the address of the
  * inital name server(s) to query and the domain search list.
 #define        LOCALDOMAINPARTS        2       /* min levels in name that is "local" */
 
 #define        RES_TIMEOUT             5       /* min. seconds between retries */
 #define        LOCALDOMAINPARTS        2       /* min levels in name that is "local" */
 
 #define        RES_TIMEOUT             5       /* min. seconds between retries */
+#define        MAXRESOLVSORT           10      /* number of net to sort on */
+#define        RES_MAXNDOTS            15      /* should reflect bit field size */
 
 
-/* this was "struct state" until 4.9 */
 struct __res_state {
        int     retrans;                /* retransmition time interval */
        int     retry;                  /* number of times to retransmit */
 struct __res_state {
        int     retrans;                /* retransmition time interval */
        int     retry;                  /* number of times to retransmit */
-       u_int32_t       options;                /* option flags - see below. */
+       u_long  options;                /* option flags - see below. */
        int     nscount;                /* number of name servers */
        int     nscount;                /* number of name servers */
-       struct  sockaddr_in nsaddr_list[MAXNS]; /* address of name server */
+       struct sockaddr_in
+               nsaddr_list[MAXNS];     /* address of name server */
 #define        nsaddr  nsaddr_list[0]          /* for backward compatibility */
        u_short id;                     /* current packet id */
        char    *dnsrch[MAXDNSRCH+1];   /* components of domain to search */
        char    defdname[MAXDNAME];     /* default domain */
 #define        nsaddr  nsaddr_list[0]          /* for backward compatibility */
        u_short id;                     /* current packet id */
        char    *dnsrch[MAXDNSRCH+1];   /* components of domain to search */
        char    defdname[MAXDNAME];     /* default domain */
-       u_int32_t       pfcode;                 /* RES_PRF_ flags - see below. */
+       u_long  pfcode;                 /* RES_PRF_ flags - see below. */
+       unsigned ndots:4;               /* threshold for initial abs. query */
+       unsigned nsort:4;               /* number of elements in sort_list[] */
+       char    unused[3];
+       struct {
+               struct in_addr  addr;
+               u_int32_t       mask;
+       } sort_list[MAXRESOLVSORT];
 };
 
 /*
  * Resolver options (keep these in synch with res_debug.c, please)
  */
 };
 
 /*
  * Resolver options (keep these in synch with res_debug.c, please)
  */
-#define RES_INIT       0x0001          /* address initialized */
-#define RES_DEBUG      0x0002          /* print debug messages */
-#define RES_AAONLY     0x0004          /* authoritative answers only */
-#define RES_USEVC      0x0008          /* use virtual circuit */
-#define RES_PRIMARY    0x0010          /* query primary server only */
-#define RES_IGNTC      0x0020          /* ignore trucation errors */
-#define RES_RECURSE    0x0040          /* recursion desired */
-#define RES_DEFNAMES   0x0080          /* use default domain name */
-#define RES_STAYOPEN   0x0100          /* Keep TCP socket open */
-#define RES_DNSRCH     0x0200          /* search up local domain tree */
+#define RES_INIT       0x00000001      /* address initialized */
+#define RES_DEBUG      0x00000002      /* print debug messages */
+#define RES_AAONLY     0x00000004      /* authoritative answers only */
+#define RES_USEVC      0x00000008      /* use virtual circuit */
+#define RES_PRIMARY    0x00000010      /* query primary server only */
+#define RES_IGNTC      0x00000020      /* ignore trucation errors */
+#define RES_RECURSE    0x00000040      /* recursion desired */
+#define RES_DEFNAMES   0x00000080      /* use default domain name */
+#define RES_STAYOPEN   0x00000100      /* Keep TCP socket open */
+#define RES_DNSRCH     0x00000200      /* search up local domain tree */
+#define        RES_INSECURE1   0x00000400      /* type 1 security disabled */
+#define        RES_INSECURE2   0x00000800      /* type 2 security disabled */
 
 #define RES_DEFAULT    (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
 
 /*
  * Resolver "pfcode" values.  Used by dig.
  */
 
 #define RES_DEFAULT    (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
 
 /*
  * Resolver "pfcode" values.  Used by dig.
  */
-#define RES_PRF_STATS  0x0001
-/*                     0x0002  */
-#define RES_PRF_CLASS   0x0004
-#define RES_PRF_CMD    0x0008
-#define RES_PRF_QUES   0x0010
-#define RES_PRF_ANS    0x0020
-#define RES_PRF_AUTH   0x0040
-#define RES_PRF_ADD    0x0080
-#define RES_PRF_HEAD1  0x0100
-#define RES_PRF_HEAD2  0x0200
-#define RES_PRF_TTLID  0x0400
-#define RES_PRF_HEADX  0x0800
-#define RES_PRF_QUERY  0x1000
-#define RES_PRF_REPLY  0x2000
-#define RES_PRF_INIT    0x4000
-/*                     0x8000  */
+#define RES_PRF_STATS  0x00000001
+/*                     0x00000002      */
+#define RES_PRF_CLASS   0x00000004
+#define RES_PRF_CMD    0x00000008
+#define RES_PRF_QUES   0x00000010
+#define RES_PRF_ANS    0x00000020
+#define RES_PRF_AUTH   0x00000040
+#define RES_PRF_ADD    0x00000080
+#define RES_PRF_HEAD1  0x00000100
+#define RES_PRF_HEAD2  0x00000200
+#define RES_PRF_TTLID  0x00000400
+#define RES_PRF_HEADX  0x00000800
+#define RES_PRF_QUERY  0x00001000
+#define RES_PRF_REPLY  0x00002000
+#define RES_PRF_INIT    0x00004000
+/*                     0x00008000      */
+
+/* hooks are still experimental as of 4.9.2 */
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+       res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr_in * const *ns,
+                                             const u_char **query,
+                                             int *querylen,
+                                             u_char *ans,
+                                             int anssiz,
+                                             int *resplen));
+
+typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns,
+                                             const u_char *query,
+                                             int querylen,
+                                             u_char *ans,
+                                             int anssiz,
+                                             int *resplen));
 
 extern struct __res_state _res;
 
 /* Private routines shared between libc/net, named, nslookup and others. */
 #define        dn_skipname     __dn_skipname
 #define        fp_query        __fp_query
 
 extern struct __res_state _res;
 
 /* Private routines shared between libc/net, named, nslookup and others. */
 #define        dn_skipname     __dn_skipname
 #define        fp_query        __fp_query
+#define        fp_nquery       __fp_nquery
 #define        hostalias       __hostalias
 #define        putlong         __putlong
 #define        putshort        __putshort
 #define p_class                __p_class
 #define p_time         __p_time
 #define p_type         __p_type
 #define        hostalias       __hostalias
 #define        putlong         __putlong
 #define        putshort        __putshort
 #define p_class                __p_class
 #define p_time         __p_time
 #define p_type         __p_type
+#define        p_cdnname       __p_cdnname
+#define        p_cdname        __p_cdname
+#define        p_fqname        __p_fqname
+#define        p_rr            __p_rr
+#define        p_option        __p_option
 __BEGIN_DECLS
 int     __dn_skipname __P((const u_char *, const u_char *));
 void    __fp_resstat __P((struct __res_state *, FILE *));
 __BEGIN_DECLS
 int     __dn_skipname __P((const u_char *, const u_char *));
 void    __fp_resstat __P((struct __res_state *, FILE *));
-void    __fp_query __P((char *, FILE *));
+void    __fp_query __P((const u_char *, FILE *));
+void    __fp_nquery __P((const u_char *, int, FILE *));
 char   *__hostalias __P((const char *));
 void    __putlong __P((u_int32_t, u_char *));
 char   *__hostalias __P((const char *));
 void    __putlong __P((u_int32_t, u_char *));
-void    __putshort __P((u_short, u_char *));
-char   *__p_class __P((int));
+void    __putshort __P((u_int16_t, u_char *));
 char   *__p_time __P((u_int32_t));
 char   *__p_time __P((u_int32_t));
-char   *__p_type __P((int));
-
-int     dn_comp __P((const u_char *, u_char *, int, u_char **, u_char **));
+void    __p_query __P((const u_char *));
+const u_char *__p_cdnname __P((const u_char *, const u_char *, int, FILE *));
+const u_char *__p_cdname __P((const u_char *, const u_char *, FILE *));
+const u_char *__p_fqname __P((const u_char *, const u_char *, FILE *));
+const u_char *__p_rr __P((const u_char *, const u_char *, FILE *));
+const char *__p_type __P((int));
+const char *__p_class __P((int));
+const char *__p_option __P((u_long option));
+int     dn_comp __P((const char *, u_char *, int, u_char **, u_char **));
 int     dn_expand __P((const u_char *, const u_char *, const u_char *,
 int     dn_expand __P((const u_char *, const u_char *, const u_char *,
-                       u_char *, int));
+                       char *, int));
 int     res_init __P((void));
 int     res_init __P((void));
-int     res_mkquery __P((int, const char *, int, int, const char *, int,
-                         const char *, char *, int));
-int     res_send __P((const char *, int, char *, int));
+int     res_query __P((const char *, int, int, u_char *, int));
+int     res_search __P((const char *, int, int, u_char *, int));
+int     res_querydomain __P((const char *, const char *, int, int,
+                             u_char *, int));
+int     res_mkquery __P((int, const char *, int, int, const u_char *, int,
+                         const u_char *, u_char *, int));
+int     res_send __P((const u_char *, int, u_char *, int));
+/* XXX - these last two don't belong in the resolver */
+u_int   inet_nsap_addr __P((const char *, u_char *, int maxlen));
+char   *inet_nsap_ntoa __P((int, const u_char *, char *ascii));
 __END_DECLS
 
 #endif /* !_RESOLV_H_ */
 __END_DECLS
 
 #endif /* !_RESOLV_H_ */
index 8f82227..709b518 100644 (file)
@@ -1,7 +1,9 @@
 /*
 /*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.
- *
+ * ++Copyright++ 1985, 1993
+ * -
+ * Copyright (c) 1985, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
- *
+ * 
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)sethostent.c       6.9 (Berkeley) 3/19/91";
+static char sccsid[] = "@(#)sethostent.c       8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -43,6 +66,7 @@ static char sccsid[] = "@(#)sethostent.c      6.9 (Berkeley) 3/19/91";
 
 void
 sethostent(stayopen)
 
 void
 sethostent(stayopen)
+       int stayopen;
 {
        if (stayopen)
                _res.options |= RES_STAYOPEN | RES_USEVC;
 {
        if (stayopen)
                _res.options |= RES_STAYOPEN | RES_USEVC;