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/net/if_faith.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: if_faith.c,v 1.37 2006/11/16 01:33:40 christos Exp $   */
    2 /*      $KAME: if_faith.c,v 1.21 2001/02/20 07:59:26 itojun Exp $       */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 /*
   33  * derived from
   34  *      @(#)if_loop.c   8.1 (Berkeley) 6/10/93
   35  * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
   36  */
   37 
   38 /*
   39  * IPv6-to-IPv4 TCP relay capturing interface
   40  */
   41 
   42 #include <sys/cdefs.h>
   43 __KERNEL_RCSID(0, "$NetBSD: if_faith.c,v 1.37 2006/11/16 01:33:40 christos Exp $");
   44 
   45 #include "opt_inet.h"
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/kernel.h>
   50 #include <sys/mbuf.h>
   51 #include <sys/socket.h>
   52 #include <sys/errno.h>
   53 #include <sys/ioctl.h>
   54 #include <sys/time.h>
   55 #include <sys/queue.h>
   56 
   57 #include <machine/cpu.h>
   58 
   59 #include <net/if.h>
   60 #include <net/if_types.h>
   61 #include <net/netisr.h>
   62 #include <net/route.h>
   63 #include <net/bpf.h>
   64 #include <net/if_faith.h>
   65 
   66 #ifdef  INET
   67 #include <netinet/in.h>
   68 #include <netinet/in_systm.h>
   69 #include <netinet/in_var.h>
   70 #include <netinet/ip.h>
   71 #endif
   72 
   73 #ifdef INET6
   74 #ifndef INET
   75 #include <netinet/in.h>
   76 #endif
   77 #include <netinet6/in6_var.h>
   78 #include <netinet/ip6.h>
   79 #include <netinet6/ip6_var.h>
   80 #endif
   81 
   82 #include "bpfilter.h"
   83 
   84 #include <net/net_osdep.h>
   85 
   86 static int      faithioctl(struct ifnet *, u_long, caddr_t);
   87 static int      faithoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
   88                             struct rtentry *);
   89 static void     faithrtrequest(int, struct rtentry *, struct rt_addrinfo *);
   90 
   91 void    faithattach(int);
   92 
   93 static int      faith_clone_create(struct if_clone *, int);
   94 static int      faith_clone_destroy(struct ifnet *);
   95 
   96 static struct if_clone faith_cloner =
   97     IF_CLONE_INITIALIZER("faith", faith_clone_create, faith_clone_destroy);
   98 
   99 #define FAITHMTU        1500
  100 
  101 /* ARGSUSED */
  102 void
  103 faithattach(int count)
  104 {
  105 
  106         if_clone_attach(&faith_cloner);
  107 }
  108 
  109 static int
  110 faith_clone_create(struct if_clone *ifc, int unit)
  111 {
  112         struct ifnet *ifp;
  113 
  114         ifp = malloc(sizeof(*ifp), M_DEVBUF, M_WAITOK | M_ZERO);
  115 
  116         snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
  117             ifc->ifc_name, unit);
  118 
  119         ifp->if_mtu = FAITHMTU;
  120         /* Change to BROADCAST experimentaly to announce its prefix. */
  121         ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
  122         ifp->if_ioctl = faithioctl;
  123         ifp->if_output = faithoutput;
  124         ifp->if_type = IFT_FAITH;
  125         ifp->if_hdrlen = 0;
  126         ifp->if_addrlen = 0;
  127         ifp->if_dlt = DLT_NULL;
  128         if_attach(ifp);
  129         if_alloc_sadl(ifp);
  130 #if NBPFILTER > 0
  131         bpfattach(ifp, DLT_NULL, sizeof(u_int));
  132 #endif
  133         return (0);
  134 }
  135 
  136 int
  137 faith_clone_destroy(struct ifnet *ifp)
  138 {
  139 
  140 #if NBPFILTER > 0
  141         bpfdetach(ifp);
  142 #endif
  143         if_detach(ifp);
  144         free(ifp, M_DEVBUF);
  145 
  146         return (0);
  147 }
  148 
  149 int
  150 faithoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  151     struct rtentry *rt)
  152 {
  153         int s, isr;
  154         struct ifqueue *ifq = 0;
  155 
  156         if ((m->m_flags & M_PKTHDR) == 0)
  157                 panic("faithoutput no HDR");
  158 #if NBPFILTER > 0
  159         /* BPF write needs to be handled specially */
  160         if (dst->sa_family == AF_UNSPEC) {
  161                 dst->sa_family = *(mtod(m, int *));
  162                 m->m_len -= sizeof(int);
  163                 m->m_pkthdr.len -= sizeof(int);
  164                 m->m_data += sizeof(int);
  165         }
  166 
  167         if (ifp->if_bpf)
  168                 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m);
  169 #endif
  170 
  171         if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
  172                 m_freem(m);
  173                 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
  174                         rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  175         }
  176         ifp->if_opackets++;
  177         ifp->if_obytes += m->m_pkthdr.len;
  178         switch (dst->sa_family) {
  179 #ifdef INET
  180         case AF_INET:
  181                 ifq = &ipintrq;
  182                 isr = NETISR_IP;
  183                 break;
  184 #endif
  185 #ifdef INET6
  186         case AF_INET6:
  187                 ifq = &ip6intrq;
  188                 isr = NETISR_IPV6;
  189                 break;
  190 #endif
  191         default:
  192                 m_freem(m);
  193                 return EAFNOSUPPORT;
  194         }
  195 
  196         /* XXX do we need more sanity checks? */
  197 
  198         m->m_pkthdr.rcvif = ifp;
  199         s = splnet();
  200         if (IF_QFULL(ifq)) {
  201                 IF_DROP(ifq);
  202                 m_freem(m);
  203                 splx(s);
  204                 return (ENOBUFS);
  205         }
  206         IF_ENQUEUE(ifq, m);
  207         schednetisr(isr);
  208         ifp->if_ipackets++;
  209         ifp->if_ibytes += m->m_pkthdr.len;
  210         splx(s);
  211         return (0);
  212 }
  213 
  214 /* ARGSUSED */
  215 static void
  216 faithrtrequest(int cmd, struct rtentry *rt,
  217     struct rt_addrinfo *info)
  218 {
  219         if (rt)
  220                 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
  221 }
  222 
  223 /*
  224  * Process an ioctl request.
  225  */
  226 /* ARGSUSED */
  227 static int
  228 faithioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  229 {
  230         struct ifaddr *ifa;
  231         struct ifreq *ifr = (struct ifreq *)data;
  232         int error = 0;
  233 
  234         switch (cmd) {
  235 
  236         case SIOCSIFADDR:
  237                 ifp->if_flags |= IFF_UP | IFF_RUNNING;
  238                 ifa = (struct ifaddr *)data;
  239                 ifa->ifa_rtrequest = faithrtrequest;
  240                 /*
  241                  * Everything else is done at a higher level.
  242                  */
  243                 break;
  244 
  245         case SIOCADDMULTI:
  246         case SIOCDELMULTI:
  247                 if (ifr == 0) {
  248                         error = EAFNOSUPPORT;           /* XXX */
  249                         break;
  250                 }
  251                 switch (ifr->ifr_addr.sa_family) {
  252 #ifdef INET
  253                 case AF_INET:
  254                         break;
  255 #endif
  256 #ifdef INET6
  257                 case AF_INET6:
  258                         break;
  259 #endif
  260 
  261                 default:
  262                         error = EAFNOSUPPORT;
  263                         break;
  264                 }
  265                 break;
  266 
  267 #ifdef SIOCSIFMTU
  268         case SIOCSIFMTU:
  269                 ifp->if_mtu = ifr->ifr_mtu;
  270                 break;
  271 #endif
  272 
  273         case SIOCSIFFLAGS:
  274                 break;
  275 
  276         default:
  277                 error = EINVAL;
  278         }
  279         return (error);
  280 }
  281 
  282 #ifdef INET6
  283 /*
  284  * XXX could be slow
  285  * XXX could be layer violation to call sys/net from sys/netinet6
  286  */
  287 int
  288 faithprefix(struct in6_addr *in6)
  289 {
  290         struct rtentry *rt;
  291         struct sockaddr_in6 sin6;
  292         int ret;
  293 
  294         if (ip6_keepfaith == 0)
  295                 return 0;
  296 
  297         memset(&sin6, 0, sizeof(sin6));
  298         sin6.sin6_family = AF_INET6;
  299         sin6.sin6_len = sizeof(struct sockaddr_in6);
  300         sin6.sin6_addr = *in6;
  301         rt = rtalloc1((struct sockaddr *)&sin6, 0);
  302         if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_FAITH &&
  303             (rt->rt_ifp->if_flags & IFF_UP) != 0)
  304                 ret = 1;
  305         else
  306                 ret = 0;
  307         if (rt)
  308                 RTFREE(rt);
  309         return ret;
  310 }
  311 #endif

Cache object: e85f323f1a6de0802527472a49e9fd8f


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