* 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
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 */
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 */
/*
.name = "rhttp",
.sock_domain = AF_INET,
.sock_family = AF_CUST_RHTTP_SRV,
+ .real_family = AF_CUST_RHTTP_SRV,
.bind = rhttp_bind_receiver,
};
.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,
.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,
.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,
.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,