diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index 42230acb8..9b3b7f559 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -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) diff --git a/include/haproxy/sock_unix.h b/include/haproxy/sock_unix.h index 99343417e..641fd823f 100644 --- a/include/haproxy/sock_unix.h +++ b/include/haproxy/sock_unix.h @@ -29,6 +29,7 @@ #include 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); diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 0bade0fd1..a8d289e12 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -741,7 +741,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); @@ -780,6 +783,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; diff --git a/src/cli.c b/src/cli.c index aa3709c19..c33b1b726 100644 --- a/src/cli.c +++ b/src/cli.c @@ -655,7 +655,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; @@ -1461,6 +1461,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) salen = sizeof(sa); if (getsockname(fd, (struct sockaddr *)&sa, &salen) != -1) { + /* only real address families in .ss_family (as provided by getsockname) */ if (sa.ss_family == AF_INET) chunk_appendf(&trash, " fam=ipv4 lport=%d", ntohs(((const struct sockaddr_in *)&sa)->sin_port)); else if (sa.ss_family == AF_INET6) @@ -1513,6 +1514,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) salen = sizeof(sa); if (getsockname(fd, (struct sockaddr *)&sa, &salen) != -1) { + /* only real address families in .ss_family (as provided by getsockname) */ if (sa.ss_family == AF_INET) chunk_appendf(&trash, " fam=ipv4 lport=%d", ntohs(((const struct sockaddr_in *)&sa)->sin_port)); else if (sa.ss_family == AF_INET6) @@ -1582,7 +1584,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; diff --git a/src/connection.c b/src/connection.c index 2e766c896..ea895963e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -2678,6 +2678,7 @@ static void conn_calculate_hash_sockaddr(const struct sockaddr_storage *ss, break; case AF_UNIX: + case AF_CUST_ABNS: un = (struct sockaddr_un *)ss; if (un->sun_path[0]) { diff --git a/src/extcheck.c b/src/extcheck.c index f01931b9d..2c04dc7a2 100644 --- a/src/extcheck.c +++ b/src/extcheck.c @@ -304,7 +304,8 @@ int prepare_external_check(struct check *check) port_to_str(&listener->rx.addr, buf, sizeof(buf)); check->argv[2] = strdup(buf); } - else if (listener->rx.addr.ss_family == AF_UNIX) { + else if (listener->rx.addr.ss_family == AF_UNIX || + listener->rx.addr.ss_family == AF_CUST_ABNS) { const struct sockaddr_un *un; un = (struct sockaddr_un *)&listener->rx.addr; @@ -412,6 +413,7 @@ static int connect_proc_chk(struct task *t) extern char **environ; struct rlimit limit; int fd; + sa_family_t family; /* close all FDs. Keep stdin/stdout/stderr in verbose mode */ fd = (global.mode & (MODE_QUIET|MODE_VERBOSE)) == MODE_QUIET ? 0 : 3; @@ -436,14 +438,15 @@ static int connect_proc_chk(struct task *t) /* Update some environment variables and command args: curconn, server addr and server port */ EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)), fail); - if (s->addr.ss_family == AF_UNIX) { + family = real_family(s->addr.ss_family); + if (family == AF_UNIX) { const struct sockaddr_un *un = (struct sockaddr_un *)&s->addr; strlcpy2(check->argv[3], un->sun_path, EXTCHK_SIZE_ADDR); memcpy(check->argv[4], "NOT_USED", 9); } else { addr_to_str(&s->addr, check->argv[3], EXTCHK_SIZE_ADDR); *check->argv[4] = 0; // just in case the address family changed - if (s->addr.ss_family == AF_INET || s->addr.ss_family == AF_INET6) + if (family == AF_INET || family == AF_INET6) snprintf(check->argv[4], EXTCHK_SIZE_UINT, "%u", s->svc_port); } diff --git a/src/frontend.c b/src/frontend.c index 22270f287..690ca1413 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -91,6 +91,7 @@ int frontend_accept(struct stream *s) fe->id, (fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"); break; case AF_UNIX: + case AF_CUST_ABNS: /* UNIX socket, only the destination is known */ send_log(fe, LOG_INFO, "Connect to unix:%d (%s/%s)\n", l->luid, @@ -131,6 +132,7 @@ int frontend_accept(struct stream *s) pn, get_host_port(src), alpn); break; case AF_UNIX: + case AF_CUST_ABNS: /* 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/hlua.c b/src/hlua.c index 89c26981c..c8b42dc81 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -3259,6 +3259,8 @@ __LJMP static inline int hlua_socket_info(struct lua_State *L, const struct sock return 1; } + ret = real_family(ret); + if (ret == AF_UNIX) { lua_pushstring(L, buffer+1); return 1; diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index b13856e3d..21a023828 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -1250,7 +1250,7 @@ int hlua_server_get_addr(lua_State *L) luaL_buffinit(L, &b); - switch (srv->addr.ss_family) { + switch (real_family(srv->addr.ss_family)) { case AF_INET: inet_ntop(AF_INET, &((struct sockaddr_in *)&srv->addr)->sin_addr, addr, INET_ADDRSTRLEN); diff --git a/src/log.c b/src/log.c index 42e766349..4b6c29c19 100644 --- a/src/log.c +++ b/src/log.c @@ -2728,7 +2728,7 @@ static inline void __do_send_log(struct log_target *target, struct log_header hd /* the socket's address is a file descriptor */ plogfd = (int *)&((struct sockaddr_in *)target->addr)->sin_addr.s_addr; } - else if (target->addr->ss_family == AF_UNIX) + else if (real_family(target->addr->ss_family) == AF_UNIX) plogfd = &logfdunix; else plogfd = &logfdinet; @@ -4168,7 +4168,7 @@ int sess_build_logline_orig(struct session *sess, struct stream *s, addr = (s ? sc_src(s->scf) : sess_src(sess)); if (addr) { /* sess->listener is always defined when the session's owner is an inbound connections */ - if (addr->ss_family == AF_UNIX) + if (real_family(addr->ss_family) == AF_UNIX) ret = lf_int(tmplog, dst + maxsize - tmplog, sess->listener->luid, ctx, LF_INT_LTOA); else @@ -4198,7 +4198,7 @@ int sess_build_logline_orig(struct session *sess, struct stream *s, addr = (s ? sc_dst(s->scf) : sess_dst(sess)); if (addr) { /* sess->listener is always defined when the session's owner is an inbound connections */ - if (addr->ss_family == AF_UNIX) + if (real_family(addr->ss_family) == AF_UNIX) ret = lf_int(tmplog, dst + maxsize - tmplog, sess->listener->luid, ctx, LF_INT_LTOA); else diff --git a/src/peers.c b/src/peers.c index 38ce54f08..5b9390cbc 100644 --- a/src/peers.c +++ b/src/peers.c @@ -4067,6 +4067,7 @@ static int peers_dump_peer(struct buffer *msg, struct appctx *appctx, struct pee chunk_appendf(&trash, " src=%s:%d", pn, get_host_port(conn->src)); break; case AF_UNIX: + case AF_CUST_ABNS: chunk_appendf(&trash, " src=unix:%d", strm_li(peer_s)->luid); break; } @@ -4077,6 +4078,7 @@ static int peers_dump_peer(struct buffer *msg, struct appctx *appctx, struct pee chunk_appendf(&trash, " addr=%s:%d", pn, get_host_port(conn->dst)); break; case AF_UNIX: + case AF_CUST_ABNS: 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 068cb9e72..32c9e45e9 100644 --- a/src/proto_uxdg.c +++ b/src/proto_uxdg.c @@ -65,7 +65,39 @@ struct protocol proto_uxdg = { .rx_unbind = sock_unbind, }; +/* Note: must not be declared 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 if the message is at most bytes long diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 51f508c31..0ae2569b3 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -83,7 +83,48 @@ struct protocol proto_uxst = { .default_iocb = sock_accept_iocb, }; +/* Note: must not be declared 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, + + .nb_receivers = 0, +}; + INITCALL1(STG_REGISTER, protocol_register, &proto_uxst); +INITCALL1(STG_REGISTER, protocol_register, &proto_abns_stream); /******************************** * 1) low-level socket functions diff --git a/src/session.c b/src/session.c index 60cb8bf41..5dbbba8e5 100644 --- a/src/session.c +++ b/src/session.c @@ -395,7 +395,7 @@ static void session_prepare_log_prefix(struct session *sess, struct buffer *out) ret = (src ? addr_to_str(src, pn, sizeof(pn)) : 0); if (ret <= 0) chunk_printf(out, "unknown ["); - else if (ret == AF_UNIX) + else if (real_family(ret) == AF_UNIX) chunk_printf(out, "%s:%d [", pn, sess->listener->luid); else chunk_printf(out, "%s:%d [", pn, get_host_port(src)); diff --git a/src/sock_unix.c b/src/sock_unix.c index 510b4240b..13e0c9146 100644 --- a/src/sock_unix.c +++ b/src/sock_unix.c @@ -29,8 +29,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -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]) diff --git a/src/stats-proxy.c b/src/stats-proxy.c index 76a14fdde..de14e299c 100644 --- a/src/stats-proxy.c +++ b/src/stats-proxy.c @@ -570,6 +570,7 @@ int stats_fill_li_line(struct proxy *px, struct listener *l, int flags, chunk_appendf(out, "[%s]:%d", str, port); break; case AF_UNIX: + case AF_CUST_ABNS: field = mkf_str(FO_CONFIG|FS_SERVICE, "unix"); break; case -1: @@ -1002,6 +1003,7 @@ int stats_fill_sv_line(struct proxy *px, struct server *sv, int flags, chunk_appendf(out, "[%s]:%d", str, sv->svc_port); break; case AF_UNIX: + case AF_CUST_ABNS: field = mkf_str(FO_CONFIG|FS_SERVICE, "unix"); break; case -1: diff --git a/src/stream.c b/src/stream.c index 7eea4ca93..0e84fab12 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3294,6 +3294,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch HA_ANON_STR(anon_key, pn), get_host_port(conn->src)); break; case AF_UNIX: + case AF_CUST_ABNS: chunk_appendf(buf, " source=unix:%d\n", strm_li(strm)->luid); break; default: @@ -3328,6 +3329,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch HA_ANON_STR(anon_key, pn), get_host_port(conn->dst)); break; case AF_UNIX: + case AF_CUST_ABNS: chunk_appendf(buf, " addr=unix:%d\n", strm_li(strm)->luid); break; default: @@ -3352,6 +3354,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch HA_ANON_STR(anon_key, pn), get_host_port(conn->src)); break; case AF_UNIX: + case AF_CUST_ABNS: chunk_appendf(buf, " addr=unix\n"); break; default: @@ -3375,6 +3378,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch HA_ANON_STR(anon_key, pn), get_host_port(conn->dst)); break; case AF_UNIX: + case AF_CUST_ABNS: chunk_appendf(buf, " addr=unix\n"); break; default: @@ -3809,6 +3813,7 @@ static int cli_io_handler_dump_sess(struct appctx *appctx) ); break; case AF_UNIX: + case AF_CUST_ABNS: 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 49c273bb6..572d12482 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1056,7 +1056,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; @@ -1223,7 +1223,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; @@ -1474,6 +1474,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; @@ -1921,6 +1922,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: @@ -1958,6 +1960,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: @@ -6418,6 +6421,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;