]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/selection: allow forwarding to link local address
authorŠtěpán Balážik <stepan.balazik@nic.cz>
Fri, 8 Jan 2021 14:41:50 +0000 (15:41 +0100)
committerŠtěpán Balážik <stepan.balazik@nic.cz>
Fri, 8 Jan 2021 14:41:50 +0000 (15:41 +0100)
This is done by changing the type of address field in struct choice to
union inaddr and moving some conversion around.

lib/selection.c
lib/selection.h
lib/selection_forward.c
lib/selection_iter.c

index 8031fb74db2470589e7b9f41ce05d46cf56ae0e1..d6ef22fbf0810550b2e1fed8d09634ab5df3a2f2 100644 (file)
@@ -125,6 +125,7 @@ void bytes_to_ip(uint8_t *bytes, size_t len, uint16_t port, union inaddr *dst)
                dst->ip4.sin_port = htons(port);
                break;
        case sizeof(struct in6_addr):
+               memset(&dst->ip6, 0, sizeof(dst->ip6)); // avoid uninit surprises
                dst->ip6.sin6_family = AF_INET6;
                memcpy(&dst->ip6.sin6_addr, bytes, len);
                dst->ip6.sin6_port = htons(port);
@@ -246,19 +247,18 @@ static void check_network_settings(struct address_state *address_state,
        }
 }
 
-void update_address_state(struct address_state *state, uint8_t *address,
+void update_address_state(struct address_state *state, union inaddr *address,
                          size_t address_len, struct kr_query *qry)
 {
-       union inaddr tmp_address;
-       bytes_to_ip(address, address_len, 0, &tmp_address);
-       check_tls_capable(state, qry->request, &tmp_address.ip);
+       check_tls_capable(state, qry->request, &address->ip);
        /* TODO: uncomment this once we actually use the information it collects
        check_tcp_connections(address_state, qry->request, &tmp_address.ip);
        */
        check_network_settings(state, address_len, qry->flags.NO_IPV4,
                               qry->flags.NO_IPV6);
        state->rtt_state =
-               get_rtt_state(address, address_len, &qry->request->ctx->cache);
+               get_rtt_state(ip_to_bytes(address, address_len),
+                             address_len, &qry->request->ctx->cache);
        invalidate_dead_upstream(
                state, qry->request->ctx->cache_rtt_tout_retry_interval);
 #ifdef SELECTION_CHOICE_LOGGING
@@ -403,11 +403,25 @@ struct kr_transport *select_transport(struct choice choices[], int choices_len,
                        break;
                default:
                        assert(0);
-                       break;
+                       return NULL;
                }
        }
 
-       bytes_to_ip(chosen->address, chosen->address_len, port, &transport->address);
+       switch (chosen->address_len)
+       {
+       case sizeof(struct in_addr):
+               transport->address.ip4 = chosen->address.ip4;
+               transport->address.ip4.sin_port = htons(port);
+               break;
+       case sizeof(struct in6_addr):
+               transport->address.ip6 = chosen->address.ip6;
+               transport->address.ip6.sin6_port = htons(port);
+               break;
+       default:
+               assert(0);
+               return NULL;
+       }
+
        transport->address_len = chosen->address_len;
 
        if (choice_index) {
index 113a468bf22a2522f1d70f6b945ce37f193d5392..18cefccc26ddfce61a6119d83fdb003c7b1c9ff3 100644 (file)
@@ -164,7 +164,7 @@ struct address_state {
  * @brief Array of these is one of inputs for the actual selection algorithm (`select_transport`)
  */
 struct choice {
-       uint8_t *address;
+       union inaddr address;
        size_t address_len;
        struct address_state *address_state;
        /** used to overwrite the port number;
@@ -240,5 +240,5 @@ uint8_t *ip_to_bytes(const union inaddr *src, size_t len);
 /**
  * @internal Fetch per-address information from various sources.
  */
-void update_address_state(struct address_state *state, uint8_t *address,
+void update_address_state(struct address_state *state, union inaddr *address,
                          size_t address_len, struct kr_query *qry);
index d741410067d46ab6464a8019a047546b52f53ab3..b311fc9f95752cedb297bb6c550fead23b8a303a 100644 (file)
@@ -59,8 +59,7 @@ void forward_choose_transport(struct kr_query *qry,
                struct address_state *addr_state = &local_state->addr_states[i];
                addr_state->ns_name = (knot_dname_t *)"";
 
-               update_address_state(addr_state, ip_to_bytes(address, addr_len),
-                                    addr_len, qry);
+               update_address_state(addr_state, address, addr_len, qry);
 
                if (addr_state->generation == -1) {
                        continue;
@@ -68,7 +67,7 @@ void forward_choose_transport(struct kr_query *qry,
                addr_state->choice_array_index = i;
 
                choices[valid++] = (struct choice){
-                       .address = ip_to_bytes(address, addr_len),
+                       .address = *address,
                        .address_len = addr_len,
                        .address_state = addr_state,
                        .port = port,
index 4e8642d7aea16c5007cd46bb35bebe0530e18c73..388f29f8ea85941daa9a3b5789d4014ce3214d4d 100644 (file)
@@ -124,7 +124,9 @@ static void unpack_state_from_zonecut(struct iter_local_state *local_state,
                        } else if (address_len == sizeof(struct in6_addr)) {
                                name_state->aaaa_state = RECORD_RESOLVED;
                        }
-                       update_address_state(address_state, address, address_len, qry);
+                       union inaddr tmp_address;
+                       bytes_to_ip(address, address_len, 0, &tmp_address);
+                       update_address_state(address_state, &tmp_address, address_len, qry);
                }
        }
        trie_it_free(it);
@@ -143,10 +145,10 @@ static int get_valid_addresses(struct iter_local_state *local_state,
                if (address_state->generation == local_state->generation &&
                    !address_state->unrecoverable_errors) {
                        choices[count] = (struct choice){
-                               .address = address,
                                .address_len = address_len,
                                .address_state = address_state,
                        };
+                       bytes_to_ip(address, address_len, 0, &choices[count].address);
                        count++;
                }
        }