sockets: Fix IPv6 raw packet checksum in IPv6-only configuration

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)
This commit is contained in:
David Cermak 2024-09-30 13:00:31 +02:00
parent 73fcf72792
commit 0d14a111cd

View File

@ -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)