2 /* $KAME: ah_input.c,v 1.29 2000/05/29 08:33:53 itojun Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * RFC1826/2402 authentication header.
38 #include "opt_inet6.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
44 #include <sys/domain.h>
45 #include <sys/protosw.h>
46 #include <sys/socket.h>
47 #include <sys/errno.h>
49 #include <sys/syslog.h>
52 #include <net/route.h>
53 #include <net/netisr.h>
54 #include <machine/cpu.h>
56 #include <netinet/in.h>
57 #include <netinet/in_systm.h>
58 #include <netinet/in_var.h>
59 #include <netinet/ip.h>
60 #include <netinet/ip_var.h>
61 #include <netinet/ip_ecn.h>
63 #include <netinet6/ip6_ecn.h>
67 #include <netinet/ip6.h>
68 #include <netinet6/ip6_var.h>
69 #include <netinet/icmp6.h>
72 #include <netinet6/ipsec.h>
74 #include <netinet6/ipsec6.h>
76 #include <netinet6/ah.h>
78 #include <netinet6/ah6.h>
80 #include <netkey/key.h>
81 #include <netkey/keydb.h>
83 #include <netkey/key_debug.h>
85 #define KEYDEBUG(lev,arg)
88 #include <machine/stdarg.h>
90 #include <net/net_osdep.h>
95 #include <netinet/ipprotosw.h>
96 extern struct ipprotosw inetsw[];
100 ah4_input(struct mbuf *m, ...)
102 ah4_input(m, va_alist)
110 struct ah_algorithm *algo;
114 struct secasvar *sav = NULL;
122 off = va_arg(ap, int);
123 proto = va_arg(ap, int);
126 #ifndef PULLDOWN_TEST
127 if (m->m_len < off + sizeof(struct newah)) {
128 m = m_pullup(m, off + sizeof(struct newah));
130 ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;"
131 "dropping the packet for simplicity\n"));
132 ipsecstat.in_inval++;
137 ip = mtod(m, struct ip *);
138 ah = (struct ah *)(((caddr_t)ip) + off);
140 ip = mtod(m, struct ip *);
141 IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah));
143 ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;"
144 "dropping the packet for simplicity\n"));
145 ipsecstat.in_inval++;
151 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
153 hlen = ip->ip_hl << 2;
156 /* find the sassoc. */
159 if ((sav = key_allocsa(AF_INET,
160 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
161 IPPROTO_AH, spi)) == 0) {
162 ipseclog((LOG_WARNING,
163 "IPv4 AH input: no key association found for spi %u\n",
164 (u_int32_t)ntohl(spi)));
168 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
169 printf("DP ah4_input called to allocate SA:%p\n", sav));
170 if (sav->state != SADB_SASTATE_MATURE
171 && sav->state != SADB_SASTATE_DYING) {
173 "IPv4 AH input: non-mature/dying SA found for spi %u\n",
174 (u_int32_t)ntohl(spi)));
175 ipsecstat.in_badspi++;
178 if (sav->alg_auth == SADB_AALG_NONE) {
179 ipseclog((LOG_DEBUG, "IPv4 AH input: "
180 "unspecified authentication algorithm for spi %u\n",
181 (u_int32_t)ntohl(spi)));
182 ipsecstat.in_badspi++;
186 algo = &ah_algorithms[sav->alg_auth];
188 siz = (*algo->sumsiz)(sav);
189 siz1 = ((siz + 3) & ~(4 - 1));
192 * sanity checks for header, 1.
197 sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
200 * Here, we do not do "siz1 == siz". This is because the way
201 * RFC240[34] section 2 is written. They do not require truncation
203 * For example, Microsoft IPsec stack attaches 160 bits of
204 * authentication data for both hmac-md5 and hmac-sha1. For hmac-sha1,
205 * 32 bits of padding is attached.
207 * There are two downsides to this specification.
208 * They have no real harm, however, they leave us fuzzy feeling.
209 * - if we attach more than 96 bits of authentication data onto AH,
210 * we will never notice about possible modification by rogue
211 * intermediate nodes.
212 * Since extra bits in AH checksum is never used, this constitutes
213 * no real issue, however, it is wacky.
214 * - even if the peer attaches big authentication data, we will never
215 * notice the difference, since longer authentication data will just
218 * We may need some clarification in the spec.
221 ipseclog((LOG_NOTICE, "sum length too short in IPv4 AH input "
222 "(%lu, should be at least %lu): %s\n",
223 (u_long)siz1, (u_long)siz,
224 ipsec4_logpacketstr(ip, spi)));
225 ipsecstat.in_inval++;
228 if ((ah->ah_len << 2) - sizoff != siz1) {
229 ipseclog((LOG_NOTICE, "sum length mismatch in IPv4 AH input "
230 "(%d should be %lu): %s\n",
231 (ah->ah_len << 2) - sizoff, (u_long)siz1,
232 ipsec4_logpacketstr(ip, spi)));
233 ipsecstat.in_inval++;
237 #ifndef PULLDOWN_TEST
238 if (m->m_len < off + sizeof(struct ah) + sizoff + siz1) {
239 m = m_pullup(m, off + sizeof(struct ah) + sizoff + siz1);
241 ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n"));
242 ipsecstat.in_inval++;
246 ip = mtod(m, struct ip *);
247 ah = (struct ah *)(((caddr_t)ip) + off);
250 IP6_EXTHDR_GET(ah, struct ah *, m, off,
251 sizeof(struct ah) + sizoff + siz1);
253 ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n"));
254 ipsecstat.in_inval++;
261 * check for sequence number.
263 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
264 if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav))
267 ipsecstat.in_ahreplay++;
268 ipseclog((LOG_WARNING,
269 "replay packet in IPv4 AH input: %s %s\n",
270 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
276 * alright, it seems sane. now we are going to check the
277 * cryptographic checksum.
279 cksum = malloc(siz1, M_TEMP, M_NOWAIT);
281 ipseclog((LOG_DEBUG, "IPv4 AH input: "
282 "couldn't alloc temporary region for cksum\n"));
283 ipsecstat.in_inval++;
290 * some of IP header fields are flipped to the host endian.
291 * convert them back to network endian. VERY stupid.
293 ip->ip_len = htons(ip->ip_len + hlen);
294 ip->ip_off = htons(ip->ip_off);
296 if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) {
298 ipsecstat.in_inval++;
301 ipsecstat.in_ahhist[sav->alg_auth]++;
306 ip->ip_len = ntohs(ip->ip_len) - hlen;
307 ip->ip_off = ntohs(ip->ip_off);
312 caddr_t sumpos = NULL;
314 if (sav->flags & SADB_X_EXT_OLD) {
316 sumpos = (caddr_t)(ah + 1);
319 sumpos = (caddr_t)(((struct newah *)ah) + 1);
322 if (bcmp(sumpos, cksum, siz) != 0) {
323 ipseclog((LOG_WARNING,
324 "checksum mismatch in IPv4 AH input: %s %s\n",
325 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
327 ipsecstat.in_ahauthfail++;
334 m->m_flags |= M_AUTHIPHDR;
335 m->m_flags |= M_AUTHIPDGM;
339 * looks okey, but we need more sanity check.
340 * XXX should elaborate.
342 if (ah->ah_nxt == IPPROTO_IPIP || ah->ah_nxt == IPPROTO_IP) {
346 sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
348 if (m->m_len < off + sizeof(struct ah) + sizoff + siz1 + hlen) {
349 m = m_pullup(m, off + sizeof(struct ah)
350 + sizoff + siz1 + hlen);
353 "IPv4 AH input: can't pullup\n"));
354 ipsecstat.in_inval++;
359 nip = (struct ip *)((u_char *)(ah + 1) + sizoff + siz1);
360 if (nip->ip_src.s_addr != ip->ip_src.s_addr
361 || nip->ip_dst.s_addr != ip->ip_dst.s_addr) {
362 m->m_flags &= ~M_AUTHIPHDR;
363 m->m_flags &= ~M_AUTHIPDGM;
367 else if (ah->ah_nxt == IPPROTO_IPV6) {
368 m->m_flags &= ~M_AUTHIPHDR;
369 m->m_flags &= ~M_AUTHIPDGM;
374 if (m->m_flags & M_AUTHIPHDR
375 && m->m_flags & M_AUTHIPDGM) {
378 "IPv4 AH input: authentication succeess\n"));
380 ipsecstat.in_ahauthsucc++;
382 ipseclog((LOG_WARNING,
383 "authentication failed in IPv4 AH input: %s %s\n",
384 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
385 ipsecstat.in_ahauthfail++;
390 * update sequence number.
392 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
393 if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) {
394 ipsecstat.in_ahreplay++;
399 /* was it transmitted over the IPsec tunnel SA? */
400 if (ipsec4_tunnel_validate(ip, nxt, sav) && nxt == IPPROTO_IPV4) {
402 * strip off all the headers that precedes AH.
403 * IP xx AH IP' payload -> IP' payload
405 * XXX more sanity checks
406 * XXX relationship with gif?
412 if (sav->flags & SADB_X_EXT_OLD) {
414 stripsiz = sizeof(struct ah) + siz1;
417 stripsiz = sizeof(struct newah) + siz1;
419 m_adj(m, off + stripsiz);
420 if (m->m_len < sizeof(*ip)) {
421 m = m_pullup(m, sizeof(*ip));
423 ipsecstat.in_inval++;
427 ip = mtod(m, struct ip *);
428 /* ECN consideration. */
429 ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
430 if (!key_checktunnelsanity(sav, AF_INET,
431 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
432 ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch "
433 "in IPv4 AH input: %s %s\n",
434 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
435 ipsecstat.in_inval++;
439 #if 0 /* XXX should we call ipfw rather than ipsec_in_reject? */
440 /* drop it if it does not match the default policy */
441 if (ipsec4_in_reject(m, NULL)) {
442 ipsecstat.in_polvio++;
449 * Should the inner packet be considered authentic?
450 * My current answer is: NO.
452 * host1 -- gw1 === gw2 -- host2
453 * In this case, gw2 can trust the authenticity of the
454 * outer packet, but NOT inner. Packet may be altered
455 * between host1 and gw1.
457 * host1 -- gw1 === host2
458 * This case falls into the same scenario as above.
461 * This case is the only case when we may be able to leave
462 * M_AUTHIPHDR and M_AUTHIPDGM set.
463 * However, if host1 is wrongly configured, and allows
464 * attacker to inject some packet with src=host1 and
465 * dst=host2, you are in risk.
467 m->m_flags &= ~M_AUTHIPHDR;
468 m->m_flags &= ~M_AUTHIPDGM;
471 key_sa_recordxfer(sav, m);
473 if (! IF_HANDOFF(&ipintrq, m, NULL)) {
474 ipsecstat.in_inval++;
479 schednetisr(NETISR_IP); /*can be skipped but to make sure*/
487 if (sav->flags & SADB_X_EXT_OLD) {
489 stripsiz = sizeof(struct ah) + siz1;
492 stripsiz = sizeof(struct newah) + siz1;
495 ip = mtod(m, struct ip *);
496 #ifndef PULLDOWN_TEST
498 * We do deep-copy since KAME requires that
499 * the packet is placed in a single external mbuf.
501 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
502 m->m_data += stripsiz;
503 m->m_len -= stripsiz;
504 m->m_pkthdr.len -= stripsiz;
507 * even in m_pulldown case, we need to strip off AH so that
508 * we can compute checksum for multiple AH correctly.
510 if (m->m_len >= stripsiz + off) {
511 ovbcopy((caddr_t)ip, ((caddr_t)ip) + stripsiz, off);
512 m->m_data += stripsiz;
513 m->m_len -= stripsiz;
514 m->m_pkthdr.len -= stripsiz;
517 * this comes with no copy if the boundary is on
522 n = m_split(m, off, M_DONTWAIT);
524 /* m is retained by m_split */
529 /* m_cat does not update m_pkthdr.len */
530 m->m_pkthdr.len += n->m_pkthdr.len;
534 if (m->m_len < sizeof(*ip)) {
535 m = m_pullup(m, sizeof(*ip));
537 ipsecstat.in_inval++;
541 ip = mtod(m, struct ip *);
543 ip->ip_len = ip->ip_len - stripsiz;
545 ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
548 /* forget about IP hdr checksum, the check has already been passed */
550 key_sa_recordxfer(sav, m);
552 if (nxt != IPPROTO_DONE)
553 (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
560 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
561 printf("DP ah4_input call free SA:%p\n", sav));
564 ipsecstat.in_success++;
569 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
570 printf("DP ah4_input call free SA:%p\n", sav));
581 ah6_input(mp, offp, proto)
585 struct mbuf *m = *mp;
590 struct ah_algorithm *algo;
594 struct secasvar *sav = NULL;
597 #ifndef PULLDOWN_TEST
598 IP6_EXTHDR_CHECK(m, off, sizeof(struct ah), IPPROTO_DONE);
599 ah = (struct ah *)(mtod(m, caddr_t) + off);
601 IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah));
603 ipseclog((LOG_DEBUG, "IPv6 AH input: can't pullup\n"));
604 ipsecstat.in_inval++;
608 ip6 = mtod(m, struct ip6_hdr *);
611 /* find the sassoc. */
614 if (ntohs(ip6->ip6_plen) == 0) {
615 ipseclog((LOG_ERR, "IPv6 AH input: "
616 "AH with IPv6 jumbogram is not supported.\n"));
617 ipsec6stat.in_inval++;
621 if ((sav = key_allocsa(AF_INET6,
622 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
623 IPPROTO_AH, spi)) == 0) {
624 ipseclog((LOG_WARNING,
625 "IPv6 AH input: no key association found for spi %u\n",
626 (u_int32_t)ntohl(spi)));
627 ipsec6stat.in_nosa++;
630 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
631 printf("DP ah6_input called to allocate SA:%p\n", sav));
632 if (sav->state != SADB_SASTATE_MATURE
633 && sav->state != SADB_SASTATE_DYING) {
635 "IPv6 AH input: non-mature/dying SA found for spi %u; ",
636 (u_int32_t)ntohl(spi)));
637 ipsec6stat.in_badspi++;
640 if (sav->alg_auth == SADB_AALG_NONE) {
641 ipseclog((LOG_DEBUG, "IPv6 AH input: "
642 "unspecified authentication algorithm for spi %u\n",
643 (u_int32_t)ntohl(spi)));
644 ipsec6stat.in_badspi++;
648 algo = &ah_algorithms[sav->alg_auth];
650 siz = (*algo->sumsiz)(sav);
651 siz1 = ((siz + 3) & ~(4 - 1));
654 * sanity checks for header, 1.
659 sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
662 * Here, we do not do "siz1 == siz". See ah4_input() for complete
666 ipseclog((LOG_NOTICE, "sum length too short in IPv6 AH input "
667 "(%lu, should be at least %lu): %s\n",
668 (u_long)siz1, (u_long)siz,
669 ipsec6_logpacketstr(ip6, spi)));
670 ipsec6stat.in_inval++;
673 if ((ah->ah_len << 2) - sizoff != siz1) {
674 ipseclog((LOG_NOTICE, "sum length mismatch in IPv6 AH input "
675 "(%d should be %lu): %s\n",
676 (ah->ah_len << 2) - sizoff, (u_long)siz1,
677 ipsec6_logpacketstr(ip6, spi)));
678 ipsec6stat.in_inval++;
681 #ifndef PULLDOWN_TEST
682 IP6_EXTHDR_CHECK(m, off, sizeof(struct ah) + sizoff + siz1, IPPROTO_DONE);
684 IP6_EXTHDR_GET(ah, struct ah *, m, off,
685 sizeof(struct ah) + sizoff + siz1);
687 ipseclog((LOG_NOTICE, "couldn't pullup gather IPv6 AH checksum part"));
688 ipsecstat.in_inval++;
696 * check for sequence number.
698 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
699 if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav))
702 ipsec6stat.in_ahreplay++;
703 ipseclog((LOG_WARNING,
704 "replay packet in IPv6 AH input: %s %s\n",
705 ipsec6_logpacketstr(ip6, spi),
706 ipsec_logsastr(sav)));
712 * alright, it seems sane. now we are going to check the
713 * cryptographic checksum.
715 cksum = malloc(siz1, M_TEMP, M_NOWAIT);
717 ipseclog((LOG_DEBUG, "IPv6 AH input: "
718 "couldn't alloc temporary region for cksum\n"));
719 ipsec6stat.in_inval++;
723 if (ah6_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) {
725 ipsec6stat.in_inval++;
728 ipsec6stat.in_ahhist[sav->alg_auth]++;
731 caddr_t sumpos = NULL;
733 if (sav->flags & SADB_X_EXT_OLD) {
735 sumpos = (caddr_t)(ah + 1);
738 sumpos = (caddr_t)(((struct newah *)ah) + 1);
741 if (bcmp(sumpos, cksum, siz) != 0) {
742 ipseclog((LOG_WARNING,
743 "checksum mismatch in IPv6 AH input: %s %s\n",
744 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
746 ipsec6stat.in_ahauthfail++;
753 m->m_flags |= M_AUTHIPHDR;
754 m->m_flags |= M_AUTHIPDGM;
758 * looks okey, but we need more sanity check.
759 * XXX should elaborate.
761 if (ah->ah_nxt == IPPROTO_IPV6) {
762 struct ip6_hdr *nip6;
765 sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
767 IP6_EXTHDR_CHECK(m, off, sizeof(struct ah) + sizoff + siz1
768 + sizeof(struct ip6_hdr), IPPROTO_DONE);
770 nip6 = (struct ip6_hdr *)((u_char *)(ah + 1) + sizoff + siz1);
771 if (!IN6_ARE_ADDR_EQUAL(&nip6->ip6_src, &ip6->ip6_src)
772 || !IN6_ARE_ADDR_EQUAL(&nip6->ip6_dst, &ip6->ip6_dst)) {
773 m->m_flags &= ~M_AUTHIPHDR;
774 m->m_flags &= ~M_AUTHIPDGM;
776 } else if (ah->ah_nxt == IPPROTO_IPIP) {
777 m->m_flags &= ~M_AUTHIPHDR;
778 m->m_flags &= ~M_AUTHIPDGM;
779 } else if (ah->ah_nxt == IPPROTO_IP) {
780 m->m_flags &= ~M_AUTHIPHDR;
781 m->m_flags &= ~M_AUTHIPDGM;
785 if (m->m_flags & M_AUTHIPHDR
786 && m->m_flags & M_AUTHIPDGM) {
789 "IPv6 AH input: authentication succeess\n"));
791 ipsec6stat.in_ahauthsucc++;
793 ipseclog((LOG_WARNING,
794 "authentication failed in IPv6 AH input: %s %s\n",
795 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
796 ipsec6stat.in_ahauthfail++;
801 * update sequence number.
803 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
804 if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) {
805 ipsec6stat.in_ahreplay++;
810 /* was it transmitted over the IPsec tunnel SA? */
811 if (ipsec6_tunnel_validate(ip6, nxt, sav) && nxt == IPPROTO_IPV6) {
813 * strip off all the headers that precedes AH.
814 * IP6 xx AH IP6' payload -> IP6' payload
816 * XXX more sanity checks
817 * XXX relationship with gif?
820 u_int32_t flowinfo; /*net endian*/
822 flowinfo = ip6->ip6_flow;
823 if (sav->flags & SADB_X_EXT_OLD) {
825 stripsiz = sizeof(struct ah) + siz1;
828 stripsiz = sizeof(struct newah) + siz1;
830 m_adj(m, off + stripsiz);
831 if (m->m_len < sizeof(*ip6)) {
833 * m_pullup is prohibited in KAME IPv6 input processing
834 * but there's no other way!
836 m = m_pullup(m, sizeof(*ip6));
838 ipsec6stat.in_inval++;
842 ip6 = mtod(m, struct ip6_hdr *);
843 /* ECN consideration. */
844 ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
845 if (!key_checktunnelsanity(sav, AF_INET6,
846 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
847 ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch "
848 "in IPv6 AH input: %s %s\n",
849 ipsec6_logpacketstr(ip6, spi),
850 ipsec_logsastr(sav)));
851 ipsec6stat.in_inval++;
855 #if 0 /* XXX should we call ipfw rather than ipsec_in_reject? */
856 /* drop it if it does not match the default policy */
857 if (ipsec6_in_reject(m, NULL)) {
858 ipsec6stat.in_polvio++;
865 * should the inner packet be considered authentic?
866 * see comment in ah4_input().
868 m->m_flags &= ~M_AUTHIPHDR;
869 m->m_flags &= ~M_AUTHIPDGM;
872 key_sa_recordxfer(sav, m);
874 if (! IF_HANDOFF(&ip6intrq, m, NULL)) {
875 ipsec6stat.in_inval++;
880 schednetisr(NETISR_IPV6); /*can be skipped but to make sure*/
890 * Copy the value of the next header field of AH to the
891 * next header field of the previous header.
892 * This is necessary because AH will be stripped off below.
894 prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
897 if (sav->flags & SADB_X_EXT_OLD) {
899 stripsiz = sizeof(struct ah) + siz1;
902 stripsiz = sizeof(struct newah) + siz1;
905 ip6 = mtod(m, struct ip6_hdr *);
906 #ifndef PULLDOWN_TEST
908 * We do deep-copy since KAME requires that
909 * the packet is placed in a single mbuf.
911 ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
912 m->m_data += stripsiz;
913 m->m_len -= stripsiz;
914 m->m_pkthdr.len -= stripsiz;
917 * even in m_pulldown case, we need to strip off AH so that
918 * we can compute checksum for multiple AH correctly.
920 if (m->m_len >= stripsiz + off) {
921 ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
922 m->m_data += stripsiz;
923 m->m_len -= stripsiz;
924 m->m_pkthdr.len -= stripsiz;
927 * this comes with no copy if the boundary is on
932 n = m_split(m, off, M_DONTWAIT);
934 /* m is retained by m_split */
939 /* m_cat does not update m_pkthdr.len */
940 m->m_pkthdr.len += n->m_pkthdr.len;
943 ip6 = mtod(m, struct ip6_hdr *);
945 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
947 key_sa_recordxfer(sav, m);
954 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
955 printf("DP ah6_input call free SA:%p\n", sav));
958 ipsec6stat.in_success++;
963 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
964 printf("DP ah6_input call free SA:%p\n", sav));