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