From: Willy Tarreau Date: Fri, 9 Aug 2024 17:37:44 +0000 (+0200) Subject: MEDIUM: socket: always properly use the sock_domain for requested families X-Git-Tag: v3.1-dev6~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d592ebdbeb298d725cceb6082eaa58d241b17675;p=thirdparty%2Fhaproxy.git MEDIUM: socket: always properly use the sock_domain for requested families Now we make sure to always look up the protocol's domain for an address family. Previously we would use it as-is, which prevented from properly using custom addresses (which is when they differ). This removes some hard-coded tests such as in log.c where UNIX vs UDP was explicitly checked for example. It requires a bit of care, however, so as to properly pass value 1 in the 3rd arg of the protocol_lookup() for DGRAM stuff. Maybe one day we'll change these for defines or enums to limit mistakes. --- diff --git a/src/dns.c b/src/dns.c index 2a4c4650fd..14c811a108 100644 --- a/src/dns.c +++ b/src/dns.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ DECLARE_STATIC_POOL(dns_msg_buf, "dns_msg_buf", DNS_TCP_MSG_RING_MAX_SIZE); static int dns_connect_nameserver(struct dns_nameserver *ns) { struct dgram_conn *dgram = &ns->dgram->conn; + const struct protocol *proto; int fd; /* Already connected */ @@ -55,7 +57,9 @@ static int dns_connect_nameserver(struct dns_nameserver *ns) return 0; /* Create an UDP socket and connect it on the nameserver's IP/Port */ - if ((fd = socket(dgram->addr.to.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + proto = protocol_lookup(dgram->addr.to.ss_family, PROTO_TYPE_DGRAM, 1); + BUG_ON(!proto); + if ((fd = socket(proto->fam->sock_domain, proto->sock_type, proto->sock_prot)) == -1) { send_log(NULL, LOG_WARNING, "DNS : section '%s': can't create socket for nameserver '%s'.\n", ns->counters->pid, ns->id); diff --git a/src/log.c b/src/log.c index 4b9573cdb7..d1f285a396 100644 --- a/src/log.c +++ b/src/log.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -2670,6 +2671,7 @@ static inline void __do_send_log(struct log_target *target, struct log_header hd }; static THREAD_LOCAL int logfdunix = -1; /* syslog to AF_UNIX socket */ static THREAD_LOCAL int logfdinet = -1; /* syslog to AF_INET socket */ + const struct protocol *proto; int *plogfd; int sent; size_t nbelem; @@ -2698,8 +2700,13 @@ static inline void __do_send_log(struct log_target *target, struct log_header hd if (plogfd && unlikely(*plogfd < 0)) { /* socket not successfully initialized yet */ - if ((*plogfd = socket(target->addr->ss_family, SOCK_DGRAM, - (target->addr->ss_family == AF_UNIX) ? 0 : IPPROTO_UDP)) < 0) { + + /* WT: this is not compliant with AF_CUST_* usage but we don't use that + * with DNS at the moment. + */ + proto = protocol_lookup(target->addr->ss_family, PROTO_TYPE_DGRAM, 1); + BUG_ON(!proto); + if ((*plogfd = socket(proto->fam->sock_domain, proto->sock_type, proto->sock_prot)) < 0) { static char once; if (!once) { diff --git a/src/resolvers.c b/src/resolvers.c index d01a30717c..33a9bbd792 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -2633,6 +2633,7 @@ static void resolvers_deinit(void) */ static int resolvers_finalize_config(void) { + const struct protocol *proto; struct resolvers *resolvers; struct proxy *px; int err_code = 0; @@ -2650,7 +2651,9 @@ static int resolvers_finalize_config(void) if (ns->dgram) { /* Check nameserver info */ - if ((fd = socket(ns->dgram->conn.addr.to.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + proto = protocol_lookup(ns->dgram->conn.addr.to.ss_family, PROTO_TYPE_DGRAM, 1); + BUG_ON(!proto); + if ((fd = socket(proto->fam->sock_domain, proto->sock_type, proto->sock_prot)) == -1) { if (!resolvers->conf.implicit) { /* emit a warning only if it was configured manually */ ha_alert("resolvers '%s': can't create socket for nameserver '%s'.\n", resolvers->id, ns->id); diff --git a/src/sock.c b/src/sock.c index 61ebf4a929..867a0ed76e 100644 --- a/src/sock.c +++ b/src/sock.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -268,6 +268,7 @@ static int sock_handle_system_err(struct connection *conn, struct proxy *be) int sock_create_server_socket(struct connection *conn, struct proxy *be, int *stream_err) { const struct netns_entry *ns = NULL; + const struct protocol *proto; int sock_fd; #ifdef USE_NS @@ -278,7 +279,9 @@ int sock_create_server_socket(struct connection *conn, struct proxy *be, int *st ns = __objt_server(conn->target)->netns; } #endif - sock_fd = my_socketat(ns, conn->dst->ss_family, SOCK_STREAM, 0); + proto = protocol_lookup(conn->dst->ss_family, PROTO_TYPE_STREAM, 0); + BUG_ON(!proto); + sock_fd = my_socketat(ns, proto->fam->sock_domain, SOCK_STREAM, 0); /* at first, handle common to all proto families system limits and permission related errors */ if (sock_fd == -1) { diff --git a/src/tools.c b/src/tools.c index 15756c880b..c1acea3341 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1941,6 +1941,7 @@ int addr_is_local(const struct netns_entry *ns, const struct sockaddr_storage *orig) { struct sockaddr_storage addr; + const struct proto_fam *fam; int result; int fd; @@ -1950,7 +1951,10 @@ int addr_is_local(const struct netns_entry *ns, memcpy(&addr, orig, sizeof(addr)); set_host_port(&addr, 0); - fd = my_socketat(ns, addr.ss_family, SOCK_DGRAM, IPPROTO_UDP); + fam = proto_fam_lookup(addr.ss_family); + BUG_ON(!fam); + + fd = my_socketat(ns, fam->sock_domain, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) return -1;