]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/esp_input.c
7bd490e8f9573a055b9078d2f254e5f18e05aa97
1 /* $KAME: esp_input.c,v 1.22 2000/03/21 05:14:49 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * RFC1827/2406 Encapsulated Security Payload.
37 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
45 #include <sys/domain.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/errno.h>
50 #include <sys/kernel.h>
51 #include <sys/syslog.h>
54 #include <net/route.h>
55 #include <net/netisr.h>
56 #include <kern/cpu_number.h>
58 #include <netinet/in.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/ip.h>
61 #include <netinet/ip_var.h>
62 #include <netinet/in_var.h>
63 #include <netinet/ip_ecn.h>
66 #include <netinet/ip6.h>
67 #include <netinet6/ip6_var.h>
68 #include <netinet/icmp6.h>
71 #include <netinet6/ipsec.h>
72 #include <netinet6/ah.h>
73 #include <netinet6/esp.h>
74 #include <netkey/key.h>
75 #include <netkey/keydb.h>
76 #include <netkey/key_debug.h>
79 #include <net/net_osdep.h>
84 extern struct protosw inetsw
[];
85 #if defined(__bsdi__) || defined(__NetBSD__)
86 extern u_char ip_protox
[];
90 (sizeof(struct esp) < sizeof(struct newesp) \
91 ? sizeof(struct newesp) : sizeof(struct esp))
100 struct esptail esptail
;
102 struct secasvar
*sav
= NULL
;
105 struct esp_algorithm
*algo
;
111 /* sanity check for alignment. */
112 if (off
% 4 != 0 || m
->m_pkthdr
.len
% 4 != 0) {
113 ipseclog((LOG_ERR
, "IPv4 ESP input: packet alignment problem "
114 "(off=%d, pktlen=%d)\n", off
, m
->m_pkthdr
.len
));
115 ipsecstat
.in_inval
++;
119 if (m
->m_len
< off
+ ESPMAXLEN
) {
120 m
= m_pullup(m
, off
+ ESPMAXLEN
);
123 "IPv4 ESP input: can't pullup in esp4_input\n"));
124 ipsecstat
.in_inval
++;
129 ip
= mtod(m
, struct ip
*);
130 esp
= (struct esp
*)(((u_int8_t
*)ip
) + off
);
132 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2;
134 hlen
= ip
->ip_hl
<< 2;
137 /* find the sassoc. */
140 if ((sav
= key_allocsa(AF_INET
,
141 (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
,
142 IPPROTO_ESP
, spi
)) == 0) {
143 ipseclog((LOG_WARNING
,
144 "IPv4 ESP input: no key association found for spi %u\n",
145 (u_int32_t
)ntohl(spi
)));
149 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
150 printf("DP esp4_input called to allocate SA:%p\n", sav
));
151 if (sav
->state
!= SADB_SASTATE_MATURE
152 && sav
->state
!= SADB_SASTATE_DYING
) {
154 "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
155 (u_int32_t
)ntohl(spi
)));
156 ipsecstat
.in_badspi
++;
159 if (sav
->alg_enc
== SADB_EALG_NONE
) {
160 ipseclog((LOG_DEBUG
, "IPv4 ESP input: "
161 "unspecified encryption algorithm for spi %u\n",
162 (u_int32_t
)ntohl(spi
)));
163 ipsecstat
.in_badspi
++;
167 algo
= &esp_algorithms
[sav
->alg_enc
]; /*XXX*/
169 /* check if we have proper ivlen information */
172 ipseclog((LOG_ERR
, "inproper ivlen in IPv4 ESP input: %s %s\n",
173 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
174 ipsecstat
.in_inval
++;
178 if (!((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
179 && (sav
->alg_auth
&& sav
->key_auth
)))
182 if (sav
->alg_auth
== SADB_AALG_NULL
)
186 * check for sequence number.
188 if (ipsec_chkreplay(ntohl(((struct newesp
*)esp
)->esp_seq
), sav
))
191 ipsecstat
.in_espreplay
++;
192 ipseclog((LOG_WARNING
,
193 "replay packet in IPv4 ESP input: %s %s\n",
194 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
200 u_char sum0
[AH_MAXSUMSIZE
];
201 u_char sum
[AH_MAXSUMSIZE
];
202 struct ah_algorithm
*sumalgo
;
205 sumalgo
= &ah_algorithms
[sav
->alg_auth
];
206 siz
= (((*sumalgo
->sumsiz
)(sav
) + 3) & ~(4 - 1));
207 if (AH_MAXSUMSIZE
< siz
) {
209 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
211 ipsecstat
.in_inval
++;
215 m_copydata(m
, m
->m_pkthdr
.len
- siz
, siz
, &sum0
[0]);
217 if (esp_auth(m
, off
, m
->m_pkthdr
.len
- off
- siz
, sav
, sum
)) {
218 ipseclog((LOG_WARNING
, "auth fail in IPv4 ESP input: %s %s\n",
219 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
220 ipsecstat
.in_espauthfail
++;
224 if (bcmp(sum0
, sum
, siz
) != 0) {
225 ipseclog((LOG_WARNING
, "auth fail in IPv4 ESP input: %s %s\n",
226 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
227 ipsecstat
.in_espauthfail
++;
231 /* strip off the authentication data */
233 ip
= mtod(m
, struct ip
*);
235 ip
->ip_len
= ip
->ip_len
- siz
;
237 ip
->ip_len
= htons(ntohs(ip
->ip_len
) - siz
);
239 m
->m_flags
|= M_AUTHIPDGM
;
240 ipsecstat
.in_espauthsucc
++;
244 * update sequence number.
246 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
247 if (ipsec_updatereplay(ntohl(((struct newesp
*)esp
)->esp_seq
), sav
)) {
248 ipsecstat
.in_espreplay
++;
255 /* process main esp header. */
256 if (sav
->flags
& SADB_X_EXT_OLD
) {
258 esplen
= sizeof(struct esp
);
261 if (sav
->flags
& SADB_X_EXT_DERIV
)
262 esplen
= sizeof(struct esp
);
264 esplen
= sizeof(struct newesp
);
267 if (m
->m_pkthdr
.len
< off
+ esplen
+ ivlen
+ sizeof(esptail
)) {
268 ipseclog((LOG_WARNING
,
269 "IPv4 ESP input: packet too short\n"));
270 ipsecstat
.in_inval
++;
274 if (m
->m_len
< off
+ esplen
+ ivlen
) {
275 m
= m_pullup(m
, off
+ esplen
+ ivlen
);
278 "IPv4 ESP input: can't pullup in esp4_input\n"));
279 ipsecstat
.in_inval
++;
286 * decrypt the packet.
289 panic("internal error: no decrypt function");
290 if ((*algo
->decrypt
)(m
, off
, sav
, algo
, ivlen
)) {
291 ipseclog((LOG_ERR
, "decrypt fail in IPv4 ESP input: %s %s\n",
292 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
293 ipsecstat
.in_inval
++;
296 ipsecstat
.in_esphist
[sav
->alg_enc
]++;
298 m
->m_flags
|= M_DECRYPTED
;
302 * find the trailer of the ESP.
304 m_copydata(m
, m
->m_pkthdr
.len
- sizeof(esptail
), sizeof(esptail
),
306 nxt
= esptail
.esp_nxt
;
307 taillen
= esptail
.esp_padlen
+ sizeof(esptail
);
309 if (m
->m_pkthdr
.len
< taillen
310 || m
->m_pkthdr
.len
- taillen
< hlen
) { /*?*/
311 ipseclog((LOG_WARNING
,
312 "bad pad length in IPv4 ESP input: %s %s\n",
313 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
314 ipsecstat
.in_inval
++;
318 /* strip off the trailing pad area. */
322 ip
->ip_len
= ip
->ip_len
- taillen
;
324 ip
->ip_len
= htons(ntohs(ip
->ip_len
) - taillen
);
327 /* was it transmitted over the IPsec tunnel SA? */
328 if (ipsec4_tunnel_validate(ip
, nxt
, sav
)) {
330 * strip off all the headers that precedes ESP header.
331 * IP4 xx ESP IP4' payload -> IP4' payload
333 * XXX more sanity checks
334 * XXX relationship with gif?
339 m_adj(m
, off
+ esplen
+ ivlen
);
340 if (m
->m_len
< sizeof(*ip
)) {
341 m
= m_pullup(m
, sizeof(*ip
));
343 ipsecstat
.in_inval
++;
347 ip
= mtod(m
, struct ip
*);
348 /* ECN consideration. */
349 ip_ecn_egress(ip4_ipsec_ecn
, &tos
, &ip
->ip_tos
);
350 if (!key_checktunnelsanity(sav
, AF_INET
,
351 (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
)) {
352 ipseclog((LOG_ERR
, "ipsec tunnel address mismatch "
353 "in IPv4 ESP input: %s %s\n",
354 ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
)));
355 ipsecstat
.in_inval
++;
359 #if 0 /* XXX should call ipfw rather than ipsec_in_reject, shouldn't it ? */
360 /* drop it if it does not match the default policy */
361 if (ipsec4_in_reject(m
, NULL
)) {
362 ipsecstat
.in_polvio
++;
367 key_sa_recordxfer(sav
, m
);
370 if (IF_QFULL(&ipintrq
)) {
371 ipsecstat
.in_inval
++;
374 IF_ENQUEUE(&ipintrq
, m
);
376 schednetisr(NETISR_IP
); /*can be skipped but to make sure*/
381 * strip off ESP header and IV.
382 * even in m_pulldown case, we need to strip off ESP so that
383 * we can always compute checksum for AH correctly.
387 stripsiz
= esplen
+ ivlen
;
389 ip
= mtod(m
, struct ip
*);
390 ovbcopy((caddr_t
)ip
, (caddr_t
)(((u_char
*)ip
) + stripsiz
), off
);
391 m
->m_data
+= stripsiz
;
392 m
->m_len
-= stripsiz
;
393 m
->m_pkthdr
.len
-= stripsiz
;
395 ip
= mtod(m
, struct ip
*);
397 ip
->ip_len
= ip
->ip_len
- stripsiz
;
399 ip
->ip_len
= htons(ntohs(ip
->ip_len
) - stripsiz
);
403 key_sa_recordxfer(sav
, m
);
405 if (nxt
!= IPPROTO_DONE
)
406 (*ip_protox
[nxt
]->pr_input
)(m
, off
);
413 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
414 printf("DP esp4_input call free SA:%p\n", sav
));
417 ipsecstat
.in_success
++;
422 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
423 printf("DP esp4_input call free SA:%p\n", sav
));
434 esp6_input(mp
, offp
, proto
)
438 struct mbuf
*m
= *mp
;
442 struct esptail esptail
;
444 struct secasvar
*sav
= NULL
;
447 struct esp_algorithm
*algo
;
452 /* sanity check for alignment. */
453 if (off
% 4 != 0 || m
->m_pkthdr
.len
% 4 != 0) {
454 ipseclog((LOG_ERR
, "IPv6 ESP input: packet alignment problem "
455 "(off=%d, pktlen=%d)\n", off
, m
->m_pkthdr
.len
));
456 ipsec6stat
.in_inval
++;
460 #ifndef PULLDOWN_TEST
461 IP6_EXTHDR_CHECK(m
, off
, ESPMAXLEN
, IPPROTO_DONE
);
462 esp
= (struct esp
*)(mtod(m
, caddr_t
) + off
);
464 IP6_EXTHDR_GET(esp
, struct esp
*, m
, off
, ESPMAXLEN
);
466 ipsec6stat
.in_inval
++;
470 ip6
= mtod(m
, struct ip6_hdr
*);
472 if (ntohs(ip6
->ip6_plen
) == 0) {
473 ipseclog((LOG_ERR
, "IPv6 ESP input: "
474 "ESP with IPv6 jumbogram is not supported.\n"));
475 ipsec6stat
.in_inval
++;
479 /* find the sassoc. */
482 if ((sav
= key_allocsa(AF_INET6
,
483 (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
,
484 IPPROTO_ESP
, spi
)) == 0) {
485 ipseclog((LOG_WARNING
,
486 "IPv6 ESP input: no key association found for spi %u\n",
487 (u_int32_t
)ntohl(spi
)));
488 ipsec6stat
.in_nosa
++;
491 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
492 printf("DP esp6_input called to allocate SA:%p\n", sav
));
493 if (sav
->state
!= SADB_SASTATE_MATURE
494 && sav
->state
!= SADB_SASTATE_DYING
) {
496 "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
497 (u_int32_t
)ntohl(spi
)));
498 ipsec6stat
.in_badspi
++;
501 if (sav
->alg_enc
== SADB_EALG_NONE
) {
502 ipseclog((LOG_DEBUG
, "IPv6 ESP input: "
503 "unspecified encryption algorithm for spi %u\n",
504 (u_int32_t
)ntohl(spi
)));
505 ipsec6stat
.in_badspi
++;
509 algo
= &esp_algorithms
[sav
->alg_enc
]; /*XXX*/
511 /* check if we have proper ivlen information */
514 ipseclog((LOG_ERR
, "inproper ivlen in IPv6 ESP input: %s %s\n",
515 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
516 ipsec6stat
.in_badspi
++;
520 if (!((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
521 && (sav
->alg_auth
&& sav
->key_auth
)))
524 if (sav
->alg_auth
== SADB_AALG_NULL
)
528 * check for sequence number.
530 if (ipsec_chkreplay(ntohl(((struct newesp
*)esp
)->esp_seq
), sav
))
533 ipsec6stat
.in_espreplay
++;
534 ipseclog((LOG_WARNING
,
535 "replay packet in IPv6 ESP input: %s %s\n",
536 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
542 u_char sum0
[AH_MAXSUMSIZE
];
543 u_char sum
[AH_MAXSUMSIZE
];
544 struct ah_algorithm
*sumalgo
;
547 sumalgo
= &ah_algorithms
[sav
->alg_auth
];
548 siz
= (((*sumalgo
->sumsiz
)(sav
) + 3) & ~(4 - 1));
549 if (AH_MAXSUMSIZE
< siz
) {
551 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
553 ipsec6stat
.in_inval
++;
557 m_copydata(m
, m
->m_pkthdr
.len
- siz
, siz
, &sum0
[0]);
559 if (esp_auth(m
, off
, m
->m_pkthdr
.len
- off
- siz
, sav
, sum
)) {
560 ipseclog((LOG_WARNING
, "auth fail in IPv6 ESP input: %s %s\n",
561 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
562 ipsec6stat
.in_espauthfail
++;
566 if (bcmp(sum0
, sum
, siz
) != 0) {
567 ipseclog((LOG_WARNING
, "auth fail in IPv6 ESP input: %s %s\n",
568 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
569 ipsec6stat
.in_espauthfail
++;
573 /* strip off the authentication data */
575 ip6
= mtod(m
, struct ip6_hdr
*);
576 ip6
->ip6_plen
= htons(ntohs(ip6
->ip6_plen
) - siz
);
578 m
->m_flags
|= M_AUTHIPDGM
;
579 ipsec6stat
.in_espauthsucc
++;
583 * update sequence number.
585 if ((sav
->flags
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) {
586 if (ipsec_updatereplay(ntohl(((struct newesp
*)esp
)->esp_seq
), sav
)) {
587 ipsec6stat
.in_espreplay
++;
594 /* process main esp header. */
595 if (sav
->flags
& SADB_X_EXT_OLD
) {
597 esplen
= sizeof(struct esp
);
600 if (sav
->flags
& SADB_X_EXT_DERIV
)
601 esplen
= sizeof(struct esp
);
603 esplen
= sizeof(struct newesp
);
606 if (m
->m_pkthdr
.len
< off
+ esplen
+ ivlen
+ sizeof(esptail
)) {
607 ipseclog((LOG_WARNING
,
608 "IPv6 ESP input: packet too short\n"));
609 ipsec6stat
.in_inval
++;
613 #ifndef PULLDOWN_TEST
614 IP6_EXTHDR_CHECK(m
, off
, esplen
+ ivlen
, IPPROTO_DONE
); /*XXX*/
616 IP6_EXTHDR_GET(esp
, struct esp
*, m
, off
, esplen
+ ivlen
);
618 ipsec6stat
.in_inval
++;
623 ip6
= mtod(m
, struct ip6_hdr
*); /*set it again just in case*/
626 * decrypt the packet.
629 panic("internal error: no decrypt function");
630 if ((*algo
->decrypt
)(m
, off
, sav
, algo
, ivlen
)) {
631 ipseclog((LOG_ERR
, "decrypt fail in IPv6 ESP input: %s %s\n",
632 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
633 ipsec6stat
.in_inval
++;
636 ipsec6stat
.in_esphist
[sav
->alg_enc
]++;
638 m
->m_flags
|= M_DECRYPTED
;
641 * find the trailer of the ESP.
643 m_copydata(m
, m
->m_pkthdr
.len
- sizeof(esptail
), sizeof(esptail
),
645 nxt
= esptail
.esp_nxt
;
646 taillen
= esptail
.esp_padlen
+ sizeof(esptail
);
648 if (m
->m_pkthdr
.len
< taillen
649 || m
->m_pkthdr
.len
- taillen
< sizeof(struct ip6_hdr
)) { /*?*/
650 ipseclog((LOG_WARNING
,
651 "bad pad length in IPv6 ESP input: %s %s\n",
652 ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
)));
653 ipsec6stat
.in_inval
++;
657 /* strip off the trailing pad area. */
660 ip6
->ip6_plen
= htons(ntohs(ip6
->ip6_plen
) - taillen
);
662 /* was it transmitted over the IPsec tunnel SA? */
663 if (ipsec6_tunnel_validate(ip6
, nxt
, sav
)) {
665 * strip off all the headers that precedes ESP header.
666 * IP6 xx ESP IP6' payload -> IP6' payload
668 * XXX more sanity checks
669 * XXX relationship with gif?
671 u_int32_t flowinfo
; /*net endian*/
672 flowinfo
= ip6
->ip6_flow
;
673 m_adj(m
, off
+ esplen
+ ivlen
);
674 if (m
->m_len
< sizeof(*ip6
)) {
675 #ifndef PULLDOWN_TEST
677 * m_pullup is prohibited in KAME IPv6 input processing
678 * but there's no other way!
681 /* okay to pullup in m_pulldown style */
683 m
= m_pullup(m
, sizeof(*ip6
));
685 ipsec6stat
.in_inval
++;
689 ip6
= mtod(m
, struct ip6_hdr
*);
690 /* ECN consideration. */
691 ip6_ecn_egress(ip6_ipsec_ecn
, &flowinfo
, &ip6
->ip6_flow
);
692 if (!key_checktunnelsanity(sav
, AF_INET6
,
693 (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
)) {
694 ipseclog((LOG_ERR
, "ipsec tunnel address mismatch "
695 "in IPv6 ESP input: %s %s\n",
696 ipsec6_logpacketstr(ip6
, spi
),
697 ipsec_logsastr(sav
)));
698 ipsec6stat
.in_inval
++;
702 #if 0 /* XXX should call ipfw rather than ipsec_in_reject, shouldn't it ? */
703 /* drop it if it does not match the default policy */
704 if (ipsec6_in_reject(m
, NULL
)) {
705 ipsec6stat
.in_polvio
++;
710 key_sa_recordxfer(sav
, m
);
713 if (IF_QFULL(&ip6intrq
)) {
714 ipsec6stat
.in_inval
++;
717 IF_ENQUEUE(&ip6intrq
, m
);
719 schednetisr(NETISR_IPV6
); /*can be skipped but to make sure*/
724 * strip off ESP header and IV.
725 * even in m_pulldown case, we need to strip off ESP so that
726 * we can always compute checksum for AH correctly.
732 * Set the next header field of the previous header correctly.
734 prvnxtp
= ip6_get_prevhdr(m
, off
); /* XXX */
737 stripsiz
= esplen
+ ivlen
;
739 ip6
= mtod(m
, struct ip6_hdr
*);
740 if (m
->m_len
>= stripsiz
+ off
) {
741 ovbcopy((caddr_t
)ip6
, ((caddr_t
)ip6
) + stripsiz
, off
);
742 m
->m_data
+= stripsiz
;
743 m
->m_len
-= stripsiz
;
744 m
->m_pkthdr
.len
-= stripsiz
;
747 * this comes with no copy if the boundary is on
752 n
= m_split(m
, off
, M_DONTWAIT
);
754 /* m is retained by m_split */
759 /* m_cat does not update m_pkthdr.len */
760 m
->m_pkthdr
.len
+= n
->m_pkthdr
.len
;
763 ip6
= mtod(m
, struct ip6_hdr
*);
764 ip6
->ip6_plen
= htons(ntohs(ip6
->ip6_plen
) - stripsiz
);
766 key_sa_recordxfer(sav
, m
);
773 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
774 printf("DP esp6_input call free SA:%p\n", sav
));
777 ipsec6stat
.in_success
++;
782 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
783 printf("DP esp6_input call free SA:%p\n", sav
));