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