1 /* $NetBSD: ipsec_input.c,v 1.22 2009/03/18 17:06:52 cegger Exp $ */
2 /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $ */
3 /* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */
6 * The authors of this code are John Ioannidis (ji@tla.org),
7 * Angelos D. Keromytis (kermit@csd.uch.gr) and
8 * Niels Provos (provos@physnet.uni-hamburg.de).
10 * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
13 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
14 * by Angelos D. Keromytis.
16 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
19 * Additional features in 1999 by Angelos D. Keromytis.
21 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
22 * Angelos D. Keromytis and Niels Provos.
23 * Copyright (c) 2001, Angelos D. Keromytis.
25 * Permission to use, copy, and modify this software with or without fee
26 * is hereby granted, provided that this entire notice is included in
27 * all copies of any software which is or includes a copy or
28 * modification of this software.
29 * You may use this code under the GNU public license if you so wish. Please
30 * contribute changes back to the authors under this freer than GPL license
31 * so that we may further the use of strong encryption without limitations to
34 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
35 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
36 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
37 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.22 2009/03/18 17:06:52 cegger Exp $");
45 * IPsec input processing.
50 #include "opt_inet6.h"
52 #include "opt_ipsec.h"
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/malloc.h>
58 #include <sys/domain.h>
59 #include <sys/protosw.h>
60 #include <sys/socket.h>
61 #include <sys/errno.h>
62 #include <sys/syslog.h>
65 #include <net/route.h>
66 #include <net/netisr.h>
68 #include <netinet/in.h>
69 #include <netinet/in_systm.h>
70 #include <netinet/ip.h>
71 #include <netinet/ip_var.h>
72 #include <netinet/in_var.h>
74 #include <netinet/ip6.h>
76 #include <netinet6/ip6_var.h>
77 #include <netinet6/ip6_private.h>
79 #include <netinet/in_pcb.h>
81 #include <netinet/icmp6.h>
84 #include <netipsec/ipsec.h>
85 #include <netipsec/ipsec_private.h>
87 #include <netipsec/ipsec6.h>
89 #include <netipsec/ah_var.h>
90 #include <netipsec/esp.h>
91 #include <netipsec/esp_var.h>
92 #include <netipsec/ipcomp_var.h>
94 #include <netipsec/key.h>
95 #include <netipsec/keydb.h>
97 #include <netipsec/xform.h>
98 #include <netinet6/ip6protosw.h>
100 #include <netipsec/ipsec_osdep.h>
102 #include <machine/stdarg.h>
104 #include <net/net_osdep.h>
106 #define IPSEC_ISTAT(p, x, y, z) \
119 } while (/*CONSTCOND*/0)
122 * ipsec_common_input gets called when an IPsec-protected packet
123 * is received by IPv4 or IPv6. It's job is to find the right SA
124 # and call the appropriate transform. The transform callback
125 * takes care of further processing (like ingress filtering).
128 ipsec_common_input(struct mbuf
*m
, int skip
, int protoff
, int af
, int sproto
)
130 union sockaddr_union dst_address
;
131 struct secasvar
*sav
;
137 struct m_tag
* tag
= NULL
;
140 IPSEC_ISTAT(sproto
, ESP_STAT_INPUT
, AH_STAT_INPUT
,
143 IPSEC_ASSERT(m
!= NULL
, ("ipsec_common_input: null packet"));
145 if ((sproto
== IPPROTO_ESP
&& !esp_enable
) ||
146 (sproto
== IPPROTO_AH
&& !ah_enable
) ||
147 (sproto
== IPPROTO_IPCOMP
&& !ipcomp_enable
)) {
149 IPSEC_ISTAT(sproto
, ESP_STAT_PDROPS
, AH_STAT_PDROPS
,
154 if (m
->m_pkthdr
.len
- skip
< 2 * sizeof (u_int32_t
)) {
156 IPSEC_ISTAT(sproto
, ESP_STAT_HDROPS
, AH_STAT_HDROPS
,
158 DPRINTF(("ipsec_common_input: packet too small\n"));
162 /* Retrieve the SPI from the relevant IPsec header */
163 if (sproto
== IPPROTO_ESP
)
164 m_copydata(m
, skip
, sizeof(u_int32_t
), &spi
);
165 else if (sproto
== IPPROTO_AH
)
166 m_copydata(m
, skip
+ sizeof(u_int32_t
), sizeof(u_int32_t
), &spi
);
167 else if (sproto
== IPPROTO_IPCOMP
) {
169 m_copydata(m
, skip
+ sizeof(u_int16_t
), sizeof(u_int16_t
), &cpi
);
170 spi
= ntohl(htons(cpi
));
172 panic("ipsec_common_input called with bad protocol number :"
178 /* find the source port for NAT-T */
179 if ((tag
= m_tag_find(m
, PACKET_TAG_IPSEC_NAT_T_PORTS
, NULL
))) {
180 sport
= ((u_int16_t
*)(tag
+ 1))[0];
181 dport
= ((u_int16_t
*)(tag
+ 1))[1];
186 * Find the SA and (indirectly) call the appropriate
187 * kernel crypto routine. The resulting mbuf chain is a valid
188 * IP packet ready to go through input processing.
190 memset(&dst_address
, 0, sizeof (dst_address
));
191 dst_address
.sa
.sa_family
= af
;
195 dst_address
.sin
.sin_len
= sizeof(struct sockaddr_in
);
196 m_copydata(m
, offsetof(struct ip
, ip_dst
),
197 sizeof(struct in_addr
),
198 &dst_address
.sin
.sin_addr
);
203 dst_address
.sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
204 m_copydata(m
, offsetof(struct ip6_hdr
, ip6_dst
),
205 sizeof(struct in6_addr
),
206 &dst_address
.sin6
.sin6_addr
);
210 DPRINTF(("ipsec_common_input: unsupported protocol "
213 IPSEC_ISTAT(sproto
, ESP_STAT_NOPF
, AH_STAT_NOPF
,
220 /* NB: only pass dst since key_allocsa follows RFC2401 */
221 sav
= KEY_ALLOCSA(&dst_address
, sproto
, spi
, sport
, dport
);
223 DPRINTF(("ipsec_common_input: no key association found for"
224 " SA %s/%08lx/%u/%u\n",
225 ipsec_address(&dst_address
),
226 (u_long
) ntohl(spi
), sproto
, ntohs(dport
)));
227 IPSEC_ISTAT(sproto
, ESP_STAT_NOTDB
, AH_STAT_NOTDB
,
234 if (sav
->tdb_xform
== NULL
) {
235 DPRINTF(("ipsec_common_input: attempted to use uninitialized"
237 ipsec_address(&dst_address
),
238 (u_long
) ntohl(spi
), sproto
));
239 IPSEC_ISTAT(sproto
, ESP_STAT_NOXFORM
, AH_STAT_NOXFORM
,
240 IPCOMP_STAT_NOXFORM
);
248 * Call appropriate transform and return -- callback takes care of
251 error
= (*sav
->tdb_xform
->xf_input
)(m
, sav
, skip
, protoff
);
259 * Common input handler for IPv4 AH, ESP, and IPCOMP.
262 ipsec4_common_input(struct mbuf
*m
, ...)
268 off
= va_arg(ap
, int);
269 nxt
= va_arg(ap
, int);
272 (void) ipsec_common_input(m
, off
, offsetof(struct ip
, ip_p
),
277 * IPsec input callback for INET protocols.
278 * This routine is called as the transform callback.
279 * Takes care of filtering and other sanity checks on
280 * the processed packet.
283 ipsec4_common_input_cb(struct mbuf
*m
, struct secasvar
*sav
,
284 int skip
, int protoff
, struct m_tag
*mt
)
286 int prot
, af
, sproto
;
289 struct tdb_ident
*tdbi
;
290 struct secasindex
*saidx
;
293 IPSEC_SPLASSERT_SOFTNET("ipsec4_common_input_cb");
295 IPSEC_ASSERT(m
!= NULL
, ("ipsec4_common_input_cb: null mbuf"));
296 IPSEC_ASSERT(sav
!= NULL
, ("ipsec4_common_input_cb: null SA"));
297 IPSEC_ASSERT(sav
->sah
!= NULL
, ("ipsec4_common_input_cb: null SAH"));
298 saidx
= &sav
->sah
->saidx
;
299 af
= saidx
->dst
.sa
.sa_family
;
300 IPSEC_ASSERT(af
== AF_INET
, ("ipsec4_common_input_cb: unexpected af %u",af
));
301 sproto
= saidx
->proto
;
302 IPSEC_ASSERT(sproto
== IPPROTO_ESP
|| sproto
== IPPROTO_AH
||
303 sproto
== IPPROTO_IPCOMP
,
304 ("ipsec4_common_input_cb: unexpected security protocol %u",
309 DPRINTF(("ipsec4_common_input_cb: null mbuf"));
310 IPSEC_ISTAT(sproto
, ESP_STAT_BADKCR
, AH_STAT_BADKCR
,
317 /* Fix IPv4 header */
318 if (m
->m_len
< skip
&& (m
= m_pullup(m
, skip
)) == NULL
) {
319 DPRINTF(("ipsec4_common_input_cb: processing failed "
321 ipsec_address(&sav
->sah
->saidx
.dst
),
322 (u_long
) ntohl(sav
->spi
)));
323 IPSEC_ISTAT(sproto
, ESP_STAT_HDROPS
, AH_STAT_HDROPS
,
329 ip
= mtod(m
, struct ip
*);
330 ip
->ip_len
= htons(m
->m_pkthdr
.len
);
332 /* On FreeBSD, ip_off and ip_len assumed in host endian. */
333 ip
->ip_off
= htons(ip
->ip_off
);
336 ip
->ip_sum
= in_cksum(m
, ip
->ip_hl
<< 2);
338 ip
= mtod(m
, struct ip
*);
342 /* IP-in-IP encapsulation */
343 if (prot
== IPPROTO_IPIP
) {
346 /* ipn will now contain the inner IPv4 header */
347 m_copydata(m
, ip
->ip_hl
<< 2, sizeof(struct ip
), &ipn
);
350 /* XXX PROXY address isn't recorded in SAH */
352 * Check that the inner source address is the same as
353 * the proxy address, if available.
355 if ((saidx
->proxy
.sa
.sa_family
== AF_INET
&&
356 saidx
->proxy
.sin
.sin_addr
.s_addr
!=
359 saidx
->proxy
.sin
.sin_addr
.s_addr
) ||
360 (saidx
->proxy
.sa
.sa_family
!= AF_INET
&&
361 saidx
->proxy
.sa
.sa_family
!= 0)) {
363 DPRINTF(("ipsec4_common_input_cb: inner "
364 "source address %s doesn't correspond to "
365 "expected proxy source %s, SA %s/%08lx\n",
366 inet_ntoa4(ipn
.ip_src
),
367 ipsp_address(saidx
->proxy
),
368 ipsp_address(saidx
->dst
),
369 (u_long
) ntohl(sav
->spi
)));
371 IPSEC_ISTAT(sproto
, ESP_STAT_PDROPS
,
380 /* IPv6-in-IP encapsulation. */
381 if (prot
== IPPROTO_IPV6
) {
384 /* ip6n will now contain the inner IPv6 header. */
385 m_copydata(m
, ip
->ip_hl
<< 2, sizeof(struct ip6_hdr
), &ip6n
);
389 * Check that the inner source address is the same as
390 * the proxy address, if available.
392 if ((saidx
->proxy
.sa
.sa_family
== AF_INET6
&&
393 !IN6_IS_ADDR_UNSPECIFIED(&saidx
->proxy
.sin6
.sin6_addr
) &&
394 !IN6_ARE_ADDR_EQUAL(&ip6n
.ip6_src
,
395 &saidx
->proxy
.sin6
.sin6_addr
)) ||
396 (saidx
->proxy
.sa
.sa_family
!= AF_INET6
&&
397 saidx
->proxy
.sa
.sa_family
!= 0)) {
399 DPRINTF(("ipsec4_common_input_cb: inner "
400 "source address %s doesn't correspond to "
401 "expected proxy source %s, SA %s/%08lx\n",
402 ip6_sprintf(&ip6n
.ip6_src
),
403 ipsec_address(&saidx
->proxy
),
404 ipsec_address(&saidx
->dst
),
405 (u_long
) ntohl(sav
->spi
)));
407 IPSEC_ISTAT(sproto
, ESP_STAT_PDROPS
,
418 * Record what we've done to the packet (under what SA it was
419 * processed). If we've been passed an mtag, it means the packet
420 * was already processed by an ethernet/crypto combo card and
421 * thus has a tag attached with all the right information, but
422 * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to
423 * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type.
425 if (mt
== NULL
&& sproto
!= IPPROTO_IPCOMP
) {
426 mtag
= m_tag_get(PACKET_TAG_IPSEC_IN_DONE
,
427 sizeof(struct tdb_ident
), M_NOWAIT
);
429 DPRINTF(("ipsec4_common_input_cb: failed to get tag\n"));
430 IPSEC_ISTAT(sproto
, ESP_STAT_HDROPS
,
431 AH_STAT_HDROPS
, IPCOMP_STAT_HDROPS
);
436 tdbi
= (struct tdb_ident
*)(mtag
+ 1);
437 memcpy(&tdbi
->dst
, &saidx
->dst
, saidx
->dst
.sa
.sa_len
);
438 tdbi
->proto
= sproto
;
439 tdbi
->spi
= sav
->spi
;
441 m_tag_prepend(m
, mtag
);
444 mt
->m_tag_id
= PACKET_TAG_IPSEC_IN_DONE
;
445 /* XXX do we need to mark m_flags??? */
448 key_sa_recordxfer(sav
, m
); /* record data transfer */
451 * Re-dispatch via software interrupt.
453 if (!IF_HANDOFF(&ipintrq
, m
, NULL
)) {
454 IPSEC_ISTAT(sproto
, ESP_STAT_QFULL
, AH_STAT_QFULL
,
457 DPRINTF(("ipsec4_common_input_cb: queue full; "
458 "proto %u packet dropped\n", sproto
));
461 schednetisr(NETISR_IP
);
470 /* IPv6 AH wrapper. */
472 ipsec6_common_input(struct mbuf
**mp
, int *offp
, int proto
)
478 if (*offp
< sizeof(struct ip6_hdr
)) {
479 DPRINTF(("ipsec6_common_input: bad offset %u\n", *offp
));
481 } else if (*offp
== sizeof(struct ip6_hdr
)) {
482 protoff
= offsetof(struct ip6_hdr
, ip6_nxt
);
484 /* Chase down the header chain... */
485 protoff
= sizeof(struct ip6_hdr
);
489 m_copydata(*mp
, protoff
, sizeof(ip6e
), &ip6e
);
491 if (ip6e
.ip6e_nxt
== IPPROTO_AH
)
492 l
= (ip6e
.ip6e_len
+ 2) << 2;
494 l
= (ip6e
.ip6e_len
+ 1) << 3;
495 IPSEC_ASSERT(l
> 0, ("ah6_input: l went zero or negative"));
496 } while (protoff
+ l
< *offp
);
498 /* Malformed packet check */
499 if (protoff
+ l
!= *offp
) {
500 DPRINTF(("ipsec6_common_input: bad packet header chain, "
501 "protoff %u, l %u, off %u\n", protoff
, l
, *offp
));
502 IPSEC_ISTAT(proto
, ESP_STAT_HDROPS
,
509 protoff
+= offsetof(struct ip6_ext
, ip6e_nxt
);
511 (void) ipsec_common_input(*mp
, *offp
, protoff
, AF_INET6
, proto
);
516 * NB: ipsec_netbsd.c has a duplicate definition of esp6_ctlinput(),
517 * with slightly ore recent multicast tests. These should be merged.
518 * For now, ifdef accordingly.
522 esp6_ctlinput(int cmd
, struct sockaddr
*sa
, void *d
)
524 if (sa
->sa_family
!= AF_INET6
||
525 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
527 if ((unsigned)cmd
>= PRC_NCMDS
)
530 /* if the parameter is from icmp6, decode it. */
532 struct ip6ctlparam
*ip6cp
= (struct ip6ctlparam
*)d
;
533 struct mbuf
*m
= ip6cp
->ip6c_m
;
534 int off
= ip6cp
->ip6c_off
;
536 struct ip6ctlparam ip6cp1
;
539 * Notify the error to all possible sockets via pfctlinput2.
540 * Since the upper layer information (such as protocol type,
541 * source and destination ports) is embedded in the encrypted
542 * data and might have been cut, we can't directly call
543 * an upper layer ctlinput function. However, the pcbnotify
544 * function will consider source and destination addresses
545 * as well as the flow info value, and may be able to find
546 * some PCB that should be notified.
547 * Although pfctlinput2 will call esp6_ctlinput(), there is
548 * no possibility of an infinite loop of function calls,
549 * because we don't pass the inner IPv6 header.
551 memset(&ip6cp1
, 0, sizeof(ip6cp1
));
552 ip6cp1
.ip6c_src
= ip6cp
->ip6c_src
;
553 pfctlinput2(cmd
, sa
, &ip6cp1
);
556 * Then go to special cases that need ESP header information.
557 * XXX: We assume that when ip6 is non NULL,
558 * M and OFF are valid.
561 if (cmd
== PRC_MSGSIZE
) {
562 struct secasvar
*sav
;
566 /* check header length before using m_copydata */
567 if (m
->m_pkthdr
.len
< off
+ sizeof (struct esp
))
569 m_copydata(m
, off
+ offsetof(struct esp
, esp_spi
),
570 sizeof(u_int32_t
), &spi
);
572 * Check to see if we have a valid SA corresponding to
573 * the address in the ICMP message payload.
575 sav
= KEY_ALLOCSA((union sockaddr_union
*)sa
,
577 valid
= (sav
!= NULL
);
581 /* XXX Further validation? */
584 * Depending on whether the SA is "valid" and
585 * routing table size (mtudisc_{hi,lo}wat), we will:
586 * - recalcurate the new MTU and create the
587 * corresponding routing entry, or
588 * - ignore the MTU change notification.
590 icmp6_mtudisc_update(ip6cp
, valid
);
593 /* we normally notify any pcb here */
596 #endif /* __FreeBSD__ */
598 extern const struct ip6protosw inet6sw
[];
599 extern u_char ip6_protox
[];
602 * IPsec input callback, called by the transform callback. Takes care of
603 * filtering and other sanity checks on the processed packet.
606 ipsec6_common_input_cb(struct mbuf
*m
, struct secasvar
*sav
, int skip
, int protoff
,
609 int prot
, af
, sproto
;
612 struct tdb_ident
*tdbi
;
613 struct secasindex
*saidx
;
618 IPSEC_ASSERT(m
!= NULL
, ("ipsec6_common_input_cb: null mbuf"));
619 IPSEC_ASSERT(sav
!= NULL
, ("ipsec6_common_input_cb: null SA"));
620 IPSEC_ASSERT(sav
->sah
!= NULL
, ("ipsec6_common_input_cb: null SAH"));
621 saidx
= &sav
->sah
->saidx
;
622 af
= saidx
->dst
.sa
.sa_family
;
623 IPSEC_ASSERT(af
== AF_INET6
,
624 ("ipsec6_common_input_cb: unexpected af %u", af
));
625 sproto
= saidx
->proto
;
626 IPSEC_ASSERT(sproto
== IPPROTO_ESP
|| sproto
== IPPROTO_AH
||
627 sproto
== IPPROTO_IPCOMP
,
628 ("ipsec6_common_input_cb: unexpected security protocol %u",
633 DPRINTF(("ipsec6_common_input_cb: null mbuf"));
634 IPSEC_ISTAT(sproto
, ESP_STAT_BADKCR
, AH_STAT_BADKCR
,
640 /* Fix IPv6 header */
641 if (m
->m_len
< sizeof(struct ip6_hdr
) &&
642 (m
= m_pullup(m
, sizeof(struct ip6_hdr
))) == NULL
) {
644 DPRINTF(("ipsec6_common_input_cb: processing failed "
645 "for SA %s/%08lx\n", ipsec_address(&sav
->sah
->saidx
.dst
),
646 (u_long
) ntohl(sav
->spi
)));
648 IPSEC_ISTAT(sproto
, ESP_STAT_HDROPS
, AH_STAT_HDROPS
,
654 ip6
= mtod(m
, struct ip6_hdr
*);
655 ip6
->ip6_plen
= htons(m
->m_pkthdr
.len
- sizeof(struct ip6_hdr
));
658 m_copydata(m
, protoff
, 1, (unsigned char *) &prot
);
661 /* IP-in-IP encapsulation */
662 if (prot
== IPPROTO_IPIP
) {
665 /* ipn will now contain the inner IPv4 header */
666 m_copydata(m
, skip
, sizeof(struct ip
), &ipn
);
670 * Check that the inner source address is the same as
671 * the proxy address, if available.
673 if ((saidx
->proxy
.sa
.sa_family
== AF_INET
&&
674 saidx
->proxy
.sin
.sin_addr
.s_addr
!= INADDR_ANY
&&
675 ipn
.ip_src
.s_addr
!= saidx
->proxy
.sin
.sin_addr
.s_addr
) ||
676 (saidx
->proxy
.sa
.sa_family
!= AF_INET
&&
677 saidx
->proxy
.sa
.sa_family
!= 0)) {
679 DPRINTF(("ipsec6_common_input_cb: inner "
680 "source address %s doesn't correspond to "
681 "expected proxy source %s, SA %s/%08lx\n",
682 inet_ntoa4(ipn
.ip_src
),
683 ipsec_address(&saidx
->proxy
),
684 ipsec_address(&saidx
->dst
),
685 (u_long
) ntohl(sav
->spi
)));
687 IPSEC_ISTAT(sproto
, ESP_STAT_PDROPS
,
688 AH_STAT_PDROPS
, IPCOMP_STAT_PDROPS
);
696 /* IPv6-in-IP encapsulation */
697 if (prot
== IPPROTO_IPV6
) {
700 /* ip6n will now contain the inner IPv6 header. */
701 m_copydata(m
, skip
, sizeof(struct ip6_hdr
), &ip6n
);
705 * Check that the inner source address is the same as
706 * the proxy address, if available.
708 if ((saidx
->proxy
.sa
.sa_family
== AF_INET6
&&
709 !IN6_IS_ADDR_UNSPECIFIED(&saidx
->proxy
.sin6
.sin6_addr
) &&
710 !IN6_ARE_ADDR_EQUAL(&ip6n
.ip6_src
,
711 &saidx
->proxy
.sin6
.sin6_addr
)) ||
712 (saidx
->proxy
.sa
.sa_family
!= AF_INET6
&&
713 saidx
->proxy
.sa
.sa_family
!= 0)) {
715 DPRINTF(("ipsec6_common_input_cb: inner "
716 "source address %s doesn't correspond to "
717 "expected proxy source %s, SA %s/%08lx\n",
718 ip6_sprintf(&ip6n
.ip6_src
),
719 ipsec_address(&saidx
->proxy
),
720 ipsec_address(&saidx
->dst
),
721 (u_long
) ntohl(sav
->spi
)));
723 IPSEC_ISTAT(sproto
, ESP_STAT_PDROPS
,
724 AH_STAT_PDROPS
, IPCOMP_STAT_PDROPS
);
732 * Record what we've done to the packet (under what SA it was
733 * processed). If we've been passed an mtag, it means the packet
734 * was already processed by an ethernet/crypto combo card and
735 * thus has a tag attached with all the right information, but
736 * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to
737 * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type.
739 if (mt
== NULL
&& sproto
!= IPPROTO_IPCOMP
) {
740 mtag
= m_tag_get(PACKET_TAG_IPSEC_IN_DONE
,
741 sizeof(struct tdb_ident
), M_NOWAIT
);
743 DPRINTF(("ipsec_common_input_cb: failed to "
745 IPSEC_ISTAT(sproto
, ESP_STAT_HDROPS
,
746 AH_STAT_HDROPS
, IPCOMP_STAT_HDROPS
);
751 tdbi
= (struct tdb_ident
*)(mtag
+ 1);
752 memcpy(&tdbi
->dst
, &saidx
->dst
, sizeof(union sockaddr_union
));
753 tdbi
->proto
= sproto
;
754 tdbi
->spi
= sav
->spi
;
756 m_tag_prepend(m
, mtag
);
759 mt
->m_tag_id
= PACKET_TAG_IPSEC_IN_DONE
;
760 /* XXX do we need to mark m_flags??? */
763 key_sa_recordxfer(sav
, m
);
765 /* Retrieve new protocol */
766 m_copydata(m
, protoff
, sizeof(u_int8_t
), &nxt8
);
769 * See the end of ip6_input for this logic.
770 * IPPROTO_IPV[46] case will be processed just like other ones
774 while (nxt
!= IPPROTO_DONE
) {
775 if (ip6_hdrnestlimit
&& (++nest
> ip6_hdrnestlimit
)) {
776 IP6_STATINC(IP6_STAT_TOOMANYHDR
);
782 * Protection against faulty packet - there should be
783 * more sanity checks in header chain processing.
785 if (m
->m_pkthdr
.len
< skip
) {
786 IP6_STATINC(IP6_STAT_TOOSHORT
);
787 in6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_truncated
);
792 * Enforce IPsec policy checking if we are seeing last header.
793 * note that we do not visit this with protocols with pcb layer
794 * code - like udp/tcp/raw ip.
796 if ((inet6sw
[ip6_protox
[nxt
]].pr_flags
& PR_LASTHDR
) != 0 &&
797 ipsec6_in_reject(m
, NULL
)) {
801 nxt
= (*inet6sw
[ip6_protox
[nxt
]].pr_input
)(&m
, &skip
, nxt
);