merged feature protocol-type

This commit is contained in:
Gerhard Rieger 2008-09-22 22:33:04 +02:00
commit 86c596bd51
23 changed files with 490 additions and 752 deletions

View file

@ -31,6 +31,10 @@ new features:
new address options ipv6-tclass and ipv6-unicast-hops set the related new address options ipv6-tclass and ipv6-unicast-hops set the related
socket options. 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: corrections:
some raw IP and UNIX datagram modes failed on BSD systems 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 Makefile now supports datarootdir (thanks to Camillo Lugaresi for
providing the patch) providing the patch)
cleanup in xio-unix.c
####################### V 1.6.0.1: ####################### V 1.6.0.1:
new features: new features:

View file

@ -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"

View file

@ -1590,11 +1590,23 @@ label(OPTION_SNDLOWAT)dit(bf(tt(sndlowat=<bytes>)))
layer will send the data to <bytes> [link(int)(TYPE_INT)]. layer will send the data to <bytes> [link(int)(TYPE_INT)].
label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>))) label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>)))
Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)]. Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)].
label(OPTION_TYPE)dit(bf(tt(type=<type>))) label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>)))
Sets the type of the socket, usually as argument to the code(socket()) or Forces the use of the specified IP version or protocol. <string> can be
code(socketpair()) call, to <type> [link(int)(TYPE_INT)]. 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 Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3
means raw socket. 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))) COMMENT(label(OPTION_USELOOPBACK)dit(bf(tt(useloopback)))
Sets the code(SO_USELOOPBACK) socket option.) Sets the code(SO_USELOOPBACK) socket option.)
COMMENT(label(OPTION_ACCEPTCONN)dit(bf(tt(acceptconn))) 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.) Set the code(SO_PASSCRED) socket option.)
COMMENT(label(OPTION_PEERCRED)dit(bf(tt(peercred))) COMMENT(label(OPTION_PEERCRED)dit(bf(tt(peercred)))
This is a read-only socket option.) 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))) COMMENT(label(OPTION_REUSEPORT)dit(bf(tt(reuseport)))
Set the code(SO_REUSEPORT) socket option.) Set the code(SO_REUSEPORT) socket option.)
COMMENT(label(OPTION_SECUTIYAUTHENTICATION)dit(bf(tt(securityauthentication))) 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.) Set the SIOCSPGRP with code(ioclt()) to enable SIGIO.)
COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs))) COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs)))
Set the code(SO_USE_IFBUFS) socket option.) 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))) label(OPTION_SO_TIMESTAMP)dit(bf(tt(so-timestamp)))
Sets the SO_TIMESTAMP socket option. This enables receiving and logging of Sets the SO_TIMESTAMP socket option. This enables receiving and logging of
timestamp ancillary messages. timestamp ancillary messages.

View file

@ -479,6 +479,9 @@ int sockan(int fd, FILE *outfile) {
{SO_REUSEADDR, "REUSEADDR"}, {SO_REUSEADDR, "REUSEADDR"},
{SO_TYPE, "TYPE"}, {SO_TYPE, "TYPE"},
{SO_ERROR, "ERROR"}, {SO_ERROR, "ERROR"},
#ifdef SO_PROTOTYPE
{SO_PROTOTYPE, "PROTOTYPE"},
#endif
{SO_DONTROUTE, "DONTROUTE"}, {SO_DONTROUTE, "DONTROUTE"},
{SO_BROADCAST, "BROADCAST"}, {SO_BROADCAST, "BROADCAST"},
{SO_SNDBUF, "SNDBUF"}, {SO_SNDBUF, "SNDBUF"},

82
test.sh
View file

@ -2374,9 +2374,9 @@ N=$((N+1))
#} #}
NAME=UNIXSOCKET NAME=UNIXSTREAM
case "$TESTS" in case "$TESTS" in
*%functions%*|*%$NAME%*) *%functions%*|*%unix%*|*%$NAME%*)
TEST="$NAME: echo via connection to UNIX domain socket" TEST="$NAME: echo via connection to UNIX domain socket"
tf="$td/test$N.stdout" tf="$td/test$N.stdout"
te="$td/test$N.stderr" te="$td/test$N.stderr"
@ -2384,7 +2384,7 @@ ts="$td/test$N.socket"
tdiff="$td/test$N.diff" tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM" da="test$N $(date) $RANDOM"
CMD1="$SOCAT $opts UNIX-LISTEN:$ts PIPE" CMD1="$SOCAT $opts UNIX-LISTEN:$ts PIPE"
CMD2="$SOCAT $opts -!!- UNIX:$ts" CMD2="$SOCAT $opts -!!- UNIX-CONNECT:$ts"
printf "test $F_n $TEST... " $N printf "test $F_n $TEST... " $N
$CMD1 </dev/null >$tf 2>"${te}1" & $CMD1 </dev/null >$tf 2>"${te}1" &
bg=$! # background process id bg=$! # background process id
@ -8520,82 +8520,6 @@ esac
N=$((N+1)) 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 # test: logging of ancillary message
while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_TYPE SCM_NAME ROOT SCM_VALUE while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_TYPE SCM_NAME ROOT SCM_VALUE
do do

View file

@ -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 */ /* note: when S_ISSOCK was undefined, it always gives 0 */
if (exists && S_ISSOCK(st_mode)) { if (exists && S_ISSOCK(st_mode)) {
#if WITH_UNIX #if WITH_UNIX
int socktype = SOCK_STREAM; union sockaddr_union us;
int optsotype = -1; socklen_t uslen;
struct sockaddr_un sa, us;
socklen_t salen, uslen = sizeof(us);
bool needbind = false;
char infobuff[256]; char infobuff[256];
struct opt *opts2;
socket_un_init(&sa);
socket_un_init(&us);
Info1("\"%s\" is a socket, connecting to it", filename); 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 */ applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
if (Getsockname(fd->stream.fd, (struct sockaddr *)&us, &uslen) < 0) { 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)); fd->stream.fd, &us, uslen, strerror(errno));
} else { } else {
Notice1("successfully connected via %s", Notice1("successfully connected via %s",
sockaddr_unix_info(&us, uslen, infobuff, sizeof(infobuff))); sockaddr_unix_info(&us.un, uslen,
infobuff, sizeof(infobuff)));
} }
#else #else
Error("\"%s\" is a socket, but UNIX socket support is not compiled in"); Error("\"%s\" is a socket, but UNIX socket support is not compiled in");

View file

@ -213,6 +213,18 @@ int xiogetaddrinfo(const char *node, const char *service,
if (node != NULL || service != NULL) { if (node != NULL || service != NULL) {
struct addrinfo *record; 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_flags |= AI_PASSIVE;
hints.ai_family = family; hints.ai_family = family;
hints.ai_socktype = socktype; hints.ai_socktype = socktype;

View file

@ -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[1],
xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen, &needbind, &lowport, them, &themlen, us, &uslen, &needbind, &lowport,
&socktype) != STAT_OK) { socktype) != STAT_OK) {
return STAT_NORETRY; 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 int
_xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0, _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0,
const char *hostname, const char *hostname,
@ -153,7 +157,7 @@ int
union sockaddr_union *them, socklen_t *themlen, union sockaddr_union *them, socklen_t *themlen,
union sockaddr_union *us, socklen_t *uslen, union sockaddr_union *us, socklen_t *uslen,
bool *needbind, bool *lowport, bool *needbind, bool *lowport,
int *socktype) { int socktype) {
uint16_t port; uint16_t port;
char infobuff[256]; char infobuff[256];
int result; int result;
@ -162,7 +166,7 @@ int
if ((result = if ((result =
xiogetaddrinfo(hostname, portname, xiogetaddrinfo(hostname, portname,
*pf, *socktype, protocol, *pf, socktype, protocol,
(union sockaddr_union *)them, themlen, (union sockaddr_union *)them, themlen,
res_opts0, res_opts1 res_opts0, res_opts1
)) ))
@ -176,7 +180,7 @@ int
applyopts(-1, opts, PH_EARLY); applyopts(-1, opts, PH_EARLY);
/* 3 means: IP address AND port accepted */ /* 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) res_opts0, res_opts1)
!= STAT_NOACTION) { != STAT_NOACTION) {
*needbind = true; *needbind = true;
@ -205,7 +209,6 @@ int
} }
retropt_bool(opts, OPT_LOWPORT, lowport); retropt_bool(opts, OPT_LOWPORT, lowport);
retropt_int(opts, OPT_SO_TYPE, socktype);
*opts0 = copyopts(opts, GROUP_ALL); *opts0 = copyopts(opts, GROUP_ALL);
@ -217,22 +220,24 @@ int
#if WITH_TCP && WITH_LISTEN #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, int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
const char *portname, int *pf, int ipproto, const char *portname, int *pf, int ipproto,
unsigned long res_opts0, unsigned long res_opts0,
unsigned long res_opts1, unsigned long res_opts1,
union sockaddr_union *us, socklen_t *uslen, union sockaddr_union *us, socklen_t *uslen,
int *socktype) { int socktype) {
char *bindname = NULL; char *bindname = NULL;
int result; int result;
retropt_int(opts, OPT_SO_TYPE, socktype);
retropt_socket_pf(opts, pf); retropt_socket_pf(opts, pf);
retropt_string(opts, OPT_BIND, &bindname); retropt_string(opts, OPT_BIND, &bindname);
if ((result = if ((result =
xiogetaddrinfo(bindname, portname, *pf, *socktype, ipproto, xiogetaddrinfo(bindname, portname, *pf, socktype, ipproto,
(union sockaddr_union *)us, uslen, (union sockaddr_union *)us, uslen,
res_opts0, res_opts1)) res_opts0, res_opts1))
!= STAT_OK) { != 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, 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[1],
fd->stream.para.socket.ip.res_opts[0], fd->stream.para.socket.ip.res_opts[0],
us, &uslen, &socktype) us, &uslen, socktype)
!= STAT_OK) { != STAT_OK) {
return STAT_NORETRY; return STAT_NORETRY;
} }

View file

@ -1,5 +1,5 @@
/* source: xio-ipapp.h */ /* 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 */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_ipapp_h_included #ifndef __xio_ipapp_h_included
@ -25,7 +25,7 @@ extern int
union sockaddr_union *them, socklen_t *themlen, union sockaddr_union *them, socklen_t *themlen,
union sockaddr_union *us, socklen_t *uslen, union sockaddr_union *us, socklen_t *uslen,
bool *needbind, bool *lowport, bool *needbind, bool *lowport,
int *socktype); int socktype);
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname, extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
struct single *xfd, struct single *xfd,
int socktype, int ipproto, void *protname, 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_opts0,
unsigned long res_opts1, unsigned long res_opts1,
union sockaddr_union *us, socklen_t *uslen, union sockaddr_union *us, socklen_t *uslen,
int *socktype); int socktype);
extern int xioopen_ip6app_connect(int argc, const char *argv[], struct opt *opts, extern int xioopen_ip6app_connect(int argc, const char *argv[], struct opt *opts,
int rw, xiofile_t *fd, int rw, xiofile_t *fd,
unsigned groups, int socktype, int ipproto, unsigned groups, int socktype, int ipproto,

View file

@ -25,6 +25,13 @@ const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_R
#endif #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 int
xioopen_listen(struct single *xfd, int xioflags, xioopen_listen(struct single *xfd, int xioflags,
struct sockaddr *us, socklen_t uslen, struct sockaddr *us, socklen_t uslen,
@ -81,15 +88,21 @@ int
} }
/* waits for incoming connection, checks its source address and port. Depending /* creates the listening socket, bind, applies options; waits for incoming
on fork option, it may fork a subprocess. 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 Returns 0 if a connection was accepted; with fork option, this is always in
a subprocess! a subprocess!
Other return values indicate a problem; this can happen in the master Other return values indicate a problem; this can happen in the master
process or in a subprocess. process or in a subprocess.
This function does not retry. If you need retries, handle this is a This function does not retry. If you need retries, handle this in a
loop in the calling function. loop in the calling function (and always provide the options...)
after fork, we set the forever/retry of the child process to 0 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, 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) {
@ -124,9 +137,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
xiosetchilddied(); /* set SIGCHLD handler */ xiosetchilddied(); /* set SIGCHLD handler */
} }
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) { if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
Msg4(level,
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }

View file

@ -200,7 +200,7 @@ static int
xfd->para.socket.ip.res_opts[1], xfd->para.socket.ip.res_opts[1],
xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen, them, &themlen, us, &uslen,
&needbind, &lowport, &socktype); &needbind, &lowport, socktype);
if (result != STAT_OK) return STAT_NORETRY; if (result != STAT_OK) return STAT_NORETRY;
if (xioopts.logopt == 'm') { if (xioopts.logopt == 'm') {
@ -431,7 +431,7 @@ static int
if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto, if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
xfd->para.socket.ip.res_opts[1], xfd->para.socket.ip.res_opts[1],
xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[0],
us, &uslen, &socktype) us, &uslen, socktype)
!= STAT_OK) { != STAT_OK) {
return STAT_NORETRY; return STAT_NORETRY;
} }

View file

@ -10,6 +10,9 @@
#include "xio-process.h" #include "xio-process.h"
#include "xio-progcall.h" #include "xio-progcall.h"
#include "xio-socket.h"
/* these options are used by address pty too */ /* these options are used by address pty too */
#if HAVE_OPENPTY #if HAVE_OPENPTY
const struct optdesc opt_openpty = { "openpty", NULL, OPT_OPENPTY, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC }; 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 */ struct opt *popts; /* parent process options */
int numleft; 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); int rw = (xioflags & XIO_ACCMODE);
bool usepipes = false; bool usepipes = false;
#if HAVE_PTY #if HAVE_PTY
@ -358,13 +361,10 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
applyopts(fd->fd, popts, PH_LATE); applyopts(fd->fd, popts, PH_LATE);
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1; if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
} else { } else {
d = AF_UNIX; type = SOCK_STREAM; d = AF_UNIX;
protocol = 0; /* PF_UNIX does not work on AIX */ retropt_int(popts, OPT_PROTOCOL_FAMILY, &d);
retropt_int(popts, OPT_SO_TYPE, &type); result = xiosocketpair(popts, d, SOCK_STREAM, 0, sv);
result = Socketpair(d, type, protocol, sv);
if (result < 0) { if (result < 0) {
Error5("socketpair(%d, %d, %d, %p): %s",
d, type, protocol, sv, strerror(errno));
return -1; return -1;
} }
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})", /*0 Info5("socketpair(%d, %d, %d, {%d,%d})",

View file

@ -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[1],
xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen, them, &themlen, us, &uslen,
&needbind, &lowport, &socktype); &needbind, &lowport, socktype);
if (result != STAT_OK) return result; if (result != STAT_OK) return result;
Notice4("opening connection to %s:%u via proxy %s:%s", Notice4("opening connection to %s:%u via proxy %s:%s",

View file

@ -17,7 +17,6 @@
#include "xio-rawip.h" #include "xio-rawip.h"
static static
int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts, int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *fd, unsigned groups, int pf, 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 static
int _xioopen_rawip_sendto(const char *hostname, const char *protname, int _xioopen_rawip_sendto(const char *hostname, const char *protname,
struct opt *opts, int xioflags, 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_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>") }; 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; return STAT_NORETRY;
} }
if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd, if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
groups, pf)) != STAT_OK) { groups, &pf)) != STAT_OK) {
return result; return result;
} }
_xio_openlate(&xxfd->stream, opts); _xio_openlate(&xxfd->stream, opts);
return STAT_OK; 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 static
int _xioopen_rawip_sendto(const char *hostname, const char *protname, int _xioopen_rawip_sendto(const char *hostname, const char *protname,
struct opt *opts, int xioflags, xiofile_t *xxfd, struct opt *opts, int xioflags, xiofile_t *xxfd,
unsigned groups, int pf) { unsigned groups, int *pf) {
char *garbage; char *garbage;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *xfd = &xxfd->stream;
union sockaddr_union us; union sockaddr_union us;
@ -107,7 +113,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
} }
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_PROTOCOL_FAMILY, pf);
/* ...res_opts[] */ /* ...res_opts[] */
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; 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); xfd->salen = sizeof(xfd->peersa);
if ((result = if ((result =
xiogetaddrinfo(hostname, NULL, pf, socktype, ipproto, xiogetaddrinfo(hostname, NULL, *pf, socktype, ipproto,
&xfd->peersa, &xfd->salen, &xfd->peersa, &xfd->salen,
xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[0],
xfd->para.socket.ip.res_opts[1])) xfd->para.socket.ip.res_opts[1]))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
if (pf == PF_UNSPEC) { if (*pf == PF_UNSPEC) {
pf = xfd->peersa.soa.sa_family; *pf = xfd->peersa.soa.sa_family;
} }
uslen = socket_init(pf, &us); uslen = socket_init(*pf, &us);
xfd->dtype = XIODATA_RECVFROM_SKIPIP; 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[0],
xfd->para.socket.ip.res_opts[1]) != STAT_NOACTION) { xfd->para.socket.ip.res_opts[1]) != STAT_NOACTION) {
needbind = true; needbind = true;
} }
return return
_xioopen_dgram_sendto(needbind?&us:NULL, uslen, _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 = if ((result =
_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd, _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
groups, pf)) != STAT_OK) { groups, &pf)) != STAT_OK) {
return result; return result;
} }
@ -216,7 +222,6 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
/*return STAT_NORETRY;*/ /*return STAT_NORETRY;*/
} }
xfd->stream.howtoend = END_NONE; xfd->stream.howtoend = END_NONE;
retropt_int(opts, OPT_SO_TYPE, &socktype);
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {
@ -274,7 +279,6 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
protname); protname);
/*return STAT_NORETRY;*/ /*return STAT_NORETRY;*/
} }
retropt_int(opts, OPT_SO_TYPE, &socktype);
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {

View file

@ -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 = { "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_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_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 }; 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 #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 }; 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 */ #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 }; 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 #endif
#ifdef SO_PROTOTYPE /* Solaris, HP-UX */ /* the SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more
const struct optdesc opt_so_prototype = {"so-prototype", "prototype", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_PROTOTYPE }; general purpose */
#endif 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 #ifdef FIOSETOWN
const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN }; const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN };
#endif #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_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_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_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 /* a subroutine that is common to all socket addresses that want to connect
to a peer address. to a peer address.
might fork. 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. returns 0 on success.
*/ */
int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
struct sockaddr *them, size_t themlen, 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) { bool alt, int level) {
int fcntl_flags = 0; int fcntl_flags = 0;
char infobuff[256]; char infobuff[256];
@ -158,9 +164,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
int _errno; int _errno;
int result; int result;
if ((xfd->fd = Socket(pf, stype, proto)) < 0) { if ((xfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) {
Msg4(level,
"socket(%d, %d, %d): %s", pf, stype, proto, strerror(errno));
return STAT_RETRYLATER; 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_CONNECTED);
applyopts(xfd->fd, opts, PH_LATE); 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 /* a subroutine that is common to all socket addresses that want to connect
to a peer address. to a peer address.
might fork. 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. returns 0 on success.
*/ */
int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
struct sockaddr *them, size_t themlen, 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 alt) {
bool dofork = false; bool dofork = false;
struct opt *opts0; struct opt *opts0;
@ -381,7 +390,6 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
int result; int result;
retropt_bool(opts, OPT_FORK, &dofork); retropt_bool(opts, OPT_FORK, &dofork);
retropt_int(opts, OPT_SO_TYPE, &stype);
opts0 = copyopts(opts, GROUP_ALL); opts0 = copyopts(opts, GROUP_ALL);
@ -398,7 +406,7 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
level = E_ERROR; level = E_ERROR;
result = result =
_xioopen_connect(xfd, us, uslen, them, themlen, opts, _xioopen_connect(xfd, us, uslen, them, themlen, opts,
pf, stype, proto, alt, level); pf, socktype, protocol, alt, level);
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #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 */ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
union sockaddr_union *us, socklen_t uslen, union sockaddr_union *us, socklen_t uslen,
struct opt *opts, 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); union sockaddr_union la; socklen_t lalen = sizeof(la);
char infobuff[256]; char infobuff[256];
if ((xfd->fd = Socket(pf, socktype, ipproto)) < 0) { if ((xfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) {
Msg4(level,
"socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
return STAT_RETRYLATER; 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 This function does not retry. If you need retries, handle this is a
loop in the calling function. loop in the calling function.
after fork, we set the forever/retry of the child process to 0 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, int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
struct sockaddr *us, socklen_t uslen, 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 (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) { if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
Msg4(level,
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
return STAT_RETRYLATER; 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 (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) { if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
Msg4(level,
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -1371,3 +1382,41 @@ int xiosetsockaddrenv(const char *lr,
} }
#endif /* _WITH_SOCKET */ #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;
}

View file

@ -5,6 +5,12 @@
#ifndef __xio_socket_h_included #ifndef __xio_socket_h_included
#define __xio_socket_h_included 1 #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_connect_timeout;
extern const struct optdesc opt_so_debug; extern const struct optdesc opt_so_debug;
extern const struct optdesc opt_so_acceptconn; 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, extern int xioopen_connect(struct single *fd,
struct sockaddr *us, size_t uslen, struct sockaddr *us, size_t uslen,
struct sockaddr *them, size_t themlen, 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 alt);
extern int _xioopen_connect(struct single *fd, extern int _xioopen_connect(struct single *fd,
struct sockaddr *us, size_t uslen, struct sockaddr *us, size_t uslen,
struct sockaddr *them, size_t themlen, 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); bool alt, int level);
/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */ /* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */
@ -93,6 +101,10 @@ int xiogetpacketsrc(int fd, struct msghdr *msgh);
extern extern
int xiocheckpeer(xiosingle_t *xfd, int xiocheckpeer(xiosingle_t *xfd,
union sockaddr_union *pa, union sockaddr_union *la); 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 extern
int xiosetsockaddrenv(const char *lr, union sockaddr_union *sau, socklen_t salen, int proto); int xiosetsockaddrenv(const char *lr, union sockaddr_union *sau, socklen_t salen, int proto);

View file

@ -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[1],
xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen, them, &themlen, us, &uslen,
&needbind, &lowport, &socktype); &needbind, &lowport, socktype);
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"", Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
targetname, targetname,

View file

@ -114,7 +114,6 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
applyopts(-1, opts, PH_INIT); applyopts(-1, opts, PH_INIT);
uslen = socket_init(pf, &us); uslen = socket_init(pf, &us);
retropt_int(opts, OPT_SO_TYPE, &socktype);
retropt_bind(opts, pf, socktype, IPPROTO_UDP, retropt_bind(opts, pf, socktype, IPPROTO_UDP,
(struct sockaddr *)&us, &uslen, 1, (struct sockaddr *)&us, &uslen, 1,
fd->stream.para.socket.ip.res_opts[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 _sockname;
union sockaddr_union *la = &_sockname; /* local address */ union sockaddr_union *la = &_sockname; /* local address */
if ((fd->stream.fd = Socket(pf, socktype, ipproto)) < 0) { if ((fd->stream.fd = xiosocket(opts, pf, socktype, ipproto, E_ERROR)) < 0) {
Error4("socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts(fd->stream.fd, opts, PH_PASTSOCKET); 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) { if (xiocheckpeer(&fd->stream, them, la) < 0) {
/* drop packet */ /* drop packet */
char buff[512]; 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); Close(fd->stream.fd);
continue; continue;
} }
@ -299,6 +297,8 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
argv[0], argc-1); argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
retropt_socket_pf(opts, &pf);
if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xxfd, if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xxfd,
groups, pf, socktype, ipproto)) groups, pf, socktype, ipproto))
!= STAT_OK) { != STAT_OK) {
@ -308,6 +308,12 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
return STAT_OK; 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 static
int _xioopen_udp_sendto(const char *hostname, const char *servname, int _xioopen_udp_sendto(const char *hostname, const char *servname,
struct opt *opts, struct opt *opts,
@ -321,7 +327,6 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
int result; int result;
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
retropt_int(opts, OPT_SO_TYPE, &socktype);
/* ...res_opts[] */ /* ...res_opts[] */
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; 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; return STAT_RETRYLATER;
} }
retropt_socket_pf(opts, &pf);
result = result =
_xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd, groups, _xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd, groups,
pf, socktype, ipproto); pf, socktype, ipproto);

View file

@ -15,76 +15,69 @@
#if WITH_UNIX #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); /* to avoid unneccessary "live" if () conditionals when no abstract support is
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); compiled in (or at least to give optimizing compilers a good chance) we need
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); a constant that can be used in C expressions */
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); #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 static
int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups, int xioflags, xiofile_t *xxfd, unsigned groups,
int pf, int socktype, int ipproto); int abstract, int dummy2, int dummy3);
static 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 #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); 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>") };
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); #if WITH_LISTEN
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); 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>") };
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); #endif /* WITH_LISTEN */
static 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>") };
int xioopen_abstract_recv(int argc, const char *argv[], struct opt *opts, 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>") };
int xioflags, xiofile_t *xfd, unsigned groups, 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>") };
int pf, int socktype, int ipproto); 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>") };
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);
#endif /* WITH_ABSTRACT_UNIXSOCKET */ #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>") }; const struct optdesc xioopt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_INIT, TYPE_BOOL, OFUNC_SPEC, 0, 0 };
#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 };
/* 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 socklen_t
xiosetunix(struct sockaddr_un *saun, xiosetunix(int pf,
struct sockaddr_un *saun,
const char *path, const char *path,
bool abstract, bool abstract,
bool tight) { bool tight) {
size_t pathlen; size_t pathlen;
socklen_t len; socklen_t len;
if (!abstract) { socket_un_init(saun);
if ((pathlen = strlen(path)) > sizeof(saun->sun_path)) { #ifdef WITH_ABSTRACT_UNIXSOCKET
Warn2("unix socket address "F_Zu" characters long, truncating to "F_Zu"", if (abstract) {
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 {
if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) { if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) {
Warn2("socket address "F_Zu" characters long, truncating to "F_Zu"", Warn2("socket address "F_Zu" characters long, truncating to "F_Zu"",
pathlen+1, sizeof(saun->sun_path)); pathlen+1, sizeof(saun->sun_path));
@ -100,15 +93,32 @@ xiosetunix(struct sockaddr_un *saun,
} else { } else {
len = sizeof(struct sockaddr_un); 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; return len;
} }
#if WITH_LISTEN #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 */ /* we expect the form: filename */
const char *name; const char *name;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *xfd = &xxfd->stream;
int pf = PF_UNIX;
int socktype = SOCK_STREAM;
int protocol = 0;
struct sockaddr_un us; struct sockaddr_un us;
socklen_t uslen; socklen_t uslen;
bool tight = true; bool tight = true;
@ -123,28 +133,29 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
return STAT_NORETRY; return STAT_NORETRY;
} }
socket_un_init(&us);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
name = argv[1]; 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_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (opt_unlink_close) { if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) { if ((xfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->opt_unlink_close = true; xfd->opt_unlink_close = true;
} }
}
xfd->howtoend = END_SHUTDOWN;
applyopts(-1, opts, PH_INIT); applyopts(-1, opts, PH_INIT);
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_EARLY); applyopts(-1, opts, PH_EARLY);
if (!(ABSTRACT && abstract)) {
if (opt_unlink_early) { if (opt_unlink_early) {
if (Unlink(name) < 0) { if (Unlink(name) < 0) {
if (errno == ENOENT) { 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 /* trying to set user-early, perm-early etc. here is useless because
file system entry is available only past bind() call. */ file system entry is available only past bind() call. */
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
}
retropt_int(opts, OPT_SO_TYPE, &socktype);
opts0 = copyopts(opts, GROUP_ALL); opts0 = copyopts(opts, GROUP_ALL);
if ((result = if ((result =
xioopen_listen(xfd, xioflags, xioopen_listen(xfd, xioflags,
(struct sockaddr *)&us, uslen, (struct sockaddr *)&us, uslen,
opts, opts0, PF_UNIX, socktype, 0)) opts, opts0, pf, socktype, protocol))
!= 0) != 0)
return result; return result;
return 0; return 0;
@ -174,10 +184,13 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
#endif /* WITH_LISTEN */ #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 */ /* we expect the form: filename */
const char *name; const char *name;
struct single *xfd = &xxfd->stream; struct single *xfd = &xxfd->stream;
int pf = PF_UNIX;
int socktype = SOCK_STREAM;
int protocol = 0;
struct sockaddr_un them, us; struct sockaddr_un them, us;
socklen_t themlen, uslen; socklen_t themlen, uslen;
bool tight = true; bool tight = true;
@ -191,15 +204,15 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
return STAT_NORETRY; return STAT_NORETRY;
} }
socket_un_init(&us);
socket_un_init(&them);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
name = argv[1]; 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); 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) { != STAT_NOACTION) {
needbind = true; needbind = true;
} }
@ -219,7 +232,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
xioopen_connect(xfd, xioopen_connect(xfd,
needbind?(struct sockaddr *)&us:NULL, uslen, needbind?(struct sockaddr *)&us:NULL, uslen,
(struct sockaddr *)&them, themlen, (struct sockaddr *)&them, themlen,
opts, PF_UNIX, socktype, 0, false)) != 0) { opts, pf, socktype, protocol, false)) != 0) {
return result; return result;
} }
if ((result = _xio_openlate(xfd, opts)) < 0) { 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; const char *name;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *xfd = &xxfd->stream;
int pf = PF_UNIX;
int socktype = SOCK_DGRAM;
int protocol = 0;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen; socklen_t uslen;
bool tight = true; bool tight = true;
int pf = PF_UNIX;
bool needbind = false; bool needbind = false;
bool opt_unlink_close = 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; return STAT_NORETRY;
} }
uslen = socket_init(pf, &us); retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
xfd->salen = socket_init(pf, &xfd->peersa); name = argv[1];
retropt_socket_pf(opts, &pf);
xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, tight);
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
retropt_int(opts, OPT_SO_TYPE, &socktype); if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
name = argv[1];
xfd->salen = xiosetunix(&xfd->peersa.un, name, false, tight);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
}
xfd->dtype = XIODATA_RECVFROM; 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) { != STAT_NOACTION) {
needbind = true; needbind = true;
} }
@ -277,15 +292,21 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
return return
_xioopen_dgram_sendto(needbind?&us:NULL, uslen, _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, pf, socktype, 0); opts, xioflags, xfd, groups,
pf, socktype, protocol);
} }
static static
int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups, int xioflags, xiofile_t *xxfd, unsigned groups,
int pf, int socktype, int dummy3) { int abstract, int dummy2, int dummy3) {
/* we expect the form: filename */
const char *name; const char *name;
xiosingle_t *xfd = &xxfd->stream;
int pf = PF_UNIX;
int socktype = SOCK_DGRAM;
int protocol = 0;
struct sockaddr_un us; struct sockaddr_un us;
socklen_t uslen; socklen_t uslen;
bool tight = true; bool tight = true;
@ -299,23 +320,24 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
return STAT_NORETRY; return STAT_NORETRY;
} }
socket_un_init(&us);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
name = argv[1]; 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; xfd->howtoend = END_NONE;
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0); 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_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (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); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->stream.opt_unlink_close = true; xfd->opt_unlink_close = true;
} }
if (opt_unlink_early) { 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; xfd->dtype = XIODATA_RECVFROM_ONE;
return _xioopen_dgram_recvfrom(&xfd->stream, xioflags, return
_xioopen_dgram_recvfrom(xfd, xioflags,
needbind?(struct sockaddr *)&us:NULL, uslen, needbind?(struct sockaddr *)&us:NULL, uslen,
opts, pf, socktype, 0, E_ERROR); opts, pf, socktype, protocol, E_ERROR);
} }
static static
int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups, int xioflags, xiofile_t *xxfd, unsigned groups,
int pf, int socktype, int ipproto) { int abstract, int dummy2, int dummy3) {
/* we expect the form: filename */
const char *name; const char *name;
xiosingle_t *xfd = &xxfd->stream;
int pf = PF_UNIX;
int socktype = SOCK_DGRAM;
int protocol = 0;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen; socklen_t uslen;
bool tight = true; bool tight = true;
@ -355,18 +384,17 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
return STAT_NORETRY; 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]; 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? */ #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 #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); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
if (opt_unlink_early) { if (opt_unlink_early) {
if (Unlink(name) < 0) { 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); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (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); 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; xfd->dtype = XIODATA_RECV;
result = _xioopen_dgram_recv(&xfd->stream, xioflags, &us.soa, uslen, result = _xioopen_dgram_recv(xfd, xioflags, &us.soa, uslen,
opts, pf, socktype, ipproto, E_ERROR); opts, pf, socktype, protocol, E_ERROR);
return result; 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) { 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) {
const char *name; /* we expect the form: filename */
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;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
} }
xfd->howtoend = END_SHUTDOWN; return
retropt_int(opts, OPT_SO_TYPE, &socktype); _xioopen_unix_client(&xxfd->stream, xioflags, groups, abstract, opts,
argv[1]);
}
uslen = socket_init(pf, &us); /* establishes communication with an existing UNIX type socket. supports stream
themlen = socket_init(pf, &them); 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); retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
name = argv[1]; themlen = xiosetunix(pf, &them.un, name, abstract, tight);
themlen = xiosetunix(&them.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); 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) { != STAT_NOACTION) {
needbind = true; 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; 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 */ /* xfd->dtype = DATA_STREAM; // is default */
if ((result = if ((result =
xioopen_connect(xfd, xioopen_connect(xfd,
needbind?(struct sockaddr *)&us:NULL, uslen, needbind?(struct sockaddr *)&us:NULL, uslen,
(struct sockaddr *)&them, themlen, (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 (errno == EPROTOTYPE) {
if (needbind) { if (needbind) {
Unlink(us.un.sun_path); Unlink(us.un.sun_path);
} }
applyopts(-1, opts, PH_INIT); dropopts2(opts, PH_INIT, PH_SPEC); opts = opts0;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
xfd->peersa = them; xfd->peersa = them;
xfd->salen = sizeof(struct sockaddr_un); xfd->salen = sizeof(struct sockaddr_un);
if ((result = if ((result =
_xioopen_dgram_sendto(needbind?&us:NULL, uslen, _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, pf, opts, xioflags, xfd, groups,
socktype?socktype:SOCK_DGRAM, 0)) pf, socktype?socktype:SOCK_DGRAM, protocol))
!= 0) { != 0) {
return result; 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 /* returns information that can be used for constructing an environment
variable describing the socket address. variable describing the socket address.
if idx is 0, this function writes "ADDR" into namebuff and the path into if idx is 0, this function writes "ADDR" into namebuff and the path into

View file

@ -5,12 +5,12 @@
#ifndef __xio_unix_h_included #ifndef __xio_unix_h_included
#define __xio_unix_h_included 1 #define __xio_unix_h_included 1
extern const struct addrdesc addr_unix_connect; extern const struct addrdesc xioaddr_unix_connect;
extern const struct addrdesc addr_unix_listen; extern const struct addrdesc xioaddr_unix_listen;
extern const struct addrdesc addr_unix_sendto; extern const struct addrdesc xioaddr_unix_sendto;
extern const struct addrdesc addr_unix_recvfrom; extern const struct addrdesc xioaddr_unix_recvfrom;
extern const struct addrdesc addr_unix_recv; extern const struct addrdesc xioaddr_unix_recv;
extern const struct addrdesc addr_unix_client; extern const struct addrdesc xioaddr_unix_client;
extern const struct addrdesc xioaddr_abstract_connect; extern const struct addrdesc xioaddr_abstract_connect;
extern const struct addrdesc xioaddr_abstract_listen; extern const struct addrdesc xioaddr_abstract_listen;
extern const struct addrdesc xioaddr_abstract_sendto; 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_recv;
extern const struct addrdesc xioaddr_abstract_client; extern const struct addrdesc xioaddr_abstract_client;
extern const struct optdesc opt_unix_tightsocklen; extern const struct optdesc xioopt_unix_tightsocklen;
extern socklen_t extern socklen_t
xiosetunix(struct sockaddr_un *saun, xiosetunix(int pf,
struct sockaddr_un *saun,
const char *path, const char *path,
bool abstract, bool abstract,
bool tight); bool tight);
@ -30,4 +31,8 @@ xiosetsockaddrenv_unix(int idx, char *namebuff, size_t namelen,
char *valuebuff, size_t valuelen, char *valuebuff, size_t valuelen,
struct sockaddr_un *sa, socklen_t salen, int ipproto); 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) */ #endif /* !defined(__xio_unix_h_included) */

View file

@ -106,7 +106,7 @@ const struct addrname addressnames[] = {
#endif #endif
#endif /* WITH_RAWIP */ #endif /* WITH_RAWIP */
#if WITH_UNIX #if WITH_UNIX
{ "local", &addr_unix_connect }, { "local", &xioaddr_unix_connect },
#endif #endif
#if WITH_FILE #if WITH_FILE
{ "open", &addr_open }, { "open", &addr_open },
@ -231,19 +231,19 @@ const struct addrname addressnames[] = {
{ "udp6-sendto", &addr_udp6_sendto }, { "udp6-sendto", &addr_udp6_sendto },
#endif #endif
#if WITH_UNIX #if WITH_UNIX
{ "unix", &addr_unix_client }, { "unix", &xioaddr_unix_client },
{ "unix-client", &addr_unix_client }, { "unix-client", &xioaddr_unix_client },
{ "unix-connect", &addr_unix_connect }, { "unix-connect", &xioaddr_unix_connect },
#endif #endif
#if WITH_UNIX && WITH_LISTEN #if WITH_UNIX && WITH_LISTEN
{ "unix-l", &addr_unix_listen }, { "unix-l", &xioaddr_unix_listen },
{ "unix-listen", &addr_unix_listen }, { "unix-listen", &xioaddr_unix_listen },
#endif #endif
#if WITH_UNIX #if WITH_UNIX
{ "unix-recv", &addr_unix_recv }, { "unix-recv", &xioaddr_unix_recv },
{ "unix-recvfrom", &addr_unix_recvfrom }, { "unix-recvfrom", &xioaddr_unix_recvfrom },
{ "unix-send", &addr_unix_sendto }, { "unix-send", &xioaddr_unix_sendto },
{ "unix-sendto", &addr_unix_sendto }, { "unix-sendto", &xioaddr_unix_sendto },
#endif #endif
#else /* !0 */ #else /* !0 */
# if WITH_INTEGRATE # if WITH_INTEGRATE

View file

@ -1502,7 +1502,7 @@ const struct optname optionnames[] = {
#ifdef O_TEXT #ifdef O_TEXT
IF_ANY ("text", &opt_o_text) IF_ANY ("text", &opt_o_text)
#endif #endif
IF_UNIX ("tightsocklen", &opt_unix_tightsocklen) IF_UNIX ("tightsocklen", &xioopt_unix_tightsocklen)
IF_TERMIOS("time", &opt_vtime) IF_TERMIOS("time", &opt_vtime)
#ifdef SO_TIMESTAMP #ifdef SO_TIMESTAMP
IF_SOCKET ("timestamp", &opt_so_timestamp) IF_SOCKET ("timestamp", &opt_so_timestamp)
@ -1533,7 +1533,7 @@ const struct optname optionnames[] = {
IF_ANY ("uid-l", &opt_user_late) IF_ANY ("uid-l", &opt_user_late)
IF_NAMED ("umask", &opt_umask) IF_NAMED ("umask", &opt_umask)
IF_IP6 ("unicast-hops", &opt_ipv6_unicast_hops) 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", &opt_unlink)
IF_NAMED ("unlink-close", &opt_unlink_close) IF_NAMED ("unlink-close", &opt_unlink_close)
IF_NAMED ("unlink-early", &opt_unlink_early) 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) { while (opt->desc != ODESC_END) {
if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { 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; opt->desc = ODESC_DONE;
return 0; return 0;
} }
@ -2580,7 +2588,7 @@ int retropt_bind(struct opt *opts,
{ {
bool tight = false; bool tight = false;
struct sockaddr_un *s_un = (struct sockaddr_un *)sa; 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; break;
#endif /* WITH_UNIX */ #endif /* WITH_UNIX */

View file

@ -521,7 +521,8 @@ enum e_optcode {
OPT_PIPES, OPT_PIPES,
/*OPT_PORT,*/ /*OPT_PORT,*/
OPT_PROMPT, /* readline */ 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_PROXYPORT,
OPT_PROXY_AUTHORIZATION, OPT_PROXY_AUTHORIZATION,
OPT_PROXY_RESOLVE, OPT_PROXY_RESOLVE,
@ -615,9 +616,7 @@ enum e_optcode {
#ifdef SO_PRIORITY #ifdef SO_PRIORITY
OPT_SO_PRIORITY, OPT_SO_PRIORITY,
#endif #endif
#ifdef SO_PROTOTYPE
OPT_SO_PROTOTYPE, OPT_SO_PROTOTYPE,
#endif
OPT_SO_RCVBUF, OPT_SO_RCVBUF,
OPT_SO_RCVBUF_LATE, OPT_SO_RCVBUF_LATE,
#ifdef SO_RCVLOWAT #ifdef SO_RCVLOWAT
@ -794,7 +793,8 @@ enum e_optcode {
/* keep consistent with xiohelp.c:optionphasenames ! */ /* keep consistent with xiohelp.c:optionphasenames ! */
enum e_phase { 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_INIT, /* retrieving info from original state */
PH_EARLY, /* before any other processing */ PH_EARLY, /* before any other processing */
PH_PREOPEN, /* before file descriptor is created/opened */ PH_PREOPEN, /* before file descriptor is created/opened */