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/xform_ipip.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: xform_ipip.c,v 1.78 2022/05/22 11:39:08 riastradh Exp $        */
    2 /*      $FreeBSD: xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $  */
    3 /*      $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun 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  * The original version of this code was written by John Ioannidis
   11  * for BSD/OS in Athens, Greece, 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: xform_ipip.c,v 1.78 2022/05/22 11:39:08 riastradh Exp $");
   43 
   44 #if defined(_KERNEL_OPT)
   45 #include "opt_inet.h"
   46 #endif
   47 
   48 /*
   49  * IP-inside-IP processing.
   50  *
   51  * The input point is encapsw{4,6}, called via the encap callback. The
   52  * output point is ipip_output, called directly. XF_IP4 has no more
   53  * meaning here, ipe4_xformsw is dummy.
   54  */
   55 
   56 #include <sys/param.h>
   57 #include <sys/systm.h>
   58 #include <sys/mbuf.h>
   59 #include <sys/kernel.h>
   60 #include <sys/protosw.h>
   61 
   62 #include <net/if.h>
   63 
   64 #include <netinet/in.h>
   65 #include <netinet/in_systm.h>
   66 #include <netinet/in_var.h>
   67 #include <netinet/ip.h>
   68 #include <netinet/ip_ecn.h>
   69 #include <netinet/ip_var.h>
   70 #include <netinet/ip_encap.h>
   71 
   72 #include <netipsec/ipsec.h>
   73 #include <netipsec/ipsec_private.h>
   74 #include <netipsec/xform.h>
   75 
   76 #include <netipsec/ipip_var.h>
   77 
   78 #ifdef INET6
   79 #include <netinet/ip6.h>
   80 #include <netipsec/ipsec6.h>
   81 #include <netinet6/in6_var.h>
   82 #include <netinet6/ip6protosw.h>
   83 #endif
   84 
   85 #include <netipsec/key.h>
   86 #include <netipsec/key_debug.h>
   87 
   88 /* XXX IPCOMP */
   89 #define M_IPSEC (M_AUTHIPHDR|M_DECRYPTED)
   90 
   91 int ipip_spoofcheck = 1;
   92 percpu_t *ipipstat_percpu;
   93 
   94 static void _ipip_input(struct mbuf *, int);
   95 
   96 #ifdef INET6
   97 static int
   98 ip4_input6(struct mbuf **m, int *offp, int proto, void *eparg __unused)
   99 {
  100         _ipip_input(*m, *offp);
  101         return IPPROTO_DONE;
  102 }
  103 #endif
  104 
  105 #ifdef INET
  106 static void
  107 ip4_input(struct mbuf *m, int off, int proto, void *eparg __unused)
  108 {
  109         _ipip_input(m, off);
  110 }
  111 #endif
  112 
  113 /*
  114  * _ipip_input gets called when we receive an IP{46} encapsulated packet,
  115  * because AH or ESP were being used in tunnel mode.
  116  */
  117 static void
  118 _ipip_input(struct mbuf *m, int iphlen)
  119 {
  120         register struct sockaddr_in *sin;
  121         register struct ifnet *ifp;
  122         register struct ifaddr *ifa;
  123         pktqueue_t *pktq = NULL;
  124         struct ip *ip4 = NULL;
  125 #ifdef INET6
  126         register struct sockaddr_in6 *sin6;
  127         struct ip6_hdr *ip6 = NULL;
  128         uint8_t itos;
  129 #endif
  130         uint8_t otos;
  131         uint8_t v;
  132         int hlen;
  133 
  134         IPIP_STATINC(IPIP_STAT_IPACKETS);
  135 
  136         m_copydata(m, 0, 1, &v);
  137 
  138         switch (v >> 4) {
  139 #ifdef INET
  140         case 4:
  141                 hlen = sizeof(struct ip);
  142                 break;
  143 #endif
  144 #ifdef INET6
  145         case 6:
  146                 hlen = sizeof(struct ip6_hdr);
  147                 break;
  148 #endif
  149         default:
  150                 DPRINTF("bad protocol version 0x%x (%u) "
  151                     "for outer header\n", v, v>>4);
  152                 IPIP_STATINC(IPIP_STAT_FAMILY);
  153                 m_freem(m);
  154                 return;
  155         }
  156 
  157         /* Bring the IP header in the first mbuf, if not there already */
  158         if (m->m_len < hlen) {
  159                 if ((m = m_pullup(m, hlen)) == NULL) {
  160                         DPRINTF("m_pullup (1) failed\n");
  161                         IPIP_STATINC(IPIP_STAT_HDROPS);
  162                         return;
  163                 }
  164         }
  165 
  166         /* Keep outer ecn field. */
  167         switch (v >> 4) {
  168 #ifdef INET
  169         case 4:
  170                 otos = mtod(m, struct ip *)->ip_tos;
  171                 break;
  172 #endif
  173 #ifdef INET6
  174         case 6:
  175                 otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
  176                 break;
  177 #endif
  178         default:
  179                 panic("%s: impossible (1)", __func__);
  180         }
  181 
  182         /* Remove outer IP header */
  183         m_adj(m, iphlen);
  184 
  185         /* Sanity check */
  186         if (m->m_pkthdr.len < sizeof(struct ip))  {
  187                 IPIP_STATINC(IPIP_STAT_HDROPS);
  188                 m_freem(m);
  189                 return;
  190         }
  191 
  192         m_copydata(m, 0, 1, &v);
  193 
  194         switch (v >> 4) {
  195 #ifdef INET
  196         case 4:
  197                 hlen = sizeof(struct ip);
  198                 pktq = ip_pktq;
  199                 break;
  200 #endif
  201 #ifdef INET6
  202         case 6:
  203                 hlen = sizeof(struct ip6_hdr);
  204                 pktq = ip6_pktq;
  205                 break;
  206 #endif
  207         default:
  208                 DPRINTF("bad protocol version %#x (%u) "
  209                     "for inner header\n", v, v >> 4);
  210                 IPIP_STATINC(IPIP_STAT_FAMILY);
  211                 m_freem(m);
  212                 return;
  213         }
  214 
  215         /*
  216          * Bring the inner IP header in the first mbuf, if not there already.
  217          */
  218         if (m->m_len < hlen) {
  219                 if ((m = m_pullup(m, hlen)) == NULL) {
  220                         DPRINTF("m_pullup (2) failed\n");
  221                         IPIP_STATINC(IPIP_STAT_HDROPS);
  222                         return;
  223                 }
  224         }
  225 
  226         /*
  227          * RFC 1853 specifies that the inner TTL should not be touched on
  228          * decapsulation. There's no reason this comment should be here, but
  229          * this is as good as any a position.
  230          */
  231 
  232         /* Some sanity checks in the inner IP header */
  233         switch (v >> 4) {
  234 #ifdef INET
  235         case 4:
  236                 ip4 = mtod(m, struct ip *);
  237                 ip_ecn_egress(ip4_ipsec_ecn, &otos, &ip4->ip_tos);
  238                 break;
  239 #endif
  240 #ifdef INET6
  241         case 6:
  242                 ip6 = mtod(m, struct ip6_hdr *);
  243                 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
  244                 ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos);
  245                 ip6->ip6_flow &= ~htonl(0xff << 20);
  246                 ip6->ip6_flow |= htonl((uint32_t)itos << 20);
  247                 break;
  248 #endif
  249         default:
  250                 panic("%s: impossible (2)", __func__);
  251         }
  252 
  253         /* Check for local address spoofing. */
  254         if ((m_get_rcvif_NOMPSAFE(m) == NULL ||
  255             !(m_get_rcvif_NOMPSAFE(m)->if_flags & IFF_LOOPBACK)) &&
  256             ipip_spoofcheck) {
  257                 int s = pserialize_read_enter();
  258                 IFNET_READER_FOREACH(ifp) {
  259                         IFADDR_READER_FOREACH(ifa, ifp) {
  260 #ifdef INET
  261                                 if (ip4) {
  262                                         if (ifa->ifa_addr->sa_family !=
  263                                             AF_INET)
  264                                                 continue;
  265 
  266                                         sin = (struct sockaddr_in *)ifa->ifa_addr;
  267 
  268                                         if (sin->sin_addr.s_addr ==
  269                                             ip4->ip_src.s_addr) {
  270                                                 pserialize_read_exit(s);
  271                                                 IPIP_STATINC(IPIP_STAT_SPOOF);
  272                                                 m_freem(m);
  273                                                 return;
  274                                         }
  275                                 }
  276 #endif
  277 
  278 #ifdef INET6
  279                                 if (ip6) {
  280                                         if (ifa->ifa_addr->sa_family !=
  281                                             AF_INET6)
  282                                                 continue;
  283 
  284                                         sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
  285 
  286                                         if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
  287                                                 pserialize_read_exit(s);
  288                                                 IPIP_STATINC(IPIP_STAT_SPOOF);
  289                                                 m_freem(m);
  290                                                 return;
  291                                         }
  292 
  293                                 }
  294 #endif
  295                         }
  296                 }
  297                 pserialize_read_exit(s);
  298         }
  299 
  300         /* Statistics: m->m_pkthdr.len is the length of the inner packet */
  301         IPIP_STATADD(IPIP_STAT_IBYTES, m->m_pkthdr.len);
  302 
  303         /*
  304          * Interface pointer stays the same; if no IPsec processing has
  305          * been done (or will be done), this will point to a normal
  306          * interface. Otherwise, it'll point to an enc interface, which
  307          * will allow a packet filter to distinguish between secure and
  308          * untrusted packets.
  309          */
  310 
  311         int s = splnet();
  312         if (__predict_false(!pktq_enqueue(pktq, m, 0))) {
  313                 IPIP_STATINC(IPIP_STAT_QFULL);
  314                 m_freem(m);
  315         }
  316         splx(s);
  317 }
  318 
  319 int
  320 ipip_output(struct mbuf *m, struct secasvar *sav, struct mbuf **mp)
  321 {
  322         char buf[IPSEC_ADDRSTRLEN];
  323         uint8_t tp, otos;
  324         struct secasindex *saidx;
  325         int error, iphlen;
  326 #ifdef INET
  327         uint8_t itos;
  328         struct ip *ipo;
  329 #endif
  330 #ifdef INET6
  331         struct ip6_hdr *ip6, *ip6o;
  332 #endif
  333 
  334         KASSERT(sav != NULL);
  335 
  336         /* XXX Deal with empty TDB source/destination addresses. */
  337 
  338         m_copydata(m, 0, 1, &tp);
  339         tp = (tp >> 4) & 0xff;  /* Get the IP version number. */
  340 
  341         saidx = &sav->sah->saidx;
  342         switch (saidx->dst.sa.sa_family) {
  343 #ifdef INET
  344         case AF_INET:
  345                 if (saidx->src.sa.sa_family != AF_INET ||
  346                     saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
  347                     saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) {
  348                         DPRINTF("unspecified tunnel endpoint "
  349                             "address in SA %s/%08lx\n",
  350                             ipsec_address(&saidx->dst, buf, sizeof(buf)),
  351                             (u_long)ntohl(sav->spi));
  352                         IPIP_STATINC(IPIP_STAT_UNSPEC);
  353                         error = EINVAL;
  354                         goto bad;
  355                 }
  356 
  357                 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
  358                 if (m == NULL) {
  359                         DPRINTF("M_PREPEND failed\n");
  360                         IPIP_STATINC(IPIP_STAT_HDROPS);
  361                         error = ENOBUFS;
  362                         goto bad;
  363                 }
  364 
  365                 iphlen = sizeof(struct ip);
  366 
  367                 ipo = mtod(m, struct ip *);
  368                 ipo->ip_v = IPVERSION;
  369                 ipo->ip_hl = 5;
  370                 ipo->ip_len = htons(m->m_pkthdr.len);
  371                 ipo->ip_ttl = ip_defttl;
  372                 ipo->ip_sum = 0;
  373                 ipo->ip_src = saidx->src.sin.sin_addr;
  374                 ipo->ip_dst = saidx->dst.sin.sin_addr;
  375                 ipo->ip_id = ip_newid(NULL);
  376 
  377                 /* If the inner protocol is IP... */
  378                 if (tp == IPVERSION) {
  379                         /* Save ECN notification */
  380                         m_copydata(m, sizeof(struct ip) +
  381                             offsetof(struct ip, ip_tos),
  382                             sizeof(uint8_t), &itos);
  383 
  384                         ipo->ip_p = IPPROTO_IPIP;
  385 
  386                         /*
  387                          * We should be keeping tunnel soft-state and
  388                          * send back ICMPs if needed.
  389                          */
  390                         m_copydata(m, sizeof(struct ip) +
  391                             offsetof(struct ip, ip_off),
  392                             sizeof(uint16_t), &ipo->ip_off);
  393                         ipo->ip_off &= ~ htons(IP_DF | IP_MF | IP_OFFMASK);
  394                 }
  395 #ifdef INET6
  396                 else if (tp == (IPV6_VERSION >> 4)) {
  397                         uint32_t itos32;
  398 
  399                         /* Save ECN notification. */
  400                         m_copydata(m, sizeof(struct ip) +
  401                             offsetof(struct ip6_hdr, ip6_flow),
  402                             sizeof(uint32_t), &itos32);
  403                         itos = ntohl(itos32) >> 20;
  404                         ipo->ip_p = IPPROTO_IPV6;
  405                         ipo->ip_off = 0;
  406                 }
  407 #endif
  408                 else {
  409                         goto nofamily;
  410                 }
  411 
  412                 otos = 0;
  413                 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
  414                 ipo->ip_tos = otos;
  415                 break;
  416 #endif /* INET */
  417 
  418 #ifdef INET6
  419         case AF_INET6:
  420                 if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) ||
  421                     saidx->src.sa.sa_family != AF_INET6 ||
  422                     IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) {
  423                         DPRINTF("unspecified tunnel endpoint "
  424                             "address in SA %s/%08lx\n",
  425                             ipsec_address(&saidx->dst, buf, sizeof(buf)),
  426                             (u_long)ntohl(sav->spi));
  427                         IPIP_STATINC(IPIP_STAT_UNSPEC);
  428                         error = ENOBUFS;
  429                         goto bad;
  430                 }
  431 
  432                 if (tp == (IPV6_VERSION >> 4)) {
  433                         /* scoped address handling */
  434                         ip6 = mtod(m, struct ip6_hdr *);
  435                         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
  436                                 ip6->ip6_src.s6_addr16[1] = 0;
  437                         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
  438                                 ip6->ip6_dst.s6_addr16[1] = 0;
  439                 }
  440 
  441                 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
  442                 if (m == NULL) {
  443                         DPRINTF("M_PREPEND failed\n");
  444                         IPIP_STATINC(IPIP_STAT_HDROPS);
  445                         error = ENOBUFS;
  446                         goto bad;
  447                 }
  448 
  449                 iphlen = sizeof(struct ip6_hdr);
  450 
  451                 /* Initialize IPv6 header */
  452                 ip6o = mtod(m, struct ip6_hdr *);
  453                 ip6o->ip6_flow = 0;
  454                 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
  455                 ip6o->ip6_vfc |= IPV6_VERSION;
  456                 ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o));
  457                 ip6o->ip6_hlim = ip_defttl;
  458                 ip6o->ip6_dst = saidx->dst.sin6.sin6_addr;
  459                 ip6o->ip6_src = saidx->src.sin6.sin6_addr;
  460                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_dst))
  461                         ip6o->ip6_dst.s6_addr16[1] = htons(saidx->dst.sin6.sin6_scope_id);
  462                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_src))
  463                         ip6o->ip6_src.s6_addr16[1] = htons(saidx->src.sin6.sin6_scope_id);
  464 
  465 #ifdef INET
  466                 if (tp == IPVERSION) {
  467                         /* Save ECN notification */
  468                         m_copydata(m, sizeof(struct ip6_hdr) +
  469                             offsetof(struct ip, ip_tos), sizeof(uint8_t),
  470                             &itos);
  471 
  472                         /* This is really IPVERSION. */
  473                         ip6o->ip6_nxt = IPPROTO_IPIP;
  474                 } else
  475 #endif
  476                 if (tp == (IPV6_VERSION >> 4)) {
  477                         uint32_t itos32;
  478 
  479                         /* Save ECN notification. */
  480                         m_copydata(m, sizeof(struct ip6_hdr) +
  481                             offsetof(struct ip6_hdr, ip6_flow),
  482                             sizeof(uint32_t), &itos32);
  483                         itos = ntohl(itos32) >> 20;
  484 
  485                         ip6o->ip6_nxt = IPPROTO_IPV6;
  486                 } else {
  487                         goto nofamily;
  488                 }
  489 
  490                 otos = 0;
  491                 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
  492                 ip6o->ip6_flow |= htonl((uint32_t)otos << 20);
  493                 break;
  494 #endif /* INET6 */
  495 
  496         default:
  497 nofamily:
  498                 DPRINTF("unsupported protocol family %u\n",
  499                     saidx->dst.sa.sa_family);
  500                 IPIP_STATINC(IPIP_STAT_FAMILY);
  501                 error = EAFNOSUPPORT;
  502                 goto bad;
  503         }
  504 
  505         IPIP_STATINC(IPIP_STAT_OPACKETS);
  506         IPIP_STATADD(IPIP_STAT_OBYTES, m->m_pkthdr.len - iphlen);
  507 
  508         *mp = m;
  509         return 0;
  510 
  511 bad:
  512         if (m)
  513                 m_freem(m);
  514         *mp = NULL;
  515         return error;
  516 }
  517 
  518 #ifdef INET
  519 static struct encapsw ipe4_encapsw = {
  520         .encapsw4 = {
  521                 .pr_input = ip4_input,
  522                 .pr_ctlinput = NULL,
  523         }
  524 };
  525 #endif
  526 #ifdef INET6
  527 static struct encapsw ipe4_encapsw6 = {
  528         .encapsw6 = {
  529                 .pr_input = ip4_input6,
  530                 .pr_ctlinput = NULL,
  531         }
  532 };
  533 #endif
  534 
  535 /*
  536  * Check the encapsulated packet to see if we want it
  537  */
  538 static int
  539 ipe4_encapcheck(struct mbuf *m, int off, int proto, void *arg)
  540 {
  541         /*
  542          * Only take packets coming from IPSEC tunnels; the rest
  543          * must be handled by the gif tunnel code.  Note that we
  544          * also return a minimum priority when we want the packet
  545          * so any explicit gif tunnels take precedence.
  546          */
  547         return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0);
  548 }
  549 
  550 /* -------------------------------------------------------------------------- */
  551 
  552 static int
  553 ipe4_init(struct secasvar *sav, const struct xformsw *xsp)
  554 {
  555         sav->tdb_xform = xsp;
  556         return 0;
  557 }
  558 
  559 static void
  560 ipe4_zeroize(struct secasvar *sav)
  561 {
  562         sav->tdb_xform = NULL;
  563 }
  564 
  565 static int
  566 ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
  567 {
  568         /* This is a rather serious mistake, so no conditional printing. */
  569         printf("should never be called\n");
  570         if (m)
  571                 m_freem(m);
  572         return EOPNOTSUPP;
  573 }
  574 
  575 static int
  576 ipe4_output(struct mbuf *m, const struct ipsecrequest *isr,
  577     struct secasvar *sav, int skip, int protoff, int flags)
  578 {
  579         panic("%s: should not have been called", __func__);
  580 }
  581 
  582 static struct xformsw ipe4_xformsw = {
  583         .xf_type        = XF_IP4,
  584         .xf_flags       = 0,
  585         .xf_name        = "IPv4 Simple Encapsulation",
  586         .xf_init        = ipe4_init,
  587         .xf_zeroize     = ipe4_zeroize,
  588         .xf_input       = ipe4_input,
  589         .xf_output      = ipe4_output,
  590         .xf_next        = NULL,
  591 };
  592 
  593 /* -------------------------------------------------------------------------- */
  594 
  595 void
  596 ipe4_attach(void)
  597 {
  598 
  599         ipipstat_percpu = percpu_alloc(sizeof(uint64_t) * IPIP_NSTATS);
  600 
  601         xform_register(&ipe4_xformsw);
  602         /* attach to encapsulation framework */
  603         /* XXX save return cookie for detach on module remove */
  604 
  605         encapinit();
  606         /* This function is called before ifinit(). Who else gets lock? */
  607         (void)encap_lock_enter();
  608         /* ipe4_encapsw and ipe4_encapsw must be added atomically */
  609 #ifdef INET
  610         (void)encap_attach_func(AF_INET, -1, ipe4_encapcheck, &ipe4_encapsw,
  611             NULL);
  612 #endif
  613 #ifdef INET6
  614         (void)encap_attach_func(AF_INET6, -1, ipe4_encapcheck, &ipe4_encapsw6,
  615             NULL);
  616 #endif
  617         encap_lock_exit();
  618 }

Cache object: bf3e523caccadfd5163d9838eee06253


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