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/bsd/net/if_faith.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) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*      $KAME: if_faith.c,v 1.21 2001/02/20 07:59:26 itojun Exp $       */
   26 
   27 /*
   28  * Copyright (c) 1982, 1986, 1993
   29  *      The Regents of the University of California.  All rights reserved.
   30  *
   31  * Redistribution and use in source and binary forms, with or without
   32  * modification, are permitted provided that the following conditions
   33  * are met:
   34  * 1. Redistributions of source code must retain the above copyright
   35  *    notice, this list of conditions and the following disclaimer.
   36  * 2. Redistributions in binary form must reproduce the above copyright
   37  *    notice, this list of conditions and the following disclaimer in the
   38  *    documentation and/or other materials provided with the distribution.
   39  * 3. All advertising materials mentioning features or use of this software
   40  *    must display the following acknowledgement:
   41  *      This product includes software developed by the University of
   42  *      California, Berkeley and its contributors.
   43  * 4. Neither the name of the University nor the names of its contributors
   44  *    may be used to endorse or promote products derived from this software
   45  *    without specific prior written permission.
   46  *
   47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   57  * SUCH DAMAGE.
   58  *
   59  * $FreeBSD: src/sys/net/if_faith.c,v 1.3.2.2 2001/07/05 14:46:25 ume Exp $
   60  */
   61 /*
   62  * derived from
   63  *      @(#)if_loop.c   8.1 (Berkeley) 6/10/93
   64  * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
   65  */
   66 
   67 /*
   68  * Loopback interface driver for protocol testing and timing.
   69  */
   70 
   71 #include "faith.h"
   72 #if NFAITH > 0
   73 
   74 #include <sys/param.h>
   75 #include <sys/systm.h>
   76 #include <sys/kernel.h>
   77 #include <sys/mbuf.h>
   78 #include <sys/socket.h>
   79 #include <sys/errno.h>
   80 #include <sys/sockio.h>
   81 #include <sys/time.h>
   82 #include <sys/queue.h>
   83 
   84 #include <net/if.h>
   85 #include <net/if_types.h>
   86 #include <net/netisr.h>
   87 #include <net/route.h>
   88 #include <net/bpf.h>
   89 #include <net/if_faith.h>
   90 
   91 #if     INET
   92 #include <netinet/in.h>
   93 #include <netinet/in_systm.h>
   94 #include <netinet/in_var.h>
   95 #include <netinet/ip.h>
   96 #endif
   97 
   98 #if INET6
   99 #ifndef INET
  100 #include <netinet/in.h>
  101 #endif
  102 #include <netinet6/in6_var.h>
  103 #include <netinet/ip6.h>
  104 #include <netinet6/ip6_var.h>
  105 #endif
  106 
  107 #include <net/dlil.h>
  108 #include "bpf.h"
  109 
  110 #include <net/net_osdep.h>
  111 
  112 static int faithioctl __P((struct ifnet *, u_long, void*));
  113 int faith_pre_output __P((struct ifnet *, register struct mbuf **, struct sockaddr *,
  114         caddr_t, char *, char *, u_long));
  115 static void faithrtrequest __P((int, struct rtentry *, struct sockaddr *));
  116 
  117 void faithattach __P((void));
  118 #ifndef __APPLE__
  119 PSEUDO_SET(faithattach, if_faith);
  120 #endif
  121 
  122 static struct ifnet faithif[NFAITH];
  123 static struct if_proto *faith_array[NFAITH];
  124 static int faith_count = 0;
  125 
  126 #define FAITHMTU        1500
  127 
  128 static
  129 int  faith_add_if(struct ifnet *ifp)
  130 {
  131     ifp->if_demux  = 0;
  132     ifp->if_framer = 0;
  133     return 0;
  134 }
  135 
  136 static 
  137 int  faith_del_if(struct ifnet *ifp)
  138 {
  139     return 0;
  140 }
  141 
  142 static
  143 int  faith_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
  144 {       
  145     int i;
  146     
  147     for (i=0; i < faith_count; i++)
  148         if (faith_array[i] == 0) {
  149             faith_array[faith_count] = proto;
  150             return 0;
  151         }
  152     
  153     if ((i == faith_count) && (faith_count == NFAITH))
  154        panic("faith_add_proto -- Too many attachments\n");
  155 
  156     faith_array[faith_count++] = proto;
  157 
  158     return (0);
  159 }
  160 
  161 static
  162 int  faith_del_proto(struct if_proto *proto, u_long dl_tag)
  163 {   
  164     int i;
  165 
  166 
  167     for (i=0; i < faith_count; i++)
  168         if (faith_array[i] == proto) {
  169             faith_array[i] = 0;
  170             return 0;
  171         }
  172 
  173     return ENOENT;
  174 }
  175 
  176 int faith_shutdown()
  177 {
  178     return 0;
  179 }
  180 
  181 int  faith_attach_inet(struct ifnet *ifp, u_long *dl_tag)
  182 {       
  183     struct dlil_proto_reg_str   reg;
  184     struct dlil_demux_desc      desc;
  185     short native=0;
  186     int   stat;
  187     int i;
  188 
  189     for (i=0; i < faith_count; i++) {
  190         if (faith_array[i] && (faith_array[i]->ifp == ifp) &&
  191             (faith_array[i]->protocol_family == PF_INET)) {
  192 #if 0
  193                 kprintf("faith_array for %s%d found dl_tag=%d\n",
  194                        ifp->if_name, ifp->if_unit, faith_array[i]->dl_tag);
  195 #endif
  196                 *dl_tag = faith_array[i]->dl_tag;
  197                 return 0;
  198        
  199         }
  200     }
  201 
  202     TAILQ_INIT(&reg.demux_desc_head); 
  203     desc.type = DLIL_DESC_RAW;
  204     desc.variants.bitmask.proto_id_length = 0;
  205     desc.variants.bitmask.proto_id = 0;
  206     desc.variants.bitmask.proto_id_mask = 0;
  207     desc.native_type = (char *) &native;
  208     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
  209     reg.interface_family = ifp->if_family;
  210     reg.unit_number      = ifp->if_unit;
  211     reg.input            = 0;
  212     reg.pre_output       = faith_pre_output;
  213     reg.event            = 0;
  214     reg.offer            = 0;
  215     reg.ioctl            = 0;
  216     reg.default_proto    = 0;
  217     reg.protocol_family  = PF_INET;
  218 
  219     stat = dlil_attach_protocol(&reg, dl_tag);
  220     if (stat) {
  221         panic("faith_attach_inet can't attach interface\n");
  222     }
  223 
  224     return stat;
  225 }
  226 
  227 void faith_reg_if_mods()
  228 {   
  229      struct dlil_ifmod_reg_str  faith_ifmod;
  230      struct dlil_protomod_reg_str faith_protoreg;
  231      int error;
  232 
  233      bzero(&faith_ifmod, sizeof(faith_ifmod));
  234      faith_ifmod.add_if = faith_add_if;
  235      faith_ifmod.del_if = faith_del_if;
  236      faith_ifmod.add_proto = faith_add_proto;
  237      faith_ifmod.del_proto = faith_del_proto;
  238      faith_ifmod.ifmod_ioctl = 0;
  239      faith_ifmod.shutdown    = faith_shutdown;
  240 
  241     
  242     if (dlil_reg_if_modules(APPLE_IF_FAM_FAITH, &faith_ifmod))
  243         panic("Couldn't register faith modules\n");
  244 
  245         /* Register protocol registration functions */
  246 
  247         bzero(&faith_protoreg, sizeof(faith_protoreg));
  248         faith_protoreg.attach_proto = faith_attach_inet;
  249         faith_protoreg.detach_proto = 0;
  250         
  251         if ( error = dlil_reg_proto_module(PF_INET, APPLE_IF_FAM_FAITH, &faith_protoreg) != 0)
  252                 kprintf("dlil_reg_proto_module failed for AF_INET error=%d\n", error);
  253 
  254     
  255 }   
  256     
  257 void
  258 faithattach(void)
  259 {
  260         struct ifnet *ifp;
  261         int i;
  262 
  263         faith_reg_if_mods(); /* DLIL modules */
  264 
  265         for (i = 0; i < NFAITH; i++) {
  266                 ifp = &faithif[i];
  267                 bzero(ifp, sizeof(faithif[i]));
  268                 ifp->if_name = "faith";
  269                 ifp->if_unit = i;
  270                 ifp->if_family = APPLE_IF_FAM_FAITH;
  271                 ifp->if_mtu = FAITHMTU;
  272                 /* LOOPBACK commented out to announce IPv6 routes to faith */
  273                 ifp->if_flags = /* IFF_LOOPBACK | */ IFF_MULTICAST;
  274                 ifp->if_ioctl = faithioctl;
  275                 ifp->if_output = NULL;
  276                 ifp->if_type = IFT_FAITH;
  277                 ifp->if_hdrlen = 0;
  278                 ifp->if_addrlen = 0;
  279                 dlil_if_attach(ifp);
  280 #if NBPFILTER > 0
  281 #ifdef HAVE_OLD_BPF
  282                 bpfattach(ifp, DLT_NULL, sizeof(u_int));
  283 #else
  284                 bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
  285 #endif
  286 #endif
  287         }
  288 }
  289 
  290 int
  291 faith_pre_output(ifp, m0, dst, route_entry, frame_type, dst_addr, dl_tag)
  292         struct ifnet *ifp;
  293         register struct mbuf **m0;
  294         struct sockaddr *dst;
  295         caddr_t                  route_entry;
  296         char                 *frame_type;
  297         char                 *dst_addr;
  298         u_long               dl_tag;
  299 {
  300         int s, isr;
  301         register struct ifqueue *ifq = 0;
  302         register struct mbuf *m = *m0;
  303         struct rtentry *rt = (struct rtentry*)route_entry;
  304 
  305         if ((m->m_flags & M_PKTHDR) == 0)
  306                 panic("faithoutput no HDR");
  307 #if NBPFILTER > 0
  308         /* BPF write needs to be handled specially */
  309         if (dst && dst->sa_family == AF_UNSPEC) {
  310                 dst->sa_family = *(mtod(m, int *));
  311                 m->m_len -= sizeof(int);
  312                 m->m_pkthdr.len -= sizeof(int);
  313                 m->m_data += sizeof(int);
  314         }
  315 
  316         if (ifp->if_bpf) {
  317                 /*
  318                  * We need to prepend the address family as
  319                  * a four byte field.  Cons up a faith header
  320                  * to pacify bpf.  This is safe because bpf
  321                  * will only read from the mbuf (i.e., it won't
  322                  * try to free it or keep a pointer a to it).
  323                  */
  324                 struct mbuf m0;
  325                 u_int32_t af = dst->sa_family;
  326 
  327                 m0.m_next = m;
  328                 m0.m_len = 4;
  329                 m0.m_data = (char *)&af;
  330 
  331 #ifdef HAVE_OLD_BPF
  332                 bpf_mtap(ifp, &m0);
  333 #else
  334                 bpf_mtap(ifp->if_bpf, &m0);
  335 #endif
  336         }
  337 #endif
  338 
  339         if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
  340                 return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
  341                         rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  342         }
  343         ifp->if_opackets++;
  344         ifp->if_obytes += m->m_pkthdr.len;
  345         switch (dst->sa_family) {
  346 #if INET
  347         case AF_INET:
  348                 ifq = &ipintrq;
  349                 isr = NETISR_IP;
  350                 break;
  351 #endif
  352 #if INET6
  353         case AF_INET6:
  354                 ifq = &ip6intrq;
  355                 isr = NETISR_IPV6;
  356                 break;
  357 #endif
  358         default:
  359                 return EAFNOSUPPORT;
  360         }
  361 
  362         /* XXX do we need more sanity checks? */
  363 
  364         m->m_pkthdr.rcvif = ifp;
  365         s = splimp();
  366         if (IF_QFULL(ifq)) {
  367                 IF_DROP(ifq);
  368                 splx(s);
  369                 return (ENOBUFS);
  370         }
  371         IF_ENQUEUE(ifq, m);
  372         schednetisr(isr);
  373         ifp->if_ipackets++;
  374         ifp->if_ibytes += m->m_pkthdr.len;
  375         splx(s);
  376         return (EJUSTRETURN);
  377 }
  378 
  379 /* ARGSUSED */
  380 static void
  381 faithrtrequest(cmd, rt, sa)
  382         int cmd;
  383         struct rtentry *rt;
  384         struct sockaddr *sa;
  385 {
  386         if (rt) {
  387                 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
  388                 /*
  389                  * For optimal performance, the send and receive buffers
  390                  * should be at least twice the MTU plus a little more for
  391                  * overhead.
  392                  */
  393                 rt->rt_rmx.rmx_recvpipe =
  394                         rt->rt_rmx.rmx_sendpipe = 3 * FAITHMTU;
  395         }
  396 }
  397 
  398 /*
  399  * Process an ioctl request.
  400  */
  401 /* ARGSUSED */
  402 static int
  403 faithioctl(ifp, cmd, data)
  404         struct ifnet *ifp;
  405         u_long cmd;
  406         void* data;
  407 {
  408         struct ifaddr *ifa;
  409         struct ifreq *ifr = (struct ifreq *)data;
  410         int error = 0;
  411 
  412         switch (cmd) {
  413 
  414         case SIOCSIFADDR:
  415                 ifp->if_flags |= IFF_UP | IFF_RUNNING;
  416                 ifa = (struct ifaddr *)data;
  417                 ifa->ifa_rtrequest = faithrtrequest;
  418                 /*
  419                  * Everything else is done at a higher level.
  420                  */
  421                 break;
  422 
  423         case SIOCADDMULTI:
  424         case SIOCDELMULTI:
  425                 if (ifr == 0) {
  426                         error = EAFNOSUPPORT;           /* XXX */
  427                         break;
  428                 }
  429                 switch (ifr->ifr_addr.sa_family) {
  430 #if INET
  431                 case AF_INET:
  432                         break;
  433 #endif
  434 #if INET6
  435                 case AF_INET6:
  436                         break;
  437 #endif
  438 
  439                 default:
  440                         error = EAFNOSUPPORT;
  441                         break;
  442                 }
  443                 break;
  444 
  445 #ifdef SIOCSIFMTU
  446         case SIOCSIFMTU:
  447                 ifp->if_mtu = ifr->ifr_mtu;
  448                 break;
  449 #endif
  450 
  451         case SIOCSIFFLAGS:
  452                 break;
  453 
  454         default:
  455                 error = EINVAL;
  456         }
  457         return (error);
  458 }
  459 
  460 #if INET6
  461 /*
  462  * XXX could be slow
  463  * XXX could be layer violation to call sys/net from sys/netinet6
  464  */
  465 int
  466 faithprefix(in6)
  467         struct in6_addr *in6;
  468 {
  469         struct rtentry *rt;
  470         struct sockaddr_in6 sin6;
  471         int ret;
  472 
  473         if (ip6_keepfaith == 0)
  474                 return 0;
  475 
  476         bzero(&sin6, sizeof(sin6));
  477         sin6.sin6_family = AF_INET6;
  478         sin6.sin6_len = sizeof(struct sockaddr_in6);
  479         sin6.sin6_addr = *in6;
  480         rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
  481         if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_FAITH &&
  482             (rt->rt_ifp->if_flags & IFF_UP) != 0)
  483                 ret = 1;
  484         else
  485                 ret = 0;
  486         if (rt)
  487                 rtfree(rt);
  488         return ret;
  489 }
  490 #endif
  491 #endif /* NFAITH > 0 */

Cache object: 5a9d6a6de23a91e0f2e477823f187a51


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