proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / netinet6 / esp_input.c
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.2 2003/06/17 04:28:51 dillon Exp $ */
3 /*      $KAME: esp_input.c,v 1.62 2002/01/07 11:39:57 kjc Exp $ */
4
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
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.
20  *
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
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * RFC1827/2406 Encapsulated Security Payload.
36  */
37
38 #include "opt_inet.h"
39 #include "opt_inet6.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/mbuf.h>
44 #include <sys/domain.h>
45 #include <sys/protosw.h>
46 #include <sys/socket.h>
47 #include <sys/errno.h>
48 #include <sys/time.h>
49 #include <sys/syslog.h>
50
51 #include <net/if.h>
52 #include <net/route.h>
53 #include <net/netisr.h>
54 #include <machine/cpu.h>
55
56 #include <netinet/in.h>
57 #include <netinet/in_systm.h>
58 #include <netinet/ip.h>
59 #include <netinet/ip_var.h>
60 #include <netinet/in_var.h>
61 #include <netinet/ip_ecn.h>
62 #ifdef INET6
63 #include <netinet6/ip6_ecn.h>
64 #endif
65
66 #ifdef INET6
67 #include <netinet/ip6.h>
68 #include <netinet6/in6_pcb.h>
69 #include <netinet6/ip6_var.h>
70 #include <netinet/icmp6.h>
71 #include <netinet6/ip6protosw.h>
72 #endif
73
74 #include <netinet6/ipsec.h>
75 #ifdef INET6
76 #include <netinet6/ipsec6.h>
77 #endif
78 #include <netinet6/ah.h>
79 #ifdef INET6
80 #include <netinet6/ah6.h>
81 #endif
82 #include <netinet6/esp.h>
83 #ifdef INET6
84 #include <netinet6/esp6.h>
85 #endif
86 #include <netkey/key.h>
87 #include <netkey/keydb.h>
88 #include <netkey/key_debug.h>
89
90 #include <machine/stdarg.h>
91
92 #include <net/net_osdep.h>
93
94 #define IPLEN_FLIPPED
95
96 #define ESPMAXLEN \
97         (sizeof(struct esp) < sizeof(struct newesp) \
98                 ? sizeof(struct newesp) : sizeof(struct esp))
99
100 #ifdef INET
101 #include <netinet/ipprotosw.h>
102 extern struct ipprotosw inetsw[];
103
104 void
105 #if __STDC__
106 esp4_input(struct mbuf *m, ...)
107 #else
108 esp4_input(m, va_alist)
109         struct mbuf *m;
110         va_dcl
111 #endif
112 {
113         struct ip *ip;
114         struct esp *esp;
115         struct esptail esptail;
116         u_int32_t spi;
117         struct secasvar *sav = NULL;
118         size_t taillen;
119         u_int16_t nxt;
120         const struct esp_algorithm *algo;
121         int ivlen;
122         size_t hlen;
123         size_t esplen;
124         int s;
125         va_list ap;
126         int off, proto;
127
128         va_start(ap, m);
129         off = va_arg(ap, int);
130         proto = va_arg(ap, int);
131         va_end(ap);
132
133         /* sanity check for alignment. */
134         if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
135                 ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
136                         "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
137                 ipsecstat.in_inval++;
138                 goto bad;
139         }
140
141         if (m->m_len < off + ESPMAXLEN) {
142                 m = m_pullup(m, off + ESPMAXLEN);
143                 if (!m) {
144                         ipseclog((LOG_DEBUG,
145                             "IPv4 ESP input: can't pullup in esp4_input\n"));
146                         ipsecstat.in_inval++;
147                         goto bad;
148                 }
149         }
150
151         ip = mtod(m, struct ip *);
152         esp = (struct esp *)(((u_int8_t *)ip) + off);
153 #ifdef _IP_VHL
154         hlen = IP_VHL_HL(ip->ip_vhl) << 2;
155 #else
156         hlen = ip->ip_hl << 2;
157 #endif
158
159         /* find the sassoc. */
160         spi = esp->esp_spi;
161
162         if ((sav = key_allocsa(AF_INET,
163                               (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
164                               IPPROTO_ESP, spi)) == 0) {
165                 ipseclog((LOG_WARNING,
166                     "IPv4 ESP input: no key association found for spi %u\n",
167                     (u_int32_t)ntohl(spi)));
168                 ipsecstat.in_nosa++;
169                 goto bad;
170         }
171         KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
172                 printf("DP esp4_input called to allocate SA:%p\n", sav));
173         if (sav->state != SADB_SASTATE_MATURE
174          && sav->state != SADB_SASTATE_DYING) {
175                 ipseclog((LOG_DEBUG,
176                     "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
177                     (u_int32_t)ntohl(spi)));
178                 ipsecstat.in_badspi++;
179                 goto bad;
180         }
181         algo = esp_algorithm_lookup(sav->alg_enc);
182         if (!algo) {
183                 ipseclog((LOG_DEBUG, "IPv4 ESP input: "
184                     "unsupported encryption algorithm for spi %u\n",
185                     (u_int32_t)ntohl(spi)));
186                 ipsecstat.in_badspi++;
187                 goto bad;
188         }
189
190         /* check if we have proper ivlen information */
191         ivlen = sav->ivlen;
192         if (ivlen < 0) {
193                 ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n",
194                     ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
195                 ipsecstat.in_inval++;
196                 goto bad;
197         }
198
199         if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
200          && (sav->alg_auth && sav->key_auth)))
201                 goto noreplaycheck;
202
203         if (sav->alg_auth == SADB_X_AALG_NULL ||
204             sav->alg_auth == SADB_AALG_NONE)
205                 goto noreplaycheck;
206
207         /*
208          * check for sequence number.
209          */
210         if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
211                 ; /* okey */
212         else {
213                 ipsecstat.in_espreplay++;
214                 ipseclog((LOG_WARNING,
215                     "replay packet in IPv4 ESP input: %s %s\n",
216                     ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
217                 goto bad;
218         }
219
220         /* check ICV */
221     {
222         u_char sum0[AH_MAXSUMSIZE];
223         u_char sum[AH_MAXSUMSIZE];
224         const struct ah_algorithm *sumalgo;
225         size_t siz;
226
227         sumalgo = ah_algorithm_lookup(sav->alg_auth);
228         if (!sumalgo)
229                 goto noreplaycheck;
230         siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
231         if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
232                 ipsecstat.in_inval++;
233                 goto bad;
234         }
235         if (AH_MAXSUMSIZE < siz) {
236                 ipseclog((LOG_DEBUG,
237                     "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
238                     (u_long)siz));
239                 ipsecstat.in_inval++;
240                 goto bad;
241         }
242
243         m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
244
245         if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
246                 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
247                     ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
248                 ipsecstat.in_espauthfail++;
249                 goto bad;
250         }
251
252         if (bcmp(sum0, sum, siz) != 0) {
253                 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
254                     ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
255                 ipsecstat.in_espauthfail++;
256                 goto bad;
257         }
258
259         /* strip off the authentication data */
260         m_adj(m, -siz);
261         ip = mtod(m, struct ip *);
262 #ifdef IPLEN_FLIPPED
263         ip->ip_len = ip->ip_len - siz;
264 #else
265         ip->ip_len = htons(ntohs(ip->ip_len) - siz);
266 #endif
267         m->m_flags |= M_AUTHIPDGM;
268         ipsecstat.in_espauthsucc++;
269     }
270
271         /*
272          * update sequence number.
273          */
274         if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
275                 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
276                         ipsecstat.in_espreplay++;
277                         goto bad;
278                 }
279         }
280
281 noreplaycheck:
282
283         /* process main esp header. */
284         if (sav->flags & SADB_X_EXT_OLD) {
285                 /* RFC 1827 */
286                 esplen = sizeof(struct esp);
287         } else {
288                 /* RFC 2406 */
289                 if (sav->flags & SADB_X_EXT_DERIV)
290                         esplen = sizeof(struct esp);
291                 else
292                         esplen = sizeof(struct newesp);
293         }
294
295         if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
296                 ipseclog((LOG_WARNING,
297                     "IPv4 ESP input: packet too short\n"));
298                 ipsecstat.in_inval++;
299                 goto bad;
300         }
301
302         if (m->m_len < off + esplen + ivlen) {
303                 m = m_pullup(m, off + esplen + ivlen);
304                 if (!m) {
305                         ipseclog((LOG_DEBUG,
306                             "IPv4 ESP input: can't pullup in esp4_input\n"));
307                         ipsecstat.in_inval++;
308                         goto bad;
309                 }
310         }
311
312         /*
313          * pre-compute and cache intermediate key
314          */
315         if (esp_schedule(algo, sav) != 0) {
316                 ipsecstat.in_inval++;
317                 goto bad;
318         }
319
320         /*
321          * decrypt the packet.
322          */
323         if (!algo->decrypt)
324                 panic("internal error: no decrypt function");
325         if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
326                 /* m is already freed */
327                 m = NULL;
328                 ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
329                     ipsec_logsastr(sav)));
330                 ipsecstat.in_inval++;
331                 goto bad;
332         }
333         ipsecstat.in_esphist[sav->alg_enc]++;
334
335         m->m_flags |= M_DECRYPTED;
336
337         /*
338          * find the trailer of the ESP.
339          */
340         m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
341              (caddr_t)&esptail);
342         nxt = esptail.esp_nxt;
343         taillen = esptail.esp_padlen + sizeof(esptail);
344
345         if (m->m_pkthdr.len < taillen
346          || m->m_pkthdr.len - taillen < hlen) { /* ? */
347                 ipseclog((LOG_WARNING,
348                     "bad pad length in IPv4 ESP input: %s %s\n",
349                     ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
350                 ipsecstat.in_inval++;
351                 goto bad;
352         }
353
354         /* strip off the trailing pad area. */
355         m_adj(m, -taillen);
356
357 #ifdef IPLEN_FLIPPED
358         ip->ip_len = ip->ip_len - taillen;
359 #else
360         ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
361 #endif
362
363         /* was it transmitted over the IPsec tunnel SA? */
364         if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
365                 /*
366                  * strip off all the headers that precedes ESP header.
367                  *      IP4 xx ESP IP4' payload -> IP4' payload
368                  *
369                  * XXX more sanity checks
370                  * XXX relationship with gif?
371                  */
372                 u_int8_t tos;
373
374                 tos = ip->ip_tos;
375                 m_adj(m, off + esplen + ivlen);
376                 if (m->m_len < sizeof(*ip)) {
377                         m = m_pullup(m, sizeof(*ip));
378                         if (!m) {
379                                 ipsecstat.in_inval++;
380                                 goto bad;
381                         }
382                 }
383                 ip = mtod(m, struct ip *);
384                 /* ECN consideration. */
385                 ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
386                 if (!key_checktunnelsanity(sav, AF_INET,
387                             (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
388                         ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
389                             "in IPv4 ESP input: %s %s\n",
390                             ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
391                         ipsecstat.in_inval++;
392                         goto bad;
393                 }
394
395                 key_sa_recordxfer(sav, m);
396                 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
397                     ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
398                         ipsecstat.in_nomem++;
399                         goto bad;
400                 }
401
402                 s = splimp();
403                 if (IF_QFULL(&ipintrq)) {
404                         ipsecstat.in_inval++;
405                         splx(s);
406                         goto bad;
407                 }
408                 IF_ENQUEUE(&ipintrq, m);
409                 m = NULL;
410                 schednetisr(NETISR_IP); /* can be skipped but to make sure */
411                 splx(s);
412                 nxt = IPPROTO_DONE;
413         } else {
414                 /*
415                  * strip off ESP header and IV.
416                  * even in m_pulldown case, we need to strip off ESP so that
417                  * we can always compute checksum for AH correctly.
418                  */
419                 size_t stripsiz;
420
421                 stripsiz = esplen + ivlen;
422
423                 ip = mtod(m, struct ip *);
424                 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
425                 m->m_data += stripsiz;
426                 m->m_len -= stripsiz;
427                 m->m_pkthdr.len -= stripsiz;
428
429                 ip = mtod(m, struct ip *);
430 #ifdef IPLEN_FLIPPED
431                 ip->ip_len = ip->ip_len - stripsiz;
432 #else
433                 ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
434 #endif
435                 ip->ip_p = nxt;
436
437                 key_sa_recordxfer(sav, m);
438                 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
439                         ipsecstat.in_nomem++;
440                         goto bad;
441                 }
442
443                 if (nxt != IPPROTO_DONE) {
444                         if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
445                             ipsec4_in_reject(m, NULL)) {
446                                 ipsecstat.in_polvio++;
447                                 goto bad;
448                         }
449                         (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
450                 } else
451                         m_freem(m);
452                 m = NULL;
453         }
454
455         if (sav) {
456                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
457                         printf("DP esp4_input call free SA:%p\n", sav));
458                 key_freesav(sav);
459         }
460         ipsecstat.in_success++;
461         return;
462
463 bad:
464         if (sav) {
465                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
466                         printf("DP esp4_input call free SA:%p\n", sav));
467                 key_freesav(sav);
468         }
469         if (m)
470                 m_freem(m);
471         return;
472 }
473 #endif /* INET */
474
475 #ifdef INET6
476 int
477 esp6_input(mp, offp, proto)
478         struct mbuf **mp;
479         int *offp, proto;
480 {
481         struct mbuf *m = *mp;
482         int off = *offp;
483         struct ip6_hdr *ip6;
484         struct esp *esp;
485         struct esptail esptail;
486         u_int32_t spi;
487         struct secasvar *sav = NULL;
488         size_t taillen;
489         u_int16_t nxt;
490         const struct esp_algorithm *algo;
491         int ivlen;
492         size_t esplen;
493         int s;
494
495         /* sanity check for alignment. */
496         if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
497                 ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
498                         "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
499                 ipsec6stat.in_inval++;
500                 goto bad;
501         }
502
503 #ifndef PULLDOWN_TEST
504         IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, IPPROTO_DONE);
505         esp = (struct esp *)(mtod(m, caddr_t) + off);
506 #else
507         IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
508         if (esp == NULL) {
509                 ipsec6stat.in_inval++;
510                 return IPPROTO_DONE;
511         }
512 #endif
513         ip6 = mtod(m, struct ip6_hdr *);
514
515         if (ntohs(ip6->ip6_plen) == 0) {
516                 ipseclog((LOG_ERR, "IPv6 ESP input: "
517                     "ESP with IPv6 jumbogram is not supported.\n"));
518                 ipsec6stat.in_inval++;
519                 goto bad;
520         }
521
522         /* find the sassoc. */
523         spi = esp->esp_spi;
524
525         if ((sav = key_allocsa(AF_INET6,
526                               (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
527                               IPPROTO_ESP, spi)) == 0) {
528                 ipseclog((LOG_WARNING,
529                     "IPv6 ESP input: no key association found for spi %u\n",
530                     (u_int32_t)ntohl(spi)));
531                 ipsec6stat.in_nosa++;
532                 goto bad;
533         }
534         KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
535                 printf("DP esp6_input called to allocate SA:%p\n", sav));
536         if (sav->state != SADB_SASTATE_MATURE
537          && sav->state != SADB_SASTATE_DYING) {
538                 ipseclog((LOG_DEBUG,
539                     "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
540                     (u_int32_t)ntohl(spi)));
541                 ipsec6stat.in_badspi++;
542                 goto bad;
543         }
544         algo = esp_algorithm_lookup(sav->alg_enc);
545         if (!algo) {
546                 ipseclog((LOG_DEBUG, "IPv6 ESP input: "
547                     "unsupported encryption algorithm for spi %u\n",
548                     (u_int32_t)ntohl(spi)));
549                 ipsec6stat.in_badspi++;
550                 goto bad;
551         }
552
553         /* check if we have proper ivlen information */
554         ivlen = sav->ivlen;
555         if (ivlen < 0) {
556                 ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n",
557                     ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
558                 ipsec6stat.in_badspi++;
559                 goto bad;
560         }
561
562         if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
563          && (sav->alg_auth && sav->key_auth)))
564                 goto noreplaycheck;
565
566         if (sav->alg_auth == SADB_X_AALG_NULL ||
567             sav->alg_auth == SADB_AALG_NONE)
568                 goto noreplaycheck;
569
570         /*
571          * check for sequence number.
572          */
573         if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
574                 ; /* okey */
575         else {
576                 ipsec6stat.in_espreplay++;
577                 ipseclog((LOG_WARNING,
578                     "replay packet in IPv6 ESP input: %s %s\n",
579                     ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
580                 goto bad;
581         }
582
583         /* check ICV */
584     {
585         u_char sum0[AH_MAXSUMSIZE];
586         u_char sum[AH_MAXSUMSIZE];
587         const struct ah_algorithm *sumalgo;
588         size_t siz;
589
590         sumalgo = ah_algorithm_lookup(sav->alg_auth);
591         if (!sumalgo)
592                 goto noreplaycheck;
593         siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
594         if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
595                 ipsecstat.in_inval++;
596                 goto bad;
597         }
598         if (AH_MAXSUMSIZE < siz) {
599                 ipseclog((LOG_DEBUG,
600                     "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
601                     (u_long)siz));
602                 ipsec6stat.in_inval++;
603                 goto bad;
604         }
605
606         m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
607
608         if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
609                 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
610                     ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
611                 ipsec6stat.in_espauthfail++;
612                 goto bad;
613         }
614
615         if (bcmp(sum0, sum, siz) != 0) {
616                 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
617                     ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
618                 ipsec6stat.in_espauthfail++;
619                 goto bad;
620         }
621
622         /* strip off the authentication data */
623         m_adj(m, -siz);
624         ip6 = mtod(m, struct ip6_hdr *);
625         ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
626
627         m->m_flags |= M_AUTHIPDGM;
628         ipsec6stat.in_espauthsucc++;
629     }
630
631         /*
632          * update sequence number.
633          */
634         if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
635                 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
636                         ipsec6stat.in_espreplay++;
637                         goto bad;
638                 }
639         }
640
641 noreplaycheck:
642
643         /* process main esp header. */
644         if (sav->flags & SADB_X_EXT_OLD) {
645                 /* RFC 1827 */
646                 esplen = sizeof(struct esp);
647         } else {
648                 /* RFC 2406 */
649                 if (sav->flags & SADB_X_EXT_DERIV)
650                         esplen = sizeof(struct esp);
651                 else
652                         esplen = sizeof(struct newesp);
653         }
654
655         if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
656                 ipseclog((LOG_WARNING,
657                     "IPv6 ESP input: packet too short\n"));
658                 ipsec6stat.in_inval++;
659                 goto bad;
660         }
661
662 #ifndef PULLDOWN_TEST
663         IP6_EXTHDR_CHECK(m, off, esplen + ivlen, IPPROTO_DONE); /* XXX */
664 #else
665         IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
666         if (esp == NULL) {
667                 ipsec6stat.in_inval++;
668                 m = NULL;
669                 goto bad;
670         }
671 #endif
672         ip6 = mtod(m, struct ip6_hdr *);        /* set it again just in case */
673
674         /*
675          * pre-compute and cache intermediate key
676          */
677         if (esp_schedule(algo, sav) != 0) {
678                 ipsec6stat.in_inval++;
679                 goto bad;
680         }
681
682         /*
683          * decrypt the packet.
684          */
685         if (!algo->decrypt)
686                 panic("internal error: no decrypt function");
687         if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
688                 /* m is already freed */
689                 m = NULL;
690                 ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
691                     ipsec_logsastr(sav)));
692                 ipsec6stat.in_inval++;
693                 goto bad;
694         }
695         ipsec6stat.in_esphist[sav->alg_enc]++;
696
697         m->m_flags |= M_DECRYPTED;
698
699         /*
700          * find the trailer of the ESP.
701          */
702         m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
703              (caddr_t)&esptail);
704         nxt = esptail.esp_nxt;
705         taillen = esptail.esp_padlen + sizeof(esptail);
706
707         if (m->m_pkthdr.len < taillen
708          || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) {       /* ? */
709                 ipseclog((LOG_WARNING,
710                     "bad pad length in IPv6 ESP input: %s %s\n",
711                     ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
712                 ipsec6stat.in_inval++;
713                 goto bad;
714         }
715
716         /* strip off the trailing pad area. */
717         m_adj(m, -taillen);
718
719         ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
720
721         /* was it transmitted over the IPsec tunnel SA? */
722         if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
723                 /*
724                  * strip off all the headers that precedes ESP header.
725                  *      IP6 xx ESP IP6' payload -> IP6' payload
726                  *
727                  * XXX more sanity checks
728                  * XXX relationship with gif?
729                  */
730                 u_int32_t flowinfo;     /* net endian */
731                 flowinfo = ip6->ip6_flow;
732                 m_adj(m, off + esplen + ivlen);
733                 if (m->m_len < sizeof(*ip6)) {
734 #ifndef PULLDOWN_TEST
735                         /*
736                          * m_pullup is prohibited in KAME IPv6 input processing
737                          * but there's no other way!
738                          */
739 #else
740                         /* okay to pullup in m_pulldown style */
741 #endif
742                         m = m_pullup(m, sizeof(*ip6));
743                         if (!m) {
744                                 ipsec6stat.in_inval++;
745                                 goto bad;
746                         }
747                 }
748                 ip6 = mtod(m, struct ip6_hdr *);
749                 /* ECN consideration. */
750                 ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
751                 if (!key_checktunnelsanity(sav, AF_INET6,
752                             (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
753                         ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
754                             "in IPv6 ESP input: %s %s\n",
755                             ipsec6_logpacketstr(ip6, spi),
756                             ipsec_logsastr(sav)));
757                         ipsec6stat.in_inval++;
758                         goto bad;
759                 }
760
761                 key_sa_recordxfer(sav, m);
762                 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || 
763                     ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
764                         ipsec6stat.in_nomem++;
765                         goto bad;
766                 }
767
768                 s = splimp();
769                 if (IF_QFULL(&ip6intrq)) {
770                         ipsec6stat.in_inval++;
771                         splx(s);
772                         goto bad;
773                 }
774                 IF_ENQUEUE(&ip6intrq, m);
775                 m = NULL;
776                 schednetisr(NETISR_IPV6); /* can be skipped but to make sure */
777                 splx(s);
778                 nxt = IPPROTO_DONE;
779         } else {
780                 /*
781                  * strip off ESP header and IV.
782                  * even in m_pulldown case, we need to strip off ESP so that
783                  * we can always compute checksum for AH correctly.
784                  */
785                 size_t stripsiz;
786                 char *prvnxtp;
787
788                 /*
789                  * Set the next header field of the previous header correctly.
790                  */
791                 prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
792                 *prvnxtp = nxt;
793
794                 stripsiz = esplen + ivlen;
795
796                 ip6 = mtod(m, struct ip6_hdr *);
797                 if (m->m_len >= stripsiz + off) {
798                         ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
799                         m->m_data += stripsiz;
800                         m->m_len -= stripsiz;
801                         m->m_pkthdr.len -= stripsiz;
802                 } else {
803                         /*
804                          * this comes with no copy if the boundary is on
805                          * cluster
806                          */
807                         struct mbuf *n;
808
809                         n = m_split(m, off, M_DONTWAIT);
810                         if (n == NULL) {
811                                 /* m is retained by m_split */
812                                 goto bad;
813                         }
814                         m_adj(n, stripsiz);
815                         m_cat(m, n);
816                         /* m_cat does not update m_pkthdr.len */
817                         m->m_pkthdr.len += n->m_pkthdr.len;
818                 }
819
820 #ifndef PULLDOWN_TEST
821                 /*
822                  * KAME requires that the packet to be contiguous on the
823                  * mbuf.  We need to make that sure.
824                  * this kind of code should be avoided.
825                  * XXX other conditions to avoid running this part?
826                  */
827                 if (m->m_len != m->m_pkthdr.len) {
828                         struct mbuf *n = NULL;
829                         int maxlen;
830
831                         MGETHDR(n, M_DONTWAIT, MT_HEADER);
832                         maxlen = MHLEN;
833                         if (n)
834                                 M_MOVE_PKTHDR(n, m);
835                         if (n && n->m_pkthdr.len > maxlen) {
836                                 MCLGET(n, M_DONTWAIT);
837                                 maxlen = MCLBYTES;
838                                 if ((n->m_flags & M_EXT) == 0) {
839                                         m_free(n);
840                                         n = NULL;
841                                 }
842                         }
843                         if (!n) {
844                                 printf("esp6_input: mbuf allocation failed\n");
845                                 goto bad;
846                         }
847
848                         if (n->m_pkthdr.len <= maxlen) {
849                                 m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t));
850                                 n->m_len = n->m_pkthdr.len;
851                                 n->m_next = NULL;
852                                 m_freem(m);
853                         } else {
854                                 m_copydata(m, 0, maxlen, mtod(n, caddr_t));
855                                 n->m_len = maxlen;
856                                 n->m_next = m;
857                                 m_adj(m, maxlen);
858                         }
859                         m = n;
860                 }
861 #endif
862
863                 ip6 = mtod(m, struct ip6_hdr *);
864                 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
865
866                 key_sa_recordxfer(sav, m);
867                 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
868                         ipsec6stat.in_nomem++;
869                         goto bad;
870                 }
871         }
872
873         *offp = off;
874         *mp = m;
875
876         if (sav) {
877                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
878                         printf("DP esp6_input call free SA:%p\n", sav));
879                 key_freesav(sav);
880         }
881         ipsec6stat.in_success++;
882         return nxt;
883
884 bad:
885         if (sav) {
886                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
887                         printf("DP esp6_input call free SA:%p\n", sav));
888                 key_freesav(sav);
889         }
890         if (m)
891                 m_freem(m);
892         return IPPROTO_DONE;
893 }
894
895 void
896 esp6_ctlinput(cmd, sa, d)
897         int cmd;
898         struct sockaddr *sa;
899         void *d;
900 {
901         const struct newesp *espp;
902         struct newesp esp;
903         struct ip6ctlparam *ip6cp = NULL, ip6cp1;
904         struct secasvar *sav;
905         struct ip6_hdr *ip6;
906         struct mbuf *m;
907         int off;
908         struct sockaddr_in6 *sa6_src, *sa6_dst;
909
910         if (sa->sa_family != AF_INET6 ||
911             sa->sa_len != sizeof(struct sockaddr_in6))
912                 return;
913         if ((unsigned)cmd >= PRC_NCMDS)
914                 return;
915
916         /* if the parameter is from icmp6, decode it. */
917         if (d != NULL) {
918                 ip6cp = (struct ip6ctlparam *)d;
919                 m = ip6cp->ip6c_m;
920                 ip6 = ip6cp->ip6c_ip6;
921                 off = ip6cp->ip6c_off;
922         } else {
923                 m = NULL;
924                 ip6 = NULL;
925         }
926
927         if (ip6) {
928                 /*
929                  * Notify the error to all possible sockets via pfctlinput2.
930                  * Since the upper layer information (such as protocol type,
931                  * source and destination ports) is embedded in the encrypted
932                  * data and might have been cut, we can't directly call
933                  * an upper layer ctlinput function. However, the pcbnotify
934                  * function will consider source and destination addresses
935                  * as well as the flow info value, and may be able to find
936                  * some PCB that should be notified.
937                  * Although pfctlinput2 will call esp6_ctlinput(), there is
938                  * no possibility of an infinite loop of function calls,
939                  * because we don't pass the inner IPv6 header.
940                  */
941                 bzero(&ip6cp1, sizeof(ip6cp1));
942                 ip6cp1.ip6c_src = ip6cp->ip6c_src;
943                 pfctlinput2(cmd, sa, (void *)&ip6cp1);
944
945                 /*
946                  * Then go to special cases that need ESP header information.
947                  * XXX: We assume that when ip6 is non NULL,
948                  * M and OFF are valid.
949                  */
950
951                 /* check if we can safely examine src and dst ports */
952                 if (m->m_pkthdr.len < off + sizeof(esp))
953                         return;
954
955                 if (m->m_len < off + sizeof(esp)) {
956                         /*
957                          * this should be rare case,
958                          * so we compromise on this copy...
959                          */
960                         m_copydata(m, off, sizeof(esp), (caddr_t)&esp);
961                         espp = &esp;
962                 } else
963                         espp = (struct newesp*)(mtod(m, caddr_t) + off);
964
965                 if (cmd == PRC_MSGSIZE) {
966                         int valid = 0;
967
968                         /*
969                          * Check to see if we have a valid SA corresponding to
970                          * the address in the ICMP message payload.
971                          */
972                         sa6_src = ip6cp->ip6c_src;
973                         sa6_dst = (struct sockaddr_in6 *)sa;
974                         sav = key_allocsa(AF_INET6,
975                                           (caddr_t)&sa6_src->sin6_addr,
976                                           (caddr_t)&sa6_dst->sin6_addr,
977                                           IPPROTO_ESP, espp->esp_spi);
978                         if (sav) {
979                                 if (sav->state == SADB_SASTATE_MATURE ||
980                                     sav->state == SADB_SASTATE_DYING)
981                                         valid++;
982                                 key_freesav(sav);
983                         }
984
985                         /* XXX Further validation? */
986
987                         /*
988                          * Depending on the value of "valid" and routing table
989                          * size (mtudisc_{hi,lo}wat), we will:
990                          * - recalcurate the new MTU and create the
991                          *   corresponding routing entry, or
992                          * - ignore the MTU change notification.
993                          */
994                         icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
995                 }
996         } else {
997                 /* we normally notify any pcb here */
998         }
999 }
1000 #endif /* INET6 */