Skip to content

Commit

Permalink
Harmonize socket address families: ipv4 vs ipv6
Browse files Browse the repository at this point in the history
If `-b bindaddr` is used, then created sockets must be of the same address family as `bindaddr` (otherwise, calls to `bind()` will fail).

This patch harmonizes the address family across the calls to `socket()`, `bind()`, and `connect()`.

Prior to this patch, `microsocks` would use the first `addrinfo` record returned by `getaddrinfo()`.  On systems with both IPv4 and IPv6, sometimes the address family of the first record would be a mismatch with `bindaddr`, resulting in an error.

This patch may fix issue rofl0r#30.  (And issue rofl0r#40?)
  • Loading branch information
parke committed Dec 12, 2021
1 parent 9d463f4 commit f538e7f
Showing 1 changed file with 20 additions and 2 deletions.
22 changes: 20 additions & 2 deletions sockssrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ struct thread {
static void dolog(const char* fmt, ...) { }
#endif

static int family_choose(struct addrinfo* remote, union sockaddr_union* bind_addr) {
int family = SOCKADDR_UNION_AF(bind_addr);
return family == AF_UNSPEC ? remote->ai_family : family;
}

static struct addrinfo* addr_choose(struct addrinfo* list, union sockaddr_union* bind_addr) {
int family = SOCKADDR_UNION_AF(bind_addr);
if(family == AF_UNSPEC) return list;
struct addrinfo* p;
for(p=list;p;p=p->ai_next) {
if(p->ai_family == family) return p;
}
dprintf(2, "warning: address family mismatch\n");
return list;
}

static int connect_socks_target(unsigned char *buf, size_t n, struct client *client) {
if(n < 5) return -EC_GENERAL_FAILURE;
if(buf[0] != 5) return -EC_GENERAL_FAILURE;
Expand Down Expand Up @@ -146,7 +162,8 @@ static int connect_socks_target(unsigned char *buf, size_t n, struct client *cli
port = (buf[minlen-2] << 8) | buf[minlen-1];
/* there's no suitable errorcode in rfc1928 for dns lookup failure */
if(resolve(namebuf, port, &remote)) return -EC_GENERAL_FAILURE;
int fd = socket(remote->ai_addr->sa_family, SOCK_STREAM, 0);
int family = family_choose(remote, &bind_addr);
int fd = socket(family, SOCK_STREAM, 0);
if(fd == -1) {
eval_errno:
if(fd != -1) close(fd);
Expand All @@ -173,7 +190,8 @@ static int connect_socks_target(unsigned char *buf, size_t n, struct client *cli
}
if(SOCKADDR_UNION_AF(&bind_addr) != AF_UNSPEC && bindtoip(fd, &bind_addr) == -1)
goto eval_errno;
if(connect(fd, remote->ai_addr, remote->ai_addrlen) == -1)
struct addrinfo* addr = addr_choose(remote, &bind_addr);
if(connect(fd, addr->ai_addr, addr->ai_addrlen) == -1)
goto eval_errno;

freeaddrinfo(remote);
Expand Down

0 comments on commit f538e7f

Please sign in to comment.