]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/quic: enable QUIC protolayer
authorFrantisek Tobias <frantisek.tobias@nic.cz>
Mon, 26 May 2025 10:39:26 +0000 (12:39 +0200)
committerFrantisek Tobias <frantisek.tobias@nic.cz>
Wed, 7 Jan 2026 13:38:01 +0000 (14:38 +0100)
daemon/bindings/net.c
daemon/lua/postconfig.lua
daemon/network.c
daemon/quic.c
daemon/quic.h
daemon/session2.c
daemon/tls.h
lib/defines.h
lib/proto.h
python/knot_resolver/datamodel/network_schema.py

index d9e8f1658ca156868e4b4e232bb898144d0d8932..be6c7b7d80cfa85a9486262c4ceac640ecca9321 100644 (file)
@@ -142,13 +142,20 @@ static bool net_listen_addrs(lua_State *L, int port, endpoint_flags_t flags, int
                        flags.sock_type = SOCK_DGRAM;
                        ret = network_listen(str, port, nic_queue, flags);
                }
+               if (!flags.kind && flags.doq && ret == 0) {
+                       flags.sock_type = SOCK_DGRAM;
+                       ret = network_listen(str, port, nic_queue, flags);
+               }
                if (!flags.kind && !flags.xdp && ret == 0) { /* common for TCP, DoT and DoH (v2) */
                        flags.sock_type = SOCK_STREAM;
                        ret = network_listen(str, port, nic_queue, flags);
                }
                if (flags.kind) {
                        flags.kind = strdup(flags.kind);
-                       flags.sock_type = SOCK_STREAM; /* TODO: allow to override this? */
+                       if (flags.doq)
+                               flags.sock_type =  SOCK_DGRAM;
+                       else
+                               flags.sock_type = SOCK_STREAM; /* TODO: allow to override this? */
                        ret = network_listen(str, (is_unix ? 0 : port), nic_queue, flags);
                }
                if (ret == 0) return true; /* success */
index ac71660eecb7f8ff6432a02be8f29830d04cbf2f..21e3efebb61e0d5f2d32b66e920377157178a9a6 100644 (file)
@@ -13,7 +13,8 @@ local function count_sockets()
                        socket.kind == 'xdp' or
                        socket.kind == 'tls' or
                        socket.kind == 'doh_legacy' or
-                       socket.kind == 'doh2') then
+                       socket.kind == 'doh2' or
+                       socket.kind == 'doq') then
                        dns_socks = dns_socks + 1
                end
        end
index a32861cb89360b73b2a436425891ee89c7caa146..5e491ba6d90e3058571a61517ee2672d20d12cc9 100644 (file)
@@ -439,12 +439,12 @@ static int open_endpoint(const char *addr_str,
        } /* else */
 
        if (ep->flags.sock_type == SOCK_DGRAM) {
-               if (kr_fails_assert(!ep->flags.tls))
+               if (kr_fails_assert(!ep->flags.tls || ep->flags.doq))
                        return kr_error(EINVAL);
                uv_udp_t *ep_handle = malloc(sizeof(uv_udp_t));
                ep->handle = (uv_handle_t *)ep_handle;
                ret = !ep->handle ? ENOMEM
-                       : io_listen_udp(the_network->loop, ep_handle, ep->fd);
+                       : io_listen_udp(the_network->loop, ep_handle, ep->fd, ep->flags.doq);
                goto finish_ret;
        } /* else */
 
index 7b3bdc2c978c1d7ae0417b558aa84c2ce0a62f1d..334368c5cc8414ccc512a815237fc66bec1e5bec 100644 (file)
 
 #include <worker.h>
 
-#define SERVER_DEFAULT_SCIDLEN 18
-
-#define ENABLE_QUIC
-
-
-// Macros from knot quic impl
-#define SERVER_DEFAULT_SCIDLEN 18
-#define QUIC_REGULAR_TOKEN_TIMEOUT (24 * 3600 * 1000000000LLU)
-#define QUIC_SEND_VERSION_NEGOTIATION    NGTCP2_ERR_VERSION_NEGOTIATION
-#define QUIC_SEND_RETRY                  NGTCP2_ERR_RETRY
-#define QUIC_SEND_STATELESS_RESET        (-NGTCP2_STATELESS_RESET_TOKENLEN)
-#define QUIC_SEND_CONN_CLOSE             (-KNOT_QUIC_HANDLE_RET_CLOSE)
-#define QUIC_SEND_EXCESSIVE_LOAD         (-KNOT_QUIC_ERR_EXCESSIVE_LOAD)
-#define MAX_STREAMS_PER_CONN 10 // this limits the number of un-finished streams per conn (i.e. if response has been recvd with FIN, it doesn't count)
-
-typedef enum {
-       KR_QUIC_SEND_IGNORE_LASTBYTE = (1 << 0),
-       KR_QUIC_SEND_IGNORE_BLOCKED  = (1 << 1),
-} kr_quic_send_flag_t;
-
-struct quic_ctx;
-// TODO maybe rename to something more in line with iter_data
-struct pl_quic_state {
-       struct protolayer_data h;
-       struct quic_ctx *quic_ctx;
-       /* struct ortt_ NOTE: Or some other data */ ;
-};
-
-struct kr_quic_conn;
-typedef struct kr_quic_cid {
-       uint8_t cid_placeholder[32];
-       struct kr_quic_conn *conn;
-       struct kr_quic_cid *next;
-} kr_quic_cid_t;
-
-typedef enum {
-       KNOT_QUIC_TABLE_CLIENT_ONLY = (1 << 0),
-} kr_quic_table_flag_t;
-
-typedef struct {
-       void *get_conn;
-       void *user_data;
-} nc_conn_ref_placeholder_t;
-
-typedef struct kr_quic_table {
-       kr_quic_table_flag_t flags;
-       size_t size;
-       size_t usage;
-       size_t pointers;
-       size_t max_conns;
-       size_t ibufs_max;
-       size_t obufs_max;
-       size_t ibufs_size;
-       size_t obufs_size;
-       size_t udp_payload_limit;
-       void (*log_cb)(const char *);
-       const char *qlog_dir;
-       uint64_t hash_secret[4];
-       struct tls_credentials *creds;
-       struct gnutls_priority_st *priority;
-       struct heap *expiry_heap;
-       kr_quic_cid_t *conns[];
-} kr_quic_table_t;
-
-typedef struct kr_quic_obuf {
-       /*ucw_*/node_t node;
-       size_t len;
-       // struct wire_buf buf;?
-       char buf[];
-} kr_quic_obuf_t;
-
-typedef enum {
-       KR_QUIC_CONN_HANDSHAKE_DONE = (1 << 0),
-       KR_QUIC_CONN_SESSION_TAKEN  = (1 << 1),
-       KR_QUIC_CONN_BLOCKED        = (1 << 2),
-       KR_QUIC_CONN_AUTHORIZED     = (1 << 3),
-} kr_quic_conn_flag_t;
-
-typedef struct kr_tcp_inbufs_upd_res {
-       size_t n_inbufs;
-       struct kr_tcp_inbufs_upd_res *next;
-       struct iovec inbufs[];
-} kr_tcp_inbufs_udp_res_t;
-
-typedef struct kr_quic_stream {
-       /** the inbuf for small, singlepacket messages
-        * while the latter is for larger comunications, but still... */
-       struct iovec inbuf;
-       struct kr_tcp_inbufs_upd_res *inbufs;
-
-       size_t firstib_consumed;
-       /*ucw_*/list_t outbufs;
-       size_t obufs_size;
-
-       kr_quic_obuf_t *unsent_obuf;
-       size_t first_offset;
-       size_t unsent_offset;
-} kr_quic_stream_t;
-
-typedef struct quic_ctx {
-       ngtcp2_crypto_conn_ref conn_ref;
-
-       // // Parameters
-       // quic_params_t params;
-       //
-       // // Context
-       // ngtcp2_settings settings;
-       // struct {
-       //      int64_t id;
-       //      uint64_t out_ack;
-       //      struct iovec in_buffer;
-       //      struct knot_tcp_inbufs_upd_res *in_parsed;
-       //      size_t in_parsed_it;
-       //      size_t in_parsed_total;
-       // } stream;
-       // ngtcp2_ccerr last_err;
-       // uint8_t secret[32];
-
-       // tls_ctx_t *tls;
-
-       // convenient struct to store Connection ID, its associated path, and stateless reset token.
-       ngtcp2_cid_token dcid_token;
-       ngtcp2_cid_token scid_token;
-       // ngtcp2_cid_token odcid_token; // maybe?
-       ngtcp2_conn *conn;
-       ngtcp2_pkt_info pi;
-       ngtcp2_path path;
-       quic_state_t state;
-} quic_ctx_t;
-
-typedef struct kr_quic_conn {
-       int heap_node_placeholder; // MUST be first field of the struct
-       uint64_t next_expiry;
-
-        // placeholder for internal struct ngtcp2_crypto_conn_ref
-       nc_conn_ref_placeholder_t conn_ref;
-
-       // conn_table next conn link
-       struct ngtcp2_conn *conn;
-       struct kr_quic_conn *next;
-
-       gnutls_session_t tls_session;
-
-       // crypto callbacks
-       ngtcp2_crypto_conn_ref crypto_ref;
-
-        // QUIC stream abstraction
-       kr_quic_stream_t *streams;
-        // number of allocated streams structures
-       int16_t streams_count;
-        // index of first stream that has complete incomming data to be processed (aka inbuf_fin)
-       int16_t stream_inprocess;
-        // stream_id/4 of first allocated stream
-       int64_t first_stream_id;
-
-       ngtcp2_ccerr last_error;
-       kr_quic_conn_flag_t flags;
-       int qlog_fd;
-
-       // TODO: consider removing
-       size_t ibufs_size;
-       size_t obufs_size;
-
-       // TODO: Definitelly move
-       ngtcp2_pkt_info pi;
-
-       // back-pointer
-       struct kr_quic_table *quic_table;
-} kr_quic_conn_t;
-
-typedef struct pl_quic_sess_data {
-       struct protolayer_data h;
-       // ngtcp2_conn *conns; This one might be wrong
-       // ngtcp2_crypto_conn_ref conn_ref;
-       // Parameters
-       quic_params_t params;
-       ngtcp2_settings settings;
-
-       // Context
-       // struct {
-       //      int64_t id;
-       //      uint64_t out_ack;
-       //      struct iovec in_buffer;
-       //      struct knot_tcp_inbufs_upd_res *in_parsed;
-       //      size_t in_parsed_it;
-       //      size_t in_parsed_total;
-       // } stream;
-       // ngtcp2_ccerr last_err;
-       // uint8_t secret[32];
-
-       uint32_t conn_count;
-       protolayer_iter_ctx_queue_t unwrap_queue;
-       protolayer_iter_ctx_queue_t wrap_queue;
-
-       kr_quic_table_t *conn_table;
-
-       struct kr_request *req;
-       quic_state_t state;
-       struct wire_buf wire_buf;
-} pl_quic_sess_data_t;
 
 static uint64_t cid2hash(const ngtcp2_cid *cid, kr_quic_table_t *table);
 kr_quic_conn_t *kr_quic_table_lookup(const ngtcp2_cid *cid, kr_quic_table_t *table);
index 9edfbc0ccbca99e4244d3dccf401f4b3f42d765d..1713ef085920d7db1c489b0af8f307188b9d73f4 100644 (file)
 #include <ngtcp2/ngtcp2_crypto_gnutls.h>
 // #include "daemon/tls.h"
 
+#include <gnutls/x509.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include "lib/log.h"
+#include "session2.h"
+#include "network.h"
+#include "lib/resolve.h"
+// #include "libknot/quic/quic.h"
+#include "libdnssec/random.h"
+#include <stdint.h>
+#include <contrib/ucw/heap.h>
+#include <contrib/ucw/lists.h>
+#include "contrib/openbsd/siphash.h"
+#include "lib/utils.h"
+#include "libdnssec/error.h"
+
+#include <stddef.h>
+#include <netinet/in.h>
+
+#include <worker.h>
+
+
 #define MAX_QUIC_FRAME_SIZE 65536
 
 typedef enum {
@@ -222,5 +244,5 @@ typedef struct pl_quic_sess_data {
 
        struct kr_request *req;
        quic_state_t state;
-       struct wire_buf wire_buf;
+       // struct wire_buf wire_buf;
 } pl_quic_sess_data_t;
index 1712037c7fab4e8392337ad5dd44a15d919d0ff4..0c729476aeab103250973c28920425656e502e56 100644 (file)
@@ -67,11 +67,12 @@ static const enum protolayer_type protolayer_grp_doh[] = {
 };
 
 static const enum protolayer_type protolayer_grp_doq[] = {
-       // PROTOLAYER_TYPE_UDP,
+       PROTOLAYER_TYPE_UDP,
        // PROTOLAYER_TYPE_PROXYV2_DGRAM,
        // PROTOLAYER_TYPE_DEFER,
        PROTOLAYER_TYPE_QUIC,
        // PROTOLAYER_TYPE_DNS_DGRAM,
+       // PROTOLAYER_TYPE_NULL,
 };
 
 struct protolayer_grp {
@@ -1525,7 +1526,10 @@ static int session2_transport_pushv(struct session2 *s,
                                return kr_ok();
                        } else {
                                int ret = uv_udp_try_send((uv_udp_t*)handle, (uv_buf_t *)iov, iovcnt,
-                                       the_network->enable_connect_udp ? NULL : comm->comm_addr);
+                                       the_network->enable_connect_udp
+                                       && s->proto != KR_PROTO_DOQ
+                                       ? NULL : comm->comm_addr);
+
                                if (ret > 0) // equals buffer size, only confuses us
                                        ret = 0;
                                if (ret == UV_EAGAIN) {
index b24b6165881cad1a40ca434cf118eb4697be717b..63eaa0534fa10cc0649dbc93dc66cd5fd394f68a 100644 (file)
@@ -15,6 +15,7 @@
 
 #define MAX_TLS_PADDING KR_EDNS_PAYLOAD
 #define TLS_MAX_UNCORK_RETRIES 100
+#define ENABLE_QUIC
 
 /* rfc 5476, 7.3 - handshake Protocol overview
  * https://tools.ietf.org/html/rfc5246#page-33
@@ -44,6 +45,10 @@ struct tls_credentials {
        gnutls_certificate_credentials_t credentials;
        time_t valid_until;
        char *ephemeral_servicename;
+#ifdef ENABLE_QUIC
+       gnutls_anti_replay_t tls_anti_replay;
+       // gnutls_datum_t tls_ticket_key;
+#endif /* ENABLE_QUIC */
 };
 
 
index 1ee0ac4e0cdd981aa41ab99e9dfd3346a0ca3be5..e8daf884dc2a4ca4cf3ca46a1817080875dc3cc8 100644 (file)
@@ -81,6 +81,7 @@ const char * kr_strerror(int e)
 #define KR_DNS_PORT   53
 #define KR_DNS_DOH_PORT 443
 #define KR_DNS_TLS_PORT 853
+#define KR_DNS_DOQ_PORT 853
 #define KR_EDNS_VERSION 0
 #define KR_EDNS_PAYLOAD 1232 /* Default UDP payload; see https://www.dnsflagday.net/2020/ */
 #define KR_CACHE_DEFAULT_TTL_MIN (5) /* avoid bursts of queries */
index 875fe8e309e55aa604265aef17fcc752313b6ce0..d91c09e43e8350c31cd27f14706fe3716eb45ee9 100644 (file)
@@ -26,8 +26,7 @@
     XX(TCP53, tcp53, "DNS TCP") \
     XX(DOT, dot, "DNS-over-TLS") \
     XX(DOH, doh, "DNS-over-HTTPS") \
-    XX(DOQ, doq, "DNS-over-QUIC") /* unused for now */ \
-    //
+    XX(DOQ, doq, "DNS-over-QUIC") \
 
 /** DNS protocol set - mutually exclusive options, contrary to
  * kr_request_qsource_flags
index 3d1451697a73676004bdc2e9159453b9593f6ac7..662cd9d280ae8e27614b0e7521c626bfbe666cf5 100644 (file)
@@ -139,7 +139,7 @@ class ListenSchema(ConfigSchema):
             return origin.port
         # default port number based on kind
         if origin.interface:
-            if origin.kind == "dot":
+            if origin.kind == "dot" or origin.kind == "doq":
                 return PortNumber(853)
             if origin.kind in ["doh-legacy", "doh2"]:
                 return PortNumber(443)