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_tokensubr.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 /*      $NetBSD: if_tokensubr.c,v 1.25 2004/03/22 18:02:12 matt Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1982, 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
   32  */
   33 
   34 /*
   35  * Copyright (c) 1997-1999
   36  *      Onno van der Linden
   37  * Copyright (c) 1995
   38  *      Matt Thomas.  All rights reserved.
   39  *
   40  * Redistribution and use in source and binary forms, with or without
   41  * modification, are permitted provided that the following conditions
   42  * are met:
   43  * 1. Redistributions of source code must retain the above copyright
   44  *    notice, this list of conditions and the following disclaimer.
   45  * 2. Redistributions in binary form must reproduce the above copyright
   46  *    notice, this list of conditions and the following disclaimer in the
   47  *    documentation and/or other materials provided with the distribution.
   48  * 3. The names of its contributors may not be used to endorse or promote
   49  *    products derived from this software without specific prior written
   50  *    permission.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   62  * SUCH DAMAGE.
   63  *
   64  *      from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __KERNEL_RCSID(0, "$NetBSD: if_tokensubr.c,v 1.25 2004/03/22 18:02:12 matt Exp $");
   69 
   70 #include "opt_inet.h"
   71 #include "opt_atalk.h"
   72 #include "opt_ccitt.h"
   73 #include "opt_llc.h"
   74 #include "opt_iso.h"
   75 #include "opt_ns.h"
   76 #include "opt_gateway.h"
   77 
   78 #include "bpfilter.h"
   79 
   80 #include <sys/param.h>
   81 #include <sys/systm.h>
   82 #include <sys/kernel.h>
   83 #include <sys/malloc.h>
   84 #include <sys/mbuf.h>
   85 #include <sys/protosw.h>
   86 #include <sys/socket.h>
   87 #include <sys/ioctl.h>
   88 #include <sys/errno.h>
   89 #include <sys/syslog.h>
   90 
   91 #include <machine/cpu.h>
   92 
   93 #include <net/if.h>
   94 #include <net/netisr.h>
   95 #include <net/route.h>
   96 #include <net/if_llc.h>
   97 #include <net/if_dl.h>
   98 #include <net/if_types.h>
   99 
  100 #if NBPFILTER > 0
  101 #include <net/bpf.h>
  102 #endif
  103 
  104 #include <net/if_ether.h>
  105 #include <net/if_token.h>
  106 
  107 #ifdef INET
  108 #include <netinet/in.h>
  109 #include <netinet/in_var.h>
  110 #include <netinet/if_inarp.h>
  111 #endif
  112 
  113 #ifdef NS
  114 #include <netns/ns.h>
  115 #include <netns/ns_if.h>
  116 #endif
  117 
  118 #ifdef DECNET
  119 #include <netdnet/dn.h>
  120 #endif
  121 
  122 #ifdef ISO
  123 #include <netiso/argo_debug.h>
  124 #include <netiso/iso.h>
  125 #include <netiso/iso_var.h>
  126 #include <netiso/iso_snpac.h>
  127 #endif
  128 
  129 #include "bpfilter.h"
  130 
  131 #ifdef LLC
  132 #include <netccitt/dll.h>
  133 #include <netccitt/llc_var.h>
  134 #endif
  135 
  136 /*
  137  * TODO:
  138  * handle source routing via send_xid()
  139  * source routing for ISO,LLC,CCITT protocols
  140  * need sockaddr_dl_8025 to handle this correctly
  141  * IPX cases
  142  * handle "fast" forwarding like if_ether and if_fddi
  143  */
  144 
  145 #if defined(LLC) && defined(CCITT)
  146 extern struct ifqueue pkintrq;
  147 #endif
  148 
  149 #define senderr(e) { error = (e); goto bad;}
  150 
  151 #if defined(__bsdi__) || defined(__NetBSD__)
  152 #define RTALLOC1(a, b)                  rtalloc1(a, b)
  153 #define ARPRESOLVE(a, b, c, d, e, f)    arpresolve(a, b, c, d, e)
  154 #define TYPEHTONS(t)                    (t)
  155 #elif defined(__FreeBSD__)
  156 #define RTALLOC1(a, b)                  rtalloc1(a, b, 0UL)
  157 #define ARPRESOLVE(a, b, c, d, e, f)    arpresolve(a, b, c, d, e, f)
  158 #define TYPEHTONS(t)                    (htons(t))
  159 #endif
  160 
  161 #define RCF_ALLROUTES (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_ALL
  162 #define RCF_SINGLEROUTE (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_SINGLE
  163 
  164 static  int token_output __P((struct ifnet *, struct mbuf *,
  165             struct sockaddr *, struct rtentry *)); 
  166 static  void token_input __P((struct ifnet *, struct mbuf *));
  167 
  168 /*
  169  * Token Ring output routine.
  170  * Encapsulate a packet of type family for the local net.
  171  * Assumes that ifp is actually pointer to arphdr structure.
  172  * XXX route info has to go into the same mbuf as the header
  173  */
  174 static int
  175 token_output(ifp, m0, dst, rt0)
  176         struct ifnet *ifp;
  177         struct mbuf *m0;
  178         struct sockaddr *dst;
  179         struct rtentry *rt0;
  180 {
  181         u_int16_t etype;
  182         int s, len, error = 0;
  183         u_char edst[ISO88025_ADDR_LEN];
  184         struct mbuf *m = m0;
  185         struct rtentry *rt;
  186         struct mbuf *mcopy = (struct mbuf *)0;
  187         struct token_header *trh;
  188 #ifdef INET
  189         struct arphdr *ah = (struct arphdr *)ifp;
  190 #endif /* INET */
  191         struct token_rif *rif = (struct  token_rif *)0;
  192         struct token_rif bcastrif;
  193         size_t riflen = 0;
  194         ALTQ_DECL(struct altq_pktattr pktattr;)
  195         short mflags;
  196 
  197         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  198                 senderr(ENETDOWN);
  199         if ((rt = rt0)) {
  200                 if ((rt->rt_flags & RTF_UP) == 0) {
  201                         if ((rt0 = rt = RTALLOC1(dst, 1)))
  202                                 rt->rt_refcnt--;
  203                         else
  204                                 senderr(EHOSTUNREACH);
  205                 }
  206                 if (rt->rt_flags & RTF_GATEWAY) {
  207                         if (rt->rt_gwroute == 0)
  208                                 goto lookup;
  209                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  210                                 rtfree(rt); rt = rt0;
  211                         lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1);
  212                                 if ((rt = rt->rt_gwroute) == 0)
  213                                         senderr(EHOSTUNREACH);
  214                         }
  215                 }
  216                 if (rt->rt_flags & RTF_REJECT)
  217                         if (rt->rt_rmx.rmx_expire == 0 ||
  218                             time.tv_sec < rt->rt_rmx.rmx_expire)
  219                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  220         }
  221 
  222         /*
  223          * If the queueing discipline needs packet classification,
  224          * do it before prepending link headers.
  225          */
  226         IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
  227 
  228         switch (dst->sa_family) {
  229 
  230 #ifdef INET
  231         case AF_INET:
  232                 if (m->m_flags & M_BCAST) {
  233                         if (ifp->if_flags & IFF_LINK0) {
  234                                 if (ifp->if_flags & IFF_LINK1)
  235                                         bcastrif.tr_rcf = htons(RCF_ALLROUTES);
  236                                 else
  237                                         bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
  238                                 rif = &bcastrif;
  239                                 riflen = sizeof(rif->tr_rcf);
  240                         }
  241                         bcopy((caddr_t)tokenbroadcastaddr, (caddr_t)edst,
  242                             sizeof(edst));
  243                 }
  244 /*
  245  * XXX m->m_flags & M_MCAST   IEEE802_MAP_IP_MULTICAST ??
  246  */
  247                 else {
  248                         if (!ARPRESOLVE(ifp, rt, m, dst, edst, rt0))
  249                                 return (0);     /* if not yet resolved */
  250                         rif = TOKEN_RIF((struct llinfo_arp *) rt->rt_llinfo);
  251                         riflen = (ntohs(rif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
  252                 }
  253                 /* If broadcasting on a simplex interface, loopback a copy. */
  254                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  255                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  256                 etype = htons(ETHERTYPE_IP);
  257                 break;
  258         case AF_ARP:
  259 /*
  260  * XXX source routing, assume m->m_data contains the useful stuff
  261  */
  262                 ah = mtod(m, struct arphdr *);
  263                 ah->ar_hrd = htons(ARPHRD_IEEE802);
  264 
  265                 switch (ntohs(ah->ar_op)) {
  266                 case ARPOP_REVREQUEST:
  267                 case ARPOP_REVREPLY:
  268                         etype = htons(ETHERTYPE_REVARP);
  269                         break;
  270 
  271                 case ARPOP_REQUEST:
  272                 case ARPOP_REPLY:
  273                 default:
  274                         etype = htons(ETHERTYPE_ARP);
  275                 }
  276 
  277                 if (m->m_flags & M_BCAST) {
  278                         if (ifp->if_flags & IFF_LINK0) {
  279                                 if (ifp->if_flags & IFF_LINK1)
  280                                         bcastrif.tr_rcf = htons(RCF_ALLROUTES);
  281                                 else
  282                                         bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
  283                                 rif = &bcastrif;
  284                                 riflen = sizeof(rif->tr_rcf);
  285                         }
  286                         bcopy((caddr_t)tokenbroadcastaddr, (caddr_t)edst,
  287                             sizeof(edst));
  288                 }
  289                 else {
  290                         bcopy((caddr_t)ar_tha(ah), (caddr_t)edst, sizeof(edst));
  291                         trh = (struct token_header *)M_TRHSTART(m);
  292                         trh->token_ac = TOKEN_AC;
  293                         trh->token_fc = TOKEN_FC;
  294                         if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
  295                                 struct token_rif *trrif;
  296 
  297                                 trrif = TOKEN_RIF(trh);
  298                                 riflen = (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
  299                         }
  300                         bcopy((caddr_t)edst, (caddr_t)trh->token_dhost,
  301                             sizeof (edst));
  302                         bcopy(LLADDR(ifp->if_sadl), (caddr_t)trh->token_shost,
  303                             sizeof(trh->token_shost));
  304                         if (riflen != 0)
  305                                 trh->token_shost[0] |= TOKEN_RI_PRESENT;
  306 /*
  307  * compare (m->m_data - m->m_pktdat) with (sizeof(struct token_header) + riflen + ...
  308  */
  309                         m->m_len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
  310                         m->m_data -= (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
  311                         m->m_pkthdr.len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
  312                         goto send;
  313                 }
  314                 break;
  315 #endif
  316 #ifdef NS
  317         case AF_NS:
  318                 etype = htons(ETHERTYPE_NS);
  319                 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
  320                     (caddr_t)edst, sizeof (edst));
  321                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
  322                         return (looutput(ifp, m, dst, rt));
  323                 /* If broadcasting on a simplex interface, loopback a copy. */
  324                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  325                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  326                 break;
  327 #endif
  328 #ifdef  ISO
  329         case AF_ISO: {
  330                 int     snpalen;
  331                 struct  llc *l;
  332                 struct sockaddr_dl *sdl;
  333 
  334                 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
  335                     sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
  336                         bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
  337                 }
  338                 else if ((error =
  339                             iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
  340                                             (char *)edst, &snpalen)))
  341                         goto bad; /* Not resolved */
  342                 /* If broadcasting on a simplex interface, loopback a copy. */
  343                 if (*edst & 1)
  344                         m->m_flags |= (M_BCAST|M_MCAST);
  345                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
  346                     (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
  347                         M_PREPEND(mcopy, sizeof (*trh), M_DONTWAIT);
  348                         if (mcopy) {
  349                                 trh = mtod(mcopy, struct token_header *);
  350                                 bcopy((caddr_t)edst,
  351                                     (caddr_t)trh->token_dhost, sizeof (edst));
  352                                 bcopy(LLADDR(ifp->if_sadl),
  353                                     (caddr_t)trh->token_shost, sizeof (edst));
  354                         }
  355                 }
  356                 M_PREPEND(m, 3, M_DONTWAIT);
  357                 if (m == NULL)
  358                         return (0);
  359                 etype = 0;
  360                 l = mtod(m, struct llc *);
  361                 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
  362                 l->llc_control = LLC_UI;
  363 #if defined(__FreeBSD__)
  364                 IFDEBUG(D_ETHER)
  365                         int i;
  366                         printf("token_output: sending pkt to: ");
  367                         for (i=0; i < ISO88025_ADDR_LEN; i++)
  368                                 printf("%x ", edst[i] & 0xff);
  369                         printf("\n");
  370                 ENDDEBUG
  371 #endif
  372                 } break;
  373 #endif /* ISO */
  374 #ifdef  LLC
  375 /*      case AF_NSAP: */
  376         case AF_CCITT: {
  377                 struct sockaddr_dl *sdl =
  378                     (struct sockaddr_dl *) rt -> rt_gateway;
  379 
  380                 if (sdl && sdl->sdl_family == AF_LINK
  381                     && sdl->sdl_alen > 0) {
  382                         bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
  383                 }
  384                 else {
  385                         /* Not a link interface ? Funny ... */
  386                         goto bad;
  387                 }
  388                 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
  389                     (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
  390                         M_PREPEND(mcopy, sizeof (*trh), M_DONTWAIT);
  391                         if (mcopy) {
  392                                 trh = mtod(mcopy, struct token_header *);
  393                                 bcopy((caddr_t)edst,
  394                                     (caddr_t)trh->token_dhost, sizeof (edst));
  395                                 bcopy(LLADDR(ifp->if_sadl),
  396                                     (caddr_t)trh->token_shost, sizeof (edst));
  397                         }
  398                 }
  399                 etype = 0;
  400 #ifdef LLC_DEBUG
  401                 {
  402                         int i;
  403                         struct llc *l = mtod(m, struct llc *);
  404 
  405                         printf("token_output: sending LLC2 pkt to: ");
  406                         for (i=0; i < ISO88025_ADDR_LEN; i++)
  407                                 printf("%x ", edst[i] & 0xff);
  408                         printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
  409                             etype & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
  410                             l->llc_control & 0xff);
  411 
  412                 }
  413 #endif /* LLC_DEBUG */
  414                 }
  415                 break;
  416 #endif /* LLC */
  417 
  418         case AF_UNSPEC:
  419         {
  420                 struct ether_header *eh;
  421                 eh = (struct ether_header *)dst->sa_data;
  422                 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
  423                 if (*edst & 1)
  424                         m->m_flags |= (M_BCAST|M_MCAST);
  425                 etype = TYPEHTONS(eh->ether_type);
  426                 if (m->m_flags & M_BCAST) {
  427                         if (ifp->if_flags & IFF_LINK0) {
  428                                 if (ifp->if_flags & IFF_LINK1)
  429                                         bcastrif.tr_rcf = htons(RCF_ALLROUTES);
  430                                 else
  431                                         bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
  432                                 rif = &bcastrif;
  433                                 riflen = sizeof(bcastrif.tr_rcf);
  434                         }
  435                 }
  436                 break;
  437         }
  438 
  439         default:
  440                 printf("%s: can't handle af%d\n", ifp->if_xname,
  441                     dst->sa_family);
  442                 senderr(EAFNOSUPPORT);
  443         }
  444 
  445 
  446         if (mcopy)
  447                 (void) looutput(ifp, mcopy, dst, rt);
  448         if (etype != 0) {
  449                 struct llc *l;
  450                 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
  451                 if (m == 0)
  452                         senderr(ENOBUFS);
  453                 l = mtod(m, struct llc *);
  454                 l->llc_control = LLC_UI;
  455                 l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
  456                 l->llc_snap.org_code[0] = l->llc_snap.org_code[1] =
  457                     l->llc_snap.org_code[2] = 0;
  458                 bcopy((caddr_t) &etype, (caddr_t) &l->llc_snap.ether_type,
  459                     sizeof(u_int16_t));
  460         }
  461 
  462         /*
  463          * Add local net header.  If no space in first mbuf,
  464          * allocate another.
  465          */
  466 
  467         M_PREPEND(m, (riflen + sizeof (*trh)), M_DONTWAIT);
  468         if (m == 0)
  469                 senderr(ENOBUFS);
  470         trh = mtod(m, struct token_header *);
  471         trh->token_ac = TOKEN_AC;
  472         trh->token_fc = TOKEN_FC;
  473         bcopy((caddr_t)edst, (caddr_t)trh->token_dhost, sizeof (edst));
  474         bcopy(LLADDR(ifp->if_sadl), (caddr_t)trh->token_shost,
  475             sizeof(trh->token_shost));
  476 
  477         if (riflen != 0) {
  478                 struct token_rif *trrif;
  479 
  480                 trh->token_shost[0] |= TOKEN_RI_PRESENT;
  481                 trrif = TOKEN_RIF(trh);
  482                 bcopy(rif, trrif, riflen);
  483         }
  484 #ifdef INET
  485 send:
  486 #endif
  487 
  488         mflags = m->m_flags;
  489         len = m->m_pkthdr.len;
  490         s = splnet();
  491         /*
  492          * Queue message on interface, and start output if interface
  493          * not yet active.
  494          */
  495         IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
  496         if (error) {
  497                 /* mbuf is already freed */
  498                 splx(s);
  499                 return (error);
  500         }
  501         ifp->if_obytes += len;
  502         if (mflags & M_MCAST)
  503                 ifp->if_omcasts++;
  504         if ((ifp->if_flags & IFF_OACTIVE) == 0)
  505                 (*ifp->if_start)(ifp);
  506         splx(s);
  507         return (error);
  508 
  509 bad:
  510         if (m)
  511                 m_freem(m);
  512         return (error);
  513 }
  514 
  515 /*
  516  * Process a received token ring packet;
  517  * the packet is in the mbuf chain m with
  518  * the token ring header.
  519  */
  520 static void
  521 token_input(ifp, m)
  522         struct ifnet *ifp;
  523         struct mbuf *m;
  524 {
  525         struct ifqueue *inq;
  526         struct llc *l;
  527         struct token_header *trh;
  528         int s, lan_hdr_len;
  529 
  530         if ((ifp->if_flags & IFF_UP) == 0) {
  531                 m_freem(m);
  532                 return;
  533         }
  534 
  535         trh = mtod(m, struct token_header *);
  536 
  537         ifp->if_ibytes += m->m_pkthdr.len;
  538         if (bcmp((caddr_t)tokenbroadcastaddr, (caddr_t)trh->token_dhost,
  539             sizeof(tokenbroadcastaddr)) == 0)
  540                 m->m_flags |= M_BCAST;
  541         else if (trh->token_dhost[0] & 1)
  542                 m->m_flags |= M_MCAST;
  543         if (m->m_flags & (M_BCAST|M_MCAST))
  544                 ifp->if_imcasts++;
  545 
  546         /* Skip past the Token Ring header and RIF. */
  547         lan_hdr_len = sizeof(struct token_header);
  548         if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
  549                 struct token_rif *trrif;
  550 
  551                 trrif = TOKEN_RIF(trh);
  552                 lan_hdr_len += (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
  553         }
  554         m_adj(m, lan_hdr_len);
  555 
  556         l = mtod(m, struct llc *);
  557         switch (l->llc_dsap) {
  558 #if defined(INET) || defined(NS) || defined(DECNET)
  559         case LLC_SNAP_LSAP:
  560         {
  561                 u_int16_t etype;
  562                 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
  563                         goto dropanyway;
  564                 if (l->llc_snap.org_code[0] != 0 ||
  565                     l->llc_snap.org_code[1] != 0 ||
  566                     l->llc_snap.org_code[2] != 0)
  567                         goto dropanyway;
  568                 etype = ntohs(l->llc_snap.ether_type);
  569                 m_adj(m, LLC_SNAPFRAMELEN);
  570                 switch (etype) {
  571 #ifdef INET
  572                 case ETHERTYPE_IP:
  573                         schednetisr(NETISR_IP);
  574                         inq = &ipintrq;
  575                         break;
  576 
  577                 case ETHERTYPE_ARP:
  578                         schednetisr(NETISR_ARP);
  579                         inq = &arpintrq;
  580                         break;
  581 #endif
  582 #ifdef NS
  583                 case ETHERTYPE_NS:
  584                         schednetisr(NETISR_NS);
  585                         inq = &nsintrq;
  586                         break;
  587 #endif
  588 #ifdef DECNET
  589                 case ETHERTYPE_DECNET:
  590                         schednetisr(NETISR_DECNET);
  591                         inq = &decnetintrq;
  592                         break;
  593 #endif
  594                 default:
  595                         /*
  596                         printf("token_input: unknown protocol 0x%x\n", etype);
  597                         */
  598                         ifp->if_noproto++;
  599                         goto dropanyway;
  600                 }
  601                 break;
  602         }
  603 #endif /* INET || NS */
  604 #ifdef  ISO
  605         case LLC_ISO_LSAP:
  606                 switch (l->llc_control) {
  607                 case LLC_UI:
  608                         /* LLC_UI_P forbidden in class 1 service */
  609                         if ((l->llc_dsap == LLC_ISO_LSAP) &&
  610                             (l->llc_ssap == LLC_ISO_LSAP)) {
  611                                 /* LSAP for ISO */
  612                                 m->m_data += 3;         /* XXX */
  613                                 m->m_len -= 3;          /* XXX */
  614                                 m->m_pkthdr.len -= 3;   /* XXX */
  615                                 M_PREPEND(m, sizeof *trh, M_DONTWAIT);
  616                                 if (m == 0)
  617                                         return;
  618                                 *mtod(m, struct token_header *) = *trh;
  619 #if defined(__FreeBSD__)
  620                                 IFDEBUG(D_ETHER)
  621                                         printf("clnp packet");
  622                                 ENDDEBUG
  623 #endif
  624                                 schednetisr(NETISR_ISO);
  625                                 inq = &clnlintrq;
  626                                 break;
  627                         }
  628                         goto dropanyway;
  629 
  630                 case LLC_XID:
  631                 case LLC_XID_P:
  632                         if(m->m_len < ISO88025_ADDR_LEN)
  633                                 goto dropanyway;
  634                         l->llc_window = 0;
  635                         l->llc_fid = 9;
  636                         l->llc_class = 1;
  637                         l->llc_dsap = l->llc_ssap = 0;
  638                         /* Fall through to */
  639                 case LLC_TEST:
  640                 case LLC_TEST_P:
  641                 {
  642                         struct sockaddr sa;
  643                         struct ether_header *eh;
  644                         int i;
  645                         u_char c = l->llc_dsap;
  646 
  647                         l->llc_dsap = l->llc_ssap;
  648                         l->llc_ssap = c;
  649                         if (m->m_flags & (M_BCAST | M_MCAST))
  650                                 bcopy(LLADDR(ifp->if_sadl),
  651                                     (caddr_t)trh->token_dhost,
  652                                     ISO88025_ADDR_LEN);
  653                         sa.sa_family = AF_UNSPEC;
  654                         sa.sa_len = sizeof(sa);
  655                         eh = (struct ether_header *)sa.sa_data;
  656                         for (i = 0; i < ISO88025_ADDR_LEN; i++) {
  657                                 eh->ether_shost[i] = c = trh->token_dhost[i];
  658                                 eh->ether_dhost[i] =
  659                                     eh->ether_dhost[i] = trh->token_shost[i];
  660                                 eh->ether_shost[i] = c;
  661                         }
  662                         eh->ether_type = 0;
  663                         ifp->if_output(ifp, m, &sa, NULL);
  664                         return;
  665                 }
  666                 default:
  667                         m_freem(m);
  668                         return;
  669                 }
  670                 break;
  671 #endif /* ISO */
  672 #ifdef LLC
  673         case LLC_X25_LSAP:
  674         {
  675 /*
  676  * XXX check for source routing info ? (sizeof(struct sdl_hdr) and
  677  * ISO88025_ADDR_LEN)
  678  */
  679                 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
  680                 if (m == 0)
  681                         return;
  682                 if (!sdl_sethdrif(ifp, trh->token_shost, LLC_X25_LSAP,
  683                                     trh->token_dhost, LLC_X25_LSAP,
  684                                     ISO88025_ADDR_LEN,
  685                                     mtod(m, struct sdl_hdr *)))
  686                         panic("ETHER cons addr failure");
  687                 mtod(m, struct sdl_hdr *)->sdlhdr_len =
  688                     m->m_pkthdr.len - sizeof(struct sdl_hdr);
  689 #ifdef LLC_DEBUG
  690                 printf("llc packet\n");
  691 #endif /* LLC_DEBUG */
  692                 schednetisr(NETISR_CCITT);
  693                 inq = &llcintrq;
  694                 break;
  695         }
  696 #endif /* LLC */
  697 
  698         default:
  699                 /* printf("token_input: unknown dsap 0x%x\n", l->llc_dsap); */
  700                 ifp->if_noproto++;
  701         dropanyway:
  702                 m_freem(m);
  703                 return;
  704         }
  705 
  706         s = splnet();
  707         if (IF_QFULL(inq)) {
  708                 IF_DROP(inq);
  709                 m_freem(m);
  710         }
  711         else
  712                 IF_ENQUEUE(inq, m);
  713         splx(s);
  714 }
  715 
  716 /*
  717  * Perform common duties while attaching to interface list
  718  */
  719 void
  720 token_ifattach(ifp, lla)
  721         struct ifnet *ifp;
  722         caddr_t lla;
  723 {
  724 
  725         ifp->if_type = IFT_ISO88025;
  726         ifp->if_addrlen = ISO88025_ADDR_LEN;
  727         ifp->if_hdrlen = 14;
  728         ifp->if_dlt = DLT_IEEE802;
  729         ifp->if_mtu = ISO88025_MTU;
  730         ifp->if_output = token_output;
  731         ifp->if_input = token_input;
  732         ifp->if_broadcastaddr = tokenbroadcastaddr;
  733 #ifdef IFF_NOTRAILERS
  734         ifp->if_flags |= IFF_NOTRAILERS;
  735 #endif
  736 
  737         if_alloc_sadl(ifp);
  738         memcpy(LLADDR(ifp->if_sadl), lla, ifp->if_addrlen);
  739 
  740 #if NBPFILTER > 0
  741         bpfattach(ifp, DLT_IEEE802, sizeof(struct token_header));
  742 #endif
  743 }
  744 
  745 void    
  746 token_ifdetach(ifp)
  747         struct ifnet *ifp;
  748 {
  749 
  750 #if NBPFILTER > 0
  751         bpfdetach(ifp);
  752 #endif
  753 #if 0   /* done in if_detach() */
  754         if_free_sadl(ifp);
  755 #endif
  756 }

Cache object: 41a2697c99a9437e1f081a38a9772d72


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