1 /* $FreeBSD: src/sys/netinet6/esp_input.c,v 1.1.2.8 2003/01/23 21:06:47 sam Exp $ */
2 /* $DragonFly: src/sys/netinet6/esp_input.c,v 1.17 2008/05/27 01:10:43 dillon Exp $ */
3 /* $KAME: esp_input.c,v 1.62 2002/01/07 11:39:57 kjc Exp $ */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * RFC1827/2406 Encapsulated Security Payload.
39 #include "opt_inet6.h"
41 #include <sys/param.h>
42 #include <sys/systm.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>
51 #include <sys/thread2.h>
52 #include <sys/msgport2.h>
55 #include <net/route.h>
56 #include <net/netisr.h>
57 #include <machine/cpu.h>
59 #include <netinet/in.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/ip.h>
62 #include <netinet/ip_var.h>
63 #include <netinet/in_var.h>
64 #include <netinet/ip_ecn.h>
66 #include <netinet6/ip6_ecn.h>
70 #include <netinet/ip6.h>
71 #include <netinet6/in6_pcb.h>
72 #include <netinet6/ip6_var.h>
73 #include <netinet/icmp6.h>
74 #include <netinet6/ip6protosw.h>
77 #include <netinet6/ipsec.h>
79 #include <netinet6/ipsec6.h>
81 #include <netinet6/ah.h>
83 #include <netinet6/ah6.h>
85 #include <netinet6/esp.h>
87 #include <netinet6/esp6.h>
89 #include <netproto/key/key.h>
90 #include <netproto/key/keydb.h>
91 #include <netproto/key/key_debug.h>
93 #include <machine/stdarg.h>
95 #include <net/net_osdep.h>
100 (sizeof(struct esp) < sizeof(struct newesp) \
101 ? sizeof(struct newesp) : sizeof(struct esp))
104 extern struct protosw inetsw[];
107 esp4_input(struct mbuf **mp, int *offp, int proto)
112 struct esptail esptail;
115 struct secasvar *sav = NULL;
118 const struct esp_algorithm *algo;
127 /* sanity check for alignment. */
128 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
129 ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
130 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
131 ipsecstat.in_inval++;
135 if (m->m_len < off + ESPMAXLEN) {
136 m = m_pullup(m, off + ESPMAXLEN);
139 "IPv4 ESP input: can't pullup in esp4_input\n"));
140 ipsecstat.in_inval++;
145 ip = mtod(m, struct ip *);
146 esp = (struct esp *)(((u_int8_t *)ip) + off);
148 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
150 hlen = ip->ip_hl << 2;
153 /* find the sassoc. */
156 if ((sav = key_allocsa(AF_INET,
157 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
158 IPPROTO_ESP, spi)) == 0) {
159 ipseclog((LOG_WARNING,
160 "IPv4 ESP input: no key association found for spi %u\n",
161 (u_int32_t)ntohl(spi)));
165 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
166 kprintf("DP esp4_input called to allocate SA:%p\n", sav));
167 if (sav->state != SADB_SASTATE_MATURE
168 && sav->state != SADB_SASTATE_DYING) {
170 "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
171 (u_int32_t)ntohl(spi)));
172 ipsecstat.in_badspi++;
175 algo = esp_algorithm_lookup(sav->alg_enc);
177 ipseclog((LOG_DEBUG, "IPv4 ESP input: "
178 "unsupported encryption algorithm for spi %u\n",
179 (u_int32_t)ntohl(spi)));
180 ipsecstat.in_badspi++;
184 /* check if we have proper ivlen information */
187 ipseclog((LOG_ERR, "improper ivlen in IPv4 ESP input: %s %s\n",
188 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
189 ipsecstat.in_inval++;
193 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
194 && (sav->alg_auth && sav->key_auth)))
197 if (sav->alg_auth == SADB_X_AALG_NULL ||
198 sav->alg_auth == SADB_AALG_NONE)
202 * check for sequence number.
204 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
207 ipsecstat.in_espreplay++;
208 ipseclog((LOG_WARNING,
209 "replay packet in IPv4 ESP input: %s %s\n",
210 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
216 u_char sum0[AH_MAXSUMSIZE];
217 u_char sum[AH_MAXSUMSIZE];
218 const struct ah_algorithm *sumalgo;
221 sumalgo = ah_algorithm_lookup(sav->alg_auth);
224 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
225 if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
226 ipsecstat.in_inval++;
229 if (AH_MAXSUMSIZE < siz) {
231 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
233 ipsecstat.in_inval++;
237 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
239 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
240 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
241 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
242 ipsecstat.in_espauthfail++;
246 if (bcmp(sum0, sum, siz) != 0) {
247 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
248 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
249 ipsecstat.in_espauthfail++;
253 /* strip off the authentication data */
255 ip = mtod(m, struct ip *);
257 ip->ip_len = ip->ip_len - siz;
259 ip->ip_len = htons(ntohs(ip->ip_len) - siz);
261 m->m_flags |= M_AUTHIPDGM;
262 ipsecstat.in_espauthsucc++;
266 * update sequence number.
268 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
269 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
270 ipsecstat.in_espreplay++;
277 /* process main esp header. */
278 if (sav->flags & SADB_X_EXT_OLD) {
280 esplen = sizeof(struct esp);
283 if (sav->flags & SADB_X_EXT_DERIV)
284 esplen = sizeof(struct esp);
286 esplen = sizeof(struct newesp);
289 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
290 ipseclog((LOG_WARNING,
291 "IPv4 ESP input: packet too short\n"));
292 ipsecstat.in_inval++;
296 if (m->m_len < off + esplen + ivlen) {
297 m = m_pullup(m, off + esplen + ivlen);
300 "IPv4 ESP input: can't pullup in esp4_input\n"));
301 ipsecstat.in_inval++;
307 * pre-compute and cache intermediate key
309 if (esp_schedule(algo, sav) != 0) {
310 ipsecstat.in_inval++;
315 * decrypt the packet.
318 panic("internal error: no decrypt function");
319 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
320 /* m is already freed */
322 ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
323 ipsec_logsastr(sav)));
324 ipsecstat.in_inval++;
327 ipsecstat.in_esphist[sav->alg_enc]++;
329 m->m_flags |= M_DECRYPTED;
332 * find the trailer of the ESP.
334 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
336 nxt = esptail.esp_nxt;
337 taillen = esptail.esp_padlen + sizeof(esptail);
339 if (m->m_pkthdr.len < taillen ||
340 m->m_pkthdr.len - taillen < off + esplen + ivlen + sizeof(esptail)) {
341 ipseclog((LOG_WARNING,
342 "bad pad length in IPv4 ESP input: %s %s\n",
343 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
344 ipsecstat.in_inval++;
348 /* strip off the trailing pad area. */
352 ip->ip_len = ip->ip_len - taillen;
354 ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
357 /* was it transmitted over the IPsec tunnel SA? */
358 if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
360 * strip off all the headers that precedes ESP header.
361 * IP4 xx ESP IP4' payload -> IP4' payload
363 * XXX more sanity checks
364 * XXX relationship with gif?
369 m_adj(m, off + esplen + ivlen);
370 if (m->m_len < sizeof(*ip)) {
371 m = m_pullup(m, sizeof(*ip));
373 ipsecstat.in_inval++;
377 ip = mtod(m, struct ip *);
378 /* ECN consideration. */
379 ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
380 if (!key_checktunnelsanity(sav, AF_INET,
381 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
382 ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
383 "in IPv4 ESP input: %s %s\n",
384 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
385 ipsecstat.in_inval++;
389 key_sa_recordxfer(sav, m);
390 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
391 ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
392 ipsecstat.in_nomem++;
396 if (netisr_queue(NETISR_IP, m)) {
397 ipsecstat.in_inval++;
405 * strip off ESP header and IV.
406 * even in m_pulldown case, we need to strip off ESP so that
407 * we can always compute checksum for AH correctly.
411 stripsiz = esplen + ivlen;
413 ip = mtod(m, struct ip *);
414 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
415 m->m_data += stripsiz;
416 m->m_len -= stripsiz;
417 m->m_pkthdr.len -= stripsiz;
419 ip = mtod(m, struct ip *);
421 ip->ip_len = ip->ip_len - stripsiz;
423 ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
427 key_sa_recordxfer(sav, m);
428 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
429 ipsecstat.in_nomem++;
433 if (nxt != IPPROTO_DONE) {
434 if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) &&
435 ipsec4_in_reject(m, NULL)) {
436 ipsecstat.in_polvio++;
439 if (!ip_lengthcheck(&m, 0)) {
440 /* freed in ip_lengthcheck() */
445 (*inetsw[ip_protox[nxt]].pr_input)(mp, offp, nxt);
453 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
454 kprintf("DP esp4_input call free SA:%p\n", sav));
457 ipsecstat.in_success++;
458 return(IPPROTO_DONE);
462 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
463 kprintf("DP esp4_input call free SA:%p\n", sav));
468 return(IPPROTO_DONE);
474 esp6_input(struct mbuf **mp, int *offp, int proto)
476 struct mbuf *m = *mp;
480 struct esptail esptail;
482 struct secasvar *sav = NULL;
485 const struct esp_algorithm *algo;
489 /* sanity check for alignment. */
490 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
491 ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
492 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
493 ipsec6stat.in_inval++;
497 #ifndef PULLDOWN_TEST
498 IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, IPPROTO_DONE);
499 esp = (struct esp *)(mtod(m, caddr_t) + off);
501 IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
503 ipsec6stat.in_inval++;
507 ip6 = mtod(m, struct ip6_hdr *);
509 if (ntohs(ip6->ip6_plen) == 0) {
510 ipseclog((LOG_ERR, "IPv6 ESP input: "
511 "ESP with IPv6 jumbogram is not supported.\n"));
512 ipsec6stat.in_inval++;
516 /* find the sassoc. */
519 if ((sav = key_allocsa(AF_INET6,
520 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
521 IPPROTO_ESP, spi)) == 0) {
522 ipseclog((LOG_WARNING,
523 "IPv6 ESP input: no key association found for spi %u\n",
524 (u_int32_t)ntohl(spi)));
525 ipsec6stat.in_nosa++;
528 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
529 kprintf("DP esp6_input called to allocate SA:%p\n", sav));
530 if (sav->state != SADB_SASTATE_MATURE
531 && sav->state != SADB_SASTATE_DYING) {
533 "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
534 (u_int32_t)ntohl(spi)));
535 ipsec6stat.in_badspi++;
538 algo = esp_algorithm_lookup(sav->alg_enc);
540 ipseclog((LOG_DEBUG, "IPv6 ESP input: "
541 "unsupported encryption algorithm for spi %u\n",
542 (u_int32_t)ntohl(spi)));
543 ipsec6stat.in_badspi++;
547 /* check if we have proper ivlen information */
550 ipseclog((LOG_ERR, "improper ivlen in IPv6 ESP input: %s %s\n",
551 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
552 ipsec6stat.in_badspi++;
556 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
557 && (sav->alg_auth && sav->key_auth)))
560 if (sav->alg_auth == SADB_X_AALG_NULL ||
561 sav->alg_auth == SADB_AALG_NONE)
565 * check for sequence number.
567 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
570 ipsec6stat.in_espreplay++;
571 ipseclog((LOG_WARNING,
572 "replay packet in IPv6 ESP input: %s %s\n",
573 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
579 u_char sum0[AH_MAXSUMSIZE];
580 u_char sum[AH_MAXSUMSIZE];
581 const struct ah_algorithm *sumalgo;
584 sumalgo = ah_algorithm_lookup(sav->alg_auth);
587 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
588 if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
589 ipsec6stat.in_inval++;
592 if (AH_MAXSUMSIZE < siz) {
594 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
596 ipsec6stat.in_inval++;
600 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
602 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
603 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
604 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
605 ipsec6stat.in_espauthfail++;
609 if (bcmp(sum0, sum, siz) != 0) {
610 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
611 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
612 ipsec6stat.in_espauthfail++;
616 /* strip off the authentication data */
618 ip6 = mtod(m, struct ip6_hdr *);
619 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
621 m->m_flags |= M_AUTHIPDGM;
622 ipsec6stat.in_espauthsucc++;
626 * update sequence number.
628 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
629 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
630 ipsec6stat.in_espreplay++;
637 /* process main esp header. */
638 if (sav->flags & SADB_X_EXT_OLD) {
640 esplen = sizeof(struct esp);
643 if (sav->flags & SADB_X_EXT_DERIV)
644 esplen = sizeof(struct esp);
646 esplen = sizeof(struct newesp);
649 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
650 ipseclog((LOG_WARNING,
651 "IPv6 ESP input: packet too short\n"));
652 ipsec6stat.in_inval++;
656 #ifndef PULLDOWN_TEST
657 IP6_EXTHDR_CHECK(m, off, esplen + ivlen, IPPROTO_DONE); /* XXX */
659 IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
661 ipsec6stat.in_inval++;
666 ip6 = mtod(m, struct ip6_hdr *); /* set it again just in case */
669 * pre-compute and cache intermediate key
671 if (esp_schedule(algo, sav) != 0) {
672 ipsec6stat.in_inval++;
677 * decrypt the packet.
680 panic("internal error: no decrypt function");
681 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
682 /* m is already freed */
684 ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
685 ipsec_logsastr(sav)));
686 ipsec6stat.in_inval++;
689 ipsec6stat.in_esphist[sav->alg_enc]++;
691 m->m_flags |= M_DECRYPTED;
694 * find the trailer of the ESP.
696 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
698 nxt = esptail.esp_nxt;
699 taillen = esptail.esp_padlen + sizeof(esptail);
701 if (m->m_pkthdr.len < taillen
702 || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) { /* ? */
703 ipseclog((LOG_WARNING,
704 "bad pad length in IPv6 ESP input: %s %s\n",
705 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
706 ipsec6stat.in_inval++;
710 /* strip off the trailing pad area. */
713 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
715 /* was it transmitted over the IPsec tunnel SA? */
716 if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
718 * strip off all the headers that precedes ESP header.
719 * IP6 xx ESP IP6' payload -> IP6' payload
721 * XXX more sanity checks
722 * XXX relationship with gif?
724 u_int32_t flowinfo; /* net endian */
725 flowinfo = ip6->ip6_flow;
726 m_adj(m, off + esplen + ivlen);
727 if (m->m_len < sizeof(*ip6)) {
728 #ifndef PULLDOWN_TEST
730 * m_pullup is prohibited in KAME IPv6 input processing
731 * but there's no other way!
734 /* okay to pullup in m_pulldown style */
736 m = m_pullup(m, sizeof(*ip6));
738 ipsec6stat.in_inval++;
742 ip6 = mtod(m, struct ip6_hdr *);
743 /* ECN consideration. */
744 ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
745 if (!key_checktunnelsanity(sav, AF_INET6,
746 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
747 ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
748 "in IPv6 ESP input: %s %s\n",
749 ipsec6_logpacketstr(ip6, spi),
750 ipsec_logsastr(sav)));
751 ipsec6stat.in_inval++;
755 key_sa_recordxfer(sav, m);
756 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
757 ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
758 ipsec6stat.in_nomem++;
762 if (netisr_queue(NETISR_IPV6, m)) {
763 ipsec6stat.in_inval++;
771 * strip off ESP header and IV.
772 * even in m_pulldown case, we need to strip off ESP so that
773 * we can always compute checksum for AH correctly.
779 * Set the next header field of the previous header correctly.
781 prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
784 stripsiz = esplen + ivlen;
786 ip6 = mtod(m, struct ip6_hdr *);
787 if (m->m_len >= stripsiz + off) {
788 ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
789 m->m_data += stripsiz;
790 m->m_len -= stripsiz;
791 m->m_pkthdr.len -= stripsiz;
794 * this comes with no copy if the boundary is on
799 n = m_split(m, off, MB_DONTWAIT);
801 /* m is retained by m_split */
805 /* m_cat does not update m_pkthdr.len */
806 m->m_pkthdr.len += n->m_pkthdr.len;
810 #ifndef PULLDOWN_TEST
812 * KAME requires that the packet to be contiguous on the
813 * mbuf. We need to make that sure.
814 * this kind of code should be avoided.
815 * XXX other conditions to avoid running this part?
817 if (m->m_len != m->m_pkthdr.len) {
818 struct mbuf *n = NULL;
821 n = m_getb(m->m_pkthdr.len, MB_DONTWAIT, MT_HEADER,
824 kprintf("esp6_input: mbuf allocation failed\n");
829 maxlen = (n->m_flags & M_EXT) ? MCLBYTES : MHLEN;
830 if (n->m_pkthdr.len <= maxlen) {
831 m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t));
832 n->m_len = n->m_pkthdr.len;
836 m_copydata(m, 0, maxlen, mtod(n, caddr_t));
845 ip6 = mtod(m, struct ip6_hdr *);
846 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
848 key_sa_recordxfer(sav, m);
849 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
850 ipsec6stat.in_nomem++;
859 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
860 kprintf("DP esp6_input call free SA:%p\n", sav));
863 ipsec6stat.in_success++;
868 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
869 kprintf("DP esp6_input call free SA:%p\n", sav));
878 esp6_ctlinput(netmsg_t msg)
880 int cmd = msg->ctlinput.nm_cmd;
881 struct sockaddr *sa = msg->ctlinput.nm_arg;
882 void *d = msg->ctlinput.nm_extra;
883 const struct newesp *espp;
885 struct ip6ctlparam *ip6cp = NULL, ip6cp1;
886 struct secasvar *sav;
890 struct sockaddr_in6 *sa6_src, *sa6_dst;
892 if (sa->sa_family != AF_INET6 ||
893 sa->sa_len != sizeof(struct sockaddr_in6))
895 if ((unsigned)cmd >= PRC_NCMDS)
898 /* if the parameter is from icmp6, decode it. */
900 ip6cp = (struct ip6ctlparam *)d;
902 ip6 = ip6cp->ip6c_ip6;
903 off = ip6cp->ip6c_off;
907 off = 0; /* fix warning */
912 * Notify the error to all possible sockets via pfctlinput2.
913 * Since the upper layer information (such as protocol type,
914 * source and destination ports) is embedded in the encrypted
915 * data and might have been cut, we can't directly call
916 * an upper layer ctlinput function. However, the pcbnotify
917 * function will consider source and destination addresses
918 * as well as the flow info value, and may be able to find
919 * some PCB that should be notified.
920 * Although kpfctlinput2 will call esp6_ctlinput(), there is
921 * no possibility of an infinite loop of function calls,
922 * because we don't pass the inner IPv6 header.
924 bzero(&ip6cp1, sizeof(ip6cp1));
925 ip6cp1.ip6c_src = ip6cp->ip6c_src;
926 kpfctlinput2(cmd, sa, (void *)&ip6cp1);
929 * Then go to special cases that need ESP header information.
930 * XXX: We assume that when ip6 is non NULL,
931 * M and OFF are valid.
934 /* check if we can safely examine src and dst ports */
935 if (m->m_pkthdr.len < off + sizeof(esp))
938 if (m->m_len < off + sizeof(esp)) {
940 * this should be rare case,
941 * so we compromise on this copy...
943 m_copydata(m, off, sizeof(esp), (caddr_t)&esp);
946 espp = (struct newesp*)(mtod(m, caddr_t) + off);
948 if (cmd == PRC_MSGSIZE) {
952 * Check to see if we have a valid SA corresponding to
953 * the address in the ICMP message payload.
955 sa6_src = ip6cp->ip6c_src;
956 sa6_dst = (struct sockaddr_in6 *)sa;
957 sav = key_allocsa(AF_INET6,
958 (caddr_t)&sa6_src->sin6_addr,
959 (caddr_t)&sa6_dst->sin6_addr,
960 IPPROTO_ESP, espp->esp_spi);
962 if (sav->state == SADB_SASTATE_MATURE ||
963 sav->state == SADB_SASTATE_DYING)
968 /* XXX Further validation? */
971 * Depending on the value of "valid" and routing table
972 * size (mtudisc_{hi,lo}wat), we will:
973 * - recalcurate the new MTU and create the
974 * corresponding routing entry, or
975 * - ignore the MTU change notification.
977 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
980 /* we normally notify any pcb here */
983 lwkt_replymsg(&msg->ctlinput.base.lmsg, 0);