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 /*      $NetBSD: ipsec_input.c,v 1.79 2023/01/27 09:33:43 ozaki-r Exp $ */
    2 /*      $FreeBSD: ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $ */
    3 /*      $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $        */
    4 
    5 /*
    6  * The authors of this code are John Ioannidis (ji@tla.org),
    7  * Angelos D. Keromytis (kermit@csd.uch.gr) and
    8  * Niels Provos (provos@physnet.uni-hamburg.de).
    9  *
   10  * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
   11  * in November 1995.
   12  *
   13  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
   14  * by Angelos D. Keromytis.
   15  *
   16  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
   17  * and Niels Provos.
   18  *
   19  * Additional features in 1999 by Angelos D. Keromytis.
   20  *
   21  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
   22  * Angelos D. Keromytis and Niels Provos.
   23  * Copyright (c) 2001, Angelos D. Keromytis.
   24  *
   25  * Permission to use, copy, and modify this software with or without fee
   26  * is hereby granted, provided that this entire notice is included in
   27  * all copies of any software which is or includes a copy or
   28  * modification of this software.
   29  * You may use this code under the GNU public license if you so wish. Please
   30  * contribute changes back to the authors under this freer than GPL license
   31  * so that we may further the use of strong encryption without limitations to
   32  * all.
   33  *
   34  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
   35  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
   36  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
   37  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
   38  * PURPOSE.
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.79 2023/01/27 09:33:43 ozaki-r Exp $");
   43 
   44 /*
   45  * IPsec input processing.
   46  */
   47 
   48 #if defined(_KERNEL_OPT)
   49 #include "opt_inet.h"
   50 #endif
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h>
   54 #include <sys/mbuf.h>
   55 #include <sys/domain.h>
   56 #include <sys/protosw.h>
   57 #include <sys/socket.h>
   58 #include <sys/errno.h>
   59 #include <sys/syslog.h>
   60 
   61 #include <net/if.h>
   62 #include <net/route.h>
   63 
   64 #include <netinet/in.h>
   65 #include <netinet/in_systm.h>
   66 #include <netinet/ip.h>
   67 #include <netinet/ip_var.h>
   68 #include <netinet/in_var.h>
   69 #include <netinet/in_proto.h>
   70 #include <netinet/udp.h>
   71 #include <netinet/tcp.h>
   72 
   73 #include <netinet/ip6.h>
   74 #ifdef INET6
   75 #include <netinet6/in6.h>
   76 #include <netinet6/ip6_var.h>
   77 #include <netinet6/ip6_private.h>
   78 #include <netinet6/scope6_var.h>
   79 #endif
   80 #include <netinet/in_pcb.h>
   81 
   82 #include <netipsec/ipsec.h>
   83 #include <netipsec/ipsec_private.h>
   84 #ifdef INET6
   85 #include <netipsec/ipsec6.h>
   86 #endif
   87 #include <netipsec/ah_var.h>
   88 #include <netipsec/esp.h>
   89 #include <netipsec/esp_var.h>
   90 #include <netipsec/ipcomp_var.h>
   91 
   92 #include <netipsec/key.h>
   93 #include <netipsec/keydb.h>
   94 
   95 #include <netipsec/xform.h>
   96 #include <netinet6/ip6protosw.h>
   97 
   98 #define IPSEC_ISTAT(p, x, y, z)                                         \
   99 do {                                                                    \
  100         switch (p) {                                                    \
  101         case IPPROTO_ESP:                                               \
  102                 ESP_STATINC(x);                                         \
  103                 break;                                                  \
  104         case IPPROTO_AH:                                                \
  105                 AH_STATINC(y);                                          \
  106                 break;                                                  \
  107         default:                                                        \
  108                 IPCOMP_STATINC(z);                                      \
  109                 break;                                                  \
  110         }                                                               \
  111 } while (/*CONSTCOND*/0)
  112 
  113 /*
  114  * fixup TCP/UDP checksum
  115  *
  116  * XXX: if we have NAT-OA payload from IKE server,
  117  *      we must do the differential update of checksum.
  118  *
  119  * XXX: NAT-OAi/NAT-OAr derived from IKE initiator/responder.
  120  *      how to know the IKE side from kernel?
  121  */
  122 static struct mbuf *
  123 ipsec4_fixup_checksum(struct mbuf *m)
  124 {
  125         struct ip *ip;
  126         struct tcphdr *th;
  127         struct udphdr *uh;
  128         int poff, off;
  129         int plen;
  130 
  131         if (m->m_len < sizeof(*ip)) {
  132                 m = m_pullup(m, sizeof(*ip));
  133                 if (m == NULL)
  134                         return NULL;
  135         }
  136         ip = mtod(m, struct ip *);
  137         poff = ip->ip_hl << 2;
  138         plen = ntohs(ip->ip_len) - poff;
  139 
  140         switch (ip->ip_p) {
  141         case IPPROTO_TCP:
  142                 M_REGION_GET(th, struct tcphdr *, m, poff, sizeof(*th));
  143                 if (th == NULL)
  144                         return NULL;
  145                 off = th->th_off << 2;
  146                 if (off < sizeof(*th) || off > plen) {
  147                         m_freem(m);
  148                         return NULL;
  149                 }
  150                 th->th_sum = 0;
  151                 th->th_sum = in4_cksum(m, IPPROTO_TCP, poff, plen);
  152                 break;
  153         case IPPROTO_UDP:
  154                 M_REGION_GET(uh, struct udphdr *, m, poff, sizeof(*uh));
  155                 if (uh == NULL)
  156                         return NULL;
  157                 off = sizeof(*uh);
  158                 if (off > plen) {
  159                         m_freem(m);
  160                         return NULL;
  161                 }
  162                 uh->uh_sum = 0;
  163                 uh->uh_sum = in4_cksum(m, IPPROTO_UDP, poff, plen);
  164                 break;
  165         default:
  166                 /* no checksum */
  167                 return m;
  168         }
  169 
  170         return m;
  171 }
  172 
  173 static void
  174 nat_t_ports_get(struct mbuf *m, uint16_t *dport, uint16_t *sport)
  175 {
  176         struct m_tag *tag;
  177 
  178         if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS))) {
  179                 *sport = ((uint16_t *)(tag + 1))[0];
  180                 *dport = ((uint16_t *)(tag + 1))[1];
  181         } else
  182                 *sport = *dport = 0;
  183 }
  184 
  185 static uint32_t
  186 spi_get(struct mbuf *m, int sproto, int skip)
  187 {
  188         uint32_t spi;
  189         uint16_t cpi;
  190 
  191         switch (sproto) {
  192         case IPPROTO_ESP:
  193                 m_copydata(m, skip, sizeof(spi), &spi);
  194                 return spi;
  195         case IPPROTO_AH:
  196                 m_copydata(m, skip + sizeof(spi), sizeof(spi), &spi);
  197                 return spi;
  198         case IPPROTO_IPCOMP:
  199                 m_copydata(m, skip + sizeof(cpi), sizeof(cpi), &cpi);
  200                 return htonl(ntohs(cpi));
  201         default:
  202                 panic("%s called with bad protocol number: %d\n", __func__,
  203                     sproto);
  204         }
  205 }
  206 
  207 
  208 /*
  209  * ipsec_common_input gets called when an IPsec-protected packet
  210  * is received by IPv4 or IPv6.  Its job is to find the right SA
  211  * and call the appropriate transform.  The transform callback
  212  * takes care of further processing (like ingress filtering).
  213  */
  214 static int
  215 ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
  216 {
  217         char buf[IPSEC_ADDRSTRLEN], buf2[IPSEC_ADDRSTRLEN];
  218         union sockaddr_union src_address, dst_address;
  219         struct secasvar *sav;
  220         u_int32_t spi;
  221         u_int16_t sport;
  222         u_int16_t dport;
  223         int error;
  224 
  225         IPSEC_ISTAT(sproto, ESP_STAT_INPUT, AH_STAT_INPUT,
  226                 IPCOMP_STAT_INPUT);
  227 
  228         KASSERT(m != NULL);
  229 
  230         if ((sproto == IPPROTO_ESP && !esp_enable) ||
  231             (sproto == IPPROTO_AH && !ah_enable) ||
  232             (sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
  233                 m_freem(m);
  234                 IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, AH_STAT_PDROPS,
  235                     IPCOMP_STAT_PDROPS);
  236                 return EOPNOTSUPP;
  237         }
  238 
  239         if (m->m_pkthdr.len - skip < 2 * sizeof(u_int32_t)) {
  240                 m_freem(m);
  241                 IPSEC_ISTAT(sproto, ESP_STAT_HDROPS, AH_STAT_HDROPS,
  242                     IPCOMP_STAT_HDROPS);
  243                 IPSECLOG(LOG_DEBUG, "packet too small\n");
  244                 return EINVAL;
  245         }
  246 
  247         /* Retrieve the SPI from the relevant IPsec header */
  248         spi = spi_get(m, sproto, skip);
  249 
  250         /* find the source port for NAT-T */
  251         nat_t_ports_get(m, &dport, &sport);
  252 
  253         /*
  254          * Find the SA and (indirectly) call the appropriate
  255          * kernel crypto routine. The resulting mbuf chain is a valid
  256          * IP packet ready to go through input processing.
  257          */
  258         memset(&src_address, 0, sizeof (src_address));
  259         memset(&dst_address, 0, sizeof(dst_address));
  260         src_address.sa.sa_family = af;
  261         dst_address.sa.sa_family = af;
  262         switch (af) {
  263 #ifdef INET
  264         case AF_INET:
  265                 src_address.sin.sin_len = sizeof(struct sockaddr_in);
  266                 dst_address.sin.sin_len = sizeof(struct sockaddr_in);
  267                 m_copydata(m, offsetof(struct ip, ip_src),
  268                     sizeof(struct in_addr),
  269                     &src_address.sin.sin_addr);
  270                 m_copydata(m, offsetof(struct ip, ip_dst),
  271                     sizeof(struct in_addr),
  272                     &dst_address.sin.sin_addr);
  273                 break;
  274 #endif
  275 #ifdef INET6
  276         case AF_INET6:
  277                 src_address.sin6.sin6_len = sizeof(struct sockaddr_in6);
  278                 dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6);
  279                 m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
  280                     sizeof(struct in6_addr),
  281                     &src_address.sin6.sin6_addr);
  282                 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
  283                     sizeof(struct in6_addr),
  284                     &dst_address.sin6.sin6_addr);
  285                 if (sa6_recoverscope(&dst_address.sin6)) {
  286                         m_freem(m);
  287                         return EINVAL;
  288                 }
  289                 break;
  290 #endif
  291         default:
  292                 IPSECLOG(LOG_DEBUG, "unsupported protocol family %u\n", af);
  293                 m_freem(m);
  294                 IPSEC_ISTAT(sproto, ESP_STAT_NOPF, AH_STAT_NOPF,
  295                     IPCOMP_STAT_NOPF);
  296                 return EPFNOSUPPORT;
  297         }
  298 
  299         /* NB: only pass dst since key_lookup_sa follows RFC2401 */
  300         sav = KEY_LOOKUP_SA(&dst_address, sproto, spi, sport, dport);
  301         if (sav == NULL) {
  302                 static struct timeval lasttime = {0, 0};
  303                 static int curpps = 0;
  304 
  305                 if (!ipsec_debug && ppsratecheck(&lasttime, &curpps, 1)) {
  306                         if (sport || dport) {
  307                                 log(LOG_INFO,
  308                                     "no key association found for SA"
  309                                     " %s[%u]-%s[%u]/SPI 0x%08lx\n",
  310                                     ipsec_address(&src_address, buf, sizeof(buf)),
  311                                     ntohs(sport),
  312                                     ipsec_address(&dst_address, buf2, sizeof(buf2)),
  313                                     ntohs(dport),
  314                                     (u_long) ntohl(spi));
  315                         } else {
  316                                 log(LOG_INFO,
  317                                     "no key association found for"
  318                                     " SA %s-%s/SPI 0x%08lx\n",
  319                                     ipsec_address(&src_address, buf, sizeof(buf)),
  320                                     ipsec_address(&src_address, buf2, sizeof(buf2)),
  321                                     (u_long) ntohl(spi));
  322                         }
  323                 } else if (ipsec_debug) {
  324                         IPSECLOG(LOG_DEBUG,
  325                             "no key association found for SA "
  326                             "%s-%s/SPI 0x%08lx/PROTO %u/PORT %u-%u\n",
  327                             ipsec_address(&src_address, buf, sizeof(buf)),
  328                             ipsec_address(&dst_address, buf2, sizeof(buf2)),
  329                              (u_long) ntohl(spi), sproto, ntohs(dport), ntohs(sport));
  330                 }
  331                 IPSEC_ISTAT(sproto, ESP_STAT_NOTDB, AH_STAT_NOTDB,
  332                     IPCOMP_STAT_NOTDB);
  333                 m_freem(m);
  334                 return ENOENT;
  335         }
  336 
  337         KASSERT(sav->tdb_xform != NULL);
  338 
  339         /*
  340          * Call appropriate transform and return -- callback takes care of
  341          * everything else.
  342          */
  343         error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff);
  344         KEY_SA_UNREF(&sav);
  345         return error;
  346 }
  347 
  348 #ifdef INET
  349 /*
  350  * Common input handler for IPv4 AH, ESP, and IPCOMP.
  351  */
  352 void
  353 ipsec4_common_input(struct mbuf *m, int off, int proto)
  354 {
  355         (void)ipsec_common_input(m, off, offsetof(struct ip, ip_p),
  356             AF_INET, proto);
  357 }
  358 
  359 /*
  360  * IPsec input callback for INET protocols.
  361  * This routine is called as the transform callback.
  362  * Takes care of filtering and other sanity checks on
  363  * the processed packet.
  364  */
  365 int
  366 ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
  367     int skip, int protoff)
  368 {
  369         int prot, af __diagused, sproto;
  370         struct ip *ip;
  371         struct secasindex *saidx;
  372         int error;
  373 
  374         if (__predict_false(m == NULL)) {
  375                 panic("%s: NULL mbuf", __func__);
  376         }
  377         if (__predict_false(skip < sizeof(struct ip))) {
  378                 panic("%s: short skip", __func__);
  379         }
  380 
  381         KASSERT(sav != NULL);
  382         saidx = &sav->sah->saidx;
  383         af = saidx->dst.sa.sa_family;
  384         KASSERTMSG(af == AF_INET, "unexpected af %u", af);
  385         sproto = saidx->proto;
  386         KASSERTMSG(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
  387             sproto == IPPROTO_IPCOMP,
  388             "unexpected security protocol %u", sproto);
  389 
  390         /*
  391          * Update the IPv4 header. The length of the packet may have changed,
  392          * so fix it, and recompute the checksum.
  393          */
  394         if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) {
  395                 char buf[IPSEC_ADDRSTRLEN];
  396 cantpull:
  397                 IPSECLOG(LOG_DEBUG,
  398                     "processing failed for SA %s/%08lx\n",
  399                     ipsec_address(&sav->sah->saidx.dst, buf,
  400                     sizeof(buf)), (u_long) ntohl(sav->spi));
  401                 IPSEC_ISTAT(sproto, ESP_STAT_HDROPS, AH_STAT_HDROPS,
  402                     IPCOMP_STAT_HDROPS);
  403                 error = ENOBUFS;
  404                 goto bad;
  405         }
  406         ip = mtod(m, struct ip *);
  407         ip->ip_len = htons(m->m_pkthdr.len);
  408         ip->ip_sum = 0;
  409         ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
  410 
  411         /*
  412          * Update TCP/UDP checksum
  413          * XXX: should only do it in NAT-T case
  414          * XXX: should do it incrementally, see FreeBSD code.
  415          */
  416         m = ipsec4_fixup_checksum(m);
  417         if (m == NULL)
  418                 goto cantpull;
  419         ip = mtod(m, struct ip *);
  420 
  421         prot = ip->ip_p;
  422 
  423         M_VERIFY_PACKET(m);
  424 
  425         key_sa_recordxfer(sav, m);
  426 
  427         if ((inetsw[ip_protox[prot]].pr_flags & PR_LASTHDR) != 0 &&
  428             ipsec_in_reject(m, NULL)) {
  429                 error = EINVAL;
  430                 goto bad;
  431         }
  432 
  433         /*
  434          * There is no struct ifnet for tunnel mode IP-IP tunnel connecttion,
  435          * so we cannot write filtering rule to the inner packet.
  436          */
  437         if (saidx->mode == IPSEC_MODE_TUNNEL)
  438                 m->m_pkthdr.pkthdr_flags |= PKTHDR_FLAG_IPSEC_SKIP_PFIL;
  439 
  440         (*inetsw[ip_protox[prot]].pr_input)(m, skip, prot);
  441         return 0;
  442 
  443 bad:
  444         m_freem(m);
  445         return error;
  446 }
  447 #endif /* INET */
  448 
  449 #ifdef INET6
  450 int
  451 ipsec6_common_input(struct mbuf **mp, int *offp, int proto)
  452 {
  453         int l = 0;
  454         int protoff, nxt;
  455         struct ip6_ext ip6e;
  456 
  457         if (*offp < sizeof(struct ip6_hdr)) {
  458                 IPSECLOG(LOG_DEBUG, "bad offset %u\n", *offp);
  459                 IPSEC_ISTAT(proto, ESP_STAT_HDROPS, AH_STAT_HDROPS,
  460                             IPCOMP_STAT_HDROPS);
  461                 m_freem(*mp);
  462                 return IPPROTO_DONE;
  463         } else if (*offp == sizeof(struct ip6_hdr)) {
  464                 protoff = offsetof(struct ip6_hdr, ip6_nxt);
  465         } else {
  466                 /* Chase down the header chain... */
  467                 protoff = sizeof(struct ip6_hdr);
  468                 nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt;
  469 
  470                 do {
  471                         protoff += l;
  472                         m_copydata(*mp, protoff, sizeof(ip6e), &ip6e);
  473 
  474                         if (nxt == IPPROTO_AH)
  475                                 l = (ip6e.ip6e_len + 2) << 2;
  476                         else if (nxt == IPPROTO_FRAGMENT)
  477                                 l = sizeof(struct ip6_frag);
  478                         else
  479                                 l = (ip6e.ip6e_len + 1) << 3;
  480                         KASSERT(l > 0);
  481 
  482                         nxt = ip6e.ip6e_nxt;
  483                 } while (protoff + l < *offp);
  484 
  485                 /* Malformed packet check */
  486                 if (protoff + l != *offp) {
  487                         IPSECLOG(LOG_DEBUG, "bad packet header chain, "
  488                             "protoff %u, l %u, off %u\n", protoff, l, *offp);
  489                         IPSEC_ISTAT(proto, ESP_STAT_HDROPS,
  490                                     AH_STAT_HDROPS,
  491                                     IPCOMP_STAT_HDROPS);
  492                         m_freem(*mp);
  493                         *mp = NULL;
  494                         return IPPROTO_DONE;
  495                 }
  496                 protoff += offsetof(struct ip6_ext, ip6e_nxt);
  497         }
  498         (void) ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto);
  499         return IPPROTO_DONE;
  500 }
  501 
  502 /*
  503  * IPsec input callback, called by the transform callback. Takes care of
  504  * filtering and other sanity checks on the processed packet.
  505  */
  506 int
  507 ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
  508     int protoff)
  509 {
  510         int af __diagused, sproto;
  511         struct ip6_hdr *ip6;
  512         struct secasindex *saidx;
  513         int nxt;
  514         u_int8_t prot;
  515         int error, nest;
  516 
  517         if (__predict_false(m == NULL)) {
  518                 panic("%s: NULL mbuf", __func__);
  519         }
  520 
  521         KASSERT(sav != NULL);
  522         saidx = &sav->sah->saidx;
  523         af = saidx->dst.sa.sa_family;
  524         KASSERTMSG(af == AF_INET6, "unexpected af %u", af);
  525         sproto = saidx->proto;
  526         KASSERTMSG(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
  527             sproto == IPPROTO_IPCOMP,
  528             "unexpected security protocol %u", sproto);
  529 
  530         /* Fix IPv6 header */
  531         if (m->m_len < sizeof(struct ip6_hdr) &&
  532             (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
  533                 char buf[IPSEC_ADDRSTRLEN];
  534                 IPSECLOG(LOG_DEBUG, "processing failed for SA %s/%08lx\n",
  535                     ipsec_address(&sav->sah->saidx.dst,
  536                     buf, sizeof(buf)), (u_long) ntohl(sav->spi));
  537                 IPSEC_ISTAT(sproto, ESP_STAT_HDROPS, AH_STAT_HDROPS,
  538                     IPCOMP_STAT_HDROPS);
  539                 error = EACCES;
  540                 goto bad;
  541         }
  542 
  543         ip6 = mtod(m, struct ip6_hdr *);
  544         ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
  545 
  546         m_copydata(m, protoff, sizeof(prot), &prot);
  547 
  548         key_sa_recordxfer(sav, m);
  549 
  550         /*
  551          * See the end of ip6_input for this logic.
  552          * IPPROTO_IPV[46] case will be processed just like other ones
  553          */
  554         nest = 0;
  555         nxt = prot;
  556         while (nxt != IPPROTO_DONE) {
  557                 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
  558                         IP6_STATINC(IP6_STAT_TOOMANYHDR);
  559                         error = EINVAL;
  560                         goto bad;
  561                 }
  562 
  563                 M_VERIFY_PACKET(m);
  564 
  565                 /*
  566                  * Protection against faulty packet - there should be
  567                  * more sanity checks in header chain processing.
  568                  */
  569                 if (m->m_pkthdr.len < skip) {
  570                         IP6_STATINC(IP6_STAT_TOOSHORT);
  571                         in6_ifstat_inc(m_get_rcvif_NOMPSAFE(m),
  572                             ifs6_in_truncated);
  573                         error = EINVAL;
  574                         goto bad;
  575                 }
  576 
  577                 /*
  578                  * Enforce IPsec policy checking if we are seeing last header.
  579                  * Note that we do not visit this with protocols with pcb layer
  580                  * code - like udp/tcp/raw ip.
  581                  */
  582                 if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
  583                     ipsec_in_reject(m, NULL)) {
  584                         error = EINVAL;
  585                         goto bad;
  586                 }
  587 
  588                 /*
  589                  * There is no struct ifnet for tunnel mode IP-IP tunnel connecttion,
  590                  * so we cannot write filtering rule to the inner packet.
  591                  */
  592                 if (saidx->mode == IPSEC_MODE_TUNNEL)
  593                         m->m_pkthdr.pkthdr_flags |= PKTHDR_FLAG_IPSEC_SKIP_PFIL;
  594 
  595                 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt);
  596         }
  597         return 0;
  598 
  599 bad:
  600         if (m)
  601                 m_freem(m);
  602         return error;
  603 }
  604 #endif /* INET6 */

Cache object: add7e3a7ee458cca55901252af2d044c


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