summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-01-23 09:33:18 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-01-23 09:33:18 -0600
commitabb8aa345f619b2f25eff5ba54e13faea349a75c (patch)
tree4127d3197ae9c50769c3d0819ace6202d5ac5367 /nuttx
parent7f2c2629194ec04937658afe3ebf92ded3ab4a12 (diff)
downloadpx4-nuttx-abb8aa345f619b2f25eff5ba54e13faea349a75c.tar.gz
px4-nuttx-abb8aa345f619b2f25eff5ba54e13faea349a75c.tar.bz2
px4-nuttx-abb8aa345f619b2f25eff5ba54e13faea349a75c.zip
Networking: Fix issues with UDP packet length and checksum calculations when IPv6 is selected
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/net/udp/udp_input.c30
-rw-r--r--nuttx/net/udp/udp_send.c58
-rw-r--r--nuttx/net/utils/Kconfig3
-rw-r--r--nuttx/net/utils/net_chksum.c36
-rw-r--r--nuttx/net/utils/utils.h20
5 files changed, 103 insertions, 44 deletions
diff --git a/nuttx/net/udp/udp_input.c b/nuttx/net/udp/udp_input.c
index 57e7d39d4..3176e7daf 100644
--- a/nuttx/net/udp/udp_input.c
+++ b/nuttx/net/udp/udp_input.c
@@ -99,6 +99,7 @@ static int udp_input(FAR struct net_driver_s *dev, unsigned int iplen)
FAR struct udp_conn_s *conn;
unsigned int udpiplen;
unsigned int hdrlen;
+ uint16_t chksum;
int ret = OK;
/* Update the count of UDP packets received */
@@ -126,13 +127,34 @@ static int udp_input(FAR struct net_driver_s *dev, unsigned int iplen)
* application sets d_sndlen, it has a packet to send.
*/
- dev->d_len -= udpiplen;
-
-#ifdef CONFIG_NET_UDP_CHECKSUMS
+ dev->d_len -= udpiplen;
dev->d_appdata = &dev->d_buf[hdrlen];
- if (udp->udpchksum != 0 && udp_chksum(dev) != 0xffff)
+#ifdef CONFIG_NET_UDP_CHECKSUMS
+ chksum = udp->udpchksum;
+ if (chksum != 0)
{
+#ifdef CONFIG_NET_IPv6
+#ifdef CONFIG_NET_IPv4
+ if (IFF_IS_IPv6(dev->d_flags))
+#endif
+ {
+ chksum = ~udp_ipv6_chksum(dev);
+ }
+#endif /* CONFIG_NET_IPv6 */
+
+#ifdef CONFIG_NET_IPv4
+#ifdef CONFIG_NET_IPv6
+ else
+#endif
+ {
+ chksum = ~udp_ipv4_chksum(dev);
+ }
+#endif /* CONFIG_NET_IPv6 */
+ }
+
+ if (chksum != 0)
+ {
#ifdef CONFIG_NET_STATISTICS
g_netstats.udp.drop++;
g_netstats.udp.chkerr++;
diff --git a/nuttx/net/udp/udp_send.c b/nuttx/net/udp/udp_send.c
index ab71fbdc3..27d5ff1c9 100644
--- a/nuttx/net/udp/udp_send.c
+++ b/nuttx/net/udp/udp_send.c
@@ -129,8 +129,6 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
ipv4->vhl = 0x45;
ipv4->tos = 0;
- ipv4->len[0] = (dev->d_len >> 8);
- ipv4->len[1] = (dev->d_len & 0xff);
++g_ipid;
ipv4->ipid[0] = g_ipid >> 8;
ipv4->ipid[1] = g_ipid & 0xff;
@@ -142,17 +140,22 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr);
net_ipv4addr_hdrcopy(ipv4->destipaddr, &conn->u.ipv4.raddr);
- /* Calculate IP checksum. */
-
- ipv4->ipchksum = 0;
- ipv4->ipchksum = ~ipv4_chksum(dev);
-
/* The total length to send is the size of the application data
* plus the IPv4 and UDP headers (and, eventually, the link layer
* header)
*/
- dev->d_len = dev->d_sndlen + IPv4UDP_HDRLEN;
+ dev->d_len = dev->d_sndlen + IPv4UDP_HDRLEN;
+
+ /* The IPv4 length includes the size of the IPv4 header */
+
+ ipv4->len[0] = (dev->d_len >> 8);
+ ipv4->len[1] = (dev->d_len & 0xff);
+
+ /* Calculate IP checksum. */
+
+ ipv4->ipchksum = 0;
+ ipv4->ipchksum = ~ipv4_chksum(dev);
}
#endif /* CONFIG_NET_IPv4 */
@@ -175,20 +178,26 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
ipv6->vtc = 0x60;
ipv6->tcf = 0x00;
ipv6->flow = 0x00;
- ipv6->len[0] = (dev->d_sndlen >> 8);
- ipv6->len[1] = (dev->d_sndlen & 0xff);
ipv6->proto = IP_PROTO_UDP;
ipv6->ttl = conn->ttl;
net_ipv6addr_copy(ipv6->srcipaddr, dev->d_ipv6addr);
net_ipv6addr_copy(ipv6->destipaddr, conn->u.ipv6.raddr);
+ /* The IPv6 length, Includes the UDP header size but not the IPv6
+ * header size
+ */
+
+ dev->d_len = dev->d_sndlen + UDP_HDRLEN;
+ ipv6->len[0] = (dev->d_len >> 8);
+ ipv6->len[1] = (dev->d_len & 0xff);
+
/* The total length to send is the size of the application data
- * plus the IPv4 and UDP headers (and, eventually, the link layer
+ * plus the IPv6 and UDP headers (and, eventually, the link layer
* header)
*/
- dev->d_len = dev->d_sndlen + IPv6UDP_HDRLEN;
+ dev->d_len += IPv6_HDRLEN;
}
#endif /* CONFIG_NET_IPv6 */
@@ -197,19 +206,34 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
udp->srcport = conn->lport;
udp->destport = conn->rport;
udp->udplen = HTONS(dev->d_sndlen + UDP_HDRLEN);
+ udp->udpchksum = 0;
#ifdef CONFIG_NET_UDP_CHECKSUMS
/* Calculate UDP checksum. */
- udp->udpchksum = 0;
- udp->udpchksum = ~(udp_chksum(dev));
+#ifdef CONFIG_NET_IPv4
+#ifdef CONFIG_NET_IPv5
+ if (conn->domain = PF_INET)
+#endif
+ {
+ udp->udpchksum = ~udp_ipv4_chksum(dev);
+ }
+#endif /* CONFIG_NET_IPv4 */
+
+#ifdef CONFIG_NET_IPv6
+#ifdef CONFIG_NET_IPv4
+ else
+#endif
+ {
+ udp->udpchksum = ~udp_ipv6_chksum(dev);
+ }
+#endif /* CONFIG_NET_IPv6 */
+
if (udp->udpchksum == 0)
{
udp->udpchksum = 0xffff;
}
-#else
- udp->udpchksum = 0;
-#endif
+#endif /* CONFIG_NET_UDP_CHECKSUMS */
nllvdbg("Outgoing UDP packet length: %d\n", dev->d_len);
diff --git a/nuttx/net/utils/Kconfig b/nuttx/net/utils/Kconfig
index 5ba6ffe3e..c6700624b 100644
--- a/nuttx/net/utils/Kconfig
+++ b/nuttx/net/utils/Kconfig
@@ -23,4 +23,5 @@ config NET_ARCH_CHKSUM
uint16_t ipv4_chksum(FAR struct net_driver_s *dev)
uint16_t tcp_ipv4_chksum(FAR struct net_driver_s *dev);
uint16_t tcp_ipv6_chksum(FAR struct net_driver_s *dev);
- uint16_t udp_chksum(FAR struct net_driver_s *dev);
+ uint16_t udp_ipv4_chksum(FAR struct net_driver_s *dev);
+ uint16_t udp_ipv6_chksum(FAR struct net_driver_s *dev);
diff --git a/nuttx/net/utils/net_chksum.c b/nuttx/net/utils/net_chksum.c
index d4179470c..98732bcc6 100644
--- a/nuttx/net/utils/net_chksum.c
+++ b/nuttx/net/utils/net_chksum.c
@@ -372,34 +372,34 @@ uint16_t tcp_chksum(FAR struct net_driver_s *dev)
#endif
/****************************************************************************
- * Name: udp_chksum
+ * Name: udp_ipv4_chksum
*
* Description:
- * Calculate the UDP checksum of the packet in d_buf and d_appdata.
+ * Calculate the UDP/IPv4 checksum of the packet in d_buf and d_appdata.
*
****************************************************************************/
-#if defined(CONFIG_NET_UDP_CHECKSUMS) && !defined(CONFIG_NET_ARCH_CHKSUM)
-uint16_t udp_chksum(FAR struct net_driver_s *dev)
+#if defined(CONFIG_NET_UDP_CHECKSUMS) && defined(CONFIG_NET_IPv4)
+uint16_t udp_ipv4_chksum(FAR struct net_driver_s *dev)
{
-#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);
+}
+#endif
-#else /* if defined(CONFIG_NET_IPv6) */
+/****************************************************************************
+ * Name: udp_ipv6_chksum
+ *
+ * Description:
+ * Calculate the UDP/IPv6 checksum of the packet in d_buf and d_appdata.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP_CHECKSUMS) && defined(CONFIG_NET_IPv6)
+uint16_t udp_ipv6_chksum(FAR struct net_driver_s *dev)
+{
return ipv6_upperlayer_chksum(dev, IP_PROTO_UDP);
-#endif
}
-#endif /* CONFIG_NET_UDP_CHECKSUMS && !CONFIG_NET_ARCH_CHKSUM */
+#endif
/****************************************************************************
* Name: icmp_chksum
diff --git a/nuttx/net/utils/utils.h b/nuttx/net/utils/utils.h
index 6eabf097e..20aeab7d7 100644
--- a/nuttx/net/utils/utils.h
+++ b/nuttx/net/utils/utils.h
@@ -176,15 +176,27 @@ uint16_t tcp_chksum(FAR struct net_driver_s *dev);
/****************************************************************************
- * Name: udp_chksum
+ * Name: udp_ipv4_chksum
*
* Description:
- * Calculate the UDP checksum of the packet in d_buf and d_appdata.
+ * Calculate the UDP/IPv4 checksum of the packet in d_buf and d_appdata.
*
****************************************************************************/
-#ifdef CONFIG_NET_UDP_CHECKSUMS
-uint16_t udp_chksum(FAR struct net_driver_s *dev);
+#if defined(CONFIG_NET_UDP_CHECKSUMS) && defined(CONFIG_NET_IPv4)
+uint16_t udp_ipv4_chksum(FAR struct net_driver_s *dev);
+#endif
+
+/****************************************************************************
+ * Name: udp_ipv6_chksum
+ *
+ * Description:
+ * Calculate the UDP/IPv6 checksum of the packet in d_buf and d_appdata.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP_CHECKSUMS) && defined(CONFIG_NET_IPv6)
+uint16_t udp_ipv6_chksum(FAR struct net_driver_s *dev);
#endif
/****************************************************************************