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.
This commit is contained in:
Willy Tarreau 2024-08-09 19:37:44 +02:00
parent ba4a416c66
commit d592ebdbeb
5 changed files with 28 additions and 7 deletions

View File

@ -31,6 +31,7 @@
#include <haproxy/errors.h>
#include <haproxy/fd.h>
#include <haproxy/log.h>
#include <haproxy/protocol.h>
#include <haproxy/sc_strm.h>
#include <haproxy/stconn.h>
#include <haproxy/stream.h>
@ -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);

View File

@ -38,6 +38,7 @@
#include <haproxy/lb_map.h>
#include <haproxy/lb_ss.h>
#include <haproxy/log.h>
#include <haproxy/protocol.h>
#include <haproxy/proxy.h>
#include <haproxy/sample.h>
#include <haproxy/sc_strm.h>
@ -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) {

View File

@ -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);

View File

@ -30,7 +30,7 @@
#include <haproxy/listener.h>
#include <haproxy/log.h>
#include <haproxy/namespace.h>
#include <haproxy/protocol-t.h>
#include <haproxy/protocol.h>
#include <haproxy/proto_sockpair.h>
#include <haproxy/sock.h>
#include <haproxy/sock_inet.h>
@ -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) {

View File

@ -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;