rwrap: Use our own rwrap_randomid()
[resolv_wrapper.git] / src / resolv_wrapper.c
index e1903c922d3d089908a826d78018d49073b4c578..899f4ccc7a97ce55ad9dcc00f75ac480db85f3ae 100644 (file)
@@ -52,7 +52,7 @@
 
 #include <resolv.h>
 
-#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+#if defined(HAVE_RES_STATE_U_EXT_NSADDRS) || defined(HAVE_RES_SOCKADDR_UNION_SIN6)
 #define HAVE_RESOLV_IPV6_NSADDRS 1
 #endif
 
@@ -434,6 +434,8 @@ static int rwrap_create_fake_ptr_rr(const char *key,
        return 0;
 }
 
+#define rwrap_randomid() 0xffff & getpid()
+
 /* Prepares a fake header with a single response. Advances header_blob */
 static ssize_t rwrap_fake_header(uint8_t **header_blob, size_t remaining,
                                 size_t ancount, size_t arcount)
@@ -451,7 +453,7 @@ static ssize_t rwrap_fake_header(uint8_t **header_blob, size_t remaining,
        h.blob = *header_blob;
        memset(h.blob, 0, NS_HFIXEDSZ);
 
-       h.header->id = res_randomid();          /* random query ID */
+       h.header->id = rwrap_randomid();        /* random query ID */
        h.header->qr = 1;                       /* response flag */
        h.header->rd = 1;                       /* recursion desired */
        h.header->ra = 1;                       /* recursion available */
@@ -1616,6 +1618,45 @@ 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);
@@ -1640,6 +1681,7 @@ static size_t rwrap_get_nameservers(struct __res_state *state,
        }
 
        return nserv;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
 }
 
 static void rwrap_log_nameservers(enum rwrap_dbglvl_e dbglvl,
@@ -1678,6 +1720,9 @@ static void rwrap_log_nameservers(enum rwrap_dbglvl_e dbglvl,
 
 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;
 
@@ -1697,12 +1742,51 @@ static void rwrap_reset_nameservers(struct __res_state *state)
 #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) {
@@ -1747,6 +1831,7 @@ static int rwrap_set_nameservers(struct __res_state *state,
        state->nscount = i;
 
        return 0;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
 }
 
 static int rwrap_parse_resolv_conf(struct __res_state *state,
@@ -1761,7 +1846,7 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
 
        fp = fopen(resolv_conf, "r");
        if (fp == NULL) {
-               RWRAP_LOG(RWRAP_LOG_ERROR,
+               RWRAP_LOG(RWRAP_LOG_WARN,
                          "Opening %s failed: %s",
                          resolv_conf, strerror(errno));
                return -1;
@@ -1847,7 +1932,7 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
        fclose(fp);
 
        if (nserv == 0) {
-               RWRAP_LOG(RWRAP_LOG_ERROR,
+               RWRAP_LOG(RWRAP_LOG_WARN,
                          "No usable nameservers found in %s",
                          resolv_conf);
                errno = ESRCH;