Module Name:    src
Committed By:   christos
Date:           Sat Oct 24 05:35:37 UTC 2009

Modified Files:
        src/lib/libc/resolv: res_data.c res_init.c res_private.h res_send.c

Log Message:
Add a knote to keep track when resolv.conf gets changed and re-initialize.
While here fix a memory leak when calling res_vinit with an already inited
res_state.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/lib/libc/resolv/res_data.c
cvs rdiff -u -r1.20 -r1.21 src/lib/libc/resolv/res_init.c
cvs rdiff -u -r1.1.1.4 -r1.2 src/lib/libc/resolv/res_private.h
cvs rdiff -u -r1.18 -r1.19 src/lib/libc/resolv/res_send.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/resolv/res_data.c
diff -u src/lib/libc/resolv/res_data.c:1.13 src/lib/libc/resolv/res_data.c:1.14
--- src/lib/libc/resolv/res_data.c:1.13	Sun Apr 12 15:43:37 2009
+++ src/lib/libc/resolv/res_data.c	Sat Oct 24 01:35:37 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: res_data.c,v 1.13 2009/04/12 19:43:37 christos Exp $	*/
+/*	$NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $	*/
 
 /*
  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
@@ -22,7 +22,7 @@
 #ifdef notdef
 static const char rcsid[] = "Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp";
 #else
-__RCSID("$NetBSD: res_data.c,v 1.13 2009/04/12 19:43:37 christos Exp $");
+__RCSID("$NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -49,6 +49,8 @@
 
 #include "port_after.h"
 
+#include "res_private.h"
+
 #ifdef __weak_alias
 __weak_alias(res_init,_res_init)
 __weak_alias(res_mkquery,_res_mkquery)
@@ -108,7 +110,6 @@
 int
 res_init(void) {
 	int rv;
-	extern int __res_vinit(res_state, int);
 #ifdef COMPAT__RES
 	/*
 	 * Compatibility with program that were accessing _res directly

Index: src/lib/libc/resolv/res_init.c
diff -u src/lib/libc/resolv/res_init.c:1.20 src/lib/libc/resolv/res_init.c:1.21
--- src/lib/libc/resolv/res_init.c:1.20	Mon Apr 20 10:42:12 2009
+++ src/lib/libc/resolv/res_init.c	Sat Oct 24 01:35:37 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: res_init.c,v 1.20 2009/04/20 14:42:12 christos Exp $	*/
+/*	$NetBSD: res_init.c,v 1.21 2009/10/24 05:35:37 christos Exp $	*/
 
 /*
  * Copyright (c) 1985, 1989, 1993
@@ -76,7 +76,7 @@
 static const char sccsid[] = "@(#)res_init.c	8.1 (Berkeley) 6/7/93";
 static const char rcsid[] = "Id: res_init.c,v 1.26 2008/12/11 09:59:00 marka Exp";
 #else
-__RCSID("$NetBSD: res_init.c,v 1.20 2009/04/20 14:42:12 christos Exp $");
+__RCSID("$NetBSD: res_init.c,v 1.21 2009/10/24 05:35:37 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -86,7 +86,9 @@
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/event.h>
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -97,6 +99,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <netdb.h>
 
 #define HAVE_MD5
@@ -156,6 +159,9 @@
 # define isascii(c) (!(c & 0200))
 #endif
 
+static struct timespec __res_conf_time;
+static const struct timespec ts = { 0, 0 };
+
 /*
  * Resolver state default settings.
  */
@@ -183,8 +189,6 @@
  */
 int
 res_ninit(res_state statp) {
-	extern int __res_vinit(res_state, int);
-
 	return (__res_vinit(statp, 0));
 }
 
@@ -208,17 +212,17 @@
 
 	RES_SET_H_ERRNO(statp, 0);
 
+	if ((statp->options & RES_INIT) != 0U)
+		res_ndestroy(statp);
+
 	if (!preinit) {
 		statp->retrans = RES_TIMEOUT;
 		statp->retry = RES_DFLRETRY;
 		statp->options = RES_DEFAULT;
-		statp->_rnd = malloc(16);
-		res_rndinit(statp);
-		statp->id = res_nrandomid(statp);
 	}
-
-	if ((statp->options & RES_INIT) != 0U)
-		res_ndestroy(statp);
+	statp->_rnd = malloc(16);
+	res_rndinit(statp);
+	statp->id = res_nrandomid(statp);
 
 	memset(u, 0, sizeof(u));
 #ifdef USELOOPBACK
@@ -343,6 +347,9 @@
 
 	nserv = 0;
 	if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+	    struct stat st;
+	    struct kevent kc;
+
 	    /* read the config file */
 	    while (fgets(buf, sizeof(buf), fp) != NULL) {
 		/* skip comments */
@@ -490,7 +497,21 @@
 #ifdef RESOLVSORT
 	    statp->nsort = nsort;
 #endif
+	    statp->_u._ext.ext->resfd = dup(fileno(fp));
 	    (void) fclose(fp);
+	    if (fstat(statp->_u._ext.ext->resfd, &st) != -1)
+		    __res_conf_time = statp->_u._ext.ext->res_conf_time =
+			st.st_mtimespec;
+	    statp->_u._ext.ext->kq = kqueue();
+	    (void)fcntl(statp->_u._ext.ext->kq, F_SETFD, FD_CLOEXEC);
+	    (void)fcntl(statp->_u._ext.ext->resfd, F_SETFD, FD_CLOEXEC);
+	    EV_SET(&kc, statp->_u._ext.ext->resfd, EVFILT_VNODE,
+		EV_ADD|EV_ENABLE|EV_CLEAR, NOTE_DELETE|NOTE_WRITE| NOTE_EXTEND|
+		NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE, 0, 0);
+	    (void)kevent(statp->_u._ext.ext->kq, &kc, 1, NULL, 0, &ts);
+	} else {
+	    statp->_u._ext.ext->kq = -1;
+	    statp->_u._ext.ext->resfd = -1;
 	}
 /*
  * Last chance to get a nameserver.  This should not normally
@@ -541,6 +562,33 @@
 	return (statp->res_h_errno);
 }
 
+void
+__res_check(res_state statp)
+{
+	/*
+	 * If the times are equal, then we check if there
+	 * was a kevent related to resolv.conf and reload.
+	 * If the times are not equal, then we don't bother
+	 * to check the kevent, because another thread already
+	 * did, loaded and changed the time.
+	 */
+	if (timespeccmp(&statp->_u._ext.ext->res_conf_time,
+	    &__res_conf_time, ==)) {
+		struct kevent ke;
+		if (statp->_u._ext.ext->kq == -1)
+			return;
+
+		switch (kevent(statp->_u._ext.ext->kq, NULL, 0, &ke, 1, &ts)) {
+		case 0:
+		case -1:
+			return;
+		default:
+			break;
+		}
+	}
+	(void)__res_vinit(statp, 0);
+}
+
 static void
 res_setoptions(res_state statp, const char *options, const char *source)
 {
@@ -758,6 +806,10 @@
 res_ndestroy(res_state statp) {
 	res_nclose(statp);
 	if (statp->_u._ext.ext != NULL) {
+		if (statp->_u._ext.ext->kq != -1)
+			(void)close(statp->_u._ext.ext->kq);
+		if (statp->_u._ext.ext->resfd != -1)
+			(void)close(statp->_u._ext.ext->resfd);
 		free(statp->_u._ext.ext);
 		statp->_u._ext.ext = NULL;
 	}

Index: src/lib/libc/resolv/res_private.h
diff -u src/lib/libc/resolv/res_private.h:1.1.1.4 src/lib/libc/resolv/res_private.h:1.2
--- src/lib/libc/resolv/res_private.h:1.1.1.4	Sun Apr 12 12:35:48 2009
+++ src/lib/libc/resolv/res_private.h	Sat Oct 24 01:35:37 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: res_private.h,v 1.1.1.4 2009/04/12 16:35:48 christos Exp $	*/
+/*	$NetBSD: res_private.h,v 1.2 2009/10/24 05:35:37 christos Exp $	*/
 
 #ifndef res_private_h
 #define res_private_h
@@ -14,10 +14,13 @@
 	} sort_list[MAXRESOLVSORT];
 	char nsuffix[64];
 	char nsuffix2[64];
+	struct timespec res_conf_time;
+	int kq, resfd;
 };
 
-extern int
-res_ourserver_p(const res_state statp, const struct sockaddr *sa);
+extern int res_ourserver_p(const res_state, const struct sockaddr *);
+extern int __res_vinit(res_state, int);
+extern void __res_check(res_state);
 
 #endif
 

Index: src/lib/libc/resolv/res_send.c
diff -u src/lib/libc/resolv/res_send.c:1.18 src/lib/libc/resolv/res_send.c:1.19
--- src/lib/libc/resolv/res_send.c:1.18	Sun Apr 12 13:07:17 2009
+++ src/lib/libc/resolv/res_send.c	Sat Oct 24 01:35:37 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: res_send.c,v 1.18 2009/04/12 17:07:17 christos Exp $	*/
+/*	$NetBSD: res_send.c,v 1.19 2009/10/24 05:35:37 christos Exp $	*/
 
 /*
  * Portions Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
@@ -93,7 +93,7 @@
 static const char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
 static const char rcsid[] = "Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp";
 #else
-__RCSID("$NetBSD: res_send.c,v 1.18 2009/04/12 17:07:17 christos Exp $");
+__RCSID("$NetBSD: res_send.c,v 1.19 2009/10/24 05:35:37 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -337,6 +337,8 @@
 	highestFD = sysconf(_SC_OPEN_MAX) - 1;
 #endif
 
+	__res_check(statp);
+
 	/* No name servers or res_init() failure */
 	if (statp->nscount == 0 || EXT(statp).ext == NULL) {
 		errno = ESRCH;

Reply via email to