diff options
| author | Tom Jones <thj@FreeBSD.org> | 2018-06-06 07:04:40 +0000 |
|---|---|---|
| committer | Tom Jones <thj@FreeBSD.org> | 2018-06-06 07:04:40 +0000 |
| commit | 1fdbfb909fa976ece3655bea8f4bc419aeed732b (patch) | |
| tree | 2e01f1f9a9f0adadc73abebeccca4552e307ede9 /sys/netinet/ip_output.c | |
| parent | bca1b45bb111aa7ce53ee184d600669979c9c091 (diff) | |
Notes
Diffstat (limited to 'sys/netinet/ip_output.c')
| -rw-r--r-- | sys/netinet/ip_output.c | 28 |
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*/ |
