kdig: remove TCP Fast Open support

This commit is contained in:
Daniel Salzman 2025-12-15 15:45:36 +01:00
parent a657f110b6
commit e84658eca9
11 changed files with 30 additions and 158 deletions

View file

@ -226,9 +226,6 @@ Options
**+**\ [\ **no**\ ]\ **tcp**
Use the TCP protocol (default is UDP for standard query and TCP for AXFR/IXFR).
**+**\ [\ **no**\ ]\ **fastopen**
Use TCP Fast Open.
**+**\ [\ **no**\ ]\ **ignore**
Don't use TCP automatically if a truncated reply is received.
@ -401,7 +398,7 @@ Examples
$ kdig @1.1.1.1 +https example.com.
$ kdig @193.17.47.1 +https=/doh example.com.
$ kdig @8.8.4.4 +https +https-get example.com.
$ kdig @8.8.8.8 +https +tls-hostname=dns.google +fastopen example.com.
$ kdig @8.8.8.8 +https +tls-hostname=dns.google example.com.
6. More queries share one DoT connection::

View file

@ -309,15 +309,14 @@ static int sockaddr_to_authority(char *buf, const size_t buf_len, const struct s
return KNOT_EOK;
}
int https_ctx_connect(https_ctx_t *ctx, int sockfd, bool fastopen,
struct sockaddr_storage *addr)
int https_ctx_connect(https_ctx_t *ctx, int sockfd, struct sockaddr_storage *addr)
{
if (ctx == NULL || addr == NULL) {
return KNOT_EINVAL;
}
// Create TLS connection
int ret = tls_ctx_connect(ctx->tls, sockfd, fastopen, addr);
int ret = tls_ctx_connect(ctx->tls, sockfd, addr);
if (ret != KNOT_EOK) {
return ret;
}

View file

@ -85,7 +85,6 @@ int https_ctx_init(https_ctx_t *ctx, tls_ctx_t *tls_ctx, const https_params_t *p
*
* \param ctx HTTPS context.
* \param sockfd Socket descriptor.
* \param fastopen Use TCP Fast Open indication.
* \param addr Socket address storage with address to server side.
*
* \retval KNOT_EOK When successfully connected.
@ -94,8 +93,7 @@ int https_ctx_init(https_ctx_t *ctx, tls_ctx_t *tls_ctx, const https_params_t *p
* \retval KNOT_NET_ETIMEOUT When server respond takes too long.
* \retval KNOT_NET_ECONNECT When unnable to connect to the server.
*/
int https_ctx_connect(https_ctx_t *ctx, int sockfd, bool fastopen,
struct sockaddr_storage *addr);
int https_ctx_connect(https_ctx_t *ctx, int sockfd, struct sockaddr_storage *addr);
/*!
* \brief Send buffer as DNS message over HTTPS.

View file

@ -10,7 +10,6 @@
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h> // OpenBSD
#include <netinet/tcp.h> // TCP_FASTOPEN
#include <sys/socket.h>
#ifdef HAVE_SYS_UIO_H
@ -210,7 +209,6 @@ int net_init(const srv_info_t *local,
const int iptype,
const int socktype,
const int wait,
const net_flags_t flags,
const struct sockaddr *proxy_src,
const struct sockaddr *proxy_dst,
net_t *net)
@ -265,7 +263,6 @@ int net_init(const srv_info_t *local,
net->wait = wait;
net->local = local;
net->remote = remote;
net->flags = flags;
net->proxy.src = proxy_src;
net->proxy.dst = proxy_dst;
@ -339,59 +336,6 @@ int net_init_crypto(net_t *net,
return KNOT_EOK;
}
/*!
* Connect with TCP Fast Open.
*/
static int fastopen_connect(int sockfd, const struct addrinfo *srv)
{
#if defined( __FreeBSD__)
const int enable = 1;
return setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN, &enable, sizeof(enable));
#elif defined(__APPLE__)
// connection is performed lazily when first data are sent
struct sa_endpoints ep = {0};
ep.sae_dstaddr = srv->ai_addr;
ep.sae_dstaddrlen = srv->ai_addrlen;
int flags = CONNECT_DATA_IDEMPOTENT|CONNECT_RESUME_ON_READ_WRITE;
return connectx(sockfd, &ep, SAE_ASSOCID_ANY, flags, NULL, 0, NULL, NULL);
#elif defined(__linux__)
// connect() will be called implicitly with sendto(), sendmsg()
return 0;
#else
errno = ENOTSUP;
return -1;
#endif
}
/*!
* Sends data with TCP Fast Open.
*/
static int fastopen_send(int sockfd, const struct msghdr *msg, int timeout)
{
#if defined(__FreeBSD__) || defined(__APPLE__)
return sendmsg(sockfd, msg, 0);
#elif defined(__linux__)
int ret = sendmsg(sockfd, msg, MSG_FASTOPEN);
if (ret == -1 && errno == EINPROGRESS) {
struct pollfd pfd = {
.fd = sockfd,
.events = POLLOUT,
.revents = 0,
};
if (poll(&pfd, 1, 1000 * timeout) != 1) {
errno = ETIMEDOUT;
return -1;
}
ret = sendmsg(sockfd, msg, 0);
}
return ret;
#else
errno = ENOTSUP;
return -1;
#endif
}
static char *net_get_remote(const net_t *net)
{
if (net->tls.params->sni != NULL) {
@ -456,39 +400,32 @@ int net_connect(net_t *net)
if (net->socktype == SOCK_STREAM) {
int cs = 1, err;
socklen_t err_len = sizeof(err);
bool fastopen = net->flags & NET_FLAGS_FASTOPEN;
#ifdef TCP_NODELAY
(void)setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &cs, sizeof(cs));
#endif
// Establish a connection.
if (net->tls.params == NULL || !fastopen) {
if (fastopen) {
ret = fastopen_connect(sockfd, net->srv);
} else {
ret = connect(sockfd, net->srv->ai_addr, net->srv->ai_addrlen);
}
if (ret != 0 && errno != EINPROGRESS) {
WARN("can't connect to %s", net->remote_str);
net_close(net);
return KNOT_NET_ECONNECT;
}
ret = connect(sockfd, net->srv->ai_addr, net->srv->ai_addrlen);
if (ret != 0 && errno != EINPROGRESS) {
WARN("can't connect to %s", net->remote_str);
net_close(net);
return KNOT_NET_ECONNECT;
}
// Check for connection timeout.
if (!fastopen && poll(&pfd, 1, 1000 * net->wait) != 1) {
WARN("connection timeout for %s", net->remote_str);
net_close(net);
return KNOT_NET_ECONNECT;
}
// Check for connection timeout.
if (poll(&pfd, 1, 1000 * net->wait) != 1) {
WARN("connection timeout for %s", net->remote_str);
net_close(net);
return KNOT_NET_ECONNECT;
}
// Check if NB socket is writeable.
cs = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &err_len);
if (cs < 0 || err != 0) {
WARN("can't connect to %s", net->remote_str);
net_close(net);
return KNOT_NET_ECONNECT;
}
// Check if NB socket is writeable.
cs = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &err_len);
if (cs < 0 || err != 0) {
WARN("can't connect to %s", net->remote_str);
net_close(net);
return KNOT_NET_ECONNECT;
}
if (net->tls.params != NULL) {
@ -505,7 +442,7 @@ int net_connect(net_t *net)
if (remote && net->https.authority == NULL) {
net->https.authority = strdup(remote);
}
ret = https_ctx_connect(&net->https, sockfd, fastopen,
ret = https_ctx_connect(&net->https, sockfd,
(struct sockaddr_storage *)net->srv->ai_addr);
} else
#endif //LIBNGHTTP2
@ -517,7 +454,7 @@ int net_connect(net_t *net)
net_close(net);
return ret;
}
ret = tls_ctx_connect(&net->tls, sockfd, fastopen,
ret = tls_ctx_connect(&net->tls, sockfd,
(struct sockaddr_storage *)net->srv->ai_addr);
}
if (ret != KNOT_EOK) {
@ -669,8 +606,6 @@ int net_send(const net_t *net, const uint8_t *buf, const size_t buf_len)
}
// Send data over TCP.
} else {
bool fastopen = net->flags & NET_FLAGS_FASTOPEN;
char proxy_buf[PROXYV2_HEADER_MAXLEN];
uint16_t pktsize = htons(buf_len); // Leading packet length bytes.
struct iovec iov[3] = {
@ -705,12 +640,7 @@ int net_send(const net_t *net, const uint8_t *buf, const size_t buf_len)
ssize_t total = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
int ret = 0;
if (fastopen) {
ret = fastopen_send(net->sockfd, &msg, net->wait);
} else {
ret = sendmsg(net->sockfd, &msg, 0);
}
int ret = sendmsg(net->sockfd, &msg, 0);
if (ret != total) {
WARN("can't send query to %s", net->remote_str);
return KNOT_NET_ESEND;

View file

@ -25,11 +25,6 @@ typedef struct {
char *service;
} srv_info_t;
typedef enum {
NET_FLAGS_NONE = 0,
NET_FLAGS_FASTOPEN = 1 << 0,
} net_flags_t;
typedef struct {
/*! Socket descriptor. */
int sockfd;
@ -40,8 +35,6 @@ typedef struct {
int socktype;
/*! Timeout for all network operations. */
int wait;
/*! Connection flags. */
net_flags_t flags;
/*! Local interface parameters. */
const srv_info_t *local;
@ -148,7 +141,6 @@ void get_addr_str(const struct sockaddr_storage *ss,
* \param iptype IP version.
* \param socktype Socket type.
* \param wait Network timeout interval.
* \param flags Connection flags.
* \param proxy_src Proxy source address.
* \param proxy_dst Proxy destination address.
* \param net Network structure to initialize.
@ -161,7 +153,6 @@ int net_init(const srv_info_t *local,
const int iptype,
const int socktype,
const int wait,
const net_flags_t flags,
const struct sockaddr *proxy_src,
const struct sockaddr *proxy_dst,
net_t *net);

View file

@ -13,10 +13,6 @@
#include <gnutls/gnutls.h>
#include <gnutls/ocsp.h>
#include <gnutls/x509.h>
#define GNUTLS_VERSION_FASTOPEN_READY 0x030503
#if GNUTLS_VERSION_NUMBER >= GNUTLS_VERSION_FASTOPEN_READY
#include <gnutls/socket.h>
#endif
#include "utils/common/tls.h"
#include "utils/common/msg.h"
@ -554,8 +550,7 @@ int tls_ctx_setup_remote_endpoint(tls_ctx_t *ctx, const gnutls_datum_t *alpn,
return KNOT_EOK;
}
int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, bool fastopen,
struct sockaddr_storage *addr)
int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, struct sockaddr_storage *addr)
{
if (ctx == NULL) {
return KNOT_EINVAL;
@ -564,16 +559,7 @@ int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, bool fastopen,
int ret = 0;
gnutls_session_set_ptr(ctx->session, ctx);
if (fastopen) {
#if GNUTLS_VERSION_NUMBER >= GNUTLS_VERSION_FASTOPEN_READY
gnutls_transport_set_fastopen(ctx->session, sockfd, (struct sockaddr *)addr,
sockaddr_len(addr), 0);
#else
return KNOT_ENOTSUP;
#endif
} else {
gnutls_transport_set_int(ctx->session, sockfd);
}
gnutls_transport_set_int(ctx->session, sockfd);
gnutls_handshake_set_timeout(ctx->session, 1000 * ctx->wait);

View file

@ -62,8 +62,7 @@ int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params,
unsigned int flags, int wait);
int tls_ctx_setup_remote_endpoint(tls_ctx_t *ctx, const gnutls_datum_t *alpn,
size_t alpn_size, const char *priority, const char *remote);
int tls_ctx_connect(tls_ctx_t *ctx, int sockfd,
bool fastopen, struct sockaddr_storage *addr);
int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, struct sockaddr_storage *addr);
int tls_ctx_send(tls_ctx_t *ctx, const uint8_t *buf, const size_t buf_len);
int tls_ctx_receive(tls_ctx_t *ctx, uint8_t *buf, const size_t buf_len);

View file

@ -854,7 +854,6 @@ static int process_query(const query_t *query, net_t *net)
// Get connection parameters.
int socktype = get_socktype(query->protocol, query->type_num);
int flags = query->fastopen ? NET_FLAGS_FASTOPEN : NET_FLAGS_NONE;
// Loop over server list to process query.
WALK_LIST(server, query->servers) {
@ -870,7 +869,7 @@ static int process_query(const query_t *query, net_t *net)
for (size_t i = 0; i <= query->retries; i++) {
// Initialize network structure for current server.
ret = net_init(query->local, remote, iptype, socktype,
query->wait, flags,
query->wait,
(struct sockaddr *)&query->proxy.src,
(struct sockaddr *)&query->proxy.dst,
net);
@ -1214,7 +1213,6 @@ static int process_xfr(const query_t *query, net_t *net)
// Get connection parameters.
int socktype = get_socktype(query->protocol, query->type_num);
int flags = query->fastopen ? NET_FLAGS_FASTOPEN : NET_FLAGS_NONE;
// Use the first nameserver from the list.
srv_info_t *remote = HEAD(query->servers);
@ -1226,7 +1224,7 @@ static int process_xfr(const query_t *query, net_t *net)
get_sockname(socktype));
// Initialize network structure.
ret = net_init(query->local, remote, iptype, socktype, query->wait, flags,
ret = net_init(query->local, remote, iptype, socktype, query->wait,
(struct sockaddr *)&query->proxy.src,
(struct sockaddr *)&query->proxy.dst,
net);

View file

@ -617,24 +617,6 @@ static int opt_notcp(const char *arg, void *query)
return opt_ignore(arg, query);
}
static int opt_fastopen(const char *arg, void *query)
{
query_t *q = query;
q->fastopen = true;
return opt_tcp(arg, query);
}
static int opt_nofastopen(const char *arg, void *query)
{
query_t *q = query;
q->fastopen = false;
return KNOT_EOK;
}
static int opt_keepopen(const char *arg, void *query)
{
query_t *q = query;
@ -1619,9 +1601,6 @@ static const param_t kdig_opts2[] = {
{ "tcp", ARG_NONE, opt_tcp },
{ "notcp", ARG_NONE, opt_notcp },
{ "fastopen", ARG_NONE, opt_fastopen },
{ "nofastopen", ARG_NONE, opt_nofastopen },
{ "ignore", ARG_NONE, opt_ignore },
{ "noignore", ARG_NONE, opt_noignore },
@ -1739,7 +1718,6 @@ query_t *query_create(const char *owner, const query_t *conf)
query->operation = OPERATION_QUERY;
query->ip = IP_ALL;
query->protocol = PROTO_ALL;
query->fastopen = false;
query->port = strdup("");
query->udp_size = -1;
query->retries = DEFAULT_RETRIES_DIG;
@ -2416,7 +2394,6 @@ static void print_help(void)
" +[no]ttl * Show TTL value.\n"
" +[no]crypto * Show binary parts of RRSIGs and DNSKEYs.\n"
" +[no]tcp Use TCP protocol.\n"
" +[no]fastopen Use TCP Fast Open.\n"
" +[no]ignore Don't use TCP automatically if truncated.\n"
" +[no]keepopen Don't close the TCP connection to be reused.\n"
" +[no]tls Use TLS with Opportunistic privacy profile.\n"

View file

@ -69,8 +69,6 @@ struct query {
ip_t ip;
/*!< Protocol type (TCP, UDP) to use. */
protocol_t protocol;
/*!< Use TCP Fast Open. */
bool fastopen;
/*!< Keep TCP connection open. */
bool keepopen;
/*!< Port/service to connect to. */

View file

@ -434,7 +434,6 @@ static int pkt_sendrecv(knsupdate_params_t *params)
get_iptype(params->ip, params->server),
get_socktype(params->protocol, KNOT_RRTYPE_SOA),
params->wait,
NET_FLAGS_NONE,
NULL,
NULL,
&net);