diff --git a/src/utils/common/netio.c b/src/utils/common/netio.c index 28db3c9804bf33c172dc2536ac1759b0ad9347a4..d8ad4498925eba80a511aeb5df51a0e8d9a44285 100644 --- a/src/utils/common/netio.c +++ b/src/utils/common/netio.c @@ -547,6 +547,17 @@ int net_send(const net_t *net, const uint8_t *buf, const size_t buf_len) return KNOT_EINVAL; } +#ifdef LIBNGTCP2 + // Send data over QUIC. + if (net->quic.params.enable) { + int ret = quic_send_dns_query((quic_ctx_t *)&net->quic, + net->sockfd, net->srv, buf, buf_len); + if (ret != KNOT_EOK) { + WARN("can't send query to %s\n", net->remote_str); + return KNOT_NET_ESEND; + } + } else +#endif // Send data over UDP. if (net->socktype == SOCK_DGRAM) { if (sendto(net->sockfd, buf, buf_len, 0, net->srv->ai_addr, diff --git a/src/utils/common/quic.c b/src/utils/common/quic.c index ffa52c869e200b2c8cf51be55c31870a327707dc..a12e494ef61ddaa4cd27f05aca8ccb859f417336 100644 --- a/src/utils/common/quic.c +++ b/src/utils/common/quic.c @@ -740,4 +740,68 @@ int quic_ctx_connect(quic_ctx_t *ctx, int sockfd, struct addrinfo *dst_addr) return KNOT_EOK; } +int quic_send_dns_query(quic_ctx_t *ctx, int sockfd, struct addrinfo *srv, + const uint8_t *buf, const size_t buf_len) +{ + if (ctx == NULL || buf == NULL) { + return KNOT_EINVAL; + } + + ngtcp2_transport_params params; + uint16_t query_length = htons(buf_len); + ngtcp2_vec datav[] = { + { + .base = (uint8_t *)&query_length, + .len = sizeof(uint16_t) + },{ + .base = (uint8_t *)buf, + .len = buf_len + } + }; + size_t datavlen = sizeof(datav)/sizeof(*datav); + ngtcp2_vec *pdatav = datav; + + struct pollfd pfd = { + .fd = sockfd, + .events = POLLIN, + .revents = 0, + }; + + ctx->stream.out_ack += buf_len + sizeof(uint16_t); + while (ctx->stream.out_ack) { + if (quic_timeout(ctx->idle_ts, ctx->tls->wait)) { + WARN("QUIC, failed to send\n"); + set_application_error(ctx, DOQ_REQUEST_CANCELLED, + (uint8_t *)"Connection timeout", + sizeof("Connection timeout") - 1); + return KNOT_NET_ETIMEOUT; + } + int ret = quic_send_data(ctx, sockfd, srv->ai_family, pdatav, + datavlen); + if (ret != KNOT_EOK) { + WARN("QUIC, failed to send\n"); + return ret; + } + pdatav = NULL; + datavlen = 0; + + ngtcp2_conn_get_remote_transport_params(ctx->conn, ¶ms); + int timeout = quic_ceil_duration_to_ms(params.max_ack_delay); + ret = poll(&pfd, 1, timeout); + if (ret < 0) { + WARN("QUIC, failed to send\n"); + return knot_map_errno(); + } else if (ret == 0) { + continue; + } + ret = quic_recv(ctx, sockfd); + if (ret != KNOT_EOK) { + WARN("QUIC, failed to send\n"); + return ret; + } + } + + return KNOT_EOK; +} + #endif diff --git a/src/utils/common/quic.h b/src/utils/common/quic.h index 1b4ad1e448ad4b41ff2f70ad6d2718a441680abc..87ba18222851c3e0980527e573fc44972d1d7a0d 100644 --- a/src/utils/common/quic.h +++ b/src/utils/common/quic.h @@ -108,4 +108,7 @@ int quic_ctx_init(quic_ctx_t *ctx, tls_ctx_t *tls_ctx, const quic_params_t *para int quic_ctx_connect(quic_ctx_t *ctx, int sockfd, struct addrinfo *dst_addr); +int quic_send_dns_query(quic_ctx_t *ctx, int sockfd, struct addrinfo *srv, + const uint8_t *buf, const size_t buf_len); + #endif //LIBNGTCP2 diff --git a/src/utils/kdig/kdig_exec.c b/src/utils/kdig/kdig_exec.c index eb4031cb9c771902da68028b6c1b41762736c430..13556a3212293b359357007901ab63c5ad570d6d 100644 --- a/src/utils/kdig/kdig_exec.c +++ b/src/utils/kdig/kdig_exec.c @@ -392,8 +392,8 @@ static knot_pkt_t *create_query_packet(const query_t *query) // Set ID = 0 for packet send over HTTPS // Due HTTP cache it is convenient to set the query ID to 0 - GET messages has same header then -#ifdef LIBNGHTTP2 - if (query->https.enable) { +#if defined(LIBNGHTTP2) || defined(LIBNGTCP2) + if (query->https.enable || query->quic.enable) { knot_wire_set_id(packet->wire, 0); } #endif