Added AI_PASSIVE handling and option ai-passive

This commit is contained in:
Gerhard Rieger 2023-11-05 13:58:07 +01:00
parent 4e00a345b4
commit 2d282f5608
8 changed files with 60 additions and 6 deletions

View file

@ -84,6 +84,14 @@ Features:
New option ai-addrconfig disables name resolution to protocol families New option ai-addrconfig disables name resolution to protocol families
that are not configured on the computer (e.g. IPv6) 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: Corrections:
When a sub process (EXEC, SYSTEM) terminated with exit code other than 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/ 0, its last sent data might have been lost depending on timing of read/

View file

@ -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 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 families that are not configured (e.g. IPv6). Default value is 1 in case the
resolver does not get an address family hint. 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_DEBUG)dit(bf(tt(res-debug)))
label(OPTION_RES_AAONLY)dit(bf(tt(res-aaonly))) label(OPTION_RES_AAONLY)dit(bf(tt(res-aaonly)))
label(OPTION_RES_USEVC)dit(bf(tt(res-usevc))) 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 option flags. Append "=0" to clear a default option. See man
NOEXPAND(resolver(5)) for more information on these options. These flags are NOEXPAND(resolver(5)) for more information on these options. These flags are
per process, however socat() restores the old values after name resolution. 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() enddit()
startdit()enddit()nl() startdit()enddit()nl()

View file

@ -84,6 +84,9 @@ const struct optdesc opt_ip_recvif = { "ip-recvif", "recvdstaddrif",OPT_IP_RECVI
#ifdef AI_ADDRCONFIG #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 }; 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 #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 #if WITH_RES_DEPRECATED
# define WITH_RES_AAONLY 1 # define WITH_RES_AAONLY 1

View file

@ -30,6 +30,7 @@ extern const struct optdesc opt_ip_recvif;
extern const struct optdesc opt_ip_transparent; extern const struct optdesc opt_ip_transparent;
extern const struct optdesc opt_ai_addrconfig; 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_debug;
extern const struct optdesc opt_res_aaonly; extern const struct optdesc opt_res_aaonly;

View file

@ -259,14 +259,22 @@ int _xioopen_ipapp_listen_prepare(
int socktype) int socktype)
{ {
char *bindname = NULL; char *bindname = NULL;
int ai_flags2[2];
int result; int result;
retropt_socket_pf(opts, pf); retropt_socket_pf(opts, pf);
retropt_string(opts, OPT_BIND, &bindname); 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 = result =
xioresolve(bindname, portname, *pf, socktype, ipproto, xioresolve(bindname, portname, *pf, socktype, ipproto,
us, uslen, ai_flags, res_opts); us, uslen, ai_flags2, res_opts);
if (result != STAT_OK) { if (result != STAT_OK) {
/*! STAT_RETRY? */ /*! STAT_RETRY? */
return result; return result;

View file

@ -507,6 +507,7 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
int pf, int socktype, int ipproto) { int pf, int socktype, int ipproto) {
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen = sizeof(us); socklen_t uslen = sizeof(us);
int ai_flags2[2];
int result; int result;
if (argc != 2) { if (argc != 2) {
@ -532,9 +533,15 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
#endif #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 = if ((result =
xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen, 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)) xfd->stream.para.socket.ip.res_opts))
!= STAT_OK) { != STAT_OK) {
return result; return result;
@ -586,6 +593,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen = sizeof(us); socklen_t uslen = sizeof(us);
char *rangename; char *rangename;
int ai_flags2[2];
int result; int result;
if (argc != 2) { if (argc != 2) {
@ -610,10 +618,15 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
#endif #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 = if ((result =
xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen, 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))
xfd->stream.para.socket.ip.res_opts))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }

View file

@ -178,6 +178,9 @@ const struct optname optionnames[] = {
#endif #endif
#if defined(AI_ADDRCONFIG) #if defined(AI_ADDRCONFIG)
IF_IP ("ai-addrconfig", &opt_ai_addrconfig) IF_IP ("ai-addrconfig", &opt_ai_addrconfig)
#endif
#if defined(AI_PASSIVE )
IF_IP ("ai-passive", &opt_ai_passive)
#endif #endif
IF_INTERFACE("allmulti", &opt_iff_allmulti) IF_INTERFACE("allmulti", &opt_iff_allmulti)
#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
@ -1251,6 +1254,9 @@ const struct optname optionnames[] = {
IF_TERMIOS("parodd", &opt_parodd) IF_TERMIOS("parodd", &opt_parodd)
#ifdef SO_PASSCRED #ifdef SO_PASSCRED
IF_SOCKET ("passcred", &opt_so_passcred) IF_SOCKET ("passcred", &opt_so_passcred)
#endif
#if defined(AI_PASSIVE )
IF_IP ("passive", &opt_ai_passive)
#endif #endif
IF_EXEC ("path", &opt_path) IF_EXEC ("path", &opt_path)
#ifdef TCP_PAWS /* OSF1 */ #ifdef TCP_PAWS /* OSF1 */
@ -3125,6 +3131,7 @@ int retropt_bind(struct opt *opts,
char hostname[512], *hostp = hostname, *portp = NULL; char hostname[512], *hostp = hostname, *portp = NULL;
size_t hostlen = sizeof(hostname)-1; size_t hostlen = sizeof(hostname)-1;
int parsres; int parsres;
int ai_flags2[2];
int result; int result;
if (retropt_string(opts, OPT_BIND, &bindname) < 0) { if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
@ -3180,11 +3187,18 @@ int retropt_bind(struct opt *opts,
portp = bindp + strlen(portsep); 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 = if ((result =
xioresolve(hostname[0]!='\0'?hostname:NULL, portp, xioresolve(hostname[0]!='\0'?hostname:NULL, portp,
af, socktype, ipproto, af, socktype, ipproto,
(union sockaddr_union *)sa, salen, (union sockaddr_union *)sa, salen,
ai_flags, res_opts)) ai_flags2, res_opts))
!= STAT_OK) { != STAT_OK) {
Error("error resolving bind option"); Error("error resolving bind option");
return STAT_NORETRY; return STAT_NORETRY;

View file

@ -203,6 +203,7 @@ enum e_func {
enum e_optcode { enum e_optcode {
OPT_ADDRESS_FAMILY = 1, OPT_ADDRESS_FAMILY = 1,
OPT_AI_ADDRCONFIG, /* getaddrinfo() */ OPT_AI_ADDRCONFIG, /* getaddrinfo() */
OPT_AI_PASSIVE, /* getaddrinfo() */
/* these are not alphabetically, I know... */ /* these are not alphabetically, I know... */
OPT_B0, /* termios.c_cflag */ OPT_B0, /* termios.c_cflag */
OPT_B50, /* termios.c_cflag */ OPT_B50, /* termios.c_cflag */