]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/esp_input.c
7bd490e8f9573a055b9078d2f254e5f18e05aa97
[apple/xnu.git] / bsd / netinet6 / esp_input.c
1 /* $KAME: esp_input.c,v 1.22 2000/03/21 05:14:49 itojun Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
18 *
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
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * RFC1827/2406 Encapsulated Security Payload.
34 */
35
36 #define _IP_VHL
37 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
38 #include "opt_inet.h"
39 #endif
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/domain.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/errno.h>
49 #include <sys/time.h>
50 #include <sys/kernel.h>
51 #include <sys/syslog.h>
52
53 #include <net/if.h>
54 #include <net/route.h>
55 #include <net/netisr.h>
56 #include <kern/cpu_number.h>
57
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>
64
65 #if INET6
66 #include <netinet/ip6.h>
67 #include <netinet6/ip6_var.h>
68 #include <netinet/icmp6.h>
69 #endif
70
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>
77
78
79 #include <net/net_osdep.h>
80
81 #define IPLEN_FLIPPED
82
83 #if INET
84 extern struct protosw inetsw[];
85 #if defined(__bsdi__) || defined(__NetBSD__)
86 extern u_char ip_protox[];
87 #endif
88
89 #define ESPMAXLEN \
90 (sizeof(struct esp) < sizeof(struct newesp) \
91 ? sizeof(struct newesp) : sizeof(struct esp))
92
93 void
94 esp4_input(m, off)
95 struct mbuf *m;
96 int off;
97 {
98 struct ip *ip;
99 struct esp *esp;
100 struct esptail esptail;
101 u_int32_t spi;
102 struct secasvar *sav = NULL;
103 size_t taillen;
104 u_int16_t nxt;
105 struct esp_algorithm *algo;
106 int ivlen;
107 size_t hlen;
108 size_t esplen;
109 int s;
110
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++;
116 goto bad;
117 }
118
119 if (m->m_len < off + ESPMAXLEN) {
120 m = m_pullup(m, off + ESPMAXLEN);
121 if (!m) {
122 ipseclog((LOG_DEBUG,
123 "IPv4 ESP input: can't pullup in esp4_input\n"));
124 ipsecstat.in_inval++;
125 goto bad;
126 }
127 }
128
129 ip = mtod(m, struct ip *);
130 esp = (struct esp *)(((u_int8_t *)ip) + off);
131 #ifdef _IP_VHL
132 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
133 #else
134 hlen = ip->ip_hl << 2;
135 #endif
136
137 /* find the sassoc. */
138 spi = esp->esp_spi;
139
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)));
146 ipsecstat.in_nosa++;
147 goto bad;
148 }
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) {
153 ipseclog((LOG_DEBUG,
154 "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
155 (u_int32_t)ntohl(spi)));
156 ipsecstat.in_badspi++;
157 goto bad;
158 }
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++;
164 goto bad;
165 }
166
167 algo = &esp_algorithms[sav->alg_enc]; /*XXX*/
168
169 /* check if we have proper ivlen information */
170 ivlen = sav->ivlen;
171 if (ivlen < 0) {
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++;
175 goto bad;
176 }
177
178 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
179 && (sav->alg_auth && sav->key_auth)))
180 goto noreplaycheck;
181
182 if (sav->alg_auth == SADB_AALG_NULL)
183 goto noreplaycheck;
184
185 /*
186 * check for sequence number.
187 */
188 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
189 ; /*okey*/
190 else {
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)));
195 goto bad;
196 }
197
198 /* check ICV */
199 {
200 u_char sum0[AH_MAXSUMSIZE];
201 u_char sum[AH_MAXSUMSIZE];
202 struct ah_algorithm *sumalgo;
203 size_t siz;
204
205 sumalgo = &ah_algorithms[sav->alg_auth];
206 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
207 if (AH_MAXSUMSIZE < siz) {
208 ipseclog((LOG_DEBUG,
209 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
210 (u_long)siz));
211 ipsecstat.in_inval++;
212 goto bad;
213 }
214
215 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
216
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++;
221 goto bad;
222 }
223
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++;
228 goto bad;
229 }
230
231 /* strip off the authentication data */
232 m_adj(m, -siz);
233 ip = mtod(m, struct ip *);
234 #ifdef IPLEN_FLIPPED
235 ip->ip_len = ip->ip_len - siz;
236 #else
237 ip->ip_len = htons(ntohs(ip->ip_len) - siz);
238 #endif
239 m->m_flags |= M_AUTHIPDGM;
240 ipsecstat.in_espauthsucc++;
241 }
242
243 /*
244 * update sequence number.
245 */
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++;
249 goto bad;
250 }
251 }
252
253 noreplaycheck:
254
255 /* process main esp header. */
256 if (sav->flags & SADB_X_EXT_OLD) {
257 /* RFC 1827 */
258 esplen = sizeof(struct esp);
259 } else {
260 /* RFC 2406 */
261 if (sav->flags & SADB_X_EXT_DERIV)
262 esplen = sizeof(struct esp);
263 else
264 esplen = sizeof(struct newesp);
265 }
266
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++;
271 goto bad;
272 }
273
274 if (m->m_len < off + esplen + ivlen) {
275 m = m_pullup(m, off + esplen + ivlen);
276 if (!m) {
277 ipseclog((LOG_DEBUG,
278 "IPv4 ESP input: can't pullup in esp4_input\n"));
279 ipsecstat.in_inval++;
280 goto bad;
281 }
282 }
283
284 {
285 /*
286 * decrypt the packet.
287 */
288 if (!algo->decrypt)
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++;
294 goto bad;
295 }
296 ipsecstat.in_esphist[sav->alg_enc]++;
297
298 m->m_flags |= M_DECRYPTED;
299 }
300
301 /*
302 * find the trailer of the ESP.
303 */
304 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
305 (caddr_t)&esptail);
306 nxt = esptail.esp_nxt;
307 taillen = esptail.esp_padlen + sizeof(esptail);
308
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++;
315 goto bad;
316 }
317
318 /* strip off the trailing pad area. */
319 m_adj(m, -taillen);
320
321 #ifdef IPLEN_FLIPPED
322 ip->ip_len = ip->ip_len - taillen;
323 #else
324 ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
325 #endif
326
327 /* was it transmitted over the IPsec tunnel SA? */
328 if (ipsec4_tunnel_validate(ip, nxt, sav)) {
329 /*
330 * strip off all the headers that precedes ESP header.
331 * IP4 xx ESP IP4' payload -> IP4' payload
332 *
333 * XXX more sanity checks
334 * XXX relationship with gif?
335 */
336 u_int8_t tos;
337
338 tos = ip->ip_tos;
339 m_adj(m, off + esplen + ivlen);
340 if (m->m_len < sizeof(*ip)) {
341 m = m_pullup(m, sizeof(*ip));
342 if (!m) {
343 ipsecstat.in_inval++;
344 goto bad;
345 }
346 }
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++;
356 goto bad;
357 }
358
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++;
363 goto bad;
364 }
365 #endif
366
367 key_sa_recordxfer(sav, m);
368
369 s = splimp();
370 if (IF_QFULL(&ipintrq)) {
371 ipsecstat.in_inval++;
372 goto bad;
373 }
374 IF_ENQUEUE(&ipintrq, m);
375 m = NULL;
376 schednetisr(NETISR_IP); /*can be skipped but to make sure*/
377 splx(s);
378 nxt = IPPROTO_DONE;
379 } else {
380 /*
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.
384 */
385 size_t stripsiz;
386
387 stripsiz = esplen + ivlen;
388
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;
394
395 ip = mtod(m, struct ip *);
396 #ifdef IPLEN_FLIPPED
397 ip->ip_len = ip->ip_len - stripsiz;
398 #else
399 ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
400 #endif
401 ip->ip_p = nxt;
402
403 key_sa_recordxfer(sav, m);
404
405 if (nxt != IPPROTO_DONE)
406 (*ip_protox[nxt]->pr_input)(m, off);
407 else
408 m_freem(m);
409 m = NULL;
410 }
411
412 if (sav) {
413 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
414 printf("DP esp4_input call free SA:%p\n", sav));
415 key_freesav(sav);
416 }
417 ipsecstat.in_success++;
418 return;
419
420 bad:
421 if (sav) {
422 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
423 printf("DP esp4_input call free SA:%p\n", sav));
424 key_freesav(sav);
425 }
426 if (m)
427 m_freem(m);
428 return;
429 }
430 #endif /* INET */
431
432 #if INET6
433 int
434 esp6_input(mp, offp, proto)
435 struct mbuf **mp;
436 int *offp, proto;
437 {
438 struct mbuf *m = *mp;
439 int off = *offp;
440 struct ip6_hdr *ip6;
441 struct esp *esp;
442 struct esptail esptail;
443 u_int32_t spi;
444 struct secasvar *sav = NULL;
445 size_t taillen;
446 u_int16_t nxt;
447 struct esp_algorithm *algo;
448 int ivlen;
449 size_t esplen;
450 int s;
451
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++;
457 goto bad;
458 }
459
460 #ifndef PULLDOWN_TEST
461 IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, IPPROTO_DONE);
462 esp = (struct esp *)(mtod(m, caddr_t) + off);
463 #else
464 IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
465 if (esp == NULL) {
466 ipsec6stat.in_inval++;
467 return IPPROTO_DONE;
468 }
469 #endif
470 ip6 = mtod(m, struct ip6_hdr *);
471
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++;
476 goto bad;
477 }
478
479 /* find the sassoc. */
480 spi = esp->esp_spi;
481
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++;
489 goto bad;
490 }
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) {
495 ipseclog((LOG_DEBUG,
496 "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
497 (u_int32_t)ntohl(spi)));
498 ipsec6stat.in_badspi++;
499 goto bad;
500 }
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++;
506 goto bad;
507 }
508
509 algo = &esp_algorithms[sav->alg_enc]; /*XXX*/
510
511 /* check if we have proper ivlen information */
512 ivlen = sav->ivlen;
513 if (ivlen < 0) {
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++;
517 goto bad;
518 }
519
520 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
521 && (sav->alg_auth && sav->key_auth)))
522 goto noreplaycheck;
523
524 if (sav->alg_auth == SADB_AALG_NULL)
525 goto noreplaycheck;
526
527 /*
528 * check for sequence number.
529 */
530 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
531 ; /*okey*/
532 else {
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)));
537 goto bad;
538 }
539
540 /* check ICV */
541 {
542 u_char sum0[AH_MAXSUMSIZE];
543 u_char sum[AH_MAXSUMSIZE];
544 struct ah_algorithm *sumalgo;
545 size_t siz;
546
547 sumalgo = &ah_algorithms[sav->alg_auth];
548 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
549 if (AH_MAXSUMSIZE < siz) {
550 ipseclog((LOG_DEBUG,
551 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
552 (u_long)siz));
553 ipsec6stat.in_inval++;
554 goto bad;
555 }
556
557 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
558
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++;
563 goto bad;
564 }
565
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++;
570 goto bad;
571 }
572
573 /* strip off the authentication data */
574 m_adj(m, -siz);
575 ip6 = mtod(m, struct ip6_hdr *);
576 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
577
578 m->m_flags |= M_AUTHIPDGM;
579 ipsec6stat.in_espauthsucc++;
580 }
581
582 /*
583 * update sequence number.
584 */
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++;
588 goto bad;
589 }
590 }
591
592 noreplaycheck:
593
594 /* process main esp header. */
595 if (sav->flags & SADB_X_EXT_OLD) {
596 /* RFC 1827 */
597 esplen = sizeof(struct esp);
598 } else {
599 /* RFC 2406 */
600 if (sav->flags & SADB_X_EXT_DERIV)
601 esplen = sizeof(struct esp);
602 else
603 esplen = sizeof(struct newesp);
604 }
605
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++;
610 goto bad;
611 }
612
613 #ifndef PULLDOWN_TEST
614 IP6_EXTHDR_CHECK(m, off, esplen + ivlen, IPPROTO_DONE); /*XXX*/
615 #else
616 IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
617 if (esp == NULL) {
618 ipsec6stat.in_inval++;
619 m = NULL;
620 goto bad;
621 }
622 #endif
623 ip6 = mtod(m, struct ip6_hdr *); /*set it again just in case*/
624
625 /*
626 * decrypt the packet.
627 */
628 if (!algo->decrypt)
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++;
634 goto bad;
635 }
636 ipsec6stat.in_esphist[sav->alg_enc]++;
637
638 m->m_flags |= M_DECRYPTED;
639
640 /*
641 * find the trailer of the ESP.
642 */
643 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
644 (caddr_t)&esptail);
645 nxt = esptail.esp_nxt;
646 taillen = esptail.esp_padlen + sizeof(esptail);
647
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++;
654 goto bad;
655 }
656
657 /* strip off the trailing pad area. */
658 m_adj(m, -taillen);
659
660 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
661
662 /* was it transmitted over the IPsec tunnel SA? */
663 if (ipsec6_tunnel_validate(ip6, nxt, sav)) {
664 /*
665 * strip off all the headers that precedes ESP header.
666 * IP6 xx ESP IP6' payload -> IP6' payload
667 *
668 * XXX more sanity checks
669 * XXX relationship with gif?
670 */
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
676 /*
677 * m_pullup is prohibited in KAME IPv6 input processing
678 * but there's no other way!
679 */
680 #else
681 /* okay to pullup in m_pulldown style */
682 #endif
683 m = m_pullup(m, sizeof(*ip6));
684 if (!m) {
685 ipsec6stat.in_inval++;
686 goto bad;
687 }
688 }
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++;
699 goto bad;
700 }
701
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++;
706 goto bad;
707 }
708 #endif
709
710 key_sa_recordxfer(sav, m);
711
712 s = splimp();
713 if (IF_QFULL(&ip6intrq)) {
714 ipsec6stat.in_inval++;
715 goto bad;
716 }
717 IF_ENQUEUE(&ip6intrq, m);
718 m = NULL;
719 schednetisr(NETISR_IPV6); /*can be skipped but to make sure*/
720 splx(s);
721 nxt = IPPROTO_DONE;
722 } else {
723 /*
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.
727 */
728 size_t stripsiz;
729 char *prvnxtp;
730
731 /*
732 * Set the next header field of the previous header correctly.
733 */
734 prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
735 *prvnxtp = nxt;
736
737 stripsiz = esplen + ivlen;
738
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;
745 } else {
746 /*
747 * this comes with no copy if the boundary is on
748 * cluster
749 */
750 struct mbuf *n;
751
752 n = m_split(m, off, M_DONTWAIT);
753 if (n == NULL) {
754 /* m is retained by m_split */
755 goto bad;
756 }
757 m_adj(n, stripsiz);
758 m_cat(m, n);
759 /* m_cat does not update m_pkthdr.len */
760 m->m_pkthdr.len += n->m_pkthdr.len;
761 }
762
763 ip6 = mtod(m, struct ip6_hdr *);
764 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
765
766 key_sa_recordxfer(sav, m);
767 }
768
769 *offp = off;
770 *mp = m;
771
772 if (sav) {
773 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
774 printf("DP esp6_input call free SA:%p\n", sav));
775 key_freesav(sav);
776 }
777 ipsec6stat.in_success++;
778 return nxt;
779
780 bad:
781 if (sav) {
782 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
783 printf("DP esp6_input call free SA:%p\n", sav));
784 key_freesav(sav);
785 }
786 if (m)
787 m_freem(m);
788 return IPPROTO_DONE;
789 }
790 #endif /* INET6 */