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.85 2022/09/03 02:47:59 thorpej Exp $  */
    2 
    3 /*
    4  * Copyright (c) 1994, 1995 Ignatios Souvatzis
    5  * Copyright (c) 1982, 1989, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * from: NetBSD: if_ethersubr.c,v 1.9 1994/06/29 06:36:11 cgd Exp
   33  *       @(#)if_ethersubr.c     8.1 (Berkeley) 6/10/93
   34  *
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: if_arcsubr.c,v 1.85 2022/09/03 02:47:59 thorpej Exp $");
   39 
   40 #ifdef _KERNEL_OPT
   41 #include "opt_inet.h"
   42 #endif
   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/ioctl.h>
   50 #include <sys/errno.h>
   51 #include <sys/syslog.h>
   52 
   53 #include <sys/cpu.h>
   54 
   55 #include <net/if.h>
   56 #include <net/route.h>
   57 #include <net/if_dl.h>
   58 #include <net/if_types.h>
   59 #include <net/if_arc.h>
   60 #include <net/if_arp.h>
   61 #include <net/if_ether.h>
   62 
   63 #include <net/bpf.h>
   64 
   65 #ifdef INET
   66 #include <netinet/in.h>
   67 #include <netinet/in_var.h>
   68 #include <netinet/if_inarp.h>
   69 #endif
   70 
   71 #ifdef INET6
   72 #ifndef INET
   73 #include <netinet/in.h>
   74 #endif
   75 #include <netinet6/in6_var.h>
   76 #include <netinet6/nd6.h>
   77 #endif
   78 
   79 #define ARCNET_ALLOW_BROKEN_ARP
   80 
   81 #ifndef ARC_IPMTU
   82 #define ARC_IPMTU       1500
   83 #endif
   84 
   85 static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *);
   86 
   87 /*
   88  * RC1201 requires us to have this configurable. We have it only per
   89  * machine at the moment... there is no generic "set mtu" ioctl, AFAICS.
   90  * Anyway, it is possible to binpatch this or set it per kernel config
   91  * option.
   92  */
   93 #if ARC_IPMTU > 60480
   94 ERROR: The arc_ipmtu is ARC_IPMTU, but must not exceed 60480.
   95 #endif
   96 int arc_ipmtu = ARC_IPMTU;
   97 uint8_t  arcbroadcastaddr = 0;
   98 
   99 #define senderr(e) { error = (e); goto bad;}
  100 
  101 static  int arc_output(struct ifnet *, struct mbuf *,
  102             const struct sockaddr *, const struct rtentry *);
  103 static  void arc_input(struct ifnet *, struct mbuf *);
  104 
  105 /*
  106  * ARCnet output routine.
  107  * Encapsulate a packet of type family for the local net.
  108  * Assumes that ifp is actually pointer to arccom structure.
  109  */
  110 static int
  111 arc_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
  112     const struct rtentry *rt)
  113 {
  114         struct mbuf             *m, *m1, *mcopy;
  115         struct arccom           *ac;
  116         const struct arc_header *cah;
  117         struct arc_header       *ah;
  118         struct arphdr           *arph;
  119         int                     error, newencoding;
  120         uint8_t                 atype, adst, myself;
  121         int                     tfrags, sflag, fsflag, rsflag;
  122 
  123         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  124                 return (ENETDOWN); /* m, m1 aren't initialized yet */
  125 
  126         error = newencoding = 0;
  127         ac = (struct arccom *)ifp;
  128         m = m0;
  129         mcopy = m1 = NULL;
  130 
  131         myself = *CLLADDR(ifp->if_sadl);
  132 
  133         /*
  134          * if the queueing discipline needs packet classification,
  135          * do it before prepending link headers.
  136          */
  137         IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
  138 
  139         switch (dst->sa_family) {
  140 #ifdef INET
  141         case AF_INET:
  142 
  143                 /*
  144                  * For now, use the simple IP addr -> ARCnet addr mapping
  145                  */
  146                 if (m->m_flags & (M_BCAST|M_MCAST))
  147                         adst = arcbroadcastaddr; /* ARCnet broadcast address */
  148                 else if (ifp->if_flags & IFF_NOARP)
  149                         adst = ntohl(satocsin(dst)->sin_addr.s_addr) & 0xFF;
  150                 else if ((error = arpresolve(ifp, rt, m, dst, &adst,
  151                     sizeof(adst))) != 0)
  152                         return error == EWOULDBLOCK ? 0 : error;
  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_copypacket(m, M_DONTWAIT);
  158                 if (ifp->if_flags & IFF_LINK0) {
  159                         atype = ARCTYPE_IP;
  160                         newencoding = 1;
  161                 } else {
  162                         atype = ARCTYPE_IP_OLD;
  163                         newencoding = 0;
  164                 }
  165                 break;
  166 
  167         case AF_ARP:
  168                 arph = mtod(m, struct arphdr *);
  169                 if (m->m_flags & M_BCAST)
  170                         adst = arcbroadcastaddr;
  171                 else {
  172                         uint8_t *tha = ar_tha(arph);
  173                         if (tha == NULL) {
  174                                 m_freem(m);
  175                                 return 0;
  176                         }
  177                         adst = *tha;
  178                 }
  179 
  180                 arph->ar_hrd = htons(ARPHRD_ARCNET);
  181 
  182                 switch (ntohs(arph->ar_op)) {
  183                 case ARPOP_REVREQUEST:
  184                 case ARPOP_REVREPLY:
  185                         if (!(ifp->if_flags & IFF_LINK0)) {
  186                                 printf("%s: can't handle af%d\n",
  187                                     ifp->if_xname, dst->sa_family);
  188                                 senderr(EAFNOSUPPORT);
  189                         }
  190 
  191                         atype = htons(ARCTYPE_REVARP);
  192                         newencoding = 1;
  193                         break;
  194 
  195                 case ARPOP_REQUEST:
  196                 case ARPOP_REPLY:
  197                 default:
  198                         if (ifp->if_flags & IFF_LINK0) {
  199                                 atype = htons(ARCTYPE_ARP);
  200                                 newencoding = 1;
  201                         } else {
  202                                 atype = htons(ARCTYPE_ARP_OLD);
  203                                 newencoding = 0;
  204                         }
  205                 }
  206 #ifdef ARCNET_ALLOW_BROKEN_ARP
  207                 /*
  208                  * XXX It's not clear per RFC826 if this is needed, but
  209                  * "assigned numbers" say this is wrong.
  210                  * However, e.g., AmiTCP 3.0Beta used it... we make this
  211                  * switchable for emergency cases. Not perfect, but...
  212                  */
  213                 if (ifp->if_flags & IFF_LINK2)
  214                         arph->ar_pro = atype - 1;
  215 #endif
  216                 break;
  217 #endif
  218 #ifdef INET6
  219         case AF_INET6:
  220                 if (m->m_flags & M_MCAST) {
  221                         adst = 0;
  222                 } else {
  223                         error = nd6_resolve(ifp, rt, m, dst, &adst,
  224                             sizeof(adst));
  225                         if (error != 0)
  226                                 return error == EWOULDBLOCK ? 0 : error;
  227                 }
  228                 atype = htons(ARCTYPE_INET6);
  229                 newencoding = 1;
  230                 break;
  231 #endif
  232 
  233         case AF_UNSPEC:
  234                 cah = (const struct arc_header *)dst->sa_data;
  235                 adst = cah->arc_dhost;
  236                 atype = cah->arc_type;
  237                 break;
  238 
  239         default:
  240                 printf("%s: can't handle af%d\n", ifp->if_xname,
  241                     dst->sa_family);
  242                 senderr(EAFNOSUPPORT);
  243         }
  244 
  245         if (mcopy)
  246                 (void) looutput(ifp, mcopy, dst, rt);
  247 
  248         /*
  249          * Add local net header.  If no space in first mbuf,
  250          * allocate another.
  251          *
  252          * For ARCnet, this is just symbolic. The header changes
  253          * form and position on its way into the hardware and out of
  254          * the wire.  At this point, it contains source, destination and
  255          * packet type.
  256          */
  257         if (newencoding) {
  258                 ++ac->ac_seqid; /* make the seqid unique */
  259 
  260                 tfrags = (m->m_pkthdr.len + 503) / 504;
  261                 fsflag = 2 * tfrags - 3;
  262                 sflag = 0;
  263                 rsflag = fsflag;
  264 
  265                 while (sflag < fsflag) {
  266                         /* we CAN'T have short packets here */
  267                         m1 = m_split(m, 504, M_DONTWAIT);
  268                         if (m1 == 0)
  269                                 senderr(ENOBUFS);
  270 
  271                         M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT);
  272                         if (m == 0)
  273                                 senderr(ENOBUFS);
  274                         ah = mtod(m, struct arc_header *);
  275                         ah->arc_type = atype;
  276                         ah->arc_dhost = adst;
  277                         ah->arc_shost = myself;
  278                         ah->arc_flag = rsflag;
  279                         ah->arc_seqid = ac->ac_seqid;
  280 
  281                         if ((error = ifq_enqueue(ifp, m)) != 0)
  282                                 return (error);
  283 
  284                         m = m1;
  285                         sflag += 2;
  286                         rsflag = sflag;
  287                 }
  288                 m1 = NULL;
  289 
  290 
  291                 /* here we can have small, especially forbidden packets */
  292 
  293                 if ((m->m_pkthdr.len >=
  294                     ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) &&
  295                     (m->m_pkthdr.len <=
  296                     ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) {
  297 
  298                         M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_DONTWAIT);
  299                         if (m == 0)
  300                                 senderr(ENOBUFS);
  301                         ah = mtod(m, struct arc_header *);
  302                         ah->arc_flag = 0xFF;
  303                         ah->arc_seqid = 0xFFFF;
  304                         ah->arc_type2 = atype;
  305                         ah->arc_flag2 = sflag;
  306                         ah->arc_seqid2 = ac->ac_seqid;
  307                 } else {
  308                         M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT);
  309                         if (m == 0)
  310                                 senderr(ENOBUFS);
  311                         ah = mtod(m, struct arc_header *);
  312                         ah->arc_flag = sflag;
  313                         ah->arc_seqid = ac->ac_seqid;
  314                 }
  315 
  316                 ah->arc_dhost = adst;
  317                 ah->arc_shost = myself;
  318                 ah->arc_type = atype;
  319         } else {
  320                 M_PREPEND(m, ARC_HDRLEN, M_DONTWAIT);
  321                 if (m == 0)
  322                         senderr(ENOBUFS);
  323                 ah = mtod(m, struct arc_header *);
  324                 ah->arc_type = atype;
  325                 ah->arc_dhost = adst;
  326                 ah->arc_shost = myself;
  327         }
  328 
  329         return ifq_enqueue(ifp, m);
  330 
  331 bad:
  332         if (m1)
  333                 m_freem(m1);
  334         if (m)
  335                 m_freem(m);
  336         return (error);
  337 }
  338 
  339 /*
  340  * Defragmenter. Returns mbuf if last packet found, else
  341  * NULL. frees imcoming mbuf as necessary.
  342  */
  343 
  344 static struct mbuf *
  345 arc_defrag(struct ifnet *ifp, struct mbuf *m)
  346 {
  347         struct arc_header *ah, *ah1;
  348         struct arccom *ac;
  349         struct ac_frag *af;
  350         struct mbuf *m1;
  351         const char *s;
  352         int newflen;
  353         u_char src, dst, typ;
  354 
  355         ac = (struct arccom *)ifp;
  356 
  357         if (m->m_len < ARC_HDRNEWLEN) {
  358                 m = m_pullup(m, ARC_HDRNEWLEN);
  359                 if (m == NULL) {
  360                         if_statinc(ifp, if_ierrors);
  361                         return NULL;
  362                 }
  363         }
  364 
  365         ah = mtod(m, struct arc_header *);
  366         typ = ah->arc_type;
  367 
  368         if (!arc_isphds(typ))
  369                 return m;
  370 
  371         src = ah->arc_shost;
  372         dst = ah->arc_dhost;
  373 
  374         if (ah->arc_flag == 0xff) {
  375                 m_adj(m, 4);
  376 
  377                 if (m->m_len < ARC_HDRNEWLEN) {
  378                         m = m_pullup(m, ARC_HDRNEWLEN);
  379                         if (m == NULL) {
  380                                 if_statinc(ifp, if_ierrors);
  381                                 return NULL;
  382                         }
  383                 }
  384 
  385                 ah = mtod(m, struct arc_header *);
  386         }
  387 
  388         af = &ac->ac_fragtab[src];
  389         m1 = af->af_packet;
  390         s = "debug code error";
  391 
  392         if (ah->arc_flag & 1) {
  393                 /*
  394                  * first fragment. We always initialize, which is
  395                  * about the right thing to do, as we only want to
  396                  * accept one fragmented packet per src at a time.
  397                  */
  398                 if (m1 != NULL)
  399                         m_freem(m1);
  400 
  401                 af->af_packet = m;
  402                 m1 = m;
  403                 af->af_maxflag = ah->arc_flag;
  404                 af->af_lastseen = 0;
  405                 af->af_seqid = ah->arc_seqid;
  406 
  407                 return NULL;
  408                 /* notreached */
  409         } else {
  410                 /* check for unfragmented packet */
  411                 if (ah->arc_flag == 0)
  412                         return m;
  413 
  414                 /* do we have a first packet from that src? */
  415                 if (m1 == NULL) {
  416                         s = "no first frag";
  417                         goto outofseq;
  418                 }
  419 
  420                 ah1 = mtod(m1, struct arc_header *);
  421 
  422                 if (ah->arc_seqid != ah1->arc_seqid) {
  423                         s = "seqid differs";
  424                         goto outofseq;
  425                 }
  426 
  427                 if (typ != ah1->arc_type) {
  428                         s = "type differs";
  429                         goto outofseq;
  430                 }
  431 
  432                 if (dst != ah1->arc_dhost) {
  433                         s = "dest host differs";
  434                         goto outofseq;
  435                 }
  436 
  437                 /* typ, seqid and dst are ok here. */
  438 
  439                 if (ah->arc_flag == af->af_lastseen) {
  440                         m_freem(m);
  441                         return NULL;
  442                 }
  443 
  444                 if (ah->arc_flag == af->af_lastseen + 2) {
  445                         /* ok, this is next fragment */
  446                         af->af_lastseen = ah->arc_flag;
  447                         m_adj(m, ARC_HDRNEWLEN);
  448 
  449                         /*
  450                          * m_cat might free the first mbuf (with pkthdr)
  451                          * in 2nd chain; therefore:
  452                          */
  453 
  454                         newflen = m->m_pkthdr.len;
  455 
  456                         m_cat(m1, m);
  457 
  458                         m1->m_pkthdr.len += newflen;
  459 
  460                         /* is it the last one? */
  461                         if (af->af_lastseen > af->af_maxflag) {
  462                                 af->af_packet = NULL;
  463                                 return (m1);
  464                         } else
  465                                 return NULL;
  466                 }
  467                 s = "other reason";
  468                 /* if all else fails, it is out of sequence, too */
  469         }
  470 outofseq:
  471         if (m1) {
  472                 m_freem(m1);
  473                 af->af_packet = NULL;
  474         }
  475 
  476         if (m)
  477                 m_freem(m);
  478 
  479         log(LOG_INFO,"%s: got out of seq. packet: %s\n",
  480             ifp->if_xname, s);
  481 
  482         return NULL;
  483 }
  484 
  485 /*
  486  * return 1 if Packet Header Definition Standard, else 0.
  487  * For now: old IP, old ARP aren't obviously. Lacking correct information,
  488  * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS.
  489  * (Apple and Novell corporations were involved, among others, in PHDS work).
  490  * Easiest is to assume that everybody else uses that, too.
  491  */
  492 int
  493 arc_isphds(uint8_t type)
  494 {
  495         return (type != ARCTYPE_IP_OLD &&
  496                 type != ARCTYPE_ARP_OLD &&
  497                 type != ARCTYPE_DIAGNOSE);
  498 }
  499 
  500 /*
  501  * Process a received Arcnet packet;
  502  * the packet is in the mbuf chain m with
  503  * the ARCnet header.
  504  */
  505 static void
  506 arc_input(struct ifnet *ifp, struct mbuf *m)
  507 {
  508         pktqueue_t *pktq = NULL;
  509         struct arc_header *ah;
  510         uint8_t atype;
  511 
  512         if ((ifp->if_flags & IFF_UP) == 0) {
  513                 m_freem(m);
  514                 return;
  515         }
  516 
  517         /* possibly defragment: */
  518         m = arc_defrag(ifp, m);
  519         if (m == NULL)
  520                 return;
  521 
  522         ah = mtod(m, struct arc_header *);
  523 
  524         if_statadd(ifp, if_ibytes, m->m_pkthdr.len);
  525 
  526         if (arcbroadcastaddr == ah->arc_dhost) {
  527                 m->m_flags |= M_BCAST|M_MCAST;
  528                 if_statinc(ifp, if_imcasts);
  529         }
  530 
  531         atype = ah->arc_type;
  532         switch (atype) {
  533 #ifdef INET
  534         case ARCTYPE_IP:
  535                 m_adj(m, ARC_HDRNEWLEN);
  536                 pktq = ip_pktq;
  537                 break;
  538 
  539         case ARCTYPE_IP_OLD:
  540                 m_adj(m, ARC_HDRLEN);
  541                 pktq = ip_pktq;
  542                 break;
  543 
  544         case ARCTYPE_ARP:
  545                 m_adj(m, ARC_HDRNEWLEN);
  546                 pktq = arp_pktq;
  547 #ifdef ARCNET_ALLOW_BROKEN_ARP
  548                 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP);
  549 #endif
  550                 break;
  551 
  552         case ARCTYPE_ARP_OLD:
  553                 m_adj(m, ARC_HDRLEN);
  554                 pktq = arp_pktq;
  555 #ifdef ARCNET_ALLOW_BROKEN_ARP
  556                 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP);
  557 #endif
  558                 break;
  559 #endif
  560 #ifdef INET6
  561         case ARCTYPE_INET6:
  562                 m_adj(m, ARC_HDRNEWLEN);
  563                 pktq = ip6_pktq;
  564                 break;
  565 #endif
  566         default:
  567                 m_freem(m);
  568                 return;
  569         }
  570 
  571         KASSERT(pktq != NULL);
  572         if (__predict_false(!pktq_enqueue(pktq, m, 0))) {
  573                 m_freem(m);
  574         }
  575 }
  576 
  577 /*
  578  * Convert Arcnet address to printable (loggable) representation.
  579  */
  580 char *
  581 arc_sprintf(uint8_t *ap)
  582 {
  583         static char arcbuf[3];
  584         char *cp = arcbuf;
  585 
  586         *cp++ = hexdigits[*ap >> 4];
  587         *cp++ = hexdigits[*ap++ & 0xf];
  588         *cp   = 0;
  589         return (arcbuf);
  590 }
  591 
  592 /*
  593  * Perform common duties while attaching to interface list
  594  */
  595 int
  596 arc_ifattach(struct ifnet *ifp, uint8_t lla)
  597 {
  598         struct arccom *ac;
  599 
  600         ifp->if_type = IFT_ARCNET;
  601         ifp->if_addrlen = 1;
  602         ifp->if_hdrlen = ARC_HDRLEN;
  603         ifp->if_dlt = DLT_ARCNET;
  604         if (ifp->if_flags & IFF_BROADCAST)
  605                 ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI;
  606         if (ifp->if_flags & IFF_LINK0 && arc_ipmtu > ARC_PHDS_MAXMTU)
  607                 log(LOG_ERR,
  608                     "%s: arc_ipmtu is %d, but must not exceed %d\n",
  609                     ifp->if_xname, arc_ipmtu, ARC_PHDS_MAXMTU);
  610 
  611         ifp->if_output = arc_output;
  612         ifp->_if_input = arc_input;
  613         ac = (struct arccom *)ifp;
  614         ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */
  615         if (lla == 0) {
  616                 /* XXX this message isn't entirely clear, to me -- cgd */
  617                 log(LOG_ERR,"%s: link address 0 reserved for broadcasts.  Please change it and ifconfig %s down up\n",
  618                    ifp->if_xname, ifp->if_xname);
  619         }
  620         if_attach(ifp);
  621 
  622         if_set_sadl(ifp, &lla, sizeof(lla), true);
  623 
  624         ifp->if_broadcastaddr = &arcbroadcastaddr;
  625 
  626         bpf_attach(ifp, DLT_ARCNET, ARC_HDRLEN);
  627 
  628         return 0;
  629 }

Cache object: 82076bd108f04bddcc8552a38eba43b0


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