]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/ah_input.c
1 /* $FreeBSD: src/sys/netinet6/ah_input.c,v 1.1.2.6 2002/04/28 05:40:26 suz Exp $ */
2 /* $KAME: ah_input.c,v 1.67 2002/01/07 11:39:56 kjc 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.
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
41 #include <sys/domain.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/errno.h>
46 #include <sys/kernel.h>
47 #include <sys/syslog.h>
50 #include <net/route.h>
51 #include <kern/cpu_number.h>
52 #include <kern/locks.h>
54 #include <netinet/in.h>
55 #include <netinet/in_systm.h>
56 #include <netinet/in_var.h>
57 #include <netinet/ip.h>
58 #include <netinet/ip_var.h>
59 #include <netinet/ip_ecn.h>
60 #include <netinet/in_pcb.h>
62 #include <netinet6/ip6_ecn.h>
66 #include <netinet/ip6.h>
67 #include <netinet6/ip6_var.h>
68 #include <netinet6/in6_pcb.h>
69 #include <netinet/icmp6.h>
70 #include <netinet6/ip6protosw.h>
73 #include <netinet6/ipsec.h>
75 #include <netinet6/ipsec6.h>
77 #include <netinet6/ah.h>
79 #include <netinet6/ah6.h>
81 #include <netkey/key.h>
82 #include <netkey/keydb.h>
84 #include <netkey/key_debug.h>
86 #define KEYDEBUG(lev,arg)
90 #include <net/net_osdep.h>
94 extern lck_mtx_t
*sadb_mutex
;
96 extern struct protosw inetsw
[];
99 ah4_input(struct mbuf
*m
, int off
)
104 const struct ah_algorithm
*algo
;
108 struct secasvar
*sav
= NULL
;
114 lck_mtx_lock(sadb_mutex
);
116 #ifndef PULLDOWN_TEST
117 if (m
->m_len
< off
+ sizeof(struct newah
)) {
118 m
= m_pullup(m
, off
+ sizeof(struct newah
));
120 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup;"
121 "dropping the packet for simplicity\n"));
122 ipsecstat
.in_inval
++;
127 ip
= mtod(m
, struct ip
*);
128 ah
= (struct ah
*)(((caddr_t
)ip
) + off
);
130 ip
= mtod(m
, struct ip
*);
131 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
, sizeof(struct newah
));
133 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup;"
134 "dropping the packet for simplicity\n"));
135 ipsecstat
.in_inval
++;
141 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2;
143 hlen
= ip
->ip_hl
<< 2;
146 /* find the sassoc. */
149 if ((sav
= key_allocsa(AF_INET
,
150 (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
,
151 IPPROTO_AH
, spi
)) == 0) {
152 ipseclog((LOG_WARNING
,
153 "IPv4 AH input: no key association found for spi %u\n",
154 (u_int32_t
)ntohl(spi
)));
158 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
159 printf("DP ah4_input called to allocate SA:%p\n", sav
));
160 if (sav
->state
!= SADB_SASTATE_MATURE
161 && sav
->state
!= SADB_SASTATE_DYING
) {
163 "IPv4 AH input: non-mature/dying SA found for spi %u\n",
164 (u_int32_t
)ntohl(spi
)));
165 ipsecstat
.in_badspi
++;
169 algo
= ah_algorithm_lookup(sav
->alg_auth
);
171 ipseclog((LOG_DEBUG
, "IPv4 AH input: "
172 "unsupported authentication algorithm for spi %u\n",
173 (u_int32_t
)ntohl(spi
)));
174 ipsecstat
.in_badspi
++;
178 siz
= (*algo
->sumsiz
)(sav
);
179 siz1
= ((siz
+ 3) & ~(4 - 1));
182 * sanity checks for header, 1.
187 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
190 * Here, we do not do "siz1 == siz". This is because the way
191 * RFC240[34] section 2 is written. They do not require truncation
193 * For example, Microsoft IPsec stack attaches 160 bits of
194 * authentication data for both hmac-md5 and hmac-sha1. For hmac-sha1,
195 * 32 bits of padding is attached.
197 * There are two downsides to this specification.
198 * They have no real harm, however, they leave us fuzzy feeling.
199 * - if we attach more than 96 bits of authentication data onto AH,
200 * we will never notice about possible modification by rogue
201 * intermediate nodes.
202 * Since extra bits in AH checksum is never used, this constitutes
203 * no real issue, however, it is wacky.
204 * - even if the peer attaches big authentication data, we will never
205 * notice the difference, since longer authentication data will just
208 * We may need some clarification in the spec.
211 ipseclog((LOG_NOTICE
, "sum length too short in IPv4 AH input "
212 "(%lu, should be at least %lu): %s\n",
213 (u_long
)siz1
, (u_long
)siz
,
214 ipsec4_logpacketstr(ip
, spi
)));
215 ipsecstat
.in_inval
++;
218 if ((ah
->ah_len
<< 2) - sizoff
!= siz1
) {
219 ipseclog((LOG_NOTICE
, "sum length mismatch in IPv4 AH input "
220 "(%d should be %lu): %s\n",
221 (ah
->ah_len
<< 2) - sizoff
, (u_long
)siz1
,
222 ipsec4_logpacketstr(ip
, spi
)));
223 ipsecstat
.in_inval
++;
227 #ifndef PULLDOWN_TEST
228 if (m
->m_len
< off
+ sizeof(struct ah
) + sizoff
+ siz1
) {
229 m
= m_pullup(m
, off
+ sizeof(struct ah
) + sizoff
+ siz1
);
231 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup\n"));
232 ipsecstat
.in_inval
++;
236 ip
= mtod(m
, struct ip
*);
237 ah
= (struct ah
*)(((caddr_t
)ip
) + off
);
240 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
,
241 sizeof(struct ah
) + sizoff
+ siz1
);
243 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup\n"));
244 ipsecstat
.in_inval
++;
251 * check for sequence number.
253 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
254 if (ipsec_chkreplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
))
257 ipsecstat
.in_ahreplay
++;
258 ipseclog((LOG_WARNING
,
259 "replay packet in IPv4 AH input: %s %s\n",
260 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
266 * alright, it seems sane. now we are going to check the
267 * cryptographic checksum.
269 cksum
= _MALLOC(siz1
, M_TEMP
, M_NOWAIT
);
271 ipseclog((LOG_DEBUG
, "IPv4 AH input: "
272 "couldn't alloc temporary region for cksum\n"));
273 ipsecstat
.in_inval
++;
278 * some of IP header fields are flipped to the host endian.
279 * convert them back to network endian. VERY stupid.
281 ip
->ip_len
= htons(ip
->ip_len
+ hlen
);
282 ip
->ip_off
= htons(ip
->ip_off
);
283 if (ah4_calccksum(m
, (caddr_t
)cksum
, siz1
, algo
, sav
)) {
285 ipsecstat
.in_inval
++;
288 ipsecstat
.in_ahhist
[sav
->alg_auth
]++;
292 ip
->ip_len
= ntohs(ip
->ip_len
) - hlen
;
293 ip
->ip_off
= ntohs(ip
->ip_off
);
296 caddr_t sumpos
= NULL
;
298 if (sav
->flags
& SADB_X_EXT_OLD
) {
300 sumpos
= (caddr_t
)(ah
+ 1);
303 sumpos
= (caddr_t
)(((struct newah
*)ah
) + 1);
306 if (bcmp(sumpos
, cksum
, siz
) != 0) {
307 ipseclog((LOG_WARNING
,
308 "checksum mismatch in IPv4 AH input: %s %s\n",
309 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
311 ipsecstat
.in_ahauthfail
++;
318 m
->m_flags
|= M_AUTHIPHDR
;
319 m
->m_flags
|= M_AUTHIPDGM
;
323 * looks okey, but we need more sanity check.
324 * XXX should elaborate.
326 if (ah
->ah_nxt
== IPPROTO_IPIP
|| ah
->ah_nxt
== IPPROTO_IP
) {
330 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
332 if (m
->m_len
< off
+ sizeof(struct ah
) + sizoff
+ siz1
+ hlen
) {
333 m
= m_pullup(m
, off
+ sizeof(struct ah
)
334 + sizoff
+ siz1
+ hlen
);
337 "IPv4 AH input: can't pullup\n"));
338 ipsecstat
.in_inval
++;
343 nip
= (struct ip
*)((u_char
*)(ah
+ 1) + sizoff
+ siz1
);
344 if (nip
->ip_src
.s_addr
!= ip
->ip_src
.s_addr
345 || nip
->ip_dst
.s_addr
!= ip
->ip_dst
.s_addr
) {
346 m
->m_flags
&= ~M_AUTHIPHDR
;
347 m
->m_flags
&= ~M_AUTHIPDGM
;
351 else if (ah
->ah_nxt
== IPPROTO_IPV6
) {
352 m
->m_flags
&= ~M_AUTHIPHDR
;
353 m
->m_flags
&= ~M_AUTHIPDGM
;
358 if (m
->m_flags
& M_AUTHIPHDR
359 && m
->m_flags
& M_AUTHIPDGM
) {
362 "IPv4 AH input: authentication succeess\n"));
364 ipsecstat
.in_ahauthsucc
++;
366 ipseclog((LOG_WARNING
,
367 "authentication failed in IPv4 AH input: %s %s\n",
368 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
369 ipsecstat
.in_ahauthfail
++;
374 * update sequence number.
376 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
377 if (ipsec_updatereplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
)) {
378 ipsecstat
.in_ahreplay
++;
383 /* was it transmitted over the IPsec tunnel SA? */
384 if (sav
->flags
& SADB_X_EXT_OLD
) {
386 stripsiz
= sizeof(struct ah
) + siz1
;
389 stripsiz
= sizeof(struct newah
) + siz1
;
391 if (ipsec4_tunnel_validate(m
, off
+ stripsiz
, nxt
, sav
)) {
393 * strip off all the headers that precedes AH.
394 * IP xx AH IP' payload -> IP' payload
396 * XXX more sanity checks
397 * XXX relationship with gif?
402 m_adj(m
, off
+ stripsiz
);
403 if (m
->m_len
< sizeof(*ip
)) {
404 m
= m_pullup(m
, sizeof(*ip
));
406 ipsecstat
.in_inval
++;
410 ip
= mtod(m
, struct ip
*);
411 /* ECN consideration. */
412 ip_ecn_egress(ip4_ipsec_ecn
, &tos
, &ip
->ip_tos
);
413 if (!key_checktunnelsanity(sav
, AF_INET
,
414 (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
)) {
415 ipseclog((LOG_NOTICE
, "ipsec tunnel address mismatch "
416 "in IPv4 AH input: %s %s\n",
417 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
418 ipsecstat
.in_inval
++;
424 * Should the inner packet be considered authentic?
425 * My current answer is: NO.
427 * host1 -- gw1 === gw2 -- host2
428 * In this case, gw2 can trust the authenticity of the
429 * outer packet, but NOT inner. Packet may be altered
430 * between host1 and gw1.
432 * host1 -- gw1 === host2
433 * This case falls into the same scenario as above.
436 * This case is the only case when we may be able to leave
437 * M_AUTHIPHDR and M_AUTHIPDGM set.
438 * However, if host1 is wrongly configured, and allows
439 * attacker to inject some packet with src=host1 and
440 * dst=host2, you are in risk.
442 m
->m_flags
&= ~M_AUTHIPHDR
;
443 m
->m_flags
&= ~M_AUTHIPDGM
;
446 key_sa_recordxfer(sav
, m
);
447 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0 ||
448 ipsec_addhist(m
, IPPROTO_IPV4
, 0) != 0) {
449 ipsecstat
.in_nomem
++;
452 lck_mtx_unlock(sadb_mutex
);
453 proto_input(PF_INET
, m
);
454 lck_mtx_lock(sadb_mutex
);
461 ip
= mtod(m
, struct ip
*);
462 #ifndef PULLDOWN_TEST
464 * We do deep-copy since KAME requires that
465 * the packet is placed in a single external mbuf.
467 ovbcopy((caddr_t
)ip
, (caddr_t
)(((u_char
*)ip
) + stripsiz
), off
);
468 m
->m_data
+= stripsiz
;
469 m
->m_len
-= stripsiz
;
470 m
->m_pkthdr
.len
-= stripsiz
;
473 * even in m_pulldown case, we need to strip off AH so that
474 * we can compute checksum for multiple AH correctly.
476 if (m
->m_len
>= stripsiz
+ off
) {
477 ovbcopy((caddr_t
)ip
, ((caddr_t
)ip
) + stripsiz
, off
);
478 m
->m_data
+= stripsiz
;
479 m
->m_len
-= stripsiz
;
480 m
->m_pkthdr
.len
-= stripsiz
;
483 * this comes with no copy if the boundary is on
488 n
= m_split(m
, off
, M_DONTWAIT
);
490 /* m is retained by m_split */
494 /* m_cat does not update m_pkthdr.len */
495 m
->m_pkthdr
.len
+= n
->m_pkthdr
.len
;
500 if (m
->m_len
< sizeof(*ip
)) {
501 m
= m_pullup(m
, sizeof(*ip
));
503 ipsecstat
.in_inval
++;
507 ip
= mtod(m
, struct ip
*);
509 ip
->ip_len
= ip
->ip_len
- stripsiz
;
511 ip
->ip_len
= htons(ntohs(ip
->ip_len
) - stripsiz
);
514 /* forget about IP hdr checksum, the check has already been passed */
516 key_sa_recordxfer(sav
, m
);
517 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0) {
518 ipsecstat
.in_nomem
++;
522 if (nxt
!= IPPROTO_DONE
) {
523 if ((ip_protox
[nxt
]->pr_flags
& PR_LASTHDR
) != 0 &&
524 ipsec4_in_reject(m
, NULL
)) {
525 ipsecstat
.in_polvio
++;
528 lck_mtx_unlock(sadb_mutex
);
529 ip_proto_dispatch_in(m
, off
, nxt
, 0);
530 lck_mtx_lock(sadb_mutex
);
537 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
538 printf("DP ah4_input call free SA:%p\n", sav
));
541 ipsecstat
.in_success
++;
542 lck_mtx_unlock(sadb_mutex
);
547 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
548 printf("DP ah4_input call free SA:%p\n", sav
));
551 lck_mtx_unlock(sadb_mutex
);
564 struct mbuf
*m
= *mp
;
569 const struct ah_algorithm
*algo
;
573 struct secasvar
*sav
= NULL
;
578 lck_mtx_lock(sadb_mutex
);
580 #ifndef PULLDOWN_TEST
581 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
), {lck_mtx_unlock(sadb_mutex
);return IPPROTO_DONE
;});
582 ah
= (struct ah
*)(mtod(m
, caddr_t
) + off
);
584 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
, sizeof(struct newah
));
586 ipseclog((LOG_DEBUG
, "IPv6 AH input: can't pullup\n"));
587 ipsec6stat
.in_inval
++;
588 lck_mtx_unlock(sadb_mutex
);
592 ip6
= mtod(m
, struct ip6_hdr
*);
595 /* find the sassoc. */
598 if (ntohs(ip6
->ip6_plen
) == 0) {
599 ipseclog((LOG_ERR
, "IPv6 AH input: "
600 "AH with IPv6 jumbogram is not supported.\n"));
601 ipsec6stat
.in_inval
++;
605 if ((sav
= key_allocsa(AF_INET6
,
606 (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
,
607 IPPROTO_AH
, spi
)) == 0) {
608 ipseclog((LOG_WARNING
,
609 "IPv6 AH input: no key association found for spi %u\n",
610 (u_int32_t
)ntohl(spi
)));
611 ipsec6stat
.in_nosa
++;
614 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
615 printf("DP ah6_input called to allocate SA:%p\n", sav
));
616 if (sav
->state
!= SADB_SASTATE_MATURE
617 && sav
->state
!= SADB_SASTATE_DYING
) {
619 "IPv6 AH input: non-mature/dying SA found for spi %u; ",
620 (u_int32_t
)ntohl(spi
)));
621 ipsec6stat
.in_badspi
++;
625 algo
= ah_algorithm_lookup(sav
->alg_auth
);
627 ipseclog((LOG_DEBUG
, "IPv6 AH input: "
628 "unsupported authentication algorithm for spi %u\n",
629 (u_int32_t
)ntohl(spi
)));
630 ipsec6stat
.in_badspi
++;
634 siz
= (*algo
->sumsiz
)(sav
);
635 siz1
= ((siz
+ 3) & ~(4 - 1));
638 * sanity checks for header, 1.
643 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
646 * Here, we do not do "siz1 == siz". See ah4_input() for complete
650 ipseclog((LOG_NOTICE
, "sum length too short in IPv6 AH input "
651 "(%lu, should be at least %lu): %s\n",
652 (u_long
)siz1
, (u_long
)siz
,
653 ipsec6_logpacketstr(ip6
, spi
)));
654 ipsec6stat
.in_inval
++;
657 if ((ah
->ah_len
<< 2) - sizoff
!= siz1
) {
658 ipseclog((LOG_NOTICE
, "sum length mismatch in IPv6 AH input "
659 "(%d should be %lu): %s\n",
660 (ah
->ah_len
<< 2) - sizoff
, (u_long
)siz1
,
661 ipsec6_logpacketstr(ip6
, spi
)));
662 ipsec6stat
.in_inval
++;
665 #ifndef PULLDOWN_TEST
666 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
) + sizoff
+ siz1
,
667 {lck_mtx_unlock(sadb_mutex
);return IPPROTO_DONE
;});
669 IP6_EXTHDR_GET(ah
, struct ah
*, m
, off
,
670 sizeof(struct ah
) + sizoff
+ siz1
);
672 ipseclog((LOG_NOTICE
, "couldn't pullup gather IPv6 AH checksum part"));
673 ipsec6stat
.in_inval
++;
681 * check for sequence number.
683 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
684 if (ipsec_chkreplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
))
687 ipsec6stat
.in_ahreplay
++;
688 ipseclog((LOG_WARNING
,
689 "replay packet in IPv6 AH input: %s %s\n",
690 ipsec6_logpacketstr(ip6
, spi
),
691 ipsec_logsastr(sav
)));
697 * alright, it seems sane. now we are going to check the
698 * cryptographic checksum.
700 cksum
= _MALLOC(siz1
, M_TEMP
, M_NOWAIT
);
702 ipseclog((LOG_DEBUG
, "IPv6 AH input: "
703 "couldn't alloc temporary region for cksum\n"));
704 ipsec6stat
.in_inval
++;
708 if (ah6_calccksum(m
, (caddr_t
)cksum
, siz1
, algo
, sav
)) {
710 ipsec6stat
.in_inval
++;
713 ipsec6stat
.in_ahhist
[sav
->alg_auth
]++;
716 caddr_t sumpos
= NULL
;
718 if (sav
->flags
& SADB_X_EXT_OLD
) {
720 sumpos
= (caddr_t
)(ah
+ 1);
723 sumpos
= (caddr_t
)(((struct newah
*)ah
) + 1);
726 if (bcmp(sumpos
, cksum
, siz
) != 0) {
727 ipseclog((LOG_WARNING
,
728 "checksum mismatch in IPv6 AH input: %s %s\n",
729 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
731 ipsec6stat
.in_ahauthfail
++;
738 m
->m_flags
|= M_AUTHIPHDR
;
739 m
->m_flags
|= M_AUTHIPDGM
;
743 * looks okey, but we need more sanity check.
744 * XXX should elaborate.
746 if (ah
->ah_nxt
== IPPROTO_IPV6
) {
747 struct ip6_hdr
*nip6
;
750 sizoff
= (sav
->flags
& SADB_X_EXT_OLD
) ? 0 : 4;
752 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
) + sizoff
+ siz1
753 + sizeof(struct ip6_hdr
),
754 {lck_mtx_unlock(sadb_mutex
);return IPPROTO_DONE
;});
756 nip6
= (struct ip6_hdr
*)((u_char
*)(ah
+ 1) + sizoff
+ siz1
);
757 if (!IN6_ARE_ADDR_EQUAL(&nip6
->ip6_src
, &ip6
->ip6_src
)
758 || !IN6_ARE_ADDR_EQUAL(&nip6
->ip6_dst
, &ip6
->ip6_dst
)) {
759 m
->m_flags
&= ~M_AUTHIPHDR
;
760 m
->m_flags
&= ~M_AUTHIPDGM
;
762 } else if (ah
->ah_nxt
== IPPROTO_IPIP
) {
763 m
->m_flags
&= ~M_AUTHIPHDR
;
764 m
->m_flags
&= ~M_AUTHIPDGM
;
765 } else if (ah
->ah_nxt
== IPPROTO_IP
) {
766 m
->m_flags
&= ~M_AUTHIPHDR
;
767 m
->m_flags
&= ~M_AUTHIPDGM
;
771 if (m
->m_flags
& M_AUTHIPHDR
772 && m
->m_flags
& M_AUTHIPDGM
) {
775 "IPv6 AH input: authentication succeess\n"));
777 ipsec6stat
.in_ahauthsucc
++;
779 ipseclog((LOG_WARNING
,
780 "authentication failed in IPv6 AH input: %s %s\n",
781 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
782 ipsec6stat
.in_ahauthfail
++;
787 * update sequence number.
789 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
790 if (ipsec_updatereplay(ntohl(((struct newah
*)ah
)->ah_seq
), sav
)) {
791 ipsec6stat
.in_ahreplay
++;
796 /* was it transmitted over the IPsec tunnel SA? */
797 if (sav
->flags
& SADB_X_EXT_OLD
) {
799 stripsiz
= sizeof(struct ah
) + siz1
;
802 stripsiz
= sizeof(struct newah
) + siz1
;
804 if (ipsec6_tunnel_validate(m
, off
+ stripsiz
, nxt
, sav
)) {
806 * strip off all the headers that precedes AH.
807 * IP6 xx AH IP6' payload -> IP6' payload
809 * XXX more sanity checks
810 * XXX relationship with gif?
812 u_int32_t flowinfo
; /*net endian*/
814 flowinfo
= ip6
->ip6_flow
;
815 m_adj(m
, off
+ stripsiz
);
816 if (m
->m_len
< sizeof(*ip6
)) {
818 * m_pullup is prohibited in KAME IPv6 input processing
819 * but there's no other way!
821 m
= m_pullup(m
, sizeof(*ip6
));
823 ipsec6stat
.in_inval
++;
827 ip6
= mtod(m
, struct ip6_hdr
*);
828 /* ECN consideration. */
829 ip6_ecn_egress(ip6_ipsec_ecn
, &flowinfo
, &ip6
->ip6_flow
);
830 if (!key_checktunnelsanity(sav
, AF_INET6
,
831 (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
)) {
832 ipseclog((LOG_NOTICE
, "ipsec tunnel address mismatch "
833 "in IPv6 AH input: %s %s\n",
834 ipsec6_logpacketstr(ip6
, spi
),
835 ipsec_logsastr(sav
)));
836 ipsec6stat
.in_inval
++;
842 * should the inner packet be considered authentic?
843 * see comment in ah4_input().
845 m
->m_flags
&= ~M_AUTHIPHDR
;
846 m
->m_flags
&= ~M_AUTHIPDGM
;
849 key_sa_recordxfer(sav
, m
);
850 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0 ||
851 ipsec_addhist(m
, IPPROTO_IPV6
, 0) != 0) {
852 ipsec6stat
.in_nomem
++;
855 lck_mtx_unlock(sadb_mutex
);
856 proto_input(PF_INET6
, m
);
857 lck_mtx_lock(sadb_mutex
);
866 * Copy the value of the next header field of AH to the
867 * next header field of the previous header.
868 * This is necessary because AH will be stripped off below.
870 prvnxtp
= ip6_get_prevhdr(m
, off
); /* XXX */
873 ip6
= mtod(m
, struct ip6_hdr
*);
874 #ifndef PULLDOWN_TEST
876 * We do deep-copy since KAME requires that
877 * the packet is placed in a single mbuf.
879 ovbcopy((caddr_t
)ip6
, ((caddr_t
)ip6
) + stripsiz
, off
);
880 m
->m_data
+= stripsiz
;
881 m
->m_len
-= stripsiz
;
882 m
->m_pkthdr
.len
-= stripsiz
;
885 * even in m_pulldown case, we need to strip off AH so that
886 * we can compute checksum for multiple AH correctly.
888 if (m
->m_len
>= stripsiz
+ off
) {
889 ovbcopy((caddr_t
)ip6
, ((caddr_t
)ip6
) + stripsiz
, off
);
890 m
->m_data
+= stripsiz
;
891 m
->m_len
-= stripsiz
;
892 m
->m_pkthdr
.len
-= stripsiz
;
895 * this comes with no copy if the boundary is on
900 n
= m_split(m
, off
, M_DONTWAIT
);
902 /* m is retained by m_split */
906 /* m_cat does not update m_pkthdr.len */
907 m
->m_pkthdr
.len
+= n
->m_pkthdr
.len
;
911 ip6
= mtod(m
, struct ip6_hdr
*);
913 ip6
->ip6_plen
= htons(ntohs(ip6
->ip6_plen
) - stripsiz
);
915 key_sa_recordxfer(sav
, m
);
916 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0) {
917 ipsec6stat
.in_nomem
++;
926 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
927 printf("DP ah6_input call free SA:%p\n", sav
));
930 ipsec6stat
.in_success
++;
931 lck_mtx_unlock(sadb_mutex
);
936 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
937 printf("DP ah6_input call free SA:%p\n", sav
));
940 lck_mtx_unlock(sadb_mutex
);
947 ah6_ctlinput(cmd
, sa
, d
)
952 const struct newah
*ahp
;
954 struct secasvar
*sav
;
957 struct ip6ctlparam
*ip6cp
= NULL
;
959 struct sockaddr_in6
*sa6_src
, *sa6_dst
;
961 if (sa
->sa_family
!= AF_INET6
||
962 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
964 if ((unsigned)cmd
>= PRC_NCMDS
)
967 /* if the parameter is from icmp6, decode it. */
969 ip6cp
= (struct ip6ctlparam
*)d
;
971 ip6
= ip6cp
->ip6c_ip6
;
972 off
= ip6cp
->ip6c_off
;
980 * XXX: We assume that when ip6 is non NULL,
981 * M and OFF are valid.
984 /* check if we can safely examine src and dst ports */
985 if (m
->m_pkthdr
.len
< off
+ sizeof(ah
))
988 if (m
->m_len
< off
+ sizeof(ah
)) {
990 * this should be rare case,
991 * so we compromise on this copy...
993 m_copydata(m
, off
, sizeof(ah
), (caddr_t
)&ah
);
996 ahp
= (struct newah
*)(mtod(m
, caddr_t
) + off
);
998 if (cmd
== PRC_MSGSIZE
) {
1002 * Check to see if we have a valid SA corresponding to
1003 * the address in the ICMP message payload.
1005 sa6_src
= ip6cp
->ip6c_src
;
1006 sa6_dst
= (struct sockaddr_in6
*)sa
;
1007 lck_mtx_lock(sadb_mutex
);
1008 sav
= key_allocsa(AF_INET6
,
1009 (caddr_t
)&sa6_src
->sin6_addr
,
1010 (caddr_t
)&sa6_dst
->sin6_addr
,
1011 IPPROTO_AH
, ahp
->ah_spi
);
1013 if (sav
->state
== SADB_SASTATE_MATURE
||
1014 sav
->state
== SADB_SASTATE_DYING
)
1018 lck_mtx_unlock(sadb_mutex
);
1020 /* XXX Further validation? */
1023 * Depending on the value of "valid" and routing table
1024 * size (mtudisc_{hi,lo}wat), we will:
1025 * - recalcurate the new MTU and create the
1026 * corresponding routing entry, or
1027 * - ignore the MTU change notification.
1029 icmp6_mtudisc_update((struct ip6ctlparam
*)d
, valid
);
1032 /* we normally notify single pcb here */
1034 /* we normally notify any pcb here */