mirror of
https://github.com/yrutschle/sslh.git
synced 2025-06-03 09:01:03 +03:00
fix handling of IPv6 UDP connections
Problem: IPv6 addresses are 4 bytes long and don't fit inside a `sockaddr`, so `recvfrom` will truncate the address to the first half. When generating a reply, the remaining half of the address is filled with garbage and the packet is subsequently delivered to the wrong host, if not immediately dropped. Solution: replace `sockaddr` with `sockaddr_storage`, the latter is guaranteed to be large enough to hold an IPv6 address and pointers can be cast to `sockaddr *` when needed.
This commit is contained in:
parent
bb76bc1d31
commit
33129481cf
2
common.h
2
common.h
@ -112,7 +112,7 @@ struct connection {
|
|||||||
struct queue q[2];
|
struct queue q[2];
|
||||||
|
|
||||||
/* SOCK_DGRAM */
|
/* SOCK_DGRAM */
|
||||||
struct sockaddr client_addr; /* Contains the remote client address */
|
struct sockaddr_storage client_addr; /* Contains the remote client address */
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
|
|
||||||
int local_endpoint; /* Contains the local address */
|
int local_endpoint; /* Contains the local address */
|
||||||
|
@ -129,7 +129,7 @@ void udp_init(struct loop_info* fd_info)
|
|||||||
* If yes, returns file descriptor of connection
|
* If yes, returns file descriptor of connection
|
||||||
* If not, returns -1
|
* If not, returns -1
|
||||||
* */
|
* */
|
||||||
static int known_source(hash* h, struct sockaddr* addr, socklen_t addrlen)
|
static int known_source(hash* h, struct sockaddr_storage* addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
struct connection search;
|
struct connection search;
|
||||||
search.client_addr = *addr;
|
search.client_addr = *addr;
|
||||||
@ -243,7 +243,7 @@ static int nonblocking_socket(struct sslhcfg_protocols_item* proto)
|
|||||||
struct connection* udp_c2s_forward(int sockfd, struct loop_info* fd_info)
|
struct connection* udp_c2s_forward(int sockfd, struct loop_info* fd_info)
|
||||||
{
|
{
|
||||||
char addr_str[NI_MAXHOST+1+NI_MAXSERV+1];
|
char addr_str[NI_MAXHOST+1+NI_MAXSERV+1];
|
||||||
struct sockaddr src_addr;
|
struct sockaddr_storage src_addr;
|
||||||
struct addrinfo addrinfo;
|
struct addrinfo addrinfo;
|
||||||
struct sslhcfg_protocols_item* proto;
|
struct sslhcfg_protocols_item* proto;
|
||||||
cnx_collection* collection = fd_info->collection;
|
cnx_collection* collection = fd_info->collection;
|
||||||
@ -259,13 +259,13 @@ struct connection* udp_c2s_forward(int sockfd, struct loop_info* fd_info)
|
|||||||
udp_timeouts(fd_info);
|
udp_timeouts(fd_info);
|
||||||
|
|
||||||
addrlen = sizeof(src_addr);
|
addrlen = sizeof(src_addr);
|
||||||
len = recvfrom(sockfd, data, sizeof(data), 0, &src_addr, &addrlen);
|
len = recvfrom(sockfd, data, sizeof(data), 0, (struct sockaddr*) &src_addr, &addrlen);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
perror("recvfrom");
|
perror("recvfrom");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
target = known_source(fd_info->hash_sources, &src_addr, addrlen);
|
target = known_source(fd_info->hash_sources, &src_addr, addrlen);
|
||||||
addrinfo.ai_addr = &src_addr;
|
addrinfo.ai_addr = (struct sockaddr*) &src_addr;
|
||||||
addrinfo.ai_addrlen = addrlen;
|
addrinfo.ai_addrlen = addrlen;
|
||||||
print_message(msg_probe_info, "received %ld UDP from %d:%s\n",
|
print_message(msg_probe_info, "received %ld UDP from %d:%s\n",
|
||||||
len, target, sprintaddr(addr_str, sizeof(addr_str), &addrinfo));
|
len, target, sprintaddr(addr_str, sizeof(addr_str), &addrinfo));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user