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.
---
include/haproxy/dns-t.h | 7 ++++++-
include/haproxy/dns.h | 16 ++++++++++++++--
src/dns.c | 20 ++++++++++----------
src/resolvers.c | 15 +++++++++------
4 files changed, 39 insertions(+), 19 deletions(-)
diff --git a/include/haproxy/dns-t.h b/include/haproxy/dns-t.h
index c00075572..58dfb4f47 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 <haproxy/dns-t.h>
#include <haproxy/server-t.h>
-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 <type> 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 <type> 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 460af2def..5101a2f70 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 <type> on nameserver <ns>.
* 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 <type> on nameserver <ns>.
* 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 824cc2d06..c63a1f373 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 <type> of nameserver
+ * <ns> 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) {
--
2.55.0