@ -13,6 +13,7 @@
# include <err.h>
# include <errno.h>
# include <fcntl.h>
# include <ifaddrs.h>
# include <limits.h>
# include <netdb.h>
# include <netinet/in.h>
@ -24,6 +25,7 @@
# include <sys/select.h>
# include <sys/socket.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <sys/un.h>
# include <termios.h>
# include <unistd.h>
@ -119,6 +121,41 @@ static void usage() {
exit ( EXIT_FAILURE ) ;
}
static int connect_localhost ( const char * port , enum ip_family ip_family ) {
int rc , family , fd , err ;
struct ifaddrs * ifaddr , * ifa ;
rc = getifaddrs ( & ifaddr ) ;
if ( rc < 0 ) return - 1 ;
int port_n = htons ( atoi ( port ) ) ;
for ( ifa = ifaddr ; ifa ! = NULL ; ifa = ifa - > ifa_next ) {
if ( ifa - > ifa_addr = = NULL ) continue ;
family = ifa - > ifa_addr - > sa_family ;
socklen_t addrlen ;
if ( family = = AF_INET ) {
if ( ip_family ! = ip_family_ipv4 & & ip_family ! = ip_family_any ) continue ;
addrlen = sizeof ( struct sockaddr_in ) ;
struct sockaddr_in * addr = ( struct sockaddr_in * ) ifa - > ifa_addr ;
addr - > sin_port = port_n ;
} else if ( family = = AF_INET6 ) {
if ( ip_family ! = ip_family_ipv6 & & ip_family ! = ip_family_any ) continue ;
addrlen = sizeof ( struct sockaddr_in6 ) ;
struct sockaddr_in6 * addr = ( struct sockaddr_in6 * ) ifa - > ifa_addr ;
addr - > sin6_port = port_n ;
} else continue ;
fd = socket ( family , SOCK_STREAM , IPPROTO_TCP ) ;
if ( fd < 0 ) continue ;
if ( connect ( fd , ifa - > ifa_addr , addrlen ) = = 0 ) break ;
err = errno ;
close ( fd ) ;
errno = err ;
}
if ( ifa = = NULL ) fd = - 1 ;
freeifaddrs ( ifaddr ) ;
return fd ;
}
static int tcp_connect ( const char * host , const char * port , enum ip_family ip_family ) {
struct addrinfo hints ;
struct addrinfo * result , * rp ;
@ -144,6 +181,11 @@ static int tcp_connect(const char *host, const char *port, enum ip_family ip_fam
if ( rp = = NULL ) fd = - 1 ;
freeaddrinfo ( result ) ;
if ( fd = = - 1 & & errno = = ECONNREFUSED & & ( host = = NULL | | ! strcmp ( host , " localhost " ) ) ) {
return connect_localhost ( port , ip_family ) ;
}
return fd ;
}