mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
Preferred IP version sorts getaddrionf() results
This commit is contained in:
parent
2d282f5608
commit
277f0d755d
16 changed files with 331 additions and 146 deletions
22
CHANGES
22
CHANGES
|
@ -75,14 +75,22 @@ Features:
|
||||||
Tests: TRY_ADDRS_4 TRY_ADDRS_4_6
|
Tests: TRY_ADDRS_4 TRY_ADDRS_4_6
|
||||||
Feature recommended by Anand Buddhdev.
|
Feature recommended by Anand Buddhdev.
|
||||||
|
|
||||||
configure option --with-default-ipv allows to specify at build time if
|
configure option --enable-default-ipv allows to specify at build time if
|
||||||
IPv4, IPv6, or none of these is the preferred default.
|
IPv4, IPv6, or none of these is the preferred default; this is related
|
||||||
|
to environment variables SOCAT_PREFERRED_RESOLVE_IP and
|
||||||
|
SOCAT_DEFAULT_LISTEN_IP, and to Socat option -4, -6.
|
||||||
|
Furthermore, mechanism of IPv4 vs.IPv6 selection has been reworked.
|
||||||
|
When no IP version is preferred by these mechanism, passive Socat
|
||||||
|
addresses (LISTEN, RECV, RECVFROM) default to IPv6 because it might
|
||||||
|
support both versions (but checkout option ipv6-v6only).
|
||||||
|
For client addresses, when one of these mechanisms applies and name
|
||||||
|
resolution gives addresses of both IP versions, the addresses of the
|
||||||
|
preferred versions are tried first.
|
||||||
|
|
||||||
Socat options -4 and -6 have been reworked.
|
New option ai-addrconfig sets or unsets the AI_ADDRCONFIG flag of the
|
||||||
Tests: TCP_ENV6 TCP_DASH6
|
resolver to prevent name resolution to address families that are not
|
||||||
|
available in the network configuration. Default value is 1 in case the
|
||||||
New option ai-addrconfig disables name resolution to protocol families
|
resolver does not get an address family hint.
|
||||||
that are not configured on the computer (e.g. IPv6)
|
|
||||||
|
|
||||||
Flag AI_PASSIVE is now automatically applied for LISTEN, RECV, and
|
Flag AI_PASSIVE is now automatically applied for LISTEN, RECV, and
|
||||||
RECVFROM type addresses, and with bind option. In addition to its
|
RECVFROM type addresses, and with bind option. In addition to its
|
||||||
|
|
|
@ -723,7 +723,7 @@
|
||||||
|
|
||||||
#undef WITH_MSGLEVEL
|
#undef WITH_MSGLEVEL
|
||||||
|
|
||||||
#undef WITH_DEFAULT_IPV /* default IP version: undef, "4", "6" */
|
#undef WITH_DEFAULT_IPV /* default IP version: "0", "4", "6" */
|
||||||
|
|
||||||
#define BUILD_DATE __DATE__ " " __TIME__
|
#define BUILD_DATE __DATE__ " " __TIME__
|
||||||
|
|
||||||
|
|
|
@ -821,12 +821,12 @@ AC_ARG_ENABLE(msglevel, [ --enable-msglevel=N set max verbosity to debug,in
|
||||||
[AC_DEFINE(WITH_MSGLEVEL,0) AC_MSG_RESULT(debug)])
|
[AC_DEFINE(WITH_MSGLEVEL,0) AC_MSG_RESULT(debug)])
|
||||||
|
|
||||||
AC_MSG_CHECKING(default IP version)
|
AC_MSG_CHECKING(default IP version)
|
||||||
AC_ARG_ENABLE(ip-version, [ --enable-ip-version=N set default IP version to undef, "4", "6"],
|
AC_ARG_ENABLE(default-ipv, [ --enable-default-ipv=N set default/preferred IP version to "0" (none), "4", "6"],
|
||||||
[case "$enableval" in
|
[case "$enableval" in
|
||||||
"") AC_DEFINE(WITH_DEFAULT_IPV, 0) AC_MSG_RESULT("0");;
|
"") AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0");;
|
||||||
4) AC_DEFINE(WITH_DEFAULT_IPV, '4') AC_MSG_RESULT("4");;
|
4) AC_DEFINE(WITH_DEFAULT_IPV, '4') AC_MSG_RESULT("4");;
|
||||||
6) AC_DEFINE(WITH_DEFAULT_IPV, '6') AC_MSG_RESULT("6");;
|
6) AC_DEFINE(WITH_DEFAULT_IPV, '6') AC_MSG_RESULT("6");;
|
||||||
*) AC_DEFINE(WITH_DEFAULT_IPV, 0) AC_MSG_RESULT("0");;
|
*) AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0");;
|
||||||
esac],
|
esac],
|
||||||
[AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0")])
|
[AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0")])
|
||||||
|
|
||||||
|
|
|
@ -2244,7 +2244,7 @@ label(OPTION_AI_ADDRCONFIG)
|
||||||
dit(bf(tt(ai-addrconfig[=0|1]))), dit(bf(tt(addrconfig[=0|1])))
|
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
|
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
|
families that are not configured (e.g. IPv6). Default value is 1 in case the
|
||||||
resolver does not get an address family hint.
|
resolver does not get an address family hint from Socat address or defaults.
|
||||||
dit(bf(tt(ai-passive[=0|1]))), dit(bf(tt(passive[=0|1])))
|
dit(bf(tt(ai-passive[=0|1]))), dit(bf(tt(passive[=0|1])))
|
||||||
Sets of unsets the AI_ADDRCONFIG flag for code(getaddrinfo)) calls. Default
|
Sets of unsets the AI_ADDRCONFIG flag for code(getaddrinfo)) calls. Default
|
||||||
is 1 for LISTEN, RECV, and RECVFROM type addresses, and with
|
is 1 for LISTEN, RECV, and RECVFROM type addresses, and with
|
||||||
|
|
71
test.sh
71
test.sh
|
@ -2483,19 +2483,28 @@ waittcp6port $tsl 1
|
||||||
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
|
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
echo "$CMD1 &"
|
echo "SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 &"
|
||||||
|
cat "${te}1" >&2
|
||||||
echo "$CMD2"
|
echo "$CMD2"
|
||||||
cat "${te}1" "${te}2"
|
cat "${te}2" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED: diff:\n"
|
$PRINTF "$FAILED (diff):\n"
|
||||||
cat "$tdiff"
|
echo "SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 &"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
|
echo "// diff:" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$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))
|
numOK=$((numOK+1))
|
||||||
fi
|
fi
|
||||||
kill $pid 2>/dev/null; wait
|
kill $pid 2>/dev/null; wait
|
||||||
|
@ -3870,25 +3879,29 @@ tdiff="$td/test$N.diff"
|
||||||
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
|
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
|
||||||
# we have a normal tcp echo listening - so the socks header must appear in answer
|
# we have a normal tcp echo listening - so the socks header must appear in answer
|
||||||
newport tcp6 # provide free port number in $PORT
|
newport tcp6 # provide free port number in $PORT
|
||||||
CMD2="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR exec:\"./socks4echo.sh\""
|
CMD0="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR exec:\"./socks4echo.sh\""
|
||||||
CMD="$TRACE $SOCAT $opts - socks4:$LOCALHOST6:32.98.76.54:32109,socksport=$PORT",socksuser="nobody"
|
CMD1="$TRACE $SOCAT $opts - socks4:$LOCALHOST6:32.98.76.54:32109,socksport=$PORT",socksuser="nobody"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD0 2>\"${te}0\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
waittcp6port $PORT 1
|
waittcp6port $PORT 1
|
||||||
echo "$da" |$CMD >$tf 2>"${te}2"
|
echo "$da" |$CMD1 >${tf}1 2>"${te}1"
|
||||||
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
if ! echo "$da" |diff - "${tf}1" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
echo "$CMD2 &"
|
echo "$CMD0 &"
|
||||||
echo "$CMD"
|
cat "${te}0" >&2
|
||||||
cat "${te}1"
|
echo "$CMD1"
|
||||||
cat "${te}2"
|
cat "${te}1" >&2
|
||||||
cat "$tdiff"
|
echo "// diff:" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
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))
|
numOK=$((numOK+1))
|
||||||
fi
|
fi
|
||||||
kill $pid 2>/dev/null
|
kill $pid 2>/dev/null
|
||||||
|
@ -7885,24 +7898,34 @@ rc1=$?
|
||||||
rc2=$?
|
rc2=$?
|
||||||
kill $pid0 2>/dev/null; wait
|
kill $pid0 2>/dev/null; wait
|
||||||
if [ $rc1 != 0 -o $rc2 != 0 ]; then
|
if [ $rc1 != 0 -o $rc2 != 0 ]; then
|
||||||
$PRINTF "$FAILED\n"
|
$PRINTF "$FAILED (client(s) failed)\n"
|
||||||
echo "$CMD0 &"
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
echo "$CMD1"
|
echo "$CMD1"
|
||||||
cat "${te}0"
|
cat "${te}1" >&2
|
||||||
cat "${te}1"
|
echo "$CMD1"
|
||||||
cat "${te}2"
|
cat "${te}2" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
elif echo "$da" |diff - "${tf}" >"$tdiff"; then
|
elif echo "$da" |diff - "${tf}" >"$tdiff"; then
|
||||||
$PRINTF "$OK\n"
|
$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
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
numOK=$((numOK+1))
|
numOK=$((numOK+1))
|
||||||
else
|
else
|
||||||
$PRINTF "$FAILED\n"
|
$PRINTF "$FAILED (diff)\n"
|
||||||
echo "$CMD0 &"
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
echo "$CMD1"
|
echo "$CMD1"
|
||||||
cat "${te}0"
|
cat "${te}1" >&2
|
||||||
cat "${te}1"
|
echo "$CMD2"
|
||||||
cat "${tdiff}"
|
cat "${te}2" >&2
|
||||||
|
echo "// diff:" >&2
|
||||||
|
cat "${tdiff}" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
fi
|
fi
|
||||||
|
|
32
xio-ip.c
32
xio-ip.c
|
@ -112,11 +112,11 @@ const struct optdesc opt_res_dnsrch = { "res-dnsrch", "dnsrch", OPT_RES_DN
|
||||||
|
|
||||||
|
|
||||||
int xioinit_ip(
|
int xioinit_ip(
|
||||||
struct single *sfd,
|
int *pf,
|
||||||
int *pf)
|
char ipv)
|
||||||
{
|
{
|
||||||
if (*pf == PF_UNSPEC) {
|
if (*pf == PF_UNSPEC) {
|
||||||
switch (xioparms.preferred_ip) {
|
switch (ipv) {
|
||||||
case '0': *pf = PF_UNSPEC; break;
|
case '0': *pf = PF_UNSPEC; break;
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
case '4': *pf = PF_INET; break;
|
case '4': *pf = PF_INET; break;
|
||||||
|
@ -254,7 +254,7 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
}
|
}
|
||||||
if (error_num == EAI_SERVICE && protocol != 0) {
|
if (error_num == EAI_SERVICE && protocol != 0) {
|
||||||
if (hints.ai_protocol == 0) {
|
if (hints.ai_protocol == 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",
|
node?node:"NULL", service?service:"NULL",
|
||||||
hints.ai_flags, hints.ai_family,
|
hints.ai_flags, hints.ai_family,
|
||||||
hints.ai_socktype, hints.ai_protocol,
|
hints.ai_socktype, hints.ai_protocol,
|
||||||
|
@ -290,7 +290,7 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
while (record) {
|
while (record) {
|
||||||
char buff[256/*!*/];
|
char buff[256/*!*/];
|
||||||
sockaddr_info(record->ai_addr, record->ai_addrlen, buff, sizeof(buff));
|
sockaddr_info(record->ai_addr, record->ai_addrlen, buff, sizeof(buff));
|
||||||
Debug5("getaddrinfo() -> flags=%d family=%d socktype=%d protocol=%d addr=%s", record->ai_flags, record->ai_family, record->ai_socktype, record->ai_protocol, buff);
|
Debug5("getaddrinfo() -> flags=0x%02x family=%d socktype=%d protocol=%d addr=%s", record->ai_flags, record->ai_family, record->ai_socktype, record->ai_protocol, buff);
|
||||||
record = record->ai_next;
|
record = record->ai_next;
|
||||||
}
|
}
|
||||||
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
||||||
|
@ -425,7 +425,7 @@ void xiofreeaddrinfo(struct addrinfo *res) {
|
||||||
|
|
||||||
/* A simple resolver interface that just returns one address,
|
/* A simple resolver interface that just returns one address,
|
||||||
the first found by calling xiogetaddrinfo().
|
the first found by calling xiogetaddrinfo().
|
||||||
family may be AF_INET, AF_INET6, or AF_UNSPEC.
|
family may be AF_INET, AF_INET6, or AF_UNSPEC;
|
||||||
Returns -1 when an error occurred or when no result found.
|
Returns -1 when an error occurred or when no result found.
|
||||||
*/
|
*/
|
||||||
int xioresolve(const char *node, const char *service,
|
int xioresolve(const char *node, const char *service,
|
||||||
|
@ -434,6 +434,7 @@ int xioresolve(const char *node, const char *service,
|
||||||
const int ai_flags[2], const unsigned long res_opts[2])
|
const int ai_flags[2], const unsigned long res_opts[2])
|
||||||
{
|
{
|
||||||
struct addrinfo *res = NULL;
|
struct addrinfo *res = NULL;
|
||||||
|
struct addrinfo *aip;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = xiogetaddrinfo(node, service, family, socktype, protocol,
|
rc = xiogetaddrinfo(node, service, family, socktype, protocol,
|
||||||
|
@ -455,8 +456,23 @@ int xioresolve(const char *node, const char *service,
|
||||||
if (res->ai_next != NULL) {
|
if (res->ai_next != NULL) {
|
||||||
Info4("xioresolve(node=\"%s\", service=%s%s%s, ...): More than one address found", node?node:"NULL", service?"\"":"", service?service:"NULL", service?"\"":"");
|
Info4("xioresolve(node=\"%s\", service=%s%s%s, ...): More than one address found", node?node:"NULL", service?"\"":"", service?service:"NULL", service?"\"":"");
|
||||||
}
|
}
|
||||||
memcpy(addr, res->ai_addr, res->ai_addrlen);
|
|
||||||
*addrlen = res->ai_addrlen;
|
aip = res;
|
||||||
|
if (ai_flags[0] & AI_PASSIVE && family == PF_UNSPEC) {
|
||||||
|
/* We select the first IPv6 address, if available,
|
||||||
|
because this might accept IPv4 connections too */
|
||||||
|
struct addrinfo *aip = res;
|
||||||
|
while (aip != NULL) {
|
||||||
|
if (aip->ai_family == PF_INET6)
|
||||||
|
break;
|
||||||
|
aip = aip->ai_next;
|
||||||
|
}
|
||||||
|
if (aip == NULL)
|
||||||
|
aip = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(addr, aip->ai_addr, aip->ai_addrlen);
|
||||||
|
*addrlen = aip->ai_addrlen;
|
||||||
xiofreeaddrinfo(res);
|
xiofreeaddrinfo(res);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
2
xio-ip.h
2
xio-ip.h
|
@ -42,7 +42,7 @@ extern const struct optdesc opt_res_defnames;
|
||||||
extern const struct optdesc opt_res_stayopen;
|
extern const struct optdesc opt_res_stayopen;
|
||||||
extern const struct optdesc opt_res_dnsrch;
|
extern const struct optdesc opt_res_dnsrch;
|
||||||
|
|
||||||
extern int xioinit_ip(struct single *sfd, int *pf);
|
extern int xioinit_ip(int *pf, char ipv);
|
||||||
|
|
||||||
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 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 void xiofreeaddrinfo(struct addrinfo *res);
|
||||||
|
|
93
xio-ipapp.c
93
xio-ipapp.c
|
@ -38,11 +38,13 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
int level;
|
int level;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
struct addrinfo **ai_sorted;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1);
|
Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(xfd, &pf);
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
xfd->howtoend = END_SHUTDOWN;
|
||||||
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
@ -69,18 +71,32 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
Info("starting connect loop");
|
Info("starting connect loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Count addrinfo entries */
|
||||||
|
themp = themlist;
|
||||||
|
i = 0;
|
||||||
|
while (themp != NULL) {
|
||||||
|
++i;
|
||||||
|
themp = themp->ai_next;
|
||||||
|
}
|
||||||
|
ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
|
||||||
|
if (ai_sorted == NULL)
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
/* Generate a list of addresses sorted by preferred ip version */
|
||||||
|
_xio_sort_ip_addresses(themlist, ai_sorted);
|
||||||
|
|
||||||
do { /* loop over retries, and forks */
|
do { /* loop over retries, and forks */
|
||||||
|
|
||||||
themp = themlist;
|
/* Loop over themlist - no, over ai_sorted */
|
||||||
/* Loop over themlist */
|
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
|
i = 0;
|
||||||
|
themp = ai_sorted[i++];
|
||||||
while (themp != NULL) {
|
while (themp != NULL) {
|
||||||
Notice1("opening connection to %s",
|
Notice1("opening connection to %s",
|
||||||
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
|
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
|
||||||
infobuff, sizeof(infobuff)));
|
infobuff, sizeof(infobuff)));
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (xfd->forever || xfd->retry || themp->ai_next != NULL) {
|
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
|
||||||
level = E_INFO;
|
level = E_INFO;
|
||||||
} else
|
} else
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
|
@ -94,7 +110,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
lowport, level);
|
lowport, level);
|
||||||
if (result == STAT_OK)
|
if (result == STAT_OK)
|
||||||
break;
|
break;
|
||||||
themp = themp->ai_next;
|
themp = ai_sorted[i++];
|
||||||
if (themp == NULL) {
|
if (themp == NULL) {
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +130,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
}
|
}
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
xiofreeaddrinfo(themlist);
|
free(ai_sorted);
|
||||||
free(opts0);free(opts);
|
free(opts0);free(opts);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +147,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
if (xfd->forever || --xfd->retry) {
|
if (xfd->forever || --xfd->retry) {
|
||||||
Nanosleep(&xfd->intervall, NULL); continue;
|
Nanosleep(&xfd->intervall, NULL); continue;
|
||||||
}
|
}
|
||||||
xiofreeaddrinfo(themlist);
|
free(ai_sorted);
|
||||||
free(opts0);
|
free(opts0);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -154,13 +170,14 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
}
|
}
|
||||||
} while (true);
|
} while (true);
|
||||||
/* only "active" process breaks (master without fork, or child) */
|
/* only "active" process breaks (master without fork, or child) */
|
||||||
|
free(ai_sorted);
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themlist);
|
||||||
|
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||||
free(opts0);free(opts);
|
free(opts0);free(opts);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
free(opts0);free(opts);
|
free(opts0); free(opts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +208,7 @@ int
|
||||||
|
|
||||||
retropt_socket_pf(opts, pf);
|
retropt_socket_pf(opts, pf);
|
||||||
|
|
||||||
|
if (hostname != NULL || portname != NULL) {
|
||||||
if ((result =
|
if ((result =
|
||||||
xiogetaddrinfo(hostname, portname,
|
xiogetaddrinfo(hostname, portname,
|
||||||
*pf, socktype, protocol,
|
*pf, socktype, protocol,
|
||||||
|
@ -198,6 +216,7 @@ int
|
||||||
!= STAT_OK) {
|
!= STAT_OK) {
|
||||||
return STAT_NORETRY; /*! STAT_RETRYLATER? */
|
return STAT_NORETRY; /*! STAT_RETRYLATER? */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
applyopts(-1, opts, PH_EARLY);
|
applyopts(-1, opts, PH_EARLY);
|
||||||
|
|
||||||
|
@ -299,7 +318,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);
|
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xfd->stream, &pf);
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
if (pf == PF_UNSPEC) {
|
if (pf == PF_UNSPEC) {
|
||||||
#if WITH_IP4 && WITH_IP6
|
#if WITH_IP4 && WITH_IP6
|
||||||
switch (xioparms.default_ip) {
|
switch (xioparms.default_ip) {
|
||||||
|
@ -338,4 +357,60 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
}
|
}
|
||||||
#endif /* WITH_IP4 && WITH_TCP && WITH_LISTEN */
|
#endif /* WITH_IP4 && WITH_TCP && WITH_LISTEN */
|
||||||
|
|
||||||
|
|
||||||
|
/* Sort the records of an addrinfo list themp (as returned by getaddrinfo),
|
||||||
|
return the sorted list in the array ai_sorted (takes at most n entries
|
||||||
|
including the terminating NULL)
|
||||||
|
Returns 0 on success. */
|
||||||
|
int _xio_sort_ip_addresses(
|
||||||
|
struct addrinfo *themlist,
|
||||||
|
struct addrinfo **ai_sorted)
|
||||||
|
{
|
||||||
|
struct addrinfo *themp;
|
||||||
|
int i;
|
||||||
|
int ipv[3];
|
||||||
|
int ipi = 0;
|
||||||
|
|
||||||
|
/* Make a simple array of IP version preferences */
|
||||||
|
switch (xioparms.preferred_ip) {
|
||||||
|
case '0':
|
||||||
|
ipv[0] = PF_UNSPEC;
|
||||||
|
ipv[1] = -1;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
ipv[0] = PF_INET;
|
||||||
|
ipv[1] = PF_INET6;
|
||||||
|
ipv[2] = -1;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
ipv[0] = PF_INET6;
|
||||||
|
ipv[1] = PF_INET;
|
||||||
|
ipv[2] = -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error("INTERNAL: undefined preferred_ip value");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the sorted list */
|
||||||
|
ipi = 0;
|
||||||
|
i = 0;
|
||||||
|
while (ipv[ipi] >= 0) {
|
||||||
|
themp = themlist;
|
||||||
|
while (themp != NULL) {
|
||||||
|
if (ipv[ipi] == PF_UNSPEC) {
|
||||||
|
ai_sorted[i] = themp;
|
||||||
|
++i;
|
||||||
|
} else if (ipv[ipi] == themp->ai_family) {
|
||||||
|
ai_sorted[i] = themp;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
themp = themp->ai_next;
|
||||||
|
}
|
||||||
|
++ipi;
|
||||||
|
}
|
||||||
|
ai_sorted[i] = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* WITH_TCP || WITH_UDP */
|
#endif /* WITH_TCP || WITH_UDP */
|
||||||
|
|
|
@ -28,5 +28,6 @@ extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
groups_t groups, int socktype,
|
groups_t groups, int socktype,
|
||||||
int ipproto, int protname);
|
int ipproto, int protname);
|
||||||
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);
|
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);
|
||||||
|
extern int _xio_sort_ip_addresses(struct addrinfo *themlist, struct addrinfo **ai_sorted);
|
||||||
|
|
||||||
#endif /* !defined(__xio_ipapp_h_included) */
|
#endif /* !defined(__xio_ipapp_h_included) */
|
||||||
|
|
|
@ -252,7 +252,9 @@ static int
|
||||||
struct addrinfo *themlist, *themp;
|
struct addrinfo *themlist, *themp;
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
int level;
|
int level = E_ERROR;
|
||||||
|
struct addrinfo **ai_sorted;
|
||||||
|
int i;
|
||||||
SSL_CTX* ctx;
|
SSL_CTX* ctx;
|
||||||
bool opt_ver = true; /* verify peer certificate */
|
bool opt_ver = true; /* verify peer certificate */
|
||||||
char *opt_cert = NULL; /* file name of client certificate */
|
char *opt_cert = NULL; /* file name of client certificate */
|
||||||
|
@ -280,7 +282,6 @@ static int
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(xfd, &pf);
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
xfd->howtoend = END_SHUTDOWN;
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
@ -340,18 +341,33 @@ static int
|
||||||
Info("starting connect loop");
|
Info("starting connect loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Count addrinfo entries */
|
||||||
|
themp = themlist;
|
||||||
|
i = 0;
|
||||||
|
while (themp != NULL) {
|
||||||
|
++i;
|
||||||
|
themp = themp->ai_next;
|
||||||
|
}
|
||||||
|
ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
|
||||||
|
if (ai_sorted == NULL)
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
/* Generate a list of addresses sorted by preferred ip version */
|
||||||
|
_xio_sort_ip_addresses(themlist, ai_sorted);
|
||||||
|
|
||||||
do { /* loop over failed connect and SSL handshake attempts */
|
do { /* loop over failed connect and SSL handshake attempts */
|
||||||
|
|
||||||
|
/* Loop over ai_sorted list */
|
||||||
|
i = 0;
|
||||||
|
themp = ai_sorted[i++];
|
||||||
|
while (themp != NULL) {
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (xfd->forever || xfd->retry) {
|
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
|
||||||
level = E_INFO;
|
level = E_INFO;
|
||||||
} else
|
} else
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
level = E_ERROR;
|
level = E_ERROR;
|
||||||
|
|
||||||
themp = themlist;
|
|
||||||
/* loop over themlist */
|
|
||||||
while (themp != NULL) {
|
|
||||||
/* This cannot fork because we retrieved fork option above */
|
/* This cannot fork because we retrieved fork option above */
|
||||||
result =
|
result =
|
||||||
_xioopen_connect(xfd,
|
_xioopen_connect(xfd,
|
||||||
|
@ -360,7 +376,7 @@ static int
|
||||||
opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level);
|
opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level);
|
||||||
if (result == STAT_OK)
|
if (result == STAT_OK)
|
||||||
break;
|
break;
|
||||||
themp = themp->ai_next;
|
themp = ai_sorted[i++];
|
||||||
if (themp == NULL) {
|
if (themp == NULL) {
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -378,16 +394,16 @@ static int
|
||||||
--xfd->retry;
|
--xfd->retry;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
xiofreeaddrinfo(themlist);
|
free(ai_sorted);
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
xiofreeaddrinfo(themlist);
|
free(ai_sorted);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/*! isn't this too early? */
|
/*! isn't this too early? */
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||||
xiofreeaddrinfo(themlist);
|
free(ai_sorted);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,6 +465,7 @@ static int
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
break;
|
break;
|
||||||
} while (true); /* drop out on success */
|
} while (true); /* drop out on success */
|
||||||
|
free(ai_sorted);
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themlist);
|
||||||
|
|
||||||
openssl_conn_loginfo(xfd->para.openssl.ssl);
|
openssl_conn_loginfo(xfd->para.openssl.ssl);
|
||||||
|
@ -572,7 +589,6 @@ static int
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(xfd, &pf);
|
|
||||||
#if WITH_IP4 && WITH_IP6
|
#if WITH_IP4 && WITH_IP6
|
||||||
switch (xioparms.default_ip) {
|
switch (xioparms.default_ip) {
|
||||||
case '4': pf = PF_INET; break;
|
case '4': pf = PF_INET; break;
|
||||||
|
|
53
xio-proxy.c
53
xio-proxy.c
|
@ -93,6 +93,8 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
union sockaddr_union us_sa, *us = &us_sa;
|
union sockaddr_union us_sa, *us = &us_sa;
|
||||||
socklen_t uslen = sizeof(us_sa);
|
socklen_t uslen = sizeof(us_sa);
|
||||||
struct addrinfo *themlist, *themp;
|
struct addrinfo *themlist, *themp;
|
||||||
|
struct addrinfo **ai_sorted;
|
||||||
|
int i;
|
||||||
const char *proxyname; char *proxyport = NULL;
|
const char *proxyname; char *proxyport = NULL;
|
||||||
const char *targetname, *targetport;
|
const char *targetname, *targetport;
|
||||||
int ipproto = IPPROTO_TCP;
|
int ipproto = IPPROTO_TCP;
|
||||||
|
@ -110,7 +112,6 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
targetname = argv[2];
|
targetname = argv[2];
|
||||||
targetport = argv[3];
|
targetport = argv[3];
|
||||||
|
|
||||||
xioinit_ip(xfd, &pf);
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
xfd->howtoend = END_SHUTDOWN;
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
@ -128,7 +129,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.ai_flags,
|
||||||
xfd->para.socket.ip.res_opts);
|
xfd->para.socket.ip.res_opts);
|
||||||
if (result != STAT_OK) return result;
|
if (result != STAT_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
Notice4("opening connection to %s:%u via proxy %s:%s",
|
||||||
|
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
do { /* loop over retries (failed connect and proxy-request attempts) */
|
||||||
|
|
||||||
|
level = E_INFO;
|
||||||
|
|
||||||
result =
|
result =
|
||||||
_xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
|
_xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
|
||||||
|
@ -137,23 +147,35 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
xfd->para.socket.ip.res_opts,
|
xfd->para.socket.ip.res_opts,
|
||||||
&themlist, us, &uslen,
|
&themlist, us, &uslen,
|
||||||
&needbind, &lowport, socktype);
|
&needbind, &lowport, socktype);
|
||||||
if (result != STAT_OK) return result;
|
if (result != STAT_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* Count addrinfo entries */
|
||||||
|
themp = themlist;
|
||||||
|
i = 0;
|
||||||
|
while (themp != NULL) {
|
||||||
|
++i;
|
||||||
|
themp = themp->ai_next;
|
||||||
|
}
|
||||||
|
ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
|
||||||
|
if (ai_sorted == NULL)
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
/* Generate a list of addresses sorted by preferred ip version */
|
||||||
|
_xio_sort_ip_addresses(themlist, ai_sorted);
|
||||||
|
|
||||||
|
/* Loop over themlist */
|
||||||
|
i = 0;
|
||||||
|
themp = ai_sorted[i++];
|
||||||
|
while (themp != NULL) {
|
||||||
Notice4("opening connection to %s:%u via proxy %s:%s",
|
Notice4("opening connection to %s:%u via proxy %s:%s",
|
||||||
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
|
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
|
||||||
|
|
||||||
do { /* loop over failed connect and proxy connect attempts */
|
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (xfd->forever || xfd->retry) {
|
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
|
||||||
level = E_INFO;
|
level = E_INFO;
|
||||||
} else
|
} else
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
level = E_ERROR;
|
level = E_ERROR;
|
||||||
|
|
||||||
themp = themlist;
|
|
||||||
/* Loop over themlist */
|
|
||||||
while (themp != NULL) {
|
|
||||||
result =
|
result =
|
||||||
_xioopen_connect(xfd,
|
_xioopen_connect(xfd,
|
||||||
needbind?us:NULL, sizeof(*us),
|
needbind?us:NULL, sizeof(*us),
|
||||||
|
@ -161,7 +183,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
|
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
|
||||||
if (result == STAT_OK)
|
if (result == STAT_OK)
|
||||||
break;
|
break;
|
||||||
themp = themp->ai_next;
|
themp = ai_sorted[i++];
|
||||||
if (themp == NULL) {
|
if (themp == NULL) {
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -170,18 +192,19 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
case STAT_RETRYLATER:
|
case STAT_RETRYLATER:
|
||||||
case STAT_RETRYNOW:
|
case STAT_RETRYNOW:
|
||||||
if (xfd->forever || xfd->retry--) {
|
if (xfd->forever || xfd->retry) {
|
||||||
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
|
--xfd->retry;
|
||||||
|
if (result == STAT_RETRYLATER)
|
||||||
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
|
free(ai_sorted);
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themlist);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xiofreeaddrinfo(themlist);
|
|
||||||
applyopts(xfd->fd, opts, PH_ALL);
|
|
||||||
|
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -74,7 +74,7 @@ int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xxfd->stream, &pf);
|
xioinit_ip(&pf, xioparms.preferred_ip);
|
||||||
if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||||
groups, &pf)) != STAT_OK) {
|
groups, &pf)) != STAT_OK) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -165,7 +165,7 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(xfd, &pf);
|
xioinit_ip(&pf, xioparms.preferred_ip);
|
||||||
if ((result =
|
if ((result =
|
||||||
_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||||
groups, &pf)) != STAT_OK) {
|
groups, &pf)) != STAT_OK) {
|
||||||
|
@ -220,7 +220,7 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xfd->stream, &pf);
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
|
if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
|
||||||
Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
|
Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
|
||||||
protname, ipproto);
|
protname, ipproto);
|
||||||
|
@ -284,7 +284,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xfd->stream, &pf);
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
|
if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
|
||||||
Error2("xioopen_rawip_recv(\"%s\",,): protocol number exceeds 255 (%u)",
|
Error2("xioopen_rawip_recv(\"%s\",,): protocol number exceeds 255 (%u)",
|
||||||
protname, ipproto);
|
protname, ipproto);
|
||||||
|
|
68
xio-socks.c
68
xio-socks.c
|
@ -54,6 +54,8 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
union sockaddr_union us_sa, *us = &us_sa;
|
union sockaddr_union us_sa, *us = &us_sa;
|
||||||
socklen_t uslen = sizeof(us_sa);
|
socklen_t uslen = sizeof(us_sa);
|
||||||
struct addrinfo *themlist, *themp;
|
struct addrinfo *themlist, *themp;
|
||||||
|
struct addrinfo **ai_sorted;
|
||||||
|
int i;
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
|
@ -72,7 +74,6 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
targetname = argv[2];
|
targetname = argv[2];
|
||||||
targetport = argv[3];
|
targetport = argv[3];
|
||||||
|
|
||||||
xioinit_ip(xfd, &pf);
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
xfd->howtoend = END_SHUTDOWN;
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
@ -82,7 +83,19 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
retropt_bool(opts, OPT_FORK, &dofork);
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
|
||||||
result = _xioopen_socks4_prepare(targetport, opts, &socksport, sockhead, &buflen);
|
result = _xioopen_socks4_prepare(targetport, opts, &socksport, sockhead, &buflen);
|
||||||
if (result != STAT_OK) return result;
|
if (result != STAT_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
|
||||||
|
targetname,
|
||||||
|
ntohs(sockhead->port),
|
||||||
|
sockdname, socksport, sockhead->userid);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
do { /* loop over retries (failed connect and socks-request attempts) */
|
||||||
|
|
||||||
|
level = E_INFO;
|
||||||
|
|
||||||
result =
|
result =
|
||||||
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
|
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
|
||||||
&pf, ipproto,
|
&pf, ipproto,
|
||||||
|
@ -91,19 +104,18 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
&themlist, us, &uslen,
|
&themlist, us, &uslen,
|
||||||
&needbind, &lowport, socktype);
|
&needbind, &lowport, socktype);
|
||||||
|
|
||||||
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
|
/* Count addrinfo entries */
|
||||||
targetname,
|
themp = themlist;
|
||||||
ntohs(sockhead->port),
|
i = 0;
|
||||||
sockdname, socksport, sockhead->userid);
|
while (themp != NULL) {
|
||||||
|
++i;
|
||||||
do { /* loop over failed connect and socks-request attempts */
|
themp = themp->ai_next;
|
||||||
|
}
|
||||||
#if WITH_RETRY
|
ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
|
||||||
if (xfd->forever || xfd->retry) {
|
if (ai_sorted == NULL)
|
||||||
level = E_INFO;
|
return STAT_RETRYLATER;
|
||||||
} else
|
/* Generate a list of addresses sorted by preferred ip version */
|
||||||
#endif /* WITH_RETRY */
|
_xio_sort_ip_addresses(themlist, ai_sorted);
|
||||||
level = E_ERROR;
|
|
||||||
|
|
||||||
/* we try to resolve the target address _before_ connecting to the socks
|
/* we try to resolve the target address _before_ connecting to the socks
|
||||||
server: this avoids unnecessary socks connects and timeouts */
|
server: this avoids unnecessary socks connects and timeouts */
|
||||||
|
@ -124,41 +136,51 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
themp = themlist;
|
|
||||||
/* loop over themlist */
|
/* loop over themlist */
|
||||||
|
i = 0;
|
||||||
|
themp = ai_sorted[i++];
|
||||||
while (themp != NULL) {
|
while (themp != NULL) {
|
||||||
Notice1("opening connection to %s",
|
Notice1("opening connection to %s",
|
||||||
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
|
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
|
||||||
infobuff, sizeof(infobuff)));
|
infobuff, sizeof(infobuff)));
|
||||||
|
#if WITH_RETRY
|
||||||
|
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
|
||||||
|
level = E_INFO;
|
||||||
|
} else
|
||||||
|
#endif /* WITH_RETRY */
|
||||||
|
level = E_ERROR;
|
||||||
|
|
||||||
/* this cannot fork because we retrieved fork option above */
|
/* this cannot fork because we retrieved fork option above */
|
||||||
result =
|
result =
|
||||||
_xioopen_connect(xfd,
|
_xioopen_connect(xfd,
|
||||||
needbind?us:NULL, sizeof(*us),
|
needbind?us:NULL, sizeof(*us),
|
||||||
themp->ai_addr, themp->ai_addrlen,
|
themp->ai_addr, themp->ai_addrlen,
|
||||||
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
|
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP,
|
||||||
|
lowport, level);
|
||||||
if (result == STAT_OK)
|
if (result == STAT_OK)
|
||||||
break;
|
break;
|
||||||
themp = themp->ai_next;
|
themp = ai_sorted[i++];
|
||||||
if (themp == NULL) {
|
if (themp == NULL) {
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case STAT_OK: break;
|
case STAT_OK: break;
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
case STAT_RETRYLATER:
|
case STAT_RETRYLATER:
|
||||||
case STAT_RETRYNOW:
|
case STAT_RETRYNOW:
|
||||||
if (xfd->forever || xfd->retry--) {
|
if (xfd->forever || xfd->retry) {
|
||||||
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
|
--xfd->retry;
|
||||||
|
if (result == STAT_RETRYLATER)
|
||||||
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
|
free(ai_sorted);
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themlist);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
xiofreeaddrinfo(themlist);
|
|
||||||
applyopts(xfd->fd, opts, PH_ALL);
|
|
||||||
|
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
13
xio-udp.c
13
xio-udp.c
|
@ -297,7 +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);
|
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xfd->stream, &pf);
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
if (pf == PF_UNSPEC) {
|
if (pf == PF_UNSPEC) {
|
||||||
#if WITH_IP4 && WITH_IP6
|
#if WITH_IP4 && WITH_IP6
|
||||||
switch (xioparms.default_ip) {
|
switch (xioparms.default_ip) {
|
||||||
|
@ -354,7 +354,7 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xfd->stream, &pf);
|
//xioinit_ip(&pf, xioparms.preferred_ip);
|
||||||
retropt_socket_pf(opts, &pf);
|
retropt_socket_pf(opts, &pf);
|
||||||
if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xfd,
|
if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xfd,
|
||||||
groups, pf, socktype, ipproto))
|
groups, pf, socktype, ipproto))
|
||||||
|
@ -451,7 +451,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(xfd, &pf);
|
//xioinit_ip(&pf, xioparms.preferred_ip);
|
||||||
if ((hostname = strdup(argv[1])) == NULL) {
|
if ((hostname = strdup(argv[1])) == NULL) {
|
||||||
Error1("strdup(\"%s\"): out of memory", argv[1]);
|
Error1("strdup(\"%s\"): out of memory", argv[1]);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
|
@ -516,7 +516,7 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xfd->stream, &pf);
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
xfd->stream.howtoend = END_NONE;
|
xfd->stream.howtoend = END_NONE;
|
||||||
retropt_socket_pf(opts, &pf);
|
retropt_socket_pf(opts, &pf);
|
||||||
if (pf == PF_UNSPEC) {
|
if (pf == PF_UNSPEC) {
|
||||||
|
@ -541,8 +541,7 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
|
|
||||||
if ((result =
|
if ((result =
|
||||||
xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen,
|
xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen,
|
||||||
ai_flags2,
|
ai_flags2, xfd->stream.para.socket.ip.res_opts))
|
||||||
xfd->stream.para.socket.ip.res_opts))
|
|
||||||
!= STAT_OK) {
|
!= STAT_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -602,7 +601,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&xfd->stream, &pf);
|
//xioinit_ip(&pf, xioparms.default_ip);
|
||||||
retropt_socket_pf(opts, &pf);
|
retropt_socket_pf(opts, &pf);
|
||||||
if (pf == PF_UNSPEC) {
|
if (pf == PF_UNSPEC) {
|
||||||
#if WITH_IP4 && WITH_IP6
|
#if WITH_IP4 && WITH_IP6
|
||||||
|
|
|
@ -95,9 +95,11 @@ int xioinitialize(void) {
|
||||||
switch (preferred_ip[0]) {
|
switch (preferred_ip[0]) {
|
||||||
case '4':
|
case '4':
|
||||||
case '6':
|
case '6':
|
||||||
xioparms.preferred_ip = preferred_ip[0]; break;
|
xioparms.preferred_ip = preferred_ip[0];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
xioparms.preferred_ip = '0'; break;
|
xioparms.preferred_ip = '0';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -386,9 +386,9 @@ xiofile_t *xioopen(const char *addr, /* address specification */
|
||||||
int xioflags) {
|
int xioflags) {
|
||||||
xiofile_t *xfd;
|
xiofile_t *xfd;
|
||||||
|
|
||||||
if (xioinitialize() < 0) {
|
//if (xioinitialize() < 0) {
|
||||||
return NULL;
|
// return NULL;
|
||||||
}
|
//}
|
||||||
|
|
||||||
Debug1("xioopen(\"%s\")", addr);
|
Debug1("xioopen(\"%s\")", addr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue