mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 07:22:34 +00:00
Reworked domain name resolution, centralized IPv4/IPv6 sorting
This commit is contained in:
parent
127280088c
commit
ec0e1ca20c
10 changed files with 258 additions and 183 deletions
2
CHANGES
2
CHANGES
|
@ -46,6 +46,8 @@ Corrections:
|
||||||
Thanks to Heinrich Schuchardt from Canonical for reporting and sending
|
Thanks to Heinrich Schuchardt from Canonical for reporting and sending
|
||||||
a patch.
|
a patch.
|
||||||
|
|
||||||
|
Reworked domain name resolution, centralized IPv4/IPv6 sorting.
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
Total inactivity timeout option -T 0 now means 0.0 seconds; up to
|
Total inactivity timeout option -T 0 now means 0.0 seconds; up to
|
||||||
version 1.8.0.0 it meant no total inactivity timeout.
|
version 1.8.0.0 it meant no total inactivity timeout.
|
||||||
|
|
89
test.sh
89
test.sh
|
@ -4969,6 +4969,7 @@ EOF
|
||||||
|
|
||||||
#0 if ! sed 's/.*\r//g' "$tpo" |diff -q "$tr" - >/dev/null 2>&1; then
|
#0 if ! sed 's/.*\r//g' "$tpo" |diff -q "$tr" - >/dev/null 2>&1; then
|
||||||
#0 if ! sed 's/.*'"$($ECHO '\r\c')"'/</g' "$tpo" |diff -q "$tr" - >/dev/null 2>&1; then
|
#0 if ! sed 's/.*'"$($ECHO '\r\c')"'/</g' "$tpo" |diff -q "$tr" - >/dev/null 2>&1; then
|
||||||
|
kill $pid 2>/dev/null # necc on OpenBSD
|
||||||
wait
|
wait
|
||||||
if ! tr "$($ECHO '\r \c')" "% " <$tpo |sed 's/%$//g' |sed 's/.*%//g' |diff "$tr" - >"$tdiff" 2>&1; then
|
if ! tr "$($ECHO '\r \c')" "% " <$tpo |sed 's/%$//g' |sed 's/.*%//g' |diff "$tr" - >"$tdiff" 2>&1; then
|
||||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
|
@ -4985,7 +4986,6 @@ else
|
||||||
numOK=$((numOK+1))
|
numOK=$((numOK+1))
|
||||||
listOK="$listOK $N"
|
listOK="$listOK $N"
|
||||||
fi
|
fi
|
||||||
kill $pid 2>/dev/null # necc on OpenBSD
|
|
||||||
wait
|
wait
|
||||||
MICROS=$SAVEMICS
|
MICROS=$SAVEMICS
|
||||||
TERM="$SAVETERM"
|
TERM="$SAVETERM"
|
||||||
|
@ -19339,7 +19339,7 @@ elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
"IP4 TCP LISTEN STDIO UNIX" \
|
"IP4 TCP LISTEN STDIO UNIX SOCKS4" \
|
||||||
"TCP4-LISTEN PIPE STDIN STDOUT TCP4 UNIX UNIX-LISTEN" \
|
"TCP4-LISTEN PIPE STDIN STDOUT TCP4 UNIX UNIX-LISTEN" \
|
||||||
"so-reuseaddr" \
|
"so-reuseaddr" \
|
||||||
"tcp4 unix" ); then
|
"tcp4 unix" ); then
|
||||||
|
@ -20234,7 +20234,7 @@ else
|
||||||
rc0=$?
|
rc0=$?
|
||||||
if [ "$rc0" -ne 0 ]; then
|
if [ "$rc0" -ne 0 ]; then
|
||||||
$PRINTF "$FAILED (rc0=$rc0)\n"
|
$PRINTF "$FAILED (rc0=$rc0)\n"
|
||||||
echo "$CMD0 &"
|
echo "$CMD0"
|
||||||
cat "${te}0" >&2
|
cat "${te}0" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
|
@ -20257,6 +20257,89 @@ UDPLITE-SENDTO udplite4 PORT
|
||||||
IP-SENDTO ip4 PROTO
|
IP-SENDTO ip4 PROTO
|
||||||
"
|
"
|
||||||
|
|
||||||
|
# Test if CONNECT to a server name that resolves to IPv6 first and IPv4
|
||||||
|
# as second address, when binding to an IPv4 address, uses IPv4
|
||||||
|
# This failed in Socat 1.8.0.0
|
||||||
|
while read ADDR protov IPPORT _; do
|
||||||
|
if [ -z "$ADDR" ] || [[ "$ADDR" == \#* ]]; then continue; fi
|
||||||
|
FEATS=
|
||||||
|
ADDR_="$(echo $ADDR |tr - _)" # TCP_CONNECT
|
||||||
|
PROTO="${ADDR%%[-:]*}" # TCP
|
||||||
|
proto=$(tolower $PROTO) # tcp
|
||||||
|
FEATS="$FEATS $PROTO"
|
||||||
|
NAME="$(echo "V1800_${ADDR_}_CONNECT_6_4" |sed 's/:[.0-8]*//')"
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%bugs%*|*%ip4%*|*%$protov%*|*%$proto%*|*%socket%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: test regression of $ADDR with IPv6,4 and binding to IPv4"
|
||||||
|
# Run an appropriate server address in background.
|
||||||
|
# Start a CONNECT command to (internal) test name localhost-6-4.dest-unreach.net
|
||||||
|
# and bind to an IPv4 address, connect, terminate immediately.
|
||||||
|
# When no error occurs the test succeeded.
|
||||||
|
if ! eval $NUMCOND; then :
|
||||||
|
elif ! cond=$(checkconds \
|
||||||
|
"" \
|
||||||
|
"" \
|
||||||
|
"" \
|
||||||
|
"$FEATS DEVTESTS IP4" \
|
||||||
|
"$ADDR GOPEN" \
|
||||||
|
"bind" \
|
||||||
|
"$protov" ); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
namesCANT="$namesCANT $NAME"
|
||||||
|
else
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
case X$IPPORT in
|
||||||
|
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
||||||
|
XPROTO) echo "IPPROTO=\"$IPPROTO\""
|
||||||
|
_PORT=$IPPROTO ;;
|
||||||
|
esac
|
||||||
|
CMD0="$TRACE $SOCAT $opts ${ADDR%%-*}-LISTEN:$_PORT,pf=ip4 PIPE"
|
||||||
|
CMD1="$TRACE $SOCAT $opts /dev/null $ADDR:localhost-6-4.dest-unreach.net:$_PORT,bind=127.0.0.1"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
$CMD0 2>"${te}0" </dev/null &
|
||||||
|
pid0=$!
|
||||||
|
wait${protov}port $PORT 1
|
||||||
|
$CMD1 2>"${te}1" </dev/null
|
||||||
|
rc1=$?
|
||||||
|
kill $pid0 2>/dev/null; wait
|
||||||
|
if [ "$rc1" -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED (rc1=$rc1)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
listOK="$listOK $N"
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
PORT=$((PORT+1))
|
||||||
|
N=$((N+1))
|
||||||
|
done <<<"
|
||||||
|
TCP-CONNECT tcp4 PORT
|
||||||
|
SCTP-CONNECT sctp4 PORT
|
||||||
|
DCCP-CONNECT dccp4 PORT
|
||||||
|
#PENSSL tcp4 PORT
|
||||||
|
#OCKS4:127.0.0.1 tcp4 PORT
|
||||||
|
#OCKS4A:127.0.0.1 tcp4 PORT
|
||||||
|
#OCKS5:127.0.0.1:1080 tcp4 PORT
|
||||||
|
#ROXY::127.0.0.1 tcp4 PORT
|
||||||
|
"
|
||||||
|
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
|
130
xio-ip.c
130
xio-ip.c
|
@ -363,7 +363,7 @@ static int xioip_freeaddrinfo_devtests(
|
||||||
#endif /* WITH_DEVTESTS */
|
#endif /* WITH_DEVTESTS */
|
||||||
|
|
||||||
|
|
||||||
/* the ultimate(?) socat resolver function
|
/* A socat resolver function
|
||||||
node: the address to be resolved; supported forms:
|
node: the address to be resolved; supported forms:
|
||||||
1.2.3.4 (IPv4 address)
|
1.2.3.4 (IPv4 address)
|
||||||
[::2] (IPv6 address)
|
[::2] (IPv6 address)
|
||||||
|
@ -376,7 +376,7 @@ static int xioip_freeaddrinfo_devtests(
|
||||||
res: a pointer to an uninitialized ptr var for the resulting socket address
|
res: a pointer to an uninitialized ptr var for the resulting socket address
|
||||||
returns: STAT_OK, STAT_RETRYLATER, STAT_NORETRY, prints message
|
returns: STAT_OK, STAT_RETRYLATER, STAT_NORETRY, prints message
|
||||||
*/
|
*/
|
||||||
int xiogetaddrinfo(const char *node, const char *service,
|
int _xiogetaddrinfo(const char *node, const char *service,
|
||||||
int family, int socktype, int protocol,
|
int family, int socktype, int protocol,
|
||||||
struct addrinfo **res, const int ai_flags[2]) {
|
struct addrinfo **res, const int ai_flags[2]) {
|
||||||
char *numnode = NULL;
|
char *numnode = NULL;
|
||||||
|
@ -388,11 +388,11 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
#endif
|
#endif
|
||||||
int error_num;
|
int error_num;
|
||||||
|
|
||||||
Debug8("xiogetaddrinfo(node=\"%s\", service=\"%s\", family=%d, socktype=%d, protoco=%d, ai_flags={0x%04x/0x%04x} }, res=%p",
|
Debug8("_xiogetaddrinfo(node=\"%s\", service=\"%s\", family=%d, socktype=%d, protoco=%d, ai_flags={0x%04x/0x%04x} }, res=%p",
|
||||||
node?node:"NULL", service?service:"NULL", family, socktype, protocol,
|
node?node:"NULL", service?service:"NULL", family, socktype, protocol,
|
||||||
ai_flags?ai_flags[0]:0, ai_flags?ai_flags[1]:0, res);
|
ai_flags?ai_flags[0]:0, ai_flags?ai_flags[1]:0, res);
|
||||||
if (service && service[0]=='\0') {
|
if (service && service[0]=='\0') {
|
||||||
Error("xiogetaddrinfo(): empty port and service");
|
Error("_xiogetaddrinfo(): empty port and service");
|
||||||
return EAI_NONAME;
|
return EAI_NONAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
if (host->h_addrtype != family) {
|
if (host->h_addrtype != family) {
|
||||||
Error2("xiogetaddrinfo(): \"%s\" does not resolve to %s",
|
Error2("_xiogetaddrinfo(): \"%s\" does not resolve to %s",
|
||||||
node, family==PF_INET?"IP4":"IP6");
|
node, family==PF_INET?"IP4":"IP6");
|
||||||
} else {
|
} else {
|
||||||
switch (family) {
|
switch (family) {
|
||||||
|
@ -653,7 +653,97 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xiofreeaddrinfo(struct addrinfo *res) {
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrapper around _xiogetaddrinfo() (which is a wrapper arount getaddrinfo())
|
||||||
|
that sorts the results according to xioparms.preferred_ip when family is
|
||||||
|
AF_UNSPEC; it returns an array of record pointers instead of a list! */
|
||||||
|
int xiogetaddrinfo(const char *node, const char *service,
|
||||||
|
int family, int socktype, int protocol,
|
||||||
|
struct addrinfo ***ai_sorted, const int ai_flags[2]) {
|
||||||
|
struct addrinfo *res;
|
||||||
|
struct addrinfo **_ai_sorted;
|
||||||
|
struct addrinfo *aip;
|
||||||
|
int ain;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = _xiogetaddrinfo(node, service, family, socktype, protocol, &res,
|
||||||
|
ai_flags);
|
||||||
|
if (rc != 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Sort results - first, count records for mem allocation */
|
||||||
|
aip = res;
|
||||||
|
ain = 0;
|
||||||
|
while (aip != NULL) {
|
||||||
|
++ain;
|
||||||
|
aip = aip->ai_next;
|
||||||
|
}
|
||||||
|
_ai_sorted = Calloc((ain+2), sizeof(struct addrinfo *));
|
||||||
|
if (_ai_sorted == NULL)
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
|
||||||
|
/* Generate a list of addresses sorted by preferred ip version */
|
||||||
|
_xio_sort_ip_addresses(res, _ai_sorted);
|
||||||
|
_ai_sorted[ain+1] = res; /* save list past NULL for later freeing */
|
||||||
|
*ai_sorted = _ai_sorted;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _xiofreeaddrinfo(struct addrinfo *res) {
|
||||||
#if WITH_DEVTESTS
|
#if WITH_DEVTESTS
|
||||||
if (!xioip_freeaddrinfo_devtests(res)) {
|
if (!xioip_freeaddrinfo_devtests(res)) {
|
||||||
return;
|
return;
|
||||||
|
@ -666,6 +756,20 @@ void xiofreeaddrinfo(struct addrinfo *res) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xiofreeaddrinfo(struct addrinfo **ai_sorted) {
|
||||||
|
int ain;
|
||||||
|
struct addrinfo *res;
|
||||||
|
|
||||||
|
/* Find the original *res from getaddrinfo past NULL */
|
||||||
|
ain = 0;
|
||||||
|
while (ai_sorted[ain] != NULL)
|
||||||
|
++ain;
|
||||||
|
res = ai_sorted[ain+1];
|
||||||
|
_xiofreeaddrinfo(res);
|
||||||
|
free(ai_sorted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* A simple resolver interface that just returns one address,
|
/* A simple resolver interface that just returns one address,
|
||||||
the first found by calling xiogetaddrinfo(), but ev.respects preferred_ip;
|
the first found by calling xiogetaddrinfo(), but ev.respects preferred_ip;
|
||||||
pf may be AF_INET, AF_INET6, or AF_UNSPEC;
|
pf may be AF_INET, AF_INET6, or AF_UNSPEC;
|
||||||
|
@ -677,7 +781,7 @@ int xioresolve(const char *node, const char *service,
|
||||||
union sockaddr_union *addr, socklen_t *addrlen,
|
union sockaddr_union *addr, socklen_t *addrlen,
|
||||||
const int ai_flags[2])
|
const int ai_flags[2])
|
||||||
{
|
{
|
||||||
struct addrinfo *res = NULL;
|
struct addrinfo **res = NULL;
|
||||||
struct addrinfo *aip;
|
struct addrinfo *aip;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -699,17 +803,17 @@ int xioresolve(const char *node, const char *service,
|
||||||
xiofreeaddrinfo(res);
|
xiofreeaddrinfo(res);
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
if (res->ai_addrlen > *addrlen) {
|
if ((*res)->ai_addrlen > *addrlen) {
|
||||||
Error3("xioresolve(node=\"%s\", addrlen="F_socklen", ...): "F_socklen" bytes required",
|
Error3("xioresolve(node=\"%s\", addrlen="F_socklen", ...): "F_socklen" bytes required",
|
||||||
node, *addrlen, res->ai_addrlen);
|
node, *addrlen, (*res)->ai_addrlen);
|
||||||
xiofreeaddrinfo(res);
|
xiofreeaddrinfo(res);
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
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?"\"":"");
|
||||||
}
|
}
|
||||||
|
|
||||||
aip = res;
|
aip = *res;
|
||||||
if (ai_flags != NULL && ai_flags[0] & AI_PASSIVE && pf == PF_UNSPEC) {
|
if (ai_flags != NULL && ai_flags[0] & AI_PASSIVE && pf == PF_UNSPEC) {
|
||||||
/* We select the first IPv6 address, if available,
|
/* We select the first IPv6 address, if available,
|
||||||
because this might accept IPv4 connections too */
|
because this might accept IPv4 connections too */
|
||||||
|
@ -719,7 +823,7 @@ int xioresolve(const char *node, const char *service,
|
||||||
aip = aip->ai_next;
|
aip = aip->ai_next;
|
||||||
}
|
}
|
||||||
if (aip == NULL)
|
if (aip == NULL)
|
||||||
aip = res;
|
aip = *res;
|
||||||
} else if (pf == PF_UNSPEC && xioparms.preferred_ip != '0') {
|
} else if (pf == PF_UNSPEC && xioparms.preferred_ip != '0') {
|
||||||
int prefip = PF_UNSPEC;
|
int prefip = PF_UNSPEC;
|
||||||
xioinit_ip(&prefip, xioparms.preferred_ip);
|
xioinit_ip(&prefip, xioparms.preferred_ip);
|
||||||
|
@ -729,7 +833,7 @@ int xioresolve(const char *node, const char *service,
|
||||||
aip = aip->ai_next;
|
aip = aip->ai_next;
|
||||||
}
|
}
|
||||||
if (aip == NULL)
|
if (aip == NULL)
|
||||||
aip = res;
|
aip = *res;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(addr, aip->ai_addr, aip->ai_addrlen);
|
memcpy(addr, aip->ai_addr, aip->ai_addrlen);
|
||||||
|
|
5
xio-ip.h
5
xio-ip.h
|
@ -49,8 +49,9 @@ extern const struct optdesc opt_res_nsaddr;
|
||||||
|
|
||||||
extern int xioinit_ip(int *pf, char ipv);
|
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]);
|
extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo ***ai_sorted, const int ai_flags[2]);
|
||||||
extern void xiofreeaddrinfo(struct addrinfo *res);
|
extern void xiofreeaddrinfo(struct addrinfo **ai_sorted);
|
||||||
|
extern int _xio_sort_ip_addresses(struct addrinfo *themlist, struct addrinfo **ai_sorted);
|
||||||
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]);
|
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]);
|
||||||
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 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 xiotype_ip_add_membership(char *token, const struct optname *ent, struct opt *opt);
|
||||||
|
|
101
xio-ipapp.c
101
xio-ipapp.c
|
@ -39,12 +39,11 @@ int xioopen_ipapp_connect(
|
||||||
int maxchildren = 0;
|
int maxchildren = 0;
|
||||||
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 **themarr, *themp;
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
int level;
|
int level;
|
||||||
struct addrinfo **ai_sorted;
|
|
||||||
int i;
|
int i;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ int xioopen_ipapp_connect(
|
||||||
|
|
||||||
if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
||||||
sfd->para.socket.ip.ai_flags,
|
sfd->para.socket.ip.ai_flags,
|
||||||
&themlist, us, &uslen, &needbind, &lowport,
|
&themarr, us, &uslen, &needbind, &lowport,
|
||||||
socktype) != STAT_OK) {
|
socktype) != STAT_OK) {
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
@ -94,33 +93,22 @@ int xioopen_ipapp_connect(
|
||||||
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 */
|
||||||
|
|
||||||
/* Loop over themlist - no, over ai_sorted */
|
/* Loop over themarr (which had been "ai_sorted") */
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
i = 0;
|
i = 0;
|
||||||
themp = ai_sorted[i++];
|
themp = themarr[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 (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
|
if (sfd->forever || sfd->retry) {
|
||||||
level = E_INFO;
|
level = E_INFO;
|
||||||
|
} else if (themarr[i] != NULL) {
|
||||||
|
level = E_WARN;
|
||||||
} else
|
} else
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
level = E_ERROR;
|
level = E_ERROR;
|
||||||
|
@ -133,7 +121,7 @@ int xioopen_ipapp_connect(
|
||||||
lowport, level);
|
lowport, level);
|
||||||
if (result == STAT_OK)
|
if (result == STAT_OK)
|
||||||
break;
|
break;
|
||||||
themp = ai_sorted[i++];
|
themp = themarr[i++];
|
||||||
if (themp == NULL) {
|
if (themp == NULL) {
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +141,7 @@ int xioopen_ipapp_connect(
|
||||||
}
|
}
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
free(opts0);free(opts);
|
free(opts0);free(opts);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +158,7 @@ int xioopen_ipapp_connect(
|
||||||
if (sfd->forever || --sfd->retry) {
|
if (sfd->forever || --sfd->retry) {
|
||||||
Nanosleep(&sfd->intervall, NULL); continue;
|
Nanosleep(&sfd->intervall, NULL); continue;
|
||||||
}
|
}
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
free(opts0);
|
free(opts0);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -197,8 +185,7 @@ int xioopen_ipapp_connect(
|
||||||
}
|
}
|
||||||
} 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(themarr);
|
||||||
xiofreeaddrinfo(themlist);
|
|
||||||
|
|
||||||
if ((result = _xio_openlate(sfd, opts)) < 0) {
|
if ((result = _xio_openlate(sfd, opts)) < 0) {
|
||||||
free(opts0);free(opts);
|
free(opts0);free(opts);
|
||||||
|
@ -223,7 +210,7 @@ int
|
||||||
int *pf,
|
int *pf,
|
||||||
int protocol,
|
int protocol,
|
||||||
const int ai_flags[2],
|
const int ai_flags[2],
|
||||||
struct addrinfo **themlist,
|
struct addrinfo ***themarr,
|
||||||
union sockaddr_union *us,
|
union sockaddr_union *us,
|
||||||
socklen_t *uslen,
|
socklen_t *uslen,
|
||||||
bool *needbind,
|
bool *needbind,
|
||||||
|
@ -236,7 +223,7 @@ int
|
||||||
|
|
||||||
if (hostname != NULL || portname != NULL) {
|
if (hostname != NULL || portname != NULL) {
|
||||||
rc = xiogetaddrinfo(hostname, portname, *pf, socktype, protocol,
|
rc = xiogetaddrinfo(hostname, portname, *pf, socktype, protocol,
|
||||||
themlist, ai_flags);
|
themarr, ai_flags);
|
||||||
if (rc == EAI_AGAIN) {
|
if (rc == EAI_AGAIN) {
|
||||||
Warn4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s",
|
Warn4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s",
|
||||||
hostname?hostname:"NULL", portname?portname:"NULL",
|
hostname?hostname:"NULL", portname?portname:"NULL",
|
||||||
|
@ -253,13 +240,13 @@ int
|
||||||
applyopts(NULL, -1, opts, PH_EARLY);
|
applyopts(NULL, -1, opts, PH_EARLY);
|
||||||
|
|
||||||
/* 3 means: IP address AND port accepted */
|
/* 3 means: IP address AND port accepted */
|
||||||
if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family,
|
if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family,
|
||||||
socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
||||||
ai_flags)
|
ai_flags)
|
||||||
!= STAT_NOACTION) {
|
!= STAT_NOACTION) {
|
||||||
*needbind = true;
|
*needbind = true;
|
||||||
} else {
|
} else {
|
||||||
switch ((*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family) {
|
switch ((*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family) {
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
case PF_INET: socket_in_init(&us->ip4); *uslen = sizeof(us->ip4); break;
|
case PF_INET: socket_in_init(&us->ip4); *uslen = sizeof(us->ip4); break;
|
||||||
#endif /* WITH_IP4 */
|
#endif /* WITH_IP4 */
|
||||||
|
@ -271,7 +258,7 @@ int
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retropt_2bytes(opts, OPT_SOURCEPORT, &port) >= 0) {
|
if (retropt_2bytes(opts, OPT_SOURCEPORT, &port) >= 0) {
|
||||||
switch ((*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family) {
|
switch ((*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family) {
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
case PF_INET: us->ip4.sin_port = htons(port); break;
|
case PF_INET: us->ip4.sin_port = htons(port); break;
|
||||||
#endif /* WITH_IP4 */
|
#endif /* WITH_IP4 */
|
||||||
|
@ -397,60 +384,4 @@ int xioopen_ipapp_listen(
|
||||||
}
|
}
|
||||||
#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 */
|
||||||
|
|
|
@ -15,13 +15,12 @@ extern const struct optdesc opt_sourceport;
|
||||||
extern const struct optdesc opt_lowport;
|
extern const struct optdesc opt_lowport;
|
||||||
|
|
||||||
extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||||
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], 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], struct addrinfo ***themlist, union sockaddr_union *us, socklen_t *uslen, bool *needbind, bool *lowport, int socktype);
|
||||||
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
|
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
|
||||||
struct single *xfd,
|
struct single *xfd,
|
||||||
int socktype, int ipproto, void *protname,
|
int socktype, int ipproto, void *protname,
|
||||||
struct opt *opts);
|
struct opt *opts);
|
||||||
extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||||
extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, const int ai_flags[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], 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) */
|
||||||
|
|
|
@ -241,11 +241,10 @@ static int xioopen_openssl_connect(
|
||||||
bool dofork = false;
|
bool dofork = false;
|
||||||
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 **themarr, *themp;
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
int level = E_ERROR;
|
int level = E_ERROR;
|
||||||
struct addrinfo **ai_sorted;
|
|
||||||
int i;
|
int i;
|
||||||
SSL_CTX* ctx;
|
SSL_CTX* ctx;
|
||||||
bool opt_ver = true; /* verify peer certificate */
|
bool opt_ver = true; /* verify peer certificate */
|
||||||
|
@ -323,7 +322,7 @@ static int xioopen_openssl_connect(
|
||||||
result =
|
result =
|
||||||
_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
||||||
sfd->para.socket.ip.ai_flags,
|
sfd->para.socket.ip.ai_flags,
|
||||||
&themlist, us, &uslen,
|
&themarr, us, &uslen,
|
||||||
&needbind, &lowport, socktype);
|
&needbind, &lowport, socktype);
|
||||||
if (result != STAT_OK) return STAT_NORETRY;
|
if (result != STAT_OK) return STAT_NORETRY;
|
||||||
|
|
||||||
|
@ -334,28 +333,15 @@ static int xioopen_openssl_connect(
|
||||||
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 */
|
/* Loop over themarr (which had been "ai_sorted") */
|
||||||
i = 0;
|
i = 0;
|
||||||
themp = ai_sorted[i++];
|
themp = themarr[i++];
|
||||||
while (themp != NULL) {
|
while (themp != NULL) {
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
|
if (sfd->forever || sfd->retry || themarr[i] != NULL) {
|
||||||
level = E_INFO;
|
level = E_INFO;
|
||||||
} else
|
} else
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
|
@ -369,7 +355,7 @@ static int xioopen_openssl_connect(
|
||||||
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 = ai_sorted[i++];
|
themp = themarr[i++];
|
||||||
if (themp == NULL) {
|
if (themp == NULL) {
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -387,16 +373,16 @@ static int xioopen_openssl_connect(
|
||||||
--sfd->retry;
|
--sfd->retry;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/*! isn't this too early? */
|
/*! isn't this too early? */
|
||||||
if ((result = _xio_openlate(sfd, opts)) < 0) {
|
if ((result = _xio_openlate(sfd, opts)) < 0) {
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +404,7 @@ static int xioopen_openssl_connect(
|
||||||
}
|
}
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themarr);
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,7 +423,7 @@ static int xioopen_openssl_connect(
|
||||||
if (sfd->forever || --sfd->retry) {
|
if (sfd->forever || --sfd->retry) {
|
||||||
Nanosleep(&sfd->intervall, NULL); continue;
|
Nanosleep(&sfd->intervall, NULL); continue;
|
||||||
}
|
}
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themarr);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,8 +444,7 @@ static int xioopen_openssl_connect(
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
break;
|
break;
|
||||||
} while (true); /* drop out on success */
|
} while (true); /* drop out on success */
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
xiofreeaddrinfo(themlist);
|
|
||||||
|
|
||||||
openssl_conn_loginfo(sfd->para.openssl.ssl);
|
openssl_conn_loginfo(sfd->para.openssl.ssl);
|
||||||
|
|
||||||
|
|
29
xio-proxy.c
29
xio-proxy.c
|
@ -93,8 +93,7 @@ static int xioopen_proxy_connect(
|
||||||
int pf = PF_UNSPEC;
|
int pf = PF_UNSPEC;
|
||||||
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 **themarr, *themp;
|
||||||
struct addrinfo **ai_sorted;
|
|
||||||
int i;
|
int i;
|
||||||
const char *proxyname; char *proxyport = NULL;
|
const char *proxyname; char *proxyport = NULL;
|
||||||
const char *targetname, *targetport;
|
const char *targetname, *targetport;
|
||||||
|
@ -146,32 +145,19 @@ static int xioopen_proxy_connect(
|
||||||
_xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
|
_xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
|
||||||
&pf, ipproto,
|
&pf, ipproto,
|
||||||
sfd->para.socket.ip.ai_flags,
|
sfd->para.socket.ip.ai_flags,
|
||||||
&themlist, us, &uslen,
|
&themarr, us, &uslen,
|
||||||
&needbind, &lowport, socktype);
|
&needbind, &lowport, socktype);
|
||||||
if (result != STAT_OK)
|
if (result != STAT_OK)
|
||||||
return result;
|
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 */
|
/* Loop over themlist */
|
||||||
i = 0;
|
i = 0;
|
||||||
themp = ai_sorted[i++];
|
themp = themarr[i++];
|
||||||
while (themp != NULL) {
|
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);
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
|
if (sfd->forever || sfd->retry || themarr[i] != NULL) {
|
||||||
level = E_INFO;
|
level = E_INFO;
|
||||||
} else
|
} else
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
|
@ -184,7 +170,7 @@ static int xioopen_proxy_connect(
|
||||||
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 = ai_sorted[i++];
|
themp = themarr[i++];
|
||||||
if (themp == NULL) {
|
if (themp == NULL) {
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -201,12 +187,11 @@ static int xioopen_proxy_connect(
|
||||||
}
|
}
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
xiofreeaddrinfo(themlist);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themarr);
|
||||||
applyopts(sfd, -1, opts, PH_ALL);
|
applyopts(sfd, -1, opts, PH_ALL);
|
||||||
|
|
||||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||||
|
|
31
xio-socks.c
31
xio-socks.c
|
@ -55,8 +55,7 @@ static int xioopen_socks4_connect(
|
||||||
bool dofork = false;
|
bool dofork = false;
|
||||||
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 **themarr, *themp;
|
||||||
struct addrinfo **ai_sorted;
|
|
||||||
int i;
|
int i;
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
|
@ -103,22 +102,9 @@ static int xioopen_socks4_connect(
|
||||||
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
|
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
|
||||||
&pf, ipproto,
|
&pf, ipproto,
|
||||||
sfd->para.socket.ip.ai_flags,
|
sfd->para.socket.ip.ai_flags,
|
||||||
&themlist, us, &uslen,
|
&themarr, us, &uslen,
|
||||||
&needbind, &lowport, socktype);
|
&needbind, &lowport, socktype);
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* 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 */
|
||||||
result =
|
result =
|
||||||
|
@ -139,15 +125,15 @@ static int xioopen_socks4_connect(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loop over themlist */
|
/* loop over themarr */
|
||||||
i = 0;
|
i = 0;
|
||||||
themp = ai_sorted[i++];
|
themp = themarr[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 (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
|
if (sfd->forever || sfd->retry || themarr[i] != NULL) {
|
||||||
level = E_INFO;
|
level = E_INFO;
|
||||||
} else
|
} else
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
|
@ -161,7 +147,7 @@ static int xioopen_socks4_connect(
|
||||||
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 = ai_sorted[i++];
|
themp = themarr[i++];
|
||||||
if (themp == NULL)
|
if (themp == NULL)
|
||||||
result = STAT_RETRYLATER;
|
result = STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -178,11 +164,10 @@ static int xioopen_socks4_connect(
|
||||||
}
|
}
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
default:
|
default:
|
||||||
free(ai_sorted);
|
xiofreeaddrinfo(themarr);
|
||||||
xiofreeaddrinfo(themlist);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themarr);
|
||||||
applyopts(sfd, -1, opts, PH_ALL);
|
applyopts(sfd, -1, opts, PH_ALL);
|
||||||
|
|
||||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||||
|
|
12
xio-socks5.c
12
xio-socks5.c
|
@ -512,7 +512,7 @@ static int xioopen_socks5(
|
||||||
const char *socks_server, *target_name, *target_port, *socks_port;
|
const char *socks_server, *target_name, *target_port, *socks_port;
|
||||||
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 **themarr, *themp;
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
|
@ -542,7 +542,7 @@ static int xioopen_socks5(
|
||||||
result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port,
|
result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port,
|
||||||
&pf, ipproto,
|
&pf, ipproto,
|
||||||
sfd->para.socket.ip.ai_flags,
|
sfd->para.socket.ip.ai_flags,
|
||||||
&themlist, us, &uslen,
|
&themarr, us, &uslen,
|
||||||
&needbind, &lowport, socktype);
|
&needbind, &lowport, socktype);
|
||||||
|
|
||||||
Notice2("connecting to socks5 server %s:%s",
|
Notice2("connecting to socks5 server %s:%s",
|
||||||
|
@ -557,8 +557,8 @@ static int xioopen_socks5(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* loop over themlist */
|
/* loop over themarr */
|
||||||
themp = themlist;
|
themp = themarr[0];
|
||||||
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,
|
||||||
|
@ -584,11 +584,11 @@ static int xioopen_socks5(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themarr);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xiofreeaddrinfo(themlist);
|
xiofreeaddrinfo(themarr);
|
||||||
applyopts(sfd, -1, opts, PH_ALL);
|
applyopts(sfd, -1, opts, PH_ALL);
|
||||||
|
|
||||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||||
|
|
Loading…
Reference in a new issue