mirror of
https://github.com/moparisthebest/socat
synced 2024-12-21 14:38:48 -05:00
merged feature protocol-type
This commit is contained in:
commit
86c596bd51
6
CHANGES
6
CHANGES
@ -31,6 +31,10 @@ new features:
|
||||
new address options ipv6-tclass and ipv6-unicast-hops set the related
|
||||
socket options.
|
||||
|
||||
so-type now only affect the socket() and socketpair() calls, not the
|
||||
name resolution. so-type and so-prototype can be applied to all socket
|
||||
based addresses.
|
||||
|
||||
corrections:
|
||||
some raw IP and UNIX datagram modes failed on BSD systems
|
||||
|
||||
@ -78,6 +82,8 @@ further changes:
|
||||
Makefile now supports datarootdir (thanks to Camillo Lugaresi for
|
||||
providing the patch)
|
||||
|
||||
cleanup in xio-unix.c
|
||||
|
||||
####################### V 1.6.0.1:
|
||||
|
||||
new features:
|
||||
|
2
VERSION
2
VERSION
@ -1 +1 @@
|
||||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar"
|
||||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar+protocol"
|
||||
|
23
doc/socat.yo
23
doc/socat.yo
@ -1590,11 +1590,23 @@ label(OPTION_SNDLOWAT)dit(bf(tt(sndlowat=<bytes>)))
|
||||
layer will send the data to <bytes> [link(int)(TYPE_INT)].
|
||||
label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>)))
|
||||
Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)].
|
||||
label(OPTION_TYPE)dit(bf(tt(type=<type>)))
|
||||
Sets the type of the socket, usually as argument to the code(socket()) or
|
||||
code(socketpair()) call, to <type> [link(int)(TYPE_INT)].
|
||||
label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>)))
|
||||
Forces the use of the specified IP version or protocol. <string> can be
|
||||
something like "ip4" or "ip6". The resulting value is
|
||||
used as first argument to the code(socket()) or code(socketpair()) calls.
|
||||
This option affects address resolution and the required syntax of bind and
|
||||
range options.
|
||||
label(OPTION_SO_TYPE)dit(bf(tt(type=<type>)))
|
||||
Sets the type of the socket, specified as second argument to the
|
||||
code(socket()) or code(socketpair()) calls, to <type>
|
||||
[link(int)(TYPE_INT)]. Address resolution is not affected by this option.
|
||||
Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3
|
||||
means raw socket.
|
||||
label(OPTION_SO_PROTOTYPE)dit(bf(tt(prototype)))
|
||||
Sets the protocol of the socket, specified as third argument to the
|
||||
code(socket()) or code(socketpair()) calls, to <prototype>
|
||||
[link(int)(TYPE_INT)]. Address resolution is not affected by this option.
|
||||
6 means TCP, 17 means UDP.
|
||||
COMMENT(label(OPTION_USELOOPBACK)dit(bf(tt(useloopback)))
|
||||
Sets the code(SO_USELOOPBACK) socket option.)
|
||||
COMMENT(label(OPTION_ACCEPTCONN)dit(bf(tt(acceptconn)))
|
||||
@ -1623,8 +1635,6 @@ COMMENT(label(OPTION_PASSCRED)dit(bf(tt(passcred)))
|
||||
Set the code(SO_PASSCRED) socket option.)
|
||||
COMMENT(label(OPTION_PEERCRED)dit(bf(tt(peercred)))
|
||||
This is a read-only socket option.)
|
||||
COMMENT(label(OPTION_PROTOTYPE)dit(bf(tt(prototype)))
|
||||
Tries to set the code(SO_PROTOTYPE) socket option.)
|
||||
COMMENT(label(OPTION_REUSEPORT)dit(bf(tt(reuseport)))
|
||||
Set the code(SO_REUSEPORT) socket option.)
|
||||
COMMENT(label(OPTION_SECUTIYAUTHENTICATION)dit(bf(tt(securityauthentication)))
|
||||
@ -1637,9 +1647,6 @@ COMMENT(label(OPTION_SIOCSPGRP)dit(bf(tt(siocspgrp=<pid_t>)))
|
||||
Set the SIOCSPGRP with code(ioclt()) to enable SIGIO.)
|
||||
COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs)))
|
||||
Set the code(SO_USE_IFBUFS) socket option.)
|
||||
label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>)))
|
||||
Forces the use of the specified IP version. <string> can be
|
||||
something like "ip4" or "ip6".
|
||||
label(OPTION_SO_TIMESTAMP)dit(bf(tt(so-timestamp)))
|
||||
Sets the SO_TIMESTAMP socket option. This enables receiving and logging of
|
||||
timestamp ancillary messages.
|
||||
|
3
filan.c
3
filan.c
@ -479,6 +479,9 @@ int sockan(int fd, FILE *outfile) {
|
||||
{SO_REUSEADDR, "REUSEADDR"},
|
||||
{SO_TYPE, "TYPE"},
|
||||
{SO_ERROR, "ERROR"},
|
||||
#ifdef SO_PROTOTYPE
|
||||
{SO_PROTOTYPE, "PROTOTYPE"},
|
||||
#endif
|
||||
{SO_DONTROUTE, "DONTROUTE"},
|
||||
{SO_BROADCAST, "BROADCAST"},
|
||||
{SO_SNDBUF, "SNDBUF"},
|
||||
|
82
test.sh
82
test.sh
@ -2374,9 +2374,9 @@ N=$((N+1))
|
||||
#}
|
||||
|
||||
|
||||
NAME=UNIXSOCKET
|
||||
NAME=UNIXSTREAM
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%$NAME%*)
|
||||
*%functions%*|*%unix%*|*%$NAME%*)
|
||||
TEST="$NAME: echo via connection to UNIX domain socket"
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
@ -2384,7 +2384,7 @@ ts="$td/test$N.socket"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD1="$SOCAT $opts UNIX-LISTEN:$ts PIPE"
|
||||
CMD2="$SOCAT $opts -!!- UNIX:$ts"
|
||||
CMD2="$SOCAT $opts -!!- UNIX-CONNECT:$ts"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD1 </dev/null >$tf 2>"${te}1" &
|
||||
bg=$! # background process id
|
||||
@ -8520,82 +8520,6 @@ esac
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
while read SCM_ENABLE SCM_RECV SCM_TYPE SCM_NAME SCM_VALUE
|
||||
do
|
||||
|
||||
# test: logging of ancillary message with ip-recvopt
|
||||
NAME=UDP4SCM_$SCM_TYPE
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%ip4%*|*%dgram%*|*%udp%*|*%udp4%*|*%recv%*|*%ancillary%*|*%$NAME%*)
|
||||
#set -vx
|
||||
TEST="$NAME: IPv4 ancillary messages"
|
||||
# idea: start a socat process with udp4-recv:..,ip-recvopts and send it a packet
|
||||
# with IP options (ip-options). check the info log for the appropriate output.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
ts1p=$PORT; PORT=$((PORT+1))
|
||||
ts1a="127.0.0.1"
|
||||
ts1="$ts1a:$ts1p"
|
||||
CMD0="$SOCAT $opts -d -d -d -u UDP4-RECV:$ts1p,reuseaddr,$SCM_RECV -"
|
||||
CMD1="$SOCAT $opts -u - UDP4-SENDTO:$ts1,$SCM_ENABLE"
|
||||
printf "test $F_n $TEST... " $N
|
||||
# is this option supported?
|
||||
if $SOCAT -hhh |grep "[[:space:]]$SCM_RECV[[:space:]]" >/dev/null; then
|
||||
$CMD0 >"$tf" 2>"${te}0" &
|
||||
pid0="$!"
|
||||
waitudp4port $ts1p 1
|
||||
echo "XYZ" |$CMD1 2>>"${te}1"
|
||||
rc1="$?"
|
||||
sleep 1
|
||||
i=0; while [ ! -s "${te}0" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done
|
||||
kill "$pid0" 2>/dev/null; wait
|
||||
# do not show more messages than requested
|
||||
case "$opts" in
|
||||
*-d*-d*-d*-d*) LEVELS="[EWNID]" ;;
|
||||
*-d*-d*-d*) LEVELS="[EWNI]" ;;
|
||||
*-d*-d*) LEVELS="[EWN]" ;;
|
||||
*-d*) LEVELS="[EW]" ;;
|
||||
*) LEVELS="[E]" ;;
|
||||
esac
|
||||
if [ "$rc1" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
echo "$CMD1"
|
||||
grep " $LEVELS " "${te}0"
|
||||
grep " $LEVELS " "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! grep "ancillary message: $SCM_TYPE: $SCM_NAME=$SCM_VALUE" ${te}0 >/dev/null; then
|
||||
$PRINTF "$FAILED\n"
|
||||
echo "$CMD0 &"
|
||||
echo "$CMD1"
|
||||
grep " $LEVELS " "${te}0"
|
||||
grep " $LEVELS " "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then
|
||||
grep " $LEVELS " "${te}0"; echo; grep " $LEVELS " "${te}1";
|
||||
fi
|
||||
numOK=$((numOK+1))
|
||||
fi
|
||||
else # option is not supported
|
||||
$PRINTF "${YELLOW}$SCM_RECV not available${NORMAL}\n"
|
||||
numCANT=$((numCANT+1))
|
||||
fi # option is not supported
|
||||
set +vx
|
||||
;;
|
||||
esac
|
||||
N=$((N+1))
|
||||
|
||||
done <<<"ip-options=x01000000 ip-recvopts IP_OPTIONS options x01000000
|
||||
, so-timestamp SCM_TIMESTAMP timestamp $(date '+%a %b %e %H:%M:.. %Y')
|
||||
ip-ttl=53 ip-recvttl IP_TTL ttl 53
|
||||
ip-tos=7 ip-recvtos IP_TOS tos 7
|
||||
, ip-pktinfo IP_PKTINFO locaddr 127.0.0.1
|
||||
, ip-recvif IP_RECVIF if lo
|
||||
, ip-recvdstaddr IP_RECVDSTADDR dstaddr 127.0.0.1"
|
||||
|
||||
|
||||
# test: logging of ancillary message
|
||||
while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_TYPE SCM_NAME ROOT SCM_VALUE
|
||||
do
|
||||
|
113
xio-gopen.c
113
xio-gopen.c
@ -45,113 +45,17 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
||||
/* note: when S_ISSOCK was undefined, it always gives 0 */
|
||||
if (exists && S_ISSOCK(st_mode)) {
|
||||
#if WITH_UNIX
|
||||
int socktype = SOCK_STREAM;
|
||||
int optsotype = -1;
|
||||
struct sockaddr_un sa, us;
|
||||
socklen_t salen, uslen = sizeof(us);
|
||||
bool needbind = false;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen;
|
||||
char infobuff[256];
|
||||
struct opt *opts2;
|
||||
|
||||
socket_un_init(&sa);
|
||||
socket_un_init(&us);
|
||||
|
||||
Info1("\"%s\" is a socket, connecting to it", filename);
|
||||
if (retropt_int(opts, OPT_SO_TYPE, &optsotype) == 0) {
|
||||
socktype = optsotype;
|
||||
|
||||
result =
|
||||
_xioopen_unix_client(&fd->stream, xioflags, groups, 0, opts, filename);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0) != STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((fd->stream.unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
fd->stream.opt_unlink_close = true;
|
||||
}
|
||||
|
||||
/* save options, because we might have to start again with Socket() */
|
||||
opts2 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
if ((fd->stream.fd = Socket(PF_UNIX, socktype, 0)) < 0) {
|
||||
Error2("socket(PF_UNIX, %d, 0): %s", socktype, strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
/*0 Info2("socket(PF_UNIX, %d, 0) -> %d", socktype, fd->stream.fd);*/
|
||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
||||
applyopts(fd->stream.fd, opts, PH_FD);
|
||||
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
|
||||
sa.sun_family = AF_UNIX;
|
||||
salen = xiosetunix(&sa, filename, false, false);
|
||||
|
||||
#if 0
|
||||
applyopts(fd->stream.fd, opts, PH_PREBIND);
|
||||
applyopts(fd->stream.fd, opts, PH_BIND);
|
||||
if (us) {
|
||||
if (Bind(fd->stream.fd, us, uslen) < 0) {
|
||||
Error4("bind(%d, {%s}, "F_Zd"): %s",
|
||||
fd->fd, sockaddr_info(us, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
if (fd->forever || --fd->retry) {
|
||||
Nanosleep(&fd->intervall, NULL);
|
||||
continue;
|
||||
} else
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
applyopts(fd->stream.fd, opts, PH_PASTBIND);
|
||||
#endif /* 0 */
|
||||
|
||||
applyopts(fd->stream.fd, opts, PH_CONNECT);
|
||||
if ((result = Connect(fd->stream.fd, (struct sockaddr *)&sa, salen)) < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||
fd->stream.fd, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
||||
sizeof(sa), strerror(errno));
|
||||
} else if (errno == EPROTOTYPE && optsotype != SOCK_STREAM) {
|
||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||
fd->stream.fd, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
||||
sizeof(sa), strerror(errno));
|
||||
Info("assuming datagram socket");
|
||||
Close(fd->stream.fd);
|
||||
|
||||
opts = opts2;
|
||||
if ((fd->stream.fd = Socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
|
||||
Error1("socket(PF_UNIX, SOCK_DGRAM, 0): %s", strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
/*0 Info1("socket(PF_UNIX, SOCK_DGRAM, 0) -> %d", fd->stream.fd);*/
|
||||
|
||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
||||
applyopts(fd->stream.fd, opts, PH_FD);
|
||||
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
|
||||
sa.sun_family = AF_UNIX;
|
||||
strncpy(sa.sun_path, filename, sizeof(sa.sun_path));
|
||||
|
||||
fd->stream.dtype = XIODATA_RECVFROM;
|
||||
fd->stream.salen = sizeof(sa);
|
||||
memcpy(&fd->stream.peersa.soa, &sa, fd->stream.salen);
|
||||
} else {
|
||||
Error4("connect(%d, %s, "F_Zd"): %s",
|
||||
fd->stream.fd, sockaddr_unix_info(&sa, fd->stream.salen, infobuff, sizeof(infobuff)),
|
||||
sizeof(sa), strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
if (fd->stream.howtoend == END_UNSPEC) {
|
||||
fd->stream.howtoend = END_SHUTDOWN;
|
||||
}
|
||||
|
||||
applyopts_fchown(fd->stream.fd, opts);
|
||||
applyopts(fd->stream.fd, opts, PH_CONNECTED);
|
||||
applyopts(fd->stream.fd, opts, PH_LATE);
|
||||
applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
|
||||
|
||||
if (Getsockname(fd->stream.fd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||
@ -159,7 +63,8 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
||||
fd->stream.fd, &us, uslen, strerror(errno));
|
||||
} else {
|
||||
Notice1("successfully connected via %s",
|
||||
sockaddr_unix_info(&us, uslen, infobuff, sizeof(infobuff)));
|
||||
sockaddr_unix_info(&us.un, uslen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
}
|
||||
#else
|
||||
Error("\"%s\" is a socket, but UNIX socket support is not compiled in");
|
||||
|
12
xio-ip.c
12
xio-ip.c
@ -213,6 +213,18 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||
if (node != NULL || service != NULL) {
|
||||
struct addrinfo *record;
|
||||
|
||||
if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM) {
|
||||
/* actual socket type value is not supported - fallback to a good one */
|
||||
socktype = SOCK_DGRAM;
|
||||
}
|
||||
if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) {
|
||||
/* actual protocol value is not supported - fallback to a good one */
|
||||
if (socktype == SOCK_DGRAM) {
|
||||
protocol = IPPROTO_UDP;
|
||||
} else {
|
||||
protocol = IPPROTO_TCP;
|
||||
}
|
||||
}
|
||||
hints.ai_flags |= AI_PASSIVE;
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = socktype;
|
||||
|
27
xio-ipapp.c
27
xio-ipapp.c
@ -53,7 +53,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen, &needbind, &lowport,
|
||||
&socktype) != STAT_OK) {
|
||||
socktype) != STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
@ -142,7 +142,11 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||
}
|
||||
|
||||
|
||||
/* returns STAT_OK on success or some other value on failure */
|
||||
/* returns STAT_OK on success or some other value on failure
|
||||
applies and consumes the following options:
|
||||
PH_EARLY
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT
|
||||
*/
|
||||
int
|
||||
_xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *hostname,
|
||||
@ -153,7 +157,7 @@ int
|
||||
union sockaddr_union *them, socklen_t *themlen,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
bool *needbind, bool *lowport,
|
||||
int *socktype) {
|
||||
int socktype) {
|
||||
uint16_t port;
|
||||
char infobuff[256];
|
||||
int result;
|
||||
@ -162,7 +166,7 @@ int
|
||||
|
||||
if ((result =
|
||||
xiogetaddrinfo(hostname, portname,
|
||||
*pf, *socktype, protocol,
|
||||
*pf, socktype, protocol,
|
||||
(union sockaddr_union *)them, themlen,
|
||||
res_opts0, res_opts1
|
||||
))
|
||||
@ -176,7 +180,7 @@ int
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
/* 3 means: IP address AND port accepted */
|
||||
if (retropt_bind(opts, *pf, *socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
||||
if (retropt_bind(opts, *pf, socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
||||
res_opts0, res_opts1)
|
||||
!= STAT_NOACTION) {
|
||||
*needbind = true;
|
||||
@ -205,7 +209,6 @@ int
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_LOWPORT, lowport);
|
||||
retropt_int(opts, OPT_SO_TYPE, socktype);
|
||||
|
||||
*opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
@ -217,22 +220,24 @@ int
|
||||
|
||||
|
||||
#if WITH_TCP && WITH_LISTEN
|
||||
/*
|
||||
applies and consumes the following options:
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND
|
||||
*/
|
||||
int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *portname, int *pf, int ipproto,
|
||||
unsigned long res_opts0,
|
||||
unsigned long res_opts1,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
int *socktype) {
|
||||
int socktype) {
|
||||
char *bindname = NULL;
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, socktype);
|
||||
|
||||
retropt_socket_pf(opts, pf);
|
||||
|
||||
retropt_string(opts, OPT_BIND, &bindname);
|
||||
if ((result =
|
||||
xiogetaddrinfo(bindname, portname, *pf, *socktype, ipproto,
|
||||
xiogetaddrinfo(bindname, portname, *pf, socktype, ipproto,
|
||||
(union sockaddr_union *)us, uslen,
|
||||
res_opts0, res_opts1))
|
||||
!= STAT_OK) {
|
||||
@ -279,7 +284,7 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
||||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, argv[1], &pf, ipproto,
|
||||
fd->stream.para.socket.ip.res_opts[1],
|
||||
fd->stream.para.socket.ip.res_opts[0],
|
||||
us, &uslen, &socktype)
|
||||
us, &uslen, socktype)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* source: xio-ipapp.h */
|
||||
/* Copyright Gerhard Rieger 2001-2006 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ipapp_h_included
|
||||
@ -25,7 +25,7 @@ extern int
|
||||
union sockaddr_union *them, socklen_t *themlen,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
bool *needbind, bool *lowport,
|
||||
int *socktype);
|
||||
int socktype);
|
||||
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
|
||||
struct single *xfd,
|
||||
int socktype, int ipproto, void *protname,
|
||||
@ -39,7 +39,7 @@ extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
||||
unsigned long res_opts0,
|
||||
unsigned long res_opts1,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
int *socktype);
|
||||
int socktype);
|
||||
extern int xioopen_ip6app_connect(int argc, const char *argv[], struct opt *opts,
|
||||
int rw, xiofile_t *fd,
|
||||
unsigned groups, int socktype, int ipproto,
|
||||
|
25
xio-listen.c
25
xio-listen.c
@ -25,6 +25,13 @@ const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_R
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
|
||||
PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap,
|
||||
OPT_SOURCEPORT, OPT_LOWPORT, cloexec
|
||||
*/
|
||||
int
|
||||
xioopen_listen(struct single *xfd, int xioflags,
|
||||
struct sockaddr *us, socklen_t uslen,
|
||||
@ -81,15 +88,21 @@ int
|
||||
}
|
||||
|
||||
|
||||
/* waits for incoming connection, checks its source address and port. Depending
|
||||
on fork option, it may fork a subprocess.
|
||||
/* creates the listening socket, bind, applies options; waits for incoming
|
||||
connection, checks its source address and port. Depending on fork option, it
|
||||
may fork a subprocess.
|
||||
Returns 0 if a connection was accepted; with fork option, this is always in
|
||||
a subprocess!
|
||||
Other return values indicate a problem; this can happen in the master
|
||||
process or in a subprocess.
|
||||
This function does not retry. If you need retries, handle this is a
|
||||
loop in the calling function.
|
||||
This function does not retry. If you need retries, handle this in a
|
||||
loop in the calling function (and always provide the options...)
|
||||
after fork, we set the forever/retry of the child process to 0
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
|
||||
PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap,
|
||||
OPT_SOURCEPORT, OPT_LOWPORT, cloexec
|
||||
*/
|
||||
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) {
|
||||
@ -124,9 +137,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ static int
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen,
|
||||
&needbind, &lowport, &socktype);
|
||||
&needbind, &lowport, socktype);
|
||||
if (result != STAT_OK) return STAT_NORETRY;
|
||||
|
||||
if (xioopts.logopt == 'm') {
|
||||
@ -431,7 +431,7 @@ static int
|
||||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
us, &uslen, &socktype)
|
||||
us, &uslen, socktype)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "xio-process.h"
|
||||
#include "xio-progcall.h"
|
||||
|
||||
#include "xio-socket.h"
|
||||
|
||||
|
||||
/* these options are used by address pty too */
|
||||
#if HAVE_OPENPTY
|
||||
const struct optdesc opt_openpty = { "openpty", NULL, OPT_OPENPTY, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
|
||||
@ -49,7 +52,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||
) {
|
||||
struct opt *popts; /* parent process options */
|
||||
int numleft;
|
||||
int d, type, protocol, sv[2], rdpip[2], wrpip[2];
|
||||
int d, sv[2], rdpip[2], wrpip[2];
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
bool usepipes = false;
|
||||
#if HAVE_PTY
|
||||
@ -358,13 +361,10 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||
applyopts(fd->fd, popts, PH_LATE);
|
||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||
} else {
|
||||
d = AF_UNIX; type = SOCK_STREAM;
|
||||
protocol = 0; /* PF_UNIX does not work on AIX */
|
||||
retropt_int(popts, OPT_SO_TYPE, &type);
|
||||
result = Socketpair(d, type, protocol, sv);
|
||||
d = AF_UNIX;
|
||||
retropt_int(popts, OPT_PROTOCOL_FAMILY, &d);
|
||||
result = xiosocketpair(popts, d, SOCK_STREAM, 0, sv);
|
||||
if (result < 0) {
|
||||
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||
d, type, protocol, sv, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
|
||||
|
@ -131,7 +131,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen,
|
||||
&needbind, &lowport, &socktype);
|
||||
&needbind, &lowport, socktype);
|
||||
if (result != STAT_OK) return result;
|
||||
|
||||
Notice4("opening connection to %s:%u via proxy %s:%s",
|
||||
|
32
xio-rawip.c
32
xio-rawip.c
@ -17,7 +17,6 @@
|
||||
#include "xio-rawip.h"
|
||||
|
||||
|
||||
|
||||
static
|
||||
int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *fd, unsigned groups, int pf,
|
||||
@ -38,7 +37,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
||||
static
|
||||
int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||
struct opt *opts, int xioflags,
|
||||
xiofile_t *xxfd, unsigned groups, int pf);
|
||||
xiofile_t *xxfd, unsigned groups, int *pf);
|
||||
|
||||
const struct addrdesc addr_rawip_sendto = { "ip-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
||||
const struct addrdesc addr_rawip_datagram= { "ip-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
||||
@ -75,17 +74,24 @@ int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, pf)) != STAT_OK) {
|
||||
groups, &pf)) != STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
_xio_openlate(&xxfd->stream, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
applies and consumes the following options:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER,
|
||||
OPT_GROUP, OPT_CLOEXEC
|
||||
*/
|
||||
static
|
||||
int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||
struct opt *opts, int xioflags, xiofile_t *xxfd,
|
||||
unsigned groups, int pf) {
|
||||
unsigned groups, int *pf) {
|
||||
char *garbage;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
union sockaddr_union us;
|
||||
@ -107,7 +113,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||
}
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_PROTOCOL_FAMILY, pf);
|
||||
|
||||
/* ...res_opts[] */
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
@ -115,29 +121,29 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||
|
||||
xfd->salen = sizeof(xfd->peersa);
|
||||
if ((result =
|
||||
xiogetaddrinfo(hostname, NULL, pf, socktype, ipproto,
|
||||
xiogetaddrinfo(hostname, NULL, *pf, socktype, ipproto,
|
||||
&xfd->peersa, &xfd->salen,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1]))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (pf == PF_UNSPEC) {
|
||||
pf = xfd->peersa.soa.sa_family;
|
||||
if (*pf == PF_UNSPEC) {
|
||||
*pf = xfd->peersa.soa.sa_family;
|
||||
}
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
uslen = socket_init(*pf, &us);
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM_SKIPIP;
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, feats,
|
||||
if (retropt_bind(opts, *pf, socktype, ipproto, &us.soa, &uslen, feats,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1]) != STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, ipproto);
|
||||
opts, xioflags, xfd, groups, *pf, socktype, ipproto);
|
||||
}
|
||||
|
||||
|
||||
@ -157,7 +163,7 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
|
||||
}
|
||||
if ((result =
|
||||
_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, pf)) != STAT_OK) {
|
||||
groups, &pf)) != STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -216,7 +222,6 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||
/*return STAT_NORETRY;*/
|
||||
}
|
||||
xfd->stream.howtoend = END_NONE;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
@ -274,7 +279,6 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
||||
protname);
|
||||
/*return STAT_NORETRY;*/
|
||||
}
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
|
93
xio-socket.c
93
xio-socket.c
@ -50,7 +50,7 @@ const struct optdesc opt_so_sndbuf_late={ "so-sndbuf-late","sndbuf-late",OPT_SO_
|
||||
const struct optdesc opt_so_rcvbuf = { "so-rcvbuf", "rcvbuf", OPT_SO_RCVBUF, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_RCVBUF};
|
||||
const struct optdesc opt_so_rcvbuf_late={"so-rcvbuf-late","rcvbuf-late",OPT_SO_RCVBUF_LATE,GROUP_SOCKET,PH_LATE,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_RCVBUF };
|
||||
const struct optdesc opt_so_error = { "so-error", "error", OPT_SO_ERROR, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ERROR};
|
||||
const struct optdesc opt_so_type = { "so-type", "type", OPT_SO_TYPE, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_TYPE };
|
||||
const struct optdesc opt_so_type = { "so-type", "type", OPT_SO_TYPE, GROUP_SOCKET, PH_SOCKET, TYPE_INT, OFUNC_SPEC, SOL_SOCKET, SO_TYPE };
|
||||
const struct optdesc opt_so_dontroute= { "so-dontroute", "dontroute", OPT_SO_DONTROUTE,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_DONTROUTE };
|
||||
#ifdef SO_RCVLOWAT
|
||||
const struct optdesc opt_so_rcvlowat = { "so-rcvlowat", "rcvlowat", OPT_SO_RCVLOWAT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_RCVLOWAT };
|
||||
@ -129,9 +129,9 @@ const struct optdesc opt_so_dgram_errind={"so-dgram-errind","dgramerrind",OPT_SO
|
||||
#ifdef SO_DONTLINGER /* Solaris */
|
||||
const struct optdesc opt_so_dontlinger = {"so-dontlinger", "dontlinger", OPT_SO_DONTLINGER, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DONTLINGER };
|
||||
#endif
|
||||
#ifdef SO_PROTOTYPE /* Solaris, HP-UX */
|
||||
const struct optdesc opt_so_prototype = {"so-prototype", "prototype", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_PROTOTYPE };
|
||||
#endif
|
||||
/* the SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more
|
||||
general purpose */
|
||||
const struct optdesc opt_so_prototype = {"so-prototype", "prototype", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_SOCKET, TYPE_INT,OFUNC_SPEC, SOL_SOCKET,SO_PROTOTYPE };
|
||||
#ifdef FIOSETOWN
|
||||
const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN };
|
||||
#endif
|
||||
@ -141,15 +141,21 @@ const struct optdesc opt_siocspgrp = { "siocspgrp", NULL, OPT_SIOCSPGRP, GRO
|
||||
const struct optdesc opt_bind = { "bind", NULL, OPT_BIND, GROUP_SOCKET, PH_BIND, TYPE_STRING,OFUNC_SPEC };
|
||||
const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNECT_TIMEOUT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.socket.connect_timeout };
|
||||
const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||
const struct optdesc opt_protocol = { "protocol", NULL, OPT_PROTOCOL, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||
|
||||
/* a subroutine that is common to all socket addresses that want to connect
|
||||
to a peer address.
|
||||
might fork.
|
||||
applies and consumes the following options:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT,
|
||||
PH_CONNECTED, PH_LATE,
|
||||
OFUNC_OFFSET,
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
returns 0 on success.
|
||||
*/
|
||||
int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts, int pf, int socktype, int protocol,
|
||||
bool alt, int level) {
|
||||
int fcntl_flags = 0;
|
||||
char infobuff[256];
|
||||
@ -158,9 +164,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
int _errno;
|
||||
int result;
|
||||
|
||||
if ((xfd->fd = Socket(pf, stype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, stype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
@ -354,7 +358,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
}
|
||||
}
|
||||
|
||||
applyopts_fchown(xfd->fd, opts);
|
||||
applyopts_fchown(xfd->fd, opts); /* OPT_USER, OPT_GROUP */
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
applyopts(xfd->fd, opts, PH_LATE);
|
||||
|
||||
@ -368,11 +372,16 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
/* a subroutine that is common to all socket addresses that want to connect
|
||||
to a peer address.
|
||||
might fork.
|
||||
applies and consumes the following option:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT,
|
||||
PH_CONNECTED, PH_LATE,
|
||||
OFUNC_OFFSET,
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
returns 0 on success.
|
||||
*/
|
||||
int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts, int pf, int socktype, int protocol,
|
||||
bool alt) {
|
||||
bool dofork = false;
|
||||
struct opt *opts0;
|
||||
@ -381,7 +390,6 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
int result;
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
retropt_int(opts, OPT_SO_TYPE, &stype);
|
||||
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
@ -398,7 +406,7 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
level = E_ERROR;
|
||||
result =
|
||||
_xioopen_connect(xfd, us, uslen, them, themlen, opts,
|
||||
pf, stype, proto, alt, level);
|
||||
pf, socktype, protocol, alt, level);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
@ -464,7 +472,12 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
}
|
||||
|
||||
|
||||
/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */
|
||||
/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip
|
||||
applies and consumes the following option:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
*/
|
||||
int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||
union sockaddr_union *us, socklen_t uslen,
|
||||
struct opt *opts,
|
||||
@ -474,9 +487,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||
union sockaddr_union la; socklen_t lalen = sizeof(la);
|
||||
char infobuff[256];
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, ipproto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
@ -600,6 +611,10 @@ void xiosigaction_hasread(int signum, siginfo_t *siginfo, void *ucontext) {
|
||||
This function does not retry. If you need retries, handle this is a
|
||||
loop in the calling function.
|
||||
after fork, we set the forever/retry of the child process to 0
|
||||
applies and consumes the following options:
|
||||
PH_INIT, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY, PH_PREOPEN, PH_FD,
|
||||
PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, cloexec, OPT_RANGE, tcpwrap
|
||||
*/
|
||||
int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
struct sockaddr *us, socklen_t uslen,
|
||||
@ -626,9 +641,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
@ -881,9 +894,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
@ -1371,3 +1382,41 @@ int xiosetsockaddrenv(const char *lr,
|
||||
}
|
||||
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
/* these do sockets internally */
|
||||
|
||||
/* retrieves options so-type and so-prototype from opts, calls socketpair, and
|
||||
ev. generates an appropriate error message.
|
||||
returns 0 on success or -1 if an error occurred. */
|
||||
int
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
|
||||
result = Socket(pf, socktype, proto);
|
||||
if (result < 0) {
|
||||
Msg4(msglevel, "socket(%d, %d, %d): %s",
|
||||
pf, socktype, proto, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* retrieves options so-type and so-prototype from opts, calls socketpair, and
|
||||
ev. generates an appropriate error message.
|
||||
returns 0 on success or -1 if an error occurred. */
|
||||
int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) {
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
|
||||
result = Socketpair(pf, socktype, proto, sv);
|
||||
if (result < 0) {
|
||||
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||
pf, socktype, proto, sv, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
16
xio-socket.h
16
xio-socket.h
@ -5,6 +5,12 @@
|
||||
#ifndef __xio_socket_h_included
|
||||
#define __xio_socket_h_included 1
|
||||
|
||||
/* SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more
|
||||
general purpose */
|
||||
#ifndef SO_PROTOTYPE
|
||||
#define SO_PROTOTYPE 0x9999
|
||||
#endif
|
||||
|
||||
extern const struct optdesc opt_connect_timeout;
|
||||
extern const struct optdesc opt_so_debug;
|
||||
extern const struct optdesc opt_so_acceptconn;
|
||||
@ -61,12 +67,14 @@ extern int retropt_socket_pf(struct opt *opts, int *pf);
|
||||
extern int xioopen_connect(struct single *fd,
|
||||
struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts,
|
||||
int pf, int socktype, int protocol,
|
||||
bool alt);
|
||||
extern int _xioopen_connect(struct single *fd,
|
||||
struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts,
|
||||
int pf, int socktype, int protocol,
|
||||
bool alt, int level);
|
||||
|
||||
/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */
|
||||
@ -93,6 +101,10 @@ int xiogetpacketsrc(int fd, struct msghdr *msgh);
|
||||
extern
|
||||
int xiocheckpeer(xiosingle_t *xfd,
|
||||
union sockaddr_union *pa, union sockaddr_union *la);
|
||||
extern int
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int level);
|
||||
extern int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]);
|
||||
extern
|
||||
int xiosetsockaddrenv(const char *lr, union sockaddr_union *sau, socklen_t salen, int proto);
|
||||
|
||||
|
@ -88,7 +88,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen,
|
||||
&needbind, &lowport, &socktype);
|
||||
&needbind, &lowport, socktype);
|
||||
|
||||
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
|
||||
targetname,
|
||||
|
16
xio-udp.c
16
xio-udp.c
@ -114,7 +114,6 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_bind(opts, pf, socktype, IPPROTO_UDP,
|
||||
(struct sockaddr *)&us, &uslen, 1,
|
||||
fd->stream.para.socket.ip.res_opts[1],
|
||||
@ -176,8 +175,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||
union sockaddr_union _sockname;
|
||||
union sockaddr_union *la = &_sockname; /* local address */
|
||||
|
||||
if ((fd->stream.fd = Socket(pf, socktype, ipproto)) < 0) {
|
||||
Error4("socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
||||
if ((fd->stream.fd = xiosocket(opts, pf, socktype, ipproto, E_ERROR)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
||||
@ -230,7 +228,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||
if (xiocheckpeer(&fd->stream, them, la) < 0) {
|
||||
/* drop packet */
|
||||
char buff[512];
|
||||
Recv(fd->stream.fd, buff, sizeof(buff), 0);
|
||||
Recv(fd->stream.fd, buff, sizeof(buff), 0); /* drop packet */
|
||||
Close(fd->stream.fd);
|
||||
continue;
|
||||
}
|
||||
@ -299,6 +297,8 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, pf, socktype, ipproto))
|
||||
!= STAT_OK) {
|
||||
@ -308,6 +308,12 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
*/
|
||||
static
|
||||
int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
||||
struct opt *opts,
|
||||
@ -321,7 +327,6 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
||||
int result;
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
/* ...res_opts[] */
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
@ -408,6 +413,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
result =
|
||||
_xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd, groups,
|
||||
pf, socktype, ipproto);
|
||||
|
609
xio-unix.c
609
xio-unix.c
@ -15,76 +15,69 @@
|
||||
|
||||
#if WITH_UNIX
|
||||
|
||||
static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
/* to avoid unneccessary "live" if () conditionals when no abstract support is
|
||||
compiled in (or at least to give optimizing compilers a good chance) we need
|
||||
a constant that can be used in C expressions */
|
||||
#if WITH_ABSTRACT_UNIXSOCKET
|
||||
# define ABSTRACT 1
|
||||
#else
|
||||
# define ABSTRACT 0
|
||||
#endif
|
||||
|
||||
static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
|
||||
static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
|
||||
static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
|
||||
static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
|
||||
static
|
||||
int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int ipproto);
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int abstract, int dummy2, int dummy3);
|
||||
static
|
||||
int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
|
||||
|
||||
/* the first free parameter is 0 for "normal" unix domain sockets, or 1 for
|
||||
abstract unix sockets (Linux); the second and third free parameter are
|
||||
unsused */
|
||||
const struct addrdesc xioaddr_unix_connect = { "unix-connect", 3, xioopen_unix_connect, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_unix_listen = { "unix-listen", 3, xioopen_unix_listen, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
|
||||
#endif /* WITH_LISTEN */
|
||||
const struct addrdesc xioaddr_unix_sendto = { "unix-sendto", 3, xioopen_unix_sendto, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_unix_recvfrom= { "unix-recvfrom", 3, xioopen_unix_recvfrom, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, 0, 0, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_unix_recv = { "unix-recv", 1, xioopen_unix_recv, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_unix_client = { "unix-client", 3, xioopen_unix_client, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
|
||||
#if WITH_ABSTRACT_UNIXSOCKET
|
||||
static int xioopen_abstract_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
static int xioopen_abstract_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
static int xioopen_abstract_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
static int xioopen_abstract_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
static
|
||||
int xioopen_abstract_recv(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int ipproto);
|
||||
static
|
||||
int xioopen_abstract_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||
const struct addrdesc xioaddr_abstract_connect = { "abstract-connect", 3, xioopen_unix_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_abstract_listen = { "abstract-listen", 3, xioopen_unix_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
|
||||
#endif /* WITH_LISTEN */
|
||||
const struct addrdesc xioaddr_abstract_sendto = { "abstract-sendto", 3, xioopen_unix_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_abstract_recvfrom= { "abstract-recvfrom", 3, xioopen_unix_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, 1, 0, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_abstract_recv = { "abstract-recv", 1, xioopen_unix_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_abstract_client = { "abstract-client", 3, xioopen_unix_client, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
|
||||
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
||||
|
||||
const struct addrdesc addr_unix_connect = { "unix-connect", 3, xioopen_unix_connect, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc addr_unix_listen = { "unix-listen", 3, xioopen_unix_listen, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||
#endif /* WITH_LISTEN */
|
||||
const struct addrdesc addr_unix_sendto = { "unix-sendto", 3, xioopen_unix_sendto, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||
const struct addrdesc addr_unix_recvfrom= { "unix-recvfrom", 3, xioopen_unix_recvfrom, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||
const struct addrdesc addr_unix_recv = { "unix-recv", 1, xioopen_unix_recv, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||
const struct addrdesc addr_unix_client = { "unix-client", 3, xioopen_unix_client, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, 0, 0 HELP(":<filename>") };
|
||||
#if WITH_ABSTRACT_UNIXSOCKET
|
||||
const struct addrdesc xioaddr_abstract_connect = { "abstract-connect", 3, xioopen_abstract_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_abstract_listen = { "abstract-listen", 3, xioopen_abstract_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||
#endif /* WITH_LISTEN */
|
||||
const struct addrdesc xioaddr_abstract_sendto = { "abstract-sendto", 3, xioopen_abstract_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_abstract_recvfrom= { "abstract-recvfrom", 3, xioopen_abstract_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_abstract_recv = { "abstract-recv", 1, xioopen_abstract_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||
const struct addrdesc xioaddr_abstract_client = { "abstract-client", 3, xioopen_abstract_client, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, 0, 0 HELP(":<filename>") };
|
||||
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
||||
|
||||
const struct optdesc opt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_INIT, TYPE_BOOL, OFUNC_SPEC, 0, 0 };
|
||||
const struct optdesc xioopt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_INIT, TYPE_BOOL, OFUNC_SPEC, 0, 0 };
|
||||
|
||||
|
||||
/* fills the socket address struct and returns its effective length.
|
||||
abstract is usually 0; != 0 generates an abstract socket address on Linux.
|
||||
tight!=0 calculates the resulting length from the path length, not from the
|
||||
structures length; this is more common.
|
||||
the struct need not be initialized when calling this function.
|
||||
*/
|
||||
socklen_t
|
||||
xiosetunix(struct sockaddr_un *saun,
|
||||
xiosetunix(int pf,
|
||||
struct sockaddr_un *saun,
|
||||
const char *path,
|
||||
bool abstract,
|
||||
bool tight) {
|
||||
size_t pathlen;
|
||||
socklen_t len;
|
||||
|
||||
if (!abstract) {
|
||||
if ((pathlen = strlen(path)) > sizeof(saun->sun_path)) {
|
||||
Warn2("unix socket address "F_Zu" characters long, truncating to "F_Zu"",
|
||||
pathlen, sizeof(saun->sun_path));
|
||||
}
|
||||
strncpy(saun->sun_path, path, sizeof(saun->sun_path));
|
||||
if (tight) {
|
||||
len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
|
||||
MIN(pathlen, sizeof(saun->sun_path));
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
saun->sun_len = len;
|
||||
#endif
|
||||
} else {
|
||||
len = sizeof(struct sockaddr_un);
|
||||
}
|
||||
} else {
|
||||
socket_un_init(saun);
|
||||
#ifdef WITH_ABSTRACT_UNIXSOCKET
|
||||
if (abstract) {
|
||||
if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) {
|
||||
Warn2("socket address "F_Zu" characters long, truncating to "F_Zu"",
|
||||
pathlen+1, sizeof(saun->sun_path));
|
||||
@ -100,15 +93,32 @@ xiosetunix(struct sockaddr_un *saun,
|
||||
} else {
|
||||
len = sizeof(struct sockaddr_un);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
||||
|
||||
if ((pathlen = strlen(path)) > sizeof(saun->sun_path)) {
|
||||
Warn2("unix socket address "F_Zu" characters long, truncating to "F_Zu"",
|
||||
pathlen, sizeof(saun->sun_path));
|
||||
}
|
||||
strncpy(saun->sun_path, path, sizeof(saun->sun_path));
|
||||
if (tight) {
|
||||
len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
|
||||
MIN(pathlen, sizeof(saun->sun_path));
|
||||
} else {
|
||||
len = sizeof(struct sockaddr_un);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#if WITH_LISTEN
|
||||
static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_STREAM;
|
||||
int protocol = 0;
|
||||
struct sockaddr_un us;
|
||||
socklen_t uslen;
|
||||
bool tight = true;
|
||||
@ -123,28 +133,29 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us, name, false, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
uslen = xiosetunix(pf, &us, name, abstract, tight);
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
|
||||
if (opt_unlink_close) {
|
||||
if ((xfd->unlink_close = strdup(name)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
}
|
||||
xfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
}
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
if (opt_unlink_early) {
|
||||
if (Unlink(name) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
@ -158,15 +169,14 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
||||
/* trying to set user-early, perm-early etc. here is useless because
|
||||
file system entry is available only past bind() call. */
|
||||
applyopts_named(name, opts, PH_EARLY); /* umask! */
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
}
|
||||
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
if ((result =
|
||||
xioopen_listen(xfd, xioflags,
|
||||
(struct sockaddr *)&us, uslen,
|
||||
opts, opts0, PF_UNIX, socktype, 0))
|
||||
opts, opts0, pf, socktype, protocol))
|
||||
!= 0)
|
||||
return result;
|
||||
return 0;
|
||||
@ -174,10 +184,13 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
||||
#endif /* WITH_LISTEN */
|
||||
|
||||
|
||||
static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
struct single *xfd = &xxfd->stream;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_STREAM;
|
||||
int protocol = 0;
|
||||
struct sockaddr_un them, us;
|
||||
socklen_t themlen, uslen;
|
||||
bool tight = true;
|
||||
@ -191,15 +204,15 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
socket_un_init(&them);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
themlen = xiosetunix(&them, name, false, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
themlen = xiosetunix(pf, &them, name, abstract, tight);
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
|
||||
if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0)
|
||||
}
|
||||
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
@ -219,7 +232,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, PF_UNIX, socktype, 0, false)) != 0) {
|
||||
opts, pf, socktype, protocol, false)) != 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||
@ -229,13 +242,16 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
||||
}
|
||||
|
||||
|
||||
static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_DGRAM;
|
||||
int protocol = 0;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen;
|
||||
bool tight = true;
|
||||
int pf = PF_UNIX;
|
||||
bool needbind = false;
|
||||
bool opt_unlink_close = false;
|
||||
|
||||
@ -245,22 +261,21 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
xfd->salen = socket_init(pf, &xfd->peersa);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
retropt_socket_pf(opts, &pf);
|
||||
xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, tight);
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
xfd->salen = xiosetunix(&xfd->peersa.un, name, false, tight);
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0)
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
@ -277,15 +292,21 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
||||
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, 0);
|
||||
opts, xioflags, xfd, groups,
|
||||
pf, socktype, protocol);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int dummy3) {
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int abstract, int dummy2, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_DGRAM;
|
||||
int protocol = 0;
|
||||
struct sockaddr_un us;
|
||||
socklen_t uslen;
|
||||
bool tight = true;
|
||||
@ -299,23 +320,24 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us, name, false, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
uslen = xiosetunix(pf, &us, name, abstract, tight);
|
||||
|
||||
xfd->stream.howtoend = END_NONE;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
|
||||
xfd->howtoend = END_NONE;
|
||||
retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
|
||||
1, 0, 0);
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
|
||||
if (opt_unlink_close) {
|
||||
if ((xfd->stream.unlink_close = strdup(name)) == NULL) {
|
||||
if ((xfd->unlink_close = strdup(name)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
}
|
||||
xfd->stream.opt_unlink_close = true;
|
||||
xfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
if (opt_unlink_early) {
|
||||
@ -327,21 +349,28 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xfd->stream.para.socket.la.soa.sa_family = pf;
|
||||
xfd->para.socket.la.soa.sa_family = pf;
|
||||
|
||||
xfd->stream.dtype = XIODATA_RECVFROM_ONE;
|
||||
return _xioopen_dgram_recvfrom(&xfd->stream, xioflags,
|
||||
xfd->dtype = XIODATA_RECVFROM_ONE;
|
||||
return
|
||||
_xioopen_dgram_recvfrom(xfd, xioflags,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
opts, pf, socktype, 0, E_ERROR);
|
||||
opts, pf, socktype, protocol, E_ERROR);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int ipproto) {
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int abstract, int dummy2, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_DGRAM;
|
||||
int protocol = 0;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen;
|
||||
bool tight = true;
|
||||
@ -355,18 +384,17 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
socket_un_init(&us.un);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us.un, name, false, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
uslen = xiosetunix(pf, &us.un, name, abstract, tight);
|
||||
|
||||
#if 1 /*!!! why bind option? */
|
||||
retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1, 0, 0);
|
||||
retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 1, 0, 0);
|
||||
#endif
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
if (opt_unlink_early) {
|
||||
if (Unlink(name) < 0) {
|
||||
@ -381,50 +409,72 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
|
||||
if (opt_unlink_close) {
|
||||
if ((xfd->stream.unlink_close = strdup(name)) == NULL) {
|
||||
if ((xfd->unlink_close = strdup(name)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
}
|
||||
xfd->stream.opt_unlink_close = true;
|
||||
xfd->opt_unlink_close = true;
|
||||
}
|
||||
}
|
||||
|
||||
xfd->stream.para.socket.la.soa.sa_family = pf;
|
||||
xfd->para.socket.la.soa.sa_family = pf;
|
||||
|
||||
xfd->stream.dtype = XIODATA_RECV;
|
||||
result = _xioopen_dgram_recv(&xfd->stream, xioflags, &us.soa, uslen,
|
||||
opts, pf, socktype, ipproto, E_ERROR);
|
||||
xfd->dtype = XIODATA_RECV;
|
||||
result = _xioopen_dgram_recv(xfd, xioflags, &us.soa, uslen,
|
||||
opts, pf, socktype, protocol, E_ERROR);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
bool tight = true;
|
||||
int pf = PF_UNIX;
|
||||
union sockaddr_union them, us;
|
||||
socklen_t themlen;
|
||||
socklen_t uslen;
|
||||
bool needbind = false;
|
||||
bool opt_unlink_close = false;
|
||||
int result;
|
||||
|
||||
static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
return
|
||||
_xioopen_unix_client(&xxfd->stream, xioflags, groups, abstract, opts,
|
||||
argv[1]);
|
||||
}
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
themlen = socket_init(pf, &them);
|
||||
/* establishes communication with an existing UNIX type socket. supports stream
|
||||
and datagram socket types: first tries to connect(), but when this fails it
|
||||
falls back to sendto().
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND,
|
||||
PH_CONNECTED, PH_LATE, ?PH_CONNECT
|
||||
OFUNC_OFFSET,
|
||||
OPT_PROTOCOL_FAMILY, OPT_UNIX_TIGHTSOCKLEN, OPT_UNLINK_CLOSE, OPT_BIND,
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK,
|
||||
*/
|
||||
int
|
||||
_xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
||||
int abstract, struct opt *opts, const char *name) {
|
||||
int pf = PF_UNIX;
|
||||
int socktype = 0; /* to be determined by server socket type */
|
||||
int protocol = 0;
|
||||
union sockaddr_union them, us;
|
||||
socklen_t themlen, uslen;
|
||||
bool tight = true;
|
||||
bool needbind = false;
|
||||
bool opt_unlink_close = false;
|
||||
struct opt *opts0;
|
||||
int result;
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_socket_pf(opts, &pf);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
themlen = xiosetunix(&them.un, name, false, tight);
|
||||
themlen = xiosetunix(pf, &them.un, name, abstract, tight);
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0)
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
@ -436,26 +486,29 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
||||
xfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
/* save options, because we might have to start again */
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
/* xfd->dtype = DATA_STREAM; // is default */
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, PF_UNIX, socktype?socktype:SOCK_STREAM, 0, false)) != 0) {
|
||||
opts, pf, socktype?socktype:SOCK_STREAM, protocol,
|
||||
false)) != 0) {
|
||||
if (errno == EPROTOTYPE) {
|
||||
if (needbind) {
|
||||
Unlink(us.un.sun_path);
|
||||
}
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
dropopts2(opts, PH_INIT, PH_SPEC); opts = opts0;
|
||||
|
||||
xfd->peersa = them;
|
||||
xfd->salen = sizeof(struct sockaddr_un);
|
||||
if ((result =
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf,
|
||||
socktype?socktype:SOCK_DGRAM, 0))
|
||||
opts, xioflags, xfd, groups,
|
||||
pf, socktype?socktype:SOCK_DGRAM, protocol))
|
||||
!= 0) {
|
||||
return result;
|
||||
}
|
||||
@ -469,278 +522,6 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
||||
}
|
||||
|
||||
|
||||
#if WITH_ABSTRACT_UNIXSOCKET
|
||||
#if WITH_LISTEN
|
||||
static int xioopen_abstract_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
bool tight = true;
|
||||
struct sockaddr_un us;
|
||||
socklen_t uslen;
|
||||
struct opt *opts0 = NULL;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us, name, true, tight);
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
/* trying to set user-early, perm-early etc. here is useless because
|
||||
file system entry is available only past bind() call. */
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
if ((result =
|
||||
xioopen_listen(xfd, xioflags,
|
||||
(struct sockaddr *)&us, uslen,
|
||||
opts, opts0, PF_UNIX, socktype, 0))
|
||||
!= 0)
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_LISTEN */
|
||||
|
||||
static int xioopen_abstract_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
struct single *xfd = &xxfd->stream;
|
||||
bool tight = true;
|
||||
struct sockaddr_un them, us;
|
||||
socklen_t themlen, uslen;
|
||||
bool needbind = false;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
socket_un_init(&them);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
themlen = xiosetunix(&them, name, true, tight);
|
||||
|
||||
if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, PF_UNIX, socktype, 0, false)) != 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int xioopen_abstract_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen;
|
||||
bool tight = true;
|
||||
int pf = PF_UNIX;
|
||||
bool needbind = false;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
xfd->salen = socket_init(pf, &xfd->peersa);
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
xfd->salen = xiosetunix(&xfd->peersa.un, name, true, tight);
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, 0);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int xioopen_abstract_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int dummy3) {
|
||||
const char *name;
|
||||
struct sockaddr_un us;
|
||||
socklen_t uslen;
|
||||
bool tight = true;
|
||||
bool needbind = true;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us, name, true, tight);
|
||||
|
||||
xfd->stream.howtoend = END_NONE;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
|
||||
|
||||
xfd->stream.para.socket.la.soa.sa_family = pf;
|
||||
|
||||
xfd->stream.dtype = XIODATA_RECVFROM_ONE;
|
||||
return _xioopen_dgram_recvfrom(&xfd->stream, xioflags,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
opts, pf, socktype, 0, E_ERROR);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int xioopen_abstract_recv(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int ipproto) {
|
||||
const char *name;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen;
|
||||
bool tight = true;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
socket_un_init(&us.un);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us.un, name, true, tight);
|
||||
|
||||
#if 1 /*!!! why bind option? */
|
||||
retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1, 0, 0);
|
||||
#endif
|
||||
|
||||
xfd->stream.para.socket.la.soa.sa_family = pf;
|
||||
|
||||
xfd->stream.dtype = XIODATA_RECV;
|
||||
result = _xioopen_dgram_recv(&xfd->stream, xioflags, &us.soa, uslen,
|
||||
opts, pf, socktype, ipproto, E_ERROR);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int xioopen_abstract_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) {
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
bool tight = true;
|
||||
int pf = PF_UNIX;
|
||||
union sockaddr_union them, us;
|
||||
socklen_t themlen;
|
||||
socklen_t uslen;
|
||||
bool needbind = false;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
themlen = socket_init(pf, &them);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
themlen = xiosetunix(&them.un, name, true, tight);
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
/* xfd->dtype = DATA_STREAM; // is default */
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, PF_UNIX, socktype?socktype:SOCK_STREAM, 0, false)) != 0) {
|
||||
if (errno == EPROTOTYPE) {
|
||||
if (needbind) {
|
||||
Unlink(us.un.sun_path);
|
||||
}
|
||||
|
||||
/* ...res_opts[] */
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
||||
xfd->peersa = them;
|
||||
xfd->salen = themlen;
|
||||
if ((result =
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf,
|
||||
socktype?socktype:SOCK_DGRAM, 0))
|
||||
!= 0) {
|
||||
return result;
|
||||
}
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
}
|
||||
}
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
||||
|
||||
/* returns information that can be used for constructing an environment
|
||||
variable describing the socket address.
|
||||
if idx is 0, this function writes "ADDR" into namebuff and the path into
|
||||
|
21
xio-unix.h
21
xio-unix.h
@ -5,12 +5,12 @@
|
||||
#ifndef __xio_unix_h_included
|
||||
#define __xio_unix_h_included 1
|
||||
|
||||
extern const struct addrdesc addr_unix_connect;
|
||||
extern const struct addrdesc addr_unix_listen;
|
||||
extern const struct addrdesc addr_unix_sendto;
|
||||
extern const struct addrdesc addr_unix_recvfrom;
|
||||
extern const struct addrdesc addr_unix_recv;
|
||||
extern const struct addrdesc addr_unix_client;
|
||||
extern const struct addrdesc xioaddr_unix_connect;
|
||||
extern const struct addrdesc xioaddr_unix_listen;
|
||||
extern const struct addrdesc xioaddr_unix_sendto;
|
||||
extern const struct addrdesc xioaddr_unix_recvfrom;
|
||||
extern const struct addrdesc xioaddr_unix_recv;
|
||||
extern const struct addrdesc xioaddr_unix_client;
|
||||
extern const struct addrdesc xioaddr_abstract_connect;
|
||||
extern const struct addrdesc xioaddr_abstract_listen;
|
||||
extern const struct addrdesc xioaddr_abstract_sendto;
|
||||
@ -18,10 +18,11 @@ extern const struct addrdesc xioaddr_abstract_recvfrom;
|
||||
extern const struct addrdesc xioaddr_abstract_recv;
|
||||
extern const struct addrdesc xioaddr_abstract_client;
|
||||
|
||||
extern const struct optdesc opt_unix_tightsocklen;
|
||||
extern const struct optdesc xioopt_unix_tightsocklen;
|
||||
|
||||
extern socklen_t
|
||||
xiosetunix(struct sockaddr_un *saun,
|
||||
xiosetunix(int pf,
|
||||
struct sockaddr_un *saun,
|
||||
const char *path,
|
||||
bool abstract,
|
||||
bool tight);
|
||||
@ -30,4 +31,8 @@ xiosetsockaddrenv_unix(int idx, char *namebuff, size_t namelen,
|
||||
char *valuebuff, size_t valuelen,
|
||||
struct sockaddr_un *sa, socklen_t salen, int ipproto);
|
||||
|
||||
extern int
|
||||
_xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
||||
int abstract, struct opt *opts, const char *name);
|
||||
|
||||
#endif /* !defined(__xio_unix_h_included) */
|
||||
|
20
xioopen.c
20
xioopen.c
@ -106,7 +106,7 @@ const struct addrname addressnames[] = {
|
||||
#endif
|
||||
#endif /* WITH_RAWIP */
|
||||
#if WITH_UNIX
|
||||
{ "local", &addr_unix_connect },
|
||||
{ "local", &xioaddr_unix_connect },
|
||||
#endif
|
||||
#if WITH_FILE
|
||||
{ "open", &addr_open },
|
||||
@ -231,19 +231,19 @@ const struct addrname addressnames[] = {
|
||||
{ "udp6-sendto", &addr_udp6_sendto },
|
||||
#endif
|
||||
#if WITH_UNIX
|
||||
{ "unix", &addr_unix_client },
|
||||
{ "unix-client", &addr_unix_client },
|
||||
{ "unix-connect", &addr_unix_connect },
|
||||
{ "unix", &xioaddr_unix_client },
|
||||
{ "unix-client", &xioaddr_unix_client },
|
||||
{ "unix-connect", &xioaddr_unix_connect },
|
||||
#endif
|
||||
#if WITH_UNIX && WITH_LISTEN
|
||||
{ "unix-l", &addr_unix_listen },
|
||||
{ "unix-listen", &addr_unix_listen },
|
||||
{ "unix-l", &xioaddr_unix_listen },
|
||||
{ "unix-listen", &xioaddr_unix_listen },
|
||||
#endif
|
||||
#if WITH_UNIX
|
||||
{ "unix-recv", &addr_unix_recv },
|
||||
{ "unix-recvfrom", &addr_unix_recvfrom },
|
||||
{ "unix-send", &addr_unix_sendto },
|
||||
{ "unix-sendto", &addr_unix_sendto },
|
||||
{ "unix-recv", &xioaddr_unix_recv },
|
||||
{ "unix-recvfrom", &xioaddr_unix_recvfrom },
|
||||
{ "unix-send", &xioaddr_unix_sendto },
|
||||
{ "unix-sendto", &xioaddr_unix_sendto },
|
||||
#endif
|
||||
#else /* !0 */
|
||||
# if WITH_INTEGRATE
|
||||
|
16
xioopts.c
16
xioopts.c
@ -1502,7 +1502,7 @@ const struct optname optionnames[] = {
|
||||
#ifdef O_TEXT
|
||||
IF_ANY ("text", &opt_o_text)
|
||||
#endif
|
||||
IF_UNIX ("tightsocklen", &opt_unix_tightsocklen)
|
||||
IF_UNIX ("tightsocklen", &xioopt_unix_tightsocklen)
|
||||
IF_TERMIOS("time", &opt_vtime)
|
||||
#ifdef SO_TIMESTAMP
|
||||
IF_SOCKET ("timestamp", &opt_so_timestamp)
|
||||
@ -1533,7 +1533,7 @@ const struct optname optionnames[] = {
|
||||
IF_ANY ("uid-l", &opt_user_late)
|
||||
IF_NAMED ("umask", &opt_umask)
|
||||
IF_IP6 ("unicast-hops", &opt_ipv6_unicast_hops)
|
||||
IF_UNIX ("unix-tightsocklen", &opt_unix_tightsocklen)
|
||||
IF_UNIX ("unix-tightsocklen", &xioopt_unix_tightsocklen)
|
||||
IF_NAMED ("unlink", &opt_unlink)
|
||||
IF_NAMED ("unlink-close", &opt_unlink_close)
|
||||
IF_NAMED ("unlink-early", &opt_unlink_early)
|
||||
@ -2398,7 +2398,15 @@ int retropt_int(struct opt *opts, int optcode, int *result) {
|
||||
|
||||
while (opt->desc != ODESC_END) {
|
||||
if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
|
||||
*result = opt->value.u_int;
|
||||
switch (opt->desc->type) {
|
||||
case TYPE_INT: *result = opt->value.u_int; break;
|
||||
case TYPE_STRING: *result = strtol(opt->value.u_string, NULL, 0);
|
||||
break;
|
||||
default: Error2("cannot convert type %d of option %s to int",
|
||||
opt->desc->type, opt->desc->defname);
|
||||
opt->desc = ODESC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
opt->desc = ODESC_DONE;
|
||||
return 0;
|
||||
}
|
||||
@ -2580,7 +2588,7 @@ int retropt_bind(struct opt *opts,
|
||||
{
|
||||
bool tight = false;
|
||||
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
|
||||
*salen = xiosetunix(s_un, bindname, false, tight);
|
||||
*salen = xiosetunix(af, s_un, bindname, false, tight);
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_UNIX */
|
||||
|
@ -521,7 +521,8 @@ enum e_optcode {
|
||||
OPT_PIPES,
|
||||
/*OPT_PORT,*/
|
||||
OPT_PROMPT, /* readline */
|
||||
OPT_PROTOCOL_FAMILY,
|
||||
OPT_PROTOCOL, /* 6=TCP, 17=UDP */
|
||||
OPT_PROTOCOL_FAMILY, /* 1=PF_UNIX, 2=PF_INET, 10=PF_INET6 */
|
||||
OPT_PROXYPORT,
|
||||
OPT_PROXY_AUTHORIZATION,
|
||||
OPT_PROXY_RESOLVE,
|
||||
@ -615,9 +616,7 @@ enum e_optcode {
|
||||
#ifdef SO_PRIORITY
|
||||
OPT_SO_PRIORITY,
|
||||
#endif
|
||||
#ifdef SO_PROTOTYPE
|
||||
OPT_SO_PROTOTYPE,
|
||||
#endif
|
||||
OPT_SO_RCVBUF,
|
||||
OPT_SO_RCVBUF_LATE,
|
||||
#ifdef SO_RCVLOWAT
|
||||
@ -794,7 +793,8 @@ enum e_optcode {
|
||||
|
||||
/* keep consistent with xiohelp.c:optionphasenames ! */
|
||||
enum e_phase {
|
||||
PH_ALL, /* not for options; use in apply funcs to say "all phases" */
|
||||
PH_ALL, /* not for option definitions; use in apply funcs to
|
||||
say "all phases" */
|
||||
PH_INIT, /* retrieving info from original state */
|
||||
PH_EARLY, /* before any other processing */
|
||||
PH_PREOPEN, /* before file descriptor is created/opened */
|
||||
|
Loading…
Reference in New Issue
Block a user