]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
intermediate commit
authorTCY16 <tom@nlnetlabs.nl>
Tue, 18 Oct 2022 13:25:47 +0000 (15:25 +0200)
committerTCY16 <tom@nlnetlabs.nl>
Tue, 18 Oct 2022 13:25:47 +0000 (15:25 +0200)
iterator/iterator.c
services/cache/infra.c
services/cache/infra.h
services/listen_dnsport.c
services/outside_network.c
services/outside_network.h

index ce4028924b27b37623efec7c3ed2b524c3595ccc..f49632cfbe3826b5b6e7a8bab3ef073ebb68ee8e 100644 (file)
@@ -68,6 +68,7 @@
 #include "sldns/str2wire.h"
 #include "sldns/parseutil.h"
 #include "sldns/sbuffer.h"
+#include "daemon/worker.h"
 
 /* in msec */
 int UNKNOWN_SERVER_NICENESS = 376;
@@ -3872,6 +3873,82 @@ process_request(struct module_qstate* qstate, struct iter_qstate* iq,
        iter_handle(qstate, iq, ie, id);
 }
 
+
+
+/** find the bound addr in the list of interfaces */
+static int
+get_bound_ip_if(struct outside_network* outnet,
+       struct sockaddr_storage *bound_addr, socklen_t bound_addrlen,
+       struct port_if* pif_return)
+{
+       int i = 0;
+       struct port_if* pif_list;
+       int pif_list_len;
+
+       /* Get the list of interfaces and check that that list isn't just the
+        * "any" address  */
+       if(addr_is_ip6(bound_addr, bound_addrlen)) {
+               pif_list = outnet->ip6_ifs;
+               pif_list_len = outnet->num_ip6;
+
+               // @TODO fix IPv6
+       } else {
+               pif_list = outnet->ip4_ifs;
+               pif_list_len = outnet->num_ip4;
+               struct sockaddr_storage addr_any;
+               socklen_t addr_any_len = 0;
+
+               struct sockaddr_storage addr_fake;
+               socklen_t addr_fake_len = 0;
+
+
+               if (!ipstrtoaddr("0.0.0.0", 0, &addr_any, &addr_any_len)) {
+                       // @TODO do something
+               }
+
+               if (!ipstrtoaddr("10.10.1.1", 0, &addr_fake, &addr_fake_len)) {
+                       // @TODO do something
+               }
+
+               log_addr(VERB_DETAIL, "!!!!! outnet->ip4_ifs->addr", &outnet->ip4_ifs->addr, bound_addrlen);
+               log_addr(VERB_DETAIL, "!!!!! addr_any", &addr_any, addr_any_len);
+
+               /* if we let the kernel decide the IP, fill in
+                * the previously used */
+               if (pif_list_len == 1 &&
+                       sockaddr_cmp_addr(&outnet->ip4_ifs->addr, outnet->ip4_ifs->addrlen,
+                               &addr_any, addr_any_len) == 0) {
+
+                       /* return the interface from the list, but substitute the
+                        * previously used address */
+                       memcpy(pif_return, outnet->ip4_ifs, sizeof(struct port_if));
+                       memcpy(&pif_return->addr, &addr_fake, addr_fake_len);
+                       pif_return->addrlen = addr_fake_len;
+
+                       log_addr(VERB_DETAIL, "!!!!! get_bound_ip_if: addr from ip4_ifs == 0.0.0.0, new is:", &pif_return->addr, outnet->ip4_ifs->addrlen);
+
+                       return 1;
+               }
+       }
+
+       if (pif_list_len == 0) {
+               return 0;
+       }
+
+       for (i = 0; i < pif_list_len; i++) {
+               struct port_if *iface = &pif_list[i];
+
+               if (iface->addrlen == bound_addrlen &&
+                       memcmp(&iface->addr, bound_addr, bound_addrlen)) {
+                       memcpy(pif_return, iface, sizeof(struct port_if));
+
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 /** process authoritative server reply */
 static void
 process_response(struct module_qstate* qstate, struct iter_qstate* iq, 
@@ -3940,19 +4017,29 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
                goto handle_it;
        }
 
-       /* handle the upstream response cookie if enabled*/
+       /* handle the upstream response cookie if enabled */
        if(qstate->env->cfg->upstream_cookies) {
                if (edns.opt_list_in &&
                        (cookie = edns_list_get_option(edns.opt_list_in,
                                LDNS_EDNS_COOKIE))){
                        struct sockaddr_storage bound_addr;
                        socklen_t bound_addrlen = sizeof(struct sockaddr);
+                       struct port_if pif;
+                       struct port_if *pif_ptr = &pif;
 
                        if(getsockname(qstate->reply->c->fd,
                                (struct sockaddr *) &bound_addr,
                                        &bound_addrlen) != -1) {
 
                                log_addr(VERB_DETAIL, "!!!!! iterator:udp socket:", &bound_addr, bound_addrlen);
+
+                               if (!(get_bound_ip_if(qstate->env->worker->back,
+                                       &bound_addr, bound_addrlen, pif_ptr))) {
+                                       bound_addrlen = 0;
+                               }
+
+                               log_addr(VERB_DETAIL, "!!!!! iterator:pif addr:", &pif.addr, pif.addrlen);
+
                        } else {
                                bound_addrlen = 0;
                        }
@@ -3964,8 +4051,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
                        if (cookie->opt_len == 24 &&
                                infra_set_server_cookie(qstate->env->infra_cache,
                                        &qstate->reply->addr, qstate->reply->addrlen,
-                                       iq->dp->name, iq->dp->namelen, &bound_addr,
-                                       bound_addrlen, cookie) >= 0) {
+                                       iq->dp->name, iq->dp->namelen, pif_ptr,
+                                       cookie) >= 0) {
                                /* log_hex() uses the verbosity levels of verbose() */
                                log_hex("complete cookie: ", cookie->opt_data,
                                        cookie->opt_len);
index bbcfd414da28e881a8d6bfb7177a78fc7111313a..f988a61dc53d13a680773df7b27b006ec990aa34 100644 (file)
@@ -383,18 +383,25 @@ infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr,
        return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
 }
 
+/* helper function to fill in random data into the client cookie*/
+void infra_fill_client_cookie_random(struct infra_cache* infra,
+       uint8_t* data) {
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               data[i] = ub_random_max(infra->random_state, 256);
+       }
+}
+
 /** init the data elements */
 static void
 data_entry_init(struct infra_cache* infra, struct lruhash_entry* e, 
        time_t timenow)
 {
-       int i;
        struct infra_data* data;
-       uint8_t cookie[8] = {0,0,0,0,0,0,0,0};
+       uint8_t client_cookie_data[8] = {0,0,0,0,0,0,0,0};
 
-       for (i = 0; i < 8; i++) {
-               cookie[i] = ub_random_max(infra->random_state, 256);
-       }
+       infra_fill_client_cookie_random(infra, client_cookie_data);
 
        data = (struct infra_data*)e->data;
        data->ttl = timenow + infra->host_ttl;
@@ -404,7 +411,8 @@ data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
        data->probedelay = 0;
        /* set EDNS cookie to zero, as this also sets the starting state*/
        memset(&data->cookie, 0, sizeof(struct edns_cookie));
-       memcpy(data->cookie.data.cookie, cookie, 8);
+       data->cookie.pif.out = NULL;
+       memcpy(data->cookie.data.cookie, client_cookie_data, 8);
        data->isdnsseclame = 0;
        data->rec_lame = 0;
        data->lame_type_A = 0;
@@ -705,41 +713,10 @@ infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
        return 1;
 }
 
-/** find the bound addr in the list of interfaces */
-static int
-get_bound_ip_if(struct outside_network* outnet,
-       struct sockaddr_storage bound_addr, socklen_t bound_addrlen,
-       struct port_if** pif_return)
-{
-       int i = 0;
-       struct port_if* pif_list;
-       int pif_list_len;
-
-       if(addr_is_ip6(&bound_addr, bound_addrlen)) {
-               pif_list = outnet->ip6_ifs;
-               pif_list_len = outnet->num_ip6;
-       } else {
-               pif_list = outnet->ip4_ifs;
-               pif_list_len = outnet->num_ip4;
-       }
-
-       for (i = 0; i < pif_list_len; i++) {
-               struct port_if *iface = &pif_list[i];
-
-               if (iface->addrlen == bound_addrlen &&
-                       memcmp(&iface->addr, &bound_addr, bound_addrlen)) {
-                       *pif_return = iface;
-                       return 1;
-               }
-       }
-       return 0;
-}
-
 int
 infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
        socklen_t addrlen, uint8_t* name, size_t namelen,
-       time_t timenow, struct outside_network* outnet, struct port_if** pif,
-       struct edns_cookie* cookie)
+       time_t timenow, struct edns_cookie* cookie)
 {
        struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
                name, namelen, 1);
@@ -763,21 +740,11 @@ infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
 
        data = (struct infra_data*) e->data;
 
-       if (data->cookie.state == SERVER_COOKIE_LEARNED) {
-               // lookup bound interface
-               log_err("!!!!! infra_get_cookie:bound_addrlen: %d", data->cookie.bound_addrlen);
-               log_addr(VERB_OPS, "!!!!! infra_get_cookie:bound_addr, len:", &data->cookie.bound_addr,
-                       data->cookie.bound_addrlen);
-
-               if (!(get_bound_ip_if(outnet, data->cookie.bound_addr,
-                       data->cookie.bound_addrlen, pif))) {
-                       log_err("!!!!!!!! creating new cookie for changed interface");
-                       data_entry_init(infra, e, timenow);
-               }
-       }
-
-       // @TODO uggo: data has changed
-       data = (struct infra_data*) e->data;
+       // @TODO fix this logic. does the cookie status matter?
+       /* renew cookie if the address isn't available isn't stored */
+       // if (data->cookie->addrlen == 0) {
+       //      infra_fill_client_cookie_random(infra, &data->cookie->data);
+       // }
 
        memcpy(cookie, &data->cookie, sizeof(struct edns_cookie));
 
@@ -790,10 +757,9 @@ infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
        return 1;
 }
 
-int
+int 
 infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
-        socklen_t addrlen, uint8_t* name, size_t namelen,
-        struct sockaddr_storage* bound_addr, socklen_t bound_addrlen,
+        socklen_t addrlen, uint8_t* name, size_t namelen, struct port_if *pif,
         struct edns_option* cookie)
 {
        struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
@@ -832,8 +798,8 @@ infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr
                        return -1;
                }
 
-               if (!(data->cookie.bound_addrlen == bound_addrlen) &&
-                       memcpy(&data->cookie.bound_addr, bound_addr, bound_addrlen)){
+               if (!(data->cookie.pif.addrlen == pif->addrlen) &&
+                       memcmp(&data->cookie.pif.addr, &pif->addr, pif->addrlen)){
 
                        // @TODO do something? this _should_ only happen on reloads?
                }
@@ -872,9 +838,12 @@ infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr
                /* store the server cookie */
                memcpy(data->cookie.data.cookie, cookie->opt_data, 24);
                data->cookie.state = SERVER_COOKIE_LEARNED;
-               if (bound_addrlen > 0) {
-                       memcpy(&data->cookie.bound_addr, bound_addr, bound_addrlen);
-                       data->cookie.bound_addrlen = bound_addrlen;
+
+               /* store the inbound interface we receive this cookie on */
+               if (pif->addrlen > 0) {
+                       memcpy(&data->cookie.pif,
+                               pif, sizeof(struct port_if));
+                       data->cookie.pif.addrlen = pif->addrlen;
                }
                verbose(VERB_QUERY, "storing received server cookie from upstream");
                lock_rw_unlock(&e->lock);
index 7ef4b0981ed6a641782d8f9c7653afeedbda14db..07fb74723644e9655feb8fd0d6285bbb80535e64 100644 (file)
@@ -90,8 +90,9 @@ enum edns_cookie_state
 struct edns_cookie {
         enum edns_cookie_state state;
         struct edns_cookie_data data;
-        struct sockaddr_storage bound_addr;
-        socklen_t bound_addrlen;
+        struct port_if pif;
+        // struct sockaddr_storage bound_addr;
+        // socklen_t bound_addrlen;
 };
 
 
@@ -375,13 +376,13 @@ int infra_edns_update(struct infra_cache* infra,
  * @param name: name of zone
  * @param namelen: length of name
  * @param timenow: what time it is now.
+ * @param pif: the interface which contains the outgoing address that we bind to
  * @param cookie: the cookie that is retrieved from cache on success.
  * @return: 0 on error, cookie pointer remains unchanged then.
  */
 int infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
         socklen_t addrlen, uint8_t* name, size_t namelen,
-        time_t timenow, struct outside_network* outnet, struct port_if** pif,
-        struct edns_cookie* cookie);
+        time_t timenow, struct edns_cookie* cookie);
 
 /**
  * Find the cookie entry in the cache and update it with to make a 'complete cookie'
@@ -394,16 +395,14 @@ int infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
  * @param name: name of zone
  * @param namelen: length of name
  * @param timenow: what time it is now.
- * @param bound_addr: the outgoing address that we bind to this cookie
- * @param bound_addr: the length of the bound address
+ * @param pif: the interface which contains the outgoing address that we bind to
  * @param cookie: the EDNS cookie option we want to store.
  * @return -1 if the wrong client cookie is found, 0 if the entry isn't found in
  *      the cache and a new one is inserted, 1 if the complete cookie is inserted
  *      or unchanged.
  */
 int infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
-        socklen_t addrlen, uint8_t* name, size_t namelen,
-        struct sockaddr_storage* bound_addr, socklen_t bound_addrlen,
+        socklen_t addrlen, uint8_t* name, size_t namelen, struct port_if *pif,
         struct edns_option* cookie);
 
 /**
index 467419b093980a7160e5261b0a63222afbdce623..bfb701fdab84b2e784b36a32b2a857f63495ef38 100644 (file)
@@ -630,7 +630,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
                        && !(errno == EADDRNOTAVAIL && verbosity < 4 && !listen)
 #endif
                        ) {
-                       log_err_addr("can't bind socket", strerror(errno),
+                       log_err_addr("1can't bind socket", strerror(errno),
                                (struct sockaddr_storage*)addr, addrlen);
                }
 #endif /* EADDRINUSE */
@@ -638,7 +638,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
                if(WSAGetLastError() != WSAEADDRINUSE &&
                        WSAGetLastError() != WSAEADDRNOTAVAIL &&
                        !(WSAGetLastError() == WSAEACCES && verbosity < 4 && !listen)) {
-                       log_err_addr("can't bind socket", 
+                       log_err_addr("2can't bind socket", 
                                wsa_strerror(WSAGetLastError()),
                                (struct sockaddr_storage*)addr, addrlen);
                }
@@ -824,12 +824,12 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
                if(addr->ai_family==AF_INET6 && errno==EINVAL)
                        *noproto = 1;
                else {
-                       log_err_addr("can't bind socket", strerror(errno),
+                       log_err_addr("3can't bind socket", strerror(errno),
                                (struct sockaddr_storage*)addr->ai_addr,
                                addr->ai_addrlen);
                }
 #else
-               log_err_addr("can't bind socket", 
+               log_err_addr("4can't bind socket", 
                        wsa_strerror(WSAGetLastError()),
                        (struct sockaddr_storage*)addr->ai_addr,
                        addr->ai_addrlen);
index 6954065bafeab2842d78834edd12fb61df034d5c..a5f00b3404fbc9a74986a01e46da043136594629 100644 (file)
@@ -1407,6 +1407,11 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
        struct pending* p;
        verbose(VERB_ALGO, "answer cb");
 
+
+       log_err("!!!!! outnet_udp_cb: HERE, error: %d", error);
+
+       // @TODO this is the function where we find the failed kernel call
+
        if(error != NETEVENT_NOERROR) {
                verbose(VERB_QUERY, "outnetudp got udp error %d", error);
                return 0;
@@ -1939,6 +1944,9 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
        int port, int* inuse, struct ub_randstate* rnd, int dscp)
 {
        int fd, noproto;
+
+       log_err("!!!!! udp_sockport: HERE!");
+
        if(addr_is_ip6(addr, addrlen)) {
                int freebind = 0;
                struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
@@ -2032,6 +2040,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
                        "outgoing interfaces of that family");
                return 0;
        }
+
        log_assert(outnet->unused_fds);
        tries = 0;
        while(1) {
@@ -2069,7 +2078,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
                        }
                }
 
-               log_err("!!!!! pif->inuse: %d, pif->maxout: %d", pif->inuse, pif->maxout);
+               log_err("!!!!! select_ifport:pif->inuse: %d, pif->maxout: %d", pif->inuse, pif->maxout);
 
                /* try to open new port, if fails, loop to try again */
                log_assert(pif->inuse < pif->maxout);
@@ -2080,6 +2089,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
                fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
                        portno, &inuse, outnet->rnd, outnet->ip_dscp);
                if(fd == -1 && !inuse) {
+                       log_err("!!!! select_ifport:nonrecoverable error making socket");
                        /* nonrecoverable error making socket */
                        return 0;
                }
@@ -2616,7 +2626,17 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
        sq->status = serviced_initial;
        sq->retry = 0;
        sq->to_be_deleted = 0;
-       sq->bound_interface = bound_interface;
+       if (bound_interface != NULL) {
+               sq->bound_interface = regional_alloc_init(region,
+                       bound_interface, sizeof(struct port_if));
+               if (!sq->bound_interface) {
+                       alloc_reg_release(alloc, region);
+                       free(sq);
+                       return NULL;
+               }
+       } else {
+               sq->bound_interface = NULL;
+       }
        sq->padding_block_size = pad_queries_block_size;
 #ifdef UNBOUND_DEBUG
        ins =
@@ -3377,7 +3397,7 @@ outnet_serviced_query(struct outside_network* outnet,
        struct edns_option* backed_up_opt_list = qstate->edns_opts_back_out;
        struct edns_option* per_upstream_opt_list = NULL;
        time_t timenow = 0;
-       struct port_if* pif;
+       struct port_if* pif = NULL;
 
        /* If we have an already populated EDNS option list make a copy since
         * we may now add upstream specific EDNS options. */
@@ -3416,12 +3436,18 @@ outnet_serviced_query(struct outside_network* outnet,
 
        if (env->cfg->upstream_cookies &&
                infra_get_cookie(env->infra_cache, addr, addrlen, zone, zonelen,
-                       *env->now, outnet, &pif, &cookie)) {
+                       *env->now, &cookie)) {
 
                if (cookie.state == SERVER_COOKIE_LEARNED) {
                        /* We known the complete cookie, so we attach it */
                        edns_opt_list_append(&per_upstream_opt_list, LDNS_EDNS_COOKIE,
                                24, cookie.data.cookie, region);
+
+                       if (cookie.pif.addrlen > 0) {
+                               pif = &cookie.pif;
+
+                               log_addr(VERB_DETAIL, "!!!!! outnet_serviced_query:pif addr:", &cookie.pif.addr, cookie.pif.addrlen);
+                       }
                } else if (cookie.state == SERVER_COOKIE_UNKNOWN) {
                        /* We know just client cookie, so we attach it */
                        edns_opt_list_append(&per_upstream_opt_list, LDNS_EDNS_COOKIE,
index 14d11b9b673c9b3a35ad1d2e22bab5f98cad2344..37162117d71eaf473b85d5eba0b9d8553e5b4990 100644 (file)
@@ -527,7 +527,7 @@ struct serviced_query {
        struct comm_timer* timer;
        /** true if serviced_query is currently doing net I/O and may block */
        int busy;
-       /** Interface bound to the EDNS cookie @TODO fix this */
+       /** interface bound to the EDNS cookie @TODO fix this */
        struct port_if* bound_interface;
 };