]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/ah_input.c
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * RFC1826/2402 authentication header.
35 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/malloc.h>
43 #include <sys/domain.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/errno.h>
48 #include <sys/kernel.h>
49 #include <sys/syslog.h>
52 #include <net/route.h>
53 #include <net/netisr.h>
54 #include <kern/cpu_number.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>
64 #include <netinet/ip6.h>
65 #include <netinet6/ip6_var.h>
66 #include <netinet/icmp6.h>
69 #include <netinet6/ipsec.h>
70 #include <netinet6/ah.h>
71 #include <netkey/key.h>
72 #include <netkey/keydb.h>
73 #include <netkey/key_debug.h>
76 #include <net/net_osdep.h>
81 extern struct protosw inetsw
[];
82 #if defined(__bsdi__) || defined(__NetBSD__)
83 extern u_char ip_protox
[];
87 ah4_input(struct mbuf
*m
, int off
)
92 struct ah_algorithm
*algo
;
96 struct secasvar
*sav
= NULL
;
101 #ifndef PULLDOWN_TEST
102 if (m
->m_len
< off
+ sizeof(struct newah
)) {
103 m
= m_pullup(m
, off
+ sizeof(struct newah
));
105 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup;"
106 "dropping the packet for simplicity\n"));
107 ipsecstat
.in_inval
++;
112 ip
= mtod(m
, struct ip
*);
113 ah
= (struct ah
*)(((caddr_t
)ip
) + off
);
115 ip
= mtod(m
, struct ip
*);
116 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
, sizeof(struct newah
));
118 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup;"
119 "dropping the packet for simplicity\n"));
120 ipsecstat
.in_inval
++;
126 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2;
128 hlen
= ip
->ip_hl
<< 2;
131 /* find the sassoc. */
134 if ((sav
= key_allocsa(AF_INET
,
135 (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
,
136 IPPROTO_AH
, spi
)) == 0) {
137 ipseclog((LOG_WARNING
,
138 "IPv4 AH input: no key association found for spi %u\n",
139 (u_int32_t
)ntohl(spi
)));
143 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
144 printf("DP ah4_input called to allocate SA:%p\n", sav
));
145 if (sav
->state
!= SADB_SASTATE_MATURE
146 && sav
->state
!= SADB_SASTATE_DYING
) {
148 "IPv4 AH input: non-mature/dying SA found for spi %u\n",
149 (u_int32_t
)ntohl(spi
)));
150 ipsecstat
.in_badspi
++;
153 if (sav
->alg_auth
== SADB_AALG_NONE
) {
154 ipseclog((LOG_DEBUG
, "IPv4 AH input: "
155 "unspecified authentication algorithm for spi %u\n",
156 (u_int32_t
)ntohl(spi
)));
157 ipsecstat
.in_badspi
++;
161 algo
= &ah_algorithms
[sav
->alg_auth
];
163 siz
= (*algo
->sumsiz
)(sav
);
164 siz1
= ((siz
+ 3) & ~(4 - 1));
167 * sanity checks for header, 1.
172 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
174 if ((ah
->ah_len
<< 2) - sizoff
!= siz1
) {
175 ipseclog((LOG_NOTICE
, "sum length mismatch in IPv4 AH input "
176 "(%d should be %u): %s\n",
177 (ah
->ah_len
<< 2) - sizoff
, (unsigned int)siz1
,
178 ipsec4_logpacketstr(ip
, spi
)));
179 ipsecstat
.in_inval
++;
183 #ifndef PULLDOWN_TEST
184 if (m
->m_len
< off
+ sizeof(struct ah
) + sizoff
+ siz1
) {
185 m
= m_pullup(m
, off
+ sizeof(struct ah
) + sizoff
+ siz1
);
187 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup\n"));
188 ipsecstat
.in_inval
++;
192 ip
= mtod(m
, struct ip
*);
193 ah
= (struct ah
*)(((caddr_t
)ip
) + off
);
196 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
,
197 sizeof(struct ah
) + sizoff
+ siz1
);
199 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup\n"));
200 ipsecstat
.in_inval
++;
207 * check for sequence number.
209 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
210 if (ipsec_chkreplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
))
213 ipsecstat
.in_ahreplay
++;
214 ipseclog((LOG_WARNING
,
215 "replay packet in IPv4 AH input: %s %s\n",
216 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
222 * alright, it seems sane. now we are going to check the
223 * cryptographic checksum.
225 cksum
= _MALLOC(siz1
, M_TEMP
, M_NOWAIT
);
227 ipseclog((LOG_DEBUG
, "IPv4 AH input: "
228 "couldn't alloc temporary region for cksum\n"));
229 ipsecstat
.in_inval
++;
236 * some of IP header fields are flipped to the host endian.
237 * convert them back to network endian. VERY stupid.
240 ip
->ip_len
= htons(ip
->ip_len
+ hlen
);
241 ip
->ip_id
= htons(ip
->ip_id
);
243 ip
->ip_len
= htons(ip
->ip_len
);
245 ip
->ip_off
= htons(ip
->ip_off
);
247 if (ah4_calccksum(m
, (caddr_t
)cksum
, algo
, sav
)) {
248 _FREE(cksum
, M_TEMP
);
249 ipsecstat
.in_inval
++;
252 ipsecstat
.in_ahhist
[sav
->alg_auth
]++;
258 ip
->ip_len
= ntohs(ip
->ip_len
) - hlen
;
259 ip
->ip_id
= ntohs(ip
->ip_id
);
261 ip
->ip_len
= ntohs(ip
->ip_len
);
263 ip
->ip_off
= ntohs(ip
->ip_off
);
268 caddr_t sumpos
= NULL
;
270 if (sav
->flags
& SADB_X_EXT_OLD
) {
272 sumpos
= (caddr_t
)(ah
+ 1);
275 sumpos
= (caddr_t
)(((struct newah
*)ah
) + 1);
278 if (bcmp(sumpos
, cksum
, siz
) != 0) {
279 ipseclog((LOG_WARNING
,
280 "checksum mismatch in IPv4 AH input: %s %s\n",
281 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
282 _FREE(cksum
, M_TEMP
);
283 ipsecstat
.in_ahauthfail
++;
288 _FREE(cksum
, M_TEMP
);
290 m
->m_flags
|= M_AUTHIPHDR
;
291 m
->m_flags
|= M_AUTHIPDGM
;
295 * looks okey, but we need more sanity check.
296 * XXX should elaborate.
298 if (ah
->ah_nxt
== IPPROTO_IPIP
|| ah
->ah_nxt
== IPPROTO_IP
) {
302 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
304 if (m
->m_len
< off
+ sizeof(struct ah
) + sizoff
+ siz1
+ hlen
) {
305 m
= m_pullup(m
, off
+ sizeof(struct ah
)
306 + sizoff
+ siz1
+ hlen
);
309 "IPv4 AH input: can't pullup\n"));
310 ipsecstat
.in_inval
++;
315 nip
= (struct ip
*)((u_char
*)(ah
+ 1) + sizoff
+ siz1
);
316 if (nip
->ip_src
.s_addr
!= ip
->ip_src
.s_addr
317 || nip
->ip_dst
.s_addr
!= ip
->ip_dst
.s_addr
) {
318 m
->m_flags
&= ~M_AUTHIPHDR
;
319 m
->m_flags
&= ~M_AUTHIPDGM
;
323 else if (ah
->ah_nxt
== IPPROTO_IPV6
) {
324 m
->m_flags
&= ~M_AUTHIPHDR
;
325 m
->m_flags
&= ~M_AUTHIPDGM
;
330 if (m
->m_flags
& M_AUTHIPHDR
331 && m
->m_flags
& M_AUTHIPDGM
) {
334 "IPv4 AH input: authentication succeess\n"));
336 ipsecstat
.in_ahauthsucc
++;
338 ipseclog((LOG_WARNING
,
339 "authentication failed in IPv4 AH input: %s %s\n",
340 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
341 ipsecstat
.in_ahauthfail
++;
346 * update sequence number.
348 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
349 if (ipsec_updatereplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
)) {
350 ipsecstat
.in_ahreplay
++;
355 /* was it transmitted over the IPsec tunnel SA? */
356 if (ipsec4_tunnel_validate(ip
, nxt
, sav
) && nxt
== IPPROTO_IPV4
) {
358 * strip off all the headers that precedes AH.
359 * IP xx AH IP' payload -> IP' payload
361 * XXX more sanity checks
362 * XXX relationship with gif?
368 if (sav
->flags
& SADB_X_EXT_OLD
) {
370 stripsiz
= sizeof(struct ah
) + siz1
;
373 stripsiz
= sizeof(struct newah
) + siz1
;
375 m_adj(m
, off
+ stripsiz
);
376 if (m
->m_len
< sizeof(*ip
)) {
377 m
= m_pullup(m
, sizeof(*ip
));
379 ipsecstat
.in_inval
++;
383 ip
= mtod(m
, struct ip
*);
384 /* ECN consideration. */
385 ip_ecn_egress(ip4_ipsec_ecn
, &tos
, &ip
->ip_tos
);
386 if (!key_checktunnelsanity(sav
, AF_INET
,
387 (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
)) {
388 ipseclog((LOG_NOTICE
, "ipsec tunnel address mismatch "
389 "in IPv4 AH input: %s %s\n",
390 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
391 ipsecstat
.in_inval
++;
395 #if 0 /* XXX should we call ipfw rather than ipsec_in_reject? */
396 /* drop it if it does not match the default policy */
397 if (ipsec4_in_reject(m
, NULL
)) {
398 ipsecstat
.in_polvio
++;
405 * Should the inner packet be considered authentic?
406 * My current answer is: NO.
408 * host1 -- gw1 === gw2 -- host2
409 * In this case, gw2 can trust the authenticity of the
410 * outer packet, but NOT inner. Packet may be altered
411 * between host1 and gw1.
413 * host1 -- gw1 === host2
414 * This case falls into the same scenario as above.
417 * This case is the only case when we may be able to leave
418 * M_AUTHIPHDR and M_AUTHIPDGM set.
419 * However, if host1 is wrongly configured, and allows
420 * attacker to inject some packet with src=host1 and
421 * dst=host2, you are in risk.
423 m
->m_flags
&= ~M_AUTHIPHDR
;
424 m
->m_flags
&= ~M_AUTHIPDGM
;
427 key_sa_recordxfer(sav
, m
);
430 if (IF_QFULL(&ipintrq
)) {
431 ipsecstat
.in_inval
++;
434 IF_ENQUEUE(&ipintrq
, m
);
436 schednetisr(NETISR_IP
); /*can be skipped but to make sure*/
442 * We do deep-copy since KAME requires that
443 * the packet is placed in a single external mbuf.
447 if (sav
->flags
& SADB_X_EXT_OLD
) {
449 stripsiz
= sizeof(struct ah
) + siz1
;
452 stripsiz
= sizeof(struct newah
) + siz1
;
455 ip
= mtod(m
, struct ip
*);
456 #ifndef PULLDOWN_TEST
457 ovbcopy((caddr_t
)ip
, (caddr_t
)(((u_char
*)ip
) + stripsiz
), off
);
458 m
->m_data
+= stripsiz
;
459 m
->m_len
-= stripsiz
;
460 m
->m_pkthdr
.len
-= stripsiz
;
463 * even in m_pulldown case, we need to strip off AH so that
464 * we can compute checksum for multiple AH correctly.
466 if (m
->m_len
>= stripsiz
+ off
) {
467 ovbcopy((caddr_t
)ip
, ((caddr_t
)ip
) + stripsiz
, off
);
468 m
->m_data
+= stripsiz
;
469 m
->m_len
-= stripsiz
;
470 m
->m_pkthdr
.len
-= stripsiz
;
473 * this comes with no copy if the boundary is on
478 n
= m_split(m
, off
, M_DONTWAIT
);
480 /* m is retained by m_split */
485 /* m_cat does not update m_pkthdr.len */
486 m
->m_pkthdr
.len
+= n
->m_pkthdr
.len
;
490 if (m
->m_len
< sizeof(*ip
)) {
491 m
= m_pullup(m
, sizeof(*ip
));
493 ipsecstat
.in_inval
++;
497 ip
= mtod(m
, struct ip
*);
499 ip
->ip_len
= ip
->ip_len
- stripsiz
;
501 ip
->ip_len
= htons(ntohs(ip
->ip_len
) - stripsiz
);
504 /* forget about IP hdr checksum, the check has already been passed */
506 key_sa_recordxfer(sav
, m
);
508 if (nxt
!= IPPROTO_DONE
)
509 (*ip_protox
[nxt
]->pr_input
)(m
, off
);
516 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
517 printf("DP ah4_input call free SA:%p\n", sav
));
520 ipsecstat
.in_success
++;
525 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
526 printf("DP ah4_input call free SA:%p\n", sav
));
537 ah6_input(mp
, offp
, proto
)
541 struct mbuf
*m
= *mp
;
546 struct ah_algorithm
*algo
;
550 struct secasvar
*sav
= NULL
;
554 #ifndef PULLDOWN_TEST
555 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
), IPPROTO_DONE
);
556 ah
= (struct ah
*)(mtod(m
, caddr_t
) + off
);
558 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
, sizeof(struct newah
));
560 ipseclog((LOG_DEBUG
, "IPv6 AH input: can't pullup\n"));
561 ipsecstat
.in_inval
++;
565 ip6
= mtod(m
, struct ip6_hdr
*);
568 /* find the sassoc. */
571 if (ntohs(ip6
->ip6_plen
) == 0) {
572 ipseclog((LOG_ERR
, "IPv6 AH input: "
573 "AH with IPv6 jumbogram is not supported.\n"));
574 ipsec6stat
.in_inval
++;
578 if ((sav
= key_allocsa(AF_INET6
,
579 (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
,
580 IPPROTO_AH
, spi
)) == 0) {
581 ipseclog((LOG_WARNING
,
582 "IPv6 AH input: no key association found for spi %u\n",
583 (u_int32_t
)ntohl(spi
)));
584 ipsec6stat
.in_nosa
++;
587 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
588 printf("DP ah6_input called to allocate SA:%p\n", sav
));
589 if (sav
->state
!= SADB_SASTATE_MATURE
590 && sav
->state
!= SADB_SASTATE_DYING
) {
592 "IPv6 AH input: non-mature/dying SA found for spi %u; ",
593 (u_int32_t
)ntohl(spi
)));
594 ipsec6stat
.in_badspi
++;
597 if (sav
->alg_auth
== SADB_AALG_NONE
) {
598 ipseclog((LOG_DEBUG
, "IPv6 AH input: "
599 "unspecified authentication algorithm for spi %u\n",
600 (u_int32_t
)ntohl(spi
)));
601 ipsec6stat
.in_badspi
++;
605 algo
= &ah_algorithms
[sav
->alg_auth
];
607 siz
= (*algo
->sumsiz
)(sav
);
608 siz1
= ((siz
+ 3) & ~(4 - 1));
611 * sanity checks for header, 1.
616 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
618 if ((ah
->ah_len
<< 2) - sizoff
!= siz1
) {
619 ipseclog((LOG_NOTICE
, "sum length mismatch in IPv6 AH input "
620 "(%d should be %u): %s\n",
621 (ah
->ah_len
<< 2) - sizoff
, (unsigned int)siz1
,
622 ipsec6_logpacketstr(ip6
, spi
)));
623 ipsec6stat
.in_inval
++;
626 #ifndef PULLDOWN_TEST
627 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
) + sizoff
+ siz1
, IPPROTO_DONE
);
629 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
,
630 sizeof(struct ah
) + sizoff
+ siz1
);
632 ipseclog((LOG_NOTICE
, "couldn't pullup gather IPv6 AH checksum part"));
633 ipsecstat
.in_inval
++;
641 * check for sequence number.
643 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
644 if (ipsec_chkreplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
))
647 ipsec6stat
.in_ahreplay
++;
648 ipseclog((LOG_WARNING
,
649 "replay packet in IPv6 AH input: %s %s\n",
650 ipsec6_logpacketstr(ip6
, spi
),
651 ipsec_logsastr(sav
)));
657 * alright, it seems sane. now we are going to check the
658 * cryptographic checksum.
660 cksum
= _MALLOC(siz1
, M_TEMP
, M_NOWAIT
);
662 ipseclog((LOG_DEBUG
, "IPv6 AH input: "
663 "couldn't alloc temporary region for cksum\n"));
664 ipsec6stat
.in_inval
++;
668 if (ah6_calccksum(m
, (caddr_t
)cksum
, algo
, sav
)) {
669 _FREE(cksum
, M_TEMP
);
670 ipsec6stat
.in_inval
++;
673 ipsec6stat
.in_ahhist
[sav
->alg_auth
]++;
676 caddr_t sumpos
= NULL
;
678 if (sav
->flags
& SADB_X_EXT_OLD
) {
680 sumpos
= (caddr_t
)(ah
+ 1);
683 sumpos
= (caddr_t
)(((struct newah
*)ah
) + 1);
686 if (bcmp(sumpos
, cksum
, siz
) != 0) {
687 ipseclog((LOG_WARNING
,
688 "checksum mismatch in IPv6 AH input: %s %s\n",
689 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
690 _FREE(cksum
, M_TEMP
);
691 ipsec6stat
.in_ahauthfail
++;
696 _FREE(cksum
, M_TEMP
);
698 m
->m_flags
|= M_AUTHIPHDR
;
699 m
->m_flags
|= M_AUTHIPDGM
;
703 * looks okey, but we need more sanity check.
704 * XXX should elaborate.
706 if (ah
->ah_nxt
== IPPROTO_IPV6
) {
707 struct ip6_hdr
*nip6
;
710 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
712 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
) + sizoff
+ siz1
713 + sizeof(struct ip6_hdr
), IPPROTO_DONE
);
715 nip6
= (struct ip6_hdr
*)((u_char
*)(ah
+ 1) + sizoff
+ siz1
);
716 if (!IN6_ARE_ADDR_EQUAL(&nip6
->ip6_src
, &ip6
->ip6_src
)
717 || !IN6_ARE_ADDR_EQUAL(&nip6
->ip6_dst
, &ip6
->ip6_dst
)) {
718 m
->m_flags
&= ~M_AUTHIPHDR
;
719 m
->m_flags
&= ~M_AUTHIPDGM
;
721 } else if (ah
->ah_nxt
== IPPROTO_IPIP
) {
722 m
->m_flags
&= ~M_AUTHIPHDR
;
723 m
->m_flags
&= ~M_AUTHIPDGM
;
724 } else if (ah
->ah_nxt
== IPPROTO_IP
) {
725 m
->m_flags
&= ~M_AUTHIPHDR
;
726 m
->m_flags
&= ~M_AUTHIPDGM
;
730 if (m
->m_flags
& M_AUTHIPHDR
731 && m
->m_flags
& M_AUTHIPDGM
) {
734 "IPv6 AH input: authentication succeess\n"));
736 ipsec6stat
.in_ahauthsucc
++;
738 ipseclog((LOG_WARNING
,
739 "authentication failed in IPv6 AH input: %s %s\n",
740 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
741 ipsec6stat
.in_ahauthfail
++;
746 * update sequence number.
748 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
749 if (ipsec_updatereplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
)) {
750 ipsec6stat
.in_ahreplay
++;
755 /* was it transmitted over the IPsec tunnel SA? */
756 if (ipsec6_tunnel_validate(ip6
, nxt
, sav
) && nxt
== IPPROTO_IPV6
) {
758 * strip off all the headers that precedes AH.
759 * IP6 xx AH IP6' payload -> IP6' payload
761 * XXX more sanity checks
762 * XXX relationship with gif?
765 u_int32_t flowinfo
; /*net endian*/
767 flowinfo
= ip6
->ip6_flow
;
768 if (sav
->flags
& SADB_X_EXT_OLD
) {
770 stripsiz
= sizeof(struct ah
) + siz1
;
773 stripsiz
= sizeof(struct newah
) + siz1
;
775 m_adj(m
, off
+ stripsiz
);
776 if (m
->m_len
< sizeof(*ip6
)) {
778 * m_pullup is prohibited in KAME IPv6 input processing
779 * but there's no other way!
781 m
= m_pullup(m
, sizeof(*ip6
));
783 ipsec6stat
.in_inval
++;
787 ip6
= mtod(m
, struct ip6_hdr
*);
788 /* ECN consideration. */
789 ip6_ecn_egress(ip6_ipsec_ecn
, &flowinfo
, &ip6
->ip6_flow
);
790 if (!key_checktunnelsanity(sav
, AF_INET6
,
791 (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
)) {
792 ipseclog((LOG_NOTICE
, "ipsec tunnel address mismatch "
793 "in IPv6 AH input: %s %s\n",
794 ipsec6_logpacketstr(ip6
, spi
),
795 ipsec_logsastr(sav
)));
796 ipsec6stat
.in_inval
++;
800 #if 0 /* XXX should we call ipfw rather than ipsec_in_reject? */
801 /* drop it if it does not match the default policy */
802 if (ipsec6_in_reject(m
, NULL
)) {
803 ipsec6stat
.in_polvio
++;
810 * should the inner packet be considered authentic?
811 * see comment in ah4_input().
813 m
->m_flags
&= ~M_AUTHIPHDR
;
814 m
->m_flags
&= ~M_AUTHIPDGM
;
817 key_sa_recordxfer(sav
, m
);
820 if (IF_QFULL(&ip6intrq
)) {
821 ipsec6stat
.in_inval
++;
824 IF_ENQUEUE(&ip6intrq
, m
);
826 schednetisr(NETISR_IPV6
); /*can be skipped but to make sure*/
832 * We do deep-copy since KAME requires that
833 * the packet is placed in a single mbuf.
839 * Copy the value of the next header field of AH to the
840 * next header field of the previous header.
841 * This is necessary because AH will be stripped off below.
843 prvnxtp
= ip6_get_prevhdr(m
, off
); /* XXX */
846 if (sav
->flags
& SADB_X_EXT_OLD
) {
848 stripsiz
= sizeof(struct ah
) + siz1
;
851 stripsiz
= sizeof(struct newah
) + siz1
;
854 ip6
= mtod(m
, struct ip6_hdr
*);
855 #ifndef PULLDOWN_TEST
856 ovbcopy((caddr_t
)ip6
, ((caddr_t
)ip6
) + stripsiz
, off
);
857 m
->m_data
+= stripsiz
;
858 m
->m_len
-= stripsiz
;
859 m
->m_pkthdr
.len
-= stripsiz
;
862 * even in m_pulldown case, we need to strip off AH so that
863 * we can compute checksum for multiple AH correctly.
865 if (m
->m_len
>= stripsiz
+ off
) {
866 ovbcopy((caddr_t
)ip6
, ((caddr_t
)ip6
) + stripsiz
, off
);
867 m
->m_data
+= stripsiz
;
868 m
->m_len
-= stripsiz
;
869 m
->m_pkthdr
.len
-= stripsiz
;
872 * this comes with no copy if the boundary is on
877 n
= m_split(m
, off
, M_DONTWAIT
);
879 /* m is retained by m_split */
884 /* m_cat does not update m_pkthdr.len */
885 m
->m_pkthdr
.len
+= n
->m_pkthdr
.len
;
888 ip6
= mtod(m
, struct ip6_hdr
*);
890 ip6
->ip6_plen
= htons(ntohs(ip6
->ip6_plen
) - stripsiz
);
892 key_sa_recordxfer(sav
, m
);
899 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
900 printf("DP ah6_input call free SA:%p\n", sav
));
903 ipsec6stat
.in_success
++;
908 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
909 printf("DP ah6_input call free SA:%p\n", sav
));