root/net/if_fddisubr.c

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

DEFINITIONS

This source file includes following definitions.
  1. fddi_output
  2. fddi_input
  3. fddi_ifattach

    1 /*      $OpenBSD: if_fddisubr.c,v 1.52 2007/06/06 10:04:36 henning Exp $        */
    2 /*      $NetBSD: if_fddisubr.c,v 1.5 1996/05/07 23:20:21 christos Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1995
    6  *      Matt Thomas.  All rights reserved.
    7  * Copyright (c) 1982, 1989, 1993
    8  *      The Regents of the University of California.  All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)if_fddisubr.c       8.1 (Berkeley) 6/10/93
   35  */
   36 
   37 /*
   38  *      @(#)COPYRIGHT   1.1 (NRL) January 1997
   39  * 
   40  * NRL grants permission for redistribution and use in source and binary
   41  * forms, with or without modification, of the software and documentation
   42  * created at NRL provided that the following conditions are met:
   43  * 
   44  * 1. Redistributions of source code must retain the above copyright
   45  *    notice, this list of conditions and the following disclaimer.
   46  * 2. Redistributions in binary form must reproduce the above copyright
   47  *    notice, this list of conditions and the following disclaimer in the
   48  *    documentation and/or other materials provided with the distribution.
   49  * 3. All advertising materials mentioning features or use of this software
   50  *    must display the following acknowledgements:
   51  *      This product includes software developed by the University of
   52  *      California, Berkeley and its contributors.
   53  *      This product includes software developed at the Information
   54  *      Technology Division, US Naval Research Laboratory.
   55  * 4. Neither the name of the NRL nor the names of its contributors
   56  *    may be used to endorse or promote products derived from this software
   57  *    without specific prior written permission.
   58  * 
   59  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
   60  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   61  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   62  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
   63  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   64  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   65  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   66  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   67  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   68  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   69  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   70  * 
   71  * The views and conclusions contained in the software and documentation
   72  * are those of the authors and should not be interpreted as representing
   73  * official policies, either expressed or implied, of the US Naval
   74  * Research Laboratory (NRL).
   75  */
   76 
   77 #include <sys/param.h>
   78 #include <sys/systm.h>
   79 #include <sys/kernel.h>
   80 #include <sys/malloc.h>
   81 #include <sys/mbuf.h>
   82 #include <sys/protosw.h>
   83 #include <sys/socket.h>
   84 #include <sys/ioctl.h>
   85 #include <sys/errno.h>
   86 #include <sys/syslog.h>
   87 
   88 #include <machine/cpu.h>
   89 
   90 #include <net/if.h>
   91 #include <net/netisr.h>
   92 #include <net/route.h>
   93 #include <net/if_llc.h>
   94 #include <net/if_dl.h>
   95 #include <net/if_types.h>
   96 
   97 #ifdef INET
   98 #include <netinet/in.h>
   99 #include <netinet/in_var.h>
  100 #endif
  101 #include <netinet/if_ether.h>
  102 #include <net/if_fddi.h>
  103 
  104 #ifdef INET6
  105 #ifndef INET
  106 #include <netinet/in.h>
  107 #include <netinet/in_var.h>
  108 #endif
  109 #include <netinet6/nd6.h>
  110 #endif
  111 
  112 #include "bpfilter.h"
  113 
  114 #include "carp.h"
  115 #if NCARP > 0
  116 #include <netinet/ip_carp.h>
  117 #endif
  118 
  119 #define senderr(e) { error = (e); goto bad;}
  120 
  121 /*
  122  * This really should be defined in if_llc.h but in case it isn't.
  123  */
  124 #ifndef llc_snap
  125 #define llc_snap        llc_un.type_snap
  126 #endif
  127 
  128 /*
  129  * FDDI output routine.
  130  * Encapsulate a packet of type family for the local net.
  131  * Assumes that ifp is actually pointer to arpcom structure.
  132  */
  133 int
  134 fddi_output(ifp0, m0, dst, rt0)
  135         struct ifnet *ifp0;
  136         struct mbuf *m0;
  137         struct sockaddr *dst;
  138         struct rtentry *rt0;
  139 {
  140         u_int16_t type;
  141         int s, len, error = 0, hdrcmplt = 0;
  142         u_char edst[6], esrc[6];
  143         struct mbuf *m = m0;
  144         struct rtentry *rt;
  145         struct mbuf *mcopy = (struct mbuf *)0;
  146         struct fddi_header *fh;
  147         struct arpcom *ac = (struct arpcom *)ifp0;
  148         short mflags;
  149         struct ifnet *ifp = ifp0;
  150 
  151 #if NCARP > 0
  152         if (ifp->if_type == IFT_CARP) {
  153                 struct ifaddr *ifa;
  154 
  155                 /* loop back if this is going to the carp interface */
  156                 if (dst != NULL && LINK_STATE_IS_UP(ifp0->if_link_state) &&
  157                     (ifa = ifa_ifwithaddr(dst)) != NULL &&
  158                     ifa->ifa_ifp == ifp0)
  159                         return (looutput(ifp0, m, dst, rt0));
  160 
  161                 ifp = ifp->if_carpdev;
  162                 ac = (struct arpcom *)ifp;
  163 
  164                 if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
  165                     (IFF_UP|IFF_RUNNING))
  166                         senderr(ENETDOWN);
  167         }
  168 #endif /* NCARP > 0 */
  169         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  170                 senderr(ENETDOWN);
  171         if ((rt = rt0) != NULL) {
  172                 if ((rt->rt_flags & RTF_UP) == 0) {
  173                         if ((rt0 = rt = rtalloc1(dst, 1, 0)) != NULL)
  174                                 rt->rt_refcnt--;
  175                         else 
  176                                 senderr(EHOSTUNREACH);
  177                 }
  178                 if (rt->rt_flags & RTF_GATEWAY) {
  179                         if (rt->rt_gwroute == 0)
  180                                 goto lookup;
  181                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  182                                 rtfree(rt); rt = rt0;
  183                         lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0);
  184                                 if ((rt = rt->rt_gwroute) == 0)
  185                                         senderr(EHOSTUNREACH);
  186                         }
  187                 }
  188                 if (rt->rt_flags & RTF_REJECT)
  189                         if (rt->rt_rmx.rmx_expire == 0 ||
  190                             time_second < rt->rt_rmx.rmx_expire)
  191                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  192         }
  193 
  194         switch (dst->sa_family) {
  195 
  196 #ifdef INET
  197         case AF_INET:
  198                 if (!arpresolve(ac, rt, m, dst, edst))
  199                         return (0);     /* if not yet resolved */
  200                 /* If broadcasting on a simplex interface, loopback a copy */
  201                 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
  202                     !m->m_pkthdr.pf.routed)
  203                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  204                 type = htons(ETHERTYPE_IP);
  205                 break;
  206 #endif
  207 #ifdef INET6
  208         case AF_INET6:
  209                 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst))
  210                         return (0);     /* if not yet resolved */
  211                 type = htons(ETHERTYPE_IPV6);
  212                 break;
  213 #endif
  214 #if 0   /*NRL IPv6*/
  215 #ifdef INET6
  216         case AF_INET6:
  217                 /*
  218                  * The bottom line here is to either queue the outgoing packet
  219                  * in the discovery engine, or fill in edst with something
  220                  * that'll work.
  221                  */
  222                 if (m->m_flags & M_MCAST) {
  223                         /*
  224                          * If multicast dest., then use IPv6 -> Ethernet mcast
  225                          * mapping.  Really simple.
  226                          */
  227                         ETHER_MAP_IN6_MULTICAST(((struct sockaddr_in6 *)dst)->sin6_addr,
  228                             edst);
  229                 } else {
  230                         /* Do unicast neighbor discovery stuff. */
  231                         if (!ipv6_discov_resolve(ifp, rt, m, dst, edst))
  232                                 return 0;
  233                 }
  234                 type = htons(ETHERTYPE_IPV6);
  235                 break;
  236 #endif /* INET6 */
  237 #endif
  238 
  239         case pseudo_AF_HDRCMPLT:
  240         {
  241                 struct fddi_header *fh = (struct fddi_header *)dst->sa_data;
  242                 hdrcmplt = 1;
  243                 bcopy((caddr_t)fh->fddi_shost, (caddr_t)esrc, sizeof (esrc));
  244                 /* FALLTHROUGH */
  245         }
  246 
  247         case AF_UNSPEC:
  248         {
  249                 struct ether_header *eh;
  250                 eh = (struct ether_header *)dst->sa_data;
  251                 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
  252                 if (*edst & 1)
  253                         m->m_flags |= (M_BCAST|M_MCAST);
  254                 type = eh->ether_type;
  255                 break;
  256         }
  257 
  258 #if NBPFILTER > 0
  259         case AF_IMPLINK:
  260         {
  261                 fh = mtod(m, struct fddi_header *);
  262                 error = EPROTONOSUPPORT;
  263                 switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
  264                         case FDDIFC_LLC_ASYNC: {
  265                                 /* legal priorities are 0 through 7 */
  266                                 if ((fh->fddi_fc & FDDIFC_Z) > 7)
  267                                         goto bad;
  268                                 break;
  269                         }
  270                         case FDDIFC_LLC_SYNC: {
  271                                 /* FDDIFC_Z bits reserved, must be zero */
  272                                 if (fh->fddi_fc & FDDIFC_Z)
  273                                         goto bad;
  274                                 break;
  275                         }
  276                         case FDDIFC_SMT: {
  277                                 /* FDDIFC_Z bits must be non zero */
  278                                 if ((fh->fddi_fc & FDDIFC_Z) == 0)
  279                                         goto bad;
  280                                 break;
  281                         }
  282                         default: {
  283                                 /* anything else is too dangerous */
  284                                 goto bad;
  285                         }
  286                 }
  287                 error = 0;
  288                 if (fh->fddi_dhost[0] & 1)
  289                         m->m_flags |= (M_BCAST|M_MCAST);
  290                 goto queue_it;
  291         }
  292 #endif
  293         default:
  294                 printf("%s: can't handle af%d\n", ifp->if_xname,
  295                         dst->sa_family);
  296                 senderr(EAFNOSUPPORT);
  297         }
  298 
  299         if (mcopy)
  300                 (void) looutput(ifp, mcopy, dst, rt);
  301 
  302         if (type != 0) {
  303                 struct llc *l;
  304                 M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
  305                 if (m == 0)
  306                         senderr(ENOBUFS);
  307                 l = mtod(m, struct llc *);
  308                 l->llc_control = LLC_UI;
  309                 l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
  310                 l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
  311                 bcopy((caddr_t) &type, (caddr_t) &l->llc_snap.ether_type,
  312                         sizeof(u_short));
  313         }
  314         /*
  315          * Add local net header.  If no space in first mbuf,
  316          * allocate another.
  317          */
  318         M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
  319         if (m == 0)
  320                 senderr(ENOBUFS);
  321         fh = mtod(m, struct fddi_header *);
  322         fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
  323         bcopy((caddr_t)edst, (caddr_t)fh->fddi_dhost, sizeof (edst));
  324 #if NBPFILTER > 0
  325   queue_it:
  326 #endif
  327         if (hdrcmplt)
  328                 bcopy((caddr_t)esrc, (caddr_t)fh->fddi_shost,
  329                     sizeof(fh->fddi_shost));
  330         else
  331                 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)fh->fddi_shost,
  332                     sizeof(fh->fddi_shost));
  333 #if NCARP > 0
  334         if (ifp0 != ifp && ifp0->if_type == IFT_CARP) {
  335                 bcopy((caddr_t)((struct arpcom *)ifp0)->ac_enaddr,
  336                     (caddr_t)fh->fddi_shost, sizeof(fh->fddi_shost));
  337         }
  338 #endif
  339         mflags = m->m_flags;
  340         len = m->m_pkthdr.len;
  341         s = splnet();
  342         /*
  343          * Queue message on interface, and start output if interface
  344          * not yet active.
  345          */
  346         IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
  347         if (error) {
  348                 /* mbuf is already freed */
  349                 splx(s);
  350                 return (error);
  351         }
  352         ifp->if_obytes += len;
  353 #if NCARP > 0
  354         if (ifp != ifp0)
  355                 ifp0->if_obytes += len;
  356 #endif /* NCARP > 0 */
  357         if (mflags & M_MCAST)
  358                 ifp->if_omcasts++;
  359         if ((ifp->if_flags & IFF_OACTIVE) == 0)
  360                 (*ifp->if_start)(ifp);
  361         splx(s);
  362         return (error);
  363 
  364 bad:
  365         if (m)
  366                 m_freem(m);
  367         return (error);
  368 }
  369 
  370 /*
  371  * Process a received FDDI packet;
  372  * the packet is in the mbuf chain m without
  373  * the fddi header, which is provided separately.
  374  */
  375 void
  376 fddi_input(ifp, fh, m)
  377         struct ifnet *ifp;
  378         struct fddi_header *fh;
  379         struct mbuf *m;
  380 {
  381         struct ifqueue *inq;
  382         struct llc *l;
  383         int s;
  384 
  385         if ((ifp->if_flags & IFF_UP) == 0) {
  386                 m_freem(m);
  387                 return;
  388         }
  389         ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh);
  390         if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost,
  391             sizeof(fddibroadcastaddr)) == 0)
  392                 m->m_flags |= M_BCAST;
  393         else if (fh->fddi_dhost[0] & 1)
  394                 m->m_flags |= M_MCAST;
  395         if (m->m_flags & (M_BCAST|M_MCAST))
  396                 ifp->if_imcasts++;
  397 
  398         l = mtod(m, struct llc *);
  399         switch (l->llc_dsap) {
  400 #if defined(INET) || defined(INET6)
  401         case LLC_SNAP_LSAP:
  402         {
  403                 u_int16_t etype;
  404                 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
  405                         goto dropanyway;
  406                 if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
  407                         goto dropanyway;
  408                 etype = ntohs(l->llc_snap.ether_type);
  409                 m_adj(m, LLC_SNAPFRAMELEN);
  410 
  411 #if NCARP > 0
  412                 if (ifp->if_carp && ifp->if_type != IFT_CARP &&
  413                     (carp_input(m, (u_int8_t *)&fh->fddi_shost,
  414                     (u_int8_t *)&fh->fddi_dhost, l->llc_snap.ether_type) == 0))
  415                         return;
  416 #endif
  417 
  418                 switch (etype) {
  419 #ifdef INET
  420                 case ETHERTYPE_IP:
  421                         schednetisr(NETISR_IP);
  422                         inq = &ipintrq;
  423                         break;
  424 
  425                 case ETHERTYPE_ARP:
  426                         if (ifp->if_flags & IFF_NOARP)
  427                                 goto dropanyway;
  428                         schednetisr(NETISR_ARP);
  429                         inq = &arpintrq;
  430                         break;
  431 #endif
  432 #ifdef INET6
  433                 case ETHERTYPE_IPV6:
  434                         schednetisr(NETISR_IPV6);
  435                         inq = &ip6intrq;
  436                         break;
  437 #endif /* INET6 */
  438                 default:
  439                         /* printf("fddi_input: unknown protocol 0x%x\n", etype); */
  440                         ifp->if_noproto++;
  441                         goto dropanyway;
  442                 }
  443                 break;
  444         }
  445 #endif /* INET || INET6 */
  446                 
  447         default:
  448                 /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */
  449                 ifp->if_noproto++;
  450         dropanyway:
  451                 m_freem(m);
  452                 return;
  453         }
  454 
  455         s = splnet();
  456         IF_INPUT_ENQUEUE(inq, m);
  457         splx(s);
  458 }
  459 /*
  460  * Perform common duties while attaching to interface list
  461  */
  462 void
  463 fddi_ifattach(ifp)
  464         struct ifnet *ifp;
  465 {
  466 
  467         ifp->if_type = IFT_FDDI;
  468         ifp->if_addrlen = 6;
  469         ifp->if_hdrlen = 21;
  470         ifp->if_mtu = FDDIMTU;
  471         ifp->if_output = fddi_output;
  472         if_alloc_sadl(ifp);
  473         bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
  474               LLADDR(ifp->if_sadl), ifp->if_addrlen);
  475 }

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