The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netipsec/ipsec_input.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $        */
    2 /*-
    3  * The authors of this code are John Ioannidis (ji@tla.org),
    4  * Angelos D. Keromytis (kermit@csd.uch.gr) and
    5  * Niels Provos (provos@physnet.uni-hamburg.de).
    6  *
    7  * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
    8  * in November 1995.
    9  *
   10  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
   11  * by Angelos D. Keromytis.
   12  *
   13  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
   14  * and Niels Provos.
   15  *
   16  * Additional features in 1999 by Angelos D. Keromytis.
   17  *
   18  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
   19  * Angelos D. Keromytis and Niels Provos.
   20  * Copyright (c) 2001, Angelos D. Keromytis.
   21  * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
   22  *
   23  * Permission to use, copy, and modify this software with or without fee
   24  * is hereby granted, provided that this entire notice is included in
   25  * all copies of any software which is or includes a copy or
   26  * modification of this software.
   27  * You may use this code under the GNU public license if you so wish. Please
   28  * contribute changes back to the authors under this freer than GPL license
   29  * so that we may further the use of strong encryption without limitations to
   30  * all.
   31  *
   32  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
   33  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
   34  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
   35  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
   36  * PURPOSE.
   37  */
   38 
   39 /*
   40  * IPsec input processing.
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __FBSDID("$FreeBSD$");
   45 
   46 #include "opt_inet.h"
   47 #include "opt_inet6.h"
   48 #include "opt_ipsec.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/malloc.h>
   53 #include <sys/mbuf.h>
   54 #include <sys/domain.h>
   55 #include <sys/protosw.h>
   56 #include <sys/socket.h>
   57 #include <sys/errno.h>
   58 #include <sys/hhook.h>
   59 #include <sys/syslog.h>
   60 
   61 #include <net/if.h>
   62 #include <net/if_var.h>
   63 #include <net/if_enc.h>
   64 #include <net/netisr.h>
   65 #include <net/vnet.h>
   66 
   67 #include <netinet/in.h>
   68 #include <netinet/in_pcb.h>
   69 #include <netinet/in_systm.h>
   70 #include <netinet/ip.h>
   71 #include <netinet/ip_var.h>
   72 #include <netinet/ip_icmp.h>
   73 #include <netinet/in_var.h>
   74 #include <netinet/tcp_var.h>
   75 
   76 #include <netinet/ip6.h>
   77 #ifdef INET6
   78 #include <netinet6/ip6_var.h>
   79 #endif
   80 #include <netinet/in_pcb.h>
   81 #ifdef INET6
   82 #include <netinet/icmp6.h>
   83 #endif
   84 
   85 #include <netipsec/ipsec.h>
   86 #ifdef INET6
   87 #include <netipsec/ipsec6.h>
   88 #endif
   89 #include <netipsec/ipsec_support.h>
   90 #include <netipsec/ah_var.h>
   91 #include <netipsec/esp.h>
   92 #include <netipsec/esp_var.h>
   93 #include <netipsec/ipcomp_var.h>
   94 
   95 #include <netipsec/key.h>
   96 #include <netipsec/keydb.h>
   97 #include <netipsec/key_debug.h>
   98 
   99 #include <netipsec/xform.h>
  100 
  101 #include <machine/in_cksum.h>
  102 #include <machine/stdarg.h>
  103 
  104 #define IPSEC_ISTAT(proto, name)        do {    \
  105         if ((proto) == IPPROTO_ESP)             \
  106                 ESPSTAT_INC(esps_##name);       \
  107         else if ((proto) == IPPROTO_AH)         \
  108                 AHSTAT_INC(ahs_##name);         \
  109         else                                    \
  110                 IPCOMPSTAT_INC(ipcomps_##name); \
  111 } while (0)
  112 
  113 /*
  114  * ipsec_common_input gets called when an IPsec-protected packet
  115  * is received by IPv4 or IPv6.  Its job is to find the right SA
  116  * and call the appropriate transform.  The transform callback
  117  * takes care of further processing (like ingress filtering).
  118  */
  119 static int
  120 ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
  121 {
  122         IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  123         union sockaddr_union dst_address;
  124         struct secasvar *sav;
  125         uint32_t spi;
  126         int error;
  127 
  128         IPSEC_ISTAT(sproto, input);
  129 
  130         IPSEC_ASSERT(m != NULL, ("null packet"));
  131 
  132         IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
  133                 sproto == IPPROTO_IPCOMP,
  134                 ("unexpected security protocol %u", sproto));
  135 
  136         if ((sproto == IPPROTO_ESP && !V_esp_enable) ||
  137             (sproto == IPPROTO_AH && !V_ah_enable) ||
  138             (sproto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
  139                 m_freem(m);
  140                 IPSEC_ISTAT(sproto, pdrops);
  141                 return EOPNOTSUPP;
  142         }
  143 
  144         if (m->m_pkthdr.len - skip < 2 * sizeof (u_int32_t)) {
  145                 m_freem(m);
  146                 IPSEC_ISTAT(sproto, hdrops);
  147                 DPRINTF(("%s: packet too small\n", __func__));
  148                 return EINVAL;
  149         }
  150 
  151         /* Retrieve the SPI from the relevant IPsec header */
  152         if (sproto == IPPROTO_ESP)
  153                 m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
  154         else if (sproto == IPPROTO_AH)
  155                 m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
  156                     (caddr_t) &spi);
  157         else if (sproto == IPPROTO_IPCOMP) {
  158                 u_int16_t cpi;
  159                 m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t),
  160                     (caddr_t) &cpi);
  161                 spi = ntohl(htons(cpi));
  162         }
  163 
  164         /*
  165          * Find the SA and (indirectly) call the appropriate
  166          * kernel crypto routine. The resulting mbuf chain is a valid
  167          * IP packet ready to go through input processing.
  168          */
  169         bzero(&dst_address, sizeof (dst_address));
  170         dst_address.sa.sa_family = af;
  171         switch (af) {
  172 #ifdef INET
  173         case AF_INET:
  174                 dst_address.sin.sin_len = sizeof(struct sockaddr_in);
  175                 m_copydata(m, offsetof(struct ip, ip_dst),
  176                     sizeof(struct in_addr),
  177                     (caddr_t) &dst_address.sin.sin_addr);
  178                 break;
  179 #endif /* INET */
  180 #ifdef INET6
  181         case AF_INET6:
  182                 dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6);
  183                 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
  184                     sizeof(struct in6_addr),
  185                     (caddr_t) &dst_address.sin6.sin6_addr);
  186                 /* We keep addresses in SADB without embedded scope id */
  187                 if (IN6_IS_SCOPE_LINKLOCAL(&dst_address.sin6.sin6_addr)) {
  188                         /* XXX: sa6_recoverscope() */
  189                         dst_address.sin6.sin6_scope_id =
  190                             ntohs(dst_address.sin6.sin6_addr.s6_addr16[1]);
  191                         dst_address.sin6.sin6_addr.s6_addr16[1] = 0;
  192                 }
  193                 break;
  194 #endif /* INET6 */
  195         default:
  196                 DPRINTF(("%s: unsupported protocol family %u\n", __func__, af));
  197                 m_freem(m);
  198                 IPSEC_ISTAT(sproto, nopf);
  199                 return EPFNOSUPPORT;
  200         }
  201 
  202         /* NB: only pass dst since key_allocsa follows RFC2401 */
  203         sav = key_allocsa(&dst_address, sproto, spi);
  204         if (sav == NULL) {
  205                 DPRINTF(("%s: no key association found for SA %s/%08lx/%u\n",
  206                     __func__, ipsec_address(&dst_address, buf, sizeof(buf)),
  207                     (u_long) ntohl(spi), sproto));
  208                 IPSEC_ISTAT(sproto, notdb);
  209                 m_freem(m);
  210                 return ENOENT;
  211         }
  212 
  213         if (sav->tdb_xform == NULL) {
  214                 DPRINTF(("%s: attempted to use uninitialized SA %s/%08lx/%u\n",
  215                     __func__, ipsec_address(&dst_address, buf, sizeof(buf)),
  216                     (u_long) ntohl(spi), sproto));
  217                 IPSEC_ISTAT(sproto, noxform);
  218                 key_freesav(&sav);
  219                 m_freem(m);
  220                 return ENXIO;
  221         }
  222 
  223         /*
  224          * Call appropriate transform and return -- callback takes care of
  225          * everything else.
  226          */
  227         error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff);
  228         return (error);
  229 }
  230 
  231 #ifdef INET
  232 /*
  233  * IPSEC_INPUT() method implementation for IPv4.
  234  *  0 - Permitted by inbound security policy for further processing.
  235  *  EACCES - Forbidden by inbound security policy.
  236  *  EINPROGRESS - consumed by IPsec.
  237  */
  238 int
  239 ipsec4_input(struct mbuf *m, int offset, int proto)
  240 {
  241 
  242         switch (proto) {
  243         case IPPROTO_AH:
  244         case IPPROTO_ESP:
  245         case IPPROTO_IPCOMP:
  246                 /* Do inbound IPsec processing for AH/ESP/IPCOMP */
  247                 ipsec_common_input(m, offset,
  248                     offsetof(struct ip, ip_p), AF_INET, proto);
  249                 return (EINPROGRESS); /* mbuf consumed by IPsec */
  250         default:
  251                 /*
  252                  * Protocols with further headers get their IPsec treatment
  253                  * within the protocol specific processing.
  254                  */
  255                 switch (proto) {
  256                 case IPPROTO_ICMP:
  257                 case IPPROTO_IGMP:
  258                 case IPPROTO_IPV4:
  259                 case IPPROTO_IPV6:
  260                 case IPPROTO_RSVP:
  261                 case IPPROTO_GRE:
  262                 case IPPROTO_MOBILE:
  263                 case IPPROTO_ETHERIP:
  264                 case IPPROTO_PIM:
  265                 case IPPROTO_SCTP:
  266                         break;
  267                 default:
  268                         return (0);
  269                 }
  270         };
  271         /*
  272          * Enforce IPsec policy checking if we are seeing last header.
  273          */
  274         if (ipsec4_in_reject(m, NULL) != 0) {
  275                 /* Forbidden by inbound security policy */
  276                 m_freem(m);
  277                 return (EACCES);
  278         }
  279         return (0);
  280 }
  281 
  282 int
  283 ipsec4_ctlinput(ipsec_ctlinput_param_t param)
  284 {
  285         struct icmp *icp = param.icmp;
  286         struct ip *ip = &icp->icmp_ip;
  287         struct sockaddr_in icmpsrc = {
  288                 .sin_len = sizeof(struct sockaddr_in),
  289                 .sin_family = AF_INET,
  290                 .sin_addr = ip->ip_dst,
  291         };
  292         struct in_conninfo inc;
  293         struct secasvar *sav;
  294         uint32_t pmtu, spi;
  295         uint32_t max_pmtu;
  296         uint8_t proto;
  297 
  298         pmtu = ntohs(icp->icmp_nextmtu);
  299 
  300         if (pmtu < V_ip4_ipsec_min_pmtu)
  301                 return (EINVAL);
  302 
  303         proto = ip->ip_p;
  304         if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
  305             proto != IPPROTO_IPCOMP)
  306                 return (EINVAL);
  307 
  308         memcpy(&spi, (caddr_t)ip + (ip->ip_hl << 2), sizeof(spi));
  309         sav = key_allocsa((union sockaddr_union *)&icmpsrc, proto, spi);
  310         if (sav == NULL)
  311                 return (ENOENT);
  312 
  313         key_freesav(&sav);
  314 
  315         memset(&inc, 0, sizeof(inc));
  316         inc.inc_faddr = ip->ip_dst;
  317 
  318         /* Update pmtu only if its smaller than the current one. */
  319         max_pmtu = tcp_hc_getmtu(&inc);
  320         if (max_pmtu == 0)
  321                 max_pmtu = tcp_maxmtu(&inc, NULL);
  322 
  323         if (pmtu < max_pmtu)
  324                 tcp_hc_updatemtu(&inc, pmtu);
  325 
  326         return (0);
  327 }
  328 
  329 /*
  330  * IPsec input callback for INET protocols.
  331  * This routine is called as the transform callback.
  332  * Takes care of filtering and other sanity checks on
  333  * the processed packet.
  334  */
  335 int
  336 ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
  337     int protoff)
  338 {
  339         IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  340         struct epoch_tracker et;
  341         struct ipsec_ctx_data ctx;
  342         struct xform_history *xh;
  343         struct secasindex *saidx;
  344         struct m_tag *mtag;
  345         struct ip *ip;
  346         int error, prot, af, sproto, isr_prot;
  347 
  348         IPSEC_ASSERT(sav != NULL, ("null SA"));
  349         IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
  350         saidx = &sav->sah->saidx;
  351         af = saidx->dst.sa.sa_family;
  352         IPSEC_ASSERT(af == AF_INET, ("unexpected af %u", af));
  353         sproto = saidx->proto;
  354         IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
  355                 sproto == IPPROTO_IPCOMP,
  356                 ("unexpected security protocol %u", sproto));
  357 
  358         if (skip != 0) {
  359                 /*
  360                  * Fix IPv4 header
  361                  */
  362                 if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) {
  363                         DPRINTF(("%s: processing failed for SA %s/%08lx\n",
  364                             __func__, ipsec_address(&sav->sah->saidx.dst,
  365                             buf, sizeof(buf)), (u_long) ntohl(sav->spi)));
  366                         IPSEC_ISTAT(sproto, hdrops);
  367                         error = ENOBUFS;
  368                         goto bad_noepoch;
  369                 }
  370 
  371                 ip = mtod(m, struct ip *);
  372                 ip->ip_len = htons(m->m_pkthdr.len);
  373                 ip->ip_sum = 0;
  374                 ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
  375         } else {
  376                 ip = mtod(m, struct ip *);
  377         }
  378         prot = ip->ip_p;
  379         /*
  380          * Check that we have NAT-T enabled and apply transport mode
  381          * decapsulation NAT procedure (RFC3948).
  382          * Do this before invoking into the PFIL.
  383          */
  384         if (sav->natt != NULL &&
  385             (prot == IPPROTO_UDP || prot == IPPROTO_TCP))
  386                 udp_ipsec_adjust_cksum(m, sav, prot, skip);
  387 
  388         /*
  389          * Needed for ipsec_run_hooks and netisr_queue_src
  390          */
  391         NET_EPOCH_ENTER(et);
  392 
  393         IPSEC_INIT_CTX(&ctx, &m, NULL, sav, AF_INET, IPSEC_ENC_BEFORE);
  394         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
  395                 goto bad;
  396         ip = mtod(m, struct ip *);      /* update pointer */
  397 
  398         /* IP-in-IP encapsulation */
  399         if (prot == IPPROTO_IPIP &&
  400             saidx->mode != IPSEC_MODE_TRANSPORT) {
  401                 if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
  402                         IPSEC_ISTAT(sproto, hdrops);
  403                         error = EINVAL;
  404                         goto bad;
  405                 }
  406                 /* enc0: strip outer IPv4 header */
  407                 m_striphdr(m, 0, ip->ip_hl << 2);
  408         }
  409 #ifdef INET6
  410         /* IPv6-in-IP encapsulation. */
  411         else if (prot == IPPROTO_IPV6 &&
  412             saidx->mode != IPSEC_MODE_TRANSPORT) {
  413                 if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
  414                         IPSEC_ISTAT(sproto, hdrops);
  415                         error = EINVAL;
  416                         goto bad;
  417                 }
  418                 /* enc0: strip IPv4 header, keep IPv6 header only */
  419                 m_striphdr(m, 0, ip->ip_hl << 2);
  420         }
  421 #endif /* INET6 */
  422         else if (prot != IPPROTO_IPV6 && saidx->mode == IPSEC_MODE_ANY) {
  423                 /*
  424                  * When mode is wildcard, inner protocol is IPv6 and
  425                  * we have no INET6 support - drop this packet a bit later.
  426                  * In other cases we assume transport mode. Set prot to
  427                  * correctly choose netisr.
  428                  */
  429                 prot = IPPROTO_IPIP;
  430         }
  431 
  432         /*
  433          * Record what we've done to the packet (under what SA it was
  434          * processed).
  435          */
  436         if (sproto != IPPROTO_IPCOMP) {
  437                 mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
  438                     sizeof(struct xform_history), M_NOWAIT);
  439                 if (mtag == NULL) {
  440                         DPRINTF(("%s: failed to get tag\n", __func__));
  441                         IPSEC_ISTAT(sproto, hdrops);
  442                         error = ENOMEM;
  443                         goto bad;
  444                 }
  445 
  446                 xh = (struct xform_history *)(mtag + 1);
  447                 bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len);
  448                 xh->spi = sav->spi;
  449                 xh->proto = sproto;
  450                 xh->mode = saidx->mode;
  451                 m_tag_prepend(m, mtag);
  452         }
  453 
  454         key_sa_recordxfer(sav, m);              /* record data transfer */
  455 
  456         /*
  457          * In transport mode requeue decrypted mbuf back to IPv4 protocol
  458          * handler. This is necessary to correctly expose rcvif.
  459          */
  460         if (saidx->mode == IPSEC_MODE_TRANSPORT)
  461                 prot = IPPROTO_IPIP;
  462         /*
  463          * Re-dispatch via software interrupt.
  464          */
  465         switch (prot) {
  466         case IPPROTO_IPIP:
  467                 isr_prot = NETISR_IP;
  468                 af = AF_INET;
  469                 break;
  470 #ifdef INET6
  471         case IPPROTO_IPV6:
  472                 isr_prot = NETISR_IPV6;
  473                 af = AF_INET6;
  474                 break;
  475 #endif
  476         default:
  477                 DPRINTF(("%s: cannot handle inner ip proto %d\n",
  478                             __func__, prot));
  479                 IPSEC_ISTAT(sproto, nopf);
  480                 error = EPFNOSUPPORT;
  481                 goto bad;
  482         }
  483 
  484         IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER);
  485         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
  486                 goto bad;
  487 
  488         /* Handle virtual tunneling interfaces */
  489         if (saidx->mode == IPSEC_MODE_TUNNEL)
  490                 error = ipsec_if_input(m, sav, af);
  491         if (error == 0) {
  492                 error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
  493                 if (error) {
  494                         IPSEC_ISTAT(sproto, qfull);
  495                         DPRINTF(("%s: queue full; proto %u packet dropped\n",
  496                             __func__, sproto));
  497                 }
  498         }
  499         NET_EPOCH_EXIT(et);
  500         key_freesav(&sav);
  501         return (error);
  502 bad:
  503         NET_EPOCH_EXIT(et);
  504 bad_noepoch:
  505         key_freesav(&sav);
  506         if (m != NULL)
  507                 m_freem(m);
  508         return (error);
  509 }
  510 #endif /* INET */
  511 
  512 #ifdef INET6
  513 static bool
  514 ipsec6_lasthdr(int proto)
  515 {
  516 
  517         switch (proto) {
  518         case IPPROTO_IPV4:
  519         case IPPROTO_IPV6:
  520         case IPPROTO_GRE:
  521         case IPPROTO_ICMPV6:
  522         case IPPROTO_ETHERIP:
  523         case IPPROTO_PIM:
  524         case IPPROTO_SCTP:
  525                 return (true);
  526         default:
  527                 return (false);
  528         };
  529 }
  530 
  531 /*
  532  * IPSEC_INPUT() method implementation for IPv6.
  533  *  0 - Permitted by inbound security policy for further processing.
  534  *  EACCES - Forbidden by inbound security policy.
  535  *  EINPROGRESS - consumed by IPsec.
  536  */
  537 int
  538 ipsec6_input(struct mbuf *m, int offset, int proto)
  539 {
  540 
  541         switch (proto) {
  542         case IPPROTO_AH:
  543         case IPPROTO_ESP:
  544         case IPPROTO_IPCOMP:
  545                 /* Do inbound IPsec processing for AH/ESP/IPCOMP */
  546                 ipsec_common_input(m, offset,
  547                     offsetof(struct ip6_hdr, ip6_nxt), AF_INET6, proto);
  548                 return (EINPROGRESS); /* mbuf consumed by IPsec */
  549         default:
  550                 /*
  551                  * Protocols with further headers get their IPsec treatment
  552                  * within the protocol specific processing.
  553                  */
  554                 if (!ipsec6_lasthdr(proto))
  555                         return (0);
  556                 /* FALLTHROUGH */
  557         };
  558         /*
  559          * Enforce IPsec policy checking if we are seeing last header.
  560          */
  561         if (ipsec6_in_reject(m, NULL) != 0) {
  562                 /* Forbidden by inbound security policy */
  563                 m_freem(m);
  564                 return (EACCES);
  565         }
  566         return (0);
  567 }
  568 
  569 int
  570 ipsec6_ctlinput(ipsec_ctlinput_param_t param)
  571 {
  572         return (0);
  573 }
  574 
  575 extern ipproto_input_t  *ip6_protox[];
  576 
  577 /*
  578  * IPsec input callback, called by the transform callback. Takes care of
  579  * filtering and other sanity checks on the processed packet.
  580  */
  581 int
  582 ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
  583     int protoff)
  584 {
  585         IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  586         struct epoch_tracker et;
  587         struct ipsec_ctx_data ctx;
  588         struct xform_history *xh;
  589         struct secasindex *saidx;
  590         struct ip6_hdr *ip6;
  591         struct m_tag *mtag;
  592         int prot, af, sproto;
  593         int nxt, isr_prot;
  594         int error, nest;
  595         uint8_t nxt8;
  596 
  597         IPSEC_ASSERT(sav != NULL, ("null SA"));
  598         IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
  599         saidx = &sav->sah->saidx;
  600         af = saidx->dst.sa.sa_family;
  601         IPSEC_ASSERT(af == AF_INET6, ("unexpected af %u", af));
  602         sproto = saidx->proto;
  603         IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
  604                 sproto == IPPROTO_IPCOMP,
  605                 ("unexpected security protocol %u", sproto));
  606 
  607         NET_EPOCH_ENTER(et);
  608 
  609         /* Fix IPv6 header */
  610         if (m->m_len < sizeof(struct ip6_hdr) &&
  611             (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
  612                 DPRINTF(("%s: processing failed for SA %s/%08lx\n",
  613                     __func__, ipsec_address(&sav->sah->saidx.dst, buf,
  614                     sizeof(buf)), (u_long) ntohl(sav->spi)));
  615 
  616                 IPSEC_ISTAT(sproto, hdrops);
  617                 error = EACCES;
  618                 goto bad;
  619         }
  620 
  621         IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_BEFORE);
  622         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
  623                 goto bad;
  624 
  625         ip6 = mtod(m, struct ip6_hdr *);
  626         ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
  627 
  628         /* Save protocol */
  629         m_copydata(m, protoff, 1, &nxt8);
  630         prot = nxt8;
  631 
  632         /* IPv6-in-IP encapsulation */
  633         if (prot == IPPROTO_IPV6 &&
  634             saidx->mode != IPSEC_MODE_TRANSPORT) {
  635                 if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
  636                         IPSEC_ISTAT(sproto, hdrops);
  637                         error = EINVAL;
  638                         goto bad;
  639                 }
  640                 /* ip6n will now contain the inner IPv6 header. */
  641                 m_striphdr(m, 0, skip);
  642                 skip = 0;
  643         }
  644 #ifdef INET
  645         /* IP-in-IP encapsulation */
  646         else if (prot == IPPROTO_IPIP &&
  647             saidx->mode != IPSEC_MODE_TRANSPORT) {
  648                 if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
  649                         IPSEC_ISTAT(sproto, hdrops);
  650                         error = EINVAL;
  651                         goto bad;
  652                 }
  653                 /* ipn will now contain the inner IPv4 header */
  654                 m_striphdr(m, 0, skip);
  655                 skip = 0;
  656         }
  657 #endif /* INET */
  658         else {
  659                 prot = IPPROTO_IPV6; /* for correct BPF processing */
  660         }
  661 
  662         /*
  663          * Record what we've done to the packet (under what SA it was
  664          * processed).
  665          */
  666         if (sproto != IPPROTO_IPCOMP) {
  667                 mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
  668                     sizeof(struct xform_history), M_NOWAIT);
  669                 if (mtag == NULL) {
  670                         DPRINTF(("%s: failed to get tag\n", __func__));
  671                         IPSEC_ISTAT(sproto, hdrops);
  672                         error = ENOMEM;
  673                         goto bad;
  674                 }
  675 
  676                 xh = (struct xform_history *)(mtag + 1);
  677                 bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len);
  678                 xh->spi = sav->spi;
  679                 xh->proto = sproto;
  680                 xh->mode = saidx->mode;
  681                 m_tag_prepend(m, mtag);
  682         }
  683 
  684         key_sa_recordxfer(sav, m);
  685 
  686 #ifdef INET
  687         if (prot == IPPROTO_IPIP)
  688                 af = AF_INET;
  689         else
  690 #endif
  691                 af = AF_INET6;
  692         IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER);
  693         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
  694                 goto bad;
  695         if (skip == 0) {
  696                 /*
  697                  * We stripped outer IPv6 header.
  698                  * Now we should requeue decrypted packet via netisr.
  699                  */
  700                 switch (prot) {
  701 #ifdef INET
  702                 case IPPROTO_IPIP:
  703                         isr_prot = NETISR_IP;
  704                         break;
  705 #endif
  706                 case IPPROTO_IPV6:
  707                         isr_prot = NETISR_IPV6;
  708                         break;
  709                 default:
  710                         DPRINTF(("%s: cannot handle inner ip proto %d\n",
  711                             __func__, prot));
  712                         IPSEC_ISTAT(sproto, nopf);
  713                         error = EPFNOSUPPORT;
  714                         goto bad;
  715                 }
  716                 /* Handle virtual tunneling interfaces */
  717                 if (saidx->mode == IPSEC_MODE_TUNNEL)
  718                         error = ipsec_if_input(m, sav, af);
  719                 if (error == 0) {
  720                         error = netisr_queue_src(isr_prot,
  721                             (uintptr_t)sav->spi, m);
  722                         if (error) {
  723                                 IPSEC_ISTAT(sproto, qfull);
  724                                 DPRINTF(("%s: queue full; proto %u packet"
  725                                     " dropped\n", __func__, sproto));
  726                         }
  727                 }
  728                 NET_EPOCH_EXIT(et);
  729                 key_freesav(&sav);
  730                 return (error);
  731         }
  732         /*
  733          * See the end of ip6_input for this logic.
  734          * IPPROTO_IPV[46] case will be processed just like other ones
  735          */
  736         nest = 0;
  737         nxt = nxt8;
  738         while (nxt != IPPROTO_DONE) {
  739                 if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
  740                         IP6STAT_INC(ip6s_toomanyhdr);
  741                         error = EINVAL;
  742                         goto bad;
  743                 }
  744 
  745                 /*
  746                  * Protection against faulty packet - there should be
  747                  * more sanity checks in header chain processing.
  748                  */
  749                 if (m->m_pkthdr.len < skip) {
  750                         IP6STAT_INC(ip6s_tooshort);
  751                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
  752                         error = EINVAL;
  753                         goto bad;
  754                 }
  755                 /*
  756                  * Enforce IPsec policy checking if we are seeing last header.
  757                  * note that we do not visit this with protocols with pcb layer
  758                  * code - like udp/tcp/raw ip.
  759                  */
  760                 if (ipsec6_lasthdr(nxt) && ipsec6_in_reject(m, NULL)) {
  761                         error = EINVAL;
  762                         goto bad;
  763                 }
  764                 nxt = ip6_protox[nxt](&m, &skip, nxt);
  765         }
  766         NET_EPOCH_EXIT(et);
  767         key_freesav(&sav);
  768         return (0);
  769 bad:
  770         NET_EPOCH_EXIT(et);
  771         key_freesav(&sav);
  772         if (m)
  773                 m_freem(m);
  774         return (error);
  775 }
  776 #endif /* INET6 */

Cache object: 346bf437f9ebf49014367953b91cf2f9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.