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 /*      $FreeBSD: releng/5.0/sys/netipsec/ipsec_input.c 106680 2002-11-08 23:37:50Z sam $       */
    2 /*      $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
    3 
    4 /*
    5  * IPsec input processing.
    6  */
    7 
    8 #include "opt_inet.h"
    9 #include "opt_inet6.h"
   10 #include "opt_ipsec.h"
   11 
   12 #include <sys/param.h>
   13 #include <sys/systm.h>
   14 #include <sys/malloc.h>
   15 #include <sys/mbuf.h>
   16 #include <sys/domain.h>
   17 #include <sys/protosw.h>
   18 #include <sys/socket.h>
   19 #include <sys/errno.h>
   20 #include <sys/syslog.h>
   21 
   22 #include <net/if.h>
   23 #include <net/route.h>
   24 #include <net/netisr.h>
   25 
   26 #include <netinet/in.h>
   27 #include <netinet/in_systm.h>
   28 #include <netinet/ip.h>
   29 #include <netinet/ip_var.h>
   30 #include <netinet/in_var.h>
   31 
   32 #include <netinet/ip6.h>
   33 #ifdef INET6
   34 #include <netinet6/ip6_var.h>
   35 #endif
   36 #include <netinet/in_pcb.h>
   37 #ifdef INET6
   38 #include <netinet/icmp6.h>
   39 #endif
   40 
   41 #include <netipsec/ipsec.h>
   42 #ifdef INET6
   43 #include <netipsec/ipsec6.h>
   44 #endif
   45 #include <netipsec/ah_var.h>
   46 #include <netipsec/esp.h>
   47 #include <netipsec/esp_var.h>
   48 #include <netipsec/ipcomp_var.h>
   49 
   50 #include <netipsec/key.h>
   51 #include <netipsec/keydb.h>
   52 
   53 #include <netipsec/xform.h>
   54 #include <netinet6/ip6protosw.h>
   55 
   56 #include <machine/in_cksum.h>
   57 #include <machine/stdarg.h>
   58 
   59 #include <net/net_osdep.h>
   60 
   61 #define IPSEC_ISTAT(p,x,y,z) ((p) == IPPROTO_ESP ? (x)++ : \
   62                             (p) == IPPROTO_AH ? (y)++ : (z)++)
   63 
   64 /*
   65  * ipsec_common_input gets called when an IPsec-protected packet
   66  * is received by IPv4 or IPv6.  It's job is to find the right SA
   67  # and call the appropriate transform.  The transform callback
   68  * takes care of further processing (like ingress filtering).
   69  */
   70 static int
   71 ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
   72 {
   73         union sockaddr_union dst_address;
   74         struct secasvar *sav;
   75         u_int32_t spi;
   76         int s, error;
   77 
   78         IPSEC_ISTAT(sproto, espstat.esps_input, ahstat.ahs_input,
   79                 ipcompstat.ipcomps_input);
   80 
   81         KASSERT(m != NULL, ("ipsec_common_input: null packet"));
   82 
   83         if ((sproto == IPPROTO_ESP && !esp_enable) ||
   84             (sproto == IPPROTO_AH && !ah_enable) ||
   85             (sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
   86                 m_freem(m);
   87                 IPSEC_ISTAT(sproto, espstat.esps_pdrops, ahstat.ahs_pdrops,
   88                     ipcompstat.ipcomps_pdrops);
   89                 return EOPNOTSUPP;
   90         }
   91 
   92         if (m->m_pkthdr.len - skip < 2 * sizeof (u_int32_t)) {
   93                 m_freem(m);
   94                 IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops,
   95                     ipcompstat.ipcomps_hdrops);
   96                 DPRINTF(("ipsec_common_input: packet too small\n"));
   97                 return EINVAL;
   98         }
   99 
  100         /* Retrieve the SPI from the relevant IPsec header */
  101         if (sproto == IPPROTO_ESP)
  102                 m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
  103         else if (sproto == IPPROTO_AH)
  104                 m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
  105                     (caddr_t) &spi);
  106         else if (sproto == IPPROTO_IPCOMP) {
  107                 u_int16_t cpi;
  108                 m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t),
  109                     (caddr_t) &cpi);
  110                 spi = ntohl(htons(cpi));
  111         }
  112 
  113         /*
  114          * Find the SA and (indirectly) call the appropriate
  115          * kernel crypto routine. The resulting mbuf chain is a valid
  116          * IP packet ready to go through input processing.
  117          */
  118         bzero(&dst_address, sizeof (dst_address));
  119         dst_address.sa.sa_family = af;
  120         switch (af) {
  121 #ifdef INET
  122         case AF_INET:
  123                 dst_address.sin.sin_len = sizeof(struct sockaddr_in);
  124                 m_copydata(m, offsetof(struct ip, ip_dst),
  125                     sizeof(struct in_addr),
  126                     (caddr_t) &dst_address.sin.sin_addr);
  127                 break;
  128 #endif /* INET */
  129 #ifdef INET6
  130         case AF_INET6:
  131                 dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6);
  132                 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
  133                     sizeof(struct in6_addr),
  134                     (caddr_t) &dst_address.sin6.sin6_addr);
  135                 break;
  136 #endif /* INET6 */
  137         default:
  138                 DPRINTF(("ipsec_common_input: unsupported protocol "
  139                         "family %u\n", af));
  140                 m_freem(m);
  141                 IPSEC_ISTAT(sproto, espstat.esps_nopf, ahstat.ahs_nopf,
  142                     ipcompstat.ipcomps_nopf);
  143                 return EPFNOSUPPORT;
  144         }
  145 
  146         s = splnet();
  147 
  148         /* NB: only pass dst since key_allocsa follows RFC2401 */
  149         sav = KEY_ALLOCSA(&dst_address, sproto, spi);
  150         if (sav == NULL) {
  151                 DPRINTF(("ipsec_common_input: no key association found for"
  152                           " SA %s/%08lx/%u\n",
  153                           ipsec_address(&dst_address),
  154                           (u_long) ntohl(spi), sproto));
  155                 IPSEC_ISTAT(sproto, espstat.esps_notdb, ahstat.ahs_notdb,
  156                     ipcompstat.ipcomps_notdb);
  157                 splx(s);
  158                 m_freem(m);
  159                 return ENOENT;
  160         }
  161 
  162         if (sav->tdb_xform == NULL) {
  163                 DPRINTF(("ipsec_common_input: attempted to use uninitialized"
  164                          " SA %s/%08lx/%u\n",
  165                          ipsec_address(&dst_address),
  166                          (u_long) ntohl(spi), sproto));
  167                 IPSEC_ISTAT(sproto, espstat.esps_noxform, ahstat.ahs_noxform,
  168                     ipcompstat.ipcomps_noxform);
  169                 KEY_FREESAV(&sav);
  170                 splx(s);
  171                 m_freem(m);
  172                 return ENXIO;
  173         }
  174 
  175         /*
  176          * Call appropriate transform and return -- callback takes care of
  177          * everything else.
  178          */
  179         error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff);
  180         KEY_FREESAV(&sav);
  181         splx(s);
  182         return error;
  183 }
  184 
  185 #ifdef INET
  186 /*
  187  * Common input handler for IPv4 AH, ESP, and IPCOMP.
  188  */
  189 int
  190 ipsec4_common_input(struct mbuf *m, ...)
  191 {
  192         va_list ap;
  193         int off, nxt;
  194 
  195         va_start(ap, m);
  196         off = va_arg(ap, int);
  197         nxt = va_arg(ap, int);
  198         va_end(ap);
  199 
  200         return ipsec_common_input(m, off, offsetof(struct ip, ip_p),
  201                                   AF_INET, nxt);
  202 }
  203 
  204 void
  205 ah4_input(struct mbuf *m, int off)
  206 {
  207         ipsec4_common_input(m, off, IPPROTO_AH);
  208 }
  209 
  210 void
  211 esp4_input(struct mbuf *m, int off)
  212 {
  213         ipsec4_common_input(m, off, IPPROTO_ESP);
  214 }
  215 
  216 void
  217 ipcomp4_input(struct mbuf *m, int off)
  218 {
  219         ipsec4_common_input(m, off, IPPROTO_IPCOMP);
  220 }
  221 
  222 /*
  223  * IPsec input callback for INET protocols.
  224  * This routine is called as the transform callback.
  225  * Takes care of filtering and other sanity checks on
  226  * the processed packet.
  227  */
  228 int
  229 ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
  230                         int skip, int protoff, struct m_tag *mt)
  231 {
  232         int prot, af, sproto;
  233         struct ip *ip;
  234         struct m_tag *mtag;
  235         struct tdb_ident *tdbi;
  236         struct secasindex *saidx;
  237         int error;
  238 
  239 #if 0
  240         SPLASSERT(net, "ipsec4_common_input_cb");
  241 #endif
  242 
  243         KASSERT(m != NULL, ("ipsec4_common_input_cb: null mbuf"));
  244         KASSERT(sav != NULL, ("ipsec4_common_input_cb: null SA"));
  245         KASSERT(sav->sah != NULL, ("ipsec4_common_input_cb: null SAH"));
  246         saidx = &sav->sah->saidx;
  247         af = saidx->dst.sa.sa_family;
  248         KASSERT(af == AF_INET, ("ipsec4_common_input_cb: unexpected af %u",af));
  249         sproto = saidx->proto;
  250         KASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
  251                 sproto == IPPROTO_IPCOMP,
  252                 ("ipsec4_common_input_cb: unexpected security protocol %u",
  253                 sproto));
  254 
  255         /* Sanity check */
  256         if (m == NULL) {
  257                 DPRINTF(("ipsec4_common_input_cb: null mbuf"));
  258                 IPSEC_ISTAT(sproto, espstat.esps_badkcr, ahstat.ahs_badkcr,
  259                     ipcompstat.ipcomps_badkcr);
  260                 KEY_FREESAV(&sav);
  261                 return EINVAL;
  262         }
  263 
  264         if (skip != 0) {
  265                 /* Fix IPv4 header */
  266                 if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) {
  267                         DPRINTF(("ipsec4_common_input_cb: processing failed "
  268                             "for SA %s/%08lx\n",
  269                             ipsec_address(&sav->sah->saidx.dst),
  270                             (u_long) ntohl(sav->spi)));
  271                         IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops,
  272                             ipcompstat.ipcomps_hdrops);
  273                         error = ENOBUFS;
  274                         goto bad;
  275                 }
  276 
  277                 ip = mtod(m, struct ip *);
  278                 ip->ip_len = htons(m->m_pkthdr.len);
  279                 ip->ip_off = htons(ip->ip_off);
  280                 ip->ip_sum = 0;
  281                 ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
  282         } else {
  283                 ip = mtod(m, struct ip *);
  284         }
  285         prot = ip->ip_p;
  286 
  287         /* IP-in-IP encapsulation */
  288         if (prot == IPPROTO_IPIP) {
  289                 struct ip ipn;
  290 
  291                 /* ipn will now contain the inner IPv4 header */
  292                 m_copydata(m, ip->ip_hl << 2, sizeof(struct ip),
  293                     (caddr_t) &ipn);
  294 
  295 #ifdef notyet
  296                 /* XXX PROXY address isn't recorded in SAH */
  297                 /*
  298                  * Check that the inner source address is the same as
  299                  * the proxy address, if available.
  300                  */
  301                 if ((saidx->proxy.sa.sa_family == AF_INET &&
  302                     saidx->proxy.sin.sin_addr.s_addr !=
  303                     INADDR_ANY &&
  304                     ipn.ip_src.s_addr !=
  305                     saidx->proxy.sin.sin_addr.s_addr) ||
  306                     (saidx->proxy.sa.sa_family != AF_INET &&
  307                         saidx->proxy.sa.sa_family != 0)) {
  308 
  309                         DPRINTF(("ipsec4_common_input_cb: inner "
  310                             "source address %s doesn't correspond to "
  311                             "expected proxy source %s, SA %s/%08lx\n",
  312                             inet_ntoa4(ipn.ip_src),
  313                             ipsp_address(saidx->proxy),
  314                             ipsp_address(saidx->dst),
  315                             (u_long) ntohl(sav->spi)));
  316 
  317                         IPSEC_ISTAT(sproto, espstat.esps_pdrops,
  318                             ahstat.ahs_pdrops,
  319                             ipcompstat.ipcomps_pdrops);
  320                         error = EACCES;
  321                         goto bad;
  322                 }
  323 #endif /*XXX*/
  324         }
  325 #if INET6
  326         /* IPv6-in-IP encapsulation. */
  327         if (prot == IPPROTO_IPV6) {
  328                 struct ip6_hdr ip6n;
  329 
  330                 /* ip6n will now contain the inner IPv6 header. */
  331                 m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr),
  332                     (caddr_t) &ip6n);
  333 
  334 #ifdef notyet
  335                 /*
  336                  * Check that the inner source address is the same as
  337                  * the proxy address, if available.
  338                  */
  339                 if ((saidx->proxy.sa.sa_family == AF_INET6 &&
  340                     !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) &&
  341                     !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
  342                         &saidx->proxy.sin6.sin6_addr)) ||
  343                     (saidx->proxy.sa.sa_family != AF_INET6 &&
  344                         saidx->proxy.sa.sa_family != 0)) {
  345 
  346                         DPRINTF(("ipsec4_common_input_cb: inner "
  347                             "source address %s doesn't correspond to "
  348                             "expected proxy source %s, SA %s/%08lx\n",
  349                             ip6_sprintf(&ip6n.ip6_src),
  350                             ipsec_address(&saidx->proxy),
  351                             ipsec_address(&saidx->dst),
  352                             (u_long) ntohl(sav->spi)));
  353 
  354                         IPSEC_ISTAT(sproto, espstat.esps_pdrops,
  355                             ahstat.ahs_pdrops,
  356                             ipcompstat.ipcomps_pdrops);
  357                         error = EACCES;
  358                         goto bad;
  359                 }
  360 #endif /*XXX*/
  361         }
  362 #endif /* INET6 */
  363 
  364         /*
  365          * Record what we've done to the packet (under what SA it was
  366          * processed). If we've been passed an mtag, it means the packet
  367          * was already processed by an ethernet/crypto combo card and
  368          * thus has a tag attached with all the right information, but
  369          * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to
  370          * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type.
  371          */
  372         if (mt == NULL && sproto != IPPROTO_IPCOMP) {
  373                 mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
  374                     sizeof(struct tdb_ident), M_NOWAIT);
  375                 if (mtag == NULL) {
  376                         DPRINTF(("ipsec4_common_input_cb: failed to get tag\n"));
  377                         IPSEC_ISTAT(sproto, espstat.esps_hdrops,
  378                             ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops);
  379                         error = ENOMEM;
  380                         goto bad;
  381                 }
  382 
  383                 tdbi = (struct tdb_ident *)(mtag + 1);
  384                 bcopy(&saidx->dst, &tdbi->dst, saidx->dst.sa.sa_len);
  385                 tdbi->proto = sproto;
  386                 tdbi->spi = sav->spi;
  387 
  388                 m_tag_prepend(m, mtag);
  389         } else {
  390                 mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
  391                 /* XXX do we need to mark m_flags??? */
  392         }
  393 
  394         key_sa_recordxfer(sav, m);              /* record data transfer */
  395 
  396         /*
  397          * Re-dispatch via software interrupt.
  398          */
  399         if (!IF_HANDOFF(&ipintrq, m, NULL)) {
  400                 IPSEC_ISTAT(sproto, espstat.esps_qfull, ahstat.ahs_qfull,
  401                             ipcompstat.ipcomps_qfull);
  402 
  403                 DPRINTF(("ipsec4_common_input_cb: queue full; "
  404                         "proto %u packet dropped\n", sproto));
  405                 return ENOBUFS;
  406         }
  407         schednetisr(NETISR_IP);
  408         return 0;
  409 bad:
  410         m_freem(m);
  411         return error;
  412 }
  413 #endif /* INET */
  414 
  415 #ifdef INET6
  416 /* IPv6 AH wrapper. */
  417 int
  418 ipsec6_common_input(struct mbuf **mp, int *offp, int proto)
  419 {
  420         int l = 0;
  421         int protoff;
  422         struct ip6_ext ip6e;
  423 
  424         if (*offp < sizeof(struct ip6_hdr)) {
  425                 DPRINTF(("ipsec6_common_input: bad offset %u\n", *offp));
  426                 return IPPROTO_DONE;
  427         } else if (*offp == sizeof(struct ip6_hdr)) {
  428                 protoff = offsetof(struct ip6_hdr, ip6_nxt);
  429         } else {
  430                 /* Chase down the header chain... */
  431                 protoff = sizeof(struct ip6_hdr);
  432 
  433                 do {
  434                         protoff += l;
  435                         m_copydata(*mp, protoff, sizeof(ip6e),
  436                             (caddr_t) &ip6e);
  437 
  438                         if (ip6e.ip6e_nxt == IPPROTO_AH)
  439                                 l = (ip6e.ip6e_len + 2) << 2;
  440                         else
  441                                 l = (ip6e.ip6e_len + 1) << 3;
  442                         KASSERT(l > 0, ("ah6_input: l went zero or negative"));
  443                 } while (protoff + l < *offp);
  444 
  445                 /* Malformed packet check */
  446                 if (protoff + l != *offp) {
  447                         DPRINTF(("ipsec6_common_input: bad packet header chain, "
  448                                 "protoff %u, l %u, off %u\n", protoff, l, *offp));
  449                         IPSEC_ISTAT(proto, espstat.esps_hdrops,
  450                                     ahstat.ahs_hdrops,
  451                                     ipcompstat.ipcomps_hdrops);
  452                         m_freem(*mp);
  453                         *mp = NULL;
  454                         return IPPROTO_DONE;
  455                 }
  456                 protoff += offsetof(struct ip6_ext, ip6e_nxt);
  457         }
  458         (void) ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto);
  459         return IPPROTO_DONE;
  460 }
  461 
  462 void
  463 esp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
  464 {
  465         if (sa->sa_family != AF_INET6 ||
  466             sa->sa_len != sizeof(struct sockaddr_in6))
  467                 return;
  468         if ((unsigned)cmd >= PRC_NCMDS)
  469                 return;
  470 
  471         /* if the parameter is from icmp6, decode it. */
  472         if (d !=  NULL) {
  473                 struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
  474                 struct mbuf *m = ip6cp->ip6c_m;
  475                 int off = ip6cp->ip6c_off;
  476 
  477                 struct ip6ctlparam ip6cp1;
  478 
  479                 /*
  480                  * Notify the error to all possible sockets via pfctlinput2.
  481                  * Since the upper layer information (such as protocol type,
  482                  * source and destination ports) is embedded in the encrypted
  483                  * data and might have been cut, we can't directly call
  484                  * an upper layer ctlinput function. However, the pcbnotify
  485                  * function will consider source and destination addresses
  486                  * as well as the flow info value, and may be able to find
  487                  * some PCB that should be notified.
  488                  * Although pfctlinput2 will call esp6_ctlinput(), there is
  489                  * no possibility of an infinite loop of function calls,
  490                  * because we don't pass the inner IPv6 header.
  491                  */
  492                 bzero(&ip6cp1, sizeof(ip6cp1));
  493                 ip6cp1.ip6c_src = ip6cp->ip6c_src;
  494                 pfctlinput2(cmd, sa, (void *)&ip6cp1);
  495 
  496                 /*
  497                  * Then go to special cases that need ESP header information.
  498                  * XXX: We assume that when ip6 is non NULL,
  499                  * M and OFF are valid.
  500                  */
  501 
  502                 if (cmd == PRC_MSGSIZE) {
  503                         struct secasvar *sav;
  504                         u_int32_t spi;
  505                         int valid;
  506 
  507                         /* check header length before using m_copydata */
  508                         if (m->m_pkthdr.len < off + sizeof (struct esp))
  509                                 return;
  510                         m_copydata(m, off + offsetof(struct esp, esp_spi),
  511                                 sizeof(u_int32_t), (caddr_t) &spi);
  512                         /*
  513                          * Check to see if we have a valid SA corresponding to
  514                          * the address in the ICMP message payload.
  515                          */
  516                         sav = KEY_ALLOCSA((union sockaddr_union *)sa,
  517                                         IPPROTO_ESP, spi);
  518                         valid = (sav != NULL);
  519                         if (sav)
  520                                 KEY_FREESAV(&sav);
  521 
  522                         /* XXX Further validation? */
  523 
  524                         /*
  525                          * Depending on whether the SA is "valid" and
  526                          * routing table size (mtudisc_{hi,lo}wat), we will:
  527                          * - recalcurate the new MTU and create the
  528                          *   corresponding routing entry, or
  529                          * - ignore the MTU change notification.
  530                          */
  531                         icmp6_mtudisc_update(ip6cp, valid);
  532                 }
  533         } else {
  534                 /* we normally notify any pcb here */
  535         }
  536 }
  537 
  538 /*
  539  * IPsec input callback, called by the transform callback. Takes care of
  540  * filtering and other sanity checks on the processed packet.
  541  */
  542 int
  543 ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int protoff,
  544     struct m_tag *mt)
  545 {
  546         int prot, af, sproto;
  547         struct ip6_hdr *ip6;
  548         struct m_tag *mtag;
  549         struct tdb_ident *tdbi;
  550         struct secasindex *saidx;
  551         int nxt;
  552         u_int8_t nxt8;
  553         int error, nest;
  554 
  555         KASSERT(m != NULL, ("ipsec6_common_input_cb: null mbuf"));
  556         KASSERT(sav != NULL, ("ipsec6_common_input_cb: null SA"));
  557         KASSERT(sav->sah != NULL, ("ipsec6_common_input_cb: null SAH"));
  558         saidx = &sav->sah->saidx;
  559         af = saidx->dst.sa.sa_family;
  560         KASSERT(af == AF_INET6,
  561                 ("ipsec6_common_input_cb: unexpected af %u", af));
  562         sproto = saidx->proto;
  563         KASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
  564                 sproto == IPPROTO_IPCOMP,
  565                 ("ipsec6_common_input_cb: unexpected security protocol %u",
  566                 sproto));
  567 
  568         /* Sanity check */
  569         if (m == NULL) {
  570                 DPRINTF(("ipsec4_common_input_cb: null mbuf"));
  571                 IPSEC_ISTAT(sproto, espstat.esps_badkcr, ahstat.ahs_badkcr,
  572                     ipcompstat.ipcomps_badkcr);
  573                 error = EINVAL;
  574                 goto bad;
  575         }
  576 
  577         /* Fix IPv6 header */
  578         if (m->m_len < sizeof(struct ip6_hdr) &&
  579             (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
  580 
  581                 DPRINTF(("ipsec_common_input_cb: processing failed "
  582                     "for SA %s/%08lx\n", ipsec_address(&sav->sah->saidx.dst),
  583                     (u_long) ntohl(sav->spi)));
  584 
  585                 IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops,
  586                     ipcompstat.ipcomps_hdrops);
  587                 error = EACCES;
  588                 goto bad;
  589         }
  590 
  591         ip6 = mtod(m, struct ip6_hdr *);
  592         ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
  593 
  594         /* Save protocol */
  595         m_copydata(m, protoff, 1, (unsigned char *) &prot);
  596 
  597 #ifdef INET
  598         /* IP-in-IP encapsulation */
  599         if (prot == IPPROTO_IPIP) {
  600                 struct ip ipn;
  601 
  602                 /* ipn will now contain the inner IPv4 header */
  603                 m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
  604 
  605 #ifdef notyet
  606                 /*
  607                  * Check that the inner source address is the same as
  608                  * the proxy address, if available.
  609                  */
  610                 if ((saidx->proxy.sa.sa_family == AF_INET &&
  611                     saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY &&
  612                     ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) ||
  613                     (saidx->proxy.sa.sa_family != AF_INET &&
  614                         saidx->proxy.sa.sa_family != 0)) {
  615 
  616                         DPRINTF(("ipsec_common_input_cb: inner "
  617                             "source address %s doesn't correspond to "
  618                             "expected proxy source %s, SA %s/%08lx\n",
  619                             inet_ntoa4(ipn.ip_src),
  620                             ipsec_address(&saidx->proxy),
  621                             ipsec_address(&saidx->dst),
  622                             (u_long) ntohl(sav->spi)));
  623 
  624                         IPSEC_ISTATsproto, (espstat.esps_pdrops,
  625                             ahstat.ahs_pdrops, ipcompstat.ipcomps_pdrops);
  626                         error = EACCES;
  627                         goto bad;
  628                 }
  629 #endif /*XXX*/
  630         }
  631 #endif /* INET */
  632 
  633         /* IPv6-in-IP encapsulation */
  634         if (prot == IPPROTO_IPV6) {
  635                 struct ip6_hdr ip6n;
  636 
  637                 /* ip6n will now contain the inner IPv6 header. */
  638                 m_copydata(m, skip, sizeof(struct ip6_hdr),
  639                     (caddr_t) &ip6n);
  640 
  641 #ifdef notyet
  642                 /*
  643                  * Check that the inner source address is the same as
  644                  * the proxy address, if available.
  645                  */
  646                 if ((saidx->proxy.sa.sa_family == AF_INET6 &&
  647                     !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) &&
  648                     !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
  649                         &saidx->proxy.sin6.sin6_addr)) ||
  650                     (saidx->proxy.sa.sa_family != AF_INET6 &&
  651                         saidx->proxy.sa.sa_family != 0)) {
  652 
  653                         DPRINTF(("ipsec_common_input_cb: inner "
  654                             "source address %s doesn't correspond to "
  655                             "expected proxy source %s, SA %s/%08lx\n",
  656                             ip6_sprintf(&ip6n.ip6_src),
  657                             ipsec_address(&saidx->proxy),
  658                             ipsec_address(&saidx->dst),
  659                             (u_long) ntohl(sav->spi)));
  660 
  661                         IPSEC_ISTAT(sproto, espstat.esps_pdrops,
  662                             ahstat.ahs_pdrops, ipcompstat.ipcomps_pdrops);
  663                         error = EACCES;
  664                         goto bad;
  665                 }
  666 #endif /*XXX*/
  667         }
  668 
  669         /*
  670          * Record what we've done to the packet (under what SA it was
  671          * processed). If we've been passed an mtag, it means the packet
  672          * was already processed by an ethernet/crypto combo card and
  673          * thus has a tag attached with all the right information, but
  674          * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to
  675          * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type.
  676          */
  677         if (mt == NULL && sproto != IPPROTO_IPCOMP) {
  678                 mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
  679                     sizeof(struct tdb_ident), M_NOWAIT);
  680                 if (mtag == NULL) {
  681                         DPRINTF(("ipsec_common_input_cb: failed to "
  682                             "get tag\n"));
  683                         IPSEC_ISTAT(sproto, espstat.esps_hdrops,
  684                             ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops);
  685                         error = ENOMEM;
  686                         goto bad;
  687                 }
  688 
  689                 tdbi = (struct tdb_ident *)(mtag + 1);
  690                 bcopy(&saidx->dst, &tdbi->dst, sizeof(union sockaddr_union));
  691                 tdbi->proto = sproto;
  692                 tdbi->spi = sav->spi;
  693 
  694                 m_tag_prepend(m, mtag);
  695         } else {
  696                 mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
  697                 /* XXX do we need to mark m_flags??? */
  698         }
  699 
  700         key_sa_recordxfer(sav, m);
  701 
  702         /* Retrieve new protocol */
  703         m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
  704 
  705         /*
  706          * See the end of ip6_input for this logic.
  707          * IPPROTO_IPV[46] case will be processed just like other ones
  708          */
  709         nest = 0;
  710         nxt = nxt8;
  711         while (nxt != IPPROTO_DONE) {
  712                 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
  713                         ip6stat.ip6s_toomanyhdr++;
  714                         error = EINVAL;
  715                         goto bad;
  716                 }
  717 
  718                 /*
  719                  * Protection against faulty packet - there should be
  720                  * more sanity checks in header chain processing.
  721                  */
  722                 if (m->m_pkthdr.len < skip) {
  723                         ip6stat.ip6s_tooshort++;
  724                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
  725                         error = EINVAL;
  726                         goto bad;
  727                 }
  728                 /*
  729                  * Enforce IPsec policy checking if we are seeing last header.
  730                  * note that we do not visit this with protocols with pcb layer
  731                  * code - like udp/tcp/raw ip.
  732                  */
  733                 if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
  734                     ipsec6_in_reject(m, NULL)) {
  735                         error = EINVAL;
  736                         goto bad;
  737                 }
  738                 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt);
  739         }
  740         return 0;
  741 bad:
  742         if (m)
  743                 m_freem(m);
  744         return error;
  745 }
  746 #endif /* INET6 */

Cache object: a85a1776219599b9006313466a0acfa5


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