socat/0004-udp-listen-bind4.patch

276 lines
7.6 KiB
Diff
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/CHANGES b/CHANGES
index 5afbc74..fdc6b04 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,10 @@

+Corrections:
+ With version 1.8.0.0, the following command failed:
+ socat UDP-LISTEN:1234,fork,reuseaddr,bind=127.0.0.1 -
+ Message: "E xioopen_ipdgram_listen(): unknown address family 0":
+ Thanks to Brian Woo for reporting this issue.
+
####################### V 1.8.0.0
Security:
diff --git a/test.sh b/test.sh
index f70ad89..1d5298b 100755
--- a/test.sh
+++ b/test.sh
@@ -2977,19 +2977,21 @@ echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
rc2=$?
kill $pid1 2>/dev/null; wait
if [ $rc2 -ne 0 ]; then
- $PRINTF "$FAILED: $TRACE $SOCAT:\n"
+ $PRINTF "$FAILED (rc2=$rc2)\n"
echo "$CMD1 &"
+ cat "${te}1" >&2
echo "$CMD2"
- cat "${te}1" "${te}2"
+ cat "${te}2" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
- $PRINTF "$FAILED\n"
+ $PRINTF "$FAILED (diff)\n"
echo "$CMD1 &"
- cat "${te}1"
+ cat "${te}1" >&2
echo "$CMD2"
- cat "${te}2"
- cat "$tdiff"
+ cat "${te}2" >&2
+ echo "// diff:" >&2
+ cat "$tdiff" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
else
@@ -3028,15 +3030,21 @@ echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
rc2=$?
kill $pid1 2>/dev/null; wait
if [ $rc2 -ne 0 ]; then
- $PRINTF "$FAILED: $TRACE $SOCAT:\n"
+ $PRINTF "$FAILED (rc2=$rc2)\n"
echo "$CMD1 &"
+ cat "${te}1" >&2
echo "$CMD2"
- cat "${te}1" "${te}2"
+ cat "${te}2" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
- $PRINTF "$FAILED\n"
- cat "$tdiff"
+ $PRINTF "$FAILED (diff)\n"
+ echo "$CMD1 &"
+ cat "${te}1" >&2
+ echo "$CMD2"
+ cat "${te}2" >&2
+ echo "// diff:" >&2
+ cat "$tdiff" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
else
@@ -19154,6 +19162,76 @@ esac
N=$((N+1))
+# Test UDP-LISTEN with bind to IPv4 address; this failed with Socat version
+# 1.8.0.0
+NAME=UDP_LISTEN_BIND4
+case "$TESTS" in
+*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%ip4%*|*%udp%*|*%udp4%*|*%listen%*|*%$NAME%*)
+TEST="$NAME: Test UDP-LISTEN with bind to IPv4 addr"
+# Start a listener with UDP-LISTEN and bind to 127.0.0.1; when it starts
+# without error and even processes data the test succeeded
+if ! eval $NUMCOND; then :
+# Remove unneeded checks, adapt lists of the remaining ones
+elif ! cond=$(checkconds \
+ "" \
+ "" \
+ "" \
+ "IP4 UDP LISTEN STDIO PIPE" \
+ "UDP-LISTEN PIPE STDIO UDP" \
+ "bind" \
+ "udp4" ); then
+ $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
+ numCANT=$((numCANT+1))
+ listCANT="$listCANT $N"
+ namesCANT="$namesCANT $NAME"
+else
+ tf="$td/test$N.stdout"
+ te="$td/test$N.stderr"
+ tdiff="$td/test$N.diff"
+ da="test$N $(date) $RANDOM"
+ newport udp4
+ CMD0="$TRACE $SOCAT $opts UDP-LISTEN:$PORT,bind=$LOCALHOST4 PIPE"
+ CMD1="$TRACE $SOCAT $opts - UDP-CONNECT:$LOCALHOST4:$PORT"
+ printf "test $F_n $TEST... " $N
+ $CMD0 >/dev/null 2>"${te}0" &
+ pid0=$!
+ waitudp4port $PORT 1
+ echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
+ rc1=$?
+ kill $pid0 2>/dev/null; wait
+ if [ "$rc1" -ne 0 ]; then
+ $PRINTF "$FAILED (rc1=$rc1)\n"
+ echo "$CMD0 &"
+ cat "${te}0" >&2
+ echo "$CMD1"
+ cat "${te}1" >&2
+ numFAIL=$((numFAIL+1))
+ listFAIL="$listFAIL $N"
+ namesFAIL="$namesFAIL $NAME"
+ elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
+ $PRINTF "$FAILED (diff)\n"
+ echo "$CMD0 &"
+ cat "${te}0" >&2
+ echo "$CMD1"
+ cat "${te}1" >&2
+ echo "// diff:" >&2
+ cat "$tdiff" >&2
+ numFAIL=$((numFAIL+1))
+ listFAIL="$listFAIL $N"
+ namesFAIL="$namesFAIL $NAME"
+ else
+ $PRINTF "$OK\n"
+ if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+ if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
+ if [ "$VERBOSE" ]; then echo "$CMD1"; fi
+ if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
+ numOK=$((numOK+1))
+ fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
# end of common tests
##################################################################################
diff --git a/xio-socket.c b/xio-socket.c
index c869b6d..ed10a99 100644
--- a/xio-socket.c
+++ b/xio-socket.c
@@ -262,7 +262,7 @@ static int xioopen_socket_connect(
sfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM;
socket_init(0, &us);
- if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3,
+ if (retropt_bind(opts, pf, socktype, proto, (struct sockaddr *)&us, &uslen, 0,
sfd->para.socket.ip.ai_flags)
!= STAT_NOACTION) {
needbind = true;
diff --git a/xio-udp.c b/xio-udp.c
index b624281..d511122 100644
--- a/xio-udp.c
+++ b/xio-udp.c
@@ -277,8 +277,10 @@ int xioopen_ipdgram_listen(
int pf = addrdesc->arg1;
int ipproto = addrdesc->arg2;
union sockaddr_union us;
+ int bind_rc;
int socktype = SOCK_DGRAM;
socklen_t uslen;
+ int result;
if (argc != 2) {
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
@@ -308,12 +310,31 @@ int xioopen_ipdgram_listen(
applyopts(sfd, -1, opts, PH_INIT);
uslen = socket_init(pf, &us);
- retropt_bind(opts, pf, socktype, ipproto,
+ bind_rc = retropt_bind(opts, pf, socktype, ipproto,
(struct sockaddr *)&us, &uslen, 1,
xfd->stream.para.socket.ip.ai_flags);
+ if (bind_rc == STAT_NORETRY)
+ return STAT_NORETRY;
+ if (pf == PF_UNSPEC && bind_rc == STAT_OK)
+ pf = us.soa.sa_family;
if (false) {
;
+#if WITH_IP4 || WITH_IP6
+ } else if (pf == PF_UNSPEC && bind_rc == STAT_NOACTION) {
+ int ai_flags[2];
+ ai_flags[0] = sfd->para.socket.ip.ai_flags[0];
+ ai_flags[1] = sfd->para.socket.ip.ai_flags[1];
+ if (!(ai_flags[1] & AI_PASSIVE))
+ ai_flags[0] |= AI_PASSIVE;
+ result =
+ xioresolve(NULL, portname, pf, socktype, ipproto, &us, &uslen, ai_flags);
+ if (result != STAT_OK) {
+ Error("error resolving bind option");
+ return STAT_NORETRY;
+ }
+ pf = us.soa.sa_family;
+#endif /* WITH_IP4 || WITH_IP6*/
#if WITH_IP4
} else if (pf == PF_INET) {
us.ip4.sin_port = parseport(portname, ipproto);
@@ -323,7 +344,9 @@ int xioopen_ipdgram_listen(
us.ip6.sin6_port = parseport(portname, ipproto);
#endif
} else {
+#if 1
Error1("xioopen_ipdgram_listen(): unknown address family %d", pf);
+#endif
}
return _xioopen_ipdgram_listen(&xfd->stream, xioflags, &us, uslen,
diff --git a/xioopts.c b/xioopts.c
index 4b651aa..abf4ffe 100644
--- a/xioopts.c
+++ b/xioopts.c
@@ -3252,6 +3252,7 @@ int retropt_bind(struct opt *opts,
UNIX (or'd): 1..tight
2..abstract
4..templatename
+ 0..generic addr spec
*/
const int ai_flags[2])
{
@@ -3271,10 +3272,13 @@ int retropt_bind(struct opt *opts,
}
bindp = bindname;
- switch (af) {
+#if WITH_IP4 && WITH_IP6
+ /* Try to derive address family from string */
+ if (af == AF_UNSPEC && bindname[0] == '[')
+ af = AF_INET6;
+#endif /* WITH_IP4 && WITH_IP6 */
- case AF_UNSPEC:
- {
+ if (feats == 0) {
size_t p = 0;
dalan(bindname, (uint8_t *)sa->sa_data, &p, *salen-sizeof(sa->sa_family), 'i');
*salen = p + sizeof(sa->sa_family);
@@ -3286,10 +3290,13 @@ int retropt_bind(struct opt *opts,
#if HAVE_STRUCT_SOCKADDR_SALEN
sa->sa_len = *salen;
#endif
- }
- break;
+ return STAT_OK;
+ }
+
+ switch (af) {
#if WITH_IP4 || WITH_IP6 || WITH_VSOCK
+ case AF_UNSPEC:
#if WITH_VSOCK
case AF_VSOCK:
#endif
@@ -3324,7 +3331,7 @@ int retropt_bind(struct opt *opts,
ai_flags2[0] = ai_flags[0];
ai_flags2[1] = ai_flags[1];
if (!(ai_flags2[1] & AI_PASSIVE))
- ai_flags2[0] |= AI_PASSIVE;
+ ai_flags2[0] |= AI_PASSIVE;
if ((result =
xioresolve(hostname[0]!='\0'?hostname:NULL, portp,