Author: thj
Date: Wed Jun  6 07:04:40 2018
New Revision: 334705
URL: https://svnweb.freebsd.org/changeset/base/334705

Log:
  Use UDP len when calculating UDP checksums
  
  The length of the IP payload is normally equal to the UDP length, UDP Options
  (draft-ietf-tsvwg-udp-options-02) suggests using the difference between IP
  length and UDP length to create space for trailing data.
  
  Correct checksum length calculation to use the UDP length rather than the IP
  length when not offloading UDP checksums.
  
  Approved by: jtl (mentor)
  Differential Revision:        https://reviews.freebsd.org/D15222

Modified:
  head/sys/netinet/ip_output.c

Modified: head/sys/netinet/ip_output.c
==============================================================================
--- head/sys/netinet/ip_output.c        Wed Jun  6 06:42:12 2018        
(r334704)
+++ head/sys/netinet/ip_output.c        Wed Jun  6 07:04:40 2018        
(r334705)
@@ -80,6 +80,10 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in_var.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_options.h>
+
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
 #ifdef SCTP
 #include <netinet/sctp.h>
 #include <netinet/sctp_crc32.h>
@@ -920,14 +924,28 @@ void
 in_delayed_cksum(struct mbuf *m)
 {
        struct ip *ip;
-       uint16_t csum, offset, ip_len;
+       struct udphdr *uh;
+       uint16_t cklen, csum, offset;
 
        ip = mtod(m, struct ip *);
        offset = ip->ip_hl << 2 ;
-       ip_len = ntohs(ip->ip_len);
-       csum = in_cksum_skip(m, ip_len, offset);
-       if (m->m_pkthdr.csum_flags & CSUM_UDP && csum == 0)
-               csum = 0xffff;
+
+       if (m->m_pkthdr.csum_flags & CSUM_UDP) {
+               /* if udp header is not in the first mbuf copy udplen */
+               if (offset + sizeof(struct udphdr) > m->m_len)
+                       m_copydata(m, offset + offsetof(struct udphdr, uh_ulen),
+                               2, (caddr_t)&cklen);
+               else {
+                       uh = (struct udphdr *)((caddr_t)ip + offset);
+                       cklen = ntohs(uh->uh_ulen);
+               }
+               csum = in_cksum_skip(m, cklen + offset, offset);
+               if (csum == 0)
+                       csum = 0xffff;
+       } else {
+               cklen = ntohs(ip->ip_len);
+               csum = in_cksum_skip(m, cklen, offset);
+       }
        offset += m->m_pkthdr.csum_data;        /* checksum offset */
 
        /* find the mbuf in the chain where the checksum starts*/
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to