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_ethersubr.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, 1989, 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_ethersubr.c      8.1 (Berkeley) 6/10/93
   34  * $FreeBSD$
   35  */
   36 
   37 #include "opt_atalk.h"
   38 #include "opt_inet.h"
   39 #include "opt_ipx.h"
   40 #include "opt_bdg.h"
   41 #include "opt_netgraph.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/kernel.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/socket.h>
   49 #include <sys/sockio.h>
   50 #include <sys/sysctl.h>
   51 
   52 #include <net/if.h>
   53 #include <net/netisr.h>
   54 #include <net/route.h>
   55 #include <net/if_llc.h>
   56 #include <net/if_dl.h>
   57 #include <net/if_types.h>
   58 
   59 #ifdef INET
   60 #include <netinet/in.h>
   61 #include <netinet/in_var.h>
   62 #include <netinet/if_ether.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 ushort ns_nettype;
   74 int ether_outputdebug = 0;
   75 int ether_inputdebug = 0;
   76 #endif
   77 
   78 #ifdef ISO
   79 #include <netiso/argo_debug.h>
   80 #include <netiso/iso.h>
   81 #include <netiso/iso_var.h>
   82 #include <netiso/iso_snpac.h>
   83 #endif
   84 
   85 /*#ifdef LLC
   86 #include <netccitt/dll.h>
   87 #include <netccitt/llc_var.h>
   88 #endif*/
   89 
   90 #if defined(LLC) && defined(CCITT)
   91 extern struct ifqueue pkintrq;
   92 #endif
   93 
   94 #ifdef NETATALK
   95 #include <netatalk/at.h>
   96 #include <netatalk/at_var.h>
   97 #include <netatalk/at_extern.h>
   98 
   99 #define llc_snap_org_code llc_un.type_snap.org_code
  100 #define llc_snap_ether_type llc_un.type_snap.ether_type
  101 
  102 extern u_char   at_org_code[3];
  103 extern u_char   aarp_org_code[3];
  104 #endif /* NETATALK */
  105 
  106 #ifdef BRIDGE
  107 #include <net/bridge.h>
  108 #endif
  109 
  110 #include "vlan.h"
  111 #if NVLAN > 0
  112 #include <net/if_vlan_var.h>
  113 #endif /* NVLAN > 0 */
  114 
  115 static  int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, 
  116                                     struct sockaddr *));
  117 u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  118 #define senderr(e) { error = (e); goto bad;}
  119 #define IFP2AC(IFP) ((struct arpcom *)IFP)
  120 
  121 #ifdef NETGRAPH
  122 #include <netgraph/ng_ether.h>
  123 #include <netgraph/ng_message.h>
  124 #include <netgraph/netgraph.h>
  125 
  126 static  void    ngether_init(void* ignored);
  127 static void     ngether_send(struct arpcom *ac,
  128                         struct ether_header *eh, struct mbuf *m);
  129 static  ng_constructor_t        ngether_constructor;
  130 static  ng_rcvmsg_t             ngether_rcvmsg;
  131 static  ng_shutdown_t           ngether_rmnode;
  132 static  ng_newhook_t            ngether_newhook;
  133 static  ng_connect_t            ngether_connect;
  134 static  ng_rcvdata_t            ngether_rcvdata;
  135 static  ng_disconnect_t         ngether_disconnect;
  136 
  137 static struct ng_type typestruct = {
  138         NG_VERSION,
  139         NG_ETHER_NODE_TYPE,
  140         NULL,
  141         ngether_constructor,
  142         ngether_rcvmsg,
  143         ngether_rmnode,
  144         ngether_newhook,
  145         NULL,
  146         ngether_connect,
  147         ngether_rcvdata,
  148         ngether_rcvdata,
  149         ngether_disconnect,
  150         NULL
  151 };
  152 
  153 #define AC2NG(AC) ((node_p)((AC)->ac_ng))
  154 #define NGEF_DIVERT NGF_TYPE1   /* all packets sent to netgraph */
  155 #endif /* NETGRAPH */
  156 
  157 /*
  158  * Ethernet output routine.
  159  * Encapsulate a packet of type family for the local net.
  160  * Use trailer local net encapsulation if enough data in first
  161  * packet leaves a multiple of 512 bytes of data in remainder.
  162  * Assumes that ifp is actually pointer to arpcom structure.
  163  */
  164 int
  165 ether_output(ifp, m0, dst, rt0)
  166         register struct ifnet *ifp;
  167         struct mbuf *m0;
  168         struct sockaddr *dst;
  169         struct rtentry *rt0;
  170 {
  171         short type;
  172         int s, error = 0;
  173         u_char edst[6];
  174         register struct mbuf *m = m0;
  175         register struct rtentry *rt;
  176         register struct ether_header *eh;
  177         int off, len = m->m_pkthdr.len, loop_copy = 0;
  178         int hlen;       /* link layer header lenght */
  179         struct arpcom *ac = (struct arpcom *)ifp;
  180 
  181         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  182                 senderr(ENETDOWN);
  183         rt = rt0;
  184         if (rt) {
  185                 if ((rt->rt_flags & RTF_UP) == 0) {
  186                         rt0 = rt = rtalloc1(dst, 1, 0UL);
  187                         if (rt0)
  188                                 rt->rt_refcnt--;
  189                         else
  190                                 senderr(EHOSTUNREACH);
  191                 }
  192                 if (rt->rt_flags & RTF_GATEWAY) {
  193                         if (rt->rt_gwroute == 0)
  194                                 goto lookup;
  195                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  196                                 rtfree(rt); rt = rt0;
  197                         lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
  198                                                           0UL);
  199                                 if ((rt = rt->rt_gwroute) == 0)
  200                                         senderr(EHOSTUNREACH);
  201                         }
  202                 }
  203                 if (rt->rt_flags & RTF_REJECT)
  204                         if (rt->rt_rmx.rmx_expire == 0 ||
  205                             time_second < rt->rt_rmx.rmx_expire)
  206                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  207         }
  208         hlen = ETHER_HDR_LEN;
  209         switch (dst->sa_family) {
  210 #ifdef INET
  211         case AF_INET:
  212                 if (!arpresolve(ac, rt, m, dst, edst, rt0))
  213                         return (0);     /* if not yet resolved */
  214                 off = m->m_pkthdr.len - m->m_len;
  215                 type = htons(ETHERTYPE_IP);
  216                 break;
  217 #endif
  218 #ifdef IPX
  219         case AF_IPX:
  220                 type = htons(ETHERTYPE_IPX);
  221                 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
  222                     (caddr_t)edst, sizeof (edst));
  223                 break;
  224 #endif
  225 #ifdef NETATALK
  226         case AF_APPLETALK:
  227           {
  228             struct at_ifaddr *aa;
  229 
  230             if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
  231                     goto bad;
  232             }
  233             if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
  234                     return (0);
  235             /*
  236              * In the phase 2 case, need to prepend an mbuf for the llc header.
  237              * Since we must preserve the value of m, which is passed to us by
  238              * value, we m_copy() the first mbuf, and use it for our llc header.
  239              */
  240             if ( aa->aa_flags & AFA_PHASE2 ) {
  241                 struct llc llc;
  242 
  243                 M_PREPEND(m, sizeof(struct llc), M_WAIT);
  244                 len += sizeof(struct llc);
  245                 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
  246                 llc.llc_control = LLC_UI;
  247                 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
  248                 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
  249                 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
  250                 type = htons(m->m_pkthdr.len);
  251                 hlen = sizeof(struct llc) + ETHER_HDR_LEN;
  252             } else {
  253                 type = htons(ETHERTYPE_AT);
  254             }
  255             break;
  256           }
  257 #endif NETATALK
  258 #ifdef NS
  259         case AF_NS:
  260                 switch(ns_nettype){
  261                 default:
  262                 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
  263                         type = 0x8137;
  264                         break;
  265                 case 0x0: /* Novell 802.3 */
  266                         type = htons( m->m_pkthdr.len);
  267                         break;
  268                 case 0xe0e0: /* Novell 802.2 and Token-Ring */
  269                         M_PREPEND(m, 3, M_WAIT);
  270                         type = htons( m->m_pkthdr.len);
  271                         cp = mtod(m, u_char *);
  272                         *cp++ = 0xE0;
  273                         *cp++ = 0xE0;
  274                         *cp++ = 0x03;
  275                         break;
  276                 }
  277                 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
  278                     (caddr_t)edst, sizeof (edst));
  279                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
  280                         m->m_pkthdr.rcvif = ifp;
  281                         schednetisr(NETISR_NS);
  282                         inq = &nsintrq;
  283                         s = splimp();
  284                         if (IF_QFULL(inq)) {
  285                                 IF_DROP(inq);
  286                                 m_freem(m);
  287                         } else
  288                                 IF_ENQUEUE(inq, m);
  289                         splx(s);
  290                         return (error);
  291                 }
  292                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
  293                         m2 = m_copy(m, 0, (int)M_COPYALL);
  294                         m2->m_pkthdr.rcvif = ifp;
  295                         schednetisr(NETISR_NS);
  296                         inq = &nsintrq;
  297                         s = splimp();
  298                         if (IF_QFULL(inq)) {
  299                                 IF_DROP(inq);
  300                                 m_freem(m2);
  301                         } else
  302                                 IF_ENQUEUE(inq, m2);
  303                         splx(s);
  304                 }
  305                 break;
  306 #endif /* NS */
  307 #ifdef  ISO
  308         case AF_ISO: {
  309                 int     snpalen;
  310                 struct  llc *l;
  311                 register struct sockaddr_dl *sdl;
  312 
  313                 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
  314                     sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
  315                         bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
  316                 } else if (error =
  317                             iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
  318                                             (char *)edst, &snpalen))
  319                         goto bad; /* Not Resolved */
  320                 /* If broadcasting on a simplex interface, loopback a copy */
  321                 if (*edst & 1)
  322                         m->m_flags |= (M_BCAST|M_MCAST);
  323                 M_PREPEND(m, 3, M_DONTWAIT);
  324                 if (m == NULL)
  325                         return (0);
  326                 type = htons(m->m_pkthdr.len);
  327                 l = mtod(m, struct llc *);
  328                 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
  329                 l->llc_control = LLC_UI;
  330                 len += 3;
  331                 IFDEBUG(D_ETHER)
  332                         int i;
  333                         printf("unoutput: sending pkt to: ");
  334                         for (i=0; i<6; i++)
  335                                 printf("%x ", edst[i] & 0xff);
  336                         printf("\n");
  337                 ENDDEBUG
  338                 } break;
  339 #endif /* ISO */
  340 #ifdef  LLC
  341 /*      case AF_NSAP: */
  342         case AF_CCITT: {
  343                 register struct sockaddr_dl *sdl =
  344                         (struct sockaddr_dl *) rt -> rt_gateway;
  345 
  346                 if (sdl && sdl->sdl_family == AF_LINK
  347                     && sdl->sdl_alen > 0) {
  348                         bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
  349                 } else goto bad; /* Not a link interface ? Funny ... */
  350                 if (*edst & 1)
  351                         loop_copy = 1;
  352                 type = htons(m->m_pkthdr.len);
  353 #ifdef LLC_DEBUG
  354                 {
  355                         int i;
  356                         register struct llc *l = mtod(m, struct llc *);
  357 
  358                         printf("ether_output: sending LLC2 pkt to: ");
  359                         for (i=0; i<6; i++)
  360                                 printf("%x ", edst[i] & 0xff);
  361                         printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
  362                                type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
  363                                l->llc_control & 0xff);
  364 
  365                 }
  366 #endif /* LLC_DEBUG */
  367                 } break;
  368 #endif /* LLC */
  369 
  370         case AF_UNSPEC:
  371                 loop_copy = -1; /* if this is for us, don't do it */
  372                 eh = (struct ether_header *)dst->sa_data;
  373                 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
  374                 type = eh->ether_type;
  375                 break;
  376 
  377         default:
  378                 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
  379                         dst->sa_family);
  380                 senderr(EAFNOSUPPORT);
  381         }
  382 
  383         /*
  384          * Add local net header.  If no space in first mbuf,
  385          * allocate another.
  386          */
  387         M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
  388         if (m == 0)
  389                 senderr(ENOBUFS);
  390         eh = mtod(m, struct ether_header *);
  391         (void)memcpy(&eh->ether_type, &type,
  392                 sizeof(eh->ether_type));
  393         (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
  394         (void)memcpy(eh->ether_shost, ac->ac_enaddr,
  395             sizeof(eh->ether_shost));
  396 
  397         /*
  398          * If a simplex interface, and the packet is being sent to our
  399          * Ethernet address or a broadcast address, loopback a copy.
  400          * XXX To make a simplex device behave exactly like a duplex
  401          * device, we should copy in the case of sending to our own
  402          * ethernet address (thus letting the original actually appear
  403          * on the wire). However, we don't do that here for security
  404          * reasons and compatibility with the original behavior.
  405          */
  406         if ((ifp->if_flags & IFF_SIMPLEX) &&
  407            (loop_copy != -1)) {
  408                 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
  409                         struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
  410 
  411                         (void) if_simloop(ifp, n, dst, hlen);
  412                 } else if (bcmp(eh->ether_dhost,
  413                     eh->ether_shost, ETHER_ADDR_LEN) == 0) {
  414                         (void) if_simloop(ifp, m, dst, hlen);
  415                         return (0);     /* XXX */
  416                 }
  417         }
  418 #ifdef BRIDGE
  419         if (do_bridge) {
  420                 struct mbuf *m0 = m ;
  421 
  422                 if (m->m_pkthdr.rcvif)
  423                         m->m_pkthdr.rcvif = NULL ;
  424                 ifp = bridge_dst_lookup(m);
  425                 bdg_forward(&m0, ifp);
  426                 if (m0)
  427                         m_freem(m0);
  428                 return (0);
  429         }
  430 #endif
  431         s = splimp();
  432         /*
  433          * Queue message on interface, and start output if interface
  434          * not yet active.
  435          */
  436         if (IF_QFULL(&ifp->if_snd)) {
  437                 IF_DROP(&ifp->if_snd);
  438                 splx(s);
  439                 senderr(ENOBUFS);
  440         }
  441         IF_ENQUEUE(&ifp->if_snd, m);
  442         if ((ifp->if_flags & IFF_OACTIVE) == 0)
  443                 (*ifp->if_start)(ifp);
  444         splx(s);
  445         ifp->if_obytes += len + sizeof (struct ether_header);
  446         if (m->m_flags & M_MCAST)
  447                 ifp->if_omcasts++;
  448         return (error);
  449 
  450 bad:
  451         if (m)
  452                 m_freem(m);
  453         return (error);
  454 }
  455 
  456 /*
  457  * Process a received Ethernet packet;
  458  * the packet is in the mbuf chain m without
  459  * the ether header, which is provided separately.
  460  */
  461 void
  462 ether_input(ifp, eh, m)
  463         struct ifnet *ifp;
  464         register struct ether_header *eh;
  465         struct mbuf *m;
  466 {
  467         register struct ifqueue *inq;
  468         u_short ether_type;
  469         int s;
  470 #if defined (ISO) || defined (LLC) || defined(NETATALK)
  471         register struct llc *l;
  472 #endif
  473 
  474         if ((ifp->if_flags & IFF_UP) == 0) {
  475                 m_freem(m);
  476                 return;
  477         }
  478         ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
  479         if (eh->ether_dhost[0] & 1) {
  480                 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
  481                          sizeof(etherbroadcastaddr)) == 0)
  482                         m->m_flags |= M_BCAST;
  483                 else
  484                         m->m_flags |= M_MCAST;
  485         }
  486         if (m->m_flags & (M_BCAST|M_MCAST))
  487                 ifp->if_imcasts++;
  488 
  489         ether_type = ntohs(eh->ether_type);
  490 
  491 #ifdef  NETGRAPH
  492         {
  493                 struct arpcom *ac = IFP2AC(ifp);
  494                 if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) {
  495                         ngether_send(ac, eh, m);
  496                         return;
  497                 }
  498         }
  499 #endif  /* NETGRAPH */
  500                 
  501 #if NVLAN > 0
  502         if (ether_type == vlan_proto) {
  503                 if (vlan_input(eh, m) < 0)
  504                         ifp->if_data.ifi_noproto++;
  505                 return;
  506         }
  507 #endif /* NVLAN > 0 */
  508 
  509         switch (ether_type) {
  510 #ifdef INET
  511         case ETHERTYPE_IP:
  512                 if (ipflow_fastforward(m))
  513                         return;
  514                 schednetisr(NETISR_IP);
  515                 inq = &ipintrq;
  516                 break;
  517 
  518         case ETHERTYPE_ARP:
  519                 schednetisr(NETISR_ARP);
  520                 inq = &arpintrq;
  521                 break;
  522 #endif
  523 #ifdef IPX
  524         case ETHERTYPE_IPX:
  525                 schednetisr(NETISR_IPX);
  526                 inq = &ipxintrq;
  527                 break;
  528 #endif
  529 #ifdef NS
  530         case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
  531                 schednetisr(NETISR_NS);
  532                 inq = &nsintrq;
  533                 break;
  534 
  535 #endif /* NS */
  536 #ifdef NETATALK
  537         case ETHERTYPE_AT:
  538                 schednetisr(NETISR_ATALK);
  539                 inq = &atintrq1;
  540                 break;
  541         case ETHERTYPE_AARP:
  542                 /* probably this should be done with a NETISR as well */
  543                 aarpinput((struct arpcom *)ifp, m); /* XXX */
  544                 return;
  545 #endif NETATALK
  546         default:
  547 #ifdef NS
  548                 checksum = mtod(m, ushort *);
  549                 /* Novell 802.3 */
  550                 if ((ether_type <= ETHERMTU) &&
  551                         ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
  552                         if(*checksum == 0xE0E0) {
  553                                 m->m_pkthdr.len -= 3;
  554                                 m->m_len -= 3;
  555                                 m->m_data += 3;
  556                         }
  557                                 schednetisr(NETISR_NS);
  558                                 inq = &nsintrq;
  559                                 break;
  560                 }
  561 #endif /* NS */
  562 #if defined (ISO) || defined (LLC) || defined(NETATALK)
  563                 if (ether_type > ETHERMTU)
  564                         goto dropanyway;
  565                 l = mtod(m, struct llc *);
  566                 switch (l->llc_dsap) {
  567 #ifdef NETATALK
  568                 case LLC_SNAP_LSAP:
  569                     switch (l->llc_control) {
  570                     case LLC_UI:
  571                         if (l->llc_ssap != LLC_SNAP_LSAP)
  572                             goto dropanyway;
  573         
  574                         if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
  575                                    sizeof(at_org_code)) == 0 &&
  576                              ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
  577                             inq = &atintrq2;
  578                             m_adj( m, sizeof( struct llc ));
  579                             schednetisr(NETISR_ATALK);
  580                             break;
  581                         }
  582 
  583                         if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
  584                                    sizeof(aarp_org_code)) == 0 &&
  585                              ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
  586                             m_adj( m, sizeof( struct llc ));
  587                             aarpinput((struct arpcom *)ifp, m); /* XXX */
  588                             return;
  589                         }
  590                 
  591                     default:
  592                         goto dropanyway;
  593                     }
  594                     break;
  595 #endif NETATALK 
  596 #ifdef  ISO
  597                 case LLC_ISO_LSAP:
  598                         switch (l->llc_control) {
  599                         case LLC_UI:
  600                                 /* LLC_UI_P forbidden in class 1 service */
  601                                 if ((l->llc_dsap == LLC_ISO_LSAP) &&
  602                                     (l->llc_ssap == LLC_ISO_LSAP)) {
  603                                         /* LSAP for ISO */
  604                                         if (m->m_pkthdr.len > ether_type)
  605                                                 m_adj(m, ether_type - m->m_pkthdr.len);
  606                                         m->m_data += 3;         /* XXX */
  607                                         m->m_len -= 3;          /* XXX */
  608                                         m->m_pkthdr.len -= 3;   /* XXX */
  609                                         M_PREPEND(m, sizeof *eh, M_DONTWAIT);
  610                                         if (m == 0)
  611                                                 return;
  612                                         *mtod(m, struct ether_header *) = *eh;
  613                                         IFDEBUG(D_ETHER)
  614                                                 printf("clnp packet");
  615                                         ENDDEBUG
  616                                         schednetisr(NETISR_ISO);
  617                                         inq = &clnlintrq;
  618                                         break;
  619                                 }
  620                                 goto dropanyway;
  621 
  622                         case LLC_XID:
  623                         case LLC_XID_P:
  624                                 if(m->m_len < 6)
  625                                         goto dropanyway;
  626                                 l->llc_window = 0;
  627                                 l->llc_fid = 9;
  628                                 l->llc_class = 1;
  629                                 l->llc_dsap = l->llc_ssap = 0;
  630                                 /* Fall through to */
  631                         case LLC_TEST:
  632                         case LLC_TEST_P:
  633                         {
  634                                 struct sockaddr sa;
  635                                 register struct ether_header *eh2;
  636                                 int i;
  637                                 u_char c = l->llc_dsap;
  638 
  639                                 l->llc_dsap = l->llc_ssap;
  640                                 l->llc_ssap = c;
  641                                 if (m->m_flags & (M_BCAST | M_MCAST))
  642                                         bcopy((caddr_t)ac->ac_enaddr,
  643                                               (caddr_t)eh->ether_dhost, 6);
  644                                 sa.sa_family = AF_UNSPEC;
  645                                 sa.sa_len = sizeof(sa);
  646                                 eh2 = (struct ether_header *)sa.sa_data;
  647                                 for (i = 0; i < 6; i++) {
  648                                         eh2->ether_shost[i] = c = eh->ether_dhost[i];
  649                                         eh2->ether_dhost[i] =
  650                                                 eh->ether_dhost[i] = eh->ether_shost[i];
  651                                         eh->ether_shost[i] = c;
  652                                 }
  653                                 ifp->if_output(ifp, m, &sa, NULL);
  654                                 return;
  655                         }
  656                         default:
  657                                 m_freem(m);
  658                                 return;
  659                         }
  660                         break;
  661 #endif /* ISO */
  662 #ifdef LLC
  663                 case LLC_X25_LSAP:
  664                 {
  665                         if (m->m_pkthdr.len > ether_type)
  666                                 m_adj(m, ether_type - m->m_pkthdr.len);
  667                         M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
  668                         if (m == 0)
  669                                 return;
  670                         if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
  671                                             eh->ether_dhost, LLC_X25_LSAP, 6,
  672                                             mtod(m, struct sdl_hdr *)))
  673                                 panic("ETHER cons addr failure");
  674                         mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
  675 #ifdef LLC_DEBUG
  676                                 printf("llc packet\n");
  677 #endif /* LLC_DEBUG */
  678                         schednetisr(NETISR_CCITT);
  679                         inq = &llcintrq;
  680                         break;
  681                 }
  682 #endif /* LLC */
  683                 dropanyway:
  684                 default:
  685 #ifdef  NETGRAPH
  686                         ngether_send(IFP2AC(ifp), eh, m);
  687 #else   /* NETGRAPH */
  688                         m_freem(m);
  689 #endif  /* NETGRAPH */
  690                         return;
  691                 }
  692 #else /* ISO || LLC || NETATALK */
  693 #ifdef  NETGRAPH
  694             ngether_send(IFP2AC(ifp), eh, m);
  695 #else   /* NETGRAPH */
  696             m_freem(m);
  697 #endif  /* NETGRAPH */
  698             return;
  699 #endif /* ISO || LLC || NETATALK */
  700         }
  701 
  702         s = splimp();
  703         if (IF_QFULL(inq)) {
  704                 IF_DROP(inq);
  705                 m_freem(m);
  706         } else
  707                 IF_ENQUEUE(inq, m);
  708         splx(s);
  709 }
  710 
  711 /*
  712  * Perform common duties while attaching to interface list
  713  */
  714 void
  715 ether_ifattach(ifp)
  716         register struct ifnet *ifp;
  717 {
  718         register struct ifaddr *ifa;
  719         register struct sockaddr_dl *sdl;
  720 
  721         ifp->if_type = IFT_ETHER;
  722         ifp->if_addrlen = 6;
  723         ifp->if_hdrlen = 14;
  724         ifp->if_mtu = ETHERMTU;
  725         ifp->if_resolvemulti = ether_resolvemulti;
  726         if (ifp->if_baudrate == 0)
  727             ifp->if_baudrate = 10000000;
  728         ifa = ifnet_addrs[ifp->if_index - 1];
  729         if (ifa == 0) {
  730                 printf("ether_ifattach: no lladdr!\n");
  731                 return;
  732         }
  733         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
  734         sdl->sdl_type = IFT_ETHER;
  735         sdl->sdl_alen = ifp->if_addrlen;
  736         bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
  737 #ifdef  NETGRAPH
  738         ngether_init(ifp);
  739 #endif  /* NETGRAPH */
  740 }
  741 
  742 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
  743 
  744 int
  745 ether_ioctl(ifp, command, data)
  746         struct ifnet *ifp;
  747         int command;
  748         caddr_t data;
  749 {
  750         struct ifaddr *ifa = (struct ifaddr *) data;
  751         struct ifreq *ifr = (struct ifreq *) data;
  752         int error = 0;
  753 
  754         switch (command) {
  755         case SIOCSIFADDR:
  756                 ifp->if_flags |= IFF_UP;
  757 
  758                 switch (ifa->ifa_addr->sa_family) {
  759 #ifdef INET
  760                 case AF_INET:
  761                         ifp->if_init(ifp->if_softc);    /* before arpwhohas */
  762                         arp_ifinit((struct arpcom *)ifp, ifa);
  763                         break;
  764 #endif
  765 #ifdef IPX
  766                 /*
  767                  * XXX - This code is probably wrong
  768                  */
  769                 case AF_IPX:
  770                         {
  771                         register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
  772                         struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
  773 
  774                         if (ipx_nullhost(*ina))
  775                                 ina->x_host =
  776                                     *(union ipx_host *) 
  777                                     ac->ac_enaddr;
  778                         else {
  779                                 bcopy((caddr_t) ina->x_host.c_host,
  780                                       (caddr_t) ac->ac_enaddr,
  781                                       sizeof(ac->ac_enaddr));
  782                         }
  783 
  784                         /*
  785                          * Set new address
  786                          */
  787                         ifp->if_init(ifp->if_softc);
  788                         break;
  789                         }
  790 #endif
  791 #ifdef NS
  792                 /*
  793                  * XXX - This code is probably wrong
  794                  */
  795                 case AF_NS:
  796                 {
  797                         register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
  798                         struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
  799 
  800                         if (ns_nullhost(*ina))
  801                                 ina->x_host =
  802                                     *(union ns_host *) (ac->ac_enaddr);
  803                         else {
  804                                 bcopy((caddr_t) ina->x_host.c_host,
  805                                       (caddr_t) ac->ac_enaddr,
  806                                       sizeof(ac->ac_enaddr));
  807                         }
  808 
  809                         /*
  810                          * Set new address
  811                          */
  812                         ifp->if_init(ifp->if_softc);
  813                         break;
  814                 }
  815 #endif
  816                 default:
  817                         ifp->if_init(ifp->if_softc);
  818                         break;
  819                 }
  820                 break;
  821 
  822         case SIOCGIFADDR:
  823                 {
  824                         struct sockaddr *sa;
  825 
  826                         sa = (struct sockaddr *) & ifr->ifr_data;
  827                         bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
  828                               (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
  829                 }
  830                 break;
  831 
  832         case SIOCSIFMTU:
  833                 /*
  834                  * Set the interface MTU.
  835                  */
  836                 if (ifr->ifr_mtu > ETHERMTU) {
  837                         error = EINVAL;
  838                 } else {
  839                         ifp->if_mtu = ifr->ifr_mtu;
  840                 }
  841                 break;
  842         }
  843         return (error);
  844 }
  845 
  846 int
  847 ether_resolvemulti(ifp, llsa, sa)
  848         struct ifnet *ifp;
  849         struct sockaddr **llsa;
  850         struct sockaddr *sa;
  851 {
  852         struct sockaddr_dl *sdl;
  853         struct sockaddr_in *sin;
  854         u_char *e_addr;
  855 
  856         switch(sa->sa_family) {
  857         case AF_LINK:
  858                 /* 
  859                  * No mapping needed. Just check that it's a valid MC address.
  860                  */
  861                 sdl = (struct sockaddr_dl *)sa;
  862                 e_addr = LLADDR(sdl);
  863                 if ((e_addr[0] & 1) != 1)
  864                         return EADDRNOTAVAIL;
  865                 *llsa = 0;
  866                 return 0;
  867 
  868 #ifdef INET
  869         case AF_INET:
  870                 sin = (struct sockaddr_in *)sa;
  871                 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
  872                         return EADDRNOTAVAIL;
  873                 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
  874                        M_WAITOK);
  875                 sdl->sdl_len = sizeof *sdl;
  876                 sdl->sdl_family = AF_LINK;
  877                 sdl->sdl_index = ifp->if_index;
  878                 sdl->sdl_type = IFT_ETHER;
  879                 sdl->sdl_nlen = 0;
  880                 sdl->sdl_alen = ETHER_ADDR_LEN;
  881                 sdl->sdl_slen = 0;
  882                 e_addr = LLADDR(sdl);
  883                 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
  884                 *llsa = (struct sockaddr *)sdl;
  885                 return 0;
  886 #endif
  887 
  888         default:
  889                 /* 
  890                  * Well, the text isn't quite right, but it's the name
  891                  * that counts...
  892                  */
  893                 return EAFNOSUPPORT;
  894         }
  895 }
  896 
  897 #ifdef  NETGRAPH
  898 
  899 /***********************************************************************
  900  * This section contains the methods for the Netgraph interface
  901  ***********************************************************************/
  902 /* It's Ascii-art time!
  903  * The ifnet is the first part of the arpcom which must be
  904  * the first part of the device's softc.. yuk.
  905  *
  906  *      +--------------------------+-----+---------+
  907  *      |   struct ifnet (*ifp)    |     |         |
  908  *      |                          |     |         |
  909  *      +--------------------------+     |         |
  910  *   +--|[ac_ng]     struct arpcom (*ac) |         |
  911  *   |  +--------------------------------+         |
  912  *   |  |   struct softc (*ifp->if_softc) (device) |
  913  *   |  +------------------------------------------+
  914  *   |               ^
  915  * AC2NG()           |
  916  *   |               v
  917  *   |       +----------------------+
  918  *   |       |   [private] [flags]  |
  919  *   +------>| struct ng_node       |
  920  *           |    [hooks]           | ** we only allow one hook
  921  *           +----------------------+
  922  *                   ^
  923  *                   |
  924  *                   v
  925  *           +-------------+
  926  *           |    [node]   |
  927  *           |    hook     |
  928  *           |    [private]|-- *unused*
  929  *           +-------------+
  930  */
  931 
  932 /*
  933  * called during interface attaching
  934  */
  935 static void
  936 ngether_init(void *ifpvoid)
  937 {
  938         struct  ifnet *ifp = ifpvoid;
  939         struct arpcom *ac = IFP2AC(ifp);
  940         static int      ngether_done_init;
  941         char    namebuf[32];
  942         node_p node;
  943 
  944         /*
  945          * we have found a node, make sure our 'type' is availabe.
  946          */
  947         if (ngether_done_init == 0) {
  948                 if (ng_newtype(&typestruct)) {
  949                         printf("ngether install failed\n");
  950                         return;
  951                 }
  952                 ngether_done_init = 1;
  953         }
  954         if (ng_make_node_common(&typestruct, &node) != 0)
  955                 return;
  956         ac->ac_ng = node;
  957         node->private = ifp;
  958         sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit);
  959         ng_name_node(AC2NG(ac), namebuf);
  960 }
  961 
  962 /*
  963  * It is not possible or allowable to create a node of this type.
  964  * If the hardware exists, it will already have created it.
  965  */
  966 static  int
  967 ngether_constructor(node_p *nodep)
  968 {
  969         return (EINVAL);
  970 }
  971 
  972 /*
  973  * Give our ok for a hook to be added...
  974  *
  975  * Allow one hook at a time (rawdata).
  976  * It can eiteh rdivert everything or only unclaimed packets.
  977  */
  978 static  int
  979 ngether_newhook(node_p node, hook_p hook, const char *name)
  980 {
  981 
  982         /* check if there is already a hook */
  983         if (LIST_FIRST(&(node->hooks)))
  984                 return(EISCONN);
  985         /*
  986          * Check for which mode hook we want.
  987          */
  988         if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) {
  989                 if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) {
  990                         return (EINVAL);
  991                 }
  992                 node->flags |= NGEF_DIVERT;
  993         } else {
  994                 node->flags &= ~NGEF_DIVERT;
  995         }
  996         return (0);
  997 }
  998 
  999 /*
 1000  * incoming messages.
 1001  * Just respond to the generic TEXT_STATUS message
 1002  */
 1003 static  int
 1004 ngether_rcvmsg(node_p node,
 1005         struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
 1006 {
 1007         struct ifnet    *ifp;
 1008         int error = 0;
 1009 
 1010         ifp = node->private;
 1011         switch (msg->header.typecookie) {
 1012             case        NGM_ETHER_COOKIE:
 1013                 error = EINVAL;
 1014                 break;
 1015             case        NGM_GENERIC_COOKIE:
 1016                 switch(msg->header.cmd) {
 1017                     case NGM_TEXT_STATUS: {
 1018                             char        *arg;
 1019                             int pos = 0;
 1020                             int resplen = sizeof(struct ng_mesg) + 512;
 1021                             MALLOC(*resp, struct ng_mesg *, resplen,
 1022                                         M_NETGRAPH, M_NOWAIT);
 1023                             if (*resp == NULL) {
 1024                                 error = ENOMEM;
 1025                                 break;
 1026                             }
 1027                             bzero(*resp, resplen);
 1028                             arg = (*resp)->data;
 1029 
 1030                             /*
 1031                              * Put in the throughput information.
 1032                              */
 1033                             pos = sprintf(arg, "%ld bytes in, %ld bytes out\n",
 1034                             ifp->if_ibytes, ifp->if_obytes);
 1035                             pos += sprintf(arg + pos,
 1036                                 "%ld output errors\n",
 1037                                 ifp->if_oerrors);
 1038                             pos += sprintf(arg + pos,
 1039                                 "ierrors = %ld\n",
 1040                                 ifp->if_ierrors);
 1041 
 1042                             (*resp)->header.version = NG_VERSION;
 1043                             (*resp)->header.arglen = strlen(arg) + 1;
 1044                             (*resp)->header.token = msg->header.token;
 1045                             (*resp)->header.typecookie = NGM_ETHER_COOKIE;
 1046                             (*resp)->header.cmd = msg->header.cmd;
 1047                             strncpy((*resp)->header.cmdstr, "status",
 1048                                         NG_CMDSTRLEN);
 1049                         }
 1050                         break;
 1051                     default:
 1052                         error = EINVAL;
 1053                         break;
 1054                     }
 1055                 break;
 1056             default:
 1057                 error = EINVAL;
 1058                 break;
 1059         }
 1060         free(msg, M_NETGRAPH);
 1061         return (error);
 1062 }
 1063 
 1064 /*
 1065  * Receive a completed ethernet packet.
 1066  * Queue it for output.
 1067  */
 1068 static  int
 1069 ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
 1070 {
 1071         struct ifnet *ifp;
 1072         int     error = 0;
 1073         int     s;
 1074         struct ether_header *eh;
 1075         
 1076         ifp = hook->node->private;
 1077 
 1078         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 1079                 senderr(ENETDOWN);
 1080         /* drop in the MAC address */
 1081         eh = mtod(m, struct ether_header *);
 1082         bcopy(IFP2AC(ifp)->ac_enaddr, eh->ether_shost, 6);
 1083         /*
 1084          * If a simplex interface, and the packet is being sent to our
 1085          * Ethernet address or a broadcast address, loopback a copy.
 1086          * XXX To make a simplex device behave exactly like a duplex
 1087          * device, we should copy in the case of sending to our own
 1088          * ethernet address (thus letting the original actually appear
 1089          * on the wire). However, we don't do that here for security
 1090          * reasons and compatibility with the original behavior.
 1091          */
 1092         if (ifp->if_flags & IFF_SIMPLEX) {
 1093                 if (m->m_flags & M_BCAST) {
 1094                         struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
 1095 
 1096                         ng_queue_data(hook, n, meta);
 1097                 } else if (bcmp(eh->ether_dhost,
 1098                     eh->ether_shost, ETHER_ADDR_LEN) == 0) {
 1099                         ng_queue_data(hook, m, meta);
 1100                         return (0);     /* XXX */
 1101                 }
 1102         }
 1103         s = splimp();
 1104         /*
 1105          * Queue message on interface, and start output if interface
 1106          * not yet active.
 1107          * XXX if we lookead at the priority in the meta data we could
 1108          * queue high priority items at the head.
 1109          */
 1110         if (IF_QFULL(&ifp->if_snd)) {
 1111                 IF_DROP(&ifp->if_snd);
 1112                 splx(s);
 1113                 senderr(ENOBUFS);
 1114         }
 1115         IF_ENQUEUE(&ifp->if_snd, m);
 1116         if ((ifp->if_flags & IFF_OACTIVE) == 0)
 1117                 (*ifp->if_start)(ifp);
 1118         splx(s);
 1119         ifp->if_obytes += m->m_pkthdr.len;
 1120         if (m->m_flags & M_MCAST)
 1121                 ifp->if_omcasts++;
 1122         return (error);
 1123 
 1124 bad:
 1125         NG_FREE_DATA(m, meta);
 1126         return (error);
 1127 }
 1128 
 1129 /*
 1130  * pass an mbuf out to the connected hook
 1131  * More complicated than just an m_prepend, as it tries to save later nodes
 1132  * from needing to do lots of m_pullups.
 1133  */     
 1134 static void
 1135 ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
 1136 {
 1137         int room;
 1138         node_p node = AC2NG(ac);
 1139         struct ether_header *eh2;
 1140                 
 1141         if (node && LIST_FIRST(&(node->hooks))) {
 1142                 /*
 1143                  * Possibly the header is already on the front,
 1144                  */
 1145                 eh2 = mtod(m, struct ether_header *) - 1;
 1146                 if ( eh == eh2) {
 1147                         /*
 1148                          * This is the case so just move the markers back to
 1149                          * re-include it. We lucked out.
 1150                          * This allows us to avoid a yucky m_pullup
 1151                          * in later nodes if it works.
 1152                          */
 1153                         m->m_len += sizeof(*eh);
 1154                         m->m_data -= sizeof(*eh);
 1155                         m->m_pkthdr.len += sizeof(*eh);
 1156                 } else {
 1157                         /*
 1158                          * Alternatively there may be room even though
 1159                          * it is stored somewhere else. If so, copy it in.
 1160                          * This only safe because we KNOW that this packet has
 1161                          * just been generated by an ethernet card, so there
 1162                          * are no aliases to the buffer. (unlike in outgoing
 1163                          * packets).
 1164                          * Nearly all ethernet cards will end up producing mbufs
 1165                          * that fall into these cases. So we are not optimising
 1166                          * contorted cases.
 1167                          */
 1168         
 1169                         if (m->m_flags & M_EXT) {
 1170                                 room = (mtod(m, caddr_t) - m->m_ext.ext_buf);
 1171                                 if (room > m->m_ext.ext_size) /* garbage */
 1172                                         room = 0; /* fail immediatly */
 1173                         } else {
 1174                                 room = (mtod(m, caddr_t) - m->m_pktdat);
 1175                         }
 1176                         if (room > sizeof (*eh)) {
 1177                                 /* we have room, just copy it and adjust */
 1178                                 m->m_len += sizeof(*eh);
 1179                                 m->m_data -= sizeof(*eh);
 1180                                 m->m_pkthdr.len += sizeof(*eh);
 1181                         } else {
 1182                                 /*
 1183                                  * Doing anything more is likely to get more
 1184                                  * expensive than it's worth..
 1185                                  * it's probable that everything else is in one
 1186                                  * big lump. The next node will do an m_pullup()
 1187                                  * for exactly the amount of data it needs and
 1188                                  * hopefully everything after that will not
 1189                                  * need one. So let's just use M_PREPEND.
 1190                                  */
 1191                                 M_PREPEND(m, sizeof (*eh), M_DONTWAIT);
 1192                                 if (m == NULL)
 1193                                         return;
 1194                         }
 1195                         bcopy ((caddr_t)eh, mtod(m, struct ether_header *),
 1196                             sizeof(*eh));
 1197                 }
 1198                 ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL);
 1199         } else {
 1200                 m_freem(m);
 1201         }
 1202 }
 1203 
 1204 /*
 1205  * do local shutdown processing..
 1206  * This node will refuse to go away, unless the hardware says to..
 1207  * don't unref the node, or remove our name. just clear our links up.
 1208  */
 1209 static  int
 1210 ngether_rmnode(node_p node)
 1211 {
 1212         ng_cutlinks(node);
 1213         node->flags &= ~NG_INVALID; /* bounce back to life */
 1214         return (0);
 1215 }
 1216 
 1217 /* already linked */
 1218 static  int
 1219 ngether_connect(hook_p hook)
 1220 {
 1221         /* be really amiable and just say "YUP that's OK by me! " */
 1222         return (0);
 1223 }
 1224 
 1225 /*
 1226  * notify on hook disconnection (destruction)
 1227  *
 1228  * For this type, removal of the last lins no effect. The interface can run
 1229  * independently.
 1230  * Since we have no per-hook information, this is rather simple.
 1231  */
 1232 static  int
 1233 ngether_disconnect(hook_p hook)
 1234 {
 1235         hook->node->flags &= ~NGEF_DIVERT;
 1236         return (0);
 1237 }
 1238 #endif /* NETGRAPH */
 1239 
 1240 /********************************** END *************************************/

Cache object: 7501c7e3460fa79ec881b9a932f1bbd4


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