Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netipsec/ipsec_output.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netipsec/ipsec_output.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.80 retrieving revision 1.81 diff -u -p -r1.80 -r1.81 --- src/sys/netipsec/ipsec_output.c 2018/05/31 15:06:45 1.80 +++ src/sys/netipsec/ipsec_output.c 2018/11/22 04:48:34 1.81 @@ -1,4 +1,4 @@ -/* $NetBSD: ipsec_output.c,v 1.80 2018/05/31 15:06:45 maxv Exp $ */ +/* $NetBSD: ipsec_output.c,v 1.81 2018/11/22 04:48:34 knakahara Exp $ */ /* * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting @@ -29,7 +29,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.80 2018/05/31 15:06:45 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.81 2018/11/22 04:48:34 knakahara Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -151,7 +151,7 @@ ipsec_process_done(struct mbuf *m, const #endif struct mbuf *mo; struct udphdr *udp = NULL; - int hlen, roff; + int hlen, roff, iphlen; KASSERT(m != NULL); KASSERT(isr != NULL); @@ -160,11 +160,30 @@ ipsec_process_done(struct mbuf *m, const saidx = &sav->sah->saidx; if (sav->natt_type != 0) { - ip = mtod(m, struct ip *); - hlen = sizeof(struct udphdr); - mo = m_makespace(m, sizeof(struct ip), hlen, &roff); + switch (saidx->dst.sa.sa_family) { +#ifdef INET + case AF_INET: + ip = mtod(m, struct ip *); + mo = m_makespace(m, sizeof(struct ip), hlen, &roff); + iphlen = ip->ip_hl << 2; + break; +#endif +#ifdef INET6 + case AF_INET6: + ip6 = mtod(m, struct ip6_hdr *); + mo = m_makespace(m, sizeof(struct ip6_hdr), hlen, &roff); + iphlen = sizeof(*ip6); + break; +#endif + default: + IPSECLOG(LOG_DEBUG, "unknown protocol family %u\n", + saidx->dst.sa.sa_family); + error = ENXIO; + goto bad; + } + if (mo == NULL) { char buf[IPSEC_ADDRSTRLEN]; IPSECLOG(LOG_DEBUG, @@ -179,7 +198,7 @@ ipsec_process_done(struct mbuf *m, const udp->uh_sport = key_portfromsaddr(&saidx->src); udp->uh_dport = key_portfromsaddr(&saidx->dst); udp->uh_sum = 0; - udp->uh_ulen = htons(m->m_pkthdr.len - (ip->ip_hl << 2)); + udp->uh_ulen = htons(m->m_pkthdr.len - iphlen); } /* @@ -190,6 +209,7 @@ ipsec_process_done(struct mbuf *m, const case AF_INET: ip = mtod(m, struct ip *); ip->ip_len = htons(m->m_pkthdr.len); + /* IPv4 packet does not have to be set UDP checksum. */ if (sav->natt_type != 0) ip->ip_p = IPPROTO_UDP; break; @@ -207,8 +227,11 @@ ipsec_process_done(struct mbuf *m, const } ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); - if (sav->natt_type != 0) + /* IPv6 packet should be set UDP checksum. */ + if (sav->natt_type != 0) { ip6->ip6_nxt = IPPROTO_UDP; + ipsec6_udp_cksum(m); + } break; #endif default: