Index: head/sys/netinet/ip_output.c =================================================================== --- head/sys/netinet/ip_output.c +++ head/sys/netinet/ip_output.c @@ -80,6 +80,10 @@ #include #include #include + +#include +#include + #ifdef SCTP #include #include @@ -920,14 +924,28 @@ 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*/