From: Daniel Salzman Date: Wed, 21 Apr 2021 10:59:36 +0000 (+0200) Subject: knot+modules: fix getting remote and local addresses in the XDP mode X-Git-Tag: v3.1.0~164^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb97af3de274ab9ea201361c9e794dc3bbf59bce;p=thirdparty%2Fknot-dns.git knot+modules: fix getting remote and local addresses in the XDP mode --- diff --git a/src/knot/events/handlers/update.c b/src/knot/events/handlers/update.c index 49514b64d7..039648636c 100644 --- a/src/knot/events/handlers/update.c +++ b/src/knot/events/handlers/update.c @@ -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, diff --git a/src/knot/include/module.h b/src/knot/include/module.h index 668dd1c349..04c448b267 100644 --- a/src/knot/include/module.h +++ b/src/knot/include/module.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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. * diff --git a/src/knot/modules/cookies/cookies.c b/src/knot/modules/cookies/cookies.c index 65950d7752..ae9b61d327 100644 --- a/src/knot/modules/cookies/cookies.c +++ b/src/knot/modules/cookies/cookies.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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, ¤t_secret, sizeof(current_secret)); diff --git a/src/knot/modules/dnstap/dnstap.c b/src/knot/modules/dnstap/dnstap.c index 0b3fdc7d6c..b74cc5274a 100644 --- a/src/knot/modules/dnstap/dnstap.c +++ b/src/knot/modules/dnstap/dnstap.c @@ -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; } diff --git a/src/knot/modules/geoip/geoip.c b/src/knot/modules/geoip/geoip.c index 4c6114a588..3263b18487 100644 --- a/src/knot/modules/geoip/geoip.c +++ b/src/knot/modules/geoip/geoip.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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; } diff --git a/src/knot/modules/queryacl/queryacl.c b/src/knot/modules/queryacl/queryacl.c index 03633ffb27..b0b5208698 100644 --- a/src/knot/modules/queryacl/queryacl.c +++ b/src/knot/modules/queryacl/queryacl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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; } diff --git a/src/knot/modules/rrl/rrl.c b/src/knot/modules/rrl/rrl.c index cd68c71b5a..f8adffe3fa 100644 --- a/src/knot/modules/rrl/rrl.c +++ b/src/knot/modules/rrl/rrl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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; } diff --git a/src/knot/modules/stats/stats.c b/src/knot/modules/stats/stats.c index b93c163737..cedbd144ce 100644 --- a/src/knot/modules/stats/stats.c +++ b/src/knot/modules/stats/stats.c @@ -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, diff --git a/src/knot/modules/whoami/whoami.c b/src/knot/modules/whoami/whoami.c index 0ec068c181..99c43723ab 100644 --- a/src/knot/modules/whoami/whoami.c +++ b/src/knot/modules/whoami/whoami.c @@ -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; } diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c index 410db29598..eb22011ebb 100644 --- a/src/knot/nameserver/axfr.c +++ b/src/knot/nameserver/axfr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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, \ diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c index 8f29c6d7c2..e0d32dfa0c 100644 --- a/src/knot/nameserver/ixfr.c +++ b/src/knot/nameserver/ixfr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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, \ diff --git a/src/knot/nameserver/notify.c b/src/knot/nameserver/notify.c index b8b677a1f0..8b1a67dc4a 100644 --- a/src/knot/nameserver/notify.c +++ b/src/knot/nameserver/notify.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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; diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c index f82c1f7f22..3645f85eb5 100644 --- a/src/knot/nameserver/process_query.c +++ b/src/knot/nameserver/process_query.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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. */ diff --git a/src/knot/nameserver/query_module.c b/src/knot/nameserver/query_module.c index 02a30c4d4c..700a558b45 100644 --- a/src/knot/nameserver/query_module.c +++ b/src/knot/nameserver/query_module.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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) { diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c index a208a24b51..ebb49b018a 100644 --- a/src/knot/nameserver/update.c +++ b/src/knot/nameserver/update.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. 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);