[CFR] reflect resolv.conf update to running application

From: Hajimu UMEMOTO (ume_at_FreeBSD.org)
Date: 08/20/05

  • Next message: Pawel Jakub Dawidek: "Re: cvs commit: src/sys/geom/label g_label.c"
    Date: Sat, 20 Aug 2005 20:11:16 +0900
    To: arch@FreeBSD.org
    
    

    Hi,

    Our resolver reads resolv.conf once, and never re-read it. Recent
    OpenBSD changed to re-read resolv.conf when it is updated. I believe
    it is useful specially for mobile environment. So, I made a patch for
    our resolver. Please review it.

    Index: lib/libc/net/getaddrinfo.c
    diff -u -p lib/libc/net/getaddrinfo.c.orig lib/libc/net/getaddrinfo.c
    --- lib/libc/net/getaddrinfo.c.orig Sat May 21 22:46:37 2005
    +++ lib/libc/net/getaddrinfo.c Sat May 21 23:20:27 2005
    @@ -2443,7 +2443,7 @@ res_searchN(name, target)
             int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
             char abuf[MAXDNAME];
     
    - if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    + if (_res_init() == -1) {
                     h_errno = NETDB_INTERNAL;
                     return (-1);
             }
    Index: lib/libc/net/gethostbydns.c
    diff -u -p lib/libc/net/gethostbydns.c.orig lib/libc/net/gethostbydns.c
    --- lib/libc/net/gethostbydns.c.orig Sat May 21 22:46:37 2005
    +++ lib/libc/net/gethostbydns.c Sat May 21 23:20:27 2005
    @@ -538,10 +538,6 @@ _dns_gethostbyaddr(void *rval, void *cb_
             he = va_arg(ap, struct hostent *);
             hed = va_arg(ap, struct hostent_data *);
     
    - if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    - h_errno = NETDB_INTERNAL;
    - return NS_UNAVAIL;
    - }
             switch (af) {
             case AF_INET:
                     (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
    Index: lib/libc/net/gethostnamadr.c
    diff -u -p lib/libc/net/gethostnamadr.c.orig lib/libc/net/gethostnamadr.c
    --- lib/libc/net/gethostnamadr.c.orig Sat May 21 22:46:37 2005
    +++ lib/libc/net/gethostnamadr.c Sat May 21 23:20:27 2005
    @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/lib/libc/net/get
     #include <resolv.h> /* XXX hack for _res */
     #include "un-namespace.h"
     #include "netdb_private.h"
    +#include "res_config.h"
     
     extern int _ht_gethostbyname(void *, void *, va_list);
     extern int _dns_gethostbyname(void *, void *, va_list);
    @@ -264,7 +265,7 @@ gethostbyaddr_r(const char *addr, int le
                     { 0 }
             };
     
    - if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    + if (_res_init() == -1) {
                     h_errno = NETDB_INTERNAL;
                     return -1;
             }
    Index: lib/libc/net/getnetbydns.c
    diff -u -p lib/libc/net/getnetbydns.c.orig lib/libc/net/getnetbydns.c
    --- lib/libc/net/getnetbydns.c.orig Sat May 21 22:46:37 2005
    +++ lib/libc/net/getnetbydns.c Sat May 21 23:20:27 2005
    @@ -304,6 +304,10 @@ _dns_getnetbyaddr(void *rval, void *cb_d
                         netbr[1], netbr[0]);
                     break;
             }
    + if (_res_init() == -1) {
    + h_errno = NETDB_INTERNAL;
    + return NS_UNAVAIL;
    + }
             if ((buf = malloc(sizeof(*buf))) == NULL) {
                     h_errno = NETDB_INTERNAL;
                     return NS_NOTFOUND;
    Index: lib/libc/net/name6.c
    diff -u -p lib/libc/net/name6.c.orig lib/libc/net/name6.c
    --- lib/libc/net/name6.c.orig Sat May 21 22:46:38 2005
    +++ lib/libc/net/name6.c Sat May 21 23:20:27 2005
    @@ -121,6 +121,7 @@ __FBSDID("$FreeBSD: src/lib/libc/net/nam
     #include <unistd.h>
     #include "un-namespace.h"
     #include "netdb_private.h"
    +#include "res_config.h"
     
     #ifndef _PATH_HOSTS
     #define _PATH_HOSTS "/etc/hosts"
    @@ -1810,11 +1811,9 @@ _dns_ghbyaddr(void *rval, void *cb_data,
                     return NS_NOTFOUND;
             }
     
    - if ((_res.options & RES_INIT) == 0) {
    - if (res_init() < 0) {
    - *errp = h_errno;
    - return NS_UNAVAIL;
    - }
    + if (_res_init() < 0) {
    + *errp = h_errno;
    + return NS_UNAVAIL;
             }
             memset(&hbuf, 0, sizeof(hbuf));
             hbuf.h_name = NULL;
    Index: lib/libc/net/res_config.h
    diff -u lib/libc/net/res_config.h.orig lib/libc/net/res_config.h
    --- lib/libc/net/res_config.h.orig Sat Mar 23 08:41:54 2002
    +++ lib/libc/net/res_config.h Sat May 21 23:20:27 2005
    @@ -8,3 +8,5 @@
     #define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
     #define CHECK_SRVR_ADDR 1 /* confirm that the server requested sent the reply */
     #define BIND_UPDATE 1 /* update support */
    +
    +int _res_init(void);
    Index: lib/libc/net/res_init.c
    diff -u -p lib/libc/net/res_init.c.orig lib/libc/net/res_init.c
    --- lib/libc/net/res_init.c.orig Thu Feb 26 06:03:45 2004
    +++ lib/libc/net/res_init.c Sat May 21 23:20:27 2005
    @@ -78,11 +78,13 @@ __FBSDID("$FreeBSD: src/lib/libc/net/res
     #include <sys/types.h>
     #include <sys/param.h>
     #include <sys/socket.h>
    +#include <sys/stat.h>
     #include <sys/time.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
     #include <arpa/nameser.h>
     #include <ctype.h>
    +#include <errno.h>
     #include <limits.h>
     #include <resolv.h>
     #include <stdio.h>
    @@ -100,6 +102,7 @@ __FBSDID("$FreeBSD: src/lib/libc/net/res
     #undef h_errno
     extern int h_errno;
     
    +static void res_readconf(void);
     static void res_setoptions(char *, char *);
     
     #ifdef RESOLVSORT
    @@ -112,6 +115,18 @@ static u_int32_t net_mask(struct in_addr
     # define isascii(c) (!(c & 0200))
     #endif
     
    +#define timespecclear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0)
    +#define timespeccmp(tvp, uvp, cmp) \
    + (((tvp)->tv_sec == (uvp)->tv_sec) ? \
    + ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \
    + ((tvp)->tv_sec cmp (uvp)->tv_sec))
    +
    +struct __res_conf_private {
    + struct timespec mtimespec;
    +};
    +
    +static struct __res_conf_private *___res_conf_private(void);
    +
     /*
      * Check structure for failed per-thread allocations.
      */
    @@ -119,6 +134,7 @@ static struct res_per_thread {
             struct __res_state res_state;
             struct __res_state_ext res_state_ext;
             struct __res_send_private res_send_private;
    + struct __res_conf_private res_conf_private;
             int h_errno;
     } _res_per_thread_bogus = { .res_send_private = { .s = -1 } }; /* socket */
     
    @@ -146,21 +162,8 @@ static struct res_per_thread {
     int
     res_init()
     {
    - FILE *fp;
             struct __res_send_private *rsp;
    - char *cp, **pp;
    - int n;
    - char buf[MAXDNAME];
    - int nserv = 0; /* number of nameserver records read from file */
    - int haveenv = 0;
    - int havesearch = 0;
    -#ifdef RESOLVSORT
    - int nsort = 0;
    - char *net;
    -#endif
    -#ifndef RFC1535
    - int dots;
    -#endif
    + char *cp;
     
             /*
              * If allocation of memory for this thread's resolver has failed,
    @@ -208,6 +211,37 @@ res_init()
             if (!_res.id)
                     _res.id = res_randomid();
     
    + _res.pfcode = 0;
    + res_readconf();
    +
    + if (issetugid())
    + _res.options |= RES_NOALIASES;
    + else if ((cp = getenv("RES_OPTIONS")) != NULL)
    + res_setoptions(cp, "env");
    + _res.options |= RES_INIT;
    + return (0);
    +}
    +
    +static void
    +res_readconf()
    +{
    + struct __res_conf_private *rcp;
    + FILE *fp;
    + char *cp, **pp;
    + int n;
    + char buf[MAXDNAME];
    + int nserv = 0; /* number of nameserver records read from file */
    + int haveenv = 0;
    + int havesearch = 0;
    +#ifdef RESOLVSORT
    + int nsort = 0;
    + char *net;
    +#endif
    +#ifndef RFC1535
    + int dots;
    +#endif
    + struct stat sb;
    +
     #ifdef USELOOPBACK
             _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
     #else
    @@ -220,7 +254,6 @@ res_init()
                     memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len);
             _res.nscount = 1;
             _res.ndots = 1;
    - _res.pfcode = 0;
     
             /* Allow user to override the local domain definition */
             if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
    @@ -262,7 +295,10 @@ res_init()
             (line[sizeof(name) - 1] == ' ' || \
              line[sizeof(name) - 1] == '\t'))
     
    + rcp = ___res_conf_private();
             if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
    + if (fstat(fileno(fp), &sb) == 0)
    + rcp->mtimespec = sb.st_mtimespec;
                 /* read the config file */
                 while (fgets(buf, sizeof(buf), fp) != NULL) {
                     /* skip comments */
    @@ -396,11 +432,11 @@ res_init()
                                     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);
                                 }
                                 _res_ext.sort_list[nsort].af = AF_INET;
    @@ -465,13 +501,14 @@ res_init()
                         continue;
                     }
                 }
    - if (nserv > 1)
    + if (nserv > 1)
                     _res.nscount = nserv;
     #ifdef RESOLVSORT
                 _res.nsort = nsort;
     #endif
                 (void) fclose(fp);
    - }
    + } else
    + timespecclear(&rcp->mtimespec);
             if (_res.defdname[0] == 0 &&
                 gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
                 (cp = strchr(buf, '.')) != NULL)
    @@ -507,12 +544,27 @@ res_init()
     #endif
     #endif /* !RFC1535 */
             }
    +}
     
    - if (issetugid())
    - _res.options |= RES_NOALIASES;
    - else if ((cp = getenv("RES_OPTIONS")) != NULL)
    - res_setoptions(cp, "env");
    - _res.options |= RES_INIT;
    +int
    +_res_init(void)
    +{
    + struct __res_conf_private *rcp;
    + struct stat sb;
    +
    + if ((_res.options & RES_INIT) == 0)
    + return (res_init());
    +
    + if (stat(_PATH_RESCONF, &sb) == -1) {
    + /*
    + * Lost the file, in chroot?
    + * Don' trash settings
    + */
    + return (0);
    + }
    + rcp = ___res_conf_private();
    + if (timespeccmp(&sb.st_mtimespec, &rcp->mtimespec, !=))
    + res_readconf();
             return (0);
     }
     
    @@ -629,6 +681,7 @@ struct __res_state _res;
     #endif
     struct __res_state_ext _res_ext;
     static struct __res_send_private _res_send_private = { .s = -1 }; /* socket */
    +static struct __res_conf_private _res_conf_private;
     
     static thread_key_t res_key;
     static once_t res_init_once = ONCE_INITIALIZER;
    @@ -697,6 +750,14 @@ ___res_send_private(void)
             if (thr_main() != 0)
                     return (&_res_send_private);
             return (&allocate_res()->res_send_private);
    +}
    +
    +struct __res_conf_private *
    +___res_conf_private(void)
    +{
    + if (thr_main() != 0)
    + return (&_res_conf_private);
    + return (&allocate_res()->res_conf_private);
     }
     
     int *
    Index: lib/libc/net/res_query.c
    diff -u -p lib/libc/net/res_query.c.orig lib/libc/net/res_query.c
    --- lib/libc/net/res_query.c.orig Sat May 21 22:46:39 2005
    +++ lib/libc/net/res_query.c Sat May 21 23:20:27 2005
    @@ -200,7 +200,7 @@ res_search(name, class, type, answer, an
             int trailing_dot, ret, saved_herrno;
             int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
     
    - if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    + if (_res_init() == -1) {
                     h_errno = NETDB_INTERNAL;
                     return (-1);
             }
    Index: lib/libc/net/res_update.c
    diff -u -p lib/libc/net/res_update.c.orig lib/libc/net/res_update.c
    --- lib/libc/net/res_update.c.orig Mon Sep 16 01:51:09 2002
    +++ lib/libc/net/res_update.c Sat May 21 23:20:27 2005
    @@ -36,6 +36,8 @@ __FBSDID("$FreeBSD: src/lib/libc/net/res
     #include <stdlib.h>
     #include <string.h>
     
    +#include "res_config.h"
    +
     /*
      * Separate a linked list of records into groups so that all records
      * in a group will belong to a single zone on the nameserver.
    @@ -84,7 +86,7 @@ res_update(ns_updrec *rrecp_in) {
             u_int16_t dlen, class, qclass, type, qtype;
             u_int32_t ttl;
     
    - if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    + if (_res_init() == -1) {
                     h_errno = NETDB_INTERNAL;
                     return (-1);
             }

    Sincerely,

    --
    Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
    ume@mahoroba.org  ume@{,jp.}FreeBSD.org
    http://www.imasy.org/~ume/
    _______________________________________________
    freebsd-arch@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-arch
    To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"
    

  • Next message: Pawel Jakub Dawidek: "Re: cvs commit: src/sys/geom/label g_label.c"