]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: protocol: add the real address family to the protocol
authorWilly Tarreau <w@1wt.eu>
Fri, 9 Aug 2024 18:13:10 +0000 (20:13 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 21 Aug 2024 15:37:46 +0000 (17:37 +0200)
For custom families, there's sometimes an underlying real address and
it would be nice to be able to directly use the real family in calls
to bind() and connect() without having to add explicit checks for
exceptions everywhere.

Let's add a .real_family field to struct proto_fam for this. For now
it's always equal to the family except for non-transferable ones such
as rhttp where it's equal to the custom one (anything else could fit).

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

index 838c7c31c12a751256440329376df7bacd56032d..42230acb8070b02717368b5f8f13fd64150ccf21 100644 (file)
@@ -74,8 +74,12 @@ enum proto_type {
  * 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.
+ *   - the socket 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.
+ *   - the real family is the one passed to bind() and connect() to map
+ *     custom families to their real equivalent one.
+ *
  * 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
@@ -86,6 +90,7 @@ struct proto_fam {
        char name[PROTO_NAME_LEN];                      /* family name, zero-terminated */
        int sock_domain;                                /* socket domain, as passed to socket()   */
        sa_family_t sock_family;                        /* socket family, for sockaddr */
+       sa_family_t real_family;                        /* the socket family passed to syscalls */
        ushort l3_addrlen;                              /* layer3 address length, used by hashes */
        socklen_t sock_addrlen;                         /* socket address length, used by bind() */
        /* 4-bytes hole here */
index a6c50ceb5f2f673677633c38477f90f30a137310..475ac5ebb48af6b7403e6e243dd2ea315da35e2b 100644 (file)
@@ -113,6 +113,17 @@ static inline const struct proto_fam *proto_fam_lookup(int ss_family)
        return NULL;
 }
 
+/* returns either the real family when known or AF_UNSPEC for non-existing
+ * families. Note that real families that contain a custom value will be
+ * returned as-is. This aims at simplifying address validation tests everywhere.
+ */
+static inline int real_family(int ss_family)
+{
+       const struct proto_fam *fam = proto_fam_lookup(ss_family);
+
+       return fam ? fam->real_family : AF_UNSPEC;
+}
+
 #endif /* _HAPROXY_PROTOCOL_H */
 
 /*
index e831a593656f1a029d15dfd71bbc9f3f0cb30f5a..ccd56cf85404da4dbaeb61b557d2cba09a4d3240 100644 (file)
@@ -24,6 +24,7 @@ struct proto_fam proto_fam_rhttp = {
        .name = "rhttp",
        .sock_domain = AF_INET,
        .sock_family = AF_CUST_RHTTP_SRV,
+       .real_family = AF_CUST_RHTTP_SRV,
        .bind = rhttp_bind_receiver,
 };
 
index 69ab45cfcb13a9b1b7b0524223d9ff477ccdcf19..00f817f6a04da7d6240323eb89dd799210ce63fc 100644 (file)
@@ -52,6 +52,7 @@ struct proto_fam proto_fam_sockpair = {
        .name = "sockpair",
        .sock_domain = AF_UNIX,
        .sock_family = AF_CUST_SOCKPAIR,
+       .real_family = AF_CUST_SOCKPAIR,
        .sock_addrlen = sizeof(struct sockaddr_un),
        .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path),
        .addrcmp = NULL,
index 028ffaa6809b10dfe570a4d7e85074f5553f8a39..07364f02aeb06f4b58c7806920061da2cf24f1b3 100644 (file)
@@ -35,6 +35,7 @@ struct proto_fam proto_fam_inet4 = {
        .name = "inet4",
        .sock_domain = PF_INET,
        .sock_family = AF_INET,
+       .real_family = AF_INET,
        .sock_addrlen = sizeof(struct sockaddr_in),
        .l3_addrlen = 32/8,
        .addrcmp = sock_inet4_addrcmp,
@@ -48,6 +49,7 @@ struct proto_fam proto_fam_inet6 = {
        .name = "inet6",
        .sock_domain = PF_INET6,
        .sock_family = AF_INET6,
+       .real_family = AF_INET6,
        .sock_addrlen = sizeof(struct sockaddr_in6),
        .l3_addrlen = 128/8,
        .addrcmp = sock_inet6_addrcmp,
index 0f9bc9a38d4a4aa4c7ce9981c36e705e7b81c60b..510b4240b1769f5b870fcfe3806fc97fba2c884e 100644 (file)
@@ -40,6 +40,7 @@ struct proto_fam proto_fam_unix = {
        .name = "unix",
        .sock_domain = PF_UNIX,
        .sock_family = AF_UNIX,
+       .real_family = AF_UNIX,
        .sock_addrlen = sizeof(struct sockaddr_un),
        .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path),
        .addrcmp = sock_unix_addrcmp,