Fix UDP socket creation/cleanup if opening IPv6 socket fails

Previously, the `net_udp_create` function returned whether the IPv6 socket in particular was created successfully. If an IPv4 socket or Websocket was created successfully before this, it was not used and also not closed properly, if the IPv6 socket could not be created.

Now, the `net_udp_create` function succeeds if the socket for at least one network type (IPv4, IPv6 or Websocket) could be created successfully.

Avoid reusing local variables and remove redundant comments. Also apply the same refactoring to `net_tcp_create`, which already has the behavior of succeeding if the socket for any network type (IPv4 or IPv6) was created successfully.
This commit is contained in:
Robert Müller 2024-08-11 15:15:45 +02:00
parent afd1bd9cde
commit 570c2c857a

View file

@ -1548,24 +1548,21 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
{ {
NETSOCKET sock = (NETSOCKET_INTERNAL *)malloc(sizeof(*sock)); NETSOCKET sock = (NETSOCKET_INTERNAL *)malloc(sizeof(*sock));
*sock = invalid_socket; *sock = invalid_socket;
NETADDR tmpbindaddr = bindaddr;
int broadcast = 1;
int socket = -1;
if(bindaddr.type & NETTYPE_IPV4) if(bindaddr.type & NETTYPE_IPV4)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
NETADDR tmpbindaddr = bindaddr;
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV4; tmpbindaddr.type = NETTYPE_IPV4;
netaddr_to_sockaddr_in(&tmpbindaddr, &addr); netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr)); int socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
if(socket >= 0) if(socket >= 0)
{ {
sock->type |= NETTYPE_IPV4; sock->type |= NETTYPE_IPV4;
sock->ipv4sock = socket; sock->ipv4sock = socket;
/* set broadcast */ /* set broadcast */
int broadcast = 1;
if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0) if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0)
{ {
dbg_msg("socket", "Setting BROADCAST on ipv4 failed: %d", net_errno()); dbg_msg("socket", "Setting BROADCAST on ipv4 failed: %d", net_errno());
@ -1581,17 +1578,15 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
} }
} }
} }
#if defined(CONF_WEBSOCKETS) #if defined(CONF_WEBSOCKETS)
if(bindaddr.type & NETTYPE_WEBSOCKET_IPV4) if(bindaddr.type & NETTYPE_WEBSOCKET_IPV4)
{ {
char addr_str[NETADDR_MAXSTRSIZE]; char addr_str[NETADDR_MAXSTRSIZE];
NETADDR tmpbindaddr = bindaddr;
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_WEBSOCKET_IPV4; tmpbindaddr.type = NETTYPE_WEBSOCKET_IPV4;
net_addr_str(&tmpbindaddr, addr_str, sizeof(addr_str), 0); net_addr_str(&tmpbindaddr, addr_str, sizeof(addr_str), 0);
socket = websocket_create(addr_str, tmpbindaddr.port); int socket = websocket_create(addr_str, tmpbindaddr.port);
if(socket >= 0) if(socket >= 0)
{ {
sock->type |= NETTYPE_WEBSOCKET_IPV4; sock->type |= NETTYPE_WEBSOCKET_IPV4;
@ -1603,17 +1598,17 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
if(bindaddr.type & NETTYPE_IPV6) if(bindaddr.type & NETTYPE_IPV6)
{ {
struct sockaddr_in6 addr; struct sockaddr_in6 addr;
NETADDR tmpbindaddr = bindaddr;
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV6; tmpbindaddr.type = NETTYPE_IPV6;
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr); netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr)); int socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
if(socket >= 0) if(socket >= 0)
{ {
sock->type |= NETTYPE_IPV6; sock->type |= NETTYPE_IPV6;
sock->ipv6sock = socket; sock->ipv6sock = socket;
/* set broadcast */ /* set broadcast */
int broadcast = 1;
if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0) if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0)
{ {
dbg_msg("socket", "Setting BROADCAST on ipv6 failed: %d", net_errno()); dbg_msg("socket", "Setting BROADCAST on ipv6 failed: %d", net_errno());
@ -1633,20 +1628,17 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
} }
} }
if(socket < 0) if(sock->type == NETTYPE_INVALID)
{ {
free(sock); free(sock);
sock = nullptr; sock = nullptr;
} }
else else
{ {
/* set non-blocking */
net_set_non_blocking(sock); net_set_non_blocking(sock);
net_buffer_init(&sock->buffer); net_buffer_init(&sock->buffer);
} }
/* return */
return sock; return sock;
} }
@ -1862,17 +1854,14 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
{ {
NETSOCKET sock = (NETSOCKET_INTERNAL *)malloc(sizeof(*sock)); NETSOCKET sock = (NETSOCKET_INTERNAL *)malloc(sizeof(*sock));
*sock = invalid_socket; *sock = invalid_socket;
NETADDR tmpbindaddr = bindaddr;
int socket4 = -1;
if(bindaddr.type & NETTYPE_IPV4) if(bindaddr.type & NETTYPE_IPV4)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
NETADDR tmpbindaddr = bindaddr;
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV4; tmpbindaddr.type = NETTYPE_IPV4;
netaddr_to_sockaddr_in(&tmpbindaddr, &addr); netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
socket4 = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr)); int socket4 = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
if(socket4 >= 0) if(socket4 >= 0)
{ {
sock->type |= NETTYPE_IPV4; sock->type |= NETTYPE_IPV4;
@ -1880,15 +1869,13 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
} }
} }
int socket6 = -1;
if(bindaddr.type & NETTYPE_IPV6) if(bindaddr.type & NETTYPE_IPV6)
{ {
struct sockaddr_in6 addr; struct sockaddr_in6 addr;
NETADDR tmpbindaddr = bindaddr;
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV6; tmpbindaddr.type = NETTYPE_IPV6;
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr); netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
socket6 = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr)); int socket6 = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
if(socket6 >= 0) if(socket6 >= 0)
{ {
sock->type |= NETTYPE_IPV6; sock->type |= NETTYPE_IPV6;
@ -1896,13 +1883,12 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
} }
} }
if(socket4 < 0 && socket6 < 0) if(sock->type == NETTYPE_INVALID)
{ {
free(sock); free(sock);
sock = nullptr; sock = nullptr;
} }
/* return */
return sock; return sock;
} }