From 0d14a111cde205a419bf5e1d9927fdc7a5ba5438 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 30 Sep 2024 13:00:31 +0200 Subject: [PATCH] sockets: Fix IPv6 raw packet checksum in IPv6-only configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: In an IPv6-only setup, raw IPv6 packets were being sent with an incorrect checksum, whereas they worked correctly in a dual-stack configuration (both IPv4 and IPv6). Analysis: * The checksum is calculated in `raw.c` when the `pcb->chksum_reqd` flag is set. * This flag is enabled for all IPv6 raw pcbs in `api_msg.c`, but only when `NETCONNTYPE_ISIPV6(msg->conn->type)` evaluates to true. * The issue arises because the macro `NETCONNTYPE_ISIPV6()` checks if the `NETCONN_TYPE_IPV6` flag is set in the netconn type. This flag wasn’t being set when creating the socket, as the `DOMAIN_TO_NETCONN_TYPE()` macro returned the original type without adding the IPv6 flag. Fix: * Made enum netconn_type reflect protocol family also in IPv6-only configs, updating the macro DOMAIN_TO_NETCONN_TYPE() to set the NETCONN_TYPE_IPV6 flag. Alternative Approach: * Another potential solution would be to modify the `enum netconn_type` to reflect both the connection type and protocol family (as of now) in a dual-stack setup, while reflect connection type only in a single-stack setup (IPv4 only or IPv6 only) --- src/api/sockets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/sockets.c b/src/api/sockets.c index b97bdd7e0..982713936 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -184,7 +184,7 @@ static void sockaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t * IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) -#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#define DOMAIN_TO_NETCONN_TYPE(domain, type) ((enum netconn_type)((type) | NETCONN_TYPE_IPV6)) #else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET)