integrate changes from bind 4.9 (most of them); continue to use address
[unix-history] / usr / src / lib / libc / net / res_init.c
index c76043f..4a0b97e 100644 (file)
@@ -1,45 +1,55 @@
-/*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ * -
+ * 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--
  */
 
  */
 
-#ifndef lint
-static char sccsid[] = "@(#)res_init.c 6.1 (Berkeley) %G%";
-#endif not lint
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_init.c 6.16 (Berkeley) %G%";
+static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $";
+#endif /* LIBC_SCCS and not lint */
 
 
-#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
-#include <stdio.h>
+#include <arpa/inet.h>
 #include <arpa/nameser.h>
 #include <arpa/nameser.h>
-#include <arpa/resolv.h>
-
-/*
- * Resolver configuration file. Contains the address of the
- * inital name server to query and the default domain for
- * non fully qualified domain names.
- */
-
-#ifdef CONFFILE
-char    *conffile = CONFFILE;
-#else
-char    *conffile = "/etc/resolv.conf";
-#endif
+#include <resolv.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 /*
  * Resolver state default settings
  */
 
 
 /*
  * Resolver state default settings
  */
 
-#ifndef RES_TIMEOUT
-#define RES_TIMEOUT 10
-#endif
-
-struct state _res = {
-    RES_TIMEOUT,                 /* retransmition time interval */
-    4,                           /* number of times to retransmit */
-    RES_RECURSE|RES_DEFNAMES,    /* options flags */
-    1,                           /* number of name servers */
+struct __res_state _res = {
+       RES_TIMEOUT,                    /* retransmition time interval */
+       4,                              /* number of times to retransmit */
+       RES_DEFAULT,                    /* options flags */
+       1,                              /* number of name servers */
 };
 
 /*
 };
 
 /*
@@ -54,81 +64,134 @@ struct state _res = {
  */
 res_init()
 {
  */
 res_init()
 {
-    register FILE *fp;
-    char buf[BUFSIZ], *cp;
-    extern u_long inet_addr();
-    extern char *index();
-    extern char *strcpy(), *strncpy();
-#ifdef DEBUG
-    extern char *getenv();
-#endif DEBUG
-    int n = 0;    /* number of nameserver records read from file */
+       register FILE *fp;
+       register char *cp, **pp;
+       register int n;
+       char buf[BUFSIZ];
+       int nserv = 0;    /* number of nameserver records read from file */
+       int haveenv = 0;
+       int havesearch = 0;
+
+#ifdef USELOOPBACK
+       _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.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';
+               haveenv++;
+       }
 
 
-    _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
-    _res.nsaddr.sin_family = AF_INET;
-    _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
-    _res.nscount = 1;
-    _res.defdname[0] = '\0';
+       if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+           /* read the config file */
+           while (fgets(buf, sizeof(buf), fp) != NULL) {
+               /* skip comments */
+               if ((*buf == ';') || (*buf == '#'))
+                       continue;
+               /* read default domain name */
+               if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
+                   if (haveenv)        /* skip if have from environ */
+                           continue;
+                   cp = buf + sizeof("domain") - 1;
+                   while (*cp == ' ' || *cp == '\t')
+                           cp++;
+                   if ((*cp == '\0') || (*cp == '\n'))
+                           continue;
+                   (void)strncpy(_res.defdname, cp,
+                                 sizeof(_res.defdname) - 1);
+                   if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
+                           *cp = '\0';
+                   havesearch = 0;
+                   continue;
+               }
+               /* set search list */
+               if (!strncmp(buf, "search", sizeof("search") - 1)) {
+                   if (haveenv)        /* skip if have from environ */
+                           continue;
+                   cp = buf + sizeof("search") - 1;
+                   while (*cp == ' ' || *cp == '\t')
+                           cp++;
+                   if ((*cp == '\0') || (*cp == '\n'))
+                           continue;
+                   (void)strncpy(_res.defdname, cp,
+                                 sizeof(_res.defdname) - 1);
+                   if ((cp = index(_res.defdname, '\n')) != NULL)
+                           *cp = '\0';
+                   /*
+                    * Set search list to be blank-separated strings
+                    * on rest of line.
+                    */
+                   cp = _res.defdname;
+                   pp = _res.dnsrch;
+                   *pp++ = cp;
+                   for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+                           if (*cp == ' ' || *cp == '\t') {
+                                   *cp = 0;
+                                   n = 1;
+                           } else if (n) {
+                                   *pp++ = cp;
+                                   n = 0;
+                           }
+                   }
+                   /* null terminate last domain if there are excess */
+                   while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+                           cp++;
+                   *cp = '\0';
+                   *pp++ = 0;
+                   havesearch = 1;
+                   continue;
+               }
+               /* read nameservers to query */
+               if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
+                  nserv < MAXNS) {
+                  struct in_addr a;
 
 
-    if ((fp = fopen(conffile, "r")) != NULL) {
-        /* read the config file */
-        while (fgets(buf, sizeof(buf), fp) != NULL) {
-            /* read default domain name */
-            if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
-                cp = buf + sizeof("domain") - 1;
-                while (*cp == ' ' || *cp == '\t')
-                    cp++;
-                if (*cp == '\0')
-                    continue;
-                (void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
-                _res.defdname[sizeof(_res.defdname) - 1] = '\0';
-                if ((cp = index(_res.defdname, '\n')) != NULL)
-                    *cp = '\0';
-                continue;
-            }
-            /* read nameservers to query */
-            if (!strncmp(buf, "nameserver", 
-               sizeof("nameserver") - 1) && (n < MAXNS)) {
-                cp = buf + sizeof("nameserver") - 1;
-                while (*cp == ' ' || *cp == '\t')
-                    cp++;
-                if (*cp == '\0')
-                    continue;
-                _res.nsaddr_list[n].sin_addr.s_addr = inet_addr(cp);
-                if (_res.nsaddr_list[n].sin_addr.s_addr == (unsigned)-1) 
-                    _res.nsaddr_list[n].sin_addr.s_addr = INADDR_ANY;
-                    _res.nsaddr_list[n].sin_family = AF_INET;
-                    _res.nsaddr_list[n].sin_port = htons(NAMESERVER_PORT);
-#ifdef DEBUG
-                if ( _res.options & RES_DEBUG )
-                    printf("Server #%d address = %s\n", n+1,
-                         inet_ntoa(_res.nsaddr_list[n].sin_addr.s_addr));
-#endif DEBUG
-                    if ( ++n >= MAXNS) { 
-                       n = MAXNS;
-#ifdef DEBUG
-                       if ( _res.options & RES_DEBUG )
-                          printf("MAXNS reached\n");
-#endif DEBUG
-                }
-                continue;
-            }
-        }
-        if ( n > 1 ) 
-            _res.nscount = n;
-        (void) fclose(fp);
-    }
-    if (_res.defdname[0] == 0) {
-        if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
-           (cp = index(buf, '.')))
-             (void)strcpy(_res.defdname, cp + 1);
-    }
+                   cp = buf + sizeof("nameserver") - 1;
+                   while (*cp == ' ' || *cp == '\t')
+                       cp++;
+                   if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
+                       _res.nsaddr_list[nserv].sin_addr = a;
+                       _res.nsaddr_list[nserv].sin_family = AF_INET;
+                       _res.nsaddr_list[nserv].sin_port =
+                               htons(NAMESERVER_PORT);
+                       nserv++;
+                   }
+                   continue;
+               }
+           }
+           if (nserv > 1) 
+               _res.nscount = nserv;
+           (void) fclose(fp);
+       }
+       if (_res.defdname[0] == 0) {
+               if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
+                  (cp = index(buf, '.')))
+                       (void)strcpy(_res.defdname, cp + 1);
+       }
 
 
-#ifdef DEBUG
-    /* Allow user to override the local domain definition */
-    if ((cp = getenv("LOCALDOMAIN")) != NULL)
-        (void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
-#endif DEBUG
-    _res.options |= RES_INIT;
-    return(0);
+       /* 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++;
+               cp = _res.defdname;
+               for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
+                   n--) {
+                       cp = index(cp, '.');
+                       *pp++ = ++cp;
+               }
+               *pp++ = 0;
+       }
+       _res.options |= RES_INIT;
+       return (0);
 }
 }