Skip to content

Commit

Permalink
Merge branch 'andrewshadura:main' into patch-allow-prefix-size
Browse files Browse the repository at this point in the history
  • Loading branch information
Leseratte10 authored Jan 1, 2023
2 parents e2d6aae + 2c240eb commit fe11a8b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 16 deletions.
2 changes: 1 addition & 1 deletion parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ int HIDDENSYM make_netent(char *value, struct netent **ent)
exit(1);
}

show_msg(MSGDEBUG, "New network entry for %s going to 0x%08x\n", ip, *ent);
show_msg(MSGDEBUG, "New network entry for %s\n", ip);

if (!startport)
(*ent)->startport = 0;
Expand Down
79 changes: 64 additions & 15 deletions tnat64.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,20 @@ int socket(SOCKET_SIGNATURE)
}
if ((__domain == AF_INET) && ((__type & SOCK_TYPE_MASK) == SOCK_STREAM))
{
return realsocket(AF_INET6, __type, __protocol);
int sock = realsocket(AF_INET6, __type, __protocol);

if (sock < 0) {
return sock;
}

// Now set this IPv6 socket to allow both IPv6 and IPv4 connections.
// Most OSes do that by default, but not all.
int no = 0;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&no, sizeof(no)) < 0) {
show_msg(MSGDEBUG, "Failed to disable IPV6_V6ONLY for socket %d: error %d (%s)\n", sock, errno, strerror(errno));
}

return sock;
}
else
{
Expand Down Expand Up @@ -321,7 +334,19 @@ int connect(CONNECT_SIGNATURE)
if (!(is_local(config, &(connaddr->sin_addr))))
{
show_msg(MSGDEBUG, "Connection for socket %d is local\n", __fd);
return realconnect(__fd, __addr, __len);
/* Rewrite to an IPv6 socket connect */
dest_address6.sin6_family = AF_INET6;
dest_address6.sin6_port = connaddr->sin_port;
dest_address6.sin6_flowinfo = 0;
dest_address6.sin6_scope_id = 0;
memcpy(&dest_address6.sin6_addr, &ipv4mapped, sizeof(struct in6_addr));
memcpy(&dest_address6.sin6_addr.s6_addr[NAT64PREFIXLEN], &connaddr->sin_addr, sizeof(struct in_addr));
if (inet_ntop(AF_INET6, &dest_address6.sin6_addr, addrbuffer, sizeof(addrbuffer)))
{
show_msg(MSGDEBUG, "Connecting to local IPv4-mapped IPv6 address %s...\n", addrbuffer);
}

return realconnect(__fd, (struct sockaddr *)&dest_address6, sizeof(struct sockaddr_in6));
}

/* Don't retry more than once */
Expand Down Expand Up @@ -440,24 +465,36 @@ int getpeername(GETPEERNAME_SIGNATURE)
get_config();

show_msg(MSGDEBUG, "Got getpeername call for socket %d\n", __fd);
struct sockaddr_in6 realpeer;
socklen_t needlen = *__len;
socklen_t realpeerlen = sizeof(realpeer);
int ret = realgetpeername(__fd, __addr, &needlen);
struct sockaddr_in * result;
if (ret < 0)
{
return ret;
}

if (*__len < sizeof(struct sockaddr_in))
{
*__len = sizeof(struct sockaddr_in);
errno = EINVAL;
return -1;
}
if (__addr->sa_family <= 10)

/* TODO: AF_INET6 is not necessarily 10, this debug print is wrong */
if (__addr->sa_family <= 10) {
show_msg(MSGDEBUG, "Address family is %s\n", afs[__addr->sa_family]);
}

if (__addr->sa_family == AF_INET6)
{
struct sockaddr_in6 realpeer;
socklen_t realpeerlen = sizeof(realpeer);
int ret = realgetpeername(__fd, (struct sockaddr *)&realpeer, &realpeerlen);
if (ret < 0) {
return ret;
}
if ((!memcmp(&realpeer.sin6_addr, &ipv4mapped, NAT64PREFIXLEN)) || (check_prefix(config, &realpeer.sin6_addr)))
{
struct sockaddr_in * result;
result = (struct sockaddr_in *)__addr;
result->sin_family = AF_INET;
result->sin_port = realpeer.sin6_port;
Expand All @@ -480,7 +517,7 @@ int getpeername(GETPEERNAME_SIGNATURE)
return ret;
}
}
return ret;
return ret;
}

int getsockname(GETSOCKNAME_SIGNATURE)
Expand All @@ -501,28 +538,40 @@ int getsockname(GETSOCKNAME_SIGNATURE)
get_config();

show_msg(MSGDEBUG, "Got getsockname call for socket %d\n", __fd);
struct sockaddr_in6 realpeer;
socklen_t needlen = *__len;
socklen_t realpeerlen = sizeof(realpeer);
int ret = realgetsockname(__fd, __addr, &needlen);
struct sockaddr_in * result;
if (ret < 0)
{
return ret;
}

if (*__len < sizeof(struct sockaddr_in))
{
*__len = sizeof(struct sockaddr_in);
errno = EINVAL;
return -1;
}
if (__addr->sa_family <= 10)

/* TODO: AF_INET6 is not necessarily 10, this debug print is wrong */
if (__addr->sa_family <= 10) {
show_msg(MSGDEBUG, "Address family is %s\n", afs[__addr->sa_family]);
}

if (__addr->sa_family == AF_INET6)
{
int ret = realgetpeername(__fd, (struct sockaddr *)&realpeer, &realpeerlen);
if ((!memcmp(&realpeer.sin6_addr, &ipv4mapped, NAT64PREFIXLEN)) || (check_prefix(config, &realpeer.sin6_addr)))
struct sockaddr_in6 realsock;
socklen_t realsocklen = sizeof(realsock);
int ret = realgetsockname(__fd, (struct sockaddr *)&realsock, &realsocklen);
if (ret < 0) {
return ret;
}
if ((!memcmp(&realsock.sin6_addr, &ipv4mapped, NAT64PREFIXLEN)) || (check_prefix(config, &realsock.sin6_addr)))
{
struct sockaddr_in * result;
result = (struct sockaddr_in *)__addr;
result->sin_family = AF_INET;
result->sin_port = 0;
memset(&result->sin_addr, 0, sizeof(struct in_addr));
result->sin_port = realsock.sin6_port;
memcpy(&result->sin_addr, &realsock.sin6_addr.s6_addr[12], sizeof(struct in_addr));
*__len = sizeof(struct sockaddr_in);
return ret;
}
Expand Down

0 comments on commit fe11a8b

Please sign in to comment.