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

          Line data    Source code
       1             : /*      $OpenBSD: if_mobileip.c,v 1.8 2018/02/18 23:53:17 dlg Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include "mobileip.h"
      20             : 
      21             : #include "bpfilter.h"
      22             : #include "pf.h"
      23             : 
      24             : #include <sys/param.h>
      25             : #include <sys/mbuf.h>
      26             : #include <sys/socket.h>
      27             : #include <sys/sockio.h>
      28             : #include <sys/kernel.h>
      29             : #include <sys/systm.h>
      30             : #include <sys/timeout.h>
      31             : #include <sys/queue.h>
      32             : 
      33             : #include <net/if.h>
      34             : #include <net/if_types.h>
      35             : #include <net/if_var.h>
      36             : #include <net/route.h>
      37             : 
      38             : #include <netinet/in.h>
      39             : #include <netinet/ip.h>
      40             : #include <netinet/ip_var.h>
      41             : 
      42             : #if NBPFILTER > 0
      43             : #include <net/bpf.h>
      44             : #endif
      45             : 
      46             : #if NPF > 0
      47             : #include <net/pfvar.h>
      48             : #endif
      49             : 
      50             : #include <net/if_mobileip.h>
      51             : 
      52             : struct mobileip_tunnel {
      53             :         unsigned int            t_rtableid;
      54             :         struct in_addr          t_src;
      55             :         struct in_addr          t_dst;
      56             : 
      57             :         TAILQ_ENTRY(mobileip_tunnel)
      58             :                                 t_entry;
      59             : };
      60             : 
      61             : TAILQ_HEAD(mobileip_list, mobileip_tunnel);
      62             : 
      63             : struct mobileip_softc {
      64             :         struct mobileip_tunnel  sc_tunnel;
      65             :         struct ifnet            sc_if;
      66             : };
      67             : 
      68             : static int      mobileip_clone_create(struct if_clone *, int);
      69             : static int      mobileip_clone_destroy(struct ifnet *);
      70             : 
      71             : static struct if_clone mobileip_cloner = IF_CLONE_INITIALIZER("mobileip",
      72             :     mobileip_clone_create, mobileip_clone_destroy);
      73             : 
      74             : static inline int
      75             :                 mobileip_cmp(const struct mobileip_tunnel *,
      76             :                     const struct mobileip_tunnel *);
      77             : 
      78             : struct mobileip_list mobileip_list = TAILQ_HEAD_INITIALIZER(mobileip_list);
      79             : 
      80             : #define MOBILEIPMTU     (1500 - (sizeof(struct mobileip_header) +       \
      81             :                             sizeof(struct mobileip_h_src)))             \
      82             : 
      83             : static int      mobileip_ioctl(struct ifnet *, u_long, caddr_t);
      84             : static int      mobileip_up(struct mobileip_softc *);
      85             : static int      mobileip_down(struct mobileip_softc *);
      86             : static int      mobileip_set_tunnel(struct mobileip_softc *,
      87             :                     struct if_laddrreq *);
      88             : static int      mobileip_get_tunnel(struct mobileip_softc *,
      89             :                     struct if_laddrreq *);
      90             : static int      mobileip_del_tunnel(struct mobileip_softc *);
      91             : 
      92             : static int      mobileip_output(struct ifnet *, struct mbuf *,
      93             :                     struct sockaddr *, struct rtentry *);
      94             : static void     mobileip_start(struct ifnet *);
      95             : static int      mobileip_encap(struct mobileip_softc *, struct mbuf *);
      96             : static struct mobileip_softc *
      97             :                 mobileip_find(const struct mobileip_tunnel *);
      98             : 
      99             : /*
     100             :  * let's begin
     101             :  */
     102             : 
     103             : int     mobileip_allow = 0;
     104             : 
     105             : void
     106           0 : mobileipattach(int n)
     107             : {
     108           0 :         if_clone_attach(&mobileip_cloner);
     109           0 : }
     110             : 
     111             : int
     112           0 : mobileip_clone_create(struct if_clone *ifc, int unit)
     113             : {
     114             :         struct mobileip_softc *sc;
     115             : 
     116           0 :         sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO);
     117           0 :         if (!sc)
     118           0 :                 return (ENOMEM);
     119             : 
     120           0 :         sc->sc_tunnel.t_rtableid = 0;
     121           0 :         sc->sc_tunnel.t_src.s_addr = INADDR_ANY;
     122           0 :         sc->sc_tunnel.t_dst.s_addr = INADDR_ANY;
     123             : 
     124           0 :         snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d",
     125           0 :             ifc->ifc_name, unit);
     126           0 :         sc->sc_if.if_softc = sc;
     127           0 :         sc->sc_if.if_type = IFT_TUNNEL;
     128           0 :         sc->sc_if.if_addrlen = 0;
     129           0 :         sc->sc_if.if_mtu = MOBILEIPMTU;
     130           0 :         sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
     131           0 :         sc->sc_if.if_output = mobileip_output;
     132           0 :         sc->sc_if.if_start = mobileip_start;
     133           0 :         sc->sc_if.if_ioctl = mobileip_ioctl;
     134           0 :         sc->sc_if.if_rtrequest = p2p_rtrequest;
     135             : 
     136           0 :         if_attach(&sc->sc_if);
     137           0 :         if_alloc_sadl(&sc->sc_if);
     138             : 
     139             : #if NBPFILTER > 0
     140           0 :         bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_LOOP, sizeof(uint32_t));
     141             : #endif
     142             : 
     143           0 :         NET_LOCK();
     144           0 :         TAILQ_INSERT_TAIL(&mobileip_list, &sc->sc_tunnel, t_entry);
     145           0 :         NET_UNLOCK();
     146             : 
     147           0 :         return (0);
     148           0 : }
     149             : 
     150             : int
     151           0 : mobileip_clone_destroy(struct ifnet *ifp)
     152             : {
     153           0 :         struct mobileip_softc *sc = ifp->if_softc;
     154             : 
     155           0 :         if_detach(ifp);
     156             : 
     157           0 :         NET_LOCK();
     158           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING))
     159           0 :                 mobileip_down(sc);
     160             : 
     161           0 :         TAILQ_REMOVE(&mobileip_list, &sc->sc_tunnel, t_entry);
     162           0 :         NET_UNLOCK();
     163             : 
     164           0 :         free(sc, M_DEVBUF, sizeof(*sc));
     165             : 
     166           0 :         return (0);
     167             : }
     168             : 
     169             : /*
     170             :  * do a checksum of a header.
     171             :  *
     172             :  * assumes len is aligned correctly, and not an odd number of bytes.
     173             :  */
     174             : static inline uint16_t
     175           0 : mobileip_cksum(const void *buf, size_t len)
     176             : {
     177           0 :         const uint16_t *p = buf;
     178             :         uint32_t sum = 0;
     179             : 
     180           0 :         do {
     181           0 :                 sum += bemtoh16(p++);
     182           0 :         } while (len -= 2);
     183             : 
     184             :         /* end-around-carry */
     185           0 :         sum = (sum >> 16) + (sum & 0xffff);
     186           0 :         sum += (sum >> 16);
     187           0 :         return (~sum);
     188             : }
     189             : 
     190             : static inline int
     191           0 : mobileip_cmp(const struct mobileip_tunnel *a, const struct mobileip_tunnel *b)
     192             : {
     193           0 :         if (a->t_src.s_addr > b->t_src.s_addr)
     194           0 :                 return (1);
     195           0 :         if (a->t_src.s_addr < b->t_src.s_addr)
     196           0 :                 return (-1);
     197             : 
     198           0 :         if (a->t_dst.s_addr > b->t_dst.s_addr)
     199           0 :                 return (1);
     200           0 :         if (a->t_dst.s_addr < b->t_dst.s_addr)
     201           0 :                 return (-1);
     202             : 
     203           0 :         if (a->t_rtableid > b->t_rtableid)
     204           0 :                 return (1);
     205           0 :         if (a->t_rtableid < b->t_rtableid)
     206           0 :                 return (-1);
     207             : 
     208           0 :         return (0);
     209           0 : }
     210             : 
     211             : static int
     212           0 : mobileip_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
     213             :     struct rtentry *rt)
     214             : {
     215             :         struct m_tag *mtag;
     216             :         int error = 0;
     217             : 
     218           0 :         if (!mobileip_allow) {
     219           0 :                 m_freem(m);
     220             :                 error = EACCES;
     221           0 :                 goto end;
     222             :         }
     223             : 
     224           0 :         if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
     225           0 :                 m_freem(m);
     226             :                 error = ENETDOWN;
     227           0 :                 goto end;
     228             :         }
     229             : 
     230           0 :         if (dst->sa_family != AF_INET) {
     231           0 :                 m_freem(m);
     232             :                 error = EAFNOSUPPORT;
     233           0 :                 goto end;
     234             :         }
     235             : 
     236             :         /* Try to limit infinite recursion through misconfiguration. */
     237           0 :         for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag;
     238           0 :              mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) {
     239           0 :                 if (memcmp(mtag + 1, &ifp->if_index,
     240           0 :                     sizeof(ifp->if_index)) == 0) {
     241           0 :                         m_freem(m);
     242             :                         error = EIO;
     243           0 :                         goto end;
     244             :                 }
     245             :         }
     246             : 
     247           0 :         mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT);
     248           0 :         if (mtag == NULL) {
     249           0 :                 m_freem(m);
     250             :                 error = ENOBUFS;
     251           0 :                 goto end;
     252             :         }
     253           0 :         memcpy(mtag + 1, &ifp->if_index, sizeof(ifp->if_index));
     254           0 :         m_tag_prepend(m, mtag);
     255             : 
     256           0 :         error = if_enqueue(ifp, m);
     257             :   end:
     258           0 :         if (error)
     259           0 :                 ifp->if_oerrors++;
     260           0 :         return (error);
     261             : }
     262             : 
     263             : static void
     264           0 : mobileip_start(struct ifnet *ifp)
     265             : {
     266           0 :         struct mobileip_softc *sc = ifp->if_softc;
     267             :         struct mbuf *m;
     268             : 
     269           0 :         while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) {
     270             : #if NBPFILTER > 0
     271           0 :                 if (ifp->if_bpf)
     272           0 :                         bpf_mtap_af(ifp->if_bpf, AF_INET, m, BPF_DIRECTION_OUT);
     273             : #endif
     274             : 
     275           0 :                 if (mobileip_encap(sc, m) != 0)
     276           0 :                         ifp->if_oerrors++;
     277             :         }
     278           0 : }
     279             : 
     280             : static int
     281           0 : mobileip_encap(struct mobileip_softc *sc, struct mbuf *m)
     282             : {
     283             :         struct ip *ip;
     284           0 :         struct mobileip_tunnel *tunnel = &sc->sc_tunnel;
     285             :         struct mobileip_header *mh;
     286             :         struct mobileip_h_src *msh;
     287             :         caddr_t hdr;
     288             :         int iphlen, hlen;
     289             : 
     290             :         /* look at the current IP header */
     291           0 :         m = m_pullup(m, sizeof(*ip));
     292           0 :         if (m == NULL)
     293           0 :                 return (ENOBUFS);
     294             : 
     295             :         /* figure out how long it is */
     296           0 :         ip = mtod(m, struct ip *);
     297           0 :         iphlen = ip->ip_hl << 2;
     298             : 
     299             :         /* figure out how much extra space we'll need */
     300             :         hlen = sizeof(*mh);
     301           0 :         if (ip->ip_src.s_addr != tunnel->t_src.s_addr)
     302           0 :                 hlen += sizeof(*msh);
     303             : 
     304             :         /* add the space */
     305           0 :         m = m_prepend(m, hlen, M_DONTWAIT);
     306           0 :         if (m == NULL)
     307           0 :                 return (ENOBUFS);
     308             : 
     309             :         /* make the IP and mobileip headers contig */
     310           0 :         m = m_pullup(m, iphlen + hlen);
     311           0 :         if (m == NULL)
     312           0 :                 return (ENOBUFS);
     313             : 
     314             :         /* move the IP header to the front */
     315           0 :         hdr = mtod(m, caddr_t);
     316           0 :         memmove(hdr, hdr + hlen, iphlen);
     317             : 
     318             :         /* fill in the headers */
     319           0 :         ip = (struct ip *)hdr;
     320           0 :         mh = (struct mobileip_header *)(hdr + iphlen);
     321           0 :         mh->mip_proto = ip->ip_p;
     322           0 :         mh->mip_flags = 0;
     323           0 :         mh->mip_hcrc = 0;
     324           0 :         mh->mip_dst = ip->ip_dst.s_addr;
     325             : 
     326           0 :         if (ip->ip_src.s_addr != tunnel->t_src.s_addr) {
     327           0 :                 mh->mip_flags |= MOBILEIP_SP;
     328             : 
     329           0 :                 msh = (struct mobileip_h_src *)(mh + 1);
     330           0 :                 msh->mip_src = ip->ip_src.s_addr;
     331             : 
     332           0 :                 ip->ip_src.s_addr = tunnel->t_src.s_addr;
     333           0 :         }
     334             : 
     335           0 :         htobem16(&mh->mip_hcrc, mobileip_cksum(mh, hlen));
     336             : 
     337           0 :         ip->ip_p = IPPROTO_MOBILE;
     338           0 :         htobem16(&ip->ip_len, bemtoh16(&ip->ip_len) + hlen);
     339           0 :         ip->ip_dst = tunnel->t_dst;
     340             : 
     341           0 :         m->m_flags &= ~(M_BCAST|M_MCAST);
     342           0 :         m->m_pkthdr.ph_rtableid = tunnel->t_rtableid;
     343             : 
     344             : #if NPF > 0
     345           0 :         pf_pkt_addr_changed(m);
     346             : #endif
     347             : 
     348           0 :         ip_send(m);
     349             : 
     350           0 :         return (0);
     351           0 : }
     352             : 
     353             : int
     354           0 : mobileip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
     355             : {
     356           0 :         struct mobileip_softc *sc = ifp->if_softc;
     357           0 :         struct ifreq *ifr = (struct ifreq *)data;
     358           0 :         struct ifaddr *ifa = (struct ifaddr *)data;
     359             :         int error = 0;
     360             : 
     361           0 :         switch(cmd) {
     362             :         case SIOCSIFADDR:
     363           0 :                 if (ifa->ifa_addr->sa_family != AF_INET) {
     364             :                         error = EAFNOSUPPORT;
     365           0 :                         break;
     366             :                 }
     367             : 
     368           0 :                 ifp->if_flags |= IFF_UP;
     369             :                 /* FALLTHROUGH */
     370             :         case SIOCSIFFLAGS:
     371           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
     372           0 :                         if (!ISSET(ifp->if_flags, IFF_RUNNING))
     373           0 :                                 error = mobileip_up(sc);
     374             :                         else
     375             :                                 error = 0;
     376             :                 } else {
     377           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
     378           0 :                                 error = mobileip_down(sc);
     379             :                 }
     380             :                 break;
     381             :         case SIOCSIFDSTADDR:
     382             :                 break;
     383             :         case SIOCSIFMTU:
     384           0 :                 if (ifr->ifr_mtu < 576) {
     385             :                         error = EINVAL;
     386           0 :                         break;
     387             :                 }
     388           0 :                 ifp->if_mtu = ifr->ifr_mtu;
     389           0 :                 break;
     390             :         case SIOCGIFMTU:
     391           0 :                 ifr->ifr_mtu = sc->sc_if.if_mtu;
     392           0 :                 break;
     393             :         case SIOCADDMULTI:
     394             :         case SIOCDELMULTI:
     395             :                 break;
     396             : 
     397             :         case SIOCSLIFPHYADDR:
     398           0 :                 error = mobileip_set_tunnel(sc, (struct if_laddrreq *)data);
     399           0 :                 break;
     400             :         case SIOCGLIFPHYADDR:
     401           0 :                 error = mobileip_get_tunnel(sc, (struct if_laddrreq *)data);
     402           0 :                 break;
     403             :         case SIOCDIFPHYADDR:
     404           0 :                 error = mobileip_del_tunnel(sc);
     405           0 :                 break;
     406             : 
     407             :         case SIOCGLIFPHYTTL:
     408           0 :                 ifr->ifr_ttl = -1;
     409           0 :                 break;
     410             : 
     411             :         case SIOCSLIFPHYRTABLE:
     412           0 :                 if (ifr->ifr_rdomainid < 0 ||
     413           0 :                     ifr->ifr_rdomainid > RT_TABLEID_MAX ||
     414           0 :                     !rtable_exists(ifr->ifr_rdomainid)) {
     415             :                         error = EINVAL;
     416           0 :                         break;
     417             :                 }
     418           0 :                 sc->sc_tunnel.t_rtableid = ifr->ifr_rdomainid;
     419           0 :                 break;
     420             :         case SIOCGLIFPHYRTABLE:
     421           0 :                 ifr->ifr_rdomainid = sc->sc_tunnel.t_rtableid;
     422           0 :                 break;
     423             : 
     424             :         default:
     425             :                 error = ENOTTY;
     426           0 :                 break;
     427             :         }
     428             : 
     429           0 :         return (error);
     430             : }
     431             : 
     432             : static int
     433           0 : mobileip_up(struct mobileip_softc *sc)
     434             : {
     435           0 :         NET_ASSERT_LOCKED();
     436             : 
     437           0 :         SET(sc->sc_if.if_flags, IFF_RUNNING);
     438             : 
     439           0 :         return (0);
     440             : }
     441             : 
     442             : static int
     443           0 : mobileip_down(struct mobileip_softc *sc)
     444             : {
     445           0 :         NET_ASSERT_LOCKED();
     446             : 
     447           0 :         CLR(sc->sc_if.if_flags, IFF_RUNNING);
     448             : 
     449           0 :         ifq_barrier(&sc->sc_if.if_snd);
     450             : 
     451           0 :         return (0);
     452             : }
     453             : 
     454             : static int
     455           0 : mobileip_set_tunnel(struct mobileip_softc *sc, struct if_laddrreq *req)
     456             : {
     457           0 :         struct sockaddr_in *src = (struct sockaddr_in *)&req->addr;
     458           0 :         struct sockaddr_in *dst = (struct sockaddr_in *)&req->dstaddr;
     459             : 
     460             :         /* sa_family and sa_len must be equal */
     461           0 :         if (src->sin_family != dst->sin_family || src->sin_len != dst->sin_len)
     462           0 :                 return (EINVAL);
     463             : 
     464           0 :         if (dst->sin_family != AF_INET)
     465           0 :                 return (EAFNOSUPPORT);
     466           0 :         if (dst->sin_len != sizeof(*dst))
     467           0 :                 return (EINVAL);
     468             : 
     469           0 :         if (in_nullhost(src->sin_addr) ||
     470           0 :             IN_MULTICAST(src->sin_addr.s_addr) ||
     471           0 :             in_nullhost(dst->sin_addr) ||
     472           0 :             IN_MULTICAST(dst->sin_addr.s_addr))
     473           0 :                 return (EINVAL);
     474             : 
     475             :         /* commit */
     476           0 :         sc->sc_tunnel.t_src = src->sin_addr;
     477           0 :         sc->sc_tunnel.t_dst = dst->sin_addr;
     478             : 
     479           0 :         return (0);
     480           0 : }
     481             : 
     482             : static int
     483           0 : mobileip_get_tunnel(struct mobileip_softc *sc, struct if_laddrreq *req)
     484             : {
     485           0 :         struct sockaddr_in *src = (struct sockaddr_in *)&req->addr;
     486           0 :         struct sockaddr_in *dst = (struct sockaddr_in *)&req->dstaddr;
     487             : 
     488           0 :         if (sc->sc_tunnel.t_dst.s_addr == INADDR_ANY)
     489           0 :                 return (EADDRNOTAVAIL);
     490             : 
     491           0 :         memset(src, 0, sizeof(*src));
     492           0 :         src->sin_family = AF_INET;
     493           0 :         src->sin_len = sizeof(*src);
     494           0 :         src->sin_addr = sc->sc_tunnel.t_src;
     495             : 
     496           0 :         memset(dst, 0, sizeof(*dst));
     497           0 :         dst->sin_family = AF_INET;
     498           0 :         dst->sin_len = sizeof(*dst);
     499           0 :         dst->sin_addr = sc->sc_tunnel.t_dst;
     500             : 
     501           0 :         return (0);
     502           0 : }
     503             : 
     504             : static int
     505           0 : mobileip_del_tunnel(struct mobileip_softc *sc)
     506             : {
     507             :         /* commit */
     508           0 :         sc->sc_tunnel.t_src.s_addr = INADDR_ANY;
     509           0 :         sc->sc_tunnel.t_dst.s_addr = INADDR_ANY;
     510             : 
     511           0 :         return (0);
     512             : }
     513             : 
     514             : static struct mobileip_softc *
     515           0 : mobileip_find(const struct mobileip_tunnel *key)
     516             : {
     517             :         struct mobileip_tunnel *t;
     518             :         struct mobileip_softc *sc;
     519             : 
     520           0 :         TAILQ_FOREACH(t, &mobileip_list, t_entry) {
     521           0 :                 if (mobileip_cmp(key, t) != 0)
     522             :                         continue;
     523             : 
     524           0 :                 sc = (struct mobileip_softc *)t;
     525           0 :                 if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING))
     526             :                         continue;
     527             : 
     528           0 :                 return (sc);
     529             :         }
     530             : 
     531           0 :         return (NULL);
     532           0 : }
     533             : 
     534             : int
     535           0 : mobileip_input(struct mbuf **mp, int *offp, int type, int af)
     536             : {
     537           0 :         struct mobileip_tunnel key;
     538           0 :         struct mbuf *m = *mp;
     539             :         struct ifnet *ifp;
     540             :         struct mobileip_softc *sc;
     541             :         caddr_t hdr;
     542             :         struct ip *ip;
     543             :         struct mobileip_header *mh;
     544             :         struct mobileip_h_src *msh;
     545             :         int iphlen = 0;
     546             :         int hlen;
     547             : 
     548           0 :         if (!mobileip_allow)
     549             :                 goto drop;
     550             : 
     551           0 :         ip = mtod(m, struct ip *);
     552             : 
     553           0 :         key.t_rtableid = m->m_pkthdr.ph_rtableid;
     554           0 :         key.t_src = ip->ip_dst;
     555           0 :         key.t_dst = ip->ip_src;
     556             : 
     557             :         /* NET_ASSERT_READ_LOCKED() */
     558           0 :         sc = mobileip_find(&key);
     559           0 :         if (sc == NULL)
     560             :                 goto drop;
     561             : 
     562             :         /* it's ours now, we can do what we want */
     563             : 
     564           0 :         iphlen = ip->ip_hl << 2;
     565             :         hlen = sizeof(*mh);
     566           0 :         m = m_pullup(m, iphlen + hlen);
     567           0 :         if (m == NULL)
     568           0 :                 return (IPPROTO_DONE);
     569             : 
     570           0 :         hdr = mtod(m, caddr_t);
     571           0 :         ip = (struct ip *)hdr;
     572           0 :         mh = (struct mobileip_header *)(hdr + iphlen);
     573             : 
     574           0 :         if (mh->mip_flags & ~MOBILEIP_SP)
     575             :                 goto drop;
     576             : 
     577           0 :         if (ISSET(mh->mip_flags, MOBILEIP_SP)) {
     578             :                 hlen += sizeof(*msh);
     579           0 :                 m = m_pullup(m, iphlen + hlen);
     580           0 :                 if (m == NULL)
     581           0 :                         return (IPPROTO_DONE);
     582             : 
     583           0 :                 hdr = mtod(m, caddr_t);
     584           0 :                 ip = (struct ip *)hdr;
     585           0 :                 mh = (struct mobileip_header *)(hdr + iphlen);
     586           0 :                 msh = (struct mobileip_h_src *)(mh + 1);
     587             : 
     588           0 :                 ip->ip_src.s_addr = msh->mip_src;
     589           0 :         }
     590             : 
     591           0 :         if (mobileip_cksum(mh, hlen) != 0)
     592             :                 goto drop;
     593             : 
     594           0 :         ip->ip_p = mh->mip_proto;
     595           0 :         htobem16(&ip->ip_len, bemtoh16(&ip->ip_len) - hlen);
     596           0 :         ip->ip_dst.s_addr = mh->mip_dst;
     597             : 
     598           0 :         memmove(hdr + hlen, hdr, iphlen);
     599           0 :         m_adj(m, hlen);
     600             : 
     601           0 :         ifp = &sc->sc_if;
     602             : 
     603           0 :         CLR(m->m_flags, M_MCAST|M_BCAST);
     604           0 :         SET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_IN_OK);
     605           0 :         m->m_pkthdr.ph_ifidx = ifp->if_index;
     606           0 :         m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
     607             : 
     608             : #if NPF > 0
     609           0 :         pf_pkt_addr_changed(m);
     610             : #endif
     611             : 
     612           0 :         ifp->if_ipackets++;
     613           0 :         ifp->if_ibytes += m->m_pkthdr.len;
     614             : 
     615             : #if NBPFILTER > 0
     616           0 :         if (ifp->if_bpf)
     617           0 :                 bpf_mtap_af(ifp->if_bpf, AF_INET, m, BPF_DIRECTION_IN);
     618             : #endif
     619             : 
     620           0 :         ipv4_input(ifp, m);
     621             : 
     622           0 :         return (IPPROTO_DONE);
     623             : 
     624             : drop:
     625           0 :         m_freem(m);
     626           0 :         return (IPPROTO_DONE);
     627           0 : }
     628             : 
     629             : #include <sys/sysctl.h>
     630             : #include <netinet/ip_gre.h>
     631             : 
     632             : int
     633           0 : mobileip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     634             :     void *newp, size_t newlen)
     635             : {
     636           0 :         int allow;
     637             :         int error;
     638             : 
     639             :         /* All sysctl names at this level are terminal. */
     640           0 :         if (namelen != 1)
     641           0 :                 return (ENOTDIR);
     642             : 
     643           0 :         switch (name[0]) {
     644             :         case MOBILEIPCTL_ALLOW:
     645           0 :                 allow = mobileip_allow;
     646             : 
     647           0 :                 error = sysctl_int(oldp, oldlenp, newp, newlen,
     648             :                     &allow);
     649           0 :                 if (error != 0)
     650           0 :                         return (error);
     651             : 
     652           0 :                 mobileip_allow = allow;
     653             :                 break;
     654             :         default:
     655           0 :                 return (ENOPROTOOPT);
     656             :         }
     657             : 
     658           0 :         return (0);
     659           0 : }

Generated by: LCOV version 1.13