diff --git a/CHANGES b/CHANGES index d15c273..99f8d4c 100644 --- a/CHANGES +++ b/CHANGES @@ -46,6 +46,8 @@ Corrections: Thanks to Heinrich Schuchardt from Canonical for reporting and sending a patch. + Reworked domain name resolution, centralized IPv4/IPv6 sorting. + Features: Total inactivity timeout option -T 0 now means 0.0 seconds; up to version 1.8.0.0 it meant no total inactivity timeout. diff --git a/test.sh b/test.sh index e773dc5..69acc15 100755 --- a/test.sh +++ b/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/.*'"$($ECHO '\r\c')"'//dev/null 2>&1; then +kill $pid 2>/dev/null # necc on OpenBSD wait if ! tr "$($ECHO '\r \c')" "% " <$tpo |sed 's/%$//g' |sed 's/.*%//g' |diff "$tr" - >"$tdiff" 2>&1; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" @@ -4985,7 +4986,6 @@ else numOK=$((numOK+1)) listOK="$listOK $N" fi -kill $pid 2>/dev/null # necc on OpenBSD wait MICROS=$SAVEMICS 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" \ "so-reuseaddr" \ "tcp4 unix" ); then @@ -20234,7 +20234,7 @@ else rc0=$? if [ "$rc0" -ne 0 ]; then $PRINTF "$FAILED (rc0=$rc0)\n" - echo "$CMD0 &" + echo "$CMD0" cat "${te}0" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" @@ -20257,6 +20257,89 @@ UDPLITE-SENDTO udplite4 PORT 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" "${te}1" /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 ################################################################################## diff --git a/xio-ip.c b/xio-ip.c index 7787861..6821571 100644 --- a/xio-ip.c +++ b/xio-ip.c @@ -363,7 +363,7 @@ static int xioip_freeaddrinfo_devtests( #endif /* WITH_DEVTESTS */ -/* the ultimate(?) socat resolver function +/* A socat resolver function node: the address to be resolved; supported forms: 1.2.3.4 (IPv4 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 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, struct addrinfo **res, const int ai_flags[2]) { char *numnode = NULL; @@ -388,11 +388,11 @@ int xiogetaddrinfo(const char *node, const char *service, #endif 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, ai_flags?ai_flags[0]:0, ai_flags?ai_flags[1]:0, res); if (service && service[0]=='\0') { - Error("xiogetaddrinfo(): empty port and service"); + Error("_xiogetaddrinfo(): empty port and service"); return EAI_NONAME; } @@ -620,7 +620,7 @@ int xiogetaddrinfo(const char *node, const char *service, return STAT_RETRYLATER; } 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"); } else { switch (family) { @@ -653,7 +653,97 @@ int xiogetaddrinfo(const char *node, const char *service, 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 (!xioip_freeaddrinfo_devtests(res)) { return; @@ -666,6 +756,20 @@ void xiofreeaddrinfo(struct addrinfo *res) { #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, the first found by calling xiogetaddrinfo(), but ev.respects preferred_ip; 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, const int ai_flags[2]) { - struct addrinfo *res = NULL; + struct addrinfo **res = NULL; struct addrinfo *aip; int rc; @@ -699,17 +803,17 @@ int xioresolve(const char *node, const char *service, xiofreeaddrinfo(res); return STAT_NORETRY; } - if (res->ai_addrlen > *addrlen) { + if ((*res)->ai_addrlen > *addrlen) { Error3("xioresolve(node=\"%s\", addrlen="F_socklen", ...): "F_socklen" bytes required", - node, *addrlen, res->ai_addrlen); + node, *addrlen, (*res)->ai_addrlen); xiofreeaddrinfo(res); 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?"\"":""); } - aip = res; + aip = *res; if (ai_flags != NULL && ai_flags[0] & AI_PASSIVE && pf == PF_UNSPEC) { /* We select the first IPv6 address, if available, because this might accept IPv4 connections too */ @@ -719,7 +823,7 @@ int xioresolve(const char *node, const char *service, aip = aip->ai_next; } if (aip == NULL) - aip = res; + aip = *res; } else if (pf == PF_UNSPEC && xioparms.preferred_ip != '0') { int prefip = PF_UNSPEC; xioinit_ip(&prefip, xioparms.preferred_ip); @@ -729,7 +833,7 @@ int xioresolve(const char *node, const char *service, aip = aip->ai_next; } if (aip == NULL) - aip = res; + aip = *res; } memcpy(addr, aip->ai_addr, aip->ai_addrlen); diff --git a/xio-ip.h b/xio-ip.h index 80b10bd..ec94e16 100644 --- a/xio-ip.h +++ b/xio-ip.h @@ -49,8 +49,9 @@ extern const struct optdesc opt_res_nsaddr; 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 void xiofreeaddrinfo(struct addrinfo *res); +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 **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 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); diff --git a/xio-ipapp.c b/xio-ipapp.c index e5f7887..1cb1b64 100644 --- a/xio-ipapp.c +++ b/xio-ipapp.c @@ -39,12 +39,11 @@ int xioopen_ipapp_connect( int maxchildren = 0; union sockaddr_union us_sa, *us = &us_sa; socklen_t uslen = sizeof(us_sa); - struct addrinfo *themlist, *themp; + struct addrinfo **themarr, *themp; char infobuff[256]; bool needbind = false; bool lowport = false; int level; - struct addrinfo **ai_sorted; int i; int result; @@ -78,7 +77,7 @@ int xioopen_ipapp_connect( if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto, sfd->para.socket.ip.ai_flags, - &themlist, us, &uslen, &needbind, &lowport, + &themarr, us, &uslen, &needbind, &lowport, socktype) != STAT_OK) { return STAT_NORETRY; } @@ -94,33 +93,22 @@ int xioopen_ipapp_connect( 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 */ - /* Loop over themlist - no, over ai_sorted */ + /* Loop over themarr (which had been "ai_sorted") */ result = STAT_RETRYLATER; i = 0; - themp = ai_sorted[i++]; + themp = themarr[i++]; while (themp != NULL) { Notice1("opening connection to %s", sockaddr_info(themp->ai_addr, themp->ai_addrlen, infobuff, sizeof(infobuff))); #if WITH_RETRY - if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) { + if (sfd->forever || sfd->retry) { level = E_INFO; + } else if (themarr[i] != NULL) { + level = E_WARN; } else #endif /* WITH_RETRY */ level = E_ERROR; @@ -133,7 +121,7 @@ int xioopen_ipapp_connect( lowport, level); if (result == STAT_OK) break; - themp = ai_sorted[i++]; + themp = themarr[i++]; if (themp == NULL) { result = STAT_RETRYLATER; } @@ -153,7 +141,7 @@ int xioopen_ipapp_connect( } #endif /* WITH_RETRY */ default: - free(ai_sorted); + xiofreeaddrinfo(themarr); free(opts0);free(opts); return result; } @@ -170,7 +158,7 @@ int xioopen_ipapp_connect( if (sfd->forever || --sfd->retry) { Nanosleep(&sfd->intervall, NULL); continue; } - free(ai_sorted); + xiofreeaddrinfo(themarr); free(opts0); return STAT_RETRYLATER; } @@ -197,8 +185,7 @@ int xioopen_ipapp_connect( } } while (true); /* only "active" process breaks (master without fork, or child) */ - free(ai_sorted); - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); if ((result = _xio_openlate(sfd, opts)) < 0) { free(opts0);free(opts); @@ -223,7 +210,7 @@ int int *pf, int protocol, const int ai_flags[2], - struct addrinfo **themlist, + struct addrinfo ***themarr, union sockaddr_union *us, socklen_t *uslen, bool *needbind, @@ -236,7 +223,7 @@ int if (hostname != NULL || portname != NULL) { rc = xiogetaddrinfo(hostname, portname, *pf, socktype, protocol, - themlist, ai_flags); + themarr, ai_flags); if (rc == EAI_AGAIN) { Warn4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s", hostname?hostname:"NULL", portname?portname:"NULL", @@ -253,13 +240,13 @@ int applyopts(NULL, -1, opts, PH_EARLY); /* 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, ai_flags) != STAT_NOACTION) { *needbind = true; } else { - switch ((*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family) { + switch ((*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family) { #if WITH_IP4 case PF_INET: socket_in_init(&us->ip4); *uslen = sizeof(us->ip4); break; #endif /* WITH_IP4 */ @@ -271,7 +258,7 @@ int } 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 case PF_INET: us->ip4.sin_port = htons(port); break; #endif /* WITH_IP4 */ @@ -397,60 +384,4 @@ int xioopen_ipapp_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 */ diff --git a/xio-ipapp.h b/xio-ipapp.h index 20679f7..af9e7b4 100644 --- a/xio-ipapp.h +++ b/xio-ipapp.h @@ -15,13 +15,12 @@ extern const struct optdesc opt_sourceport; 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_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, struct single *xfd, int socktype, int ipproto, void *protname, 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_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) */ diff --git a/xio-openssl.c b/xio-openssl.c index 39977fb..dddbfe9 100644 --- a/xio-openssl.c +++ b/xio-openssl.c @@ -241,11 +241,10 @@ static int xioopen_openssl_connect( bool dofork = false; union sockaddr_union us_sa, *us = &us_sa; socklen_t uslen = sizeof(us_sa); - struct addrinfo *themlist, *themp; + struct addrinfo **themarr, *themp; bool needbind = false; bool lowport = false; int level = E_ERROR; - struct addrinfo **ai_sorted; int i; SSL_CTX* ctx; bool opt_ver = true; /* verify peer certificate */ @@ -323,7 +322,7 @@ static int xioopen_openssl_connect( result = _xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto, sfd->para.socket.ip.ai_flags, - &themlist, us, &uslen, + &themarr, us, &uslen, &needbind, &lowport, socktype); if (result != STAT_OK) return STAT_NORETRY; @@ -334,28 +333,15 @@ static int xioopen_openssl_connect( 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 */ - /* Loop over ai_sorted list */ + /* Loop over themarr (which had been "ai_sorted") */ i = 0; - themp = ai_sorted[i++]; + themp = themarr[i++]; while (themp != NULL) { #if WITH_RETRY - if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) { + if (sfd->forever || sfd->retry || themarr[i] != NULL) { level = E_INFO; } else #endif /* WITH_RETRY */ @@ -369,7 +355,7 @@ static int xioopen_openssl_connect( opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level); if (result == STAT_OK) break; - themp = ai_sorted[i++]; + themp = themarr[i++]; if (themp == NULL) { result = STAT_RETRYLATER; } @@ -387,16 +373,16 @@ static int xioopen_openssl_connect( --sfd->retry; continue; } - free(ai_sorted); + xiofreeaddrinfo(themarr); return STAT_NORETRY; #endif /* WITH_RETRY */ default: - free(ai_sorted); + xiofreeaddrinfo(themarr); return result; } /*! isn't this too early? */ if ((result = _xio_openlate(sfd, opts)) < 0) { - free(ai_sorted); + xiofreeaddrinfo(themarr); return result; } @@ -418,7 +404,7 @@ static int xioopen_openssl_connect( } #endif /* WITH_RETRY */ default: - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); return STAT_NORETRY; } @@ -437,7 +423,7 @@ static int xioopen_openssl_connect( if (sfd->forever || --sfd->retry) { Nanosleep(&sfd->intervall, NULL); continue; } - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); return STAT_RETRYLATER; } @@ -458,8 +444,7 @@ static int xioopen_openssl_connect( #endif /* WITH_RETRY */ break; } while (true); /* drop out on success */ - free(ai_sorted); - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); openssl_conn_loginfo(sfd->para.openssl.ssl); diff --git a/xio-proxy.c b/xio-proxy.c index da9fcea..86d86e3 100644 --- a/xio-proxy.c +++ b/xio-proxy.c @@ -93,8 +93,7 @@ static int xioopen_proxy_connect( int pf = PF_UNSPEC; union sockaddr_union us_sa, *us = &us_sa; socklen_t uslen = sizeof(us_sa); - struct addrinfo *themlist, *themp; - struct addrinfo **ai_sorted; + struct addrinfo **themarr, *themp; int i; const char *proxyname; char *proxyport = NULL; const char *targetname, *targetport; @@ -146,32 +145,19 @@ static int xioopen_proxy_connect( _xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport, &pf, ipproto, sfd->para.socket.ip.ai_flags, - &themlist, us, &uslen, + &themarr, us, &uslen, &needbind, &lowport, socktype); 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++]; + themp = themarr[i++]; while (themp != NULL) { Notice4("opening connection to %s:%u via proxy %s:%s", proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport); #if WITH_RETRY - if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) { + if (sfd->forever || sfd->retry || themarr[i] != NULL) { level = E_INFO; } else #endif /* WITH_RETRY */ @@ -184,7 +170,7 @@ static int xioopen_proxy_connect( opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level); if (result == STAT_OK) break; - themp = ai_sorted[i++]; + themp = themarr[i++]; if (themp == NULL) { result = STAT_RETRYLATER; } @@ -201,12 +187,11 @@ static int xioopen_proxy_connect( } #endif /* WITH_RETRY */ default: - free(ai_sorted); - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); return result; } } - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); applyopts(sfd, -1, opts, PH_ALL); if ((result = _xio_openlate(sfd, opts)) < 0) diff --git a/xio-socks.c b/xio-socks.c index 5bbb805..1dc434b 100644 --- a/xio-socks.c +++ b/xio-socks.c @@ -55,8 +55,7 @@ static int xioopen_socks4_connect( bool dofork = false; union sockaddr_union us_sa, *us = &us_sa; socklen_t uslen = sizeof(us_sa); - struct addrinfo *themlist, *themp; - struct addrinfo **ai_sorted; + struct addrinfo **themarr, *themp; int i; bool needbind = false; bool lowport = false; @@ -103,22 +102,9 @@ static int xioopen_socks4_connect( _xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport, &pf, ipproto, sfd->para.socket.ip.ai_flags, - &themlist, us, &uslen, + &themarr, us, &uslen, &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 server: this avoids unnecessary socks connects and timeouts */ result = @@ -139,15 +125,15 @@ static int xioopen_socks4_connect( return result; } - /* loop over themlist */ + /* loop over themarr */ i = 0; - themp = ai_sorted[i++]; + themp = themarr[i++]; while (themp != NULL) { Notice1("opening connection to %s", sockaddr_info(themp->ai_addr, themp->ai_addrlen, infobuff, sizeof(infobuff))); #if WITH_RETRY - if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) { + if (sfd->forever || sfd->retry || themarr[i] != NULL) { level = E_INFO; } else #endif /* WITH_RETRY */ @@ -161,7 +147,7 @@ static int xioopen_socks4_connect( opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level); if (result == STAT_OK) break; - themp = ai_sorted[i++]; + themp = themarr[i++]; if (themp == NULL) result = STAT_RETRYLATER; } @@ -178,11 +164,10 @@ static int xioopen_socks4_connect( } #endif /* WITH_RETRY */ default: - free(ai_sorted); - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); return result; } - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); applyopts(sfd, -1, opts, PH_ALL); if ((result = _xio_openlate(sfd, opts)) < 0) diff --git a/xio-socks5.c b/xio-socks5.c index 1585d7a..d57008d 100644 --- a/xio-socks5.c +++ b/xio-socks5.c @@ -512,7 +512,7 @@ static int xioopen_socks5( const char *socks_server, *target_name, *target_port, *socks_port; union sockaddr_union us_sa, *us = &us_sa; socklen_t uslen = sizeof(us_sa); - struct addrinfo *themlist, *themp; + struct addrinfo **themarr, *themp; bool needbind = false; bool lowport = false; char infobuff[256]; @@ -542,7 +542,7 @@ static int xioopen_socks5( result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port, &pf, ipproto, sfd->para.socket.ip.ai_flags, - &themlist, us, &uslen, + &themarr, us, &uslen, &needbind, &lowport, socktype); Notice2("connecting to socks5 server %s:%s", @@ -557,8 +557,8 @@ static int xioopen_socks5( } #endif - /* loop over themlist */ - themp = themlist; + /* loop over themarr */ + themp = themarr[0]; while (themp != NULL) { Notice1("opening connection to %s", sockaddr_info(themp->ai_addr, themp->ai_addrlen, @@ -584,11 +584,11 @@ static int xioopen_socks5( } #endif default: - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); return result; } } - xiofreeaddrinfo(themlist); + xiofreeaddrinfo(themarr); applyopts(sfd, -1, opts, PH_ALL); if ((result = _xio_openlate(sfd, opts)) < 0)