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_output.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 /*-
    2  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    3  * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD: releng/11.1/sys/netipsec/ipsec_output.c 319599 2017-06-05 11:11:07Z ae $
   28  */
   29 
   30 /*
   31  * IPsec output processing.
   32  */
   33 #include "opt_inet.h"
   34 #include "opt_inet6.h"
   35 #include "opt_ipsec.h"
   36 #include "opt_sctp.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/domain.h>
   42 #include <sys/protosw.h>
   43 #include <sys/socket.h>
   44 #include <sys/errno.h>
   45 #include <sys/hhook.h>
   46 #include <sys/syslog.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_enc.h>
   50 #include <net/if_var.h>
   51 #include <net/vnet.h>
   52 
   53 #include <netinet/in.h>
   54 #include <netinet/in_systm.h>
   55 #include <netinet/ip.h>
   56 #include <netinet/ip_var.h>
   57 #include <netinet/in_var.h>
   58 #include <netinet/ip_ecn.h>
   59 #ifdef INET6
   60 #include <netinet6/ip6_ecn.h>
   61 #endif
   62 
   63 #include <netinet/ip6.h>
   64 #ifdef INET6
   65 #include <netinet6/ip6_var.h>
   66 #include <netinet6/scope6_var.h>
   67 #endif
   68 #include <netinet/in_pcb.h>
   69 #ifdef INET6
   70 #include <netinet/icmp6.h>
   71 #endif
   72 #ifdef SCTP
   73 #include <netinet/sctp_crc32.h>
   74 #endif
   75 
   76 #include <netinet/udp.h>
   77 #include <netipsec/ah.h>
   78 #include <netipsec/esp.h>
   79 #include <netipsec/ipsec.h>
   80 #ifdef INET6
   81 #include <netipsec/ipsec6.h>
   82 #endif
   83 #include <netipsec/ah_var.h>
   84 #include <netipsec/esp_var.h>
   85 #include <netipsec/ipcomp_var.h>
   86 
   87 #include <netipsec/xform.h>
   88 
   89 #include <netipsec/key.h>
   90 #include <netipsec/keydb.h>
   91 #include <netipsec/key_debug.h>
   92 
   93 #include <machine/in_cksum.h>
   94 
   95 #define IPSEC_OSTAT_INC(proto, name)    do {            \
   96         if ((proto) == IPPROTO_ESP)     \
   97                 ESPSTAT_INC(esps_##name);       \
   98         else if ((proto) == IPPROTO_AH)\
   99                 AHSTAT_INC(ahs_##name);         \
  100         else                                    \
  101                 IPCOMPSTAT_INC(ipcomps_##name); \
  102 } while (0)
  103 
  104 static int ipsec_encap(struct mbuf **mp, struct secasindex *saidx);
  105 
  106 #ifdef INET
  107 static struct secasvar *
  108 ipsec4_allocsa(struct mbuf *m, struct secpolicy *sp, u_int *pidx, int *error)
  109 {
  110         struct secasindex *saidx, tmpsaidx;
  111         struct ipsecrequest *isr;
  112         struct sockaddr_in *sin;
  113         struct secasvar *sav;
  114         struct ip *ip;
  115 
  116         /*
  117          * Check system global policy controls.
  118          */
  119 next:
  120         isr = sp->req[*pidx];
  121         if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) ||
  122             (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) ||
  123             (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
  124                 DPRINTF(("%s: IPsec outbound packet dropped due"
  125                         " to policy (check your sysctls)\n", __func__));
  126                 IPSEC_OSTAT_INC(isr->saidx.proto, pdrops);
  127                 *error = EHOSTUNREACH;
  128                 return (NULL);
  129         }
  130         /*
  131          * Craft SA index to search for proper SA.  Note that
  132          * we only initialize unspecified SA peers for transport
  133          * mode; for tunnel mode they must already be filled in.
  134          */
  135         if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
  136                 saidx = &tmpsaidx;
  137                 *saidx = isr->saidx;
  138                 ip = mtod(m, struct ip *);
  139                 if (saidx->src.sa.sa_len == 0) {
  140                         sin = &saidx->src.sin;
  141                         sin->sin_len = sizeof(*sin);
  142                         sin->sin_family = AF_INET;
  143                         sin->sin_port = IPSEC_PORT_ANY;
  144                         sin->sin_addr = ip->ip_src;
  145                 }
  146                 if (saidx->dst.sa.sa_len == 0) {
  147                         sin = &saidx->dst.sin;
  148                         sin->sin_len = sizeof(*sin);
  149                         sin->sin_family = AF_INET;
  150                         sin->sin_port = IPSEC_PORT_ANY;
  151                         sin->sin_addr = ip->ip_dst;
  152                 }
  153         } else
  154                 saidx = &sp->req[*pidx]->saidx;
  155         /*
  156          * Lookup SA and validate it.
  157          */
  158         sav = key_allocsa_policy(sp, saidx, error);
  159         if (sav == NULL) {
  160                 IPSECSTAT_INC(ips_out_nosa);
  161                 if (*error != 0)
  162                         return (NULL);
  163                 if (ipsec_get_reqlevel(sp, *pidx) != IPSEC_LEVEL_REQUIRE) {
  164                         /*
  165                          * We have no SA and policy that doesn't require
  166                          * this IPsec transform, thus we can continue w/o
  167                          * IPsec processing, i.e. return EJUSTRETURN.
  168                          * But first check if there is some bundled transform.
  169                          */
  170                         if (sp->tcount > ++(*pidx))
  171                                 goto next;
  172                         *error = EJUSTRETURN;
  173                 }
  174                 return (NULL);
  175         }
  176         IPSEC_ASSERT(sav->tdb_xform != NULL, ("SA with NULL tdb_xform"));
  177         return (sav);
  178 }
  179 
  180 /*
  181  * IPsec output logic for IPv4.
  182  */
  183 static int
  184 ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
  185 {
  186         struct ipsec_ctx_data ctx;
  187         union sockaddr_union *dst;
  188         struct secasvar *sav;
  189         struct ip *ip;
  190         int error, i, off;
  191 
  192         IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx));
  193 
  194         /*
  195          * We hold the reference to SP. Content of SP couldn't be changed.
  196          * Craft secasindex and do lookup for suitable SA.
  197          * Then do encapsulation if needed and call xform's output.
  198          * We need to store SP in the xform callback parameters.
  199          * In xform callback we will extract SP and it can be used to
  200          * determine next transform. At the end of transform we can
  201          * release reference to SP.
  202          */
  203         sav = ipsec4_allocsa(m, sp, &idx, &error);
  204         if (sav == NULL) {
  205                 if (error == EJUSTRETURN) { /* No IPsec required */
  206                         key_freesp(&sp);
  207                         return (error);
  208                 }
  209                 goto bad;
  210         }
  211         /*
  212          * XXXAE: most likely ip_sum at this point is wrong.
  213          */
  214         IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET, IPSEC_ENC_BEFORE);
  215         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
  216                 goto bad;
  217 
  218         ip = mtod(m, struct ip *);
  219         dst = &sav->sah->saidx.dst;
  220         /* Do the appropriate encapsulation, if necessary */
  221         if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
  222             dst->sa.sa_family != AF_INET ||         /* PF mismatch */
  223             (dst->sa.sa_family == AF_INET &&        /* Proxy */
  224              dst->sin.sin_addr.s_addr != INADDR_ANY &&
  225              dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
  226                 /* Fix IPv4 header checksum and length */
  227                 ip->ip_len = htons(m->m_pkthdr.len);
  228                 ip->ip_sum = 0;
  229                 ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
  230                 error = ipsec_encap(&m, &sav->sah->saidx);
  231                 if (error != 0) {
  232                         DPRINTF(("%s: encapsulation for SPI 0x%08x failed "
  233                             "with error %d\n", __func__, ntohl(sav->spi),
  234                             error));
  235                         /* XXXAE: IPSEC_OSTAT_INC(tunnel); */
  236                         goto bad;
  237                 }
  238         }
  239 
  240         IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
  241         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
  242                 goto bad;
  243 
  244         /*
  245          * Dispatch to the appropriate IPsec transform logic.  The
  246          * packet will be returned for transmission after crypto
  247          * processing, etc. are completed.
  248          *
  249          * NB: m & sav are ``passed to caller'' who's responsible for
  250          *     reclaiming their resources.
  251          */
  252         switch(dst->sa.sa_family) {
  253         case AF_INET:
  254                 ip = mtod(m, struct ip *);
  255                 i = ip->ip_hl << 2;
  256                 off = offsetof(struct ip, ip_p);
  257                 break;
  258 #ifdef INET6
  259         case AF_INET6:
  260                 i = sizeof(struct ip6_hdr);
  261                 off = offsetof(struct ip6_hdr, ip6_nxt);
  262                 break;
  263 #endif /* INET6 */
  264         default:
  265                 DPRINTF(("%s: unsupported protocol family %u\n",
  266                     __func__, dst->sa.sa_family));
  267                 error = EPFNOSUPPORT;
  268                 IPSEC_OSTAT_INC(sav->sah->saidx.proto, nopf);
  269                 goto bad;
  270         }
  271         error = (*sav->tdb_xform->xf_output)(m, sp, sav, idx, i, off);
  272         return (error);
  273 bad:
  274         IPSECSTAT_INC(ips_out_inval);
  275         if (m != NULL)
  276                 m_freem(m);
  277         if (sav != NULL)
  278                 key_freesav(&sav);
  279         key_freesp(&sp);
  280         return (error);
  281 }
  282 
  283 int
  284 ipsec4_process_packet(struct mbuf *m, struct secpolicy *sp,
  285     struct inpcb *inp)
  286 {
  287 
  288         return (ipsec4_perform_request(m, sp, 0));
  289 }
  290 
  291 static int
  292 ipsec4_common_output(struct mbuf *m, struct inpcb *inp, int forwarding)
  293 {
  294         struct secpolicy *sp;
  295         int error;
  296 
  297         /* Lookup for the corresponding outbound security policy */
  298         sp = ipsec4_checkpolicy(m, inp, &error);
  299         if (sp == NULL) {
  300                 if (error == -EINVAL) {
  301                         /* Discarded by policy. */
  302                         m_freem(m);
  303                         return (EACCES);
  304                 }
  305                 return (0); /* No IPsec required. */
  306         }
  307 
  308         /*
  309          * Usually we have to have tunnel mode IPsec security policy
  310          * when we are forwarding a packet. Otherwise we could not handle
  311          * encrypted replies, because they are not destined for us. But
  312          * some users are doing source address translation for forwarded
  313          * packets, and thus, even if they are forwarded, the replies will
  314          * return back to us.
  315          */
  316         if (!forwarding) {
  317                 /*
  318                  * Do delayed checksums now because we send before
  319                  * this is done in the normal processing path.
  320                  */
  321                 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
  322                         in_delayed_cksum(m);
  323                         m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
  324                 }
  325 #ifdef SCTP
  326                 if (m->m_pkthdr.csum_flags & CSUM_SCTP) {
  327                         struct ip *ip = mtod(m, struct ip *);
  328 
  329                         sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
  330                         m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
  331                 }
  332 #endif
  333         }
  334         /* NB: callee frees mbuf and releases reference to SP */
  335         error = ipsec4_process_packet(m, sp, inp);
  336         if (error == EJUSTRETURN) {
  337                 /*
  338                  * We had a SP with a level of 'use' and no SA. We
  339                  * will just continue to process the packet without
  340                  * IPsec processing and return without error.
  341                  */
  342                 return (0);
  343         }
  344         if (error == 0)
  345                 return (EINPROGRESS); /* consumed by IPsec */
  346         return (error);
  347 }
  348 
  349 /*
  350  * IPSEC_OUTPUT() method implementation for IPv4.
  351  * 0 - no IPsec handling needed
  352  * other values - mbuf consumed by IPsec.
  353  */
  354 int
  355 ipsec4_output(struct mbuf *m, struct inpcb *inp)
  356 {
  357 
  358         /*
  359          * If the packet is resubmitted to ip_output (e.g. after
  360          * AH, ESP, etc. processing), there will be a tag to bypass
  361          * the lookup and related policy checking.
  362          */
  363         if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL)
  364                 return (0);
  365 
  366         return (ipsec4_common_output(m, inp, 0));
  367 }
  368 
  369 /*
  370  * IPSEC_FORWARD() method implementation for IPv4.
  371  * 0 - no IPsec handling needed
  372  * other values - mbuf consumed by IPsec.
  373  */
  374 int
  375 ipsec4_forward(struct mbuf *m)
  376 {
  377 
  378         /*
  379          * Check if this packet has an active inbound SP and needs to be
  380          * dropped instead of forwarded.
  381          */
  382         if (ipsec4_in_reject(m, NULL) != 0) {
  383                 m_freem(m);
  384                 return (EACCES);
  385         }
  386         return (ipsec4_common_output(m, NULL, 1));
  387 }
  388 #endif
  389 
  390 #ifdef INET6
  391 static int
  392 in6_sa_equal_addrwithscope(const struct sockaddr_in6 *sa,
  393     const struct in6_addr *ia)
  394 {
  395         struct in6_addr ia2;
  396 
  397         if (IN6_IS_SCOPE_LINKLOCAL(&sa->sin6_addr)) {
  398                 memcpy(&ia2, &sa->sin6_addr, sizeof(ia2));
  399                 ia2.s6_addr16[1] = htons(sa->sin6_scope_id);
  400                 return (IN6_ARE_ADDR_EQUAL(ia, &ia2));
  401         }
  402         return (IN6_ARE_ADDR_EQUAL(&sa->sin6_addr, ia));
  403 }
  404 
  405 static struct secasvar *
  406 ipsec6_allocsa(struct mbuf *m, struct secpolicy *sp, u_int *pidx, int *error)
  407 {
  408         struct secasindex *saidx, tmpsaidx;
  409         struct ipsecrequest *isr;
  410         struct sockaddr_in6 *sin6;
  411         struct secasvar *sav;
  412         struct ip6_hdr *ip6;
  413 
  414         /*
  415          * Check system global policy controls.
  416          */
  417 next:
  418         isr = sp->req[*pidx];
  419         if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) ||
  420             (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) ||
  421             (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
  422                 DPRINTF(("%s: IPsec outbound packet dropped due"
  423                         " to policy (check your sysctls)\n", __func__));
  424                 IPSEC_OSTAT_INC(isr->saidx.proto, pdrops);
  425                 *error = EHOSTUNREACH;
  426                 return (NULL);
  427         }
  428         /*
  429          * Craft SA index to search for proper SA.  Note that
  430          * we only fillin unspecified SA peers for transport
  431          * mode; for tunnel mode they must already be filled in.
  432          */
  433         if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
  434                 saidx = &tmpsaidx;
  435                 *saidx = isr->saidx;
  436                 ip6 = mtod(m, struct ip6_hdr *);
  437                 if (saidx->src.sin6.sin6_len == 0) {
  438                         sin6 = (struct sockaddr_in6 *)&saidx->src;
  439                         sin6->sin6_len = sizeof(*sin6);
  440                         sin6->sin6_family = AF_INET6;
  441                         sin6->sin6_port = IPSEC_PORT_ANY;
  442                         sin6->sin6_addr = ip6->ip6_src;
  443                         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
  444                                 /* fix scope id for comparing SPD */
  445                                 sin6->sin6_addr.s6_addr16[1] = 0;
  446                                 sin6->sin6_scope_id =
  447                                     ntohs(ip6->ip6_src.s6_addr16[1]);
  448                         }
  449                 }
  450                 if (saidx->dst.sin6.sin6_len == 0) {
  451                         sin6 = (struct sockaddr_in6 *)&saidx->dst;
  452                         sin6->sin6_len = sizeof(*sin6);
  453                         sin6->sin6_family = AF_INET6;
  454                         sin6->sin6_port = IPSEC_PORT_ANY;
  455                         sin6->sin6_addr = ip6->ip6_dst;
  456                         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
  457                                 /* fix scope id for comparing SPD */
  458                                 sin6->sin6_addr.s6_addr16[1] = 0;
  459                                 sin6->sin6_scope_id =
  460                                     ntohs(ip6->ip6_dst.s6_addr16[1]);
  461                         }
  462                 }
  463         } else
  464                 saidx = &sp->req[*pidx]->saidx;
  465         /*
  466          * Lookup SA and validate it.
  467          */
  468         sav = key_allocsa_policy(sp, saidx, error);
  469         if (sav == NULL) {
  470                 IPSEC6STAT_INC(ips_out_nosa);
  471                 if (*error != 0)
  472                         return (NULL);
  473                 if (ipsec_get_reqlevel(sp, *pidx) != IPSEC_LEVEL_REQUIRE) {
  474                         /*
  475                          * We have no SA and policy that doesn't require
  476                          * this IPsec transform, thus we can continue w/o
  477                          * IPsec processing, i.e. return EJUSTRETURN.
  478                          * But first check if there is some bundled transform.
  479                          */
  480                         if (sp->tcount > ++(*pidx))
  481                                 goto next;
  482                         *error = EJUSTRETURN;
  483                 }
  484                 return (NULL);
  485         }
  486         IPSEC_ASSERT(sav->tdb_xform != NULL, ("SA with NULL tdb_xform"));
  487         return (sav);
  488 }
  489 
  490 /*
  491  * IPsec output logic for IPv6.
  492  */
  493 static int
  494 ipsec6_perform_request(struct mbuf *m, struct secpolicy *sp, u_int idx)
  495 {
  496         struct ipsec_ctx_data ctx;
  497         union sockaddr_union *dst;
  498         struct secasvar *sav;
  499         struct ip6_hdr *ip6;
  500         int error, i, off;
  501 
  502         IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx));
  503 
  504         sav = ipsec6_allocsa(m, sp, &idx, &error);
  505         if (sav == NULL) {
  506                 if (error == EJUSTRETURN) { /* No IPsec required */
  507                         key_freesp(&sp);
  508                         return (error);
  509                 }
  510                 goto bad;
  511         }
  512 
  513         /* Fix IP length in case if it is not set yet. */
  514         ip6 = mtod(m, struct ip6_hdr *);
  515         ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
  516 
  517         IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET6, IPSEC_ENC_BEFORE);
  518         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
  519                 goto bad;
  520 
  521         ip6 = mtod(m, struct ip6_hdr *); /* pfil can change mbuf */
  522         dst = &sav->sah->saidx.dst;
  523 
  524         /* Do the appropriate encapsulation, if necessary */
  525         if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
  526             dst->sa.sa_family != AF_INET6 ||        /* PF mismatch */
  527             ((dst->sa.sa_family == AF_INET6) &&
  528              (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
  529              (!in6_sa_equal_addrwithscope(&dst->sin6, &ip6->ip6_dst)))) {
  530                 if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
  531                         /* No jumbogram support. */
  532                         error = ENXIO;   /*XXX*/
  533                         goto bad;
  534                 }
  535                 error = ipsec_encap(&m, &sav->sah->saidx);
  536                 if (error != 0) {
  537                         DPRINTF(("%s: encapsulation for SPI 0x%08x failed "
  538                             "with error %d\n", __func__, ntohl(sav->spi),
  539                             error));
  540                         /* XXXAE: IPSEC_OSTAT_INC(tunnel); */
  541                         goto bad;
  542                 }
  543         }
  544 
  545         IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
  546         if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
  547                 goto bad;
  548 
  549         switch(dst->sa.sa_family) {
  550 #ifdef INET
  551         case AF_INET:
  552                 {
  553                 struct ip *ip;
  554                 ip = mtod(m, struct ip *);
  555                 i = ip->ip_hl << 2;
  556                 off = offsetof(struct ip, ip_p);
  557                 }
  558                 break;
  559 #endif /* AF_INET */
  560         case AF_INET6:
  561                 i = sizeof(struct ip6_hdr);
  562                 off = offsetof(struct ip6_hdr, ip6_nxt);
  563                 break;
  564         default:
  565                 DPRINTF(("%s: unsupported protocol family %u\n",
  566                                  __func__, dst->sa.sa_family));
  567                 error = EPFNOSUPPORT;
  568                 IPSEC_OSTAT_INC(sav->sah->saidx.proto, nopf);
  569                 goto bad;
  570         }
  571         error = (*sav->tdb_xform->xf_output)(m, sp, sav, idx, i, off);
  572         return (error);
  573 bad:
  574         IPSEC6STAT_INC(ips_out_inval);
  575         if (m != NULL)
  576                 m_freem(m);
  577         if (sav != NULL)
  578                 key_freesav(&sav);
  579         key_freesp(&sp);
  580         return (error);
  581 }
  582 
  583 int
  584 ipsec6_process_packet(struct mbuf *m, struct secpolicy *sp,
  585     struct inpcb *inp)
  586 {
  587 
  588         return (ipsec6_perform_request(m, sp, 0));
  589 }
  590 
  591 static int
  592 ipsec6_common_output(struct mbuf *m, struct inpcb *inp, int forwarding)
  593 {
  594         struct secpolicy *sp;
  595         int error;
  596 
  597         /* Lookup for the corresponding outbound security policy */
  598         sp = ipsec6_checkpolicy(m, inp, &error);
  599         if (sp == NULL) {
  600                 if (error == -EINVAL) {
  601                         /* Discarded by policy. */
  602                         m_freem(m);
  603                         return (EACCES);
  604                 }
  605                 return (0); /* No IPsec required. */
  606         }
  607 
  608         if (!forwarding) {
  609                 /*
  610                  * Do delayed checksums now because we send before
  611                  * this is done in the normal processing path.
  612                  */
  613                 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
  614                         in6_delayed_cksum(m, m->m_pkthdr.len -
  615                             sizeof(struct ip6_hdr), sizeof(struct ip6_hdr));
  616                 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
  617                 }
  618 #ifdef SCTP
  619                 if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
  620                         sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
  621                         m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
  622                 }
  623 #endif
  624         }
  625         /* NB: callee frees mbuf and releases reference to SP */
  626         error = ipsec6_process_packet(m, sp, inp);
  627         if (error == EJUSTRETURN) {
  628                 /*
  629                  * We had a SP with a level of 'use' and no SA. We
  630                  * will just continue to process the packet without
  631                  * IPsec processing and return without error.
  632                  */
  633                 return (0);
  634         }
  635         if (error == 0)
  636                 return (EINPROGRESS); /* consumed by IPsec */
  637         return (error);
  638 }
  639 
  640 /*
  641  * IPSEC_OUTPUT() method implementation for IPv6.
  642  * 0 - no IPsec handling needed
  643  * other values - mbuf consumed by IPsec.
  644  */
  645 int
  646 ipsec6_output(struct mbuf *m, struct inpcb *inp)
  647 {
  648 
  649         /*
  650          * If the packet is resubmitted to ip_output (e.g. after
  651          * AH, ESP, etc. processing), there will be a tag to bypass
  652          * the lookup and related policy checking.
  653          */
  654         if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL)
  655                 return (0);
  656 
  657         return (ipsec6_common_output(m, inp, 0));
  658 }
  659 
  660 /*
  661  * IPSEC_FORWARD() method implementation for IPv6.
  662  * 0 - no IPsec handling needed
  663  * other values - mbuf consumed by IPsec.
  664  */
  665 int
  666 ipsec6_forward(struct mbuf *m)
  667 {
  668 
  669         /*
  670          * Check if this packet has an active inbound SP and needs to be
  671          * dropped instead of forwarded.
  672          */
  673         if (ipsec6_in_reject(m, NULL) != 0) {
  674                 m_freem(m);
  675                 return (EACCES);
  676         }
  677         return (ipsec6_common_output(m, NULL, 1));
  678 }
  679 #endif /* INET6 */
  680 
  681 int
  682 ipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
  683     u_int idx)
  684 {
  685         struct xform_history *xh;
  686         struct secasindex *saidx;
  687         struct m_tag *mtag;
  688         int error;
  689 
  690         saidx = &sav->sah->saidx;
  691         switch (saidx->dst.sa.sa_family) {
  692 #ifdef INET
  693         case AF_INET:
  694                 /* Fix the header length, for AH processing. */
  695                 mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
  696                 break;
  697 #endif /* INET */
  698 #ifdef INET6
  699         case AF_INET6:
  700                 /* Fix the header length, for AH processing. */
  701                 if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) {
  702                         error = ENXIO;
  703                         goto bad;
  704                 }
  705                 if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) {
  706                         /* No jumbogram support. */
  707                         error = ENXIO;  /*?*/
  708                         goto bad;
  709                 }
  710                 mtod(m, struct ip6_hdr *)->ip6_plen =
  711                         htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
  712                 break;
  713 #endif /* INET6 */
  714         default:
  715                 DPRINTF(("%s: unknown protocol family %u\n", __func__,
  716                     saidx->dst.sa.sa_family));
  717                 error = ENXIO;
  718                 goto bad;
  719         }
  720 
  721         /*
  722          * Add a record of what we've done to the packet.
  723          */
  724         mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, sizeof(*xh), M_NOWAIT);
  725         if (mtag == NULL) {
  726                 DPRINTF(("%s: could not get packet tag\n", __func__));
  727                 error = ENOMEM;
  728                 goto bad;
  729         }
  730 
  731         xh = (struct xform_history *)(mtag + 1);
  732         xh->dst = saidx->dst;
  733         xh->proto = saidx->proto;
  734         xh->mode = saidx->mode;
  735         xh->spi = sav->spi;
  736         m_tag_prepend(m, mtag);
  737 
  738         key_sa_recordxfer(sav, m);              /* record data transfer */
  739 
  740         /*
  741          * If there's another (bundled) SA to apply, do so.
  742          * Note that this puts a burden on the kernel stack size.
  743          * If this is a problem we'll need to introduce a queue
  744          * to set the packet on so we can unwind the stack before
  745          * doing further processing.
  746          */
  747         if (++idx < sp->tcount) {
  748                 switch (saidx->dst.sa.sa_family) {
  749 #ifdef INET
  750                 case AF_INET:
  751                         key_freesav(&sav);
  752                         IPSECSTAT_INC(ips_out_bundlesa);
  753                         return (ipsec4_perform_request(m, sp, idx));
  754                         /* NOTREACHED */
  755 #endif
  756 #ifdef INET6
  757                 case AF_INET6:
  758                         key_freesav(&sav);
  759                         IPSEC6STAT_INC(ips_out_bundlesa);
  760                         return (ipsec6_perform_request(m, sp, idx));
  761                         /* NOTREACHED */
  762 #endif /* INET6 */
  763                 default:
  764                         DPRINTF(("%s: unknown protocol family %u\n", __func__,
  765                             saidx->dst.sa.sa_family));
  766                         error = EPFNOSUPPORT;
  767                         goto bad;
  768                 }
  769         }
  770 
  771         key_freesp(&sp), sp = NULL;     /* Release reference to SP */
  772 #ifdef INET
  773         /*
  774          * Do UDP encapsulation if SA requires it.
  775          */
  776         if (sav->natt != NULL) {
  777                 error = udp_ipsec_output(m, sav);
  778                 if (error != 0)
  779                         goto bad;
  780         }
  781 #endif /* INET */
  782         /*
  783          * We're done with IPsec processing, transmit the packet using the
  784          * appropriate network protocol (IP or IPv6).
  785          */
  786         switch (saidx->dst.sa.sa_family) {
  787 #ifdef INET
  788         case AF_INET:
  789                 key_freesav(&sav);
  790                 return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
  791 #endif /* INET */
  792 #ifdef INET6
  793         case AF_INET6:
  794                 key_freesav(&sav);
  795                 return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
  796 #endif /* INET6 */
  797         }
  798         panic("ipsec_process_done");
  799 bad:
  800         m_freem(m);
  801         key_freesav(&sav);
  802         if (sp != NULL)
  803                 key_freesp(&sp);
  804         return (error);
  805 }
  806 
  807 /*
  808  * ipsec_prepend() is optimized version of M_PREPEND().
  809  * ipsec_encap() is called by IPsec output routine for tunnel mode SA.
  810  * It is expected that after IP encapsulation some IPsec transform will
  811  * be performed. Each IPsec transform inserts its variable length header
  812  * just after outer IP header using m_makespace(). If given mbuf has not
  813  * enough free space at the beginning, we allocate new mbuf and reserve
  814  * some space at the beginning and at the end.
  815  * This helps avoid allocating of new mbuf and data copying in m_makespace(),
  816  * we place outer header in the middle of mbuf's data with reserved leading
  817  * and trailing space:
  818  *      [ LEADINGSPACE ][ Outer IP header ][ TRAILINGSPACE ]
  819  * LEADINGSPACE will be used to add ethernet header, TRAILINGSPACE will
  820  * be used to inject AH/ESP/IPCOMP header.
  821  */
  822 #define IPSEC_TRAILINGSPACE     (sizeof(struct udphdr) +/* NAT-T */     \
  823     max(sizeof(struct newesp) + EALG_MAX_BLOCK_LEN,     /* ESP + IV */  \
  824         sizeof(struct newah) + HASH_MAX_LEN             /* AH + ICV */))
  825 static struct mbuf *
  826 ipsec_prepend(struct mbuf *m, int len, int how)
  827 {
  828         struct mbuf *n;
  829 
  830         M_ASSERTPKTHDR(m);
  831         IPSEC_ASSERT(len < MHLEN, ("wrong length"));
  832         if (M_LEADINGSPACE(m) >= len) {
  833                 /* No need to allocate new mbuf. */
  834                 m->m_data -= len;
  835                 m->m_len += len;
  836                 m->m_pkthdr.len += len;
  837                 return (m);
  838         }
  839         n = m_gethdr(how, m->m_type);
  840         if (n == NULL) {
  841                 m_freem(m);
  842                 return (NULL);
  843         }
  844         m_move_pkthdr(n, m);
  845         n->m_next = m;
  846         if (len + IPSEC_TRAILINGSPACE < M_SIZE(n))
  847                 m_align(n, len + IPSEC_TRAILINGSPACE);
  848         n->m_len = len;
  849         n->m_pkthdr.len += len;
  850         return (n);
  851 }
  852 
  853 static int
  854 ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
  855 {
  856 #ifdef INET6
  857         struct ip6_hdr *ip6;
  858 #endif
  859         struct ip *ip;
  860         int setdf;
  861         uint8_t itos, proto;
  862 
  863         ip = mtod(*mp, struct ip *);
  864         switch (ip->ip_v) {
  865 #ifdef INET
  866         case IPVERSION:
  867                 proto = IPPROTO_IPIP;
  868                 /*
  869                  * Collect IP_DF state from the inner header
  870                  * and honor system-wide control of how to handle it.
  871                  */
  872                 switch (V_ip4_ipsec_dfbit) {
  873                 case 0: /* clear in outer header */
  874                 case 1: /* set in outer header */
  875                         setdf = V_ip4_ipsec_dfbit;
  876                         break;
  877                 default:/* propagate to outer header */
  878                         setdf = (ip->ip_off & htons(IP_DF)) != 0;
  879                 }
  880                 itos = ip->ip_tos;
  881                 break;
  882 #endif
  883 #ifdef INET6
  884         case (IPV6_VERSION >> 4):
  885                 proto = IPPROTO_IPV6;
  886                 ip6 = mtod(*mp, struct ip6_hdr *);
  887                 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
  888                 setdf = V_ip4_ipsec_dfbit ? 1: 0;
  889                 /* scoped address handling */
  890                 in6_clearscope(&ip6->ip6_src);
  891                 in6_clearscope(&ip6->ip6_dst);
  892                 break;
  893 #endif
  894         default:
  895                 return (EAFNOSUPPORT);
  896         }
  897         switch (saidx->dst.sa.sa_family) {
  898 #ifdef INET
  899         case AF_INET:
  900                 if (saidx->src.sa.sa_family != AF_INET ||
  901                     saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
  902                     saidx->dst.sin.sin_addr.s_addr == INADDR_ANY)
  903                         return (EINVAL);
  904                 *mp = ipsec_prepend(*mp, sizeof(struct ip), M_NOWAIT);
  905                 if (*mp == NULL)
  906                         return (ENOBUFS);
  907                 ip = mtod(*mp, struct ip *);
  908                 ip->ip_v = IPVERSION;
  909                 ip->ip_hl = sizeof(struct ip) >> 2;
  910                 ip->ip_p = proto;
  911                 ip->ip_len = htons((*mp)->m_pkthdr.len);
  912                 ip->ip_ttl = V_ip_defttl;
  913                 ip->ip_sum = 0;
  914                 ip->ip_off = setdf ? htons(IP_DF): 0;
  915                 ip->ip_src = saidx->src.sin.sin_addr;
  916                 ip->ip_dst = saidx->dst.sin.sin_addr;
  917                 ip_ecn_ingress(V_ip4_ipsec_ecn, &ip->ip_tos, &itos);
  918                 ip_fillid(ip);
  919                 break;
  920 #endif /* INET */
  921 #ifdef INET6
  922         case AF_INET6:
  923                 if (saidx->src.sa.sa_family != AF_INET6 ||
  924                     IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr) ||
  925                     IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr))
  926                         return (EINVAL);
  927                 *mp = ipsec_prepend(*mp, sizeof(struct ip6_hdr), M_NOWAIT);
  928                 if (*mp == NULL)
  929                         return (ENOBUFS);
  930                 ip6 = mtod(*mp, struct ip6_hdr *);
  931                 ip6->ip6_flow = 0;
  932                 ip6->ip6_vfc = IPV6_VERSION;
  933                 ip6->ip6_hlim = V_ip6_defhlim;
  934                 ip6->ip6_nxt = proto;
  935                 ip6->ip6_dst = saidx->dst.sin6.sin6_addr;
  936                 /* For link-local address embed scope zone id */
  937                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
  938                         ip6->ip6_dst.s6_addr16[1] =
  939                             htons(saidx->dst.sin6.sin6_scope_id & 0xffff);
  940                 ip6->ip6_src = saidx->src.sin6.sin6_addr;
  941                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
  942                         ip6->ip6_src.s6_addr16[1] =
  943                             htons(saidx->src.sin6.sin6_scope_id & 0xffff);
  944                 ip6->ip6_plen = htons((*mp)->m_pkthdr.len - sizeof(*ip6));
  945                 ip_ecn_ingress(V_ip6_ipsec_ecn, &proto, &itos);
  946                 ip6->ip6_flow |= htonl((uint32_t)proto << 20);
  947                 break;
  948 #endif /* INET6 */
  949         default:
  950                 return (EAFNOSUPPORT);
  951         }
  952         (*mp)->m_flags &= ~(M_BCAST | M_MCAST);
  953         return (0);
  954 }
  955 

Cache object: 1ca28a6b77ed1026b6c94289feb6181c


[ 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.