integrate changes from bind 4.9 (most of them); continue to use address
[unix-history] / usr / src / lib / libc / net / res_init.c
index e1163a6..4a0b97e 100644 (file)
-/*
- * 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 5.4 (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 = "/usr/local/lib/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
  */
-struct state _res = {
-       90,
-       2,
-       RES_RECURSE|RES_DEFNAMES,
+
+struct __res_state _res = {
+       RES_TIMEOUT,                    /* retransmition time interval */
+       4,                              /* number of times to retransmit */
+       RES_DEFAULT,                    /* options flags */
+       1,                              /* number of name servers */
 };
 
 /*
 };
 
 /*
- * Read the configuration file for default settings.
- * Return true if the name server address is initialized.
+ * Set up default settings.  If the configuration file exist, the values
+ * there will have precedence.  Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * The configuration file should only be used if you want to redefine your
+ * domain or run without a server on your machine.
+ *
+ * Return 0 if completes successfully, -1 on error
  */
 res_init()
 {
  */
 res_init()
 {
-       FILE *fp;
-       char buf[BUFSIZ], *cp;
-       int n;
-       extern u_long inet_addr();
-       extern char *index(), *getenv();
+       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;
 
 
-       _res.options |= RES_INIT;
-       _res.nsaddr.sin_family = AF_INET;
+#ifdef USELOOPBACK
+       _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
        _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
        _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+#endif
+       _res.nsaddr.sin_family = AF_INET;
        _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
        _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+       _res.nscount = 1;
+       _res.pfcode = 0;
 
 
-       /* first try reading the config file */
-       if ((fp = fopen(conffile, "r")) != NULL) {
-               if (fgets(_res.defdname, sizeof(_res.defdname), fp) == NULL)
-                       _res.defdname[0] = '\0';
-               else if ((cp = index(_res.defdname, '\n')) != NULL)
+       /* 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';
                        *cp = '\0';
-               if (fgets(buf, sizeof (buf), fp) != NULL)
-                       _res.nsaddr.sin_addr.s_addr = inet_addr(buf);
-               (void) fclose(fp);
+               haveenv++;
        }
 
        }
 
-       /* Allow user to override the local domain definition */
-       if ((cp = getenv("LOCALDOMAIN")) != NULL)
-               strncpy(_res.defdname, cp, sizeof(_res.defdname));
+       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;
+
+                   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);
+       }
+
+       /* 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);
 }
 }