about summary refs log tree commit diff
path: root/resolv/res_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/res_init.c')
-rw-r--r--resolv/res_init.c67
1 files changed, 53 insertions, 14 deletions
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 98807ff771..42c7c2ef8c 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -60,6 +60,7 @@ static char rcsid[] = "$Id$";
 
 #include <sys/param.h>
 #include <sys/socket.h>
+#include <sys/time.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
@@ -75,7 +76,7 @@ static char rcsid[] = "$Id$";
 # include "../conf/portability.h"
 #endif
 
-/*
+/*-------------------------------------- info about "sortlist" --------------
  * Marc Majka		1994/04/16
  * Allan Nathanson	1994/10/29 (BIND 4.9.3.x)
  *
@@ -93,10 +94,9 @@ static char rcsid[] = "$Id$";
  *   "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 seperated 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>
@@ -112,6 +112,8 @@ static int netinfo_res_init __P((int *haveenv, int *havesearch));
 static void res_setoptions __P((char *, char *));
 
 #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
 
@@ -146,11 +148,12 @@ struct __res_state _res;
  *
  * Return 0 if completes successfully, -1 on error
  */
+int
 res_init()
 {
 	register FILE *fp;
 	register char *cp, **pp;
-	register int n, dots;
+	register int n;
 	char buf[BUFSIZ];
 	int nserv = 0;    /* number of nameserver records read from file */
 	int haveenv = 0;
@@ -159,6 +162,9 @@ res_init()
 	int nsort = 0;
 	char *net;
 #endif
+#ifndef RFC1535
+	int dots;
+#endif
 
 	/*
 	 * These three fields used to be statically initialized.  This made
@@ -172,13 +178,26 @@ res_init()
 	 * 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 & RES_INIT))
-		_res.options |= RES_DEFAULT;
+		_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);
@@ -317,17 +336,18 @@ res_init()
 			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;
@@ -343,7 +363,7 @@ res_init()
 			    }
 			    nsort++;
 			}
-			*cp++ = n;
+			*cp = n;
 		    }
 		    continue;
 		}
@@ -448,6 +468,7 @@ res_setoptions(options, source)
 }
 
 #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;
@@ -556,17 +577,26 @@ netinfo_res_init(haveenv, havesearch)
 			 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;
@@ -607,3 +637,12 @@ netinfo_res_init(haveenv, havesearch)
     return(0);	/* if not using DNS configuration from NetInfo */
 }
 #endif	/* NeXT */
+
+u_int16_t
+res_randomid()
+{
+	struct timeval now;
+
+	gettimeofday(&now, NULL);
+	return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}