LCOV - code coverage report
Current view: top level - netinet - ip_ipip.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 246 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13