From: Manu Nicolas Date: Tue, 1 Sep 2026 10:44:48 +0000 (+0000) Subject: MINOR: dns: select the nameserver server type explicitly X-Git-Tag: v3.5-dev6~21 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=2f6aabe9cdcf520d339ac72cb568f6f972a5c0e5;p=haproxy.git MINOR: dns: select the nameserver server type explicitly DNS send, receive and response functions currently infer which server to use from the non-null member of a nameserver. This is unambiguous while a nameserver owns only one server, but prevents one logical nameserver from exposing both datagram and stream servers. Pass a dns_server_type through these interfaces and add predicates for readable type checks. Existing queries still select the same server, so this patch does not change runtime behavior. --- diff --git a/include/haproxy/dns-t.h b/include/haproxy/dns-t.h index 5f114e146..cf3c21043 100644 --- a/include/haproxy/dns-t.h +++ b/include/haproxy/dns-t.h @@ -136,6 +136,11 @@ struct dns_session { int shutdown; }; +enum dns_server_type { + DNS_SERVER_DGRAM = 0, + DNS_SERVER_STREAM, +}; + /* Structure describing a name server */ struct dns_nameserver { @@ -147,7 +152,7 @@ struct dns_nameserver { int line; /* line where the section appears */ } conf; /* config information */ - int (*process_responses)(struct dns_nameserver *ns); /* callback used to process responses */ + int (*process_responses)(struct dns_nameserver *ns, enum dns_server_type type); /* callback used to process responses */ struct dns_dgram_server *dgram; /* used for dgram dns */ struct dns_stream_server *stream; /* used for tcp dns */ diff --git a/include/haproxy/dns.h b/include/haproxy/dns.h index 3e0cd5939..c929415d0 100644 --- a/include/haproxy/dns.h +++ b/include/haproxy/dns.h @@ -25,10 +25,22 @@ #include #include -int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len); -ssize_t dns_recv_nameserver(struct dns_nameserver *ns, void *data, size_t size); +int dns_send_nameserver(struct dns_nameserver *ns, enum dns_server_type type, void *buf, size_t len); +ssize_t dns_recv_nameserver(struct dns_nameserver *ns, enum dns_server_type type, void *data, size_t size); int dns_dgram_init(struct dns_nameserver *ns, struct sockaddr_storage *sk); int dns_stream_init(struct dns_nameserver *ns, struct server *s); void dns_nameserver_deinit(struct dns_nameserver *ns); +/* Returns nonzero if selects a datagram server. */ +static inline int dns_server_type_is_dgram(enum dns_server_type type) +{ + return type == DNS_SERVER_DGRAM; +} + +/* Returns nonzero if selects a stream server. */ +static inline int dns_server_type_is_stream(enum dns_server_type type) +{ + return type == DNS_SERVER_STREAM; +} + #endif // _HAPROXY_DNS_H diff --git a/src/dns.c b/src/dns.c index 9418226d5..48d8d62e4 100644 --- a/src/dns.c +++ b/src/dns.c @@ -132,16 +132,16 @@ static int dns_connect_nameserver(struct dns_nameserver *ns) return 0; } -/* Sends a message to a name server +/* Sends a message using server type on nameserver . * It returns message length on success * or -1 in error case * 0 is returned in case of output ring buffer is full */ -int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len) +int dns_send_nameserver(struct dns_nameserver *ns, enum dns_server_type type, void *buf, size_t len) { int ret = -1; - if (ns->dgram) { + if (dns_server_type_is_dgram(type) && ns->dgram) { struct dgram_conn *dgram = &ns->dgram->conn; int fd; @@ -190,7 +190,7 @@ int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len) ns->counters->sent++; HA_SPIN_UNLOCK(DNS_LOCK, &dgram->lock); } - else if (ns->stream) { + else if (dns_server_type_is_stream(type) && ns->stream) { struct ist myist; myist = ist2(buf, len); @@ -208,16 +208,16 @@ int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len) void dns_session_free(struct dns_session *); -/* Receives a dns message +/* Receives a DNS message using server type on nameserver . * Returns message length * 0 is returned if no more message available * -1 in error case */ -ssize_t dns_recv_nameserver(struct dns_nameserver *ns, void *data, size_t size) +ssize_t dns_recv_nameserver(struct dns_nameserver *ns, enum dns_server_type type, void *data, size_t size) { ssize_t ret = -1; - if (ns->dgram) { + if (dns_server_type_is_dgram(type) && ns->dgram) { struct dgram_conn *dgram = &ns->dgram->conn; struct sockaddr_storage from = {0}; socklen_t fromlen = sizeof(from); @@ -249,7 +249,7 @@ ssize_t dns_recv_nameserver(struct dns_nameserver *ns, void *data, size_t size) } HA_SPIN_UNLOCK(DNS_LOCK, &dgram->lock); } - else if (ns->stream) { + else if (dns_server_type_is_stream(type) && ns->stream) { struct dns_stream_server *dss = ns->stream; struct dns_session *ds; @@ -353,7 +353,7 @@ static void dns_resolve_recv(struct dgram_conn *dgram) HA_SPIN_UNLOCK(DNS_LOCK, &dgram->lock); - ns->process_responses(ns); + ns->process_responses(ns, DNS_SERVER_DGRAM); } /* Called when a dns network socket is ready to send data */ @@ -1336,7 +1336,7 @@ static struct task *dns_process_rsp(struct task *t, void *context, unsigned int { struct dns_nameserver *ns = (struct dns_nameserver *)context; - ns->process_responses(ns); + ns->process_responses(ns, DNS_SERVER_STREAM); return t; } diff --git a/src/resolvers.c b/src/resolvers.c index 8c2ebe4b8..17d21d1f4 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -470,7 +470,10 @@ static int resolv_send_query(struct resolv_resolution *resolution) } list_for_each_entry(ns, &resolvers->nameservers, list) { - if (dns_send_nameserver(ns, trash.area, len) >= 0) + enum dns_server_type type; + + type = ns->dgram ? DNS_SERVER_DGRAM : DNS_SERVER_STREAM; + if (dns_send_nameserver(ns, type, trash.area, len) >= 0) resolution->nb_queries++; } @@ -2313,14 +2316,14 @@ void resolv_unlink_resolution(struct resolv_requester *requester) leave_resolver_code(); } -/* Called when a network IO is generated on a name server socket for an incoming - * packet. It performs the following actions: +/* Called when a network IO is generated on server type of nameserver + * for an incoming packet. It performs the following actions: * - check if the packet requires processing (not outdated resolution) * - ensure the DNS packet received is valid and call requester's callback * - call requester's error callback if invalid response * - check the dn_name in the packet against the one sent */ -static int resolv_process_responses(struct dns_nameserver *ns) +static int resolv_process_responses(struct dns_nameserver *ns, enum dns_server_type type) { struct dns_counters *tmpcounters; struct resolvers *resolvers; @@ -2341,9 +2344,9 @@ static int resolv_process_responses(struct dns_nameserver *ns) /* process all pending input messages */ while (1) { /* read message received */ - if ((buflen = dns_recv_nameserver(ns, (void *)buf, sizeof(buf))) <= 0) { + buflen = dns_recv_nameserver(ns, type, (void *)buf, sizeof(buf)); + if (buflen <= 0) break; - } /* message too big */ if (buflen > resolvers->accepted_payload_size) {