aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/ip_output.c
diff options
context:
space:
mode:
authorTom Jones <thj@FreeBSD.org>2018-06-06 07:04:40 +0000
committerTom Jones <thj@FreeBSD.org>2018-06-06 07:04:40 +0000
commit1fdbfb909fa976ece3655bea8f4bc419aeed732b (patch)
tree2e01f1f9a9f0adadc73abebeccca4552e307ede9 /sys/netinet/ip_output.c
parentbca1b45bb111aa7ce53ee184d600669979c9c091 (diff)
Notes
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r--sys/netinet/ip_output.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index b2580cc08638..51bc2d885403 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -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*/