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_loop.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_loop.c,v 1.55 2005/02/26 22:45:09 perry Exp $       */
    2 
    3 /*
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the project nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1982, 1986, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)if_loop.c   8.2 (Berkeley) 1/9/95
   61  */
   62 
   63 /*
   64  * Loopback interface driver for protocol testing and timing.
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __KERNEL_RCSID(0, "$NetBSD: if_loop.c,v 1.55 2005/02/26 22:45:09 perry Exp $");
   69 
   70 #include "opt_inet.h"
   71 #include "opt_atalk.h"
   72 #include "opt_iso.h"
   73 #include "opt_ns.h"
   74 #include "opt_ipx.h"
   75 #include "opt_mbuftrace.h"
   76 
   77 #include "bpfilter.h"
   78 
   79 #include <sys/param.h>
   80 #include <sys/systm.h>
   81 #include <sys/kernel.h>
   82 #include <sys/mbuf.h>
   83 #include <sys/socket.h>
   84 #include <sys/errno.h>
   85 #include <sys/ioctl.h>
   86 #include <sys/time.h>
   87 
   88 #include <machine/cpu.h>
   89 
   90 #include <net/if.h>
   91 #include <net/if_types.h>
   92 #include <net/netisr.h>
   93 #include <net/route.h>
   94 
   95 #ifdef  INET
   96 #include <netinet/in.h>
   97 #include <netinet/in_systm.h>
   98 #include <netinet/in_var.h>
   99 #include <netinet/ip.h>
  100 #endif
  101 
  102 #ifdef INET6
  103 #ifndef INET
  104 #include <netinet/in.h>
  105 #endif
  106 #include <netinet6/in6_var.h>
  107 #include <netinet/ip6.h>
  108 #endif
  109 
  110 #ifdef NS
  111 #include <netns/ns.h>
  112 #include <netns/ns_if.h>
  113 #endif
  114 
  115 #ifdef IPX
  116 #include <netipx/ipx.h>
  117 #include <netipx/ipx_if.h>
  118 #endif
  119 
  120 #ifdef ISO
  121 #include <netiso/iso.h>
  122 #include <netiso/iso_var.h>
  123 #endif
  124 
  125 #ifdef NETATALK
  126 #include <netatalk/at.h>
  127 #include <netatalk/at_var.h>
  128 #endif
  129 
  130 #if NBPFILTER > 0
  131 #include <net/bpf.h>
  132 #endif
  133 
  134 #if defined(LARGE_LOMTU)
  135 #define LOMTU   (131072 +  MHLEN + MLEN)
  136 #define LOMTU_MAX LOMTU
  137 #else
  138 #define LOMTU   (32768 +  MHLEN + MLEN)
  139 #define LOMTU_MAX       (65536 +  MHLEN + MLEN)
  140 #endif
  141 
  142 #ifdef ALTQ
  143 void    lostart(struct ifnet *);
  144 #endif
  145 
  146 struct loop_softc {
  147         LIST_ENTRY(loop_softc) sc_list;
  148         struct ifnet sc_if;
  149 };
  150 
  151 LIST_HEAD(, loop_softc) loop_softc_list;
  152 
  153 int loop_clone_create(struct if_clone *, int);
  154 int loop_clone_destroy(struct ifnet *);
  155 
  156 struct if_clone loop_cloner =
  157     IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy);
  158 
  159 void
  160 loopattach(int n)
  161 {
  162         LIST_INIT(&loop_softc_list);
  163 
  164         (void)loop_clone_create(&loop_cloner, 0);       /* lo0 always exists */
  165         if_clone_attach(&loop_cloner);
  166 }
  167 
  168 int
  169 loop_clone_create(struct if_clone *ifc, int unit)
  170 {
  171         struct loop_softc *sc;
  172 
  173         sc = malloc(sizeof(struct loop_softc), M_DEVBUF, M_WAITOK | M_ZERO);
  174 
  175         snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), "%s%d",
  176             ifc->ifc_name, unit);
  177 
  178         sc->sc_if.if_softc = sc;
  179         sc->sc_if.if_mtu = LOMTU;
  180         sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST;
  181         sc->sc_if.if_ioctl = loioctl;
  182         sc->sc_if.if_output = looutput;
  183 #ifdef ALTQ
  184         sc->sc_if.if_start = lostart;
  185 #endif
  186         sc->sc_if.if_type = IFT_LOOP;
  187         sc->sc_if.if_hdrlen = 0;
  188         sc->sc_if.if_addrlen = 0;
  189         sc->sc_if.if_dlt = DLT_NULL;
  190         IFQ_SET_READY(&sc->sc_if.if_snd);
  191         if (unit == 0)
  192                 lo0ifp = &sc->sc_if;
  193         if_attach(&sc->sc_if);
  194         if_alloc_sadl(&sc->sc_if);
  195 #if NBPFILTER > 0
  196         bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
  197 #endif
  198 #ifdef MBUFTRACE
  199         sc->sc_if.if_mowner = malloc(sizeof(struct mowner), M_DEVBUF,
  200             M_WAITOK | M_ZERO);
  201         strlcpy(sc->sc_if.if_mowner->mo_name, sc->sc_if.if_xname,
  202             sizeof(sc->sc_if.if_mowner->mo_name));
  203         MOWNER_ATTACH(sc->sc_if.if_mowner);
  204 #endif
  205         LIST_INSERT_HEAD(&loop_softc_list, sc, sc_list);
  206 
  207         return (0);
  208 }
  209 
  210 int
  211 loop_clone_destroy(struct ifnet *ifp)
  212 {
  213         struct loop_softc *sc = ifp->if_softc;
  214 
  215         if (ifp == lo0ifp)
  216                 return (EPERM);
  217 
  218 #ifdef MBUFTRACE
  219         MOWNER_DETACH(ifp->if_mowner);
  220         free(ifp->if_mowner, M_DEVBUF);
  221 #endif
  222 
  223 #if NBPFILTER > 0
  224         bpfdetach(ifp);
  225 #endif
  226         if_detach(ifp);
  227 
  228         LIST_REMOVE(sc, sc_list);
  229         free(sc, M_DEVBUF);
  230 
  231         return (0);
  232 }
  233 
  234 int
  235 looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  236     struct rtentry *rt)
  237 {
  238         int s, isr;
  239         struct ifqueue *ifq = NULL;
  240 
  241         MCLAIM(m, ifp->if_mowner);
  242         if ((m->m_flags & M_PKTHDR) == 0)
  243                 panic("looutput: no header mbuf");
  244 #if NBPFILTER > 0
  245         if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK))
  246                 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m);
  247 #endif
  248         m->m_pkthdr.rcvif = ifp;
  249 
  250         if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
  251                 m_freem(m);
  252                 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
  253                         rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  254         }
  255 
  256         ifp->if_opackets++;
  257         ifp->if_obytes += m->m_pkthdr.len;
  258 
  259 #ifdef ALTQ
  260         /*
  261          * ALTQ on the loopback interface is just for debugging.  It's
  262          * used only for loopback interfaces, not for a simplex interface.
  263          */
  264         if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) &&
  265             ifp->if_start == lostart) {
  266                 struct altq_pktattr pktattr;
  267                 int error;
  268 
  269                 /*
  270                  * If the queueing discipline needs packet classification,
  271                  * do it before prepending the link headers.
  272                  */
  273                 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
  274 
  275                 M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT);
  276                 if (m == NULL)
  277                         return (ENOBUFS);
  278                 *(mtod(m, uint32_t *)) = dst->sa_family;
  279 
  280                 s = splnet();
  281                 IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
  282                 (*ifp->if_start)(ifp);
  283                 splx(s);
  284                 return (error);
  285         }
  286 #endif /* ALTQ */
  287 
  288         m_tag_delete_nonpersistent(m);
  289 
  290         switch (dst->sa_family) {
  291 
  292 #ifdef INET
  293         case AF_INET:
  294                 ifq = &ipintrq;
  295                 isr = NETISR_IP;
  296                 break;
  297 #endif
  298 #ifdef INET6
  299         case AF_INET6:
  300                 m->m_flags |= M_LOOP;
  301                 ifq = &ip6intrq;
  302                 isr = NETISR_IPV6;
  303                 break;
  304 #endif
  305 #ifdef NS
  306         case AF_NS:
  307                 ifq = &nsintrq;
  308                 isr = NETISR_NS;
  309                 break;
  310 #endif
  311 #ifdef ISO
  312         case AF_ISO:
  313                 ifq = &clnlintrq;
  314                 isr = NETISR_ISO;
  315                 break;
  316 #endif
  317 #ifdef IPX
  318         case AF_IPX:
  319                 ifq = &ipxintrq;
  320                 isr = NETISR_IPX;
  321                 break;
  322 #endif
  323 #ifdef NETATALK
  324         case AF_APPLETALK:
  325                 ifq = &atintrq2;
  326                 isr = NETISR_ATALK;
  327                 break;
  328 #endif
  329         default:
  330                 printf("%s: can't handle af%d\n", ifp->if_xname,
  331                     dst->sa_family);
  332                 m_freem(m);
  333                 return (EAFNOSUPPORT);
  334         }
  335         s = splnet();
  336         if (IF_QFULL(ifq)) {
  337                 IF_DROP(ifq);
  338                 m_freem(m);
  339                 splx(s);
  340                 return (ENOBUFS);
  341         }
  342         IF_ENQUEUE(ifq, m);
  343         schednetisr(isr);
  344         ifp->if_ipackets++;
  345         ifp->if_ibytes += m->m_pkthdr.len;
  346         splx(s);
  347         return (0);
  348 }
  349 
  350 #ifdef ALTQ
  351 void
  352 lostart(struct ifnet *ifp)
  353 {
  354         struct ifqueue *ifq;
  355         struct mbuf *m;
  356         uint32_t af;
  357         int s, isr;
  358 
  359         for (;;) {
  360                 IFQ_DEQUEUE(&ifp->if_snd, m);
  361                 if (m == NULL)
  362                         return;
  363 
  364                 af = *(mtod(m, uint32_t *));
  365                 m_adj(m, sizeof(uint32_t));
  366 
  367                 switch (af) {
  368 #ifdef INET
  369                 case AF_INET:
  370                         ifq = &ipintrq;
  371                         isr = NETISR_IP;
  372                         break;
  373 #endif
  374 #ifdef INET6
  375                 case AF_INET6:
  376                         m->m_flags |= M_LOOP;
  377                         ifq = &ip6intrq;
  378                         isr = NETISR_IPV6;
  379                         break;
  380 #endif
  381 #ifdef IPX
  382                 case AF_IPX:
  383                         ifq = &ipxintrq;
  384                         isr = NETISR_IPX;
  385                         break;
  386 #endif
  387 #ifdef NS
  388                 case AF_NS:
  389                         ifq = &nsintrq;
  390                         isr = NETISR_NS;
  391                         break;
  392 #endif
  393 #ifdef ISO
  394                 case AF_ISO:
  395                         ifq = &clnlintrq;
  396                         isr = NETISR_ISO;
  397                         break;
  398 #endif
  399 #ifdef NETATALK
  400                 case AF_APPLETALK:
  401                         ifq = &atintrq2;
  402                         isr = NETISR_ATALK;
  403                         break;
  404 #endif
  405                 default:
  406                         printf("%s: can't handle af%d\n", ifp->if_xname, af);
  407                         m_freem(m);
  408                         return;
  409                 }
  410 
  411                 s = splnet();
  412                 if (IF_QFULL(ifq)) {
  413                         IF_DROP(ifq);
  414                         splx(s);
  415                         m_freem(m);
  416                         return;
  417                 }
  418                 IF_ENQUEUE(ifq, m);
  419                 schednetisr(isr);
  420                 ifp->if_ipackets++;
  421                 ifp->if_ibytes += m->m_pkthdr.len;
  422                 splx(s);
  423         }
  424 }
  425 #endif /* ALTQ */
  426 
  427 /* ARGSUSED */
  428 void
  429 lortrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
  430 {
  431 
  432         if (rt)
  433                 rt->rt_rmx.rmx_mtu = lo0ifp->if_mtu;
  434 }
  435 
  436 /*
  437  * Process an ioctl request.
  438  */
  439 /* ARGSUSED */
  440 int
  441 loioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  442 {
  443         struct ifaddr *ifa;
  444         struct ifreq *ifr;
  445         int error = 0;
  446 
  447         switch (cmd) {
  448 
  449         case SIOCSIFADDR:
  450                 ifp->if_flags |= IFF_UP;
  451                 ifa = (struct ifaddr *)data;
  452                 if (ifa != NULL /*&& ifa->ifa_addr->sa_family == AF_ISO*/)
  453                         ifa->ifa_rtrequest = lortrequest;
  454                 /*
  455                  * Everything else is done at a higher level.
  456                  */
  457                 break;
  458 
  459         case SIOCSIFMTU:
  460                 ifr = (struct ifreq *)data;
  461                 if ((unsigned)ifr->ifr_mtu > LOMTU_MAX)
  462                         error = EINVAL;
  463                 else {
  464                         /* XXX update rt mtu for AF_ISO? */
  465                         ifp->if_mtu = ifr->ifr_mtu;
  466                 }
  467                 break;
  468 
  469         case SIOCADDMULTI:
  470         case SIOCDELMULTI:
  471                 ifr = (struct ifreq *)data;
  472                 if (ifr == NULL) {
  473                         error = EAFNOSUPPORT;           /* XXX */
  474                         break;
  475                 }
  476                 switch (ifr->ifr_addr.sa_family) {
  477 
  478 #ifdef INET
  479                 case AF_INET:
  480                         break;
  481 #endif
  482 #ifdef INET6
  483                 case AF_INET6:
  484                         break;
  485 #endif
  486 
  487                 default:
  488                         error = EAFNOSUPPORT;
  489                         break;
  490                 }
  491                 break;
  492 
  493         default:
  494                 error = EINVAL;
  495         }
  496         return (error);
  497 }

Cache object: 3e77c820e39138e189d0ee6b061e11d4


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