The branch, master has been updated
       via  f34b454 rwrap: make use of res_{get,set}servers() for FreeBSD
       via  4eb4e25 rwrap: split out a rwrap_set_nameservers() function
       via  93702c8 rwrap: split out rwrap_{get,log}_nameservers() functions
       via  be1a294 rwrap: split out a rwrap_reset_nameservers() function
       via  e47b20d rwrap: let configure use define HAVE_RES_STATE_U_EXT_NSADDRS
       via  2cc5920 rwrap: fix resolv wrapper with ipv6 addresses and old glibc 
versions
       via  396e83a tests/test_res_init.c: avoid using public ipv6 addresses 
from google in tests
      from  3ab29a2 rwrap: improve logging messages by including getprogname()

https://git.samba.org/?p=resolv_wrapper.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit f34b4540fd1b860ecff38f9caaa6f4c48197a18a
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Mar 10 13:11:40 2020 +0100

    rwrap: make use of res_{get,set}servers() for FreeBSD
    
    This way don't depend on the opaque structure on FreeBSD
    and have support for ipv6 nameservers.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit 4eb4e25b89bcd5a10b9f0e3e42c4181b65518adf
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Mar 10 13:07:25 2020 +0100

    rwrap: split out a rwrap_set_nameservers() function
    
    This will make it easier to add support for ipv6 nameservers
    on FreeBSD in the next step.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit 93702c87726ac9f29df41e192c105e2f030d1d80
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Mar 10 13:07:25 2020 +0100

    rwrap: split out rwrap_{get,log}_nameservers() functions
    
    This will make it easier to add support for ipv6 nameservers
    on FreeBSD in the next step.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit be1a2940aff74edc7b6063b1772558f63eb82544
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Mar 10 13:07:25 2020 +0100

    rwrap: split out a rwrap_reset_nameservers() function
    
    This will make it easier to add support for ipv6 nameservers
    on FreeBSD in the following commits.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit e47b20d78b1d5ba9b66cb054659ed338d43f469e
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Mar 18 17:01:48 2020 +0100

    rwrap: let configure use define HAVE_RES_STATE_U_EXT_NSADDRS
    
    The configure check should describe what it checked for.
    Let the code logic decide if that means we expect
    HAVE_RESOLV_IPV6_NSADDRS to be defined.
    
    We'll get another condition that sets HAVE_RESOLV_IPV6_NSADDRS
    in the following commits.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit 2cc59200e35fe6251871d60a53f8a0886ec82fb5
Author: Stefan Metzmacher <me...@samba.org>
Date:   Thu Feb 14 15:46:22 2019 +0100

    rwrap: fix resolv wrapper with ipv6 addresses and old glibc versions
    
    The handling of __res_state._u._ext was different before
    this glibc commit (e.g. glibc-2.19):
    
      commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7
      Author:     Andreas Schwab <sch...@suse.de>
      AuthorDate: Thu Feb 19 15:52:08 2015 +0100
      Commit:     Andreas Schwab <sch...@suse.de>
      CommitDate: Thu May 21 15:16:37 2015 +0200
    
          Simplify handling of nameserver configuration in resolver
    
          Remove use of ext.nsmap member of struct __res_state and always use
          an identity mapping betwen the nsaddr_list array and the ext.nsaddrs
          array.  The fact that a nameserver has an IPv6 address is signalled by
          setting nsaddr_list[].sin_family to zero.
    
    As a result of fixing this, it's now possible to run 'test_res_init'
    even without using resolv_wrapper.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit 396e83a1537a6f5df1cbe8aa152180c36cd18764
Author: Stefan Metzmacher <me...@samba.org>
Date:   Fri Feb 15 17:24:57 2019 +0100

    tests/test_res_init.c: avoid using public ipv6 addresses from google in 
tests
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 ConfigureChecks.cmake |  10 +-
 config.h.cmake        |   4 +-
 src/resolv_wrapper.c  | 370 +++++++++++++++++++++++++++++++++++++-------------
 tests/test_res_init.c |  84 ++++++++----
 4 files changed, 347 insertions(+), 121 deletions(-)


Changeset truncated at 500 lines:

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index ae9437b..8444232 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -173,7 +173,15 @@ int main(void) {
     return 0;
 }" HAVE_IPV6)
 
-check_struct_has_member("struct __res_state" _u._ext.nsaddrs resolv.h 
HAVE_RESOLV_IPV6_NSADDRS)
+check_struct_has_member("struct __res_state" _u._ext.nsaddrs
+                        "sys/socket.h;netinet/in.h;resolv.h"
+                        HAVE_RES_STATE_U_EXT_NSADDRS)
+check_struct_has_member("union res_sockaddr_union" sin
+                        "sys/socket.h;netinet/in.h;resolv.h"
+                        HAVE_RES_SOCKADDR_UNION_SIN)
+check_struct_has_member("union res_sockaddr_union" sin6
+                        "sys/socket.h;netinet/in.h;resolv.h"
+                        HAVE_RES_SOCKADDR_UNION_SIN6)
 
 check_c_source_compiles("
 void log_fn(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
diff --git a/config.h.cmake b/config.h.cmake
index 0c2fa35..8eba17b 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -55,7 +55,9 @@
 /**************************** OPTIONS ****************************/
 
 #cmakedefine HAVE_IPV6 1
-#cmakedefine HAVE_RESOLV_IPV6_NSADDRS 1
+#cmakedefine HAVE_RES_STATE_U_EXT_NSADDRS 1
+#cmakedefine HAVE_RES_SOCKADDR_UNION_SIN 1
+#cmakedefine HAVE_RES_SOCKADDR_UNION_SIN6 1
 
 #cmakedefine HAVE_ATTRIBUTE_PRINTF_FORMAT 1
 #cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1
diff --git a/src/resolv_wrapper.c b/src/resolv_wrapper.c
index cbca248..0d3f34c 100644
--- a/src/resolv_wrapper.c
+++ b/src/resolv_wrapper.c
@@ -52,6 +52,10 @@
 
 #include <resolv.h>
 
+#if defined(HAVE_RES_STATE_U_EXT_NSADDRS) || 
defined(HAVE_RES_SOCKADDR_UNION_SIN6)
+#define HAVE_RESOLV_IPV6_NSADDRS 1
+#endif
+
 /* GCC has printf type attribute check. */
 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
@@ -173,6 +177,12 @@ static void rwrap_log(enum rwrap_dbglvl_e dbglvl,
 
 #define RWRAP_MAX_RECURSION 64
 
+union rwrap_sockaddr {
+       struct sockaddr sa;
+       struct sockaddr_in in;
+       struct sockaddr_in6 in6;
+};
+
 /* Priority and weight can be omitted from the hosts file, but need to be part
  * of the output
  */
@@ -1602,12 +1612,235 @@ static int libc_res_nsearch(struct __res_state *state,
  *   RES_HELPER
  ***************************************************************************/
 
+static size_t rwrap_get_nameservers(struct __res_state *state,
+                                   size_t nserv,
+                                   union rwrap_sockaddr *nsaddrs)
+{
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+       union res_sockaddr_union set[MAXNS];
+       size_t i;
+       int rc;
+
+       memset(set, 0, sizeof(set));
+       memset(nsaddrs, 0, sizeof(*nsaddrs) * nserv);
+
+       if (nserv > MAXNS) {
+               nserv = MAXNS;
+       }
+
+       rc = res_getservers(state, set, nserv);
+       if (rc <= 0) {
+               return 0;
+       }
+       if (rc < nserv) {
+               nserv = rc;
+       }
+
+       for (i = 0; i < nserv; i++) {
+               switch (set[i].sin.sin_family) {
+               case AF_INET:
+                       nsaddrs[i] = (union rwrap_sockaddr) {
+                               .in = set[i].sin,
+                       };
+                       break;
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN6
+               case AF_INET6:
+                       nsaddrs[i] = (union rwrap_sockaddr) {
+                               .in6 = set[i].sin6,
+                       };
+                       break;
+#endif
+               }
+       }
+
+       return nserv;
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+       size_t i;
+
+       memset(nsaddrs, 0, sizeof(*nsaddrs) * nserv);
+
+       if (nserv > (size_t)state->nscount) {
+               nserv = (size_t)state->nscount;
+       }
+
+       for (i = 0; i < nserv; i++) {
+#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+               if (state->_u._ext.nsaddrs[i] != NULL) {
+                       nsaddrs[i] = (union rwrap_sockaddr) {
+                               .in6 = *state->_u._ext.nsaddrs[i],
+                       };
+               } else
+#endif /* HAVE_RES_STATE_U_EXT_NSADDRS */
+               {
+                       nsaddrs[i] = (union rwrap_sockaddr) {
+                               .in = state->nsaddr_list[i],
+                       };
+               }
+       }
+
+       return nserv;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+}
+
+static void rwrap_log_nameservers(enum rwrap_dbglvl_e dbglvl,
+                                 const char *func,
+                                 struct __res_state *state)
+{
+       union rwrap_sockaddr nsaddrs[MAXNS];
+       size_t nserv = MAXNS;
+       size_t i;
+
+       memset(nsaddrs, 0, sizeof(nsaddrs));
+       nserv = rwrap_get_nameservers(state, nserv, nsaddrs);
+       for (i = 0; i < nserv; i++) {
+               char ip[INET6_ADDRSTRLEN];
+
+               switch (nsaddrs[i].sa.sa_family) {
+               case AF_INET:
+                       inet_ntop(AF_INET, &(nsaddrs[i].in.sin_addr),
+                                 ip, sizeof(ip));
+                       break;
+               case AF_INET6:
+                       inet_ntop(AF_INET6, &(nsaddrs[i].in6.sin6_addr),
+                                 ip, sizeof(ip));
+                       break;
+               default:
+                       snprintf(ip, sizeof(ip), "<unknown sa_family=%d",
+                                nsaddrs[i].sa.sa_family);
+                       break;
+               }
+
+               rwrap_log(dbglvl, func,
+                         "        nameserver: %s",
+                         ip);
+       }
+}
+
+static void rwrap_reset_nameservers(struct __res_state *state)
+{
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+       res_setservers(state, NULL, 0);
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+       size_t i;
+
+       for (i = 0; i < (size_t)state->nscount; i++) {
+               if (state->_u._ext.nssocks[i] != -1) {
+                       close(state->_u._ext.nssocks[i]);
+                       state->_u._ext.nssocks[i] = -1;
+               }
+               SAFE_FREE(state->_u._ext.nsaddrs[i]);
+       }
+       memset(&state->_u._ext, 0, sizeof(state->_u._ext));
+       for (i = 0; i < MAXNS; i++) {
+               state->_u._ext.nssocks[i] = -1;
+               state->_u._ext.nsmap[i] = MAXNS + 1;
+       }
+       state->ipv6_unavail = false;
+#endif
+       memset(state->nsaddr_list, 0, sizeof(state->nsaddr_list));
+       state->nscount = 0;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+}
+
+static int rwrap_set_nameservers(struct __res_state *state,
+                                size_t nserv,
+                                const union rwrap_sockaddr *nsaddrs)
+{
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+       union res_sockaddr_union set[MAXNS];
+       size_t i;
+
+       memset(set, 0, sizeof(set));
+
+       if (nserv > MAXNS) {
+               nserv = MAXNS;
+       }
+
+       rwrap_reset_nameservers(state);
+
+       for (i = 0; i < nserv; i++) {
+               switch (nsaddrs[i].sa.sa_family) {
+               case AF_INET:
+                       set[i] = (union res_sockaddr_union) {
+                               .sin = nsaddrs[i].in,
+                       };
+                       break;
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN6
+               case AF_INET6:
+                       set[i] = (union res_sockaddr_union) {
+                               .sin6 = nsaddrs[i].in6,
+                       };
+                       break;
+#endif
+               default:
+                       RWRAP_LOG(RWRAP_LOG_ERROR,
+                                 "Internal error unhandled sa_family=%d",
+                                 nsaddrs[i].sa.sa_family);
+                       errno = ENOSYS;
+                       return -1;
+               }
+       }
+
+       res_setservers(state, set, nserv);
+       return 0;
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+       size_t i;
+
+       if (nserv > MAXNS) {
+               nserv = MAXNS;
+       }
+       rwrap_reset_nameservers(state);
+
+       for (i = 0; i < nserv; i++) {
+               switch (nsaddrs[i].sa.sa_family) {
+               case AF_INET:
+                       state->nsaddr_list[i] = nsaddrs[i].in;
+                       break;
+#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+               case AF_INET6:
+                       state->_u._ext.nsaddrs[i] = 
malloc(sizeof(nsaddrs[i].in6));
+                       if (state->_u._ext.nsaddrs[i] == NULL) {
+                               rwrap_reset_nameservers(state);
+                               errno = ENOMEM;
+                               return -1;
+                       }
+                       *state->_u._ext.nsaddrs[i] = nsaddrs[i].in6;
+                       state->_u._ext.nssocks[i] = -1;
+                       state->_u._ext.nsmap[i] = MAXNS + 1;
+                       state->_u._ext.nscount6++;
+                       break;
+#endif
+               default:
+                       RWRAP_LOG(RWRAP_LOG_ERROR,
+                                 "Internal error unhandled sa_family=%d",
+                                 nsaddrs[i].sa.sa_family);
+                       rwrap_reset_nameservers(state);
+                       errno = ENOSYS;
+                       return -1;
+               }
+       }
+
+       /*
+        * note that state->_u._ext.nscount is left as 0,
+        * this matches glibc and allows resolv wrapper
+        * to work with most (maybe all) glibc versions.
+        */
+       state->nscount = i;
+
+       return 0;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+}
+
 static int rwrap_parse_resolv_conf(struct __res_state *state,
                                   const char *resolv_conf)
 {
        FILE *fp;
        char buf[BUFSIZ];
-       int nserv = 0;
+       size_t nserv = 0;
+       union rwrap_sockaddr nsaddrs[MAXNS];
+
+       memset(nsaddrs, 0, sizeof(nsaddrs));
 
        fp = fopen(resolv_conf, "r");
        if (fp == NULL) {
@@ -1627,6 +1860,7 @@ static int rwrap_parse_resolv_conf(struct __res_state 
*state,
 
                if (RESOLV_MATCH(buf, "nameserver") && nserv < MAXNS) {
                        struct in_addr a;
+                       struct in6_addr a6;
                        char *q;
                        int ok;
 
@@ -1645,57 +1879,42 @@ static int rwrap_parse_resolv_conf(struct __res_state 
*state,
 
                        ok = inet_pton(AF_INET, p, &a);
                        if (ok) {
-                               state->nsaddr_list[state->nscount] = (struct 
sockaddr_in) {
-                                       .sin_family = AF_INET,
-                                       .sin_addr = a,
-                                       .sin_port = htons(53),
-                                       .sin_zero = { 0 },
+                               nsaddrs[nserv] = (union rwrap_sockaddr) {
+                                       .in = {
+                                               .sin_family = AF_INET,
+                                               .sin_addr = a,
+                                               .sin_port = htons(53),
+                                               .sin_zero = { 0 },
+                                       },
                                };
 
-                               state->nscount++;
                                nserv++;
-                       } else {
+                               continue;
+                       }
+
+                       ok = inet_pton(AF_INET6, p, &a6);
+                       if (ok) {
 #ifdef HAVE_RESOLV_IPV6_NSADDRS
-                               /* IPv6 */
-                               struct in6_addr a6;
-                               ok = inet_pton(AF_INET6, p, &a6);
-                               if (ok) {
-                                       struct sockaddr_in6 *sa6;
-
-                                       sa6 = malloc(sizeof(*sa6));
-                                       if (sa6 == NULL) {
-                                               fclose(fp);
-                                               return -1;
-                                       }
-
-                                       sa6->sin6_family = AF_INET6;
-                                       sa6->sin6_port = htons(53);
-                                       sa6->sin6_flowinfo = 0;
-                                       sa6->sin6_addr = a6;
-
-                                       
state->_u._ext.nsaddrs[state->_u._ext.nscount] = sa6;
-                                       
state->_u._ext.nssocks[state->_u._ext.nscount] = -1;
-                                       
state->_u._ext.nsmap[state->_u._ext.nscount] = MAXNS + 1;
-
-                                       state->_u._ext.nscount++;
-                                       nserv++;
-                               } else {
-                                       RWRAP_LOG(RWRAP_LOG_ERROR,
-                                               "Malformed DNS server");
-                                       continue;
-                               }
+                               nsaddrs[nserv] = (union rwrap_sockaddr) {
+                                       .in6 = {
+
+                                               .sin6_family = AF_INET6,
+                                               .sin6_port = htons(53),
+                                               .sin6_flowinfo = 0,
+                                               .sin6_addr = a6,
+                                       },
+                               };
+                               nserv++;
+                               continue;
 #else /* !HAVE_RESOLV_IPV6_NSADDRS */
-                               /*
-                                * BSD uses an opaque structure to store the
-                                * IPv6 addresses. So we can not simply store
-                                * these addresses the same way as above.
-                                */
                                RWRAP_LOG(RWRAP_LOG_WARN,
                                          "resolve_wrapper does not support "
                                          "IPv6 on this platform");
-                                       continue;
+                               continue;
 #endif
                        }
+
+                       RWRAP_LOG(RWRAP_LOG_ERROR, "Malformed DNS server[%s]", 
p);
                        continue;
                } /* TODO: match other keywords */
        }
@@ -1709,7 +1928,16 @@ static int rwrap_parse_resolv_conf(struct __res_state 
*state,
        }
 
        fclose(fp);
-       return 0;
+
+       if (nserv == 0) {
+               RWRAP_LOG(RWRAP_LOG_ERROR,
+                         "No usable nameservers found in %s",
+                         resolv_conf);
+               errno = ESRCH;
+               return -1;
+       }
+
+       return rwrap_set_nameservers(state, nserv, nsaddrs);
 }
 
 /****************************************************************************
@@ -1725,21 +1953,6 @@ static int rwrap_res_ninit(struct __res_state *state)
                const char *resolv_conf = getenv("RESOLV_WRAPPER_CONF");
 
                if (resolv_conf != NULL) {
-                       uint16_t i;
-
-                       (void)i; /* maybe unused */
-
-                       /* Delete name servers */
-                       state->nscount = 0;
-                       memset(state->nsaddr_list, 0, 
sizeof(state->nsaddr_list));
-
-#ifdef HAVE_RESOLV_IPV6_NSADDRS
-                       state->_u._ext.nscount = 0;
-                       for (i = 0; i < state->_u._ext.nscount; i++) {
-                               SAFE_FREE(state->_u._ext.nsaddrs[i]);
-                       }
-#endif
-
                        rc = rwrap_parse_resolv_conf(state, resolv_conf);
                }
        }
@@ -1786,19 +1999,8 @@ int __res_init(void)
 
 static void rwrap_res_nclose(struct __res_state *state)
 {
-#ifdef HAVE_RESOLV_IPV6_NSADDRS
-       int i;
-#endif
-
+       rwrap_reset_nameservers(state);
        libc_res_nclose(state);
-
-#ifdef HAVE_RESOLV_IPV6_NSADDRS
-       if (state != NULL) {
-               for (i = 0; i < state->_u._ext.nscount; i++) {
-                       SAFE_FREE(state->_u._ext.nsaddrs[i]);
-               }
-       }
-#endif
 }
 
 #if !defined(res_nclose) && defined(HAVE_RES_NCLOSE)
@@ -1841,23 +2043,11 @@ static int rwrap_res_nquery(struct __res_state *state,
 {
        int rc;
        const char *fake_hosts;
-#ifndef NDEBUG
-       int i;
-#endif
 
        RWRAP_LOG(RWRAP_LOG_TRACE,
                  "Resolve the domain name [%s] - class=%d, type=%d",
                  dname, class, type);
-#ifndef NDEBUG
-       for (i = 0; i < state->nscount; i++) {
-               char ip[INET6_ADDRSTRLEN];
-
-               inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, ip, 
sizeof(ip));
-               RWRAP_LOG(RWRAP_LOG_TRACE,
-                         "        nameserver: %s",
-                         ip);
-       }
-#endif
+       rwrap_log_nameservers(RWRAP_LOG_TRACE, __func__, state);
 
        fake_hosts = getenv("RESOLV_WRAPPER_HOSTS");
        if (fake_hosts != NULL) {
@@ -1950,23 +2140,11 @@ static int rwrap_res_nsearch(struct __res_state *state,
 {
        int rc;
        const char *fake_hosts;
-#ifndef NDEBUG
-       int i;
-#endif
 
        RWRAP_LOG(RWRAP_LOG_TRACE,
                  "Resolve the domain name [%s] - class=%d, type=%d",
                  dname, class, type);
-#ifndef NDEBUG
-       for (i = 0; i < state->nscount; i++) {
-               char ip[INET6_ADDRSTRLEN];
-
-               inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, ip, 
sizeof(ip));
-               RWRAP_LOG(RWRAP_LOG_TRACE,
-                         "        nameserver: %s",
-                         ip);
-       }
-#endif


-- 
Resolv Wrapper Repository

Reply via email to