]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: protocol: properly assign the sock_domain and sock_family
authorWilly Tarreau <w@1wt.eu>
Fri, 9 Aug 2024 16:59:46 +0000 (18:59 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 21 Aug 2024 14:46:15 +0000 (16:46 +0200)
When we finally split sock_domain from sock_family in 2.3, something
was not cleanly finished. The family is what should be stored in the
address while the domain is what is supposed to be passed to socket().
But for the custom addresses, we did the opposite, just because the
protocol_lookup() function was acting on the domain, not the family
(both of which are equal for non-custom addresses).

This is an API bug but there's no point backporting it since it does
not have visible effects. It was visible in the code since a few places
were using PF_UNIX while others were comparing the domain against AF_MAX
instead of comparing the family.

This patch clarifies this in the comments on top of proto_fam, addresses
the indexing issue and properly reconfigures the two custom families.

include/haproxy/protocol-t.h
src/proto_rhttp.c
src/proto_sockpair.c
src/protocol.c
src/sock.c

index fde7590a48fb68d38f4288d74406821b6b3d6ed7..838c7c31c12a751256440329376df7bacd56032d 100644 (file)
@@ -70,7 +70,17 @@ enum proto_type {
 #define PROTO_F_REUSEPORT_TESTED                0x00000002 /* SO_REUSEPORT support was tested */
 
 /* protocol families define standard functions acting on a given address family
- * for a socket implementation, such as AF_INET/PF_INET for example.
+ * for a socket implementation, such as AF_INET/PF_INET for example. There is
+ * permanent confusion between domain and family. Here's how it works:
+ *   - the domain defines the format of addresses (e.g. sockaddr_in etc),
+ *     it is passed as the first argument to socket()
+ *   - the family is part of the address and is stored in receivers, servers
+ *     and everywhere there is an address. It's also a proto_fam selector.
+ * Domains are often PF_xxx though man 2 socket on Linux quotes 4.x BSD's man
+ * that says AF_* can be used everywhere. At least it tends to keep the code
+ * clearer about the intent. In HAProxy we're defining new address families
+ * with AF_CUST_* which appear in addresses, and they cannot be used for the
+ * domain, the socket() call must use sock_domain instead.
  */
 struct proto_fam {
        char name[PROTO_NAME_LEN];                      /* family name, zero-terminated */
index 0bf5bdc511e58679b620faa352218ae09dae8116..e831a593656f1a029d15dfd71bbc9f3f0cb30f5a 100644 (file)
@@ -22,8 +22,8 @@
 
 struct proto_fam proto_fam_rhttp = {
        .name = "rhttp",
-       .sock_domain = AF_CUST_RHTTP_SRV,
-       .sock_family = AF_INET,
+       .sock_domain = AF_INET,
+       .sock_family = AF_CUST_RHTTP_SRV,
        .bind = rhttp_bind_receiver,
 };
 
index a719063a81d94bb408abb6688f1e1370b9e16b24..69ab45cfcb13a9b1b7b0524223d9ff477ccdcf19 100644 (file)
@@ -50,8 +50,8 @@ struct connection *sockpair_accept_conn(struct listener *l, int *status);
 
 struct proto_fam proto_fam_sockpair = {
        .name = "sockpair",
-       .sock_domain = AF_CUST_SOCKPAIR,
-       .sock_family = AF_UNIX,
+       .sock_domain = AF_UNIX,
+       .sock_family = AF_CUST_SOCKPAIR,
        .sock_addrlen = sizeof(struct sockaddr_un),
        .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path),
        .addrcmp = NULL,
index 399835a887e7e4a1976f99db6c2a11a2f2906969..69f4595bb23c9353f2106ab58c326350329a0901 100644 (file)
@@ -38,14 +38,14 @@ __decl_spinlock(proto_lock);
 /* Registers the protocol <proto> */
 void protocol_register(struct protocol *proto)
 {
-       int sock_domain = proto->fam->sock_domain;
+       int sock_family = proto->fam->sock_family;
 
-       BUG_ON(sock_domain < 0 || sock_domain >= AF_CUST_MAX);
+       BUG_ON(sock_family < 0 || sock_family >= AF_CUST_MAX);
        BUG_ON(proto->proto_type >= PROTO_NUM_TYPES);
 
        HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
        LIST_APPEND(&protocols, &proto->list);
-       __protocol_by_family[sock_domain]
+       __protocol_by_family[sock_family]
                            [proto->proto_type]
                            [proto->xprt_type == PROTO_TYPE_DGRAM] = proto;
        HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
index df82c6ea7b309fac442c2bbbf79574d794ed1038..61ebf4a929e8e8ed79d62c3efbab18aca95867bb 100644 (file)
@@ -1147,7 +1147,7 @@ int _sock_supports_reuseport(const struct proto_fam *fam, int type, int protocol
        fd1 = fd2 = -1;
 
        /* ignore custom sockets */
-       if (!fam || fam->sock_domain >= AF_MAX)
+       if (!fam || fam->sock_family >= AF_MAX)
                goto leave;
 
        fd1 = socket(fam->sock_domain, type, protocol);