diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index 838c7c31c..42230acb8 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -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 */ diff --git a/include/haproxy/protocol.h b/include/haproxy/protocol.h index a6c50ceb5..475ac5ebb 100644 --- a/include/haproxy/protocol.h +++ b/include/haproxy/protocol.h @@ -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 */ /* diff --git a/src/proto_rhttp.c b/src/proto_rhttp.c index e831a5936..ccd56cf85 100644 --- a/src/proto_rhttp.c +++ b/src/proto_rhttp.c @@ -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, }; diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index 69ab45cfc..00f817f6a 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -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, diff --git a/src/sock_inet.c b/src/sock_inet.c index 028ffaa68..07364f02a 100644 --- a/src/sock_inet.c +++ b/src/sock_inet.c @@ -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, diff --git a/src/sock_unix.c b/src/sock_unix.c index 0f9bc9a38..510b4240b 100644 --- a/src/sock_unix.c +++ b/src/sock_unix.c @@ -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,