Networking: Calculation of TCP and UDP checksums differ with IPv4 and IPv6
This commit is contained in:
parent
65ae9c990c
commit
4a0eb1f0b1
@ -54,7 +54,8 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define BUF ((struct net_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define IPv4BUF ((struct net_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
#define IPv6BUF ((struct net_ipv6hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
#define ICMPBUF ((struct icmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define ICMPBUF ((struct icmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
#define ICMPv6BUF ((struct icmp_ipv6hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define ICMPv6BUF ((struct icmp_ipv6hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
|
||||||
@ -111,35 +112,30 @@ static uint16_t chksum(uint16_t sum, FAR const uint8_t *data, uint16_t len)
|
|||||||
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: upper_layer_chksum
|
* Name: ipv4_upperlayer_chksum
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if !CONFIG_NET_ARCH_CHKSUM
|
#if !defined(CONFIG_NET_ARCH_CHKSUM) && defined(CONFIG_NET_IPv4)
|
||||||
static uint16_t upper_layer_chksum(FAR struct net_driver_s *dev,
|
static uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev,
|
||||||
uint8_t proto)
|
uint8_t proto)
|
||||||
{
|
{
|
||||||
FAR struct net_iphdr_s *pbuf = BUF;
|
FAR struct net_iphdr_s *pbuf = IPv4BUF;
|
||||||
uint16_t upper_layer_len;
|
uint16_t upperlen;
|
||||||
uint16_t sum;
|
uint16_t sum;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
upperlen = (((uint16_t)(pbuf->len[0]) << 8) + pbuf->len[1]) - IPv4_HDRLEN;
|
||||||
upper_layer_len = (((uint16_t)(pbuf->len[0]) << 8) + pbuf->len[1]);
|
|
||||||
#else /* CONFIG_NET_IPv6 */
|
|
||||||
upper_layer_len = (((uint16_t)(pbuf->len[0]) << 8) + pbuf->len[1]) - IPv4_HDRLEN;
|
|
||||||
#endif /* CONFIG_NET_IPv6 */
|
|
||||||
|
|
||||||
/* Verify some minimal assumptions */
|
/* Verify some minimal assumptions */
|
||||||
|
|
||||||
if (upper_layer_len > NET_DEV_MTU(dev))
|
if (upperlen > NET_DEV_MTU(dev))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First sum pseudo-header. */
|
/* First sum pseudo-header. */
|
||||||
|
|
||||||
/* IP protocol and length fields. This addition cannot carry. */
|
/* IP protocol and length fields. This addition cannot carry. */
|
||||||
|
|
||||||
sum = upper_layer_len + proto;
|
sum = upperlen + proto;
|
||||||
|
|
||||||
/* Sum IP source and destination addresses. */
|
/* Sum IP source and destination addresses. */
|
||||||
|
|
||||||
@ -147,7 +143,45 @@ static uint16_t upper_layer_chksum(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
/* Sum TCP header and data. */
|
/* Sum TCP header and data. */
|
||||||
|
|
||||||
sum = chksum(sum, &dev->d_buf[IPv4_HDRLEN + NET_LL_HDRLEN(dev)], upper_layer_len);
|
sum = chksum(sum, &dev->d_buf[IPv4_HDRLEN + NET_LL_HDRLEN(dev)], upperlen);
|
||||||
|
|
||||||
|
return (sum == 0) ? 0xffff : htons(sum);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ipv6_upperlayer_chksum
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(CONFIG_NET_ARCH_CHKSUM) && defined(CONFIG_NET_IPv6)
|
||||||
|
static uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev,
|
||||||
|
uint8_t proto)
|
||||||
|
{
|
||||||
|
FAR struct net_ipv6hdr_s *pbuf = IPv6BUF;
|
||||||
|
uint16_t upperlen;
|
||||||
|
uint16_t sum;
|
||||||
|
|
||||||
|
upperlen = (((uint16_t)(pbuf->len[0]) << 8) + pbuf->len[1]);
|
||||||
|
|
||||||
|
/* Verify some minimal assumptions */
|
||||||
|
|
||||||
|
if (upperlen > NET_DEV_MTU(dev))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First sum pseudo-header. */
|
||||||
|
/* IP protocol and length fields. This addition cannot carry. */
|
||||||
|
|
||||||
|
sum = upperlen + proto;
|
||||||
|
|
||||||
|
/* Sum IP source and destination addresses. */
|
||||||
|
|
||||||
|
sum = chksum(sum, (uint8_t *)&pbuf->srcipaddr, 2 * sizeof(net_ipv6addr_t));
|
||||||
|
|
||||||
|
/* Sum TCP header and data. */
|
||||||
|
|
||||||
|
sum = chksum(sum, &dev->d_buf[IPv6_HDRLEN + NET_LL_HDRLEN(dev)], upperlen);
|
||||||
|
|
||||||
return (sum == 0) ? 0xffff : htons(sum);
|
return (sum == 0) ? 0xffff : htons(sum);
|
||||||
}
|
}
|
||||||
@ -328,7 +362,22 @@ uint16_t ipv6_chksum(FAR struct net_driver_s *dev)
|
|||||||
#if !CONFIG_NET_ARCH_CHKSUM
|
#if !CONFIG_NET_ARCH_CHKSUM
|
||||||
uint16_t tcp_chksum(FAR struct net_driver_s *dev)
|
uint16_t tcp_chksum(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
return upper_layer_chksum(dev, IP_PROTO_TCP);
|
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||||
|
if (IFF_IS_IPv6(dev->d_flags))
|
||||||
|
{
|
||||||
|
return ipv6_upperlayer_chksum(dev, IP_PROTO_TCP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ipv4_upperlayer_chksum(dev, IP_PROTO_TCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(CONFIG_NET_IPv4)
|
||||||
|
return ipv4_upperlayer_chksum(dev, IP_PROTO_TCP);
|
||||||
|
|
||||||
|
#else /* if defined(CONFIG_NET_IPv6) */
|
||||||
|
return ipv6_upperlayer_chksum(dev, IP_PROTO_TCP);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
||||||
|
|
||||||
@ -343,7 +392,22 @@ uint16_t tcp_chksum(FAR struct net_driver_s *dev)
|
|||||||
#if defined(CONFIG_NET_UDP_CHECKSUMS) && !defined(CONFIG_NET_ARCH_CHKSUM)
|
#if defined(CONFIG_NET_UDP_CHECKSUMS) && !defined(CONFIG_NET_ARCH_CHKSUM)
|
||||||
uint16_t udp_chksum(FAR struct net_driver_s *dev)
|
uint16_t udp_chksum(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
return upper_layer_chksum(dev, IP_PROTO_UDP);
|
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||||
|
if (IFF_IS_IPv6(dev->d_flags))
|
||||||
|
{
|
||||||
|
return ipv6_upperlayer_chksum(dev, IP_PROTO_UDP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ipv4_upperlayer_chksum(dev, IP_PROTO_UDP);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(CONFIG_NET_IPv4)
|
||||||
|
return ipv4_upperlayer_chksum(dev, IP_PROTO_UDP);
|
||||||
|
|
||||||
|
#else /* if defined(CONFIG_NET_IPv6) */
|
||||||
|
return ipv6_upperlayer_chksum(dev, IP_PROTO_UDP);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_UDP_CHECKSUMS && !CONFIG_NET_ARCH_CHKSUM */
|
#endif /* CONFIG_NET_UDP_CHECKSUMS && !CONFIG_NET_ARCH_CHKSUM */
|
||||||
|
|
||||||
@ -374,7 +438,7 @@ uint16_t icmp_chksum(FAR struct net_driver_s *dev, int len)
|
|||||||
#ifdef CONFIG_NET_ICMPv6
|
#ifdef CONFIG_NET_ICMPv6
|
||||||
uint16_t icmpv6_chksum(FAR struct net_driver_s *dev)
|
uint16_t icmpv6_chksum(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
return upper_layer_chksum(dev, IP_PROTO_ICMP6);
|
return ipv6_upperlayer_chksum(dev, IP_PROTO_ICMP6);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user