Core: add AF_UNIX address support to PROXY protocol v2 write.

Add ngx_proxy_protocol_unix_addrs_t with two 108-byte path fields
and an AF_UNIX case in ngx_proxy_protocol_v2_write_header(), using
the family-promotion framework: when either src or dst is AF_UNIX,
af is set to NGX_PROXY_PROTOCOL_AF_UNIX and both paths are extracted
by ngx_proxy_protocol_v2_write_unix().  Mixed IPv4/IPv6 with Unix-
domain connections emit IPv4/IPv6 headers with 127.0.0.1 or ::1 as
the Unix-side substitute address via write_ipv4()/write_ipv6().

Update NGX_PROXY_PROTOCOL_V2_MAX_HEADER from 52 to 232 to cover
the largest possible v2 address block (16-byte fixed header plus
216 bytes for Unix src and dst paths).
This commit is contained in:
Vadim Zhestikov 2026-05-20 14:04:10 -07:00
parent 3fc8c7d42e
commit 2c7812a4f4

View file

@ -12,7 +12,7 @@
#define NGX_PROXY_PROTOCOL_V2_SIGNATURE "\r\n\r\n\0\r\nQUIT\n"
#define NGX_PROXY_PROTOCOL_V1_MAX_HEADER 107
#define NGX_PROXY_PROTOCOL_V2_MAX_HEADER 52
#define NGX_PROXY_PROTOCOL_V2_MAX_HEADER 232
#define NGX_PROXY_PROTOCOL_AF_UNSPEC 0
#define NGX_PROXY_PROTOCOL_AF_INET 1
@ -75,6 +75,16 @@ typedef struct {
} ngx_proxy_protocol_inet6_addrs_t;
#if (NGX_HAVE_UNIX_DOMAIN)
typedef struct {
u_char src_addr[108];
u_char dst_addr[108];
} ngx_proxy_protocol_unix_addrs_t;
#endif
typedef struct {
u_char type;
u_char len[2];
@ -383,7 +393,7 @@ ngx_proxy_protocol_v2_write_ipv4(struct sockaddr *sa, u_char *addr,
ngx_memcpy(port, &sin->sin_port, 2);
} else {
/* unknown: substitute 127.0.0.1 port 0 */
/* AF_UNIX or unknown: substitute 127.0.0.1 port 0 */
ngx_memcpy(addr, loopback, 4);
port[0] = 0;
port[1] = 0;
@ -422,7 +432,7 @@ ngx_proxy_protocol_v2_write_ipv6(struct sockaddr *sa, u_char *addr,
break;
default:
/* unknown: substitute ::1 port 0 */
/* AF_UNIX or unknown: substitute ::1 port 0 */
ngx_memzero(addr, 16);
addr[15] = 1;
port[0] = 0;
@ -434,6 +444,31 @@ ngx_proxy_protocol_v2_write_ipv6(struct sockaddr *sa, u_char *addr,
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
static void
ngx_proxy_protocol_v2_write_unix(struct sockaddr *sa, socklen_t socklen,
u_char *addr)
{
struct sockaddr_un *saun;
if (sa->sa_family != AF_UNIX) {
*addr = '\0';
return;
}
saun = (struct sockaddr_un *) sa;
if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) {
*addr = '\0';
} else {
ngx_cpystrn(addr, (u_char *) saun->sun_path, 108);
}
}
#endif
static u_char *
ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *last)
{
@ -447,6 +482,9 @@ ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *las
struct in6_addr *src6, *dst6;
ngx_proxy_protocol_inet6_addrs_t *in6;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
ngx_proxy_protocol_unix_addrs_t *un;
#endif
if (last - buf < NGX_PROXY_PROTOCOL_V2_MAX_HEADER) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
@ -491,6 +529,12 @@ ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *las
#endif
if (src_fam == AF_INET || dst_fam == AF_INET) {
af = NGX_PROXY_PROTOCOL_AF_INET;
#if (NGX_HAVE_UNIX_DOMAIN)
} else if (src_fam == AF_UNIX || dst_fam == AF_UNIX) {
af = NGX_PROXY_PROTOCOL_AF_UNIX;
#endif
} else {
af = NGX_PROXY_PROTOCOL_AF_UNSPEC;
}
@ -562,6 +606,27 @@ ngx_proxy_protocol_v2_write_header(ngx_connection_t *c, u_char *buf, u_char *las
p += sizeof(ngx_proxy_protocol_inet6_addrs_t);
break;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
case NGX_PROXY_PROTOCOL_AF_UNIX:
header->len[0] = 0;
header->len[1] = sizeof(ngx_proxy_protocol_unix_addrs_t);
un = (ngx_proxy_protocol_unix_addrs_t *) p;
ngx_memzero(un, sizeof(ngx_proxy_protocol_unix_addrs_t));
ngx_proxy_protocol_v2_write_unix(c->sockaddr, c->socklen,
un->src_addr);
ngx_proxy_protocol_v2_write_unix(c->local_sockaddr, c->local_socklen,
un->dst_addr);
p += sizeof(ngx_proxy_protocol_unix_addrs_t);
break;
#endif
default: /* NGX_PROXY_PROTOCOL_AF_UNSPEC */