mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
New address ACCEPT-FD
This commit is contained in:
parent
c311542e11
commit
ebacb7c4e8
10 changed files with 232 additions and 56 deletions
5
CHANGES
5
CHANGES
|
@ -117,6 +117,11 @@ Features:
|
||||||
network namespace.
|
network namespace.
|
||||||
Tests: NETNS NETNS_EXEC
|
Tests: NETNS NETNS_EXEC
|
||||||
|
|
||||||
|
New address ACCEPT-FD (ACCEPT) expects a listening file descriptor
|
||||||
|
passed from parent, and accepts one or more connections for data
|
||||||
|
transfer. This can be used with "inetd mode" of systemd.
|
||||||
|
Test: ACCEPT_FD
|
||||||
|
|
||||||
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/
|
||||||
|
|
29
doc/socat.yo
29
doc/socat.yo
|
@ -945,6 +945,18 @@ label(ADDRESS_SOCKET_SENDTO)dit(bf(tt(SOCKET-SENDTO:<domain>:<type>:<protocol>:<
|
||||||
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
|
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
|
||||||
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV)
|
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV)
|
||||||
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
|
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
|
||||||
|
label(ADDRESS_ACCEPT_FD)dit(bf(tt(ACCEPT-FD:<fdnum>)))
|
||||||
|
Expects a listening socket in <fdnum> and accepts one or (with option
|
||||||
|
link(fork)(OPTION_FORK)) more connections. This address type is useful under
|
||||||
|
systemd control with "inetd mode".nl()
|
||||||
|
Example: (link(example)(EXAMPLE_ADDRESS_ACCEPT_FD))
|
||||||
|
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET)link(TCP)(GROUP_TCP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl()
|
||||||
|
Useful options:
|
||||||
|
link(fork)(OPTION_FORK)),
|
||||||
|
link(range)(OPTION_RANGE),
|
||||||
|
link(sourceport)(OPTION_SOURCEPORT),
|
||||||
|
link(lowport)(OPTION_LOWPORT),
|
||||||
|
link(tcpwrap)(OPTION_TCPWRAPPERS),
|
||||||
label(ADDRESS_SOCKS4)dit(bf(tt(SOCKS4:<socks-server>:<host>:<port>)))
|
label(ADDRESS_SOCKS4)dit(bf(tt(SOCKS4:<socks-server>:<host>:<port>)))
|
||||||
Connects via <socks-server> [link(IP address)(TYPE_IP_ADDRESS)]
|
Connects via <socks-server> [link(IP address)(TYPE_IP_ADDRESS)]
|
||||||
to <host> [link(IPv4 address)(TYPE_IPV4_ADDRESS)]
|
to <host> [link(IPv4 address)(TYPE_IPV4_ADDRESS)]
|
||||||
|
@ -4140,6 +4152,23 @@ socat - \
|
||||||
sends an SSDP (Simple Service Discovery Protocol) query to the local network
|
sends an SSDP (Simple Service Discovery Protocol) query to the local network
|
||||||
and collects and outputs the answers received.
|
and collects and outputs the answers received.
|
||||||
|
|
||||||
|
|
||||||
|
label(EXAMPLE_ADDRESS_ACCEPT_FD)
|
||||||
|
mancommand(\.LP)
|
||||||
|
mancommand(\.nf)
|
||||||
|
mancommand(\fBsystemd-socket-activate -l 1077 --inetd socat ACCEPT:0,fork PIPE\fP)
|
||||||
|
mancommand(\.RE)
|
||||||
|
mancommand(\.fi)
|
||||||
|
|
||||||
|
htmlcommand(<hr><div class="shell">systemd-socket-activate -l 1077 --inetd socat ACCEPT:0,fork PIPE</div>)
|
||||||
|
|
||||||
|
tt(systemd-socket-activate) is a program for testing tt(systemd) socket
|
||||||
|
activation of daemons. With tt(--inetd) it waits for a connection on the
|
||||||
|
specified port. It does not accept the connection but passes the listening file
|
||||||
|
descriptor as FDs 0 and 1. Socat() accepts the waiting connection and starts
|
||||||
|
data transfer.
|
||||||
|
|
||||||
|
|
||||||
dit(bf(tt()))
|
dit(bf(tt()))
|
||||||
|
|
||||||
|
|
||||||
|
|
73
test.sh
73
test.sh
|
@ -6168,8 +6168,11 @@ if ! diff "$tref" "$tf" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED\n"
|
$PRINTF "$FAILED\n"
|
||||||
echo "$CMD0 &"
|
echo "$CMD0 &"
|
||||||
cat "${te}0" >&2
|
cat "${te}0" >&2
|
||||||
echo "$CMD1"
|
echo "$CMD1 &"
|
||||||
cat "${te}1" >&2
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}2" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
|
@ -6178,6 +6181,8 @@ else
|
||||||
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
numOK=$((numOK+1))
|
numOK=$((numOK+1))
|
||||||
fi # !(rc -ne 0)
|
fi # !(rc -ne 0)
|
||||||
wait
|
wait
|
||||||
|
@ -16648,6 +16653,70 @@ PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# Test the ACCEPT-FD address
|
||||||
|
NAME=ACCEPT_FD
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%systemd%*|*%accept%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: ACCEPT-FD address"
|
||||||
|
# Start Socat with address ACCEPT-FD via systemd-socket-activate for echoing
|
||||||
|
# data.
|
||||||
|
# Connect with a client; the test succeeds when the client gets its data back.
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
elif ! $(type systemd-socket-activate >/dev/null 2>&1); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}systemd-socket-activate not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! F=$(testfeats IP4 TCP LISTEN); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! A=$(testaddrs ACCEPT-FD PIPE STDIO TCP4); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! runsip4 >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
else
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
newport tcp4
|
||||||
|
CMD0="systemd-socket-activate -l $PORT --inetd $TRACE $SOCAT $opts ACCEPT-FD:0 PIPE"
|
||||||
|
CMD1="$TRACE $SOCAT $opts - TCP4:$LOCALHOST:$PORT"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
$CMD0 >/dev/null 2>"${te}0" &
|
||||||
|
pid0=$!
|
||||||
|
waittcp4port $PORT 1
|
||||||
|
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
||||||
|
rc1=$?
|
||||||
|
kill $pid0 2>/dev/null; wait
|
||||||
|
if echo "$da" |diff "${tf}1" - >$tdiff; then
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
else
|
||||||
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
cat $tdiff >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
@ -16840,7 +16909,7 @@ wait<something>port $PORT 1
|
||||||
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
||||||
rc1=$?
|
rc1=$?
|
||||||
kill $pid0 2>/dev/null; wait
|
kill $pid0 2>/dev/null; wait
|
||||||
if [ !!! ]; then
|
if echo "$da" |diff "${tf}1" - >$tdiff !!!; then
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
|
|
@ -35,7 +35,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
||||||
int duptostderr;
|
int duptostderr;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Error3("\"%s:%s\": wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
|
Error2("\"%s\": wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
retropt_bool(opts, OPT_DASH, &dash);
|
retropt_bool(opts, OPT_DASH, &dash);
|
||||||
|
|
57
xio-fdnum.c
57
xio-fdnum.c
|
@ -7,15 +7,21 @@
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
|
|
||||||
|
#include "xio-listen.h"
|
||||||
|
|
||||||
#include "xio-fdnum.h"
|
#include "xio-fdnum.h"
|
||||||
|
|
||||||
|
|
||||||
#if WITH_FDNUM
|
#if WITH_FDNUM
|
||||||
|
|
||||||
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
static int xioopen_accept_fd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
|
||||||
const struct addrdesc xioaddr_fd = { "FD", 3, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<num>") };
|
const struct addrdesc xioaddr_fd = { "FD", 1+XIO_RDWR, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<fdnum>") };
|
||||||
|
#if WITH_LISTEN
|
||||||
|
const struct addrdesc xioaddr_accept_fd = { "ACCEPT-FD", 1+XIO_RDWR, xioopen_accept_fd, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, 0, 0, 0 HELP(":<fdnum>") };
|
||||||
|
#endif /* WITH_LISTEN */
|
||||||
|
|
||||||
|
|
||||||
/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
|
/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
|
||||||
|
@ -28,7 +34,7 @@ static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Error3("%s:%s: wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
|
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
numfd = strtoul(argv[1], &a1, 0);
|
numfd = strtoul(argv[1], &a1, 0);
|
||||||
|
@ -46,8 +52,55 @@ static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WITH_LISTEN
|
||||||
|
|
||||||
|
/* Use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
|
||||||
|
static int xioopen_accept_fd(
|
||||||
|
int argc,
|
||||||
|
const char *argv[],
|
||||||
|
struct opt *opts,
|
||||||
|
int xioflags,
|
||||||
|
xiofile_t *xfd,
|
||||||
|
groups_t groups,
|
||||||
|
int dummy1,
|
||||||
|
int dummy2,
|
||||||
|
int dummy3)
|
||||||
|
{
|
||||||
|
char *a1;
|
||||||
|
int rw = (xioflags&XIO_ACCMODE);
|
||||||
|
int numfd;
|
||||||
|
union sockaddr_union us;
|
||||||
|
socklen_t uslen = sizeof(union sockaddr_union);
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
numfd = strtoul(argv[1], &a1, 0);
|
||||||
|
if (*a1 != '\0') {
|
||||||
|
Error1("error in FD number \"%s\"", argv[1]);
|
||||||
|
}
|
||||||
|
/* we dont want to see these fds in child processes */
|
||||||
|
if (Fcntl_l(numfd, F_SETFD, FD_CLOEXEC) < 0) {
|
||||||
|
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Getsockname(numfd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||||
|
Warn2("getsockname(fd=%d, ...): %s", numfd, strerror(errno));
|
||||||
|
}
|
||||||
|
Notice2("using file descriptor %d accepting a connection for %s", numfd, ddirection[rw]);
|
||||||
|
xfd->stream.fd = numfd;
|
||||||
|
if ((result = _xioopen_accept_fd(&xfd->stream, xioflags, (struct sockaddr *)&us, uslen, opts, us.soa.sa_family, 0, 0)) < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_LISTEN */
|
||||||
#endif /* WITH_FDNUM */
|
#endif /* WITH_FDNUM */
|
||||||
|
|
||||||
|
|
||||||
#if WITH_FD
|
#if WITH_FD
|
||||||
|
|
||||||
/* retrieve and apply options to a standard file descriptor.
|
/* retrieve and apply options to a standard file descriptor.
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define __xio_fdnum_h_included 1
|
#define __xio_fdnum_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc xioaddr_fd;
|
extern const struct addrdesc xioaddr_fd;
|
||||||
|
extern const struct addrdesc xioaddr_accept_fd;
|
||||||
|
|
||||||
extern int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3);
|
extern int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
|
114
xio-listen.c
114
xio-listen.c
|
@ -27,7 +27,6 @@ const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_R
|
||||||
#endif
|
#endif
|
||||||
const struct optdesc opt_accept_timeout = { "accept-timeout", "listen-timeout", OPT_ACCEPT_TIMEOUT, GROUP_LISTEN, PH_LISTEN, TYPE_TIMEVAL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.accept_timeout) };
|
const struct optdesc opt_accept_timeout = { "accept-timeout", "listen-timeout", OPT_ACCEPT_TIMEOUT, GROUP_LISTEN, PH_LISTEN, TYPE_TIMEVAL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.accept_timeout) };
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
applies and consumes the following option:
|
applies and consumes the following option:
|
||||||
PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
|
PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
|
||||||
|
@ -106,45 +105,11 @@ int
|
||||||
*/
|
*/
|
||||||
int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen,
|
int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen,
|
||||||
struct opt *opts, int pf, int socktype, int proto, int level) {
|
struct opt *opts, int pf, int socktype, int proto, int level) {
|
||||||
struct sockaddr sa;
|
|
||||||
socklen_t salen;
|
|
||||||
int backlog = 5; /* why? 1 seems to cause problems under some load */
|
int backlog = 5; /* why? 1 seems to cause problems under some load */
|
||||||
char *rangename;
|
|
||||||
bool dofork = false;
|
|
||||||
int maxchildren = 0;
|
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
char lisname[256];
|
|
||||||
union sockaddr_union _peername;
|
|
||||||
union sockaddr_union _sockname;
|
|
||||||
union sockaddr_union *pa = &_peername; /* peer address */
|
|
||||||
union sockaddr_union *la = &_sockname; /* local address */
|
|
||||||
socklen_t pas = sizeof(_peername); /* peer address size */
|
|
||||||
socklen_t las = sizeof(_sockname); /* local address size */
|
|
||||||
int result;
|
|
||||||
|
|
||||||
retropt_bool(opts, OPT_FORK, &dofork);
|
|
||||||
|
|
||||||
if (dofork) {
|
|
||||||
if (!(xioflags & XIO_MAYFORK)) {
|
|
||||||
Error("option fork not allowed here");
|
|
||||||
return STAT_NORETRY;
|
|
||||||
}
|
|
||||||
xfd->flags |= XIO_DOESFORK;
|
|
||||||
}
|
|
||||||
|
|
||||||
retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);
|
|
||||||
|
|
||||||
if (! dofork && maxchildren) {
|
|
||||||
Error("option max-children not allowed without option fork");
|
|
||||||
return STAT_NORETRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
if (dofork) {
|
|
||||||
xiosetchilddied(); /* set SIGCHLD handler */
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) {
|
if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) {
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -175,13 +140,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* under some circumstances (e.g., TCP listen on port 0) bind() fills empty
|
|
||||||
fields that we want to know. */
|
|
||||||
salen = sizeof(sa);
|
|
||||||
if (Getsockname(xfd->fd, us, &uslen) < 0) {
|
|
||||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
|
||||||
xfd->fd, &us, uslen, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||||
#if WITH_UNIX
|
#if WITH_UNIX
|
||||||
|
@ -197,6 +155,70 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
}
|
}
|
||||||
#endif /* WITH_UNIX */
|
#endif /* WITH_UNIX */
|
||||||
|
|
||||||
|
applyopts(xfd->fd, opts, PH_PRELISTEN);
|
||||||
|
retropt_int(opts, OPT_BACKLOG, &backlog);
|
||||||
|
applyopts(xfd->fd, opts, PH_LISTEN);
|
||||||
|
if (Listen(xfd->fd, backlog) < 0) {
|
||||||
|
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
return _xioopen_accept_fd(xfd, xioflags, us, uslen, opts, pf, proto,level);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _xioopen_accept_fd(
|
||||||
|
struct single *xfd,
|
||||||
|
int xioflags,
|
||||||
|
struct sockaddr *us,
|
||||||
|
socklen_t uslen,
|
||||||
|
struct opt *opts,
|
||||||
|
int pf,
|
||||||
|
int proto,
|
||||||
|
int level)
|
||||||
|
{
|
||||||
|
struct sockaddr sa;
|
||||||
|
socklen_t salen;
|
||||||
|
char *rangename;
|
||||||
|
bool dofork = false;
|
||||||
|
int maxchildren = 0;
|
||||||
|
char infobuff[256];
|
||||||
|
char lisname[256];
|
||||||
|
union sockaddr_union _peername;
|
||||||
|
union sockaddr_union _sockname;
|
||||||
|
union sockaddr_union *pa = &_peername; /* peer address */
|
||||||
|
union sockaddr_union *la = &_sockname; /* local address */
|
||||||
|
socklen_t pas = sizeof(_peername); /* peer address size */
|
||||||
|
socklen_t las = sizeof(_sockname); /* local address size */
|
||||||
|
int result;
|
||||||
|
|
||||||
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
|
||||||
|
if (dofork) {
|
||||||
|
if (!(xioflags & XIO_MAYFORK)) {
|
||||||
|
Error("option fork not allowed here");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
xfd->flags |= XIO_DOESFORK;
|
||||||
|
}
|
||||||
|
|
||||||
|
retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);
|
||||||
|
|
||||||
|
if (! dofork && maxchildren) {
|
||||||
|
Error("option max-children not allowed without option fork");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dofork) {
|
||||||
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Under some circumstances (e.g., TCP listen on port 0) bind() fills empty
|
||||||
|
fields that we want to know. */
|
||||||
|
salen = sizeof(sa);
|
||||||
|
if (Getsockname(xfd->fd, us, &uslen) < 0) {
|
||||||
|
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||||
|
xfd->fd, &us, uslen, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_IP4 /*|| WITH_IP6*/
|
#if WITH_IP4 /*|| WITH_IP6*/
|
||||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||||
if (xioparserange(rangename, pf, &xfd->para.socket.range,
|
if (xioparserange(rangename, pf, &xfd->para.socket.range,
|
||||||
|
@ -221,14 +243,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
|
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
|
||||||
#endif /* WITH_TCP || WITH_UDP */
|
#endif /* WITH_TCP || WITH_UDP */
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PRELISTEN);
|
|
||||||
retropt_int(opts, OPT_BACKLOG, &backlog);
|
|
||||||
applyopts(xfd->fd, opts, PH_LISTEN);
|
|
||||||
if (Listen(xfd->fd, backlog) < 0) {
|
|
||||||
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
|
||||||
return STAT_RETRYLATER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xioparms.logopt == 'm') {
|
if (xioparms.logopt == 'm') {
|
||||||
Info("starting accept loop, switching to syslog");
|
Info("starting accept loop, switching to syslog");
|
||||||
diag_set('y', xioparms.syslogfac); xioparms.logopt = 'y';
|
diag_set('y', xioparms.syslogfac); xioparms.logopt = 'y';
|
||||||
|
|
|
@ -20,5 +20,6 @@ int
|
||||||
int _xioopen_listen(struct single *fd, int xioflags,
|
int _xioopen_listen(struct single *fd, int xioflags,
|
||||||
struct sockaddr *us, socklen_t uslen,
|
struct sockaddr *us, socklen_t uslen,
|
||||||
struct opt *opts, int pf, int socktype, int proto, int level);
|
struct opt *opts, int pf, int socktype, int proto, int level);
|
||||||
|
extern int _xioopen_accept_fd(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen, struct opt *opts, int pf, int proto, int level);
|
||||||
|
|
||||||
#endif /* !defined(__xio_listen_h_included) */
|
#endif /* !defined(__xio_listen_h_included) */
|
||||||
|
|
|
@ -1847,7 +1847,7 @@ int xioparsenetwork(
|
||||||
char *addrname;
|
char *addrname;
|
||||||
const char *maskname;
|
const char *maskname;
|
||||||
if ((maskname = strchr(rangename, ':')) == NULL) {
|
if ((maskname = strchr(rangename, ':')) == NULL) {
|
||||||
Error1("syntax error in range \"%s\": use <addr>:<mask>", rangename);
|
Error1("syntax error in range \"%s\" of unspecified address family: use <addr>:<mask>", rangename);
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
++maskname; /* skip ':' */
|
++maskname; /* skip ':' */
|
||||||
|
|
|
@ -33,6 +33,10 @@ const struct addrname addressnames[] = {
|
||||||
{ "ABSTRACT-RECVFROM", &xioaddr_abstract_recvfrom },
|
{ "ABSTRACT-RECVFROM", &xioaddr_abstract_recvfrom },
|
||||||
{ "ABSTRACT-SENDTO", &xioaddr_abstract_sendto },
|
{ "ABSTRACT-SENDTO", &xioaddr_abstract_sendto },
|
||||||
#endif /* defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET) */
|
#endif /* defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET) */
|
||||||
|
#if WITH_LISTEN
|
||||||
|
{ "ACCEPT", &xioaddr_accept_fd },
|
||||||
|
{ "ACCEPT-FD", &xioaddr_accept_fd },
|
||||||
|
#endif
|
||||||
#if WITH_CREAT
|
#if WITH_CREAT
|
||||||
{ "CREAT", &xioaddr_creat },
|
{ "CREAT", &xioaddr_creat },
|
||||||
{ "CREATE", &xioaddr_creat },
|
{ "CREATE", &xioaddr_creat },
|
||||||
|
|
Loading…
Reference in a new issue