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/netinet/ip_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 /*      $OpenBSD: ip_ipip.c,v 1.98 2022/01/02 22:36:04 jsg Exp $ */
    2 /*
    3  * The authors of this code are John Ioannidis (ji@tla.org),
    4  * Angelos D. Keromytis (kermit@csd.uch.gr) and
    5  * Niels Provos (provos@physnet.uni-hamburg.de).
    6  *
    7  * The original version of this code was written by John Ioannidis
    8  * for BSD/OS in Athens, Greece, in November 1995.
    9  *
   10  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
   11  * by Angelos D. Keromytis.
   12  *
   13  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
   14  * and Niels Provos.
   15  *
   16  * Additional features in 1999 by Angelos D. Keromytis.
   17  *
   18  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
   19  * Angelos D. Keromytis and Niels Provos.
   20  * Copyright (c) 2001, Angelos D. Keromytis.
   21  *
   22  * Permission to use, copy, and modify this software with or without fee
   23  * is hereby granted, provided that this entire notice is included in
   24  * all copies of any software which is or includes a copy or
   25  * modification of this software.
   26  * You may use this code under the GNU public license if you so wish. Please
   27  * contribute changes back to the authors under this freer than GPL license
   28  * so that we may further the use of strong encryption without limitations to
   29  * all.
   30  *
   31  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
   32  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
   33  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
   34  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
   35  * PURPOSE.
   36  */
   37 
   38 /*
   39  * IP-inside-IP processing
   40  */
   41 
   42 #include "bpfilter.h"
   43 #include "gif.h"
   44 #include "pf.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/socket.h>
   50 #include <sys/sysctl.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_types.h>
   54 #include <net/if_var.h>
   55 #include <net/route.h>
   56 #include <net/netisr.h>
   57 #include <net/bpf.h>
   58 
   59 #include <netinet/in.h>
   60 #include <netinet/ip.h>
   61 #include <netinet/in_pcb.h>
   62 #include <netinet/ip_var.h>
   63 #include <netinet/ip_ecn.h>
   64 #include <netinet/ip_ipip.h>
   65 
   66 #ifdef MROUTING
   67 #include <netinet/ip_mroute.h>
   68 #endif
   69 
   70 #if NPF > 0
   71 #include <net/pfvar.h>
   72 #endif
   73 
   74 #ifdef ENCDEBUG
   75 #define DPRINTF(fmt, args...)                                           \
   76         do {                                                            \
   77                 if (encdebug)                                           \
   78                         printf("%s: " fmt "\n", __func__, ## args);     \
   79         } while (0)
   80 #else
   81 #define DPRINTF(fmt, args...)                                           \
   82         do { } while (0)
   83 #endif
   84 
   85 /*
   86  * We can control the acceptance of IP4 packets by altering the sysctl
   87  * net.inet.ipip.allow value.  Zero means drop them, all else is acceptance.
   88  */
   89 int ipip_allow = 0;
   90 
   91 struct cpumem *ipipcounters;
   92 
   93 void
   94 ipip_init(void)
   95 {
   96         ipipcounters = counters_alloc(ipips_ncounters);
   97 }
   98 
   99 /*
  100  * Really only a wrapper for ipip_input_if(), for use with pr_input.
  101  */
  102 int
  103 ipip_input(struct mbuf **mp, int *offp, int nxt, int af)
  104 {
  105         struct ifnet *ifp;
  106 
  107         /* If we do not accept IP-in-IP explicitly, drop.  */
  108         if (!ipip_allow && ((*mp)->m_flags & (M_AUTH|M_CONF)) == 0) {
  109                 DPRINTF("dropped due to policy");
  110                 ipipstat_inc(ipips_pdrops);
  111                 m_freemp(mp);
  112                 return IPPROTO_DONE;
  113         }
  114 
  115         ifp = if_get((*mp)->m_pkthdr.ph_ifidx);
  116         if (ifp == NULL) {
  117                 m_freemp(mp);
  118                 return IPPROTO_DONE;
  119         }
  120         nxt = ipip_input_if(mp, offp, nxt, af, ifp);
  121         if_put(ifp);
  122 
  123         return nxt;
  124 }
  125 
  126 /*
  127  * ipip_input gets called when we receive an IP{46} encapsulated packet,
  128  * either because we got it at a real interface, or because AH or ESP
  129  * were being used in tunnel mode (in which case the ph_ifidx element
  130  * will contain the index of the encX interface associated with the
  131  * tunnel.
  132  */
  133 
  134 int
  135 ipip_input_if(struct mbuf **mp, int *offp, int proto, int oaf,
  136     struct ifnet *ifp)
  137 {
  138         struct mbuf *m = *mp;
  139         struct sockaddr_in *sin;
  140         struct ip *ip;
  141 #ifdef INET6
  142         struct sockaddr_in6 *sin6;
  143         struct ip6_hdr *ip6;
  144 #endif
  145         int mode, hlen;
  146         u_int8_t itos, otos;
  147         sa_family_t iaf;
  148 
  149         ipipstat_inc(ipips_ipackets);
  150 
  151         switch (oaf) {
  152         case AF_INET:
  153                 hlen = sizeof(struct ip);
  154                 break;
  155 #ifdef INET6
  156         case AF_INET6:
  157                 hlen = sizeof(struct ip6_hdr);
  158                 break;
  159 #endif
  160         default:
  161                 unhandled_af(oaf);
  162         }
  163 
  164         /* Bring the IP header in the first mbuf, if not there already */
  165         if (m->m_len < hlen) {
  166                 if ((m = *mp = m_pullup(m, hlen)) == NULL) {
  167                         DPRINTF("m_pullup() failed");
  168                         ipipstat_inc(ipips_hdrops);
  169                         goto bad;
  170                 }
  171         }
  172 
  173         /* Keep outer ecn field. */
  174         switch (oaf) {
  175         case AF_INET:
  176                 ip = mtod(m, struct ip *);
  177                 otos = ip->ip_tos;
  178                 break;
  179 #ifdef INET6
  180         case AF_INET6:
  181                 ip6 = mtod(m, struct ip6_hdr *);
  182                 otos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
  183                 break;
  184 #endif
  185         }
  186 
  187         /* Remove outer IP header */
  188         KASSERT(*offp > 0);
  189         m_adj(m, *offp);
  190         *offp = 0;
  191         ip = NULL;
  192 #ifdef INET6
  193         ip6 = NULL;
  194 #endif
  195 
  196         switch (proto) {
  197         case IPPROTO_IPV4:
  198                 hlen = sizeof(struct ip);
  199                 break;
  200 
  201 #ifdef INET6
  202         case IPPROTO_IPV6:
  203                 hlen = sizeof(struct ip6_hdr);
  204                 break;
  205 #endif
  206         default:
  207                 ipipstat_inc(ipips_family);
  208                 goto bad;
  209         }
  210 
  211         /* Sanity check */
  212         if (m->m_pkthdr.len < hlen) {
  213                 ipipstat_inc(ipips_hdrops);
  214                 goto bad;
  215         }
  216 
  217         /*
  218          * Bring the inner header into the first mbuf, if not there already.
  219          */
  220         if (m->m_len < hlen) {
  221                 if ((m = *mp = m_pullup(m, hlen)) == NULL) {
  222                         DPRINTF("m_pullup() failed");
  223                         ipipstat_inc(ipips_hdrops);
  224                         goto bad;
  225                 }
  226         }
  227 
  228         /*
  229          * RFC 1853 specifies that the inner TTL should not be touched on
  230          * decapsulation. There's no reason this comment should be here, but
  231          * this is as good as any a position.
  232          */
  233 
  234         /* Some sanity checks in the inner IP header */
  235         switch (proto) {
  236         case IPPROTO_IPV4:
  237                 iaf = AF_INET;
  238                 ip = mtod(m, struct ip *);
  239                 hlen = ip->ip_hl << 2;
  240                 if (m->m_pkthdr.len < hlen) {
  241                         ipipstat_inc(ipips_hdrops);
  242                         goto bad;
  243                 }
  244                 itos = ip->ip_tos;
  245                 mode = m->m_flags & (M_AUTH|M_CONF) ?
  246                     ECN_ALLOWED_IPSEC : ECN_ALLOWED;
  247                 if (!ip_ecn_egress(mode, &otos, &itos)) {
  248                         DPRINTF("ip_ecn_egress() failed");
  249                         ipipstat_inc(ipips_pdrops);
  250                         goto bad;
  251                 }
  252                 /* re-calculate the checksum if ip_tos was changed */
  253                 if (itos != ip->ip_tos)
  254                         ip_tos_patch(ip, itos);
  255                 break;
  256 #ifdef INET6
  257         case IPPROTO_IPV6:
  258                 iaf = AF_INET6;
  259                 ip6 = mtod(m, struct ip6_hdr *);
  260                 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
  261                 if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) {
  262                         DPRINTF("ip_ecn_egress() failed");
  263                         ipipstat_inc(ipips_pdrops);
  264                         goto bad;
  265                 }
  266                 ip6->ip6_flow &= ~htonl(0xff << 20);
  267                 ip6->ip6_flow |= htonl((u_int32_t) itos << 20);
  268                 break;
  269 #endif
  270         }
  271 
  272         /* Check for local address spoofing. */
  273         if (!(ifp->if_flags & IFF_LOOPBACK) && ipip_allow != 2) {
  274                 struct sockaddr_storage ss;
  275                 struct rtentry *rt;
  276 
  277                 memset(&ss, 0, sizeof(ss));
  278 
  279                 if (ip) {
  280                         sin = (struct sockaddr_in *)&ss;
  281                         sin->sin_family = AF_INET;
  282                         sin->sin_len = sizeof(*sin);
  283                         sin->sin_addr = ip->ip_src;
  284 #ifdef INET6
  285                 } else if (ip6) {
  286                         sin6 = (struct sockaddr_in6 *)&ss;
  287                         sin6->sin6_family = AF_INET6;
  288                         sin6->sin6_len = sizeof(*sin6);
  289                         sin6->sin6_addr = ip6->ip6_src;
  290 #endif /* INET6 */
  291                 }
  292                 rt = rtalloc(sstosa(&ss), 0, m->m_pkthdr.ph_rtableid);
  293                 if ((rt != NULL) && (rt->rt_flags & RTF_LOCAL)) {
  294                         ipipstat_inc(ipips_spoof);
  295                         rtfree(rt);
  296                         goto bad;
  297                 }
  298                 rtfree(rt);
  299         }
  300 
  301         /* Statistics */
  302         ipipstat_add(ipips_ibytes, m->m_pkthdr.len - hlen);
  303 
  304 #if NBPFILTER > 0 && NGIF > 0
  305         if (ifp->if_type == IFT_GIF && ifp->if_bpf != NULL)
  306                 bpf_mtap_af(ifp->if_bpf, iaf, m, BPF_DIRECTION_IN);
  307 #endif
  308 #if NPF > 0
  309         pf_pkt_addr_changed(m);
  310 #endif
  311 
  312         /*
  313          * Interface pointer stays the same; if no IPsec processing has
  314          * been done (or will be done), this will point to a normal
  315          * interface. Otherwise, it'll point to an enc interface, which
  316          * will allow a packet filter to distinguish between secure and
  317          * untrusted packets.
  318          */
  319 
  320         switch (proto) {
  321         case IPPROTO_IPV4:
  322                 return ip_input_if(mp, offp, proto, oaf, ifp);
  323 #ifdef INET6
  324         case IPPROTO_IPV6:
  325                 return ip6_input_if(mp, offp, proto, oaf, ifp);
  326 #endif
  327         }
  328  bad:
  329         m_freemp(mp);
  330         return IPPROTO_DONE;
  331 }
  332 
  333 int
  334 ipip_output(struct mbuf **mp, struct tdb *tdb)
  335 {
  336         struct mbuf *m = *mp;
  337         u_int8_t tp, otos, itos;
  338         u_int64_t obytes;
  339         struct ip *ipo;
  340 #ifdef INET6
  341         struct ip6_hdr *ip6, *ip6o;
  342 #endif /* INET6 */
  343 #ifdef ENCDEBUG
  344         char buf[INET6_ADDRSTRLEN];
  345 #endif
  346         int error;
  347 
  348         /* XXX Deal with empty TDB source/destination addresses. */
  349 
  350         m_copydata(m, 0, 1, &tp);
  351         tp = (tp >> 4) & 0xff;  /* Get the IP version number. */
  352 
  353         switch (tdb->tdb_dst.sa.sa_family) {
  354         case AF_INET:
  355                 if (tdb->tdb_src.sa.sa_family != AF_INET ||
  356                     tdb->tdb_src.sin.sin_addr.s_addr == INADDR_ANY ||
  357                     tdb->tdb_dst.sin.sin_addr.s_addr == INADDR_ANY) {
  358 
  359                         DPRINTF("unspecified tunnel endpoint address "
  360                             "in SA %s/%08x",
  361                             ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
  362                             ntohl(tdb->tdb_spi));
  363 
  364                         ipipstat_inc(ipips_unspec);
  365                         error = EINVAL;
  366                         goto drop;
  367                 }
  368 
  369                 M_PREPEND(*mp, sizeof(struct ip), M_DONTWAIT);
  370                 if (*mp == NULL) {
  371                         DPRINTF("M_PREPEND failed");
  372                         ipipstat_inc(ipips_hdrops);
  373                         error = ENOBUFS;
  374                         goto drop;
  375                 }
  376                 m = *mp;
  377 
  378                 ipo = mtod(m, struct ip *);
  379 
  380                 ipo->ip_v = IPVERSION;
  381                 ipo->ip_hl = 5;
  382                 ipo->ip_len = htons(m->m_pkthdr.len);
  383                 ipo->ip_ttl = ip_defttl;
  384                 ipo->ip_sum = 0;
  385                 ipo->ip_src = tdb->tdb_src.sin.sin_addr;
  386                 ipo->ip_dst = tdb->tdb_dst.sin.sin_addr;
  387 
  388                 /*
  389                  * We do the htons() to prevent snoopers from determining our
  390                  * endianness.
  391                  */
  392                 ipo->ip_id = htons(ip_randomid());
  393 
  394                 /* If the inner protocol is IP... */
  395                 if (tp == IPVERSION) {
  396                         /* Save ECN notification */
  397                         m_copydata(m, sizeof(struct ip) +
  398                             offsetof(struct ip, ip_tos),
  399                             sizeof(u_int8_t), (caddr_t) &itos);
  400 
  401                         ipo->ip_p = IPPROTO_IPIP;
  402 
  403                         /*
  404                          * We should be keeping tunnel soft-state and
  405                          * send back ICMPs if needed.
  406                          */
  407                         m_copydata(m, sizeof(struct ip) +
  408                             offsetof(struct ip, ip_off),
  409                             sizeof(u_int16_t), (caddr_t) &ipo->ip_off);
  410                         ipo->ip_off = ntohs(ipo->ip_off);
  411                         ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK);
  412                         ipo->ip_off = htons(ipo->ip_off);
  413                 }
  414 #ifdef INET6
  415                 else if (tp == (IPV6_VERSION >> 4)) {
  416                         u_int32_t itos32;
  417 
  418                         /* Save ECN notification. */
  419                         m_copydata(m, sizeof(struct ip) +
  420                             offsetof(struct ip6_hdr, ip6_flow),
  421                             sizeof(u_int32_t), (caddr_t) &itos32);
  422                         itos = ntohl(itos32) >> 20;
  423                         ipo->ip_p = IPPROTO_IPV6;
  424                         ipo->ip_off = 0;
  425                 }
  426 #endif /* INET6 */
  427                 else {
  428                         ipipstat_inc(ipips_family);
  429                         error = EAFNOSUPPORT;
  430                         goto drop;
  431                 }
  432 
  433                 otos = 0;
  434                 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
  435                 ipo->ip_tos = otos;
  436 
  437                 obytes = m->m_pkthdr.len - sizeof(struct ip);
  438                 if (tdb->tdb_xform->xf_type == XF_IP4)
  439                         tdb->tdb_cur_bytes += obytes;
  440                 break;
  441 
  442 #ifdef INET6
  443         case AF_INET6:
  444                 if (IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr) ||
  445                     tdb->tdb_src.sa.sa_family != AF_INET6 ||
  446                     IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_src.sin6.sin6_addr)) {
  447 
  448                         DPRINTF("unspecified tunnel endpoint address "
  449                             "in SA %s/%08x",
  450                             ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
  451                             ntohl(tdb->tdb_spi));
  452 
  453                         ipipstat_inc(ipips_unspec);
  454                         error = EINVAL;
  455                         goto drop;
  456                 }
  457 
  458                 /* If the inner protocol is IPv6, clear link local scope */
  459                 if (tp == (IPV6_VERSION >> 4)) {
  460                         /* scoped address handling */
  461                         ip6 = mtod(m, struct ip6_hdr *);
  462                         if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
  463                                 ip6->ip6_src.s6_addr16[1] = 0;
  464                         if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
  465                                 ip6->ip6_dst.s6_addr16[1] = 0;
  466                 }
  467 
  468                 M_PREPEND(*mp, sizeof(struct ip6_hdr), M_DONTWAIT);
  469                 if (*mp == NULL) {
  470                         DPRINTF("M_PREPEND failed");
  471                         ipipstat_inc(ipips_hdrops);
  472                         error = ENOBUFS;
  473                         goto drop;
  474                 }
  475                 m = *mp;
  476 
  477                 /* Initialize IPv6 header */
  478                 ip6o = mtod(m, struct ip6_hdr *);
  479                 ip6o->ip6_flow = 0;
  480                 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
  481                 ip6o->ip6_vfc |= IPV6_VERSION;
  482                 ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o));
  483                 ip6o->ip6_hlim = ip_defttl;
  484                 in6_embedscope(&ip6o->ip6_src, &tdb->tdb_src.sin6, NULL);
  485                 in6_embedscope(&ip6o->ip6_dst, &tdb->tdb_dst.sin6, NULL);
  486 
  487                 if (tp == IPVERSION) {
  488                         /* Save ECN notification */
  489                         m_copydata(m, sizeof(struct ip6_hdr) +
  490                             offsetof(struct ip, ip_tos), sizeof(u_int8_t),
  491                             (caddr_t) &itos);
  492 
  493                         /* This is really IPVERSION. */
  494                         ip6o->ip6_nxt = IPPROTO_IPIP;
  495                 }
  496                 else
  497                         if (tp == (IPV6_VERSION >> 4)) {
  498                                 u_int32_t itos32;
  499 
  500                                 /* Save ECN notification. */
  501                                 m_copydata(m, sizeof(struct ip6_hdr) +
  502                                     offsetof(struct ip6_hdr, ip6_flow),
  503                                     sizeof(u_int32_t), (caddr_t) &itos32);
  504                                 itos = ntohl(itos32) >> 20;
  505 
  506                                 ip6o->ip6_nxt = IPPROTO_IPV6;
  507                         } else {
  508                                 ipipstat_inc(ipips_family);
  509                                 error = EAFNOSUPPORT;
  510                                 goto drop;
  511                         }
  512 
  513                 otos = 0;
  514                 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
  515                 ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
  516 
  517                 obytes = m->m_pkthdr.len - sizeof(struct ip6_hdr);
  518                 if (tdb->tdb_xform->xf_type == XF_IP4)
  519                         tdb->tdb_cur_bytes += obytes;
  520                 break;
  521 #endif /* INET6 */
  522 
  523         default:
  524                 DPRINTF("unsupported protocol family %d",
  525                     tdb->tdb_dst.sa.sa_family);
  526                 ipipstat_inc(ipips_family);
  527                 error = EPFNOSUPPORT;
  528                 goto drop;
  529         }
  530 
  531         ipipstat_pkt(ipips_opackets, ipips_obytes, obytes);
  532         return 0;
  533 
  534  drop:
  535         m_freemp(mp);
  536         return error;
  537 }
  538 
  539 #ifdef IPSEC
  540 int
  541 ipe4_attach(void)
  542 {
  543         return 0;
  544 }
  545 
  546 int
  547 ipe4_init(struct tdb *tdbp, const struct xformsw *xsp, struct ipsecinit *ii)
  548 {
  549         tdbp->tdb_xform = xsp;
  550         return 0;
  551 }
  552 
  553 int
  554 ipe4_zeroize(struct tdb *tdbp)
  555 {
  556         return 0;
  557 }
  558 
  559 int
  560 ipe4_input(struct mbuf **mp, struct tdb *tdb, int hlen, int proto)
  561 {
  562         /* This is a rather serious mistake, so no conditional printing. */
  563         printf("%s: should never be called\n", __func__);
  564         m_freemp(mp);
  565         return EINVAL;
  566 }
  567 #endif  /* IPSEC */
  568 
  569 int
  570 ipip_sysctl_ipipstat(void *oldp, size_t *oldlenp, void *newp)
  571 {
  572         struct ipipstat ipipstat;
  573 
  574         CTASSERT(sizeof(ipipstat) == (ipips_ncounters * sizeof(uint64_t)));
  575         memset(&ipipstat, 0, sizeof ipipstat);
  576         counters_read(ipipcounters, (uint64_t *)&ipipstat, ipips_ncounters);
  577         return (sysctl_rdstruct(oldp, oldlenp, newp,
  578             &ipipstat, sizeof(ipipstat)));
  579 }
  580 
  581 int
  582 ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  583     size_t newlen)
  584 {
  585         int error;
  586 
  587         /* All sysctl names at this level are terminal. */
  588         if (namelen != 1)
  589                 return (ENOTDIR);
  590 
  591         switch (name[0]) {
  592         case IPIPCTL_ALLOW:
  593                 NET_LOCK();
  594                 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
  595                     &ipip_allow, 0, 2);
  596                 NET_UNLOCK();
  597                 return (error);
  598         case IPIPCTL_STATS:
  599                 return (ipip_sysctl_ipipstat(oldp, oldlenp, newp));
  600         default:
  601                 return (ENOPROTOOPT);
  602         }
  603         /* NOTREACHED */
  604 }

Cache object: bd5801e11878739f7df8f487471b8ba2


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