mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Mechanism for ai-* options; new option ai-addrconfig
This commit is contained in:
parent
8b2e0593f3
commit
4e00a345b4
28 changed files with 492 additions and 285 deletions
6
CHANGES
6
CHANGES
|
@ -78,6 +78,12 @@ Features:
|
|||
configure option --with-default-ipv allows to specify at build time if
|
||||
IPv4, IPv6, or none of these is the preferred default.
|
||||
|
||||
Socat options -4 and -6 have been reworked.
|
||||
Tests: TCP_ENV6 TCP_DASH6
|
||||
|
||||
New option ai-addrconfig disables name resolution to protocol families
|
||||
that are not configured on the computer (e.g. IPv6)
|
||||
|
||||
Corrections:
|
||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
||||
0, its last sent data might have been lost depending on timing of read/
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"1.7.4.5+"
|
||||
"1.7.4.5+conn-over"
|
||||
|
|
17
doc/socat.yo
17
doc/socat.yo
|
@ -218,10 +218,10 @@ label(option_W)dit(bf(tt(-W))tt(<lockfile>))
|
|||
If lockfile exists, waits until it disappears. When lockfile does not exist,
|
||||
creates it and continues, unlinks lockfile on exit.
|
||||
label(option_4)dit(bf(tt(-4)))
|
||||
Use IP version 4 in case that the addresses do not implicitly or explicitly
|
||||
Use IP version 4 in case the addresses do not implicitly or explicitly
|
||||
specify a version; this is the default.
|
||||
label(option_6)dit(bf(tt(-6)))
|
||||
Use IP version 6 in case that the addresses do not implicitly or explicitly
|
||||
Use IP version 6 in case the addresses do not implicitly or explicitly
|
||||
specify a version.
|
||||
label(option_statistics)dit(bf(tt(--statistics)))
|
||||
Logs transfer statistics (bytes and blocks counters for both directions)
|
||||
|
@ -2240,6 +2240,11 @@ label(OPTOIN_IP_TRANSPARENT)
|
|||
dit(bf(tt(ip-transparent)))
|
||||
Sets the IP_TRANSPARENT socket option.
|
||||
This option might require root privilege.
|
||||
label(OPTION_AI_ADDRCONFIG)
|
||||
dit(bf(tt(ai-addrconfig[=0|1]))), dit(bf(tt(addrconfig[=0|1])))
|
||||
Sets or unsets the AI_ADDRCONFIG flag to prevent name resolution to address
|
||||
families that are not configured (e.g. IPv6). Default value is 1 in case the
|
||||
resolver does not get an address family hint.
|
||||
label(OPTION_RES_DEBUG)dit(bf(tt(res-debug)))
|
||||
label(OPTION_RES_AAONLY)dit(bf(tt(res-aaonly)))
|
||||
label(OPTION_RES_USEVC)dit(bf(tt(res-usevc)))
|
||||
|
@ -2249,10 +2254,10 @@ label(OPTION_RES_RECURSE)dit(bf(tt(res-recurse)))
|
|||
label(OPTION_RES_DEFNAMES)dit(bf(tt(res-defnames)))
|
||||
label(OPTION_RES_STAYOPEN)dit(bf(tt(res-stayopen)))
|
||||
label(OPTION_RES_DNSRCH)dit(bf(tt(res-dnsrch)))
|
||||
These options set the corresponding resolver (name resolution) option flags.
|
||||
Append "=0" to clear a default option. See man NOEXPAND(resolver(5)) for more
|
||||
information on these options. Note: these options are valid only for the
|
||||
address they are applied to.
|
||||
These options temporarily set the corresponding resolver (name resolution)
|
||||
option flags. Append "=0" to clear a default option. See man
|
||||
NOEXPAND(resolver(5)) for more information on these options. These flags are
|
||||
per process, however socat() restores the old values after name resolution.
|
||||
|
||||
enddit()
|
||||
|
||||
|
|
2
sycls.c
2
sycls.c
|
@ -1445,7 +1445,7 @@ struct hostent *Gethostbyname(const char *name) {
|
|||
int Getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints, struct addrinfo **res) {
|
||||
int result;
|
||||
Debug15("getaddrinfo(%s%s%s, %s%s%s, {%d,%d,%d,%d,"F_socklen",%p,%p,%p}, %p)",
|
||||
Debug15("getaddrinfo(%s%s%s, %s%s%s, {0x%02x,%d,%d,%d,"F_socklen",%p,%p,%p}, %p)",
|
||||
node?"\"":"", node?node:"NULL", node?"\"":"",
|
||||
service?"\"":"", service?service:"NULL", service?"\"":"",
|
||||
hints->ai_flags, hints->ai_family, hints->ai_socktype,
|
||||
|
|
217
test.sh
217
test.sh
|
@ -173,6 +173,7 @@ SOL_SOCKET="$($PROCAN -c |grep "^#define[[:space:]]*SOL_SOCKET[[:space:]]" |cut
|
|||
SO_REUSEADDR="$($PROCAN -c |grep "^#define[[:space:]]*SO_REUSEADDR[[:space:]]" |cut -d' ' -f3)"
|
||||
TCP_MAXSEG="$($PROCAN -c |grep "^#define[[:space:]]*TCP_MAXSEG[[:space:]]" |cut -d' ' -f3)"
|
||||
SIZE_T=$($PROCAN |grep size_t |awk '{print($3);}')
|
||||
#AI_ADDRCONFIG=; if [ "$($SOCAT -hhh |grep ai-addrconfig)" ]; then AI_ADDRCONFIG="ai-addrconfig=0"; fi
|
||||
|
||||
# SSL certificate contents
|
||||
TESTCERT_CONF=testcert.conf
|
||||
|
@ -2089,8 +2090,20 @@ case "$TESTS" in
|
|||
*%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%listen%*|*%$NAME%*)
|
||||
TEST="$NAME: echo via connection to TCP V6 socket"
|
||||
if ! eval $NUMCOND; then :;
|
||||
elif ! testfeats tcp ip6 >/dev/null || ! runsip6 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N
|
||||
elif ! F=$(testfeats IP6 TCP LISTEN STDIO PIPE); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! A=$(testaddrs - TCP6-LISTEN PIPE STDIN STDOUT TCP6-CONNECT); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! o=$(testoptions so-reuseaddr ) >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! runsip6 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv6 not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
|
@ -2101,27 +2114,36 @@ newport tcp6; tsl=$PORT
|
|||
ts="[::1]:$tsl"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD1="$TRACE $SOCAT $opts TCP6-LISTEN:$tsl,$REUSEADDR PIPE"
|
||||
CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP6:$ts"
|
||||
CMD2="$TRACE $SOCAT $opts STDIN!!STDOUT TCP6:$ts"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD1 >"$tf" 2>"${te}1" &
|
||||
pid=$! # background process id
|
||||
waittcp6port $tsl 1
|
||||
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
|
||||
if [ $? -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||
echo "$CMD1 &"
|
||||
echo "$CMD2"
|
||||
cat "$te"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||
echo "$CMD1 &"
|
||||
cat "${te}1" >&2
|
||||
echo "$CMD2"
|
||||
cat "${te}2" >&2
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED: diff:\n"
|
||||
cat "$tdiff"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
$PRINTF "$FAILED: diff:\n"
|
||||
echo "$CMD1 &"
|
||||
cat "${te}1" >&2
|
||||
echo "$CMD2"
|
||||
cat "${te}2" >&2
|
||||
echo diff:
|
||||
cat "$tdiff"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
||||
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
|
||||
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||
numOK=$((numOK+1))
|
||||
fi
|
||||
kill $pid 2>/dev/null
|
||||
|
@ -2131,17 +2153,26 @@ N=$((N+1))
|
|||
#set +vx
|
||||
|
||||
|
||||
# Test if TCP client with IPv4 address connects to IPv4 port
|
||||
NAME=TCPX4
|
||||
case "$TESTS" in
|
||||
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%listen%*|*%$NAME%*)
|
||||
TEST="$NAME: echo via connection to TCP socket, v4 by target"
|
||||
if ! eval $NUMCOND; then :;
|
||||
elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N
|
||||
elif ! F=$(testfeats STDIO PIPE IP4 TCP LISTEN); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N
|
||||
elif ! A=$(testaddrs TCP TCP-LISTEN STDIN STDOUT PIPE); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! o=$(testoptions pf) >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! runsip4 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
|
@ -2151,29 +2182,39 @@ tdiff="$td/test$N.diff"
|
|||
newport tcp4; tsl=$PORT
|
||||
ts="127.0.0.1:$tsl"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD1="$TRACE $SOCAT $opts TCP-LISTEN:$tsl,pf=ip4,$REUSEADDR PIPE"
|
||||
CMD2="$TRACE $SOCAT $opts STDIN!!STDOUT TCP:$ts"
|
||||
CMD0="$TRACE $SOCAT $opts TCP-LISTEN:$tsl,pf=ip4,$REUSEADDR PIPE"
|
||||
CMD1="$TRACE $SOCAT $opts STDIN!!STDOUT TCP:$ts"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD1 >"$tf" 2>"${te}1" &
|
||||
$CMD0 >"$tf" 2>"${te}0" &
|
||||
pid=$! # background process id
|
||||
waittcp4port $tsl 1
|
||||
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
|
||||
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
|
||||
if [ $? -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||
echo "$CMD1 &"
|
||||
echo "$CMD2"
|
||||
cat "$te"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\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" >"$tdiff"; then
|
||||
$PRINTF "$FAILED: diff:\n"
|
||||
cat "$tdiff"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
$PRINTF "$FAILED: diff:\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0" >&2
|
||||
echo "$CMD1"
|
||||
cat "${te}1" >&2
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
namesFAIL="$namesFAIL $NAME"
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
||||
numOK=$((numOK+1))
|
||||
$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
|
||||
kill $pid 2>/dev/null
|
||||
fi
|
||||
|
@ -2181,17 +2222,26 @@ esac
|
|||
N=$((N+1))
|
||||
|
||||
|
||||
# Test if TCP client with IPv6 address connects to IPv6 port
|
||||
NAME=TCPX6
|
||||
case "$TESTS" in
|
||||
*%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%listen%*|*%$NAME%*)
|
||||
TEST="$NAME: echo via connection to TCP socket, v6 by target"
|
||||
if ! eval $NUMCOND; then :;
|
||||
elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N
|
||||
elif ! F=$(testfeats STDIO PIPE IP6 TCP LISTEN); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N
|
||||
elif ! A=$(testaddrs TCP TCP-LISTEN STDIN STDOUT PIPE); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! o=$(testoptions pf) >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! runsip6 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv6 not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
|
@ -2201,29 +2251,39 @@ tdiff="$td/test$N.diff"
|
|||
newport tcp6; tsl=$PORT
|
||||
ts="[::1]:$tsl"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD1="$TRACE $SOCAT $opts TCP-LISTEN:$tsl,pf=ip6,$REUSEADDR PIPE"
|
||||
CMD2="$TRACE $SOCAT $opts STDIN!!STDOUT TCP:$ts"
|
||||
CMD0="$TRACE $SOCAT $opts TCP-LISTEN:$tsl,pf=ip6,$REUSEADDR PIPE"
|
||||
CMD1="$TRACE $SOCAT $opts STDIN!!STDOUT TCP:$ts"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD1 >"$tf" 2>"${te}1" &
|
||||
$CMD0 >"$tf" 2>"${te}0" &
|
||||
pid=$! # background process id
|
||||
waittcp6port $tsl 1
|
||||
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
|
||||
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
|
||||
if [ $? -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||
echo "$CMD1 &"
|
||||
echo "$CMD2"
|
||||
cat "$te"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\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" >"$tdiff"; then
|
||||
$PRINTF "$FAILED: diff:\n"
|
||||
cat "$tdiff"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
$PRINTF "$FAILED: diff:\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0" >&2
|
||||
echo "$CMD1"
|
||||
cat "${te}1" >&2
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
namesFAIL="$namesFAIL $NAME"
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
||||
numOK=$((numOK+1))
|
||||
$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
|
||||
kill $pid 2>/dev/null
|
||||
fi
|
||||
|
@ -8298,7 +8358,7 @@ newport udp6; ts1p=$PORT
|
|||
if1="$MCINTERFACE"
|
||||
ts1a="[::1]"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD1="$TRACE $SOCAT -u $opts UDP6-RECV:$ts1p,reuseaddr,ipv6-join-group=[ff02::2]:$if1 -"
|
||||
CMD1="$TRACE $SOCAT -u $opts UDP6-RECV:$ts1p,$REUSEADDR,ipv6-join-group=[ff02::2]:$if1 -"
|
||||
#CMD2="$TRACE $SOCAT -u $opts - UDP6-SENDTO:[ff02::2]:$ts1p,bind=$ts1a"
|
||||
CMD2="$TRACE $SOCAT -u $opts - UDP6-SENDTO:[ff02::2]:$ts1p"
|
||||
printf "test $F_n $TEST... " $N
|
||||
|
@ -13589,7 +13649,7 @@ tf="$td/test$N.stdout"
|
|||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$TRACE $SOCAT $opts FILE:/dev/null OPENSSL-CONNECT:$SNISERVER:443"
|
||||
CMD0="$TRACE $SOCAT $opts FILE:/dev/null OPENSSL-CONNECT:$SNISERVER:443,pf=ip4"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 >/dev/null 2>"${te}0"
|
||||
rc0=$?
|
||||
|
@ -15177,7 +15237,7 @@ tf="$td/test$N.stdout"
|
|||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$TRACE $SOCAT $opts -t 3 $PROTO-RECVFROM:$tsl,fork SYSTEM:'read t x; sleep \$t; echo \$x >>'\"$tf\""
|
||||
CMD0="$TRACE $SOCAT $opts -t 3 $PROTO-RECVFROM:$tsl,fork SYSTEM:'read t x; sleep \$t; echo \\\"\$x\\\" >>'\"$tf\""
|
||||
CMD1="$TRACE $SOCAT $opts -t 3 - $PROTO-SENDTO:$tsc"
|
||||
printf "test $F_n $TEST... " $N
|
||||
eval $CMD0 </dev/null 2>"${te}0" &
|
||||
|
@ -15947,6 +16007,7 @@ newport tcp6
|
|||
CMD0a="$TRACE $SOCAT $opts -lp server1 -6 OPENSSL-LISTEN:$PORT,cert=testsrv.crt,key=testsrv.key,verify=0 PIPE"
|
||||
CMD0b="$TRACE $SOCAT $opts -lp server2 -6 OPENSSL-LISTEN:$PORT,accept-timeout=.01,cert=testsrv.crt,key=testsrv.key,verify=0 PIPE"
|
||||
CMD1="$TRACE $SOCAT $opts -lp client -6 -T 0.1 PIPE OPENSSL-CONNECT:$LOCALHOST6:$PORT,verify=0"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0a >/dev/null 2>"${te}0a" &
|
||||
pid0=$!
|
||||
waittcp6port $PORT 1
|
||||
|
@ -16077,8 +16138,8 @@ TEST="$NAME: try all available TCP4 addresses"
|
|||
# that is closed on both addresses.
|
||||
# The test succeeded when the log shows that Socat tried to connect two times.
|
||||
if ! eval $NUMCOND; then :;
|
||||
elif [ -z "$FOREIGN" ]; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N
|
||||
elif ! $(type nslookup >/dev/null 2>&1); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}nslookup not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
#elif ! $(type nslookup >/dev/null 2>&1) && ! $(type host >/dev/null 2>&1); then
|
||||
|
@ -16097,6 +16158,10 @@ elif ! runsip4 >/dev/null; then
|
|||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif [ -z "$FOREIGN" ]; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
|
@ -16162,7 +16227,7 @@ elif [ -z "$FOREIGN" ]; then # only needs Internet DNS
|
|||
# $PRINTF "test $F_n $TEST... ${YELLOW}nslookup and host not available${NORMAL}\n" $N
|
||||
# numCANT=$((numCANT+1))
|
||||
# listCANT="$listCANT $N"
|
||||
elif ! F=$(testfeats ip4 ip6 tcp); then
|
||||
elif ! F=$(testfeats IP4 IP6 TCP); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
|
@ -16178,6 +16243,10 @@ elif ! runsip6 >/dev/null; then
|
|||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv6 not available or not routable${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif [ -z "$FOREIGN" ]; then # only needs Internet DNS
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
|
@ -16185,10 +16254,18 @@ tdiff="$td/test$N.diff"
|
|||
da="test$N $(date) $RANDOM"
|
||||
LOCALHOST_4_6=localhost-4-6.dest-unreach.net
|
||||
if type nslookup >/dev/null 2>&1; then
|
||||
ADDRS=$(nslookup server-4.dest-unreach.net. |sed -n '/^$/,$ p' |grep ^Address |awk '{print($2);}')
|
||||
ADDRS=$(nslookup $LOCALHOST_4_6 |sed -n '/^$/,$ p' |grep ^Address |awk '{print($2);}')
|
||||
elif type host >/dev/null 2>&1; then
|
||||
ADDRS=$(host server-4.dest-unreach.net. |sed 's/.*address //')
|
||||
ADDRS=$(host $LOCALHOST_4_6 |sed 's/.*address //')
|
||||
fi
|
||||
# Specific config: on Ubuntu-12.04: getaddrinfo(...AI_ADDRCONFIG) does not
|
||||
# resolve to IPv6 addresses even when there are link local IPv6 addresses
|
||||
if test -f /etc/os-release &&
|
||||
grep -q '^NAME="Ubuntu"' /etc/os-release &&
|
||||
grep -q '^VERSION="12\.04' /etc/os-release; then
|
||||
AI_ADDRCONFIG="ai-addrconfig=0,"
|
||||
fi
|
||||
# Check if PORT is really closed on both addresses
|
||||
while true; do
|
||||
OPEN=
|
||||
for addr in $ADDRS; do
|
||||
|
@ -16196,7 +16273,7 @@ while true; do
|
|||
*.*) ;;
|
||||
*:*) addr="[$addr]" ;
|
||||
esac
|
||||
if $SOCAT /dev/null TCP:$addr:$PORT 2>/dev/null; then
|
||||
if $SOCAT /dev/null TCP:$addr:$PORT,$AI_ADDRCONFIG 2>/dev/null; then
|
||||
# port is open :-(
|
||||
OPEN=1
|
||||
break
|
||||
|
@ -16207,7 +16284,7 @@ while true; do
|
|||
fi
|
||||
newport tcp4
|
||||
done
|
||||
CMD="$TRACE $SOCAT $opts -d -d /dev/null TCP:localhost-4-6.dest-unreach.net:$PORT"
|
||||
CMD="$TRACE $SOCAT $opts -d -d /dev/null TCP:$LOCALHOST_4_6:$PORT,$AI_ADDRCONFIG"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD >/dev/null 2>"${te}"
|
||||
rc=$?
|
||||
|
@ -16378,8 +16455,8 @@ elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then
|
|||
$PRINTF "test $F_n $TEST... ${YELLOW}Must be root${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! $(type systemd-socket-activate >/dev/null 2>&1); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}systemd-socket-activate not available${NORMAL}\n" $N
|
||||
elif ! $(type nslookup >/dev/null 2>&1); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}nslookup not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! F=$(testfeats STDIO IP4 TCP PIPE); then
|
||||
|
@ -16398,6 +16475,10 @@ elif ! runsip4 >/dev/null; then
|
|||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! runsip4 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif [ -z "$FOREIGN" ]; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
|
|
94
xio-ip.c
94
xio-ip.c
|
@ -81,6 +81,10 @@ const struct optdesc opt_ip_recvdstaddr = { "ip-recvdstaddr", "recvdstaddr",OPT_
|
|||
const struct optdesc opt_ip_recvif = { "ip-recvif", "recvdstaddrif",OPT_IP_RECVIF, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVIF };
|
||||
#endif
|
||||
|
||||
#ifdef AI_ADDRCONFIG
|
||||
const struct optdesc opt_ai_addrconfig = { "ai-addrconfig", "addrconfig", OPT_AI_ADDRCONFIG, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_ADDRCONFIG };
|
||||
#endif
|
||||
|
||||
#if WITH_RES_DEPRECATED
|
||||
# define WITH_RES_AAONLY 1
|
||||
# define WITH_RES_PRIMARY 1
|
||||
|
@ -153,8 +157,8 @@ unsigned long res_opts() {
|
|||
*/
|
||||
int xiogetaddrinfo(const char *node, const char *service,
|
||||
int family, int socktype, int protocol,
|
||||
struct addrinfo **res,
|
||||
unsigned long res_opts0, unsigned long res_opts1) {
|
||||
struct addrinfo **res, const int ai_flags[2],
|
||||
const unsigned long res_opts[2]) {
|
||||
char *numnode = NULL;
|
||||
size_t nodelen;
|
||||
unsigned long save_res_opts = 0;
|
||||
|
@ -166,13 +170,13 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
int error_num;
|
||||
|
||||
#if HAVE_RESOLV_H
|
||||
if (res_opts0 | res_opts1) {
|
||||
if (res_opts[0] | res_opts[1]) {
|
||||
if (!(_res.options & RES_INIT)) {
|
||||
Res_init(); /*!!! returns -1 on error */
|
||||
}
|
||||
save_res_opts = _res.options;
|
||||
_res.options &= ~res_opts0;
|
||||
_res.options |= res_opts1;
|
||||
_res.options |= res_opts[0];
|
||||
_res.options &= ~res_opts[1];
|
||||
Debug2("changed _res.options from 0x%lx to 0x%lx",
|
||||
save_res_opts, _res.options);
|
||||
}
|
||||
|
@ -203,9 +207,8 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
} else if (node && node[0] == '[' && node[(nodelen=strlen(node))-1]==']') {
|
||||
if ((numnode = Malloc(nodelen-1)) == NULL) {
|
||||
#if HAVE_RESOLV_H
|
||||
if (res_opts0 | res_opts1) {
|
||||
_res.options = (_res.options & (~res_opts0&~res_opts1) |
|
||||
save_res_opts& ( res_opts0| res_opts1));
|
||||
if (res_opts[0] | res_opts[1]) {
|
||||
_res.options = save_res_opts;
|
||||
}
|
||||
#endif
|
||||
return STAT_NORETRY;
|
||||
|
@ -219,12 +222,17 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
if (family == PF_UNSPEC) family = PF_INET6;
|
||||
#endif /* WITH_IP6 */
|
||||
}
|
||||
|
||||
if (family == 0)
|
||||
hints.ai_flags |= AI_ADDRCONFIG;
|
||||
hints.ai_flags |= AI_PASSIVE /* important for IPv4+IPv6 listen */;
|
||||
#if HAVE_GETADDRINFO
|
||||
if (node != NULL || service != NULL) {
|
||||
struct addrinfo *record;
|
||||
|
||||
hints.ai_flags |= AI_PASSIVE; /* important for IPv4+IPv6 listen */
|
||||
if (ai_flags != NULL) {
|
||||
hints.ai_flags |= ai_flags[0];
|
||||
hints.ai_flags &= ~ai_flags[1];
|
||||
}
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = socktype;
|
||||
hints.ai_protocol = protocol;
|
||||
|
@ -256,7 +264,7 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
continue;
|
||||
}
|
||||
if ((error_num = Getaddrinfo(node, service, &hints, res)) != 0) {
|
||||
Error7("getaddrinfo(\"%s\", \"%s\", {%d,%d,%d,%d}, {}): %s",
|
||||
Error7("getaddrinfo(\"%s\", \"%s\", {0x%02x,%d,%d,%d}, {}): %s",
|
||||
node?node:"NULL", service?service:"NULL",
|
||||
hints.ai_flags, hints.ai_family,
|
||||
hints.ai_socktype, hints.ai_protocol,
|
||||
|
@ -265,9 +273,8 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
if (numnode) free(numnode);
|
||||
|
||||
#if HAVE_RESOLV_H
|
||||
if (res_opts0 | res_opts1) {
|
||||
_res.options = (_res.options & (~res_opts0&~res_opts1) |
|
||||
save_res_opts& ( res_opts0| res_opts1));
|
||||
if (res_opts[0] | res_opts[1]) {
|
||||
_res.options = save_res_opts;
|
||||
}
|
||||
#endif
|
||||
return STAT_RETRYLATER;
|
||||
|
@ -364,9 +371,8 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
h_errno == NETDB_INTERNAL ? strerror(errno) :
|
||||
hstrerror(h_errno));
|
||||
#if HAVE_RESOLV_H
|
||||
if (res_opts0 | res_opts1) {
|
||||
_res.options = (_res.options & (~res_opts0&~res_opts1) |
|
||||
save_res_opts& ( res_opts0| res_opts1));
|
||||
if (res_opts[0] | res_opts[1]) {
|
||||
_res.options = save_res_opts;
|
||||
}
|
||||
#endif
|
||||
return STAT_RETRYLATER;
|
||||
|
@ -399,9 +405,8 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
if (numnode) free(numnode);
|
||||
|
||||
#if HAVE_RESOLV_H
|
||||
if (res_opts0 | res_opts1) {
|
||||
_res.options = (_res.options & (~res_opts0&~res_opts1) |
|
||||
save_res_opts& ( res_opts0| res_opts1));
|
||||
if (res_opts[0] | res_opts[1]) {
|
||||
_res.options = save_res_opts;
|
||||
}
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
return STAT_OK;
|
||||
|
@ -423,12 +428,13 @@ void xiofreeaddrinfo(struct addrinfo *res) {
|
|||
int xioresolve(const char *node, const char *service,
|
||||
int family, int socktype, int protocol,
|
||||
union sockaddr_union *addr, socklen_t *addrlen,
|
||||
unsigned long res_opts0, unsigned long res_opts1) {
|
||||
const int ai_flags[2], const unsigned long res_opts[2])
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
int rc;
|
||||
|
||||
rc = xiogetaddrinfo(node, service, family, socktype, protocol,
|
||||
&res, res_opts0, res_opts1);
|
||||
&res, ai_flags, res_opts);
|
||||
if (rc != 0) {
|
||||
xiofreeaddrinfo(res);
|
||||
return -1;
|
||||
|
@ -760,12 +766,12 @@ mc:addr
|
|||
union sockaddr_union sockaddr2;
|
||||
socklen_t socklen2 = sizeof(sockaddr2.ip4);
|
||||
|
||||
/* first parameter is alway multicast address */
|
||||
/* First parameter is always multicast address */
|
||||
/*! result */
|
||||
xioresolve(opt->value.u_string/*multiaddr*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1, 0, 0);
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1,
|
||||
xfd->para.socket.ip.ai_flags, xfd->para.socket.ip.res_opts);
|
||||
ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
|
||||
if (0) {
|
||||
; /* for canonical reasons */
|
||||
|
@ -774,9 +780,10 @@ mc:addr
|
|||
/* three parameters */
|
||||
/* second parameter is interface address */
|
||||
xioresolve(opt->value2.u_string/*param2*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2, 0, 0);
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts);
|
||||
ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
|
||||
/* third parameter is interface */
|
||||
if (ifindex(opt->value3.u_string/*ifindex*/,
|
||||
|
@ -802,9 +809,11 @@ mc:addr
|
|||
} else {
|
||||
/*! result */
|
||||
xioresolve(opt->value2.u_string/*param2*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2, 0, 0);
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts);
|
||||
ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
|
||||
}
|
||||
}
|
||||
|
@ -953,27 +962,30 @@ int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
|
|||
|
||||
/* first parameter is always multicast address */
|
||||
rc = xioresolve(opt->value.u_string/*mcaddr*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1, 0, 0);
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1, xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
ip4_mreq_src.imr_multiaddr = sockaddr1.ip4.sin_addr;
|
||||
/* second parameter is interface address */
|
||||
rc = xioresolve(opt->value.u_string/*ifaddr*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2, 0, 0);
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2, xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
ip4_mreq_src.imr_interface = sockaddr2.ip4.sin_addr;
|
||||
/* third parameter is source address */
|
||||
rc = xioresolve(opt->value.u_string/*srcaddr*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr3, &socklen3, 0, 0);
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr3, &socklen3, xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
|
8
xio-ip.h
8
xio-ip.h
|
@ -29,6 +29,8 @@ extern const struct optdesc opt_ip_recvdstaddr;
|
|||
extern const struct optdesc opt_ip_recvif;
|
||||
extern const struct optdesc opt_ip_transparent;
|
||||
|
||||
extern const struct optdesc opt_ai_addrconfig;
|
||||
|
||||
extern const struct optdesc opt_res_debug;
|
||||
extern const struct optdesc opt_res_aaonly;
|
||||
extern const struct optdesc opt_res_usevc;
|
||||
|
@ -39,9 +41,11 @@ extern const struct optdesc opt_res_defnames;
|
|||
extern const struct optdesc opt_res_stayopen;
|
||||
extern const struct optdesc opt_res_dnsrch;
|
||||
|
||||
extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo **res, unsigned long res_opts0, unsigned long res_opts1);
|
||||
extern int xioinit_ip(struct single *sfd, int *pf);
|
||||
|
||||
extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo **res, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
extern void xiofreeaddrinfo(struct addrinfo *res);
|
||||
extern int xioresolve(const char *node, const char *service, int family, int socktype, int protocol, union sockaddr_union *addr, socklen_t *addrlen, unsigned long res_opts0, unsigned long res_opts1);
|
||||
extern int xioresolve(const char *node, const char *service, int family, int socktype, int protocol, union sockaddr_union *addr, socklen_t *addrlen, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
extern int xiolog_ancillary_ip(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
|
||||
extern int xiotype_ip_add_membership(char *token, const struct optname *ent, struct opt *opt);
|
||||
extern int xioapply_ip_add_membership(xiosingle_t *xfd, struct opt *opt);
|
||||
|
|
11
xio-ip4.c
11
xio-ip4.c
|
@ -14,7 +14,12 @@
|
|||
#include "xio-ip4.h"
|
||||
|
||||
|
||||
int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
|
||||
int xioparsenetwork_ip4(
|
||||
const char *rangename,
|
||||
struct xiorange *range,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2])
|
||||
{
|
||||
struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
|
||||
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
|
||||
char *rangename1; /* a copy of rangename with writing allowed */
|
||||
|
@ -46,7 +51,7 @@ int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
|
|||
}
|
||||
} else if (delimpos = strchr(rangename1, ':')) {
|
||||
if ((rc = xioresolve(delimpos+1, NULL, PF_INET, 0, 0,
|
||||
&sau, &socklen, 0, 0))
|
||||
&sau, &socklen, ai_flags, res_opts))
|
||||
!= STAT_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -59,7 +64,7 @@ int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
|
|||
{
|
||||
*delimpos = 0;
|
||||
if ((rc = xioresolve(rangename1, NULL, PF_INET, 0, 0,
|
||||
&sau, &socklen, 0, 0))
|
||||
&sau, &socklen, ai_flags, res_opts))
|
||||
!= STAT_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
extern const struct optdesc opt_ip4_add_membership;
|
||||
|
||||
int xioparsenetwork_ip4(const char *rangename, struct xiorange *range);
|
||||
extern int xioparsenetwork_ip4(const char *rangename, struct xiorange *range, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
extern
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range);
|
||||
extern int
|
||||
|
|
43
xio-ip6.c
43
xio-ip6.c
|
@ -82,7 +82,12 @@ const struct optdesc opt_ipv6_recvpathmtu = { "ipv6-recvpathmtu", "recvpathmtu",
|
|||
/* Returns canonical form of IPv6 address.
|
||||
IPv6 address may bei enclose in brackets.
|
||||
Returns STAT_OK on success, STAT_NORETRY on failure. */
|
||||
int xioip6_pton(const char *src, struct in6_addr *dst) {
|
||||
int xioip6_pton(
|
||||
const char *src,
|
||||
struct in6_addr *dst,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2])
|
||||
{
|
||||
union sockaddr_union sockaddr;
|
||||
socklen_t sockaddrlen = sizeof(sockaddr);
|
||||
|
||||
|
@ -94,10 +99,10 @@ int xioip6_pton(const char *src, struct in6_addr *dst) {
|
|||
plainaddr[INET6_ADDRSTRLEN-1] = '\0';
|
||||
if ((clos = strchr(plainaddr, ']')) != NULL)
|
||||
*clos = '\0';
|
||||
return xioip6_pton(plainaddr, dst);
|
||||
return xioip6_pton(plainaddr, dst, ai_flags, res_opts);
|
||||
}
|
||||
if (xioresolve(src, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
|
||||
0, 0)
|
||||
ai_flags, res_opts)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -105,7 +110,12 @@ int xioip6_pton(const char *src, struct in6_addr *dst) {
|
|||
return STAT_OK;
|
||||
}
|
||||
|
||||
int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) {
|
||||
int xioparsenetwork_ip6(
|
||||
const char *rangename,
|
||||
struct xiorange *range,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2])
|
||||
{
|
||||
char *delimpos; /* absolute address of delimiter */
|
||||
size_t delimind; /* index of delimiter in string */
|
||||
unsigned int bits; /* netmask bits */
|
||||
|
@ -135,7 +145,7 @@ int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) {
|
|||
}
|
||||
baseaddr[delimind-2] = '\0';
|
||||
if (xioresolve(baseaddr, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
|
||||
0, 0)
|
||||
ai_flags, res_opts)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -480,9 +490,12 @@ int xioapply_ipv6_join_group(
|
|||
/* First parameter is multicast address */
|
||||
if ((res =
|
||||
xioresolve(opt->value.u_string/*multiaddr*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1, 0, 0)) != STAT_OK) {
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return res;
|
||||
}
|
||||
ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr;
|
||||
|
@ -619,9 +632,10 @@ int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt) {
|
|||
/* First parameter is always multicast address */
|
||||
if ((res =
|
||||
xioresolve(opt->value.u_string/*mcaddr*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1, 0, 0)) != STAT_OK) {
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1,
|
||||
xfd->para.socket.ip.ai_flags, xfd->para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return res;
|
||||
}
|
||||
memcpy(&ip6_gsr.gsr_group, &sockaddr1.ip6, socklen1);
|
||||
|
@ -636,9 +650,10 @@ int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt) {
|
|||
/* Third parameter is source address */
|
||||
if ((res =
|
||||
xioresolve(opt->value3.u_string/*srcaddr*/, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2, 0, 0)) != STAT_OK) {
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2,
|
||||
xfd->para.socket.ip.ai_flags, xfd->para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return res;
|
||||
}
|
||||
memcpy(&ip6_gsr.gsr_source, &sockaddr2.ip6, socklen2);
|
||||
|
|
|
@ -32,9 +32,8 @@ extern const struct optdesc opt_ipv6_tclass;
|
|||
extern const struct optdesc opt_ipv6_recvtclass;
|
||||
extern const struct optdesc opt_ipv6_recvpathmtu;
|
||||
|
||||
extern int xioip6_pton(const char *src, struct in6_addr *dst);
|
||||
extern
|
||||
int xioparsenetwork_ip6(const char *rangename, struct xiorange *range);
|
||||
extern int xioip6_pton(const char *src, struct in6_addr *dst, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
extern int xioparsenetwork_ip6(const char *rangename, struct xiorange *range, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
extern int xiorange_ip6andmask(struct xiorange *range);
|
||||
|
||||
extern
|
||||
|
|
70
xio-ipapp.c
70
xio-ipapp.c
|
@ -42,6 +42,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
xioinit_ip(xfd, &pf);
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
@ -50,8 +51,8 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
|
||||
if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts,
|
||||
&themlist, us, &uslen, &needbind, &lowport,
|
||||
socktype) != STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
|
@ -170,16 +171,21 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT
|
||||
*/
|
||||
int
|
||||
_xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *hostname,
|
||||
const char *portname,
|
||||
int *pf,
|
||||
int protocol,
|
||||
unsigned long res_opts0, unsigned long res_opts1,
|
||||
struct addrinfo **themlist,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
bool *needbind, bool *lowport,
|
||||
int socktype) {
|
||||
_xioopen_ipapp_prepare(
|
||||
struct opt *opts,
|
||||
struct opt **opts0,
|
||||
const char *hostname,
|
||||
const char *portname,
|
||||
int *pf,
|
||||
int protocol,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2],
|
||||
struct addrinfo **themlist,
|
||||
union sockaddr_union *us,
|
||||
socklen_t *uslen,
|
||||
bool *needbind,
|
||||
bool *lowport,
|
||||
int socktype) {
|
||||
uint16_t port;
|
||||
int result;
|
||||
|
||||
|
@ -188,9 +194,7 @@ int
|
|||
if ((result =
|
||||
xiogetaddrinfo(hostname, portname,
|
||||
*pf, socktype, protocol,
|
||||
themlist,
|
||||
res_opts0, res_opts1
|
||||
))
|
||||
themlist, ai_flags, res_opts))
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY; /*! STAT_RETRYLATER? */
|
||||
}
|
||||
|
@ -200,7 +204,7 @@ int
|
|||
/* 3 means: IP address AND port accepted */
|
||||
if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family,
|
||||
socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
||||
res_opts0, res_opts1)
|
||||
ai_flags, res_opts)
|
||||
!= STAT_NOACTION) {
|
||||
*needbind = true;
|
||||
} else {
|
||||
|
@ -242,12 +246,18 @@ int
|
|||
applies and consumes the following options:
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND
|
||||
*/
|
||||
int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *portname, int *pf, int ipproto,
|
||||
unsigned long res_opts0,
|
||||
unsigned long res_opts1,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
int socktype) {
|
||||
int _xioopen_ipapp_listen_prepare(
|
||||
struct opt *opts,
|
||||
struct opt **opts0,
|
||||
const char *portname,
|
||||
int *pf,
|
||||
int ipproto,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2],
|
||||
union sockaddr_union *us,
|
||||
socklen_t *uslen,
|
||||
int socktype)
|
||||
{
|
||||
char *bindname = NULL;
|
||||
int result;
|
||||
|
||||
|
@ -256,8 +266,7 @@ int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
|||
retropt_string(opts, OPT_BIND, &bindname);
|
||||
result =
|
||||
xioresolve(bindname, portname, *pf, socktype, ipproto,
|
||||
us, uslen,
|
||||
res_opts0, res_opts1);
|
||||
us, uslen, ai_flags, res_opts);
|
||||
if (result != STAT_OK) {
|
||||
/*! STAT_RETRY? */
|
||||
return result;
|
||||
|
@ -270,7 +279,7 @@ int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
|||
/* we expect the form: port */
|
||||
/* currently only used for TCP4 */
|
||||
int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *fd,
|
||||
int xioflags, xiofile_t *xfd,
|
||||
groups_t groups, int socktype,
|
||||
int ipproto, int pf) {
|
||||
struct opt *opts0 = NULL;
|
||||
|
@ -282,6 +291,7 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
|||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
xioinit_ip(&xfd->stream, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
#if WITH_IP4 && WITH_IP6
|
||||
switch (xioparms.default_ip) {
|
||||
|
@ -296,22 +306,22 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
|||
#endif
|
||||
}
|
||||
|
||||
fd->stream.howtoend = END_SHUTDOWN;
|
||||
xfd->stream.howtoend = END_SHUTDOWN;
|
||||
|
||||
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, argv[1], &pf, ipproto,
|
||||
fd->stream.para.socket.ip.res_opts[1],
|
||||
fd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts,
|
||||
us, &uslen, socktype)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
xioopen_listen(&fd->stream, xioflags,
|
||||
xioopen_listen(&xfd->stream, xioflags,
|
||||
(struct sockaddr *)us, uslen,
|
||||
opts, opts0, pf, socktype, ipproto))
|
||||
!= 0)
|
||||
|
|
18
xio-ipapp.h
18
xio-ipapp.h
|
@ -17,15 +17,8 @@ extern const struct optdesc opt_lowport;
|
|||
extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd,
|
||||
groups_t groups, int socktype,
|
||||
int ipproto, int protname);
|
||||
extern int
|
||||
_xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *hostname,
|
||||
const char *portname, int *pf, int protocol,
|
||||
unsigned long res_opts0, unsigned long res_opts1,
|
||||
struct addrinfo **res,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
bool *needbind, bool *lowport,
|
||||
int socktype);
|
||||
extern int _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0, const char *hostname, const char *portname, int *pf, int protocol, const int ai_flags[2], const unsigned long res_opts[2], struct addrinfo **res, union sockaddr_union *us, socklen_t *uslen, bool *needbind, bool *lowport,
|
||||
int socktype);
|
||||
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
|
||||
struct single *xfd,
|
||||
int socktype, int ipproto, void *protname,
|
||||
|
@ -34,11 +27,6 @@ extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
|||
int xioflags, xiofile_t *fd,
|
||||
groups_t groups, int socktype,
|
||||
int ipproto, int protname);
|
||||
extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *portname, int *pf, int ipproto,
|
||||
unsigned long res_opts0,
|
||||
unsigned long res_opts1,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
int socktype);
|
||||
extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, const int ai_flags[2], const unsigned long res_opts[2], union sockaddr_union *us, socklen_t *uslen, int socktype);
|
||||
|
||||
#endif /* !defined(__xio_ipapp_h_included) */
|
||||
|
|
|
@ -199,7 +199,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
|||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
|
|
@ -280,6 +280,7 @@ static int
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(xfd, &pf);
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
|
@ -326,8 +327,8 @@ static int
|
|||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts,
|
||||
&themlist, us, &uslen,
|
||||
&needbind, &lowport, socktype);
|
||||
if (result != STAT_OK) return STAT_NORETRY;
|
||||
|
@ -571,6 +572,7 @@ static int
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(xfd, &pf);
|
||||
#if WITH_IP4 && WITH_IP6
|
||||
switch (xioparms.default_ip) {
|
||||
case '4': pf = PF_INET; break;
|
||||
|
@ -610,8 +612,8 @@ static int
|
|||
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
|
||||
|
||||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts,
|
||||
us, &uslen, socktype)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
|
@ -1894,7 +1896,8 @@ static int openssl_handle_peer_certificate(struct single *xfd,
|
|||
case 16: /* IPv6 */
|
||||
inet_ntop(AF_INET6, data, aBuffer, sizeof(aBuffer));
|
||||
if (peername != NULL) {
|
||||
xioip6_pton(peername, &ip6bin);
|
||||
xioip6_pton(peername, &ip6bin, xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts);
|
||||
if (memcmp(data, &ip6bin, sizeof(ip6bin)) == 0) {
|
||||
Debug2("subjectAltName \"%s\" matches peername \"%s\"",
|
||||
aBuffer, peername);
|
||||
|
|
24
xio-proxy.c
24
xio-proxy.c
|
@ -110,6 +110,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
targetname = argv[2];
|
||||
targetport = argv[3];
|
||||
|
||||
xioinit_ip(xfd, &pf);
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
|
@ -124,14 +125,16 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
}
|
||||
|
||||
result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport);
|
||||
result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts);
|
||||
if (result != STAT_OK) return result;
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
|
||||
&pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts,
|
||||
&themlist, us, &uslen,
|
||||
&needbind, &lowport, socktype);
|
||||
if (result != STAT_OK) return result;
|
||||
|
@ -242,8 +245,13 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
|
||||
|
||||
int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
|
||||
const char *targetname, const char *targetport) {
|
||||
int _xioopen_proxy_prepare(
|
||||
struct proxyvars *proxyvars,
|
||||
struct opt *opts,
|
||||
const char *targetname,
|
||||
const char *targetport,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2]) {
|
||||
union sockaddr_union host;
|
||||
socklen_t socklen = sizeof(host);
|
||||
int rc;
|
||||
|
@ -300,10 +308,10 @@ int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
|
|||
if (proxyvars->doresolve) {
|
||||
/* currently we only resolve to IPv4 addresses. This is in accordance to
|
||||
RFC 2396; however once it becomes clear how IPv6 addresses should be
|
||||
represented in CONNECT commands this code might be extended */
|
||||
represented in CONNECT commands this code might need to be extended */
|
||||
rc = xioresolve(targetname, targetport, PF_INET/*!?*/,
|
||||
SOCK_STREAM, IPPROTO_TCP,
|
||||
&host, &socklen, 0, 0);
|
||||
SOCK_STREAM, IPPROTO_TCP,
|
||||
&host, &socklen, ai_flags, res_opts);
|
||||
if (rc != STAT_OK) {
|
||||
proxyvars->targetaddr = strdup(targetname);
|
||||
} else {
|
||||
|
|
|
@ -25,8 +25,7 @@ extern const struct optdesc opt_proxy_authorization_file;
|
|||
|
||||
extern const struct addrdesc xioaddr_proxy_connect;
|
||||
|
||||
int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
|
||||
const char *targetname, const char *targetport);
|
||||
extern int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts, const char *targetname, const char *targetport, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
int _xioopen_proxy_connect(struct single *xfd,
|
||||
struct proxyvars *proxyvars,
|
||||
int level);
|
||||
|
|
31
xio-rawip.c
31
xio-rawip.c
|
@ -73,6 +73,8 @@ int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
|
|||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(&xxfd->stream, &pf);
|
||||
if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, &pf)) != STAT_OK) {
|
||||
return result;
|
||||
|
@ -123,8 +125,8 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
|||
if ((result =
|
||||
xioresolve(hostname, NULL, *pf, socktype, ipproto,
|
||||
&xfd->peersa, &xfd->salen,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1]))
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
@ -137,8 +139,9 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
|||
xfd->dtype = XIODATA_RECVFROM_SKIPIP;
|
||||
|
||||
if (retropt_bind(opts, *pf, socktype, ipproto, &us.soa, &uslen, feats,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1]) != STAT_NOACTION) {
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
return
|
||||
|
@ -161,6 +164,8 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(xfd, &pf);
|
||||
if ((result =
|
||||
_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, &pf)) != STAT_OK) {
|
||||
|
@ -176,7 +181,10 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
/* which reply packets will be accepted - determine by range option */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -212,6 +220,7 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(&xfd->stream, &pf);
|
||||
if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
|
||||
Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
|
||||
protname, ipproto);
|
||||
|
@ -239,8 +248,9 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1,
|
||||
xfd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.res_opts[1]) != STAT_NOACTION) {
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
|
@ -274,6 +284,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(&xfd->stream, &pf);
|
||||
if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
|
||||
Error2("xioopen_rawip_recv(\"%s\",,): protocol number exceeds 255 (%u)",
|
||||
protname, ipproto);
|
||||
|
@ -297,9 +308,9 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
if (retropt_bind(opts, pf, socktype, ipproto,
|
||||
&/*us.soa*/xfd->stream.para.socket.la.soa, &uslen, 1,
|
||||
xfd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.res_opts[1]) ==
|
||||
STAT_OK) {
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts)
|
||||
== STAT_OK) {
|
||||
needbind = true;
|
||||
} else {
|
||||
/* pf is required during xioread checks */
|
||||
|
|
49
xio-socket.c
49
xio-socket.c
|
@ -277,7 +277,7 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
socket_init(0, &us);
|
||||
if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3,
|
||||
0, 0)
|
||||
xfd->para.socket.ip.ai_flags, xfd->para.socket.ip.res_opts)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
us.soa.sa_family = pf;
|
||||
|
@ -540,7 +540,10 @@ int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
|
||||
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -619,7 +622,10 @@ int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
|
|||
xfd->para.socket.la.soa.sa_family = pf;
|
||||
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -699,7 +705,10 @@ int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
/* which reply sockets will accept - determine by range option */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -1169,7 +1178,10 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
|
||||
/* for generic sockets, this has already been retrieved */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -1371,7 +1383,10 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
|||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -1814,19 +1829,25 @@ char *xiogetifname(int ind, char *val, int ins) {
|
|||
|
||||
|
||||
/* parses a network specification consisting of an address and a mask. */
|
||||
int xioparsenetwork(const char *rangename, int pf, struct xiorange *range) {
|
||||
int xioparsenetwork(
|
||||
const char *rangename,
|
||||
int pf,
|
||||
struct xiorange *range,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2])
|
||||
{
|
||||
size_t addrlen = 0, masklen = 0;
|
||||
int result;
|
||||
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
return xioparsenetwork_ip4(rangename, range);
|
||||
return xioparsenetwork_ip4(rangename, range, ai_flags, res_opts);
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
return xioparsenetwork_ip6(rangename, range);
|
||||
return xioparsenetwork_ip6(rangename, range, ai_flags, res_opts);
|
||||
break;
|
||||
#endif /* WITH_IP6 */
|
||||
case PF_UNSPEC:
|
||||
|
@ -1887,9 +1908,15 @@ int xioparsenetwork(const char *rangename, int pf, struct xiorange *range) {
|
|||
|
||||
/* parses a string of form address/bits or address:mask, and fills the fields
|
||||
of the range union. The addr component is masked with mask. */
|
||||
int xioparserange(const char *rangename, int pf, struct xiorange *range) {
|
||||
int xioparserange(
|
||||
const char *rangename,
|
||||
int pf,
|
||||
struct xiorange *range,
|
||||
const int ai_flags[2],
|
||||
const unsigned long res_opts[2])
|
||||
{
|
||||
int i;
|
||||
if (xioparsenetwork(rangename, pf, range) < 0) {
|
||||
if (xioparsenetwork(rangename, pf, range, ai_flags, res_opts) < 0) {
|
||||
Error2("failed to parse or resolve range \"%s\" (pf=%d)", rangename, pf);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -125,11 +125,8 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
extern
|
||||
int xiosetsockaddrenv(const char *lr, union sockaddr_union *sau, socklen_t salen, int proto);
|
||||
|
||||
extern
|
||||
int xioparsenetwork(const char *rangename, int pf,
|
||||
struct xiorange *range);
|
||||
extern
|
||||
int xioparserange(const char *rangename, int pf, struct xiorange *range);
|
||||
extern int xioparsenetwork(const char *rangename, int pf, struct xiorange *range, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
extern int xioparserange(const char *rangename, int pf, struct xiorange *range, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
|
||||
extern int
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int level);
|
||||
|
|
13
xio-socks.c
13
xio-socks.c
|
@ -72,6 +72,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
|||
targetname = argv[2];
|
||||
targetport = argv[3];
|
||||
|
||||
xioinit_ip(xfd, &pf);
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
|
@ -85,8 +86,8 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
|||
result =
|
||||
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
|
||||
&pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts,
|
||||
&themlist, us, &uslen,
|
||||
&needbind, &lowport, socktype);
|
||||
|
||||
|
@ -272,10 +273,10 @@ int
|
|||
socklen_t saulen = sizeof(sau);
|
||||
|
||||
if ((result = xioresolve(hostname, NULL,
|
||||
PF_INET, SOCK_STREAM, IPPROTO_TCP,
|
||||
&sau, &saulen,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0]))
|
||||
PF_INET, SOCK_STREAM, IPPROTO_TCP,
|
||||
&sau, &saulen,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return result; /*! STAT_RETRY? */
|
||||
}
|
||||
|
|
|
@ -133,7 +133,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
Error1("strdup(\"%s\"): out of memory", argv[1]);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
if ((result = xioparsenetwork(ifaddr, pf, &network)) != STAT_OK) {
|
||||
if ((result = xioparsenetwork(ifaddr, pf, &network,
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
/*! recover */
|
||||
return result;
|
||||
}
|
||||
|
|
66
xio-udp.c
66
xio-udp.c
|
@ -107,7 +107,10 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &sfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &sfd->para.socket.range,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
sfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -282,7 +285,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
|
||||
/* we expect the form: port */
|
||||
int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *fd,
|
||||
int xioflags, xiofile_t *xfd,
|
||||
groups_t groups, int pf, int ipproto,
|
||||
int protname) {
|
||||
const char *portname = argv[1];
|
||||
|
@ -294,6 +297,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
xioinit_ip(&xfd->stream, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
#if WITH_IP4 && WITH_IP6
|
||||
switch (xioparms.default_ip) {
|
||||
|
@ -311,14 +315,14 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
|
||||
|
||||
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
retropt_bind(opts, pf, socktype, ipproto,
|
||||
(struct sockaddr *)&us, &uslen, 1,
|
||||
fd->stream.para.socket.ip.res_opts[1],
|
||||
fd->stream.para.socket.ip.res_opts[0]);
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts);
|
||||
|
||||
if (false) {
|
||||
;
|
||||
|
@ -334,13 +338,13 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
Error1("xioopen_ipdgram_listen(): unknown address family %d", pf);
|
||||
}
|
||||
|
||||
return _xioopen_ipdgram_listen(&fd->stream, xioflags, &us, uslen,
|
||||
return _xioopen_ipdgram_listen(&xfd->stream, xioflags, &us, uslen,
|
||||
opts, pf, socktype, ipproto);
|
||||
}
|
||||
|
||||
static
|
||||
int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, groups_t groups,
|
||||
int xioflags, xiofile_t *xfd, groups_t groups,
|
||||
int pf, int socktype, int ipproto) {
|
||||
int result;
|
||||
|
||||
|
@ -350,13 +354,14 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(&xfd->stream, &pf);
|
||||
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, xfd,
|
||||
groups, pf, socktype, ipproto))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
_xio_openlate(&xxfd->stream, opts);
|
||||
_xio_openlate(&xfd->stream, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
@ -387,9 +392,9 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
|||
xfd->salen = sizeof(xfd->peersa);
|
||||
if ((result =
|
||||
xioresolve(hostname, servname, pf, socktype, ipproto,
|
||||
&xfd->peersa, &xfd->salen,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1]))
|
||||
&xfd->peersa, &xfd->salen,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
@ -398,8 +403,8 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
|||
}
|
||||
uslen = socket_init(pf, &us);
|
||||
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, feats,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1])
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
@ -446,6 +451,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(xfd, &pf);
|
||||
if ((hostname = strdup(argv[1])) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", argv[1]);
|
||||
return STAT_RETRYLATER;
|
||||
|
@ -474,7 +480,10 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
/* which reply packets will be accepted - determine by range option */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename)
|
||||
>= 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range,
|
||||
xfd->para.socket.ip.ai_flags,
|
||||
xfd->para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
@ -506,6 +515,7 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(&xfd->stream, &pf);
|
||||
xfd->stream.howtoend = END_NONE;
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
|
@ -523,9 +533,9 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
|
||||
if ((result =
|
||||
xioresolve(NULL, argv[1], pf, socktype, ipproto,
|
||||
&us, &uslen, xfd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.res_opts[1]))
|
||||
xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen,
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
@ -538,8 +548,8 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
socklen_t lalen = sizeof(la);
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, ipproto, &la.soa, &lalen, 1,
|
||||
xfd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.res_opts[1])
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts)
|
||||
!= STAT_NOACTION) {
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
|
@ -584,6 +594,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
xioinit_ip(&xfd->stream, &pf);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
#if WITH_IP4 && WITH_IP6
|
||||
|
@ -600,9 +611,9 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
|
||||
if ((result =
|
||||
xioresolve(NULL, argv[1], pf, socktype, ipproto,
|
||||
&us, &uslen, xfd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.res_opts[1]))
|
||||
xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen,
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
@ -617,8 +628,8 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
if (retropt_bind(opts, pf, socktype, ipproto,
|
||||
&xfd->stream.para.socket.la.soa, &lalen, 1,
|
||||
xfd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.res_opts[1])
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts)
|
||||
!= STAT_NOACTION) {
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
|
@ -638,7 +649,10 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->stream.para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->stream.para.socket.range,
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
xfd->stream.para.socket.ip.res_opts)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
|
13
xio-unix.c
13
xio-unix.c
|
@ -240,7 +240,8 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
|
||||
(abstract<<1)|xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
|
||||
(abstract<<1)|xfd->para.socket.un.tight, NULL, NULL)
|
||||
== STAT_OK) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
|
@ -383,7 +384,8 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
xfd->dtype = XIODATA_RECVFROM;
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
|
||||
(abstract<<1)| xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
|
||||
(abstract<<1)| xfd->para.socket.un.tight, NULL, NULL)
|
||||
== STAT_OK) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
|
@ -451,7 +453,8 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
#if 0
|
||||
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
|
||||
(abstract<<1)|xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
|
||||
(abstract<<1)|xfd->para.socket.un.tight, NULL, NULL)
|
||||
== STAT_OK) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -531,7 +534,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
#if 0
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
|
||||
(abstract<<1)|xfd->para.socket.un.tight, 0, 0)
|
||||
(abstract<<1)|xfd->para.socket.un.tight, NULL, NULL)
|
||||
== STAT_OK) {
|
||||
}
|
||||
#endif
|
||||
|
@ -616,7 +619,7 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
|
|||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
|
||||
(abstract<<1)|xfd->para.socket.un.tight, 0, 0)
|
||||
(abstract<<1)|xfd->para.socket.un.tight, NULL, NULL)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,8 @@ static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
|
|||
xiolog_vsock_cid();
|
||||
|
||||
ret = retropt_bind(opts, pf, socktype, protocol,
|
||||
(struct sockaddr *)&sa_local, &sa_len, 3, 0, 0);
|
||||
(struct sockaddr *)&sa_local, &sa_len, 3,
|
||||
NULL, NULL);
|
||||
if (ret == STAT_NORETRY)
|
||||
return ret;
|
||||
if (ret == STAT_OK)
|
||||
|
@ -153,7 +154,7 @@ static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
|
|||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
ret = retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&sa_bind,
|
||||
&sa_len, 1, 0, 0);
|
||||
&sa_len, 1, NULL, NULL);
|
||||
if (ret == STAT_NORETRY)
|
||||
return ret;
|
||||
if (ret == STAT_OK)
|
||||
|
|
3
xio.h
3
xio.h
|
@ -130,7 +130,8 @@ extern xioparms_t xioparms;
|
|||
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
struct para_ip {
|
||||
unsigned int res_opts[2]; /* bits to be set in _res.options are
|
||||
int ai_flags[2]; /* flags for getaddrinfo() ai_flags (set/unset) */
|
||||
unsigned long res_opts[2]; /* bits to be set in _res.options are
|
||||
at [0], bits to be cleared are at [1] */
|
||||
bool dosourceport; /* check the source port of incoming connection or packets */
|
||||
uint16_t sourceport; /* host byte order */
|
||||
|
|
31
xioopts.c
31
xioopts.c
|
@ -172,6 +172,12 @@ const struct optname optionnames[] = {
|
|||
#endif
|
||||
#if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
|
||||
IF_IP ("add-source-membership", &opt_ip_add_source_membership)
|
||||
#endif
|
||||
#if defined(AI_ADDRCONFIG)
|
||||
IF_IP ("addrconfig", &opt_ai_addrconfig)
|
||||
#endif
|
||||
#if defined(AI_ADDRCONFIG)
|
||||
IF_IP ("ai-addrconfig", &opt_ai_addrconfig)
|
||||
#endif
|
||||
IF_INTERFACE("allmulti", &opt_iff_allmulti)
|
||||
#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
|
||||
|
@ -2597,8 +2603,8 @@ int parseopts_table(const char **a, groups_t groups, struct opt **opts,
|
|||
}
|
||||
*buffp = '\0';
|
||||
if (xioresolve(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP,
|
||||
(union sockaddr_union *)&sa, &salen,
|
||||
0, 0/*!!!*/) != STAT_OK) {
|
||||
(union sockaddr_union *)&sa, &salen, NULL,
|
||||
NULL/*!! !*/) != STAT_OK) {
|
||||
opt->desc = ODESC_ERROR; continue;
|
||||
}
|
||||
opt->value.u_ip4addr = sa.sin_addr;
|
||||
|
@ -3109,7 +3115,8 @@ int retropt_bind(struct opt *opts,
|
|||
UNIX (or'd): 1..tight
|
||||
2..abstract
|
||||
*/
|
||||
unsigned long res_opts0, unsigned long res_opts1) {
|
||||
const int ai_flags[2], const unsigned long res_opts[2])
|
||||
{
|
||||
const char portsep[] = ":";
|
||||
const char *ends[] = { portsep, NULL };
|
||||
const char *nests[] = { "[", "]", NULL };
|
||||
|
@ -3175,9 +3182,9 @@ int retropt_bind(struct opt *opts,
|
|||
}
|
||||
if ((result =
|
||||
xioresolve(hostname[0]!='\0'?hostname:NULL, portp,
|
||||
af, socktype, ipproto,
|
||||
(union sockaddr_union *)sa, salen,
|
||||
res_opts0, res_opts1))
|
||||
af, socktype, ipproto,
|
||||
(union sockaddr_union *)sa, salen,
|
||||
ai_flags, res_opts))
|
||||
!= STAT_OK) {
|
||||
Error("error resolving bind option");
|
||||
return STAT_NORETRY;
|
||||
|
@ -4070,6 +4077,10 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
|
|||
break;
|
||||
|
||||
case OFUNC_OFFSET_MASKS:
|
||||
/* An external (e.g. library) variable with independent bits is to be
|
||||
manipulated. Here the data target is an array with size 2, the first
|
||||
element holds the bit mask to be set, the second one those to be
|
||||
cleared. Each related option sets or unsets a specific bit. */
|
||||
{
|
||||
void *masks = (char *)xfd + opt->desc->major;
|
||||
size_t masksize = opt->desc->minor;
|
||||
|
@ -4089,8 +4100,14 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
|
|||
((uint32_t *)masks)[1] |= bit;
|
||||
}
|
||||
break;
|
||||
case sizeof(uint64_t):
|
||||
if (opt->value.u_bool) {
|
||||
((uint64_t *)masks)[0] |= bit;
|
||||
} else {
|
||||
((uint64_t *)masks)[1] |= bit;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t));
|
||||
Error1("applyopts_single: masksize "F_Zu" not implemented",
|
||||
masksize);
|
||||
}
|
||||
|
|
14
xioopts.h
14
xioopts.h
|
@ -24,6 +24,7 @@ enum e_types {
|
|||
TYPE_CONST, /* keyword means a fix value - implies int type */
|
||||
TYPE_BIN, /* raw binary data, length determined by data */
|
||||
TYPE_BOOL, /* value is 0 or 1 (no-value is interpreted as 1) */
|
||||
TYPE_BOOL_NULL, /* value is 0 or 1 (no-value is interpreted as 1), or just opt= */
|
||||
TYPE_BYTE, /* unsigned char */
|
||||
|
||||
TYPE_INT, /* int */
|
||||
|
@ -103,7 +104,7 @@ enum e_func {
|
|||
OFUNC_TERMIO, /* termio() ? */
|
||||
OFUNC_SPEC, /* special, i.e. no generalizable function call */
|
||||
OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */
|
||||
OFUNC_OFFSET_MASKS, /* !!! */
|
||||
OFUNC_OFFSET_MASKS, /* set pos or neg bit pattern in array[2] */
|
||||
/*OFUNC_APPL,*/ /* special, i.e. application must know which f. */
|
||||
OFUNC_EXT, /* with extended file descriptors only */
|
||||
OFUNC_TERMIOS_FLAG, /* a flag in struct termios: major..tcflag, minor..bit
|
||||
|
@ -201,6 +202,7 @@ enum e_func {
|
|||
/* optcode's */
|
||||
enum e_optcode {
|
||||
OPT_ADDRESS_FAMILY = 1,
|
||||
OPT_AI_ADDRCONFIG, /* getaddrinfo() */
|
||||
/* these are not alphabetically, I know... */
|
||||
OPT_B0, /* termios.c_cflag */
|
||||
OPT_B50, /* termios.c_cflag */
|
||||
|
@ -954,15 +956,7 @@ extern int retropt_ulong(struct opt *opts, int optcode, unsigned long *result);
|
|||
extern int retropt_flag(struct opt *opts, int optcode, flags_t *result);
|
||||
extern int retropt_string(struct opt *opts, int optcode, char **result);
|
||||
extern int retropt_timespec(struct opt *opts, int optcode, struct timespec *result);
|
||||
extern int retropt_bind(struct opt *opts,
|
||||
int af,
|
||||
int socktype,
|
||||
int ipproto,
|
||||
struct sockaddr *sa,
|
||||
socklen_t *salen,
|
||||
int feats, /* TCP etc: 1..address allowed,
|
||||
3..address and port allowed */
|
||||
unsigned long res_opts0, unsigned long res_opts1);
|
||||
extern int retropt_bind(struct opt *opts, int af, int socktype, int ipproto, struct sockaddr *sa, socklen_t *salen, int feats, const int ai_flags[2], const unsigned long res_opts[2]);
|
||||
extern int applyopts(int fd, struct opt *opts, enum e_phase phase);
|
||||
extern int applyopts2(int fd, struct opt *opts, unsigned int from,
|
||||
unsigned int to);
|
||||
|
|
Loading…
Reference in a new issue