root/net/if_loop.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. loopattach
  2. loop_clone_create
  3. loop_clone_destroy
  4. looutput
  5. lo_altqstart
  6. lortrequest
  7. loioctl

    1 /*      $OpenBSD: if_loop.c,v 1.41 2007/06/06 10:04:36 henning Exp $    */
    2 /*      $NetBSD: if_loop.c,v 1.15 1996/05/07 02:40:33 thorpej Exp $     */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * 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 project 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 PROJECT 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 PROJECT 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 /*
   34  * Copyright (c) 1982, 1986, 1993
   35  *      The Regents of the University of California.  All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. Neither the name of the University nor the names of its contributors
   46  *    may be used to endorse or promote products derived from this software
   47  *    without specific prior written permission.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      @(#)if_loop.c   8.1 (Berkeley) 6/10/93
   62  */
   63 
   64 /*
   65  *      @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
   66  * 
   67  * NRL grants permission for redistribution and use in source and binary
   68  * forms, with or without modification, of the software and documentation
   69  * created at NRL provided that the following conditions are met:
   70  * 
   71  * 1. Redistributions of source code must retain the above copyright
   72  *    notice, this list of conditions and the following disclaimer.
   73  * 2. Redistributions in binary form must reproduce the above copyright
   74  *    notice, this list of conditions and the following disclaimer in the
   75  *    documentation and/or other materials provided with the distribution.
   76  * 3. All advertising materials mentioning features or use of this software
   77  *    must display the following acknowledgements:
   78  *      This product includes software developed by the University of
   79  *      California, Berkeley and its contributors.
   80  *      This product includes software developed at the Information
   81  *      Technology Division, US Naval Research Laboratory.
   82  * 4. Neither the name of the NRL nor the names of its contributors
   83  *    may be used to endorse or promote products derived from this software
   84  *    without specific prior written permission.
   85  * 
   86  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
   87  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   88  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   89  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
   90  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   91  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   92  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   93  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   94  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   95  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   96  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   97  * 
   98  * The views and conclusions contained in the software and documentation
   99  * are those of the authors and should not be interpreted as representing
  100  * official policies, either expressed or implied, of the US Naval
  101  * Research Laboratory (NRL).
  102  */
  103 
  104 /*
  105  * Loopback interface driver for protocol testing and timing.
  106  */
  107 
  108 #include "bpfilter.h"
  109 
  110 #include <sys/param.h>
  111 #include <sys/systm.h>
  112 #include <sys/kernel.h>
  113 #include <sys/mbuf.h>
  114 #include <sys/socket.h>
  115 #include <sys/errno.h>
  116 #include <sys/ioctl.h>
  117 #include <sys/time.h>
  118 
  119 #include <machine/cpu.h>
  120 
  121 #include <net/if.h>
  122 #include <net/if_types.h>
  123 #include <net/netisr.h>
  124 #include <net/route.h>
  125 
  126 #ifdef  INET
  127 #include <netinet/in.h>
  128 #include <netinet/in_systm.h>
  129 #include <netinet/in_var.h>
  130 #include <netinet/ip.h>
  131 #endif
  132 
  133 #ifdef INET6
  134 #ifndef INET
  135 #include <netinet/in.h>
  136 #endif
  137 #include <netinet6/in6_var.h>
  138 #include <netinet/ip6.h>
  139 #endif
  140 
  141 #ifdef NETATALK
  142 #include <netinet/if_ether.h>
  143 #include <netatalk/at.h>
  144 #include <netatalk/at_var.h>
  145 #endif
  146 
  147 #if NBPFILTER > 0
  148 #include <net/bpf.h>
  149 #endif
  150 
  151 #if defined(LARGE_LOMTU)
  152 #define LOMTU   (131072 +  MHLEN + MLEN)
  153 #else
  154 #define LOMTU   (32768 +  MHLEN + MLEN)
  155 #endif
  156   
  157 #ifdef ALTQ
  158 static void lo_altqstart(struct ifnet *);
  159 #endif
  160 
  161 int     loop_clone_create(struct if_clone *, int);
  162 int     loop_clone_destroy(struct ifnet *);
  163 
  164 struct if_clone loop_cloner =
  165     IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy);
  166 
  167 /* ARGSUSED */
  168 void
  169 loopattach(n)
  170         int n;
  171 {
  172         (void) loop_clone_create(&loop_cloner, 0);
  173         if_clone_attach(&loop_cloner);
  174 }
  175 
  176 int
  177 loop_clone_create(ifc, unit)
  178         struct if_clone *ifc;
  179         int unit;
  180 {
  181         struct ifnet *ifp;
  182 
  183         MALLOC(ifp, struct ifnet *, sizeof(*ifp), M_DEVBUF, M_NOWAIT);
  184         if (ifp == NULL)
  185                 return (ENOMEM);
  186         bzero(ifp, sizeof(struct ifnet));
  187 
  188         snprintf(ifp->if_xname, sizeof ifp->if_xname, "lo%d", unit);
  189         ifp->if_softc = NULL;
  190         ifp->if_mtu = LOMTU;
  191         ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
  192         ifp->if_ioctl = loioctl;
  193         ifp->if_output = looutput;
  194         ifp->if_type = IFT_LOOP;
  195         ifp->if_hdrlen = sizeof(u_int32_t);
  196         ifp->if_addrlen = 0;
  197         IFQ_SET_READY(&ifp->if_snd);
  198 #ifdef ALTQ
  199         ifp->if_start = lo_altqstart;
  200 #endif
  201         if (unit == 0) {
  202                 lo0ifp = ifp;
  203                 if_attachhead(ifp);
  204                 if_addgroup(lo0ifp, ifc->ifc_name);
  205         } else
  206                 if_attach(ifp);
  207         if_alloc_sadl(ifp);
  208 #if NBPFILTER > 0
  209         bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
  210 #endif
  211         return (0);
  212 }
  213 
  214 int
  215 loop_clone_destroy(ifp)
  216         struct ifnet *ifp;
  217 {
  218         if (ifp == lo0ifp)
  219                 return (EPERM);
  220 
  221         if_detach(ifp);
  222 
  223         free(ifp, M_DEVBUF);
  224         return (0);
  225 }
  226 
  227 int
  228 looutput(ifp, m, dst, rt)
  229         struct ifnet *ifp;
  230         struct mbuf *m;
  231         struct sockaddr *dst;
  232         struct rtentry *rt;
  233 {
  234         int s, isr;
  235         struct ifqueue *ifq = 0;
  236 
  237         if ((m->m_flags & M_PKTHDR) == 0)
  238                 panic("looutput: no header mbuf");
  239 #if NBPFILTER > 0
  240         /*
  241          * only send packets to bpf if they are real loopback packets;
  242          * looutput() is also called for SIMPLEX interfaces to duplicate
  243          * packets for local use. But don't dup them to bpf.
  244          */
  245         if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK))
  246                 bpf_mtap_af(ifp->if_bpf, htonl(dst->sa_family), m,
  247                     BPF_DIRECTION_OUT);
  248 #endif
  249         m->m_pkthdr.rcvif = ifp;
  250 
  251         if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
  252                 m_freem(m);
  253                 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
  254                         rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  255         }
  256 
  257         ifp->if_opackets++;
  258         ifp->if_obytes += m->m_pkthdr.len;
  259 #ifdef ALTQ
  260         /*
  261          * altq for loop is just for debugging.
  262          * only used when called for loop interface (not for
  263          * a simplex interface).
  264          */
  265         if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd))
  266             && ifp->if_start == lo_altqstart) {
  267                 int32_t *afp;
  268                 int error;
  269 
  270                 M_PREPEND(m, sizeof(int32_t), M_DONTWAIT);
  271                 if (m == 0)
  272                         return (ENOBUFS);
  273                 afp = mtod(m, int32_t *);
  274                 *afp = (int32_t)dst->sa_family;
  275 
  276                 s = splnet();
  277                 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
  278                 (*ifp->if_start)(ifp);
  279                 splx(s);
  280                 return (error);
  281         }
  282 #endif /* ALTQ */
  283         switch (dst->sa_family) {
  284 
  285 #ifdef INET
  286         case AF_INET:
  287                 ifq = &ipintrq;
  288                 isr = NETISR_IP;
  289                 break;
  290 #endif
  291 #ifdef INET6
  292         case AF_INET6:
  293                 ifq = &ip6intrq;
  294                 isr = NETISR_IPV6;
  295                 break;
  296 #endif /* INET6 */
  297 #ifdef NETATALK
  298         case AF_APPLETALK:
  299                 ifq = &atintrq2;
  300                 isr = NETISR_ATALK;
  301                 break;
  302 #endif /* NETATALK */
  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 static void
  326 lo_altqstart(ifp)
  327         struct ifnet *ifp;
  328 {
  329         struct ifqueue *ifq;
  330         struct mbuf *m;
  331         int32_t af, *afp;
  332         int s, isr;
  333         
  334         while (1) {
  335                 s = splnet();
  336                 IFQ_DEQUEUE(&ifp->if_snd, m);
  337                 splx(s);
  338                 if (m == NULL)
  339                         return;
  340 
  341                 afp = mtod(m, int32_t *);
  342                 af = *afp;
  343                 m_adj(m, sizeof(int32_t));
  344 
  345                 switch (af) {
  346 #ifdef INET
  347                 case AF_INET:
  348                         ifq = &ipintrq;
  349                         isr = NETISR_IP;
  350                         break;
  351 #endif
  352 #ifdef INET6
  353                 case AF_INET6:
  354                         m->m_flags |= M_LOOP;
  355                         ifq = &ip6intrq;
  356                         isr = NETISR_IPV6;
  357                         break;
  358 #endif
  359 #ifdef NETATALK
  360                 case AF_APPLETALK:
  361                         ifq = &atintrq2;
  362                         isr = NETISR_ATALK;
  363                         break;
  364 #endif /* NETATALK */
  365                 default:
  366                         printf("lo_altqstart: can't handle af%d\n", af);
  367                         m_freem(m);
  368                         return;
  369                 }
  370 
  371                 s = splnet();
  372                 if (IF_QFULL(ifq)) {
  373                         IF_DROP(ifq);
  374                         m_freem(m);
  375                         splx(s);
  376                         return;
  377                 }
  378                 IF_ENQUEUE(ifq, m);
  379                 schednetisr(isr);
  380                 ifp->if_ipackets++;
  381                 ifp->if_ibytes += m->m_pkthdr.len;
  382                 splx(s);
  383         }
  384 }
  385 #endif /* ALTQ */
  386 
  387 /* ARGSUSED */
  388 void
  389 lortrequest(cmd, rt, info)
  390         int cmd;
  391         struct rtentry *rt;
  392         struct rt_addrinfo *info;
  393 {
  394 
  395         if (rt)
  396                 rt->rt_rmx.rmx_mtu = LOMTU;
  397 }
  398 
  399 /*
  400  * Process an ioctl request.
  401  */
  402 /* ARGSUSED */
  403 int
  404 loioctl(ifp, cmd, data)
  405         struct ifnet *ifp;
  406         u_long cmd;
  407         caddr_t data;
  408 {
  409         struct ifaddr *ifa;
  410         struct ifreq *ifr;
  411         int error = 0;
  412 
  413         switch (cmd) {
  414 
  415         case SIOCSIFADDR:
  416                 ifp->if_flags |= IFF_UP | IFF_RUNNING;
  417                 ifa = (struct ifaddr *)data;
  418                 if (ifa != 0)
  419                         ifa->ifa_rtrequest = lortrequest;
  420                 /*
  421                  * Everything else is done at a higher level.
  422                  */
  423                 break;
  424 
  425         case SIOCADDMULTI:
  426         case SIOCDELMULTI:
  427                 ifr = (struct ifreq *)data;
  428                 if (ifr == 0) {
  429                         error = EAFNOSUPPORT;           /* XXX */
  430                         break;
  431                 }
  432                 switch (ifr->ifr_addr.sa_family) {
  433 
  434 #ifdef INET
  435                 case AF_INET:
  436                         break;
  437 #endif
  438 #ifdef INET6
  439                 case AF_INET6:
  440                         break;
  441 #endif /* INET6 */
  442 
  443                 default:
  444                         error = EAFNOSUPPORT;
  445                         break;
  446                 }
  447                 break;
  448 
  449         case SIOCSIFMTU:
  450                 ifr = (struct ifreq *)data;
  451                 ifp->if_mtu = ifr->ifr_mtu;
  452                 break;
  453 
  454         default:
  455                 error = EINVAL;
  456         }
  457         return (error);
  458 }

/* [<][>][^][v][top][bottom][index][help] */