Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libc/resolv/res_init.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libc/resolv/res_init.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.15 retrieving revision 1.15.12.1 diff -u -p -r1.15 -r1.15.12.1 --- src/lib/libc/resolv/res_init.c 2008/06/21 23:37:53 1.15 +++ src/lib/libc/resolv/res_init.c 2011/01/09 20:43:29 1.15.12.1 @@ -1,4 +1,4 @@ -/* $NetBSD: res_init.c,v 1.15 2008/06/21 23:37:53 christos Exp $ */ +/* $NetBSD: res_init.c,v 1.15.12.1 2011/01/09 20:43:29 riz Exp $ */ /* * Copyright (c) 1985, 1989, 1993 @@ -74,9 +74,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #ifdef notdef static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static const char rcsid[] = "Id: res_init.c,v 1.23 2007/07/09 01:43:23 marka Exp"; +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.15 2008/06/21 23:37:53 christos Exp $"); +__RCSID("$NetBSD: res_init.c,v 1.15.12.1 2011/01/09 20:43:29 riz Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -86,7 +86,9 @@ __RCSID("$NetBSD: res_init.c,v 1.15 2008 #include #include #include +#include #include +#include #include #include @@ -97,8 +99,23 @@ __RCSID("$NetBSD: res_init.c,v 1.15 2008 #include #include #include +#include #include +#define HAVE_MD5 +#include + +#ifndef HAVE_MD5 +# include "../dst/md5.h" +#else +# ifdef SOLARIS2 +# include +# endif +#endif +#ifndef _MD5_H_ +# define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */ +#endif + #include "port_after.h" #if 0 @@ -142,6 +159,9 @@ static u_int32_t net_mask __P((struct in # define isascii(c) (!(c & 0200)) #endif +static struct timespec __res_conf_time; +static const struct timespec ts = { 0, 0 }; + /* * Resolver state default settings. */ @@ -169,8 +189,6 @@ static u_int32_t net_mask __P((struct in */ int res_ninit(res_state statp) { - extern int __res_vinit(res_state, int); - return (__res_vinit(statp, 0)); } @@ -190,20 +208,21 @@ __res_vinit(res_state statp, int preinit #endif int dots; union res_sockaddr_union u[2]; - int maxns = MAXNS; 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->id = res_randomid(); } - - 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 @@ -328,6 +347,9 @@ __res_vinit(res_state statp, int preinit 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 */ @@ -475,7 +497,21 @@ __res_vinit(res_state statp, int preinit #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 @@ -523,10 +559,42 @@ __res_vinit(res_state statp, int preinit if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(statp, cp, "env"); statp->options |= RES_INIT; - return (statp->res_h_errno); } +int +res_check(res_state statp, struct timespec *mtime) +{ + /* + * 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) + goto out; + + switch (kevent(statp->_u._ext.ext->kq, NULL, 0, &ke, 1, &ts)) { + case 0: + case -1: +out: + if (mtime) + *mtime = __res_conf_time; + return 0; + default: + break; + } + } + (void)__res_vinit(statp, 0); + if (mtime) + *mtime = __res_conf_time; + return 1; +} + static void res_setoptions(res_state statp, const char *options, const char *source) { @@ -672,12 +740,48 @@ net_mask(in) /*!< XXX - should really u } #endif +static u_char srnd[16]; + +void +res_rndinit(res_state statp) +{ + struct timeval now; + u_int32_t u32; + u_int16_t u16; + u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd; + + gettimeofday(&now, NULL); + u32 = (u_int32_t)now.tv_sec; + memcpy(rnd, &u32, 4); + u32 = now.tv_usec; + memcpy(rnd + 4, &u32, 4); + u32 += (u_int32_t)now.tv_sec; + memcpy(rnd + 8, &u32, 4); + u16 = getpid(); + memcpy(rnd + 12, &u16, 2); +} + u_int -res_randomid(void) { +res_nrandomid(res_state statp) { struct timeval now; + u_int16_t u16; + MD5_CTX ctx; + u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd; gettimeofday(&now, NULL); - return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); + u16 = (u_int16_t) (now.tv_sec ^ now.tv_usec); + memcpy(rnd + 14, &u16, 2); +#ifndef HAVE_MD5 + MD5_Init(&ctx); + MD5_Update(&ctx, rnd, 16); + MD5_Final(rnd, &ctx); +#else + MD5Init(&ctx); + MD5Update(&ctx, rnd, 16); + MD5Final(rnd, &ctx); +#endif + memcpy(&u16, rnd + 14, 2); + return ((u_int) u16); } /*% @@ -707,10 +811,19 @@ res_nclose(res_state statp) { void res_ndestroy(res_state statp) { res_nclose(statp); - if (statp->_u._ext.ext != NULL) + 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; + } + if (statp->_rnd != NULL) { + free(statp->_rnd); + statp->_rnd = NULL; + } statp->options &= ~RES_INIT; - statp->_u._ext.ext = NULL; } const char *