* -
* 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
* are met:
* 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
* 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
static char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
# include "../conf/portability.h"
#endif
-/*
+/*-------------------------------------- info about "sortlist" --------------
* Marc Majka 1994/04/16
* Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
*
* "search" property.
* - The sortlist comprised of IP address netmask pairs are stored as
* values of the "sortlist" property. The IP address and optional netmask
- * should be seperated by a slash (/) character.
+ * should be separated by a slash (/) or ampersand (&) character.
* - Internal resolver variables can be set from the value of the "options"
* property.
- *
*/
#if defined(NeXT)
# include <netinfo/ni.h>
# include "../conf/options.h"
#endif
-static void res_setoptions __P((char *, char *));
+static void res_setoptions __P((char *, char *)) internal_function;
#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
static u_int32_t net_mask __P((struct in_addr));
#endif
* Resolver state default settings.
*/
-struct __res_state _res;
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+ = { RES_TIMEOUT, } /* Motorola, et al. */
+# endif
+ ;
/*
* Set up default settings. If the configuration file exist, the values
* 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
+ * 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.
*
*
* Return 0 if completes successfully, -1 on error
*/
+int
res_init()
{
register FILE *fp;
register char *cp, **pp;
- register int n, dots;
- char buf[BUFSIZ];
+ register int n;
+ char buf[MAXDNAME];
int nserv = 0; /* number of nameserver records read from file */
int haveenv = 0;
int havesearch = 0;
int nsort = 0;
char *net;
#endif
+#ifndef RFC1535
+ int dots;
+#endif
/*
* These three fields used to be statically initialized. This made
* 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.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
*/
if (!_res.retrans)
_res.retrans = RES_TIMEOUT;
if (!_res.retry)
_res.retry = 4;
- if (!_res.options)
+ if (!(_res.options & RES_INIT))
_res.options = RES_DEFAULT;
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
#ifdef USELOOPBACK
_res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+ _res.nscount = 1;
#else
_res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+ _res.nscount = 0;
#endif
_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) {
+ if ((cp = __secure_getenv("LOCALDOMAIN")) != NULL) {
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
haveenv++;
#endif
if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
/* read the config file */
- while (fgets(buf, sizeof(buf), fp) != NULL) {
+ while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
/* skip comments */
if (*buf == ';' || *buf == '#')
continue;
if (*cp == '\0' || *cp == '\n' || *cp == ';')
break;
net = cp;
- while (*cp && *cp != '/' &&
+ while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
isascii(*cp) && !isspace(*cp))
cp++;
n = *cp;
*cp = 0;
if (inet_aton(net, &a)) {
_res.sort_list[nsort].addr = a;
- if (n == '/') {
+ if (ISSORTMASK(n)) {
*cp++ = n;
net = cp;
- while (*cp && isascii(*cp) && !isspace(*cp))
+ while (*cp && *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 =
+ _res.sort_list[nsort].mask =
net_mask(_res.sort_list[nsort].addr);
}
} else {
- _res.sort_list[nsort].mask =
+ _res.sort_list[nsort].mask =
net_mask(_res.sort_list[nsort].addr);
}
nsort++;
}
- *cp++ = n;
+ *cp = n;
}
continue;
}
continue;
}
}
- if (nserv > 1)
+ if (nserv > _res.nscount)
_res.nscount = nserv;
#ifdef RESOLVSORT
_res.nsort = nsort;
(void) fclose(fp);
}
if (_res.defdname[0] == 0 &&
- gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+ __gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
(cp = strchr(buf, '.')) != NULL)
strcpy(_res.defdname, cp + 1);
#endif /* !RFC1535 */
}
- if ((cp = getenv("RES_OPTIONS")) != NULL)
+ if ((cp = __secure_getenv("RES_OPTIONS")) != NULL)
res_setoptions(cp, "env");
_res.options |= RES_INIT;
return (0);
}
static void
+internal_function
res_setoptions(options, source)
char *options, *source;
{
}
printf(";;\tdebug\n");
#endif
+ } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+ _res.options |= RES_USE_INET6;
} else {
/* XXX - print a warning here? */
}
}
#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
static u_int32_t
net_mask(in) /* XXX - should really use system's version of this */
struct in_addr in;
}
ni_namelist_free(&nl);
}
-
- if (nserv > 1)
+
+ if (nserv > _res.nscount)
_res.nscount = nserv;
#ifdef RESOLVSORT
n++) {
char ch;
char *cp;
+ const char *sp;
struct in_addr a;
- cp = strchr(nl.ni_namelist_val[n], '/');
+ cp = NULL;
+ for (sp = sort_mask; *sp; sp++) {
+ char *cp1;
+ cp1 = strchr(nl.ni_namelist_val[n], *sp);
+ if (cp && cp1)
+ cp = (cp < cp1)? cp : cp1;
+ else if (cp1)
+ cp = cp1;
+ }
if (cp != NULL) {
- ch = *cp;
- *cp = '\0';
+ ch = *cp;
+ *cp = '\0';
+ break;
}
-
if (inet_aton(nl.ni_namelist_val[n], &a)) {
_res.sort_list[nsort].addr = a;
- if (*cp && ch == '/') {
+ if (*cp && ISSORTMASK(ch)) {
*cp++ = ch;
if (inet_aton(cp, &a)) {
_res.sort_list[nsort].mask = a.s_addr;
return(0); /* if not using DNS configuration from NetInfo */
}
#endif /* NeXT */
+
+u_int
+res_randomid()
+{
+ struct timeval now;
+
+ __gettimeofday(&now, NULL);
+ return (0xffff & (now.tv_sec ^ now.tv_usec ^ __getpid()));
+}