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 /*
    2  * Copyright (c) 1982, 1986, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)if_loop.c   8.1 (Berkeley) 6/10/93
   34  * $FreeBSD$
   35  */
   36 
   37 /*
   38  * Loopback interface driver for protocol testing and timing.
   39  */
   40 #include "loop.h"
   41 #if NLOOP > 0
   42 
   43 #include "opt_atalk.h"
   44 #include "opt_inet.h"
   45 #include "opt_ipx.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/sockio.h>
   53 
   54 #include <net/if.h>
   55 #include <net/if_types.h>
   56 #include <net/netisr.h>
   57 #include <net/route.h>
   58 #include <net/bpf.h>
   59 
   60 #ifdef  INET
   61 #include <netinet/in.h>
   62 #include <netinet/in_var.h>
   63 #endif
   64 
   65 #ifdef IPX
   66 #include <netipx/ipx.h>
   67 #include <netipx/ipx_if.h>
   68 #endif
   69 
   70 #ifdef NS
   71 #include <netns/ns.h>
   72 #include <netns/ns_if.h>
   73 #endif
   74 
   75 #ifdef ISO
   76 #include <netiso/iso.h>
   77 #include <netiso/iso_var.h>
   78 #endif
   79 
   80 #ifdef NETATALK
   81 #include <netatalk/at.h>
   82 #include <netatalk/at_var.h>
   83 #endif NETATALK
   84 
   85 #include "bpfilter.h"
   86 #if NBPFILTER > 0
   87 #include <net/bpfdesc.h>
   88 #endif
   89 
   90 static int loioctl __P((struct ifnet *, u_long, caddr_t));
   91 static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
   92 
   93 static void loopattach __P((void *));
   94 PSEUDO_SET(loopattach, if_loop);
   95 
   96 static int looutput __P((struct ifnet *ifp,
   97                 struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
   98 
   99 #ifdef TINY_LOMTU
  100 #define LOMTU   (1024+512)
  101 #else
  102 #define LOMTU   16384
  103 #endif
  104 
  105 struct  ifnet loif[NLOOP];
  106 
  107 /* ARGSUSED */
  108 static void
  109 loopattach(dummy)
  110         void *dummy;
  111 {
  112         register struct ifnet *ifp;
  113         register int i = 0;
  114 
  115         for (ifp = loif; i < NLOOP; ifp++) {
  116             ifp->if_name = "lo";
  117             ifp->if_unit = i++;
  118             ifp->if_mtu = LOMTU;
  119             ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
  120             ifp->if_ioctl = loioctl;
  121             ifp->if_output = looutput;
  122             ifp->if_type = IFT_LOOP;
  123             if_attach(ifp);
  124 #if NBPFILTER > 0
  125             bpfattach(ifp, DLT_NULL, sizeof(u_int));
  126 #endif
  127         }
  128 }
  129 
  130 static int
  131 looutput(ifp, m, dst, rt)
  132         struct ifnet *ifp;
  133         register struct mbuf *m;
  134         struct sockaddr *dst;
  135         register struct rtentry *rt;
  136 {
  137         if ((m->m_flags & M_PKTHDR) == 0)
  138                 panic("looutput no HDR");
  139 
  140         if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
  141                 m_freem(m);
  142                 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
  143                         rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  144         }
  145         ifp->if_opackets++;
  146         ifp->if_obytes += m->m_pkthdr.len;
  147 #if 1   /* XXX */
  148         switch (dst->sa_family) {
  149         case AF_INET:
  150         case AF_IPX:
  151         case AF_NS:
  152         case AF_ISO:
  153         case AF_APPLETALK:
  154                 break;
  155         default:
  156                 printf("looutput: af=%d unexpected", dst->sa_family);
  157                 m_freem(m);
  158                 return (EAFNOSUPPORT);
  159         }
  160 #endif
  161         return(if_simloop(ifp, m, dst, 0));
  162 }
  163 
  164 /*
  165  * if_simloop()
  166  *
  167  * This function is to support software emulation of hardware loopback,
  168  * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't
  169  * hear their own broadcasts, we create a copy of the packet that we
  170  * would normally receive via a hardware loopback.
  171  *
  172  * This function expects the packet to include the media header of length hlen.
  173  */
  174 
  175 int
  176 if_simloop(ifp, m, dst, hlen)
  177         struct ifnet *ifp;
  178         register struct mbuf *m;
  179         struct sockaddr *dst;
  180         int hlen;
  181 {
  182         int s, isr;
  183         register struct ifqueue *ifq = 0;
  184 
  185         if ((m->m_flags & M_PKTHDR) == 0)
  186                 panic("if_simloop: no HDR");
  187         m->m_pkthdr.rcvif = ifp;
  188 #if NBPFILTER > 0
  189         /* BPF write needs to be handled specially */
  190         if (dst->sa_family == AF_UNSPEC) {
  191                 dst->sa_family = *(mtod(m, int *));
  192                 m->m_len -= sizeof(int);
  193                 m->m_pkthdr.len -= sizeof(int);
  194                 m->m_data += sizeof(int);
  195         }
  196 
  197         if (ifp->if_bpf) {
  198                 struct mbuf m0, *n = m;
  199                 u_int af = dst->sa_family;
  200 
  201                 if (ifp->if_bpf->bif_dlt == DLT_NULL) {
  202                         /*
  203                          * We need to prepend the address family as
  204                          * a four byte field.  Cons up a dummy header
  205                          * to pacify bpf.  This is safe because bpf
  206                          * will only read from the mbuf (i.e., it won't
  207                          * try to free it or keep a pointer a to it).
  208                          */
  209                         m0.m_next = m;
  210                         m0.m_len = 4;
  211                         m0.m_data = (char *)&af;
  212                         n = &m0;
  213                 }
  214                 bpf_mtap(ifp, n);
  215         }
  216 #endif
  217 
  218         /* Strip away media header */
  219         if (hlen > 0) {
  220 #ifdef __alpha__
  221                 /* The alpha doesn't like unaligned data.
  222                  * We move data down in the first mbuf */
  223                 if (hlen & 3) {
  224                         bcopy(m->m_data + hlen, m->m_data, m->m_len - hlen);
  225                         m->m_len -= hlen;
  226                         if (m->m_flags & M_PKTHDR)
  227                                 m->m_pkthdr.len -= hlen;
  228                 } else
  229 #endif
  230                 m_adj(m, hlen);
  231         }
  232 
  233         switch (dst->sa_family) {
  234 #ifdef INET
  235         case AF_INET:
  236                 ifq = &ipintrq;
  237                 isr = NETISR_IP;
  238                 break;
  239 #endif
  240 #ifdef IPX
  241         case AF_IPX:
  242                 ifq = &ipxintrq;
  243                 isr = NETISR_IPX;
  244                 break;
  245 #endif
  246 #ifdef NS
  247         case AF_NS:
  248                 ifq = &nsintrq;
  249                 isr = NETISR_NS;
  250                 break;
  251 #endif
  252 #ifdef ISO
  253         case AF_ISO:
  254                 ifq = &clnlintrq;
  255                 isr = NETISR_ISO;
  256                 break;
  257 #endif
  258 #ifdef NETATALK
  259         case AF_APPLETALK:
  260                 ifq = &atintrq2;
  261                 isr = NETISR_ATALK;
  262                 break;
  263 #endif NETATALK
  264         default:
  265                 printf("if_simloop: can't handle af=%d\n", dst->sa_family);
  266                 m_freem(m);
  267                 return (EAFNOSUPPORT);
  268         }
  269         s = splimp();
  270         if (IF_QFULL(ifq)) {
  271                 IF_DROP(ifq);
  272                 m_freem(m);
  273                 splx(s);
  274                 return (ENOBUFS);
  275         }
  276         IF_ENQUEUE(ifq, m);
  277         schednetisr(isr);
  278         ifp->if_ipackets++;
  279         ifp->if_ibytes += m->m_pkthdr.len;
  280         splx(s);
  281         return (0);
  282 }
  283 
  284 /* ARGSUSED */
  285 static void
  286 lortrequest(cmd, rt, sa)
  287         int cmd;
  288         struct rtentry *rt;
  289         struct sockaddr *sa;
  290 {
  291         if (rt) {
  292                 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
  293                 /*
  294                  * For optimal performance, the send and receive buffers
  295                  * should be at least twice the MTU plus a little more for
  296                  * overhead.
  297                  */
  298                 rt->rt_rmx.rmx_recvpipe = 
  299                         rt->rt_rmx.rmx_sendpipe = 3 * LOMTU;
  300         }
  301 }
  302 
  303 /*
  304  * Process an ioctl request.
  305  */
  306 /* ARGSUSED */
  307 static int
  308 loioctl(ifp, cmd, data)
  309         register struct ifnet *ifp;
  310         u_long cmd;
  311         caddr_t data;
  312 {
  313         register struct ifaddr *ifa;
  314         register struct ifreq *ifr = (struct ifreq *)data;
  315         register int error = 0;
  316 
  317         switch (cmd) {
  318 
  319         case SIOCSIFADDR:
  320                 ifp->if_flags |= IFF_UP | IFF_RUNNING;
  321                 ifa = (struct ifaddr *)data;
  322                 ifa->ifa_rtrequest = lortrequest;
  323                 /*
  324                  * Everything else is done at a higher level.
  325                  */
  326                 break;
  327 
  328         case SIOCADDMULTI:
  329         case SIOCDELMULTI:
  330                 if (ifr == 0) {
  331                         error = EAFNOSUPPORT;           /* XXX */
  332                         break;
  333                 }
  334                 switch (ifr->ifr_addr.sa_family) {
  335 
  336 #ifdef INET
  337                 case AF_INET:
  338                         break;
  339 #endif
  340 
  341                 default:
  342                         error = EAFNOSUPPORT;
  343                         break;
  344                 }
  345                 break;
  346 
  347         case SIOCSIFMTU:
  348                 ifp->if_mtu = ifr->ifr_mtu;
  349                 break;
  350 
  351         case SIOCSIFFLAGS:
  352                 break;
  353 
  354         default:
  355                 error = EINVAL;
  356         }
  357         return (error);
  358 }
  359 #endif /* NLOOP > 0 */

Cache object: b00cfa512023db37aff467ea17d8f5f4


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