From: Willy Tarreau Date: Fri, 9 Aug 2024 19:12:23 +0000 (+0200) Subject: MINOR: protocol: create abnsz socket address family X-Git-Tag: v3.1-dev11~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d24768ab4473ee5867eb01ad56ef7fcac44e1192;p=thirdparty%2Fhaproxy.git MINOR: protocol: create abnsz socket address family For now it's the same as abns. We'll need to modify sock_unix_addrcmp(), and a few other ones to support effective path length when dealing with the \0. Let's check with Tristan's patch for this (upcoming patch). Co-authored-by: Aurelien DARRAGON --- diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index 9b3b7f5593..2a44e1471b 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -41,7 +41,8 @@ struct connection; #define AF_CUST_SOCKPAIR (AF_MAX + 2) #define AF_CUST_RHTTP_SRV (AF_MAX + 3) #define AF_CUST_ABNS (AF_MAX + 4) -#define AF_CUST_MAX (AF_MAX + 5) +#define AF_CUST_ABNSZ (AF_MAX + 5) +#define AF_CUST_MAX (AF_MAX + 6) /* * Test in case AF_CUST_MAX overflows the sa_family_t (unsigned int) diff --git a/include/haproxy/sock_unix.h b/include/haproxy/sock_unix.h index 641fd823f3..39583e9f9b 100644 --- a/include/haproxy/sock_unix.h +++ b/include/haproxy/sock_unix.h @@ -30,6 +30,7 @@ extern struct proto_fam proto_fam_unix; 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_unix_bind_receiver(struct receiver *rx, char **errmsg); diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index a8d289e129..c47e5cd1fe 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -744,7 +744,8 @@ static inline int is_addr(const struct sockaddr_storage *addr) /* 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) + if (addr->ss_family == AF_UNIX || addr->ss_family == AF_CUST_ABNS || + addr->ss_family == AF_CUST_ABNSZ || addr->ss_family == AF_CUST_SOCKPAIR) return 1; else return is_inet_addr(addr); @@ -784,6 +785,7 @@ static inline int get_addr_len(const struct sockaddr_storage *addr) return sizeof(struct sockaddr_in6); case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: return sizeof(struct sockaddr_un); } return 0; diff --git a/src/cli.c b/src/cli.c index 556be111b0..e63ba93642 100644 --- a/src/cli.c +++ b/src/cli.c @@ -655,11 +655,14 @@ int listeners_setenv(struct proxy *frontend, const char *varname) if (trash->data) chunk_appendf(trash, ";"); - if (l->rx.addr.ss_family == AF_UNIX || l->rx.addr.ss_family == AF_CUST_ABNS) { + if (l->rx.addr.ss_family == AF_UNIX || + l->rx.addr.ss_family == AF_CUST_ABNS || + l->rx.addr.ss_family == AF_CUST_ABNSZ) { const struct sockaddr_un *un; un = (struct sockaddr_un *)&l->rx.addr; - if (l->rx.addr.ss_family == AF_CUST_ABNS) { + if (l->rx.addr.ss_family == AF_CUST_ABNS || + l->rx.addr.ss_family == AF_CUST_ABNSZ) { chunk_appendf(trash, "abns@%s", un->sun_path+1); } else { chunk_appendf(trash, "unix@%s", un->sun_path); @@ -1584,11 +1587,14 @@ 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 || l->rx.addr.ss_family == AF_CUST_ABNS) { + if (l->rx.addr.ss_family == AF_UNIX || + l->rx.addr.ss_family == AF_CUST_ABNS || + l->rx.addr.ss_family == AF_CUST_ABNSZ) { const struct sockaddr_un *un; un = (struct sockaddr_un *)&l->rx.addr; - if (l->rx.addr.ss_family == AF_CUST_ABNS) { + if (l->rx.addr.ss_family == AF_CUST_ABNS || + l->rx.addr.ss_family == AF_CUST_ABNSZ) { chunk_appendf(&trash, "abns@%s ", un->sun_path+1); } else { chunk_appendf(&trash, "unix@%s ", un->sun_path); diff --git a/src/connection.c b/src/connection.c index 9c1d4a0133..07655934b5 100644 --- a/src/connection.c +++ b/src/connection.c @@ -2684,6 +2684,7 @@ static void conn_calculate_hash_sockaddr(const struct sockaddr_storage *ss, break; case AF_CUST_ABNS: + case AF_CUST_ABNSZ: conn_hash_update(hash, &((struct sockaddr_un *)ss)->sun_path, sizeof(((struct sockaddr_un *)ss)->sun_path), diff --git a/src/extcheck.c b/src/extcheck.c index 20e9fa8f94..c71639cd5f 100644 --- a/src/extcheck.c +++ b/src/extcheck.c @@ -306,7 +306,8 @@ int prepare_external_check(struct check *check) check->argv[2] = strdup(buf); } else if (listener->rx.addr.ss_family == AF_UNIX || - listener->rx.addr.ss_family == AF_CUST_ABNS) { + listener->rx.addr.ss_family == AF_CUST_ABNS || + listener->rx.addr.ss_family == AF_CUST_ABNSZ) { const struct sockaddr_un *un; un = (struct sockaddr_un *)&listener->rx.addr; diff --git a/src/frontend.c b/src/frontend.c index 690ca1413b..5e3821d76b 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -92,6 +92,7 @@ int frontend_accept(struct stream *s) break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: /* UNIX socket, only the destination is known */ send_log(fe, LOG_INFO, "Connect to unix:%d (%s/%s)\n", l->luid, @@ -133,6 +134,7 @@ int frontend_accept(struct stream *s) break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: /* UNIX socket, only the destination is known */ chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [unix:%d] ALPN=%s\n", s->uniq_id, fe->id, (unsigned short)l->rx.fd, (unsigned short)conn->handle.fd, diff --git a/src/peers.c b/src/peers.c index 5b9390cbca..5094002b1c 100644 --- a/src/peers.c +++ b/src/peers.c @@ -4068,6 +4068,7 @@ static int peers_dump_peer(struct buffer *msg, struct appctx *appctx, struct pee break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: chunk_appendf(&trash, " src=unix:%d", strm_li(peer_s)->luid); break; } @@ -4079,6 +4080,7 @@ static int peers_dump_peer(struct buffer *msg, struct appctx *appctx, struct pee break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: chunk_appendf(&trash, " addr=unix:%d", strm_li(peer_s)->luid); break; } diff --git a/src/proto_uxdg.c b/src/proto_uxdg.c index 32c9e45e92..b0a538340d 100644 --- a/src/proto_uxdg.c +++ b/src/proto_uxdg.c @@ -96,8 +96,40 @@ struct protocol proto_abns_dgram = { .nb_receivers = 0, }; +/* Note: must not be declared as its list will be overwritten */ +struct protocol proto_abnsz_dgram = { + .name = "abnsz_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_abnsz, + + /* 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_abnsz_dgram.receivers), + .nb_receivers = 0, +}; + INITCALL1(STG_REGISTER, protocol_register, &proto_uxdg); INITCALL1(STG_REGISTER, protocol_register, &proto_abns_dgram); +INITCALL1(STG_REGISTER, protocol_register, &proto_abnsz_dgram); /* This function tries to bind dgram unix socket listener. It may return a warning or * an error message in if the message is at most bytes long diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 0ae2569b36..f8b6958091 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -123,8 +123,49 @@ struct protocol proto_abns_stream = { .nb_receivers = 0, }; +/* Note: must not be declared as its list will be overwritten */ +struct protocol proto_abnsz_stream = { + .name = "abnsz_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_abnsz, + + /* 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, + + .nb_receivers = 0, +}; + INITCALL1(STG_REGISTER, protocol_register, &proto_uxst); INITCALL1(STG_REGISTER, protocol_register, &proto_abns_stream); +INITCALL1(STG_REGISTER, protocol_register, &proto_abnsz_stream); /******************************** * 1) low-level socket functions diff --git a/src/sock_unix.c b/src/sock_unix.c index 13e0c9146d..8785845b31 100644 --- a/src/sock_unix.c +++ b/src/sock_unix.c @@ -63,6 +63,19 @@ struct proto_fam proto_fam_abns = { .get_dst = sock_get_dst, }; +struct proto_fam proto_fam_abnsz = { + .name = "abnsz", + .sock_domain = AF_UNIX, + .sock_family = AF_CUST_ABNSZ, + .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 diff --git a/src/stats-proxy.c b/src/stats-proxy.c index de14e299c8..5fc1f5c5ed 100644 --- a/src/stats-proxy.c +++ b/src/stats-proxy.c @@ -571,6 +571,7 @@ int stats_fill_li_line(struct proxy *px, struct listener *l, int flags, break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: field = mkf_str(FO_CONFIG|FS_SERVICE, "unix"); break; case -1: @@ -1004,6 +1005,7 @@ int stats_fill_sv_line(struct proxy *px, struct server *sv, int flags, break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: field = mkf_str(FO_CONFIG|FS_SERVICE, "unix"); break; case -1: diff --git a/src/stream.c b/src/stream.c index 0e84fab12d..34696bd2c7 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3295,6 +3295,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: chunk_appendf(buf, " source=unix:%d\n", strm_li(strm)->luid); break; default: @@ -3330,6 +3331,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: chunk_appendf(buf, " addr=unix:%d\n", strm_li(strm)->luid); break; default: @@ -3355,6 +3357,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: chunk_appendf(buf, " addr=unix\n"); break; default: @@ -3379,6 +3382,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: chunk_appendf(buf, " addr=unix\n"); break; default: @@ -3814,6 +3818,7 @@ static int cli_io_handler_dump_sess(struct appctx *appctx) break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: chunk_appendf(&trash, " src=unix:%d fe=%s be=%s srv=%s", strm_li(curr_strm)->luid, diff --git a/src/tools.c b/src/tools.c index ec36a9d942..d2decb69be 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1053,6 +1053,10 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int str2 += 5; ss.ss_family = AF_CUST_ABNS; } + else if (strncmp(str2, "abnsz@", 5) == 0) { + str2 += 6; + ss.ss_family = AF_CUST_ABNSZ; + } else if (strncmp(str2, "ip@", 3) == 0) { str2 += 3; ss.ss_family = AF_UNSPEC; @@ -1218,14 +1222,14 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int goto out; } } - else if (ss.ss_family == AF_UNIX || ss.ss_family == AF_CUST_ABNS) { + else if (ss.ss_family == AF_UNIX || ss.ss_family == AF_CUST_ABNS || ss.ss_family == AF_CUST_ABNSZ) { struct sockaddr_un *un = (struct sockaddr_un *)&ss; int prefix_path_len; int max_path_len; int adr_len; int abstract = 0; - if (ss.ss_family == AF_CUST_ABNS) + if (ss.ss_family == AF_CUST_ABNS || ss.ss_family == AF_CUST_ABNSZ) abstract = 1; /* complete unix socket path name during startup or soft-restart is @@ -1474,8 +1478,10 @@ char * sa2str(const struct sockaddr_storage *addr, int port, int map_ports) break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: path = ((struct sockaddr_un *)addr)->sun_path; - if (addr->ss_family == AF_CUST_ABNS) { + if (addr->ss_family == AF_CUST_ABNS || + addr->ss_family == AF_CUST_ABNSZ) { const int max_length = sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path) - 1; return memprintf(&out, "abns@%.*s", max_length, path+1); } else { @@ -1922,6 +1928,7 @@ int addr_to_str(const struct sockaddr_storage *addr, char *str, int size) break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: memcpy(str, "unix", 5); return addr->ss_family; default: @@ -1960,6 +1967,7 @@ int port_to_str(const struct sockaddr_storage *addr, char *str, int size) break; case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: memcpy(str, "unix", 5); return addr->ss_family; default: @@ -6421,6 +6429,7 @@ const char *hash_ipanon(uint32_t scramble, char *ipstring, int hasport) case AF_UNIX: case AF_CUST_ABNS: + case AF_CUST_ABNSZ: return HA_ANON_STR(scramble, ipstring); break;