]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
knot+modules: fix getting remote and local addresses in the XDP mode
authorDaniel Salzman <daniel.salzman@nic.cz>
Wed, 21 Apr 2021 10:59:36 +0000 (12:59 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Thu, 22 Apr 2021 06:29:37 +0000 (08:29 +0200)
15 files changed:
src/knot/events/handlers/update.c
src/knot/include/module.h
src/knot/modules/cookies/cookies.c
src/knot/modules/dnstap/dnstap.c
src/knot/modules/geoip/geoip.c
src/knot/modules/queryacl/queryacl.c
src/knot/modules/rrl/rrl.c
src/knot/modules/stats/stats.c
src/knot/modules/whoami/whoami.c
src/knot/nameserver/axfr.c
src/knot/nameserver/ixfr.c
src/knot/nameserver/notify.c
src/knot/nameserver/process_query.c
src/knot/nameserver/query_module.c
src/knot/nameserver/update.c

index 49514b64d7c0fdfff01363fb602e022e0bba5413..039648636c9b5d76bafa2ec25714ad16b704c3bf 100644 (file)
@@ -30,7 +30,7 @@
 
 #define UPDATE_LOG(priority, qdata, fmt...) \
        ns_log(priority, knot_pkt_qname(qdata->query), LOG_OPERATION_UPDATE, \
-              LOG_DIRECTION_IN, (struct sockaddr *)qdata->params->remote, fmt)
+              LOG_DIRECTION_IN, (struct sockaddr *)knotd_qdata_remote_addr(qdata), fmt)
 
 static void init_qdata_from_request(knotd_qdata_t *qdata,
                                     const zone_t *zone,
index 668dd1c349cab787f974b846500ce0c70ff3188d..04c448b2675f928b0ab92a833187bbf42695881e 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -425,6 +425,26 @@ typedef struct {
        struct knotd_qdata_extra *extra; /*!< Private items (process_query.h). */
 } knotd_qdata_t;
 
+/*!
+ * Gets the local (destination) address of the query.
+ *
+ * \param[in] qdata  Query data.
+ * \param[out] buff  Auxiliary buffer (not used for XDP).
+ *
+ * \return Local address or NULL if error.
+ */
+const struct sockaddr_storage *knotd_qdata_local_addr(knotd_qdata_t *qdata,
+                                                      struct sockaddr_storage *buff);
+
+/*!
+ * Gets the remote (source) address of the query.
+ *
+ * \param[in] qdata  Query data.
+ *
+ * \return Remote address or NULL if error.
+ */
+const struct sockaddr_storage *knotd_qdata_remote_addr(knotd_qdata_t *qdata);
+
 /*!
  * Gets the current zone name.
  *
index 65950d7752b6a693e200db1ea041e2a742fd1e40..ae9b61d32745841834463cc3de2cb50cb09907c0 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -182,7 +182,7 @@ static knotd_state_t cookies_process(knotd_state_t state, knot_pkt_t *pkt,
                .timestamp = (uint32_t)time(NULL),
                .lifetime_before = 3600,
                .lifetime_after = 300,
-               .client_addr = qdata->params->remote
+               .client_addr = knotd_qdata_remote_addr(qdata)
        };
        uint64_t current_secret = ATOMIC_GET(ctx->secret.variable);
        memcpy(params.secret, &current_secret, sizeof(current_secret));
index 0b3fdc7d6ca0bb21695e0a9ba21869a944cb99e6..b74cc5274afa5511385d0ef268aa5c16cc351052 100644 (file)
@@ -89,18 +89,13 @@ static knotd_state_t log_message(knotd_state_t state, const knot_pkt_t *pkt,
                protocol = IPPROTO_UDP;
        }
 
-       /* Try to get the destination address. */
-       struct sockaddr_storage dst_addr;
-       socklen_t dst_addr_len = sizeof(dst_addr);
-       (void)getsockname(qdata->params->socket, (struct sockaddr *)&dst_addr,
-                         &dst_addr_len);
-
        /* Create a dnstap message. */
+       struct sockaddr_storage buff;
        Dnstap__Message msg;
        int ret = dt_message_fill(&msg, msgtype,
-                                 (const struct sockaddr *)qdata->params->remote,
-                                 (struct sockaddr *)&dst_addr, protocol, pkt->wire,
-                                 pkt->size, &tv);
+                                 (const struct sockaddr *)knotd_qdata_remote_addr(qdata),
+                                 (const struct sockaddr *)knotd_qdata_local_addr(qdata, &buff),
+                                 protocol, pkt->wire, pkt->size, &tv);
        if (ret != KNOT_EOK) {
                return state;
        }
index 4c6114a5883d71c664ddf218916953651e4d1130..3263b18487fea0d0dbddc934c351a9fe37429084 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -803,7 +803,7 @@ static knotd_in_state_t geoip_process(knotd_in_state_t state, knot_pkt_t *pkt,
 
        // Check if EDNS Client Subnet is available.
        struct sockaddr_storage ecs_addr = { 0 };
-       const struct sockaddr_storage *remote = qdata->params->remote;
+       const struct sockaddr_storage *remote = knotd_qdata_remote_addr(qdata);
        if (knot_edns_client_subnet_get_addr(&ecs_addr, qdata->ecs) == KNOT_EOK) {
                remote = &ecs_addr;
        }
index 03633ffb27148ab31d50cb24b4c655f1be1ff596..b0b520869834c96c34b9ff57aaf34101e462f1d7 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -44,34 +44,17 @@ static knotd_state_t queryacl_process(knotd_state_t state, knot_pkt_t *pkt,
        }
 
        if (ctx->allow_addr.count > 0) {
-               if (!knotd_conf_addr_range_match(&ctx->allow_addr, qdata->params->remote)) {
+               const struct sockaddr_storage *addr = knotd_qdata_remote_addr(qdata);
+               if (!knotd_conf_addr_range_match(&ctx->allow_addr, addr)) {
                        qdata->rcode = KNOT_RCODE_NOTAUTH;
                        return KNOTD_STATE_FAIL;
                }
        }
 
        if (ctx->allow_iface.count > 0) {
-               struct sockaddr_storage iface;
-               socklen_t iface_len = sizeof(iface);
-               struct sockaddr_storage *iface_ptr;
-
-               if (qdata->params->xdp_msg != NULL) {
-#ifdef ENABLE_XDP
-                       iface_ptr = (struct sockaddr_storage *)&qdata->params->xdp_msg->ip_to;
-#else
-                       assert(0);
-                       return KNOTD_STATE_FAIL;
-#endif
-               } else {
-                       if (getsockname(qdata->params->socket, (struct sockaddr *)&iface,
-                                       &iface_len) != 0) {
-                               knotd_mod_log(mod, LOG_ERR, "failed to get interface address");
-                               return KNOTD_STATE_FAIL;
-                       }
-                       iface_ptr = &iface;
-               }
-
-               if (!knotd_conf_addr_range_match(&ctx->allow_iface, iface_ptr)) {
+               struct sockaddr_storage buff;
+               const struct sockaddr_storage *addr = knotd_qdata_local_addr(qdata, &buff);
+               if (addr == NULL || !knotd_conf_addr_range_match(&ctx->allow_iface, addr)) {
                        qdata->rcode = KNOT_RCODE_NOTAUTH;
                        return KNOTD_STATE_FAIL;
                }
index cd68c71b5a42e0d383db07069394cfe60e78496c..f8adffe3fa06b3fa2f60afa5501ed545a4081e4f 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -92,7 +92,7 @@ static knotd_state_t ratelimit_apply(knotd_state_t state, knot_pkt_t *pkt,
        }
 
        // Exempt clients.
-       if (knotd_conf_addr_range_match(&ctx->whitelist, qdata->params->remote)) {
+       if (knotd_conf_addr_range_match(&ctx->whitelist, knotd_qdata_remote_addr(qdata))) {
                return state;
        }
 
@@ -130,7 +130,7 @@ static knotd_state_t ratelimit_apply(knotd_state_t state, knot_pkt_t *pkt,
                }
        }
 
-       if (rrl_query(ctx->rrl, qdata->params->remote, &req, zone_name, mod) == KNOT_EOK) {
+       if (rrl_query(ctx->rrl, knotd_qdata_remote_addr(qdata), &req, zone_name, mod) == KNOT_EOK) {
                // Rate limiting not applied.
                return state;
        }
index b93c163737bef04c9c6647686efb2890571d7418..cedbd144ce87043c331f84bdc4c32e802840b0fa 100644 (file)
@@ -492,7 +492,7 @@ static knotd_state_t update_counters(knotd_state_t state, knot_pkt_t *pkt,
        // Count the request protocol.
        if (stats->protocol) {
                bool xdp = qdata->params->xdp_msg != NULL;
-               if (qdata->params->remote->ss_family == AF_INET) {
+               if (knotd_qdata_remote_addr(qdata)->ss_family == AF_INET) {
                        if (qdata->params->flags & KNOTD_QUERY_FLAG_LIMIT_SIZE) {
                                if (xdp) {
                                        knotd_mod_stats_incr(mod, tid, CTR_PROTOCOL,
index 0ec068c181801172b02bb69178c4550757545276..99c43723ab0b3e3902e9ff8771c2a6023f653cfb 100644 (file)
@@ -49,7 +49,7 @@ static knotd_in_state_t whoami_query(knotd_in_state_t state, knot_pkt_t *pkt,
        }
 
        /* Retrieve the IP address that sent the query. */
-       const struct sockaddr_storage *query_source = qdata->params->remote;
+       const struct sockaddr_storage *query_source = knotd_qdata_remote_addr(qdata);
        if (query_source == NULL) {
                return KNOTD_IN_STATE_ERROR;
        }
index 410db295987e2976dcfefc992adbb7e47a185d55..eb22011ebbab5f9d7d44f3897d66f59a881aeb17 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
 #include "libknot/libknot.h"
 
 #define ZONE_NAME(qdata) knot_pkt_qname((qdata)->query)
-#define REMOTE(qdata) (struct sockaddr *)(qdata)->params->remote
+#define REMOTE(qdata) (struct sockaddr *)knotd_qdata_remote_addr(qdata)
 
 #define AXFROUT_LOG(priority, qdata, fmt...) \
        ns_log(priority, ZONE_NAME(qdata), LOG_OPERATION_AXFR, \
index 8f29c6d7c2c819c9e19c2e4f08bc57869b0d60ad..e0d32dfa0c5e3e283aef4229c731cacba02a9bf9 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 #include "libknot/libknot.h"
 
 #define ZONE_NAME(qdata) knot_pkt_qname((qdata)->query)
-#define REMOTE(qdata) (struct sockaddr *)(qdata)->params->remote
+#define REMOTE(qdata) (struct sockaddr *)knotd_qdata_remote_addr(qdata)
 
 #define IXFROUT_LOG(priority, qdata, fmt...) \
        ns_log(priority, ZONE_NAME(qdata), LOG_OPERATION_IXFR, \
index b8b677a1f0409c257acfc25c61561a85e8a457af..8b1a67dc4a2917ab8941afa93c5c3dc6447674e5 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@
 
 #define NOTIFY_IN_LOG(priority, qdata, fmt...) \
        ns_log(priority, knot_pkt_qname(qdata->query), LOG_OPERATION_NOTIFY, \
-              LOG_DIRECTION_IN, qdata->params->remote, fmt)
+              LOG_DIRECTION_IN, knotd_qdata_remote_addr(qdata), fmt)
 
 static int notify_check_query(knotd_qdata_t *qdata)
 {
@@ -84,7 +84,7 @@ int notify_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
        }
 
        /* Incoming NOTIFY expires REFRESH timer and renews EXPIRE timer. */
-       zone_set_preferred_master(zone, qdata->params->remote);
+       zone_set_preferred_master(zone, knotd_qdata_remote_addr(qdata));
        zone_events_schedule_now(zone, ZONE_EVENT_REFRESH);
 
        return KNOT_STATE_DONE;
index f82c1f7f225aa6df15fb991cb8d98cb63a724574..3645f85eb586c35a189c2340d00cc6442a2ddc45 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -239,7 +239,7 @@ static int answer_edns_init(const knot_pkt_t *query, knot_pkt_t *resp,
 
        /* Initialize OPT record. */
        uint16_t max_payload;
-       switch (qdata->params->remote->ss_family) {
+       switch (knotd_qdata_remote_addr(qdata)->ss_family) {
        case AF_INET:
                max_payload = conf()->cache.srv_udp_max_payload_ipv4;
                break;
@@ -386,7 +386,7 @@ static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx
                resp->max_size = KNOT_WIRE_MIN_PKTSIZE;
                if (knot_pkt_has_edns(query)) {
                        uint16_t server_size;
-                       switch (qdata->params->remote->ss_family) {
+                       switch (knotd_qdata_remote_addr(qdata)->ss_family) {
                        case AF_INET:
                                server_size = conf()->cache.srv_udp_max_payload_ipv4;
                                break;
@@ -633,7 +633,7 @@ bool process_query_acl_check(conf_t *conf, acl_action_t action,
 {
        const knot_dname_t *zone_name = qdata->extra->zone->name;
        knot_pkt_t *query = qdata->query;
-       const struct sockaddr_storage *query_source = qdata->params->remote;
+       const struct sockaddr_storage *query_source = knotd_qdata_remote_addr(qdata);
        knot_tsig_key_t tsig = { 0 };
 
        /* Skip if already checked and valid. */
index 02a30c4d4c4afbcf71531a104af9a538c73d1d4e..700a558b4505d02a2c40e30b17bc1a50a6ef7b8d 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -613,6 +613,50 @@ void knotd_conf_free(knotd_conf_t *conf)
        memset(conf, 0, sizeof(*conf));
 }
 
+_public_
+const struct sockaddr_storage *knotd_qdata_local_addr(knotd_qdata_t *qdata,
+                                                      struct sockaddr_storage *buff)
+{
+       if (qdata == NULL) {
+               return NULL;
+       }
+
+       if (qdata->params->xdp_msg != NULL) {
+#ifdef ENABLE_XDP
+               return (struct sockaddr_storage *)&qdata->params->xdp_msg->ip_to;
+#else
+               assert(0);
+               return NULL;
+#endif
+       } else {
+               socklen_t buff_len = sizeof(*buff);
+               if (getsockname(qdata->params->socket, (struct sockaddr *)buff,
+                               &buff_len) != 0) {
+                       return NULL;
+               }
+               return buff;
+       }
+}
+
+_public_
+const struct sockaddr_storage *knotd_qdata_remote_addr(knotd_qdata_t *qdata)
+{
+       if (qdata == NULL) {
+               return NULL;
+       }
+
+       if (qdata->params->xdp_msg != NULL) {
+#ifdef ENABLE_XDP
+               return (struct sockaddr_storage *)&qdata->params->xdp_msg->ip_from;
+#else
+               assert(0);
+               return NULL;
+#endif
+       } else {
+               return qdata->params->remote;
+       }
+}
+
 _public_
 const knot_dname_t *knotd_qdata_zone_name(knotd_qdata_t *qdata)
 {
index a208a24b517b80fbfed52596d651f31a2870d1f4..ebb49b018ad32f2ef3a14d48ef28a9483e44cbc4 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@ static int update_enqueue(zone_t *zone, knotd_qdata_t *qdata)
 
        /* Store socket and remote address. */
        req->fd = dup(qdata->params->socket);
-       memcpy(&req->remote, qdata->params->remote, sizeof(req->remote));
+       memcpy(&req->remote, knotd_qdata_remote_addr(qdata), sizeof(req->remote));
 
        /* Store update request. */
        req->query = knot_pkt_new(NULL, qdata->query->max_size, NULL);