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.62 2006/11/16 01:33:40 christos 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.62 2006/11/16 01:33:40 christos Exp $");
   69 
   70 #include "opt_inet.h"
   71 #include "opt_atalk.h"
   72 #include "opt_iso.h"
   73 #include "opt_ipx.h"
   74 #include "opt_mbuftrace.h"
   75 
   76 #include "bpfilter.h"
   77 
   78 #include <sys/param.h>
   79 #include <sys/systm.h>
   80 #include <sys/kernel.h>
   81 #include <sys/mbuf.h>
   82 #include <sys/socket.h>
   83 #include <sys/errno.h>
   84 #include <sys/ioctl.h>
   85 #include <sys/time.h>
   86 
   87 #include <machine/cpu.h>
   88 
   89 #include <net/if.h>
   90 #include <net/if_types.h>
   91 #include <net/netisr.h>
   92 #include <net/route.h>
   93 
   94 #ifdef  INET
   95 #include <netinet/in.h>
   96 #include <netinet/in_systm.h>
   97 #include <netinet/in_var.h>
   98 #include <netinet/ip.h>
   99 #endif
  100 
  101 #ifdef INET6
  102 #ifndef INET
  103 #include <netinet/in.h>
  104 #endif
  105 #include <netinet6/in6_var.h>
  106 #include <netinet/ip6.h>
  107 #endif
  108 
  109 
  110 #ifdef IPX
  111 #include <netipx/ipx.h>
  112 #include <netipx/ipx_if.h>
  113 #endif
  114 
  115 #ifdef ISO
  116 #include <netiso/iso.h>
  117 #include <netiso/iso_var.h>
  118 #endif
  119 
  120 #ifdef NETATALK
  121 #include <netatalk/at.h>
  122 #include <netatalk/at_var.h>
  123 #endif
  124 
  125 #if NBPFILTER > 0
  126 #include <net/bpf.h>
  127 #endif
  128 
  129 #if defined(LARGE_LOMTU)
  130 #define LOMTU   (131072 +  MHLEN + MLEN)
  131 #define LOMTU_MAX LOMTU
  132 #else
  133 #define LOMTU   (32768 +  MHLEN + MLEN)
  134 #define LOMTU_MAX       (65536 +  MHLEN + MLEN)
  135 #endif
  136 
  137 #ifdef ALTQ
  138 static void     lostart(struct ifnet *);
  139 #endif
  140 
  141 static int      loop_clone_create(struct if_clone *, int);
  142 static int      loop_clone_destroy(struct ifnet *);
  143 
  144 static struct if_clone loop_cloner =
  145     IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy);
  146 
  147 void
  148 loopattach(int n)
  149 {
  150 
  151         (void)loop_clone_create(&loop_cloner, 0);       /* lo0 always exists */
  152         if_clone_attach(&loop_cloner);
  153 }
  154 
  155 static int
  156 loop_clone_create(struct if_clone *ifc, int unit)
  157 {
  158         struct ifnet *ifp;
  159 
  160         ifp = malloc(sizeof(*ifp), M_DEVBUF, M_WAITOK | M_ZERO);
  161 
  162         snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
  163             ifc->ifc_name, unit);
  164 
  165         ifp->if_mtu = LOMTU;
  166         ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST | IFF_RUNNING;
  167         ifp->if_ioctl = loioctl;
  168         ifp->if_output = looutput;
  169 #ifdef ALTQ
  170         ifp->if_start = lostart;
  171 #endif
  172         ifp->if_type = IFT_LOOP;
  173         ifp->if_hdrlen = 0;
  174         ifp->if_addrlen = 0;
  175         ifp->if_dlt = DLT_NULL;
  176         IFQ_SET_READY(&ifp->if_snd);
  177         if (unit == 0)
  178                 lo0ifp = ifp;
  179         if_attach(ifp);
  180         if_alloc_sadl(ifp);
  181 #if NBPFILTER > 0
  182         bpfattach(ifp, DLT_NULL, sizeof(u_int));
  183 #endif
  184 #ifdef MBUFTRACE
  185         ifp->if_mowner = malloc(sizeof(struct mowner), M_DEVBUF,
  186             M_WAITOK | M_ZERO);
  187         strlcpy(ifp->if_mowner->mo_name, ifp->if_xname,
  188             sizeof(ifp->if_mowner->mo_name));
  189         MOWNER_ATTACH(ifp->if_mowner);
  190 #endif
  191 
  192         return (0);
  193 }
  194 
  195 static int
  196 loop_clone_destroy(struct ifnet *ifp)
  197 {
  198 
  199         if (ifp == lo0ifp)
  200                 return (EPERM);
  201 
  202 #ifdef MBUFTRACE
  203         MOWNER_DETACH(ifp->if_mowner);
  204         free(ifp->if_mowner, M_DEVBUF);
  205 #endif
  206 
  207 #if NBPFILTER > 0
  208         bpfdetach(ifp);
  209 #endif
  210         if_detach(ifp);
  211 
  212         free(ifp, M_DEVBUF);
  213 
  214         return (0);
  215 }
  216 
  217 int
  218 looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  219     struct rtentry *rt)
  220 {
  221         int s, isr;
  222         struct ifqueue *ifq = NULL;
  223 
  224         MCLAIM(m, ifp->if_mowner);
  225         if ((m->m_flags & M_PKTHDR) == 0)
  226                 panic("looutput: no header mbuf");
  227 #if NBPFILTER > 0
  228         if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK))
  229                 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m);
  230 #endif
  231         m->m_pkthdr.rcvif = ifp;
  232 
  233         if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
  234                 m_freem(m);
  235                 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
  236                         rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  237         }
  238 
  239         ifp->if_opackets++;
  240         ifp->if_obytes += m->m_pkthdr.len;
  241 
  242 #ifdef ALTQ
  243         /*
  244          * ALTQ on the loopback interface is just for debugging.  It's
  245          * used only for loopback interfaces, not for a simplex interface.
  246          */
  247         if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) &&
  248             ifp->if_start == lostart) {
  249                 struct altq_pktattr pktattr;
  250                 int error;
  251 
  252                 /*
  253                  * If the queueing discipline needs packet classification,
  254                  * do it before prepending the link headers.
  255                  */
  256                 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
  257 
  258                 M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT);
  259                 if (m == NULL)
  260                         return (ENOBUFS);
  261                 *(mtod(m, uint32_t *)) = dst->sa_family;
  262 
  263                 s = splnet();
  264                 IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
  265                 (*ifp->if_start)(ifp);
  266                 splx(s);
  267                 return (error);
  268         }
  269 #endif /* ALTQ */
  270 
  271         m_tag_delete_nonpersistent(m);
  272 
  273         switch (dst->sa_family) {
  274 
  275 #ifdef INET
  276         case AF_INET:
  277                 ifq = &ipintrq;
  278                 isr = NETISR_IP;
  279                 break;
  280 #endif
  281 #ifdef INET6
  282         case AF_INET6:
  283                 m->m_flags |= M_LOOP;
  284                 ifq = &ip6intrq;
  285                 isr = NETISR_IPV6;
  286                 break;
  287 #endif
  288 #ifdef ISO
  289         case AF_ISO:
  290                 ifq = &clnlintrq;
  291                 isr = NETISR_ISO;
  292                 break;
  293 #endif
  294 #ifdef IPX
  295         case AF_IPX:
  296                 ifq = &ipxintrq;
  297                 isr = NETISR_IPX;
  298                 break;
  299 #endif
  300 #ifdef NETATALK
  301         case AF_APPLETALK:
  302                 ifq = &atintrq2;
  303                 isr = NETISR_ATALK;
  304                 break;
  305 #endif
  306         default:
  307                 printf("%s: can't handle af%d\n", ifp->if_xname,
  308                     dst->sa_family);
  309                 m_freem(m);
  310                 return (EAFNOSUPPORT);
  311         }
  312         s = splnet();
  313         if (IF_QFULL(ifq)) {
  314                 IF_DROP(ifq);
  315                 m_freem(m);
  316                 splx(s);
  317                 return (ENOBUFS);
  318         }
  319         IF_ENQUEUE(ifq, m);
  320         schednetisr(isr);
  321         ifp->if_ipackets++;
  322         ifp->if_ibytes += m->m_pkthdr.len;
  323         splx(s);
  324         return (0);
  325 }
  326 
  327 #ifdef ALTQ
  328 static void
  329 lostart(struct ifnet *ifp)
  330 {
  331         struct ifqueue *ifq;
  332         struct mbuf *m;
  333         uint32_t af;
  334         int s, isr;
  335 
  336         for (;;) {
  337                 IFQ_DEQUEUE(&ifp->if_snd, m);
  338                 if (m == NULL)
  339                         return;
  340 
  341                 af = *(mtod(m, uint32_t *));
  342                 m_adj(m, sizeof(uint32_t));
  343 
  344                 switch (af) {
  345 #ifdef INET
  346                 case AF_INET:
  347                         ifq = &ipintrq;
  348                         isr = NETISR_IP;
  349                         break;
  350 #endif
  351 #ifdef INET6
  352                 case AF_INET6:
  353                         m->m_flags |= M_LOOP;
  354                         ifq = &ip6intrq;
  355                         isr = NETISR_IPV6;
  356                         break;
  357 #endif
  358 #ifdef IPX
  359                 case AF_IPX:
  360                         ifq = &ipxintrq;
  361                         isr = NETISR_IPX;
  362                         break;
  363 #endif
  364 #ifdef ISO
  365                 case AF_ISO:
  366                         ifq = &clnlintrq;
  367                         isr = NETISR_ISO;
  368                         break;
  369 #endif
  370 #ifdef NETATALK
  371                 case AF_APPLETALK:
  372                         ifq = &atintrq2;
  373                         isr = NETISR_ATALK;
  374                         break;
  375 #endif
  376                 default:
  377                         printf("%s: can't handle af%d\n", ifp->if_xname, af);
  378                         m_freem(m);
  379                         return;
  380                 }
  381 
  382                 s = splnet();
  383                 if (IF_QFULL(ifq)) {
  384                         IF_DROP(ifq);
  385                         splx(s);
  386                         m_freem(m);
  387                         return;
  388                 }
  389                 IF_ENQUEUE(ifq, m);
  390                 schednetisr(isr);
  391                 ifp->if_ipackets++;
  392                 ifp->if_ibytes += m->m_pkthdr.len;
  393                 splx(s);
  394         }
  395 }
  396 #endif /* ALTQ */
  397 
  398 /* ARGSUSED */
  399 void
  400 lortrequest(int cmd, struct rtentry *rt,
  401     struct rt_addrinfo *info)
  402 {
  403 
  404         if (rt)
  405                 rt->rt_rmx.rmx_mtu = lo0ifp->if_mtu;
  406 }
  407 
  408 /*
  409  * Process an ioctl request.
  410  */
  411 /* ARGSUSED */
  412 int
  413 loioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  414 {
  415         struct ifaddr *ifa;
  416         struct ifreq *ifr;
  417         int error = 0;
  418 
  419         switch (cmd) {
  420 
  421         case SIOCSIFADDR:
  422                 ifp->if_flags |= IFF_UP;
  423                 ifa = (struct ifaddr *)data;
  424                 if (ifa != NULL /*&& ifa->ifa_addr->sa_family == AF_ISO*/)
  425                         ifa->ifa_rtrequest = lortrequest;
  426                 /*
  427                  * Everything else is done at a higher level.
  428                  */
  429                 break;
  430 
  431         case SIOCSIFMTU:
  432                 ifr = (struct ifreq *)data;
  433                 if ((unsigned)ifr->ifr_mtu > LOMTU_MAX)
  434                         error = EINVAL;
  435                 else {
  436                         /* XXX update rt mtu for AF_ISO? */
  437                         ifp->if_mtu = ifr->ifr_mtu;
  438                 }
  439                 break;
  440 
  441         case SIOCADDMULTI:
  442         case SIOCDELMULTI:
  443                 ifr = (struct ifreq *)data;
  444                 if (ifr == NULL) {
  445                         error = EAFNOSUPPORT;           /* XXX */
  446                         break;
  447                 }
  448                 switch (ifr->ifr_addr.sa_family) {
  449 
  450 #ifdef INET
  451                 case AF_INET:
  452                         break;
  453 #endif
  454 #ifdef INET6
  455                 case AF_INET6:
  456                         break;
  457 #endif
  458 
  459                 default:
  460                         error = EAFNOSUPPORT;
  461                         break;
  462                 }
  463                 break;
  464 
  465         default:
  466                 error = EINVAL;
  467         }
  468         return (error);
  469 }

Cache object: ab0d7927cc0cd63842653b462a48eb13


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