diff --git a/include/haproxy/proto_sockpair.h b/include/haproxy/proto_sockpair.h index b04ebea38..6807169a7 100644 --- a/include/haproxy/proto_sockpair.h +++ b/include/haproxy/proto_sockpair.h @@ -21,6 +21,8 @@ #ifndef _HAPROXY_PROTO_SOCKPAIR_H #define _HAPROXY_PROTO_SOCKPAIR_H +extern struct proto_fam proto_fam_sockpair; + int recv_fd_uxst(int sock); int send_fd_uxst(int fd, int send_fd); int sockpair_bind_receiver(struct receiver *rx, void (*handler)(int fd), char **errmsg); diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index f29c94435..fe0c9812a 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -58,6 +58,21 @@ struct connection; #define CONNECT_DELACK_ALWAYS 0x00000004 /* Use a delayed ACK */ #define CONNECT_CAN_USE_TFO 0x00000008 /* We can use TFO for this connection */ +/* protocol families define standard functions acting on a given address family + * for a socket implementation, such as AF_INET/PF_INET for example. + */ +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 */ + socklen_t sock_addrlen; /* socket address length, used by bind() */ + int l3_addrlen; /* layer3 address length, used by hashes */ + int (*addrcmp)(const struct sockaddr_storage *, const struct sockaddr_storage *); /* compare addresses (like memcmp) */ + int (*bind)(struct receiver *rx, void (*handler)(int fd), char **errmsg); /* bind a receiver */ + int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve src addr */ + int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve dst addr */ +}; + /* This structure contains all information needed to easily handle a protocol. * Its primary goal is to ease listeners maintenance. Specifically, the * bind() primitive must be used before any fork(), and the enable_all() @@ -65,6 +80,7 @@ struct connection; */ struct protocol { char name[PROTO_NAME_LEN]; /* protocol name, zero-terminated */ + struct proto_fam *fam; /* protocol family */ int sock_domain; /* socket domain, as passed to socket() */ int sock_type; /* socket type, as passed to socket() */ int sock_prot; /* socket protocol, as passed to socket() */ diff --git a/include/haproxy/sock_inet.h b/include/haproxy/sock_inet.h index 9f95679b2..7ecdc7b60 100644 --- a/include/haproxy/sock_inet.h +++ b/include/haproxy/sock_inet.h @@ -31,6 +31,9 @@ extern int sock_inet6_v6only_default; extern int sock_inet_tcp_maxseg_default; extern int sock_inet6_tcp_maxseg_default; +extern struct proto_fam proto_fam_inet4; +extern struct proto_fam proto_fam_inet6; + int sock_inet4_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); int sock_inet_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); diff --git a/include/haproxy/sock_unix.h b/include/haproxy/sock_unix.h index 38ededaa0..3b46b4842 100644 --- a/include/haproxy/sock_unix.h +++ b/include/haproxy/sock_unix.h @@ -28,6 +28,8 @@ #include #include +extern struct proto_fam proto_fam_unix; + int sock_unix_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); int sock_unix_bind_receiver(struct receiver *rx, void (*handler)(int fd), char **errmsg); diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index a920f4e61..a2a9607a8 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -45,9 +45,22 @@ static void sockpair_add_listener(struct listener *listener, int port); static int sockpair_bind_listener(struct listener *listener, char *errmsg, int errlen); static int sockpair_connect_server(struct connection *conn, int flags); +struct proto_fam proto_fam_sockpair = { + .name = "sockpair", + .sock_domain = AF_CUST_SOCKPAIR, + .sock_family = AF_UNIX, + .sock_addrlen = sizeof(struct sockaddr_un), + .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path), + .addrcmp = NULL, + .bind = sockpair_bind_receiver, + .get_src = NULL, + .get_dst = NULL, +}; + /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_sockpair = { .name = "sockpair", + .fam = &proto_fam_sockpair, .sock_domain = AF_CUST_SOCKPAIR, .sock_type = SOCK_STREAM, .sock_prot = 0, diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 4af22e557..cb4dc3202 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -51,6 +51,7 @@ static void tcpv6_add_listener(struct listener *listener, int port); /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_tcpv4 = { .name = "tcpv4", + .fam = &proto_fam_inet4, .sock_domain = AF_INET, .sock_type = SOCK_STREAM, .sock_prot = IPPROTO_TCP, @@ -76,6 +77,7 @@ INITCALL1(STG_REGISTER, protocol_register, &proto_tcpv4); /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_tcpv6 = { .name = "tcpv6", + .fam = &proto_fam_inet6, .sock_domain = AF_INET6, .sock_type = SOCK_STREAM, .sock_prot = IPPROTO_TCP, diff --git a/src/proto_udp.c b/src/proto_udp.c index 43eff39c4..d4d6b2afa 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -47,6 +47,7 @@ static void udp6_add_listener(struct listener *listener, int port); /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_udp4 = { .name = "udp4", + .fam = &proto_fam_inet4, .sock_domain = AF_CUST_UDP4, .sock_type = SOCK_DGRAM, .sock_prot = IPPROTO_UDP, @@ -72,6 +73,7 @@ INITCALL1(STG_REGISTER, protocol_register, &proto_udp4); /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_udp6 = { .name = "udp6", + .fam = &proto_fam_inet6, .sock_domain = AF_CUST_UDP6, .sock_type = SOCK_DGRAM, .sock_prot = IPPROTO_UDP, diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 5ceb18f13..0b8e1767d 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -48,6 +48,7 @@ static int uxst_pause_listener(struct listener *l); /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_unix = { .name = "unix_stream", + .fam = &proto_fam_unix, .sock_domain = PF_UNIX, .sock_type = SOCK_STREAM, .sock_prot = 0, diff --git a/src/sock_inet.c b/src/sock_inet.c index 3bb4f34bf..09ff71e5e 100644 --- a/src/sock_inet.c +++ b/src/sock_inet.c @@ -31,6 +31,29 @@ #include #include +struct proto_fam proto_fam_inet4 = { + .name = "inet4", + .sock_domain = PF_INET, + .sock_family = AF_INET, + .sock_addrlen = sizeof(struct sockaddr_in), + .l3_addrlen = 32/8, + .addrcmp = sock_inet4_addrcmp, + .bind = sock_inet_bind_receiver, + .get_src = sock_get_src, + .get_dst = sock_inet_get_dst, +}; + +struct proto_fam proto_fam_inet6 = { + .name = "inet6", + .sock_domain = PF_INET6, + .sock_family = AF_INET6, + .sock_addrlen = sizeof(struct sockaddr_in6), + .l3_addrlen = 128/8, + .addrcmp = sock_inet6_addrcmp, + .bind = sock_inet_bind_receiver, + .get_src = sock_get_src, + .get_dst = sock_get_dst, +}; /* PLEASE NOTE for function below: * - sock_inet4_* is solely for AF_INET (IPv4) diff --git a/src/sock_unix.c b/src/sock_unix.c index 04accb4be..4620b7440 100644 --- a/src/sock_unix.c +++ b/src/sock_unix.c @@ -36,6 +36,18 @@ #include +struct proto_fam proto_fam_unix = { + .name = "unix", + .sock_domain = PF_UNIX, + .sock_family = AF_UNIX, + .sock_addrlen = sizeof(struct sockaddr_un), + .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path), + .addrcmp = sock_unix_addrcmp, + .bind = sock_unix_bind_receiver, + .get_src = sock_get_src, + .get_dst = sock_get_dst, +}; + /* PLEASE NOTE for functions below: * * The address family SHOULD always be checked. In some cases a function will