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_arcsubr.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_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $   */
    2 /*      $FreeBSD: releng/5.0/sys/net/if_arcsubr.c 106939 2002-11-15 00:00:15Z sam $ */
    3 
    4 /*
    5  * Copyright (c) 1994, 1995 Ignatios Souvatzis
    6  * Copyright (c) 1982, 1989, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by the University of
   20  *      California, Berkeley and its contributors.
   21  * 4. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  * from: NetBSD: if_ethersubr.c,v 1.9 1994/06/29 06:36:11 cgd Exp
   38  *       @(#)if_ethersubr.c     8.1 (Berkeley) 6/10/93
   39  *
   40  */
   41 #include "opt_inet.h"
   42 #include "opt_inet6.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/protosw.h>
   50 #include <sys/socket.h>
   51 #include <sys/sockio.h>
   52 #include <sys/errno.h>
   53 #include <sys/syslog.h>
   54 
   55 #include <machine/cpu.h>
   56 
   57 #include <net/if.h>
   58 #include <net/netisr.h>
   59 #include <net/route.h>
   60 #include <net/if_dl.h>
   61 #include <net/if_types.h>
   62 #include <net/if_arc.h>
   63 #include <net/if_arp.h>
   64 #include <net/bpf.h>
   65 
   66 #if defined(INET) || defined(INET6)
   67 #include <netinet/in.h>
   68 #include <netinet/in_var.h>
   69 #include <netinet/if_ether.h>
   70 #endif
   71 
   72 #ifdef INET6
   73 #include <netinet6/nd6.h>
   74 #endif
   75 
   76 MODULE_VERSION(arcnet, 1);
   77 
   78 #define ARCNET_ALLOW_BROKEN_ARP
   79 
   80 static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *);
   81 
   82 u_int8_t  arcbroadcastaddr = 0;
   83 
   84 #define senderr(e) { error = (e); goto bad;}
   85 #define SIN(s) ((struct sockaddr_in *)s)
   86 
   87 /*
   88  * ARCnet output routine.
   89  * Encapsulate a packet of type family for the local net.
   90  * Assumes that ifp is actually pointer to arccom structure.
   91  */
   92 int
   93 arc_output(ifp, m, dst, rt0)
   94         struct ifnet *ifp;
   95         struct mbuf *m;
   96         struct sockaddr *dst;
   97         struct rtentry *rt0;
   98 {
   99         struct mbuf             *mcopy;
  100         struct rtentry          *rt;
  101         struct arccom           *ac;
  102         struct arc_header       *ah;
  103         struct arphdr           *arph;
  104         int                     error;
  105         u_int8_t                atype, adst;
  106 #if __FreeBSD_version < 500000
  107         int                     s;
  108 #endif
  109 
  110         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  111                 return(ENETDOWN); /* m, m1 aren't initialized yet */
  112 
  113         error = 0;
  114         ac = (struct arccom *)ifp;
  115         mcopy = NULL;
  116 
  117         if ((rt = rt0)) {
  118                 if ((rt->rt_flags & RTF_UP) == 0) {
  119                         if ((rt0 = rt = rtalloc1(dst, 1, 0UL)))
  120                                 rt->rt_refcnt--;
  121                         else
  122                                 senderr(EHOSTUNREACH);
  123                 }
  124                 if (rt->rt_flags & RTF_GATEWAY) {
  125                         if (rt->rt_gwroute == 0)
  126                                 goto lookup;
  127                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  128                                 rtfree(rt); rt = rt0;
  129                         lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL);
  130                                 if ((rt = rt->rt_gwroute) == 0)
  131                                         senderr(EHOSTUNREACH);
  132                         }
  133                 }
  134                 if (rt->rt_flags & RTF_REJECT)
  135                         if (rt->rt_rmx.rmx_expire == 0 ||
  136                             time_second < rt->rt_rmx.rmx_expire)
  137                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  138         }
  139 
  140         switch (dst->sa_family) {
  141 #ifdef INET
  142         case AF_INET:
  143 
  144                 /*
  145                  * For now, use the simple IP addr -> ARCnet addr mapping
  146                  */
  147                 if (m->m_flags & (M_BCAST|M_MCAST))
  148                         adst = arcbroadcastaddr; /* ARCnet broadcast address */
  149                 else if (ifp->if_flags & IFF_NOARP)
  150                         adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
  151                 else if (!arpresolve(ifp, rt, m, dst, &adst, rt0))
  152                         return 0;       /* not resolved yet */
  153 
  154                 /* If broadcasting on a simplex interface, loopback a copy */
  155                 if ((m->m_flags & (M_BCAST|M_MCAST)) &&
  156                     (ifp->if_flags & IFF_SIMPLEX))
  157                         mcopy = m_copy(m, 0, (int)M_COPYALL);
  158                 atype = (ifp->if_flags & IFF_LINK0) ?
  159                         ARCTYPE_IP_OLD : ARCTYPE_IP;
  160                 break;
  161 #endif
  162 #ifdef INET6
  163         case AF_INET6:
  164 #ifdef OLDIP6OUTPUT
  165                 if (!nd6_resolve(ifp, rt, m, dst, (u_char *)&adst))
  166                         return(0);      /* if not yet resolves */
  167 #else
  168                 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)&adst))
  169                         return(0); /* it must be impossible, but... */
  170 #endif /* OLDIP6OUTPUT */
  171                 atype = ARCTYPE_INET6;
  172                 break;
  173 #endif
  174 
  175         case AF_UNSPEC:
  176                 ah = (struct arc_header *)dst->sa_data;
  177                 adst = ah->arc_dhost;
  178                 atype = ah->arc_type;
  179 
  180                 if (atype == ARCTYPE_ARP) {
  181                         atype = (ifp->if_flags & IFF_LINK0) ?
  182                             ARCTYPE_ARP_OLD: ARCTYPE_ARP;
  183 
  184 #ifdef ARCNET_ALLOW_BROKEN_ARP
  185                         /*
  186                          * XXX It's not clear per RFC826 if this is needed, but
  187                          * "assigned numbers" say this is wrong.
  188                          * However, e.g., AmiTCP 3.0Beta used it... we make this
  189                          * switchable for emergency cases. Not perfect, but...
  190                          */
  191                         arph = mtod(m, struct arphdr *);
  192                         if (ifp->if_flags & IFF_LINK2)
  193                                 arph->ar_pro = atype - 1;
  194 #endif
  195                 }
  196                 break;
  197 
  198         default:
  199                 if_printf(ifp, "can't handle af%d\n", dst->sa_family);
  200                 senderr(EAFNOSUPPORT);
  201         }
  202 
  203         if (mcopy)
  204                 (void) if_simloop(ifp, mcopy, dst->sa_family, 0);
  205 
  206         M_PREPEND(m, ARC_HDRLEN, M_DONTWAIT);
  207         if (m == 0)
  208                 senderr(ENOBUFS);
  209         ah = mtod(m, struct arc_header *);
  210         ah->arc_type = atype;
  211         ah->arc_dhost = adst;
  212         ah->arc_shost = *IF_LLADDR(ifp);
  213 
  214         BPF_MTAP(ifp, m);
  215 
  216 #if __FreeBSD_version < 500000
  217         s = splimp();
  218 
  219         /*
  220          * Queue message on interface, and start output if interface
  221          * not yet active.
  222          */
  223         if (IF_QFULL(&ifp->if_snd)) {
  224                 IF_DROP(&ifp->if_snd);
  225                 splx(s);
  226                 senderr(ENOBUFS);
  227         }
  228         ifp->if_obytes += m->m_pkthdr.len;
  229         IF_ENQUEUE(&ifp->if_snd, m);
  230         if ((ifp->if_flags & IFF_OACTIVE) == 0)
  231                 (*ifp->if_start)(ifp);
  232         splx(s);
  233 #else
  234         if (!IF_HANDOFF(&ifp->if_snd, m, ifp)) {
  235                 m = 0;
  236                 senderr(ENOBUFS);
  237         }
  238 #endif
  239 
  240         return (error);
  241 
  242 bad:
  243         if (m)
  244                 m_freem(m);
  245         return (error);
  246 }
  247 
  248 void
  249 arc_frag_init(ifp)
  250         struct ifnet *ifp;
  251 {
  252         struct arccom *ac;
  253 
  254         ac = (struct arccom *)ifp;
  255         ac->curr_frag = 0;
  256 }
  257 
  258 struct mbuf *
  259 arc_frag_next(ifp)
  260         struct ifnet *ifp;
  261 {
  262         struct arccom *ac;
  263         struct mbuf *m;
  264         struct arc_header *ah;
  265 
  266         ac = (struct arccom *)ifp;
  267         if ((m = ac->curr_frag) == 0) {
  268                 int tfrags;
  269 
  270                 /* dequeue new packet */
  271                 IF_DEQUEUE(&ifp->if_snd, m);
  272                 if (m == 0)
  273                         return 0;
  274 
  275                 ah = mtod(m, struct arc_header *);
  276                 if (!arc_isphds(ah->arc_type))
  277                         return m;
  278 
  279                 ++ac->ac_seqid;         /* make the seqid unique */
  280                 tfrags = (m->m_pkthdr.len + 503) / 504;
  281                 ac->fsflag = 2 * tfrags - 3;
  282                 ac->sflag = 0;
  283                 ac->rsflag = ac->fsflag;
  284                 ac->arc_dhost = ah->arc_dhost;
  285                 ac->arc_shost = ah->arc_shost;
  286                 ac->arc_type = ah->arc_type;
  287 
  288                 m_adj(m, ARC_HDRLEN);
  289                 ac->curr_frag = m;
  290         }
  291 
  292         /* split out next fragment and return it */
  293         if (ac->sflag < ac->fsflag) {
  294                 /* we CAN'T have short packets here */
  295                 ac->curr_frag = m_split(m, 504, M_DONTWAIT);
  296                 if (ac->curr_frag == 0) {
  297                         m_freem(m);
  298                         return 0;
  299                 }
  300 
  301                 M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT);
  302                 if (m == 0) {
  303                         m_freem(ac->curr_frag);
  304                         ac->curr_frag = 0;
  305                         return 0;
  306                 }
  307 
  308                 ah = mtod(m, struct arc_header *);
  309                 ah->arc_flag = ac->rsflag;
  310                 ah->arc_seqid = ac->ac_seqid;
  311 
  312                 ac->sflag += 2;
  313                 ac->rsflag = ac->sflag;
  314         } else if ((m->m_pkthdr.len >=
  315             ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) &&
  316             (m->m_pkthdr.len <=
  317             ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) {
  318                 ac->curr_frag = 0;
  319 
  320                 M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_DONTWAIT);
  321                 if (m == 0)
  322                         return 0;
  323 
  324                 ah = mtod(m, struct arc_header *);
  325                 ah->arc_flag = 0xFF;
  326                 ah->arc_seqid = 0xFFFF;
  327                 ah->arc_type2 = ac->arc_type;
  328                 ah->arc_flag2 = ac->sflag;
  329                 ah->arc_seqid2 = ac->ac_seqid;
  330         } else {
  331                 ac->curr_frag = 0;
  332 
  333                 M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT);
  334                 if (m == 0)
  335                         return 0;
  336 
  337                 ah = mtod(m, struct arc_header *);
  338                 ah->arc_flag = ac->sflag;
  339                 ah->arc_seqid = ac->ac_seqid;
  340         }
  341 
  342         ah->arc_dhost = ac->arc_dhost;
  343         ah->arc_shost = ac->arc_shost;
  344         ah->arc_type = ac->arc_type;
  345 
  346         return m;
  347 }
  348 
  349 /*
  350  * Defragmenter. Returns mbuf if last packet found, else
  351  * NULL. frees imcoming mbuf as necessary.
  352  */
  353 
  354 static __inline struct mbuf *
  355 arc_defrag(ifp, m)
  356         struct ifnet *ifp;
  357         struct mbuf *m;
  358 {
  359         struct arc_header *ah, *ah1;
  360         struct arccom *ac;
  361         struct ac_frag *af;
  362         struct mbuf *m1;
  363         char *s;
  364         int newflen;
  365         u_char src,dst,typ;
  366 
  367         ac = (struct arccom *)ifp;
  368 
  369         if (m->m_len < ARC_HDRNEWLEN) {
  370                 m = m_pullup(m, ARC_HDRNEWLEN);
  371                 if (m == NULL) {
  372                         ++ifp->if_ierrors;
  373                         return NULL;
  374                 }
  375         }
  376 
  377         ah = mtod(m, struct arc_header *);
  378         typ = ah->arc_type;
  379 
  380         if (!arc_isphds(typ))
  381                 return m;
  382 
  383         src = ah->arc_shost;
  384         dst = ah->arc_dhost;
  385 
  386         if (ah->arc_flag == 0xff) {
  387                 m_adj(m, 4);
  388 
  389                 if (m->m_len < ARC_HDRNEWLEN) {
  390                         m = m_pullup(m, ARC_HDRNEWLEN);
  391                         if (m == NULL) {
  392                                 ++ifp->if_ierrors;
  393                                 return NULL;
  394                         }
  395                 }
  396 
  397                 ah = mtod(m, struct arc_header *);
  398         }
  399 
  400         af = &ac->ac_fragtab[src];
  401         m1 = af->af_packet;
  402         s = "debug code error";
  403 
  404         if (ah->arc_flag & 1) {
  405                 /*
  406                  * first fragment. We always initialize, which is
  407                  * about the right thing to do, as we only want to
  408                  * accept one fragmented packet per src at a time.
  409                  */
  410                 if (m1 != NULL)
  411                         m_freem(m1);
  412 
  413                 af->af_packet = m;
  414                 m1 = m;
  415                 af->af_maxflag = ah->arc_flag;
  416                 af->af_lastseen = 0;
  417                 af->af_seqid = ah->arc_seqid;
  418 
  419                 return NULL;
  420                 /* notreached */
  421         } else {
  422                 /* check for unfragmented packet */
  423                 if (ah->arc_flag == 0)
  424                         return m;
  425 
  426                 /* do we have a first packet from that src? */
  427                 if (m1 == NULL) {
  428                         s = "no first frag";
  429                         goto outofseq;
  430                 }
  431 
  432                 ah1 = mtod(m1, struct arc_header *);
  433 
  434                 if (ah->arc_seqid != ah1->arc_seqid) {
  435                         s = "seqid differs";
  436                         goto outofseq;
  437                 }
  438 
  439                 if (typ != ah1->arc_type) {
  440                         s = "type differs";
  441                         goto outofseq;
  442                 }
  443 
  444                 if (dst != ah1->arc_dhost) {
  445                         s = "dest host differs";
  446                         goto outofseq;
  447                 }
  448 
  449                 /* typ, seqid and dst are ok here. */
  450 
  451                 if (ah->arc_flag == af->af_lastseen) {
  452                         m_freem(m);
  453                         return NULL;
  454                 }
  455 
  456                 if (ah->arc_flag == af->af_lastseen + 2) {
  457                         /* ok, this is next fragment */
  458                         af->af_lastseen = ah->arc_flag;
  459                         m_adj(m,ARC_HDRNEWLEN);
  460 
  461                         /*
  462                          * m_cat might free the first mbuf (with pkthdr)
  463                          * in 2nd chain; therefore:
  464                          */
  465 
  466                         newflen = m->m_pkthdr.len;
  467 
  468                         m_cat(m1,m);
  469 
  470                         m1->m_pkthdr.len += newflen;
  471 
  472                         /* is it the last one? */
  473                         if (af->af_lastseen > af->af_maxflag) {
  474                                 af->af_packet = NULL;
  475                                 return(m1);
  476                         } else
  477                                 return NULL;
  478                 }
  479                 s = "other reason";
  480                 /* if all else fails, it is out of sequence, too */
  481         }
  482 outofseq:
  483         if (m1) {
  484                 m_freem(m1);
  485                 af->af_packet = NULL;
  486         }
  487 
  488         if (m)
  489                 m_freem(m);
  490 
  491         log(LOG_INFO,"%s%d: got out of seq. packet: %s\n",
  492             ifp->if_name, ifp->if_unit, s);
  493 
  494         return NULL;
  495 }
  496 
  497 /*
  498  * return 1 if Packet Header Definition Standard, else 0.
  499  * For now: old IP, old ARP aren't obviously. Lacking correct information,
  500  * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS.
  501  * (Apple and Novell corporations were involved, among others, in PHDS work).
  502  * Easiest is to assume that everybody else uses that, too.
  503  */
  504 int
  505 arc_isphds(type)
  506         u_int8_t type;
  507 {
  508         return (type != ARCTYPE_IP_OLD &&
  509                 type != ARCTYPE_ARP_OLD &&
  510                 type != ARCTYPE_DIAGNOSE);
  511 }
  512 
  513 /*
  514  * Process a received Arcnet packet;
  515  * the packet is in the mbuf chain m with
  516  * the ARCnet header.
  517  */
  518 void
  519 arc_input(ifp, m)
  520         struct ifnet *ifp;
  521         struct mbuf *m;
  522 {
  523         struct arc_header *ah;
  524         struct ifqueue *inq;
  525         u_int8_t atype;
  526 #ifdef INET
  527         struct arphdr *arph;
  528 #endif
  529 #if __FreeBSD_version < 500000
  530         int s;
  531 #endif
  532 
  533         if ((ifp->if_flags & IFF_UP) == 0) {
  534                 m_freem(m);
  535                 return;
  536         }
  537 
  538         /* possibly defragment: */
  539         m = arc_defrag(ifp, m);
  540         if (m == NULL)
  541                 return;
  542 
  543         BPF_MTAP(ifp, m);
  544 
  545         ah = mtod(m, struct arc_header *);
  546 
  547         ifp->if_ibytes += m->m_pkthdr.len;
  548 
  549         if (arcbroadcastaddr == ah->arc_dhost) {
  550                 m->m_flags |= M_BCAST|M_MCAST;
  551                 ifp->if_imcasts++;
  552         }
  553 
  554         atype = ah->arc_type;
  555         switch (atype) {
  556 #ifdef INET
  557         case ARCTYPE_IP:
  558                 m_adj(m, ARC_HDRNEWLEN);
  559                 schednetisr(NETISR_IP);
  560                 inq = &ipintrq;
  561                 break;
  562 
  563         case ARCTYPE_IP_OLD:
  564                 m_adj(m, ARC_HDRLEN);
  565                 schednetisr(NETISR_IP);
  566                 inq = &ipintrq;
  567                 break;
  568 
  569         case ARCTYPE_ARP:
  570                 if (ifp->if_flags & IFF_NOARP) {
  571                         /* Discard packet if ARP is disabled on interface */
  572                         m_freem(m);
  573                         return;
  574                 }
  575                 m_adj(m, ARC_HDRNEWLEN);
  576                 schednetisr(NETISR_ARP);
  577                 inq = &arpintrq;
  578 #ifdef ARCNET_ALLOW_BROKEN_ARP
  579                 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP);
  580 #endif
  581                 break;
  582 
  583         case ARCTYPE_ARP_OLD:
  584                 if (ifp->if_flags & IFF_NOARP) {
  585                         /* Discard packet if ARP is disabled on interface */
  586                         m_freem(m);
  587                         return;
  588                 }
  589                 m_adj(m, ARC_HDRLEN);
  590                 schednetisr(NETISR_ARP);
  591                 inq = &arpintrq;
  592                 arph = mtod(m, struct arphdr *);
  593 #ifdef ARCNET_ALLOW_BROKEN_ARP
  594                 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP);
  595 #endif
  596                 break;
  597 #endif
  598 #ifdef INET6
  599         case ARCTYPE_INET6:
  600                 m_adj(m, ARC_HDRNEWLEN);
  601                 schednetisr(NETISR_IPV6);
  602                 inq = &ip6intrq;
  603                 break;
  604 #endif
  605         default:
  606                 m_freem(m);
  607                 return;
  608         }
  609 
  610 #if __FreeBSD_version < 500000
  611         s = splimp();
  612         if (IF_QFULL(inq)) {
  613                 IF_DROP(inq);
  614                 m_freem(m);
  615         } else
  616                 IF_ENQUEUE(inq, m);
  617         splx(s);
  618 #else
  619         IF_HANDOFF(inq, m, NULL);
  620 #endif
  621 }
  622 
  623 /*
  624  * Convert Arcnet address to printable (loggable) representation.
  625  */
  626 static char digits[] = "0123456789abcdef";
  627 char *
  628 arc_sprintf(ap)
  629         u_int8_t *ap;
  630 {
  631         static char arcbuf[3];
  632         char *cp = arcbuf;
  633 
  634         *cp++ = digits[*ap >> 4];
  635         *cp++ = digits[*ap++ & 0xf];
  636         *cp   = 0;
  637         return (arcbuf);
  638 }
  639 
  640 /*
  641  * Register (new) link level address.
  642  */
  643 void
  644 arc_storelladdr(ifp, lla)
  645         struct ifnet *ifp;
  646         u_int8_t lla;
  647 {
  648         *IF_LLADDR(ifp) = lla;
  649 }
  650 
  651 /*
  652  * Perform common duties while attaching to interface list
  653  */
  654 void
  655 arc_ifattach(ifp, lla)
  656         struct ifnet *ifp;
  657         u_int8_t lla;
  658 {
  659         struct ifaddr *ifa;
  660         struct sockaddr_dl *sdl;
  661         struct arccom *ac;
  662 
  663         if_attach(ifp);
  664         ifp->if_type = IFT_ARCNET;
  665         ifp->if_addrlen = 1;
  666         ifp->if_hdrlen = ARC_HDRLEN;
  667         ifp->if_mtu = 1500;
  668         if (ifp->if_baudrate == 0)
  669                 ifp->if_baudrate = 2500000;
  670 #if __FreeBSD_version < 500000
  671         ifa = ifnet_addrs[ifp->if_index - 1];
  672 #else
  673         ifa = ifaddr_byindex(ifp->if_index);
  674 #endif
  675         KASSERT(ifa != NULL, ("%s: no lladdr!\n", __FUNCTION__));
  676         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
  677         sdl->sdl_type = IFT_ARCNET;
  678         sdl->sdl_alen = ifp->if_addrlen;
  679 
  680         if (ifp->if_flags & IFF_BROADCAST)
  681                 ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI;
  682 
  683         ac = (struct arccom *)ifp;
  684         ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */
  685         if (lla == 0) {
  686                 /* XXX this message isn't entirely clear, to me -- cgd */
  687                 log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts.  Please change it and ifconfig %s%d down up\n",
  688                    ifp->if_name, ifp->if_unit, ifp->if_name, ifp->if_unit);
  689         }
  690         arc_storelladdr(ifp, lla);
  691 
  692         ifp->if_broadcastaddr = &arcbroadcastaddr;
  693 
  694         bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN);
  695 }
  696 
  697 void
  698 arc_ifdetach(ifp)
  699         struct ifnet *ifp;
  700 {
  701         bpfdetach(ifp);
  702         if_detach(ifp);
  703 }
  704 
  705 int
  706 arc_ioctl(ifp, command, data)
  707         struct ifnet *ifp;
  708         int command;
  709         caddr_t data;
  710 {
  711         struct ifaddr *ifa = (struct ifaddr *) data;
  712         struct ifreq *ifr = (struct ifreq *) data;
  713         int error = 0;
  714 
  715         switch (command) {
  716         case SIOCSIFADDR:
  717                 ifp->if_flags |= IFF_UP;
  718                 switch (ifa->ifa_addr->sa_family) {
  719 #ifdef INET
  720                 case AF_INET:
  721                         ifp->if_init(ifp->if_softc);    /* before arpwhohas */
  722                         arp_ifinit(ifp, ifa);
  723                         break;
  724 #endif
  725                 default:
  726                         ifp->if_init(ifp->if_softc);
  727                         break;
  728                 }
  729                 break;
  730 
  731         case SIOCADDMULTI:
  732         case SIOCDELMULTI:
  733                 if (ifr == NULL)
  734                         error = EAFNOSUPPORT;
  735                 else {
  736                         switch (ifr->ifr_addr.sa_family) {
  737                         case AF_INET:
  738                         case AF_INET6:
  739                                 error = 0;
  740                                 break;
  741                         default:
  742                                 error = EAFNOSUPPORT;
  743                                 break;
  744                         }
  745                 }
  746                 break;
  747 
  748         case SIOCSIFMTU:
  749                 /*
  750                  * Set the interface MTU.
  751                  * mtu can't be larger than ARCMTU for RFC1051
  752                  * and can't be larger than ARC_PHDS_MTU
  753                  */
  754                 if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) ||
  755                     ifr->ifr_mtu > ARC_PHDS_MAXMTU)
  756                         error = EINVAL;
  757                 else
  758                         ifp->if_mtu = ifr->ifr_mtu;
  759                 break;
  760 
  761 #if 0
  762         case SIOCGIFADDR:
  763                 {
  764                         struct sockaddr *sa;
  765 
  766                         sa = (struct sockaddr *) & ifr->ifr_data;
  767                         bcopy(IFP2AC(ifp)->ac_enaddr,
  768                               (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
  769                 }
  770                 break;
  771 #endif
  772         }
  773 
  774         return (error);
  775 }

Cache object: 3e1191535ffe7b14c26ff35c9a96ba48


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