This is a pre-requisite to adding the abnsz socket address family:
in this patch we make use of protocol API rework started by
732913f
("MINOR: protocol: properly assign the sock_domain and sock_family") in
order to implement a dedicated address family for ABNS sockets (based on
UNIX parent family).
Thanks to this, it will become trivial to implement a new ABNSZ (for abns
zero) family which is essentially the same as ABNS but with a slight
difference when it comes to path handling (ABNS uses the whole sun_path
length, while ABNSZ's path is zero terminated and evaluation stops at 0)
It was verified that this patch doesn't break reg-tests and behaves
properly (tests performed on the CLI with show sess and show fd).
Anywhere relevant, AF_CUST_ABNS is handled alongside AF_UNIX. If no
distinction needs to be made, real_family() is used to fetch the proper
real family type to handle it properly.
Both stream and dgram were converted, so no functional change should be
expected for this "internal" rework, except that proto will be displayed
as "abns_{stream,dgram}" instead of "unix_{stream,dgram}".
Before ("show sess" output):
0x64c35528aab0: proto=unix_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=21,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
After:
0x619da7ad74c0: proto=abns_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=22,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
Co-authored-by: Aurelien DARRAGON <adarragon@haproxy.com>
#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)
#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);
*/
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);
case AF_INET6:
return sizeof(struct sockaddr_in6);
case AF_UNIX:
+ case AF_CUST_ABNS:
return sizeof(struct sockaddr_un);
}
return 0;
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;
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)
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)
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;
break;
case AF_UNIX:
+ case AF_CUST_ABNS:
un = (struct sockaddr_un *)ss;
if (un->sun_path[0]) {
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;
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;
/* 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);
}
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,
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,
return 1;
}
+ ret = real_family(ret);
+
if (ret == AF_UNIX) {
lua_pushstring(L, buffer+1);
return 1;
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);
/* 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;
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
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
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;
}
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;
}
.rx_unbind = sock_unbind,
};
+/* 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
.default_iocb = sock_accept_iocb,
};
+/* 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,
+
+ .nb_receivers = 0,
+};
+
INITCALL1(STG_REGISTER, protocol_register, &proto_uxst);
+INITCALL1(STG_REGISTER, protocol_register, &proto_abns_stream);
/********************************
* 1) low-level socket functions
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));
#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>
.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
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])
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:
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:
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:
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:
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:
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:
);
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,
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;
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;
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;
ptr = &((struct sockaddr_in6 *)addr)->sin6_addr;
break;
case AF_UNIX:
+ case AF_CUST_ABNS:
memcpy(str, "unix", 5);
return addr->ss_family;
default:
port = ((struct sockaddr_in6 *)addr)->sin6_port;
break;
case AF_UNIX:
+ case AF_CUST_ABNS:
memcpy(str, "unix", 5);
return addr->ss_family;
default:
break;
case AF_UNIX:
+ case AF_CUST_ABNS:
return HA_ANON_STR(scramble, ipstring);
break;