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/ether_at_pr_module.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 /*
   26  * Copyright (c) 1982, 1989, 1993
   27  *      The Regents of the University of California.  All rights reserved.
   28  *
   29  * Redistribution and use in source and binary forms, with or without
   30  * modification, are permitted provided that the following conditions
   31  * are met:
   32  * 1. Redistributions of source code must retain the above copyright
   33  *    notice, this list of conditions and the following disclaimer.
   34  * 2. Redistributions in binary form must reproduce the above copyright
   35  *    notice, this list of conditions and the following disclaimer in the
   36  *    documentation and/or other materials provided with the distribution.
   37  * 3. All advertising materials mentioning features or use of this software
   38  *    must display the following acknowledgement:
   39  *      This product includes software developed by the University of
   40  *      California, Berkeley and its contributors.
   41  * 4. Neither the name of the University nor the names of its contributors
   42  *    may be used to endorse or promote products derived from this software
   43  *    without specific prior written permission.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   55  * SUCH DAMAGE.
   56  *
   57  */
   58 
   59 
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/kernel.h>
   64 #include <sys/malloc.h>
   65 #include <sys/mbuf.h>
   66 #include <sys/socket.h>
   67 #include <sys/sockio.h>
   68 #include <sys/sysctl.h>
   69 
   70 #include <net/if.h>
   71 #include <net/netisr.h>
   72 #include <net/route.h>
   73 #include <net/if_llc.h>
   74 #include <net/if_dl.h>
   75 #include <net/if_types.h>
   76 #include <netinet/if_ether.h>
   77 
   78 #include <sys/socketvar.h>
   79 
   80 #include <net/dlil.h>
   81 #include <netat/at_pat.h>
   82 #if NETAT
   83 extern struct ifqueue atalkintrq;
   84 #endif
   85 
   86 
   87 #if BRIDGE
   88 #include <net/bridge.h>
   89 #endif
   90 
   91 /* #include "vlan.h" */
   92 #if NVLAN > 0
   93 #include <net/if_vlan_var.h>
   94 #endif /* NVLAN > 0 */
   95 
   96 static
   97 u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
   98 
   99 #define IFP2AC(IFP) ((struct arpcom *)IFP)
  100 
  101 
  102 struct dl_es_at_entry 
  103 {
  104      struct ifnet *ifp;
  105      u_long       dl_tag;
  106      int    ref_count;
  107 };
  108 
  109 
  110 /*
  111  * Temp static for protocol registration XXX
  112  */
  113 
  114 #define MAX_EN_COUNT 30
  115 
  116 static struct dl_es_at_entry en_at_array[MAX_EN_COUNT];
  117 
  118 /*
  119  * Process a received Ethernet packet;
  120  * the packet is in the mbuf chain m without
  121  * the ether header, which is provided separately.
  122  */
  123 int
  124 at_ether_input(m, frame_header, ifp, dl_tag, sync_ok)
  125     struct mbuf  *m;
  126     char         *frame_header;
  127     struct ifnet *ifp;
  128     u_long           dl_tag;
  129     int          sync_ok;
  130 
  131 {
  132     register struct ether_header *eh = (struct ether_header *) frame_header;
  133     register struct ifqueue *inq=0;
  134     u_short ether_type;
  135     int s;
  136     u_int16_t ptype = -1;
  137     unsigned char buf[18];
  138 
  139 #if NETAT
  140     register struct llc *l;
  141 #endif
  142 
  143     if ((ifp->if_flags & IFF_UP) == 0) {
  144         m_freem(m);
  145         return EJUSTRETURN;
  146     }
  147 
  148     ifp->if_lastchange = time;
  149 
  150     if (eh->ether_dhost[0] & 1) {
  151         if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
  152                  sizeof(etherbroadcastaddr)) == 0)
  153             m->m_flags |= M_BCAST;
  154         else
  155             m->m_flags |= M_MCAST;
  156     }
  157     if (m->m_flags & (M_BCAST|M_MCAST))
  158         ifp->if_imcasts++;
  159 
  160     ether_type = ntohs(eh->ether_type);
  161 
  162 #if NVLAN > 0
  163         if (ether_type == vlan_proto) {
  164                 if (vlan_input(eh, m) < 0)
  165                         ifp->if_data.ifi_noproto++;
  166                 return EJUSTRETURN;
  167         }
  168 #endif /* NVLAN > 0 */
  169 
  170         if (ether_type > ETHERMTU)
  171              return ENOENT;
  172 
  173 #if NETAT
  174         l = mtod(m, struct llc *);
  175 
  176         switch (l->llc_dsap) {
  177         case LLC_SNAP_LSAP:
  178 
  179              /* Temporary hack: check for AppleTalk and AARP packets */
  180              /* WARNING we're checking only on the "ether_type" (the 2 bytes
  181               * of the SNAP header. This shouldn't be a big deal, 
  182               * AppleTalk pat_input is making sure we have the right packets
  183               * because it needs to discrimante AARP from EtherTalk packets.
  184               */
  185 
  186              if (l->llc_ssap == LLC_SNAP_LSAP &&
  187                  l->llc_un.type_snap.control == 0x03) {
  188 
  189 #ifdef APPLETALK_DEBUG
  190                   printf("new_ether_input: SNAP Cntrol type=0x%x Src=%s\n",
  191                          l->llc_un.type_snap.ether_type,
  192                          ether_sprintf(buf, &eh->ether_shost));
  193                   printf("                                     Dst=%s\n",
  194                          ether_sprintf(buf, &eh->ether_dhost));
  195 #endif /* APPLETALK_DEBUG */
  196 
  197                   if ((l->llc_un.type_snap.ether_type == 0x809B) ||
  198                       (l->llc_un.type_snap.ether_type == 0x80F3)) {
  199 
  200 
  201                        /*
  202                         * note: for AppleTalk we need to pass the enet header of the
  203                         * packet up stack. To do so, we made sure in that the FULL packet
  204                         * is copied in the mbuf by the mace driver, and only the m_data and
  205                         * length have been shifted to make IP and the other guys happy.
  206                         */
  207 
  208                        m->m_data -= sizeof(*eh);
  209                        m->m_len += sizeof(*eh);
  210                        m->m_pkthdr.len += sizeof(*eh);  
  211 #ifdef APPLETALK_DEBUG
  212                        l == (struct llc *)(eh+1);
  213                        if (l->llc_un.type_snap.ether_type == 0x80F3) {
  214                             kprintf("new_ether_input: RCV AppleTalk type=0x%x Src=%s\n",
  215                                     l->llc_un.type_snap.ether_type,
  216                                     ether_sprintf(buf, &eh->ether_shost));
  217                             kprintf("                                     Dst=%s\n",
  218                                     ether_sprintf(buf, &eh->ether_dhost));
  219                        }
  220 #endif /* APPLETALK_DEBUG */
  221                        schednetisr(NETISR_APPLETALK);
  222                        inq = &atalkintrq ;
  223                     
  224                        break;
  225                   }
  226              }
  227             
  228              break;
  229             
  230             
  231         default:
  232              return ENOENT;
  233         }
  234 
  235 
  236         if (inq == 0)
  237              return ENOENT;
  238 
  239         s = splimp();
  240         if (IF_QFULL(inq)) {
  241                 IF_DROP(inq);
  242                 m_freem(m);
  243                 splx(s);
  244                 return EJUSTRETURN;
  245         } else
  246                 IF_ENQUEUE(inq, m);
  247         splx(s);
  248         return 0;
  249 #else
  250         return ENOENT;
  251 #endif  /* NETAT */
  252 }
  253 
  254 
  255 
  256 int
  257 ether_pre_output(ifp, m0, dst_netaddr, route, type, edst, dl_tag )
  258     struct ifnet    *ifp;
  259     struct mbuf     **m0;
  260     struct sockaddr *dst_netaddr;
  261     caddr_t         route;
  262     char            *type;
  263     char            *edst;
  264     u_long          dl_tag;
  265 {
  266     int s;
  267     register struct mbuf *m = *m0;
  268     register struct rtentry *rt;
  269     register struct ether_header *eh;
  270     int off, len = m->m_pkthdr.len;
  271     int hlen;   /* link layer header lenght */
  272     struct arpcom *ac = IFP2AC(ifp);
  273 
  274 
  275 
  276     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 
  277         return ENETDOWN;
  278 
  279     hlen = ETHER_HDR_LEN;
  280 
  281     /*
  282      * Tell ether_frameout it's ok to loop packet unless negated below.
  283      */
  284     m->m_flags |= M_LOOP;
  285 
  286     switch (dst_netaddr->sa_family) {
  287     case AF_UNSPEC:
  288         m->m_flags &= ~M_LOOP;
  289         eh = (struct ether_header *)dst_netaddr->sa_data;
  290         (void)memcpy(edst, eh->ether_dhost, 6);
  291         *(u_short *)type = eh->ether_type;
  292         break;
  293         
  294 
  295     case AF_APPLETALK:
  296     {
  297         eh = (struct ether_header *)dst_netaddr->sa_data;
  298         bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, 6);
  299                 
  300         *(u_short *)type = m->m_pkthdr.len;
  301     }
  302     break;
  303 
  304 
  305     default:
  306         kprintf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
  307                dst_netaddr->sa_family);
  308 
  309         return EAFNOSUPPORT;
  310     }
  311 
  312     return (0);
  313 }
  314 
  315 
  316 
  317 
  318 
  319 int
  320 ether_prmod_ioctl(dl_tag, ifp, command, data)
  321     u_long       dl_tag;
  322     struct ifnet *ifp;
  323     int          command;
  324     caddr_t      data;
  325 {
  326     struct ifaddr *ifa = (struct ifaddr *) data;
  327     struct ifreq *ifr = (struct ifreq *) data;
  328     int error = 0;
  329     boolean_t funnel_state;
  330     struct arpcom *ac = (struct arpcom *) ifp;
  331     struct sockaddr_dl *sdl;
  332     struct sockaddr_in *sin;
  333     u_char *e_addr;
  334 
  335 
  336     funnel_state = thread_funnel_set(network_flock, TRUE);
  337 
  338     switch (command) {
  339 
  340     case SIOCSIFADDR:
  341          if ((ifp->if_flags & IFF_RUNNING) == 0) {
  342               ifp->if_flags |= IFF_UP;
  343               dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
  344          }
  345 
  346         break;
  347 
  348     case SIOCGIFADDR:
  349     {
  350         struct sockaddr *sa;
  351 
  352         sa = (struct sockaddr *) & ifr->ifr_data;
  353         bcopy(IFP2AC(ifp)->ac_enaddr,
  354               (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
  355     }
  356     break;
  357 
  358     case SIOCSIFMTU:
  359         /*
  360          * Set the interface MTU.
  361          */
  362         if (ifr->ifr_mtu > ETHERMTU) {
  363             error = EINVAL;
  364         } else {
  365             ifp->if_mtu = ifr->ifr_mtu;
  366         }
  367         break;
  368 
  369     default:
  370          return EOPNOTSUPP;
  371     }
  372 
  373     (void) thread_funnel_set(network_flock, funnel_state);
  374 
  375     return (error);
  376 }
  377 
  378 
  379 
  380 void
  381 ether_attach_at(struct ifnet *ifp, u_long *at_dl_tag, u_long *aarp_dl_tag)
  382 {
  383     struct dlil_proto_reg_str   reg;
  384     struct dlil_demux_desc      desc;
  385     struct dlil_demux_desc      desc2;
  386     u_short native = 0;           /* 802.2 frames use a length here */
  387     int   stat;
  388     int   first_empty;
  389     int   i;
  390 
  391 
  392     first_empty = MAX_EN_COUNT;
  393     for (i=0; i < MAX_EN_COUNT; i++) {
  394          if (en_at_array[i].ifp == 0)
  395               first_empty = i;
  396 
  397          if (en_at_array[i].ifp == ifp) {
  398               en_at_array[i].ref_count++;
  399               *at_dl_tag = *aarp_dl_tag = en_at_array[i].dl_tag;
  400               return;
  401         }
  402     }
  403     
  404     if (first_empty == MAX_EN_COUNT)
  405          return;
  406 
  407     TAILQ_INIT(&reg.demux_desc_head);
  408     desc.type = DLIL_DESC_802_2_SNAP;
  409     desc.variants.desc_802_2_SNAP.dsap = LLC_SNAP_LSAP;
  410     desc.variants.desc_802_2_SNAP.ssap = LLC_SNAP_LSAP;
  411     desc.variants.desc_802_2_SNAP.control_code = 0x03;
  412     desc.variants.desc_802_2_SNAP.org[0] = 0x08;
  413     desc.variants.desc_802_2_SNAP.org[1] = 0x00;
  414     desc.variants.desc_802_2_SNAP.org[2] = 0x07;
  415     desc.variants.desc_802_2_SNAP.protocol_type = 0x809B;
  416     desc.native_type = NULL;
  417     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
  418     reg.interface_family = ifp->if_family;
  419     reg.unit_number      = ifp->if_unit;
  420     reg.input            = at_ether_input;
  421     reg.pre_output       = ether_pre_output;
  422     reg.event            = 0;
  423     reg.offer            = 0;
  424     reg.ioctl            = ether_prmod_ioctl;
  425     reg.default_proto    = 0;
  426     reg.protocol_family  = PF_APPLETALK;
  427 
  428     desc2 = desc;
  429     desc2.variants.desc_802_2_SNAP.protocol_type = 0x80F3;
  430     desc2.variants.desc_802_2_SNAP.org[0] = 0;
  431     desc2.variants.desc_802_2_SNAP.org[1] = 0;
  432     desc2.variants.desc_802_2_SNAP.org[2] = 0;
  433 
  434     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc2, next); 
  435 
  436     stat = dlil_attach_protocol(&reg, at_dl_tag);
  437     if (stat) {
  438         printf("WARNING: ether_attach_at can't attach at to interface\n");
  439         return;
  440     }
  441 
  442     *aarp_dl_tag = *at_dl_tag;
  443 
  444     en_at_array[first_empty].ifp = ifp;
  445     en_at_array[first_empty].dl_tag = *at_dl_tag;
  446     en_at_array[first_empty].ref_count = 1;
  447 
  448 } /* ether_attach_at */
  449 
  450 
  451 void
  452 ether_detach_at(struct ifnet *ifp)
  453 {
  454      int i;
  455      
  456      for (i=0; i < MAX_EN_COUNT; i++) {
  457           if (en_at_array[i].ifp == ifp)
  458                break;
  459      }
  460 
  461      if (i < MAX_EN_COUNT) {
  462           if (en_at_array[i].ref_count > 1) 
  463                en_at_array[i].ref_count--;
  464           else {
  465                if (en_at_array[i].ref_count == 1) {
  466                     dlil_detach_protocol(en_at_array[i].dl_tag);
  467                     en_at_array[i].ifp = 0;
  468                }
  469           }
  470      }
  471 }

Cache object: 6cd024670dee1b55dd2ebcc7c18df190


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