WIP: make abns a custom unix socket address family

Now it looks better and seems to work fine. Both stream and dgram
were converted, and regtests still pass. Some tests must be performed
on the CLI with show sess and show fd to be sure.
This commit is contained in:
Willy Tarreau 2024-08-09 18:48:14 +02:00
parent e5e49d9cf2
commit 7f2b85773f
8 changed files with 106 additions and 9 deletions

View File

@ -40,7 +40,8 @@ struct connection;
#define AF_CUST_EXISTING_FD (AF_MAX + 1)
#define AF_CUST_SOCKPAIR (AF_MAX + 2)
#define AF_CUST_RHTTP_SRV (AF_MAX + 3)
#define AF_CUST_MAX (AF_MAX + 4)
#define AF_CUST_ABNS (AF_MAX + 4)
#define AF_CUST_MAX (AF_MAX + 5)
/*
* Test in case AF_CUST_MAX overflows the sa_family_t (unsigned int)

View File

@ -29,6 +29,7 @@
#include <haproxy/receiver-t.h>
extern struct proto_fam proto_fam_unix;
extern struct proto_fam proto_fam_abns;
int sock_unix_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
int sock_unix_bind_receiver(struct receiver *rx, char **errmsg);

View File

@ -710,7 +710,10 @@ static inline int is_inet_addr(const struct sockaddr_storage *addr)
*/
static inline int is_addr(const struct sockaddr_storage *addr)
{
if (addr->ss_family == AF_UNIX || addr->ss_family == AF_CUST_SOCKPAIR)
/* WT: ideally we should use real_family(addr->ss_family) here, but we
* have so few custom addresses that it's simple enough to test them all.
*/
if (addr->ss_family == AF_UNIX || addr->ss_family == AF_CUST_ABNS || addr->ss_family == AF_CUST_SOCKPAIR)
return 1;
else
return is_inet_addr(addr);
@ -749,6 +752,7 @@ static inline int get_addr_len(const struct sockaddr_storage *addr)
case AF_INET6:
return sizeof(struct sockaddr_in6);
case AF_UNIX:
case AF_CUST_ABNS:
return sizeof(struct sockaddr_un);
}
return 0;

View File

@ -651,7 +651,7 @@ int listeners_setenv(struct proxy *frontend, const char *varname)
if (trash->data)
chunk_appendf(trash, ";");
if (l->rx.addr.ss_family == AF_UNIX) {
if (l->rx.addr.ss_family == AF_UNIX || l->rx.addr.ss_family == AF_CUST_ABNS) {
const struct sockaddr_un *un;
un = (struct sockaddr_un *)&l->rx.addr;
@ -1579,7 +1579,7 @@ static int cli_io_handler_show_cli_sock(struct appctx *appctx)
char addr[46];
char port[6];
if (l->rx.addr.ss_family == AF_UNIX) {
if (l->rx.addr.ss_family == AF_UNIX || l->rx.addr.ss_family == AF_CUST_ABNS) {
const struct sockaddr_un *un;
un = (struct sockaddr_un *)&l->rx.addr;

View File

@ -67,7 +67,39 @@ struct protocol proto_uxdg = {
.nb_receivers = 0,
};
/* Note: must not be declared <const> as its list will be overwritten */
struct protocol proto_abns_dgram = {
.name = "abns_dgram",
/* connection layer */
.xprt_type = PROTO_TYPE_DGRAM,
.listen = uxdg_bind_listener,
.enable = uxdg_enable_listener,
.disable = uxdg_disable_listener,
.add = default_add_listener,
.unbind = default_unbind_listener,
.suspend = default_suspend_listener,
.resume = default_resume_listener,
/* binding layer */
.rx_suspend = uxdg_suspend_receiver,
/* address family */
.fam = &proto_fam_abns,
/* socket layer */
.proto_type = PROTO_TYPE_DGRAM,
.sock_type = SOCK_DGRAM,
.sock_prot = 0,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
.rx_unbind = sock_unbind,
.receivers = LIST_HEAD_INIT(proto_abns_dgram.receivers),
.nb_receivers = 0,
};
INITCALL1(STG_REGISTER, protocol_register, &proto_uxdg);
INITCALL1(STG_REGISTER, protocol_register, &proto_abns_dgram);
/* This function tries to bind dgram unix socket listener. It may return a warning or
* an error message in <errmsg> if the message is at most <errlen> bytes long

View File

@ -85,7 +85,48 @@ struct protocol proto_uxst = {
.nb_receivers = 0,
};
/* Note: must not be declared <const> as its list will be overwritten */
struct protocol proto_abns_stream = {
.name = "abns_stream",
/* connection layer */
.xprt_type = PROTO_TYPE_STREAM,
.listen = uxst_bind_listener,
.enable = uxst_enable_listener,
.disable = uxst_disable_listener,
.add = default_add_listener,
.unbind = default_unbind_listener,
.suspend = default_suspend_listener,
.resume = default_resume_listener,
.accept_conn = sock_accept_conn,
.ctrl_init = sock_conn_ctrl_init,
.ctrl_close = sock_conn_ctrl_close,
.connect = uxst_connect_server,
.drain = sock_drain,
.check_events = sock_check_events,
.ignore_events = sock_ignore_events,
/* binding layer */
.rx_suspend = uxst_suspend_receiver,
/* address family */
.fam = &proto_fam_abns,
/* socket layer */
.proto_type = PROTO_TYPE_STREAM,
.sock_type = SOCK_STREAM,
.sock_prot = 0,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
.rx_unbind = sock_unbind,
.rx_listening = sock_accepting_conn,
.default_iocb = sock_accept_iocb,
.receivers = LIST_HEAD_INIT(proto_abns_stream.receivers),
.nb_receivers = 0,
};
INITCALL1(STG_REGISTER, protocol_register, &proto_uxst);
INITCALL1(STG_REGISTER, protocol_register, &proto_abns_stream);
/********************************
* 1) low-level socket functions

View File

@ -29,8 +29,9 @@
#include <haproxy/fd.h>
#include <haproxy/global.h>
#include <haproxy/listener.h>
#include <haproxy/receiver-t.h>
#include <haproxy/namespace.h>
#include <haproxy/protocol.h>
#include <haproxy/receiver-t.h>
#include <haproxy/sock.h>
#include <haproxy/sock_unix.h>
#include <haproxy/tools.h>
@ -49,6 +50,19 @@ struct proto_fam proto_fam_unix = {
.get_dst = sock_get_dst,
};
struct proto_fam proto_fam_abns = {
.name = "abns",
.sock_domain = AF_UNIX,
.sock_family = AF_CUST_ABNS,
.real_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
@ -71,10 +85,10 @@ 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 (a->ss_family != b->ss_family)
if (real_family(a->ss_family) != real_family(b->ss_family))
return -1;
if (a->ss_family != AF_UNIX)
if (real_family(a->ss_family) != AF_UNIX)
return -1;
if (au->sun_path[0] != bu->sun_path[0])

View File

@ -1043,7 +1043,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
else if (strncmp(str2, "abns@", 5) == 0) {
str2 += 5;
abstract = 1;
ss.ss_family = AF_UNIX;
ss.ss_family = AF_CUST_ABNS;
}
else if (strncmp(str2, "ip@", 3) == 0) {
str2 += 3;
@ -1186,7 +1186,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
goto out;
}
}
else if (ss.ss_family == AF_UNIX) {
else if (ss.ss_family == AF_UNIX || ss.ss_family == AF_CUST_ABNS) {
struct sockaddr_un *un = (struct sockaddr_un *)&ss;
int prefix_path_len;
int max_path_len;
@ -1435,6 +1435,7 @@ char * sa2str(const struct sockaddr_storage *addr, int port, int map_ports)
ptr = &((struct sockaddr_in6 *)addr)->sin6_addr;
break;
case AF_UNIX:
case AF_CUST_ABNS:
path = ((struct sockaddr_un *)addr)->sun_path;
if (path[0] == '\0') {
const int max_length = sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path) - 1;
@ -1882,6 +1883,7 @@ int addr_to_str(const struct sockaddr_storage *addr, char *str, int size)
ptr = &((struct sockaddr_in6 *)addr)->sin6_addr;
break;
case AF_UNIX:
case AF_CUST_ABNS:
memcpy(str, "unix", 5);
return addr->ss_family;
default:
@ -1919,6 +1921,7 @@ int port_to_str(const struct sockaddr_storage *addr, char *str, int size)
port = ((struct sockaddr_in6 *)addr)->sin6_port;
break;
case AF_UNIX:
case AF_CUST_ABNS:
memcpy(str, "unix", 5);
return addr->ss_family;
default:
@ -6352,6 +6355,7 @@ const char *hash_ipanon(uint32_t scramble, char *ipstring, int hasport)
break;
case AF_UNIX:
case AF_CUST_ABNS:
return HA_ANON_STR(scramble, ipstring);
break;