Mechanism for ai-* options; new option ai-addrconfig

This commit is contained in:
Gerhard Rieger 2023-11-05 13:56:58 +01:00
parent 8b2e0593f3
commit 4e00a345b4
28 changed files with 492 additions and 285 deletions

View file

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

View file

@ -1 +1 @@
"1.7.4.5+"
"1.7.4.5+conn-over"

View file

@ -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()

View file

@ -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
View file

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

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

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

View file

@ -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);

View file

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

View file

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

View file

@ -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) */

View file

@ -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;
}

View file

@ -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);

View file

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

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}

View file

@ -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);

View file

@ -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? */
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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
View file

@ -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 */

View file

@ -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);
}

View file

@ -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);