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

Cache object: 67ff92328a9301925bae0bc466801129


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