Connect to local interfaces for localhost

If connecting to localhost fails, try connecting to all local addresses.
This works around ssb-server binding to a local address and not a loopback address.
main
cel 6 years ago
parent 7c6272311b
commit 37666be2d3

@ -78,7 +78,9 @@ Connect to server over IPv6 only.
Capability key for secret-handshake. Default is SSB's capability key,
.Li 1KHLiKZvAvjbY1ziZEHMXawbCEIM6qwjCDm3VYRan/s= .
.It Fl s Ar host
The hostname to connect to. Default is localhost.
The hostname to connect to. Default is localhost. If set to localhost and connection to localhost fails,
.Nm
may attempt to connect to other local interface addresses.
.It Fl p Ar port
The port to connect to. Default is 8008.
.It Fl u Ar socket_path

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

Loading…
Cancel
Save