mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
Corrected UNIX client NAMED options to work on bind address
This commit is contained in:
parent
5570bf4d62
commit
d9d320cb47
13 changed files with 232 additions and 45 deletions
5
CHANGES
5
CHANGES
|
@ -34,6 +34,11 @@ Corrections:
|
|||
pselect() system call.
|
||||
Thanks to Fulvio Scapin for reporting this issue.
|
||||
|
||||
UNIX domain client addresses applied file system entry options (group
|
||||
NAMED) to the server socket instead of the client (bind) socket entry.
|
||||
Tests: UNIX_SENDTO_UNLINK UNIX_CONNECT_UNLINK
|
||||
Thanks to Nico Williams for reporting this major issue.
|
||||
|
||||
Porting:
|
||||
In gcc version 10 the default changed from -fcommon to -fno-common.
|
||||
Consequently, linking filan and procan failed with error
|
||||
|
|
20
DEVELOPMENT
20
DEVELOPMENT
|
@ -157,6 +157,26 @@ PH_LATE FD is ready, before start of data loop
|
|||
PH_LATE2 FD is ready, dropping privileges
|
||||
|
||||
|
||||
Passive UNIX socket addresses; this is a mix of socket phases and file system phases:
|
||||
PH_INIT retrieving info from original state
|
||||
PH_EARLY before any other processing
|
||||
PH_PRESOCKET before socket call
|
||||
PH_SOCKET for socket call
|
||||
PH_PASTSOCKET after socket call
|
||||
PH_FD soon after FD creation or identification
|
||||
PH_PREOPEN before file creation/opening
|
||||
PH_PREBIND before socket bind()
|
||||
PH_BIND during socket bind()
|
||||
PH_PASTOPEN past file creation/opening
|
||||
PH_PASTBIND past socket bind(), not used up to 1.7.3.4
|
||||
PH_PRECONNECT before connect()
|
||||
PH_CONNECT during connect()
|
||||
PH_PASTCONNECT after connect()
|
||||
PH_CONNECTED phase common with listen
|
||||
PH_LATE FD is ready, before start of data loop
|
||||
PH_LATE2 FD is ready, dropping privileges
|
||||
|
||||
|
||||
FD addresses:
|
||||
|
||||
PH_INIT retrieving info from original state
|
||||
|
|
|
@ -1541,6 +1541,8 @@ startdit()enddit()nl()
|
|||
label(GROUP_NAMED)em(bf(NAMED option group))
|
||||
|
||||
These options work on file system entries.nl()
|
||||
Please note that, with UNIX domain client addresses, this means the bind entry,
|
||||
not the target/peer entry.nl()
|
||||
See also options link(user)(OPTION_USER), link(group)(OPTION_GROUP), and
|
||||
link(mode)(OPTION_MODE).
|
||||
|
||||
|
@ -1575,12 +1577,11 @@ label(OPTION_UNLINK_LATE)dit(bf(tt(unlink-late)))
|
|||
label(OPTION_UNLINK_CLOSE)dit(bf(tt(unlink-close)))
|
||||
Removes the addresses file system entry when closing the address.
|
||||
For link(named pipes)(ADDRESS_NAMED_PIPE),
|
||||
link(listening unix domain sockets)(ADDRESS_UNIX_LISTEN),
|
||||
link(UNIX domain sockets)(ADDRESS_UNIX_LISTEN),
|
||||
and the link(symbolic links)(OPTION_SYMBOLIC_LINK) of link(pty addresses)(ADDRESS_PTY),
|
||||
the default is 1; for link(created files)(ADDRESS_CREAT),
|
||||
link(opened files)(ADDRESS_OPEN),
|
||||
link(generic opened files)(ADDRESS_GOPEN), and
|
||||
link(client unix domain sockets)(ADDRESS_UNIX_CONNECT) the default is 0.
|
||||
link(opened files)(ADDRESS_OPEN), and
|
||||
link(generic opened files)(ADDRESS_GOPEN) the default is 0.
|
||||
enddit()
|
||||
|
||||
startdit()enddit()nl()
|
||||
|
|
88
test.sh
88
test.sh
|
@ -13573,7 +13573,6 @@ esac
|
|||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
# Test if unbalanced quoting in Socat addresses is detected
|
||||
NAME=UNBALANCED_QUOTE
|
||||
case "$TESTS" in
|
||||
|
@ -13703,6 +13702,93 @@ esac
|
|||
N=$((N+1))
|
||||
|
||||
|
||||
# test if option unlink-close removes the bind socket file
|
||||
NAME=UNIX_SENDTO_UNLINK
|
||||
case "$TESTS" in
|
||||
*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%unix%*|*%$NAME%*)
|
||||
TEST="$NAME: Option unlink-close with UNIX sendto socket"
|
||||
# Have a recv socket with option unlink-close=0
|
||||
# and a sendto socket with option unlink-close=1
|
||||
# Expected beavior: the recv socket is kept, the
|
||||
# sendto/bind socket is removed
|
||||
if ! eval $NUMCOND; then :; else
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
uns="$td/test$N.server"
|
||||
unc="$td/test$N.client"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$TRACE $SOCAT $opts -u UNIX-RECV:$uns,unlink-close=0 GOPEN:$tf"
|
||||
CMD1="$TRACE $SOCAT $opts - UNIX-SENDTO:$uns,bind=$unc,unlink-close=1"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 >/dev/null 2>"${te}0" &
|
||||
pid0=$!
|
||||
waitunixport $uns 1
|
||||
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
||||
rc1=$?
|
||||
kill $pid0 2>/dev/null; wait
|
||||
if test -S $uns && ! test -S $unc; then
|
||||
$PRINTF "$OK\n"
|
||||
numOK=$((numOK+1))
|
||||
else
|
||||
$PRINTF "$FAILED\n"
|
||||
echo "$CMD0 &"
|
||||
echo "$CMD1"
|
||||
ls -ld $uns $unc
|
||||
cat "${te}0"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
fi
|
||||
fi # NUMCOND
|
||||
;;
|
||||
esac
|
||||
N=$((N+1))
|
||||
|
||||
# test if option unlink-close removes the bind socket file
|
||||
NAME=UNIX_CONNECT_UNLINK
|
||||
case "$TESTS" in
|
||||
*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%unix%*|*%$NAME%*)
|
||||
TEST="$NAME: Option unlink-close with UNIX connect socket"
|
||||
# Have a listen socket with option unlink-close=0
|
||||
# and a connect socket with option unlink-close=1
|
||||
# Expected beavior: the listen socket entry is kept, the
|
||||
# connect/bind socket is removed
|
||||
if ! eval $NUMCOND; then :; else
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
uns="$td/test$N.server"
|
||||
unc="$td/test$N.client"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$TRACE $SOCAT $opts -u UNIX-LISTEN:$uns,unlink-close=0 GOPEN:$tf"
|
||||
CMD1="$TRACE $SOCAT $opts - UNIX-CONNECT:$uns,bind=$unc,unlink-close=1"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 >/dev/null 2>"${te}0" &
|
||||
pid0=$!
|
||||
waitunixport $uns 1
|
||||
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
||||
rc1=$?
|
||||
kill $pid0 2>/dev/null; wait
|
||||
if test -S $uns && ! test -S $unc; then
|
||||
$PRINTF "$OK\n"
|
||||
numOK=$((numOK+1))
|
||||
else
|
||||
$PRINTF "$FAILED\n"
|
||||
echo "$CMD0 &"
|
||||
echo "$CMD1"
|
||||
ls -ld $uns $unc
|
||||
cat "${te}0"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
fi
|
||||
fi # NUMCOND
|
||||
;;
|
||||
esac
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
##################################################################################
|
||||
#=================================================================================
|
||||
# here come tests that might affect your systems integrity. Put normal tests
|
||||
|
|
|
@ -79,7 +79,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
result =
|
||||
_xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)us:NULL, uslen,
|
||||
needbind?us:NULL, uslen,
|
||||
(struct sockaddr *)them, themlen,
|
||||
opts, pf, socktype, ipproto, lowport, level);
|
||||
switch (result) {
|
||||
|
|
|
@ -278,7 +278,7 @@ static int
|
|||
/* this cannot fork because we retrieved fork option above */
|
||||
result =
|
||||
_xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)us:NULL, uslen,
|
||||
needbind?us:NULL, uslen,
|
||||
(struct sockaddr *)them, themlen,
|
||||
opts, pf, socktype, ipproto, lowport, level);
|
||||
switch (result) {
|
||||
|
|
|
@ -149,7 +149,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
result =
|
||||
_xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)us:NULL, sizeof(*us),
|
||||
needbind?us:NULL, sizeof(*us),
|
||||
(struct sockaddr *)them, themlen,
|
||||
opts, pf, socktype, IPPROTO_TCP, lowport, level);
|
||||
switch (result) {
|
||||
|
|
79
xio-socket.c
79
xio-socket.c
|
@ -264,7 +264,7 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
needbind?&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, pf, socktype, proto, false)) != 0) {
|
||||
return result;
|
||||
|
@ -337,7 +337,7 @@ int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
if ((result =
|
||||
xioopen_listen(xfd, xioflags,
|
||||
(struct sockaddr *)&us, uslen,
|
||||
&us.soa, uslen,
|
||||
opts, opts0, 0/*instead of pf*/, socktype, proto))
|
||||
!= STAT_OK)
|
||||
return result;
|
||||
|
@ -702,7 +702,7 @@ int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
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,
|
||||
int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int socktype, int protocol,
|
||||
bool alt, int level) {
|
||||
|
@ -713,6 +713,10 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
int _errno;
|
||||
int result;
|
||||
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_EARLY);
|
||||
}
|
||||
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
@ -723,6 +727,9 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
#if WITH_TCP || WITH_UDP
|
||||
|
@ -733,7 +740,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
|
||||
/* prepare sockaddr for bind probing */
|
||||
if (us) {
|
||||
sinp = (union sockaddr_union *)us;
|
||||
sinp = us;
|
||||
} else {
|
||||
if (them->sa_family == AF_INET) {
|
||||
socket_in_init(&sin.ip4);
|
||||
|
@ -779,7 +786,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
i = N = XIO_IPPORT_LOWER + dv.rem;
|
||||
do { /* loop over lowport bind() attempts */
|
||||
*port = htons(i);
|
||||
if (Bind(xfd->fd, (struct sockaddr *)sinp, sizeof(*sinp)) < 0) {
|
||||
if (Bind(xfd->fd, &sinp->soa, sizeof(*sinp)) < 0) {
|
||||
Msg4(errno==EADDRINUSE?E_INFO:level,
|
||||
"bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
|
||||
sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
|
||||
|
@ -803,14 +810,20 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
#endif /* WITH_TCP || WITH_UDP */
|
||||
|
||||
if (us) {
|
||||
if (Bind(xfd->fd, us, uslen) < 0) {
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
if (Bind(xfd->fd, &us->soa, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(us, uslen, infobuff, sizeof(infobuff)),
|
||||
xfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PASTOPEN);
|
||||
}
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
|
||||
|
@ -822,7 +835,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
Fcntl_l(xfd->fd, F_SETFL, fcntl_flags|O_NONBLOCK);
|
||||
}
|
||||
|
||||
result = Connect(xfd->fd, (struct sockaddr *)them, themlen);
|
||||
result = Connect(xfd->fd, them, themlen);
|
||||
_errno = errno;
|
||||
la.soa.sa_family = them->sa_family; lalen = sizeof(la);
|
||||
if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) {
|
||||
|
@ -909,6 +922,9 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
|
||||
applyopts_fchown(xfd->fd, opts); /* OPT_USER, OPT_GROUP */
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_LATE);
|
||||
}
|
||||
applyopts(xfd->fd, opts, PH_LATE);
|
||||
|
||||
return STAT_OK;
|
||||
|
@ -925,7 +941,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
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,
|
||||
int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int socktype, int protocol,
|
||||
bool alt) {
|
||||
|
@ -1033,6 +1049,10 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
union sockaddr_union la; socklen_t lalen = sizeof(la);
|
||||
char infobuff[256];
|
||||
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_EARLY);
|
||||
}
|
||||
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
@ -1044,18 +1064,24 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
|
||||
if (us) {
|
||||
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
||||
if (Bind(xfd->fd, &us->soa, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s",
|
||||
xfd->fd, sockaddr_info((struct sockaddr *)us, uslen, infobuff, sizeof(infobuff)),
|
||||
xfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PASTOPEN);
|
||||
}
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
|
||||
|
@ -1068,6 +1094,9 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
|
||||
applyopts_fchown(xfd->fd, opts);
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_LATE);
|
||||
}
|
||||
applyopts(xfd->fd, opts, PH_LATE);
|
||||
|
||||
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
||||
|
@ -1221,7 +1250,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
if ((us != NULL) && Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
||||
if ((us != NULL) && Bind(xfd->fd, us, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
|
||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||
strerror(errno));
|
||||
|
@ -1362,7 +1391,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
palen = msgh.msg_namelen;
|
||||
|
||||
Notice1("receiving packet from %s"/*"src"*/,
|
||||
sockaddr_info((struct sockaddr *)pa, palen, peername, sizeof(peername))/*,
|
||||
sockaddr_info(&pa->soa, palen, peername, sizeof(peername))/*,
|
||||
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
|
||||
|
||||
xiodopacketinfo(&msgh, true, true);
|
||||
|
@ -1374,7 +1403,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
continue;
|
||||
}
|
||||
Info1("permitting packet from %s",
|
||||
sockaddr_info((struct sockaddr *)pa, palen,
|
||||
sockaddr_info(&pa->soa, palen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
|
||||
/* set the env vars describing the local and remote sockets */
|
||||
|
@ -1482,7 +1511,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
|||
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
if ((us != NULL) && Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
||||
if ((us != NULL) && Bind(xfd->fd, us, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
|
||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||
strerror(errno));
|
||||
|
@ -1727,12 +1756,12 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
if (xiocheckrange(pa, &xfd->para.socket.range) < 0) {
|
||||
char infobuff[256];
|
||||
Warn1("refusing connection from %s due to range option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
return -1;
|
||||
}
|
||||
Info1("permitting connection from %s due to range option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
}
|
||||
#endif /* WITH_IP4 */
|
||||
|
@ -1744,7 +1773,7 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
if (pa->soa.sa_family == AF_INET &&
|
||||
ntohs(((struct sockaddr_in *)pa)->sin_port) != xfd->para.socket.ip.sourceport) {
|
||||
Warn1("refusing connection from %s due to wrong sourceport",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
return -1;
|
||||
}
|
||||
|
@ -1753,20 +1782,20 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
if (pa->soa.sa_family == AF_INET6 &&
|
||||
ntohs(((struct sockaddr_in6 *)pa)->sin6_port) != xfd->para.socket.ip.sourceport) {
|
||||
Warn1("refusing connection from %s due to wrong sourceport",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
return -1;
|
||||
}
|
||||
#endif /* WITH_IP6 */
|
||||
Info1("permitting connection from %s due to sourceport option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
} else if (xfd->para.socket.ip.lowport) {
|
||||
if (pa == NULL) { return -1; }
|
||||
if (pa->soa.sa_family == AF_INET &&
|
||||
ntohs(((struct sockaddr_in *)pa)->sin_port) >= IPPORT_RESERVED) {
|
||||
Warn1("refusing connection from %s due to lowport option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
return -1;
|
||||
}
|
||||
|
@ -1775,13 +1804,13 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
ntohs(((struct sockaddr_in6 *)pa)->sin6_port) >=
|
||||
IPPORT_RESERVED) {
|
||||
Warn1("refusing connection from %s due to lowport option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
return -1;
|
||||
}
|
||||
#endif /* WITH_IP6 */
|
||||
Info1("permitting connection from %s due to lowport option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
}
|
||||
#endif /* WITH_TCP || WITH_UDP */
|
||||
|
@ -1791,12 +1820,12 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
if (result < 0) {
|
||||
char infobuff[256];
|
||||
Warn1("refusing connection from %s due to tcpwrapper option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
return -1;
|
||||
} else if (result > 0) {
|
||||
Info1("permitting connection from %s due to tcpwrapper option",
|
||||
sockaddr_info((struct sockaddr *)pa, 0,
|
||||
sockaddr_info(&pa->soa, 0,
|
||||
infobuff, sizeof(infobuff)));
|
||||
}
|
||||
#endif /* (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
|
||||
|
|
|
@ -74,13 +74,13 @@ char *xiogetifname(int ind, char *val, int ins);
|
|||
extern int retropt_socket_pf(struct opt *opts, int *pf);
|
||||
|
||||
extern int xioopen_connect(struct single *fd,
|
||||
struct sockaddr *us, size_t uslen,
|
||||
union sockaddr_union *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts,
|
||||
int pf, int socktype, int protocol,
|
||||
bool alt);
|
||||
extern int _xioopen_connect(struct single *fd,
|
||||
struct sockaddr *us, size_t uslen,
|
||||
union sockaddr_union *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts,
|
||||
int pf, int socktype, int protocol,
|
||||
|
|
|
@ -126,7 +126,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
|||
/* this cannot fork because we retrieved fork option above */
|
||||
result =
|
||||
_xioopen_connect (xfd,
|
||||
needbind?(struct sockaddr *)us:NULL, sizeof(*us),
|
||||
needbind?us:NULL, sizeof(*us),
|
||||
(struct sockaddr *)them, themlen,
|
||||
opts, pf, socktype, IPPROTO_TCP, lowport, level);
|
||||
switch (result) {
|
||||
|
|
37
xio-unix.c
37
xio-unix.c
|
@ -210,13 +210,14 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
|||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
struct single *xfd = &xxfd->stream;
|
||||
const struct opt *namedopt;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_STREAM;
|
||||
int protocol = 0;
|
||||
struct sockaddr_un them, us;
|
||||
socklen_t themlen, uslen = sizeof(us);
|
||||
bool needbind = false;
|
||||
bool opt_unlink_close = false;
|
||||
bool opt_unlink_close = true;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
|
@ -235,6 +236,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
|||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.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);
|
||||
|
@ -244,8 +246,13 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
|||
needbind = true;
|
||||
}
|
||||
|
||||
if (opt_unlink_close) {
|
||||
if ((xfd->unlink_close = strdup(name)) == NULL) {
|
||||
if (!needbind &&
|
||||
(namedopt = searchopt(opts, GROUP_NAMED, 0, 0, 0))) {
|
||||
Error1("Option \"%s\" only with bind option", namedopt->desc->defname);
|
||||
}
|
||||
|
||||
if (opt_unlink_close && needbind) {
|
||||
if ((xfd->unlink_close = strdup(us.sun_path)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
}
|
||||
xfd->opt_unlink_close = true;
|
||||
|
@ -253,7 +260,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
needbind?(union sockaddr_union *)&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, pf, socktype, protocol, false)) != 0) {
|
||||
return result;
|
||||
|
@ -269,13 +276,14 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
const struct opt *namedopt;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_DGRAM;
|
||||
int protocol = 0;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen = sizeof(us);
|
||||
bool needbind = false;
|
||||
bool opt_unlink_close = false;
|
||||
bool opt_unlink_close = true;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)",
|
||||
|
@ -303,8 +311,13 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
needbind = true;
|
||||
}
|
||||
|
||||
if (opt_unlink_close) {
|
||||
if ((xfd->unlink_close = strdup(name)) == NULL) {
|
||||
if (!needbind &&
|
||||
(namedopt = searchopt(opts, GROUP_NAMED, 0, 0, 0))) {
|
||||
Error1("Option \"%s\" only with bind option", namedopt->desc->defname);
|
||||
}
|
||||
|
||||
if (opt_unlink_close && needbind) {
|
||||
if ((xfd->unlink_close = strdup(us.un.sun_path)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
}
|
||||
xfd->opt_unlink_close = true;
|
||||
|
@ -511,6 +524,7 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
|||
int
|
||||
_xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
||||
int abstract, struct opt *opts, const char *name) {
|
||||
const struct opt *namedopt;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = 0; /* to be determined by server socket type */
|
||||
int protocol = 0;
|
||||
|
@ -540,6 +554,11 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
|||
needbind = true;
|
||||
}
|
||||
|
||||
if (!needbind &&
|
||||
(namedopt = searchopt(opts, GROUP_NAMED, 0, 0, 0))) {
|
||||
Error1("Option \"%s\" only with bind option", namedopt->desc->defname);
|
||||
}
|
||||
|
||||
if (opt_unlink_close) {
|
||||
if ((xfd->unlink_close = strdup(name)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
|
@ -553,8 +572,8 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
|||
/* xfd->dtype = DATA_STREAM; // is default */
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
needbind?&us:NULL, uslen,
|
||||
&them.soa, themlen,
|
||||
opts, pf, socktype?socktype:SOCK_STREAM, protocol,
|
||||
false)) != 0) {
|
||||
if (errno == EPROTOTYPE) {
|
||||
|
|
25
xioopts.c
25
xioopts.c
|
@ -2514,6 +2514,31 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* look for an option with the given properties
|
||||
return a pointer to the first matching valid option in the list
|
||||
Returns NULL when no matching option found */
|
||||
const struct opt *searchopt(const struct opt *opts, unsigned int groups, enum e_phase from, enum e_phase to,
|
||||
enum e_func func) {
|
||||
int i;
|
||||
|
||||
if (!opts) return NULL;
|
||||
|
||||
/* remember: struct opt are in an array */
|
||||
i = 0;
|
||||
while (opts[i].desc != ODESC_END) {
|
||||
if (opts[i].desc != ODESC_DONE &&
|
||||
(groups == 0 || (groups && (opts[i].desc->group&groups))) &&
|
||||
(from == 0 || (from <= opts[i].desc->phase)) &&
|
||||
(to == 0 || (opts[i].desc->phase <= to)) &&
|
||||
(func == 0 || (opts[i].desc->func == func))) {
|
||||
return &opts[i];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy the already parsed options for repeated application, but only those
|
||||
matching groups ANY and <groups> */
|
||||
struct opt *copyopts(const struct opt *opts, unsigned int groups) {
|
||||
|
|
|
@ -932,6 +932,8 @@ extern int parseopts(const char **a, unsigned int groups, struct opt **opts);
|
|||
extern int parseopts_table(const char **a, unsigned int groups,
|
||||
struct opt **opts,
|
||||
const struct optname optionnames[], size_t optionnum);
|
||||
extern const struct opt *searchopt(const struct opt *opts, unsigned int groups, enum e_phase from, enum e_phase to,
|
||||
enum e_func func);
|
||||
extern struct opt *copyopts(const struct opt *opts, unsigned int groups);
|
||||
extern struct opt *moveopts(struct opt *opts, unsigned int groups);
|
||||
extern int leftopts(const struct opt *opts);
|
||||
|
|
Loading…
Reference in a new issue