From 2d282f5608c69453df88977f72ffb8108c9529c6 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sun, 5 Nov 2023 13:58:07 +0100 Subject: [PATCH] Added AI_PASSIVE handling and option ai-passive --- CHANGES | 8 ++++++++ doc/socat.yo | 8 +++++++- xio-ip.c | 3 +++ xio-ip.h | 1 + xio-ipapp.c | 10 +++++++++- xio-udp.c | 19 ++++++++++++++++--- xioopts.c | 16 +++++++++++++++- xioopts.h | 1 + 8 files changed, 60 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 9de7304..e69e89b 100644 --- a/CHANGES +++ b/CHANGES @@ -84,6 +84,14 @@ Features: New option ai-addrconfig disables name resolution to protocol families that are not configured on the computer (e.g. IPv6) + Flag AI_PASSIVE is now automatically applied for LISTEN, RECV, and + RECVFROM type addresses, and with bind option. In addition to its + application to the getaddrinfo() function, when this flag is set while + no IP version is preferred by build, environment, option, or address + type, Socat chooses IPv6 because this might activate both versions (but + confirm option ipv6-v6only). + Added option ai-passive to control this flag explicitely. + Corrections: When a sub process (EXEC, SYSTEM) terminated with exit code other than 0, its last sent data might have been lost depending on timing of read/ diff --git a/doc/socat.yo b/doc/socat.yo index 38dc481..8da8ac7 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -2245,6 +2245,10 @@ dit(bf(tt(ai-addrconfig[=0|1]))), dit(bf(tt(addrconfig[=0|1]))) Sets or unsets the AI_ADDRCONFIG flag to prevent name resolution to address families that are not configured (e.g. IPv6). Default value is 1 in case the resolver does not get an address family hint. +dit(bf(tt(ai-passive[=0|1]))), dit(bf(tt(passive[=0|1]))) + Sets of unsets the AI_ADDRCONFIG flag for code(getaddrinfo)) calls. Default + is 1 for LISTEN, RECV, and RECVFROM type addresses, and with + link(bind)(OPTION_BIND) option. label(OPTION_RES_DEBUG)dit(bf(tt(res-debug))) label(OPTION_RES_AAONLY)dit(bf(tt(res-aaonly))) label(OPTION_RES_USEVC)dit(bf(tt(res-usevc))) @@ -2258,7 +2262,9 @@ label(OPTION_RES_DNSRCH)dit(bf(tt(res-dnsrch))) option flags. Append "=0" to clear a default option. See man NOEXPAND(resolver(5)) for more information on these options. These flags are per process, however socat() restores the old values after name resolution. - + Please note that these flags only affects DNS resolution, but not hosts or + NIS based name resolution, and they have no effect when (g)libc retrieves + the results from code(nscd). enddit() startdit()enddit()nl() diff --git a/xio-ip.c b/xio-ip.c index cb5a88a..71933e8 100644 --- a/xio-ip.c +++ b/xio-ip.c @@ -84,6 +84,9 @@ const struct optdesc opt_ip_recvif = { "ip-recvif", "recvdstaddrif",OPT_IP_RECVI #ifdef AI_ADDRCONFIG const struct optdesc opt_ai_addrconfig = { "ai-addrconfig", "addrconfig", OPT_AI_ADDRCONFIG, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_ADDRCONFIG }; #endif +#ifdef AI_PASSIVE +const struct optdesc opt_ai_passive = { "ai-passive", "passive", OPT_AI_PASSIVE, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_PASSIVE }; +#endif #if WITH_RES_DEPRECATED # define WITH_RES_AAONLY 1 diff --git a/xio-ip.h b/xio-ip.h index 2777461..b12d4d9 100644 --- a/xio-ip.h +++ b/xio-ip.h @@ -30,6 +30,7 @@ extern const struct optdesc opt_ip_recvif; extern const struct optdesc opt_ip_transparent; extern const struct optdesc opt_ai_addrconfig; +extern const struct optdesc opt_ai_passive; extern const struct optdesc opt_res_debug; extern const struct optdesc opt_res_aaonly; diff --git a/xio-ipapp.c b/xio-ipapp.c index fabc7b7..93f0e52 100644 --- a/xio-ipapp.c +++ b/xio-ipapp.c @@ -259,14 +259,22 @@ int _xioopen_ipapp_listen_prepare( int socktype) { char *bindname = NULL; + int ai_flags2[2]; int result; retropt_socket_pf(opts, pf); retropt_string(opts, OPT_BIND, &bindname); + + /* Set AI_PASSIVE, except when it is explicitely disabled */ + ai_flags2[0] = ai_flags[0]; + ai_flags2[1] = ai_flags[1]; + if (!(ai_flags2[1] & AI_PASSIVE)) + ai_flags2[0] |= AI_PASSIVE; + result = xioresolve(bindname, portname, *pf, socktype, ipproto, - us, uslen, ai_flags, res_opts); + us, uslen, ai_flags2, res_opts); if (result != STAT_OK) { /*! STAT_RETRY? */ return result; diff --git a/xio-udp.c b/xio-udp.c index 8e7477e..aaba4d3 100644 --- a/xio-udp.c +++ b/xio-udp.c @@ -507,6 +507,7 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts, int pf, int socktype, int ipproto) { union sockaddr_union us; socklen_t uslen = sizeof(us); + int ai_flags2[2]; int result; if (argc != 2) { @@ -532,9 +533,15 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts, #endif } + /* Set AI_PASSIVE, except when it is explicitely disabled */ + ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0]; + ai_flags2[1] = xfd->stream.para.socket.ip.ai_flags[1]; + if (!(ai_flags2[1] & AI_PASSIVE)) + ai_flags2[0] |= AI_PASSIVE; + if ((result = xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen, - xfd->stream.para.socket.ip.ai_flags, + ai_flags2, xfd->stream.para.socket.ip.res_opts)) != STAT_OK) { return result; @@ -586,6 +593,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts, union sockaddr_union us; socklen_t uslen = sizeof(us); char *rangename; + int ai_flags2[2]; int result; if (argc != 2) { @@ -610,10 +618,15 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts, #endif } + /* Set AI_PASSIVE, except when it is explicitely disabled */ + ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0]; + ai_flags2[1] = xfd->stream.para.socket.ip.ai_flags[1]; + if (!(ai_flags2[1] & AI_PASSIVE)) + ai_flags2[0] |= AI_PASSIVE; + if ((result = xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen, - xfd->stream.para.socket.ip.ai_flags, - xfd->stream.para.socket.ip.res_opts)) + ai_flags2, xfd->stream.para.socket.ip.res_opts)) != STAT_OK) { return result; } diff --git a/xioopts.c b/xioopts.c index 7878096..5a84ad5 100644 --- a/xioopts.c +++ b/xioopts.c @@ -178,6 +178,9 @@ const struct optname optionnames[] = { #endif #if defined(AI_ADDRCONFIG) IF_IP ("ai-addrconfig", &opt_ai_addrconfig) +#endif +#if defined(AI_PASSIVE ) + IF_IP ("ai-passive", &opt_ai_passive) #endif IF_INTERFACE("allmulti", &opt_iff_allmulti) #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) @@ -1251,6 +1254,9 @@ const struct optname optionnames[] = { IF_TERMIOS("parodd", &opt_parodd) #ifdef SO_PASSCRED IF_SOCKET ("passcred", &opt_so_passcred) +#endif +#if defined(AI_PASSIVE ) + IF_IP ("passive", &opt_ai_passive) #endif IF_EXEC ("path", &opt_path) #ifdef TCP_PAWS /* OSF1 */ @@ -3125,6 +3131,7 @@ int retropt_bind(struct opt *opts, char hostname[512], *hostp = hostname, *portp = NULL; size_t hostlen = sizeof(hostname)-1; int parsres; + int ai_flags2[2]; int result; if (retropt_string(opts, OPT_BIND, &bindname) < 0) { @@ -3180,11 +3187,18 @@ int retropt_bind(struct opt *opts, portp = bindp + strlen(portsep); } } + + /* Set AI_PASSIVE, except when it is explicitely disabled */ + ai_flags2[0] = ai_flags[0]; + ai_flags2[1] = ai_flags[1]; + if (!(ai_flags2[1] & AI_PASSIVE)) + ai_flags2[0] |= AI_PASSIVE; + if ((result = xioresolve(hostname[0]!='\0'?hostname:NULL, portp, af, socktype, ipproto, (union sockaddr_union *)sa, salen, - ai_flags, res_opts)) + ai_flags2, res_opts)) != STAT_OK) { Error("error resolving bind option"); return STAT_NORETRY; diff --git a/xioopts.h b/xioopts.h index ab9fe88..4a79218 100644 --- a/xioopts.h +++ b/xioopts.h @@ -203,6 +203,7 @@ enum e_func { enum e_optcode { OPT_ADDRESS_FAMILY = 1, OPT_AI_ADDRCONFIG, /* getaddrinfo() */ + OPT_AI_PASSIVE, /* getaddrinfo() */ /* these are not alphabetically, I know... */ OPT_B0, /* termios.c_cflag */ OPT_B50, /* termios.c_cflag */