From 43861e32341a95ddf75f4b2134bc5c7da02891a9 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Mon, 28 Oct 2024 15:02:19 +0100 Subject: [PATCH] MEDIUM: sock_unix: use per-family addrcmp function Thanks to previous commit, we may now use dedicated addrcmp functions for each UNIX address family. This allows to simplify sock_unix_addrcmp() function and avoid useless checks in order to try to guess the socket type. In this patch we implement sock_abns_addrcmp() and sock_abnsz_addrcmp() functions, which are respectively used for ABNS and ABNSZ custom families sock_unix_addrcmp() now only holds regular UNIX socket comparing logic. --- include/haproxy/sock_unix.h | 2 + src/sock_unix.c | 74 ++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/include/haproxy/sock_unix.h b/include/haproxy/sock_unix.h index 39583e9f9b..9431094f30 100644 --- a/include/haproxy/sock_unix.h +++ b/include/haproxy/sock_unix.h @@ -33,6 +33,8 @@ extern struct proto_fam proto_fam_abns; extern struct proto_fam proto_fam_abnsz; int sock_unix_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); +int sock_abns_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); +int sock_abnsz_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); int sock_unix_bind_receiver(struct receiver *rx, char **errmsg); #endif /* _HAPROXY_SOCK_UNIX_H */ diff --git a/src/sock_unix.c b/src/sock_unix.c index 8785845b31..22ab862f5e 100644 --- a/src/sock_unix.c +++ b/src/sock_unix.c @@ -57,7 +57,7 @@ struct proto_fam proto_fam_abns = { .real_family = AF_UNIX, .sock_addrlen = sizeof(struct sockaddr_un), .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path), - .addrcmp = sock_unix_addrcmp, + .addrcmp = sock_abns_addrcmp, .bind = sock_unix_bind_receiver, .get_src = sock_get_src, .get_dst = sock_get_dst, @@ -70,7 +70,7 @@ struct proto_fam proto_fam_abnsz = { .real_family = AF_UNIX, .sock_addrlen = sizeof(struct sockaddr_un), .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path), - .addrcmp = sock_unix_addrcmp, + .addrcmp = sock_abnsz_addrcmp, .bind = sock_unix_bind_receiver, .get_src = sock_get_src, .get_dst = sock_get_dst, @@ -85,12 +85,58 @@ struct proto_fam proto_fam_abnsz = { */ -/* Compares two AF_UNIX sockaddr addresses. Returns 0 if they match or non-zero - * if they do not match. It also supports ABNS socket addresses (those starting - * with \0). For regular UNIX sockets however, this does explicitly support - * matching names ending exactly with .XXXXX.tmp which are newly bound sockets - * about to be replaced; this suffix is then ignored. Note that our UNIX socket - * paths are always zero-terminated. +/* Compares two AF_CUST_ABNS sockaddr addresses (ABNS UNIX sockets). Returns 0 if + * they match or non-zero. + */ +int sock_abns_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b) +{ + const struct sockaddr_un *au = (const struct sockaddr_un *)a; + const struct sockaddr_un *bu = (const struct sockaddr_un *)b; + + if (a->ss_family != b->ss_family) + return -1; + + if (a->ss_family != AF_CUST_ABNS) + return -1; + + if (au->sun_path[0] != bu->sun_path[0]) + return -1; + + if (au->sun_path[0] != '\0') + return -1; + + return memcmp(au->sun_path, bu->sun_path, sizeof(au->sun_path)); +} + + +/* Compares two AF_CUST_ABNSZ sockaddr addresses (ABNSZ UNIX sockets). Returns 0 if + * they match or non-zero. + */ +int sock_abnsz_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b) +{ + const struct sockaddr_un *au = (const struct sockaddr_un *)a; + const struct sockaddr_un *bu = (const struct sockaddr_un *)b; + + if (a->ss_family != b->ss_family) + return -1; + + if (a->ss_family != AF_CUST_ABNSZ) + return -1; + + if (au->sun_path[0] != bu->sun_path[0]) + return -1; + + if (au->sun_path[0] != '\0') + return -1; + + return strncmp(au->sun_path + 1, bu->sun_path + 1, sizeof(au->sun_path) - 1); +} + +/* Compares two AF_UNIX sockaddr addresses (regular UNIX sockets). Returns 0 if + * they match or non-zero. Tis does explicitly support matching names ending + * exactly with .XXXXX.tmp which are newly bound sockets about to be replaced; + * this suffix is then ignored. Note that our UNIX socket paths are always + * zero-terminated. */ int sock_unix_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b) { @@ -98,19 +144,13 @@ int sock_unix_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_st const struct sockaddr_un *bu = (const struct sockaddr_un *)b; int idx, dot, idx2; - if (real_family(a->ss_family) != real_family(b->ss_family)) + if (a->ss_family != b->ss_family) return -1; - if (real_family(a->ss_family) != AF_UNIX) + if (a->ss_family != AF_UNIX) return -1; - if (au->sun_path[0] != bu->sun_path[0]) - return -1; - - if (au->sun_path[0] == 0) - return memcmp(au->sun_path, bu->sun_path, sizeof(au->sun_path)); - - idx = 1; dot = 0; + idx = 0; dot = 0; while (au->sun_path[idx] == bu->sun_path[idx]) { if (au->sun_path[idx] == 0) return 0;