patchlwIP - A Lightweight TCP/IP stack - Patches: patch #7905, Add RFC3542-style checksum...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

patch #7905: Add RFC3542-style checksum compuation on raw, IPv6 sockets.

Submitter:  Grant Erickson <marathon96>
Submitted:  Thu 20 Dec 2012 04:35:48 PM UTC
   
 
Category:  IPv6 Priority:  5 - Normal
Status:  Done Privacy:  Public
Assigned to:  goldsimon Open/Closed:  Closed
Planned Release:  None

Fri 21 Feb 2014 07:43:09 AM UTC, comment #4: 

Looking at it, it seems that the patch (using 'q') should work when using a PBUF_RAM pbuf with enough space for all headers. However, it can't work when this is not the case, so I guess you're right. At this point, the extra 'q' should have a length of zero and only provide space for the next headers, so using 'p' should be the right thing.

Done, thanks.

Simon Goldschmidt <goldsimon>
Group administrator
Fri 21 Feb 2014 06:55:54 AM UTC, comment #3: 

I haven't checked, just had a quick look over the code, and I didn't see that.

Simon Goldschmidt <goldsimon>
Group administrator
Fri 21 Feb 2014 03:20:33 AM UTC, comment #2: 

I'm not convinced that this patch is correct -- I think that the lines

chksum = ip6_chksum_pseudo(q, pcb->protocol, q->tot_len, ipX_2_ip6(src_ip), ipX_2_ip6(dst_ip));
+ (u16_t )(((u8_t *)q->payload) + pcb->chksum_offset) = chksum;

should refer to "p" and not "q".

At least, if I use the original code, then it doesn't work, and if I use the "p" version, then it does work.

Philip Gladstone <pjsg>
Thu 20 Feb 2014 07:10:21 PM UTC, comment #1: 

Done, thanks for the patch.

Simon Goldschmidt <goldsimon>
Group administrator
Thu 20 Dec 2012 04:35:48 PM UTC, original submission:  

From: Grant Erickson <marathon96@gmail.com>
Date: Wed, 19 Dec 2012 18:21:07 -0800
Subject: [PATCH 1/2] Add RFC3542-style checksum compuation on raw, IPv6 sockets

This patch adds support for RFC3542-style checksum computation on raw,
IPv6 sockets via the IPV6_CHECKSUM socket option.

This allows the development of application-layer utilities such as
ping6 which are unable to compute the raw packet checksum without a
prior knowledge of the source address selection.

---
 src/api/sockets.c      | 84 ++++++++++++++++++++++
 src/core/raw.c         | 11 +++
 src/include/lwip/raw.h |  5 ++
 .../sw/tps/lwip/lwip/src/include/lwip/sockets.h    |  3 +-
 4 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/src/api/sockets.c b/src/api/sockets.c
index 6603671..64bdb19 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -1710,6 +1710,22 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
     }  /* switch (optname) */
     break;
 #endif /* LWIP_UDP && LWIP_UDPLITE*/
+  /* Level: IPPROTO_RAW */
+  case IPPROTO_RAW:
+    switch (optname) {
+#if LWIP_IPV6
+    case IPV6_CHECKSUM:
+      if (*optlen < sizeof(int)) {
+        err = EINVAL;
+        break;
+      }
+#endif /* LWIP_IPV6 */
+    default:
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
+                                  s, optname));
+      err = ENOPROTOOPT;
+    }  /* switch (optname) */
+    break;
 /* UNDEFINED LEVEL */
   default:
       LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
@@ -1960,6 +1976,24 @@ lwip_getsockopt_internal(void *arg)
     }  /* switch (optname) */
     break;
 #endif /* LWIP_UDP */
+  /* Level: IPPROTO_RAW */
+  case IPPROTO_RAW:
+    switch (optname) {
+#if LWIP_IPV6
+    case IPV6_CHECKSUM:
+   if (sock->conn->pcb.raw->chksum_reqd == 0)
+        (int )optval = -1;
+      else
+        (int )optval = sock->conn->pcb.raw->chksum_offset;
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n",
+                  s, ((int)optval)) );
+      break;
+#endif /* LWIP_IPV6 */
+    default:
+      LWIP_ASSERT("unhandled optname", 0);
+      break;
+    }  /* switch (optname) */
+ break;
   default:
     LWIP_ASSERT("unhandled level", 0);
     break;
@@ -2134,12 +2168,26 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
         return 0;
 
       break;
+    case IPV6_CHECKSUM:
+        err = EINVAL;
+        break;
       default:
         LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
                     s, optname));
         err = ENOPROTOOPT;
     }  /* switch (optname) */
     break;
+  case IPPROTO_ICMPV6:
+    switch (optname) {
+    case IPV6_CHECKSUM:
+        err = EINVAL;
+        break;
+    default:
+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_ICMPV6, UNIMPL: optname=0x%x, ..)\n",
+                                    s, optname));
+        err = ENOPROTOOPT;
+    }  /* switch (optname) */
+    break;
 #endif /* LWIP_IPV6 */
 
 #if LWIP_UDP && LWIP_UDPLITE
@@ -2166,6 +2214,22 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
     }  /* switch (optname) */
     break;
 #endif /* LWIP_UDP && LWIP_UDPLITE */
+/* Level: IPPROTO_RAW */
+  case IPPROTO_RAW:
+    switch (optname) {
+#if LWIP_IPV6
+    case IPV6_CHECKSUM:
+        /* Per RFC3542, odd offsets are not allowed */
+        if (((int )optval > 0) && ((int )optval & 1))
+            err = EINVAL;
+        break;
+#endif /* LWIP_IPV6 */
+    default:
+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
+                                    s, optname));
+        err = ENOPROTOOPT;
+    } /* switch (optname) */
+ break;
 /* UNDEFINED LEVEL */
   default:
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
@@ -2422,6 +2486,26 @@ lwip_setsockopt_internal(void *arg)
     }  /* switch (optname) */
     break;
 #endif /* LWIP_UDP */
+  /* Level: IPPROTO_RAW */
+  case IPPROTO_RAW:
+    switch (optname) {
+#if LWIP_IPV6
+    case IPV6_CHECKSUM:
+      if ((int )optval < 0) {
+        sock->conn->pcb.raw->chksum_reqd = 0;
+      } else {
+        sock->conn->pcb.raw->chksum_reqd = 1;
+        sock->conn->pcb.raw->chksum_offset = (int )optval;
+      }
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n",
+                  s, sock->conn->pcb.raw->chksum_reqd));
+      break;
+#endif /* LWIP_IPV6 */
+    default:
+      LWIP_ASSERT("unhandled optname", 0);
+      break;
+    }  /* switch (optname) */
+    break;
   default:
     LWIP_ASSERT("unhandled level", 0);
     break;
diff --git a/src/core/raw.c b/src/core/raw.c
index 6f50848..3e21a50 100644
--- a/src/core/raw.c
+++ b/src/core/raw.c
@@ -51,6 +51,7 @@
 #include "arch/perf.h"
 #include "lwip/ip6.h"
 #include "lwip/ip6_addr.h"
+#include "lwip/inet_chksum.h"
 
 #include <string.h>
 
@@ -306,6 +307,16 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
     src_ip = &pcb->local_ip;
   }
 
+#if LWIP_IPV6
+  /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, */
+  /* compute the checksum and update the checksum in the payload. */
+  if (PCB_ISIPV6(pcb) && pcb->chksum_reqd) {
+      u16_t chksum;
+      chksum = ip6_chksum_pseudo(q, pcb->protocol, q->tot_len, ipX_2_ip6(src_ip), ipX_2_ip6(dst_ip));
+      (u16_t )(((u8_t *)q->payload) + pcb->chksum_offset) = chksum;
+  }
+#endif
+
   NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
   err = ipX_output_if(PCB_ISIPV6(pcb), q, ipX_2_ip(src_ip), ipX_2_ip(dst_ip), pcb->ttl, pcb->tos, pcb->protocol, netif);
   NETIF_SET_HWADDRHINT(netif, NULL);
diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h
index f0c8ed4..e141248 100644
--- a/src/include/lwip/raw.h
+++ b/src/include/lwip/raw.h
@@ -97,6 +97,11 @@ struct raw_pcb {
   } recv;
   /* user-supplied argument for the recv callback */
   void *recv_arg;
+#if LWIP_IPV6
+  /* fields for handling checksum computations as per RFC3542. */
+  u8_t  chksum_reqd;
+  u16_t chksum_offset;
+#endif
 };
 
 /* The following functions is the application layer interface to the
diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h
index 6906ed3..2ae81b6 100644
--- a/src/include/lwip/sockets.h
+++ b/src/include/lwip/sockets.h
@@ -185,7 +185,8 @@ struct linger {
 /*
  * Options for level IPPROTO_IPV6
  */
-#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */
+#define IPV6_CHECKSUM       7  /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */
+#define IPV6_V6ONLY         27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */
 #endif /* LWIP_IPV6 */
 
 #if LWIP_UDP && LWIP_UDPLITE

Grant Erickson <marathon96>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attached Files
file #27131:  rfc3542-checksum-0002.0.patch added by marathon96 (7KiB - application/octet-stream - Patch 2/2.)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by pjsg (Posted a comment)
  • -email is unavailable- added by goldsimon (Updated the item)
  • -email is unavailable- added by marathon96 (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2014-02-21 goldsimon StatusIn Progress Done
        Open/ClosedOpen Closed
    2014-02-21 goldsimon StatusDone In Progress
        Open/ClosedClosed Open
    2014-02-20 goldsimon StatusNone Done
        Assigned toNone goldsimon
        Open/ClosedOpen Closed
    2013-01-15 goldsimon CategoryNone IPv6
    2012-12-20 marathon96 Attached File- Added rfc3542-checksum-0002.0.patch, #27131

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code