189099Sfjoe/* $NetBSD: if_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $ */ 289099Sfjoe/* $FreeBSD: stable/11/sys/net/if_arcsubr.c 332159 2018-04-06 23:31:47Z brooks $ */ 389099Sfjoe 4139823Simp/*- 589099Sfjoe * Copyright (c) 1994, 1995 Ignatios Souvatzis 689099Sfjoe * Copyright (c) 1982, 1989, 1993 789099Sfjoe * The Regents of the University of California. All rights reserved. 889099Sfjoe * 989099Sfjoe * Redistribution and use in source and binary forms, with or without 1089099Sfjoe * modification, are permitted provided that the following conditions 1189099Sfjoe * are met: 1289099Sfjoe * 1. Redistributions of source code must retain the above copyright 1389099Sfjoe * notice, this list of conditions and the following disclaimer. 1489099Sfjoe * 2. Redistributions in binary form must reproduce the above copyright 1589099Sfjoe * notice, this list of conditions and the following disclaimer in the 1689099Sfjoe * documentation and/or other materials provided with the distribution. 1789099Sfjoe * 3. All advertising materials mentioning features or use of this software 1889099Sfjoe * must display the following acknowledgement: 1989099Sfjoe * This product includes software developed by the University of 2089099Sfjoe * California, Berkeley and its contributors. 2189099Sfjoe * 4. Neither the name of the University nor the names of its contributors 2289099Sfjoe * may be used to endorse or promote products derived from this software 2389099Sfjoe * without specific prior written permission. 2489099Sfjoe * 2589099Sfjoe * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2689099Sfjoe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2789099Sfjoe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2889099Sfjoe * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2989099Sfjoe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3089099Sfjoe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3189099Sfjoe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3289099Sfjoe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3389099Sfjoe * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3489099Sfjoe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3589099Sfjoe * SUCH DAMAGE. 3689099Sfjoe * 3789099Sfjoe * from: NetBSD: if_ethersubr.c,v 1.9 1994/06/29 06:36:11 cgd Exp 3889099Sfjoe * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 3989099Sfjoe * 4089099Sfjoe */ 4189099Sfjoe#include "opt_inet.h" 4289099Sfjoe#include "opt_inet6.h" 4389099Sfjoe 4489099Sfjoe#include <sys/param.h> 4589099Sfjoe#include <sys/systm.h> 4689099Sfjoe#include <sys/kernel.h> 47129880Sphk#include <sys/module.h> 4889099Sfjoe#include <sys/malloc.h> 4989099Sfjoe#include <sys/mbuf.h> 5089099Sfjoe#include <sys/protosw.h> 5189099Sfjoe#include <sys/socket.h> 5289099Sfjoe#include <sys/sockio.h> 5389099Sfjoe#include <sys/errno.h> 5489099Sfjoe#include <sys/syslog.h> 5589099Sfjoe 5689099Sfjoe#include <machine/cpu.h> 5789099Sfjoe 5889099Sfjoe#include <net/if.h> 59257176Sglebius#include <net/if_var.h> 6089099Sfjoe#include <net/netisr.h> 6189099Sfjoe#include <net/route.h> 6289099Sfjoe#include <net/if_dl.h> 6389099Sfjoe#include <net/if_types.h> 6489099Sfjoe#include <net/if_arc.h> 6589099Sfjoe#include <net/if_arp.h> 6689099Sfjoe#include <net/bpf.h> 67186119Sqingli#include <net/if_llatbl.h> 6889099Sfjoe 6989099Sfjoe#if defined(INET) || defined(INET6) 7089099Sfjoe#include <netinet/in.h> 7189099Sfjoe#include <netinet/in_var.h> 7289099Sfjoe#include <netinet/if_ether.h> 7389099Sfjoe#endif 7489099Sfjoe 7589099Sfjoe#ifdef INET6 7689099Sfjoe#include <netinet6/nd6.h> 7789099Sfjoe#endif 7889099Sfjoe 7989099Sfjoe#define ARCNET_ALLOW_BROKEN_ARP 8089099Sfjoe 8192725Salfredstatic struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 82109771Sfjoestatic int arc_resolvemulti(struct ifnet *, struct sockaddr **, 83109771Sfjoe struct sockaddr *); 8489099Sfjoe 8589099Sfjoeu_int8_t arcbroadcastaddr = 0; 8689099Sfjoe 87110106Sfjoe#define ARC_LLADDR(ifp) (*(u_int8_t *)IF_LLADDR(ifp)) 88110106Sfjoe 8989099Sfjoe#define senderr(e) { error = (e); goto bad;} 90249925Sglebius#define SIN(s) ((const struct sockaddr_in *)(s)) 9189099Sfjoe 9289099Sfjoe/* 9389099Sfjoe * ARCnet output routine. 9489099Sfjoe * Encapsulate a packet of type family for the local net. 9589099Sfjoe * Assumes that ifp is actually pointer to arccom structure. 9689099Sfjoe */ 9789099Sfjoeint 98249925Sglebiusarc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 99191148Skmacy struct route *ro) 10089099Sfjoe{ 10189099Sfjoe struct arc_header *ah; 10289099Sfjoe int error; 10389099Sfjoe u_int8_t atype, adst; 104109771Sfjoe int loop_copy = 0; 105110106Sfjoe int isphds; 106287861Smelifaro#if defined(INET) || defined(INET6) 107287861Smelifaro int is_gw = 0; 108275211Sbz#endif 10989099Sfjoe 110148887Srwatson if (!((ifp->if_flags & IFF_UP) && 111148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING))) 11289099Sfjoe return(ENETDOWN); /* m, m1 aren't initialized yet */ 11389099Sfjoe 11489099Sfjoe error = 0; 115287861Smelifaro#if defined(INET) || defined(INET6) 116293544Smelifaro if (ro != NULL) 117293544Smelifaro is_gw = (ro->ro_flags & RT_HAS_GW) != 0; 118287861Smelifaro#endif 11989099Sfjoe 12089099Sfjoe switch (dst->sa_family) { 12189099Sfjoe#ifdef INET 12289099Sfjoe case AF_INET: 12389099Sfjoe 12489099Sfjoe /* 12589099Sfjoe * For now, use the simple IP addr -> ARCnet addr mapping 12689099Sfjoe */ 12789099Sfjoe if (m->m_flags & (M_BCAST|M_MCAST)) 12889099Sfjoe adst = arcbroadcastaddr; /* ARCnet broadcast address */ 12989099Sfjoe else if (ifp->if_flags & IFF_NOARP) 13089099Sfjoe adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 131128636Sluigi else { 132301217Sgnn error = arpresolve(ifp, is_gw, m, dst, &adst, NULL, 133301217Sgnn NULL); 134128636Sluigi if (error) 135128636Sluigi return (error == EWOULDBLOCK ? 0 : error); 136128636Sluigi } 13789099Sfjoe 13889099Sfjoe atype = (ifp->if_flags & IFF_LINK0) ? 13989099Sfjoe ARCTYPE_IP_OLD : ARCTYPE_IP; 14089099Sfjoe break; 141127260Smdodd case AF_ARP: 142127260Smdodd { 143127260Smdodd struct arphdr *ah; 144127260Smdodd ah = mtod(m, struct arphdr *); 145127260Smdodd ah->ar_hrd = htons(ARPHRD_ARCNET); 146127260Smdodd 147127260Smdodd loop_copy = -1; /* if this is for us, don't do it */ 148127260Smdodd 149127260Smdodd switch(ntohs(ah->ar_op)) { 150127260Smdodd case ARPOP_REVREQUEST: 151127260Smdodd case ARPOP_REVREPLY: 152127275Smdodd atype = ARCTYPE_REVARP; 153127260Smdodd break; 154127260Smdodd case ARPOP_REQUEST: 155127260Smdodd case ARPOP_REPLY: 156127260Smdodd default: 157127275Smdodd atype = ARCTYPE_ARP; 158127260Smdodd break; 159127260Smdodd } 160127260Smdodd 161127260Smdodd if (m->m_flags & M_BCAST) 162127290Smdodd bcopy(ifp->if_broadcastaddr, &adst, ARC_ADDR_LEN); 163127260Smdodd else 164127290Smdodd bcopy(ar_tha(ah), &adst, ARC_ADDR_LEN); 165127260Smdodd 166127260Smdodd } 167127260Smdodd break; 16889099Sfjoe#endif 16989099Sfjoe#ifdef INET6 17089099Sfjoe case AF_INET6: 171276896Smelifaro if ((m->m_flags & M_MCAST) != 0) 172276886Smelifaro adst = arcbroadcastaddr; /* ARCnet broadcast address */ 173287861Smelifaro else { 174301217Sgnn error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL, 175301217Sgnn NULL); 176287861Smelifaro if (error != 0) 177287861Smelifaro return (error == EWOULDBLOCK ? 0 : error); 178287861Smelifaro } 17989099Sfjoe atype = ARCTYPE_INET6; 18089099Sfjoe break; 18189099Sfjoe#endif 18289099Sfjoe case AF_UNSPEC: 183249925Sglebius { 184249925Sglebius const struct arc_header *ah; 185249925Sglebius 186109771Sfjoe loop_copy = -1; 187249925Sglebius ah = (const struct arc_header *)dst->sa_data; 18889099Sfjoe adst = ah->arc_dhost; 18989099Sfjoe atype = ah->arc_type; 19089099Sfjoe 19189099Sfjoe if (atype == ARCTYPE_ARP) { 19289099Sfjoe atype = (ifp->if_flags & IFF_LINK0) ? 19389099Sfjoe ARCTYPE_ARP_OLD: ARCTYPE_ARP; 19489099Sfjoe 19589099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 19689099Sfjoe /* 19789099Sfjoe * XXX It's not clear per RFC826 if this is needed, but 19889099Sfjoe * "assigned numbers" say this is wrong. 19989099Sfjoe * However, e.g., AmiTCP 3.0Beta used it... we make this 20089099Sfjoe * switchable for emergency cases. Not perfect, but... 20189099Sfjoe */ 20289099Sfjoe if (ifp->if_flags & IFF_LINK2) 203109771Sfjoe mtod(m, struct arphdr *)->ar_pro = atype - 1; 20489099Sfjoe#endif 20589099Sfjoe } 20689099Sfjoe break; 207249925Sglebius } 20889099Sfjoe default: 209105598Sbrooks if_printf(ifp, "can't handle af%d\n", dst->sa_family); 21089099Sfjoe senderr(EAFNOSUPPORT); 21189099Sfjoe } 21289099Sfjoe 213110106Sfjoe isphds = arc_isphds(atype); 214243882Sglebius M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_NOWAIT); 215298075Spfg if (m == NULL) 21689099Sfjoe senderr(ENOBUFS); 21789099Sfjoe ah = mtod(m, struct arc_header *); 21889099Sfjoe ah->arc_type = atype; 21989099Sfjoe ah->arc_dhost = adst; 220110106Sfjoe ah->arc_shost = ARC_LLADDR(ifp); 221110106Sfjoe if (isphds) { 222110106Sfjoe ah->arc_flag = 0; 223110106Sfjoe ah->arc_seqid = 0; 224110106Sfjoe } 22589099Sfjoe 226109771Sfjoe if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 227109771Sfjoe if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 228109771Sfjoe struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 229109771Sfjoe 230109771Sfjoe (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); 231109771Sfjoe } else if (ah->arc_dhost == ah->arc_shost) { 232109771Sfjoe (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); 233109771Sfjoe return (0); /* XXX */ 234109771Sfjoe } 235109771Sfjoe } 236109771Sfjoe 237106939Ssam BPF_MTAP(ifp, m); 23889099Sfjoe 239191605Skmacy error = ifp->if_transmit(ifp, m); 24089099Sfjoe 24189099Sfjoe return (error); 24289099Sfjoe 24389099Sfjoebad: 24489099Sfjoe if (m) 24589099Sfjoe m_freem(m); 24689099Sfjoe return (error); 24789099Sfjoe} 24889099Sfjoe 24989099Sfjoevoid 250157681Srwatsonarc_frag_init(struct ifnet *ifp) 25189099Sfjoe{ 25289099Sfjoe struct arccom *ac; 25389099Sfjoe 254147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 25589099Sfjoe ac->curr_frag = 0; 25689099Sfjoe} 25789099Sfjoe 25889099Sfjoestruct mbuf * 259157681Srwatsonarc_frag_next(struct ifnet *ifp) 26089099Sfjoe{ 26189099Sfjoe struct arccom *ac; 26289099Sfjoe struct mbuf *m; 26389099Sfjoe struct arc_header *ah; 26489099Sfjoe 265147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 266298075Spfg if ((m = ac->curr_frag) == NULL) { 26789099Sfjoe int tfrags; 26889099Sfjoe 26989099Sfjoe /* dequeue new packet */ 27089099Sfjoe IF_DEQUEUE(&ifp->if_snd, m); 271298075Spfg if (m == NULL) 27289099Sfjoe return 0; 27389099Sfjoe 27489099Sfjoe ah = mtod(m, struct arc_header *); 27589099Sfjoe if (!arc_isphds(ah->arc_type)) 27689099Sfjoe return m; 27789099Sfjoe 27889099Sfjoe ++ac->ac_seqid; /* make the seqid unique */ 279298649Spfg tfrags = howmany(m->m_pkthdr.len, ARC_MAX_DATA); 28089099Sfjoe ac->fsflag = 2 * tfrags - 3; 28189099Sfjoe ac->sflag = 0; 28289099Sfjoe ac->rsflag = ac->fsflag; 28389099Sfjoe ac->arc_dhost = ah->arc_dhost; 28489099Sfjoe ac->arc_shost = ah->arc_shost; 28589099Sfjoe ac->arc_type = ah->arc_type; 28689099Sfjoe 287110106Sfjoe m_adj(m, ARC_HDRNEWLEN); 28889099Sfjoe ac->curr_frag = m; 28989099Sfjoe } 29089099Sfjoe 29189099Sfjoe /* split out next fragment and return it */ 29289099Sfjoe if (ac->sflag < ac->fsflag) { 29389099Sfjoe /* we CAN'T have short packets here */ 294243882Sglebius ac->curr_frag = m_split(m, ARC_MAX_DATA, M_NOWAIT); 29589099Sfjoe if (ac->curr_frag == 0) { 29693750Sluigi m_freem(m); 29789099Sfjoe return 0; 29889099Sfjoe } 29989099Sfjoe 300243882Sglebius M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 301298075Spfg if (m == NULL) { 30293750Sluigi m_freem(ac->curr_frag); 30389099Sfjoe ac->curr_frag = 0; 30489099Sfjoe return 0; 30589099Sfjoe } 30689099Sfjoe 30789099Sfjoe ah = mtod(m, struct arc_header *); 30889099Sfjoe ah->arc_flag = ac->rsflag; 30989099Sfjoe ah->arc_seqid = ac->ac_seqid; 31089099Sfjoe 31189099Sfjoe ac->sflag += 2; 31289099Sfjoe ac->rsflag = ac->sflag; 31389099Sfjoe } else if ((m->m_pkthdr.len >= 31489099Sfjoe ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && 31589099Sfjoe (m->m_pkthdr.len <= 31689099Sfjoe ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { 31789099Sfjoe ac->curr_frag = 0; 31889099Sfjoe 319243882Sglebius M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_NOWAIT); 320298075Spfg if (m == NULL) 32189099Sfjoe return 0; 32289099Sfjoe 32389099Sfjoe ah = mtod(m, struct arc_header *); 32489099Sfjoe ah->arc_flag = 0xFF; 32589099Sfjoe ah->arc_seqid = 0xFFFF; 32689099Sfjoe ah->arc_type2 = ac->arc_type; 32789099Sfjoe ah->arc_flag2 = ac->sflag; 32889099Sfjoe ah->arc_seqid2 = ac->ac_seqid; 32989099Sfjoe } else { 33089099Sfjoe ac->curr_frag = 0; 33189099Sfjoe 332243882Sglebius M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 333298075Spfg if (m == NULL) 33489099Sfjoe return 0; 33589099Sfjoe 33689099Sfjoe ah = mtod(m, struct arc_header *); 33789099Sfjoe ah->arc_flag = ac->sflag; 33889099Sfjoe ah->arc_seqid = ac->ac_seqid; 33989099Sfjoe } 34089099Sfjoe 34189099Sfjoe ah->arc_dhost = ac->arc_dhost; 34289099Sfjoe ah->arc_shost = ac->arc_shost; 34389099Sfjoe ah->arc_type = ac->arc_type; 34489099Sfjoe 34589099Sfjoe return m; 34689099Sfjoe} 34789099Sfjoe 34889099Sfjoe/* 34989099Sfjoe * Defragmenter. Returns mbuf if last packet found, else 350298995Spfg * NULL. frees incoming mbuf as necessary. 35189099Sfjoe */ 35289099Sfjoe 353105228Sphkstatic __inline struct mbuf * 354157681Srwatsonarc_defrag(struct ifnet *ifp, struct mbuf *m) 35589099Sfjoe{ 35689099Sfjoe struct arc_header *ah, *ah1; 35789099Sfjoe struct arccom *ac; 35889099Sfjoe struct ac_frag *af; 35989099Sfjoe struct mbuf *m1; 36089099Sfjoe char *s; 36189099Sfjoe int newflen; 36289099Sfjoe u_char src,dst,typ; 36389099Sfjoe 364147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 36589099Sfjoe 36689099Sfjoe if (m->m_len < ARC_HDRNEWLEN) { 36789099Sfjoe m = m_pullup(m, ARC_HDRNEWLEN); 36889099Sfjoe if (m == NULL) { 369271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 37089099Sfjoe return NULL; 37189099Sfjoe } 37289099Sfjoe } 37389099Sfjoe 37489099Sfjoe ah = mtod(m, struct arc_header *); 37589099Sfjoe typ = ah->arc_type; 37689099Sfjoe 37789099Sfjoe if (!arc_isphds(typ)) 37889099Sfjoe return m; 37989099Sfjoe 38089099Sfjoe src = ah->arc_shost; 38189099Sfjoe dst = ah->arc_dhost; 38289099Sfjoe 38389099Sfjoe if (ah->arc_flag == 0xff) { 38489099Sfjoe m_adj(m, 4); 38589099Sfjoe 38689099Sfjoe if (m->m_len < ARC_HDRNEWLEN) { 38789099Sfjoe m = m_pullup(m, ARC_HDRNEWLEN); 38889099Sfjoe if (m == NULL) { 389271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 39089099Sfjoe return NULL; 39189099Sfjoe } 39289099Sfjoe } 39389099Sfjoe 39489099Sfjoe ah = mtod(m, struct arc_header *); 39589099Sfjoe } 39689099Sfjoe 39789099Sfjoe af = &ac->ac_fragtab[src]; 39889099Sfjoe m1 = af->af_packet; 39989099Sfjoe s = "debug code error"; 40089099Sfjoe 40189099Sfjoe if (ah->arc_flag & 1) { 40289099Sfjoe /* 40389099Sfjoe * first fragment. We always initialize, which is 40489099Sfjoe * about the right thing to do, as we only want to 40589099Sfjoe * accept one fragmented packet per src at a time. 40689099Sfjoe */ 40789099Sfjoe if (m1 != NULL) 40889099Sfjoe m_freem(m1); 40989099Sfjoe 41089099Sfjoe af->af_packet = m; 41189099Sfjoe m1 = m; 41289099Sfjoe af->af_maxflag = ah->arc_flag; 41389099Sfjoe af->af_lastseen = 0; 41489099Sfjoe af->af_seqid = ah->arc_seqid; 41589099Sfjoe 41689099Sfjoe return NULL; 41789099Sfjoe /* notreached */ 41889099Sfjoe } else { 41989099Sfjoe /* check for unfragmented packet */ 42089099Sfjoe if (ah->arc_flag == 0) 42189099Sfjoe return m; 42289099Sfjoe 42389099Sfjoe /* do we have a first packet from that src? */ 42489099Sfjoe if (m1 == NULL) { 42589099Sfjoe s = "no first frag"; 42689099Sfjoe goto outofseq; 42789099Sfjoe } 42889099Sfjoe 42989099Sfjoe ah1 = mtod(m1, struct arc_header *); 43089099Sfjoe 43189099Sfjoe if (ah->arc_seqid != ah1->arc_seqid) { 43289099Sfjoe s = "seqid differs"; 43389099Sfjoe goto outofseq; 43489099Sfjoe } 43589099Sfjoe 43689099Sfjoe if (typ != ah1->arc_type) { 43789099Sfjoe s = "type differs"; 43889099Sfjoe goto outofseq; 43989099Sfjoe } 44089099Sfjoe 44189099Sfjoe if (dst != ah1->arc_dhost) { 44289099Sfjoe s = "dest host differs"; 44389099Sfjoe goto outofseq; 44489099Sfjoe } 44589099Sfjoe 44689099Sfjoe /* typ, seqid and dst are ok here. */ 44789099Sfjoe 44889099Sfjoe if (ah->arc_flag == af->af_lastseen) { 44989099Sfjoe m_freem(m); 45089099Sfjoe return NULL; 45189099Sfjoe } 45289099Sfjoe 45389099Sfjoe if (ah->arc_flag == af->af_lastseen + 2) { 45489099Sfjoe /* ok, this is next fragment */ 45589099Sfjoe af->af_lastseen = ah->arc_flag; 45689099Sfjoe m_adj(m,ARC_HDRNEWLEN); 45789099Sfjoe 45889099Sfjoe /* 45989099Sfjoe * m_cat might free the first mbuf (with pkthdr) 46089099Sfjoe * in 2nd chain; therefore: 46189099Sfjoe */ 46289099Sfjoe 46389099Sfjoe newflen = m->m_pkthdr.len; 46489099Sfjoe 46589099Sfjoe m_cat(m1,m); 46689099Sfjoe 46789099Sfjoe m1->m_pkthdr.len += newflen; 46889099Sfjoe 46989099Sfjoe /* is it the last one? */ 47089099Sfjoe if (af->af_lastseen > af->af_maxflag) { 47189099Sfjoe af->af_packet = NULL; 47289099Sfjoe return(m1); 47389099Sfjoe } else 47489099Sfjoe return NULL; 47589099Sfjoe } 47689099Sfjoe s = "other reason"; 47789099Sfjoe /* if all else fails, it is out of sequence, too */ 47889099Sfjoe } 47989099Sfjoeoutofseq: 48089099Sfjoe if (m1) { 48189099Sfjoe m_freem(m1); 48289099Sfjoe af->af_packet = NULL; 48389099Sfjoe } 48489099Sfjoe 48589099Sfjoe if (m) 48689099Sfjoe m_freem(m); 48789099Sfjoe 488121816Sbrooks log(LOG_INFO,"%s: got out of seq. packet: %s\n", 489121816Sbrooks ifp->if_xname, s); 49089099Sfjoe 49189099Sfjoe return NULL; 49289099Sfjoe} 49389099Sfjoe 49489099Sfjoe/* 49589099Sfjoe * return 1 if Packet Header Definition Standard, else 0. 49689099Sfjoe * For now: old IP, old ARP aren't obviously. Lacking correct information, 49789099Sfjoe * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 49889099Sfjoe * (Apple and Novell corporations were involved, among others, in PHDS work). 49989099Sfjoe * Easiest is to assume that everybody else uses that, too. 50089099Sfjoe */ 50189099Sfjoeint 502157681Srwatsonarc_isphds(u_int8_t type) 50389099Sfjoe{ 50489099Sfjoe return (type != ARCTYPE_IP_OLD && 50589099Sfjoe type != ARCTYPE_ARP_OLD && 50689099Sfjoe type != ARCTYPE_DIAGNOSE); 50789099Sfjoe} 50889099Sfjoe 50989099Sfjoe/* 51089099Sfjoe * Process a received Arcnet packet; 51189099Sfjoe * the packet is in the mbuf chain m with 51289099Sfjoe * the ARCnet header. 51389099Sfjoe */ 51489099Sfjoevoid 515157681Srwatsonarc_input(struct ifnet *ifp, struct mbuf *m) 51689099Sfjoe{ 51789099Sfjoe struct arc_header *ah; 518111888Sjlemon int isr; 51989099Sfjoe u_int8_t atype; 52089099Sfjoe 52189099Sfjoe if ((ifp->if_flags & IFF_UP) == 0) { 52289099Sfjoe m_freem(m); 52389099Sfjoe return; 52489099Sfjoe } 52589099Sfjoe 52689099Sfjoe /* possibly defragment: */ 52789099Sfjoe m = arc_defrag(ifp, m); 52889099Sfjoe if (m == NULL) 52989099Sfjoe return; 53089099Sfjoe 531106939Ssam BPF_MTAP(ifp, m); 53289099Sfjoe 53389099Sfjoe ah = mtod(m, struct arc_header *); 534109771Sfjoe /* does this belong to us? */ 535110106Sfjoe if ((ifp->if_flags & IFF_PROMISC) == 0 536109771Sfjoe && ah->arc_dhost != arcbroadcastaddr 537110106Sfjoe && ah->arc_dhost != ARC_LLADDR(ifp)) { 538109771Sfjoe m_freem(m); 539109771Sfjoe return; 540109771Sfjoe } 54189099Sfjoe 542271867Sglebius if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); 54389099Sfjoe 544109771Sfjoe if (ah->arc_dhost == arcbroadcastaddr) { 54589099Sfjoe m->m_flags |= M_BCAST|M_MCAST; 546271867Sglebius if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); 54789099Sfjoe } 54889099Sfjoe 54989099Sfjoe atype = ah->arc_type; 55089099Sfjoe switch (atype) { 55189099Sfjoe#ifdef INET 55289099Sfjoe case ARCTYPE_IP: 55389099Sfjoe m_adj(m, ARC_HDRNEWLEN); 554111888Sjlemon isr = NETISR_IP; 55589099Sfjoe break; 55689099Sfjoe 55789099Sfjoe case ARCTYPE_IP_OLD: 55889099Sfjoe m_adj(m, ARC_HDRLEN); 559111888Sjlemon isr = NETISR_IP; 56089099Sfjoe break; 56189099Sfjoe 56289099Sfjoe case ARCTYPE_ARP: 56389099Sfjoe if (ifp->if_flags & IFF_NOARP) { 56489099Sfjoe /* Discard packet if ARP is disabled on interface */ 56589099Sfjoe m_freem(m); 56689099Sfjoe return; 56789099Sfjoe } 56889099Sfjoe m_adj(m, ARC_HDRNEWLEN); 569111888Sjlemon isr = NETISR_ARP; 57089099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 57189099Sfjoe mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 57289099Sfjoe#endif 57389099Sfjoe break; 57489099Sfjoe 57589099Sfjoe case ARCTYPE_ARP_OLD: 57689099Sfjoe if (ifp->if_flags & IFF_NOARP) { 57789099Sfjoe /* Discard packet if ARP is disabled on interface */ 57889099Sfjoe m_freem(m); 57989099Sfjoe return; 58089099Sfjoe } 58189099Sfjoe m_adj(m, ARC_HDRLEN); 582111888Sjlemon isr = NETISR_ARP; 58389099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 58489099Sfjoe mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 58589099Sfjoe#endif 58689099Sfjoe break; 58789099Sfjoe#endif 58889099Sfjoe#ifdef INET6 58989099Sfjoe case ARCTYPE_INET6: 59089099Sfjoe m_adj(m, ARC_HDRNEWLEN); 591111888Sjlemon isr = NETISR_IPV6; 59289099Sfjoe break; 59389099Sfjoe#endif 59489099Sfjoe default: 59589099Sfjoe m_freem(m); 59689099Sfjoe return; 59789099Sfjoe } 598223741Sbz M_SETFIB(m, ifp->if_fib); 599111888Sjlemon netisr_dispatch(isr, m); 60089099Sfjoe} 60189099Sfjoe 60289099Sfjoe/* 60389099Sfjoe * Register (new) link level address. 60489099Sfjoe */ 60589099Sfjoevoid 606157681Srwatsonarc_storelladdr(struct ifnet *ifp, u_int8_t lla) 60789099Sfjoe{ 608110106Sfjoe ARC_LLADDR(ifp) = lla; 60989099Sfjoe} 61089099Sfjoe 61189099Sfjoe/* 61289099Sfjoe * Perform common duties while attaching to interface list 61389099Sfjoe */ 61489099Sfjoevoid 615157681Srwatsonarc_ifattach(struct ifnet *ifp, u_int8_t lla) 61689099Sfjoe{ 61789099Sfjoe struct ifaddr *ifa; 61889099Sfjoe struct sockaddr_dl *sdl; 61989099Sfjoe struct arccom *ac; 62089099Sfjoe 62189099Sfjoe if_attach(ifp); 62289099Sfjoe ifp->if_addrlen = 1; 62389099Sfjoe ifp->if_hdrlen = ARC_HDRLEN; 62489099Sfjoe ifp->if_mtu = 1500; 625109771Sfjoe ifp->if_resolvemulti = arc_resolvemulti; 62689099Sfjoe if (ifp->if_baudrate == 0) 62789099Sfjoe ifp->if_baudrate = 2500000; 628152315Sru ifa = ifp->if_addr; 629135577Sstefanf KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); 63089099Sfjoe sdl = (struct sockaddr_dl *)ifa->ifa_addr; 63189099Sfjoe sdl->sdl_type = IFT_ARCNET; 63289099Sfjoe sdl->sdl_alen = ifp->if_addrlen; 63389099Sfjoe 63489099Sfjoe if (ifp->if_flags & IFF_BROADCAST) 63589099Sfjoe ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 63689099Sfjoe 637147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 63889099Sfjoe ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 63989099Sfjoe if (lla == 0) { 64089099Sfjoe /* XXX this message isn't entirely clear, to me -- cgd */ 641121816Sbrooks log(LOG_ERR,"%s: link address 0 reserved for broadcasts. Please change it and ifconfig %s down up\n", 642121816Sbrooks ifp->if_xname, ifp->if_xname); 64389099Sfjoe } 64489099Sfjoe arc_storelladdr(ifp, lla); 64589099Sfjoe 64689099Sfjoe ifp->if_broadcastaddr = &arcbroadcastaddr; 64789099Sfjoe 64889099Sfjoe bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 64989099Sfjoe} 65089099Sfjoe 65189099Sfjoevoid 652157681Srwatsonarc_ifdetach(struct ifnet *ifp) 65389099Sfjoe{ 65489099Sfjoe bpfdetach(ifp); 65589099Sfjoe if_detach(ifp); 65689099Sfjoe} 65789099Sfjoe 65889099Sfjoeint 659194581Srdivackyarc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 66089099Sfjoe{ 66189099Sfjoe struct ifaddr *ifa = (struct ifaddr *) data; 66289099Sfjoe struct ifreq *ifr = (struct ifreq *) data; 66389099Sfjoe int error = 0; 66489099Sfjoe 66589099Sfjoe switch (command) { 66689099Sfjoe case SIOCSIFADDR: 66789099Sfjoe ifp->if_flags |= IFF_UP; 66889099Sfjoe switch (ifa->ifa_addr->sa_family) { 66989099Sfjoe#ifdef INET 67089099Sfjoe case AF_INET: 67189099Sfjoe ifp->if_init(ifp->if_softc); /* before arpwhohas */ 67289099Sfjoe arp_ifinit(ifp, ifa); 67389099Sfjoe break; 67489099Sfjoe#endif 67589099Sfjoe default: 67689099Sfjoe ifp->if_init(ifp->if_softc); 67789099Sfjoe break; 67889099Sfjoe } 67989099Sfjoe break; 68089099Sfjoe 681109771Sfjoe case SIOCGIFADDR: 682332159Sbrooks ifr->ifr_addr.sa_data[0] = ARC_LLADDR(ifp); 683109771Sfjoe break; 684109771Sfjoe 68589099Sfjoe case SIOCADDMULTI: 68689099Sfjoe case SIOCDELMULTI: 68789099Sfjoe if (ifr == NULL) 68889099Sfjoe error = EAFNOSUPPORT; 68989099Sfjoe else { 69089099Sfjoe switch (ifr->ifr_addr.sa_family) { 69189099Sfjoe case AF_INET: 69289099Sfjoe case AF_INET6: 69389099Sfjoe error = 0; 69489099Sfjoe break; 69589099Sfjoe default: 69689099Sfjoe error = EAFNOSUPPORT; 69789099Sfjoe break; 69889099Sfjoe } 69989099Sfjoe } 70089099Sfjoe break; 70189099Sfjoe 70289099Sfjoe case SIOCSIFMTU: 70389099Sfjoe /* 70489099Sfjoe * Set the interface MTU. 70589099Sfjoe * mtu can't be larger than ARCMTU for RFC1051 70689099Sfjoe * and can't be larger than ARC_PHDS_MTU 70789099Sfjoe */ 70889099Sfjoe if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 70989099Sfjoe ifr->ifr_mtu > ARC_PHDS_MAXMTU) 71089099Sfjoe error = EINVAL; 71189099Sfjoe else 71289099Sfjoe ifp->if_mtu = ifr->ifr_mtu; 71389099Sfjoe break; 714109771Sfjoe } 71589099Sfjoe 716109771Sfjoe return (error); 717109771Sfjoe} 71889099Sfjoe 719109771Sfjoe/* based on ether_resolvemulti() */ 720109771Sfjoeint 721157681Srwatsonarc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 722157681Srwatson struct sockaddr *sa) 723109771Sfjoe{ 724109771Sfjoe struct sockaddr_dl *sdl; 725184680Sbz#ifdef INET 726109771Sfjoe struct sockaddr_in *sin; 727184680Sbz#endif 728109771Sfjoe#ifdef INET6 729109771Sfjoe struct sockaddr_in6 *sin6; 730109771Sfjoe#endif 731109771Sfjoe 732109771Sfjoe switch(sa->sa_family) { 733109771Sfjoe case AF_LINK: 734109771Sfjoe /* 735109771Sfjoe * No mapping needed. Just check that it's a valid MC address. 736109771Sfjoe */ 737109771Sfjoe sdl = (struct sockaddr_dl *)sa; 738109771Sfjoe if (*LLADDR(sdl) != arcbroadcastaddr) 739109771Sfjoe return EADDRNOTAVAIL; 740298075Spfg *llsa = NULL; 741109771Sfjoe return 0; 742109771Sfjoe#ifdef INET 743109771Sfjoe case AF_INET: 744109771Sfjoe sin = (struct sockaddr_in *)sa; 745109771Sfjoe if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 746109771Sfjoe return EADDRNOTAVAIL; 747260870Smelifaro sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); 748109771Sfjoe sdl->sdl_alen = ARC_ADDR_LEN; 749109771Sfjoe *LLADDR(sdl) = 0; 750109771Sfjoe *llsa = (struct sockaddr *)sdl; 751109771Sfjoe return 0; 752109771Sfjoe#endif 753109771Sfjoe#ifdef INET6 754109771Sfjoe case AF_INET6: 755109771Sfjoe sin6 = (struct sockaddr_in6 *)sa; 756109771Sfjoe if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 757109771Sfjoe /* 758109771Sfjoe * An IP6 address of 0 means listen to all 759109771Sfjoe * of the Ethernet multicast address used for IP6. 760109771Sfjoe * (This is used for multicast routers.) 761109771Sfjoe */ 762109771Sfjoe ifp->if_flags |= IFF_ALLMULTI; 763298075Spfg *llsa = NULL; 764109771Sfjoe return 0; 76589099Sfjoe } 766109771Sfjoe if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 767109771Sfjoe return EADDRNOTAVAIL; 768260870Smelifaro sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); 769109771Sfjoe sdl->sdl_alen = ARC_ADDR_LEN; 770109771Sfjoe *LLADDR(sdl) = 0; 771109771Sfjoe *llsa = (struct sockaddr *)sdl; 772109771Sfjoe return 0; 77389099Sfjoe#endif 774109771Sfjoe 775109771Sfjoe default: 776109771Sfjoe /* 777109771Sfjoe * Well, the text isn't quite right, but it's the name 778109771Sfjoe * that counts... 779109771Sfjoe */ 780109771Sfjoe return EAFNOSUPPORT; 78189099Sfjoe } 78289099Sfjoe} 783147256Sbrooks 784227293Sedstatic MALLOC_DEFINE(M_ARCCOM, "arccom", "ARCNET interface internals"); 785147256Sbrooks 786147256Sbrooksstatic void* 787147256Sbrooksarc_alloc(u_char type, struct ifnet *ifp) 788147256Sbrooks{ 789147256Sbrooks struct arccom *ac; 790147256Sbrooks 791147256Sbrooks ac = malloc(sizeof(struct arccom), M_ARCCOM, M_WAITOK | M_ZERO); 792147256Sbrooks ac->ac_ifp = ifp; 793147256Sbrooks 794147256Sbrooks return (ac); 795147256Sbrooks} 796147256Sbrooks 797147256Sbrooksstatic void 798147256Sbrooksarc_free(void *com, u_char type) 799147256Sbrooks{ 800147256Sbrooks 801147256Sbrooks free(com, M_ARCCOM); 802147256Sbrooks} 803147256Sbrooks 804147256Sbrooksstatic int 805147256Sbrooksarc_modevent(module_t mod, int type, void *data) 806147256Sbrooks{ 807147256Sbrooks 808147256Sbrooks switch (type) { 809147256Sbrooks case MOD_LOAD: 810147256Sbrooks if_register_com_alloc(IFT_ARCNET, arc_alloc, arc_free); 811147256Sbrooks break; 812147256Sbrooks case MOD_UNLOAD: 813147256Sbrooks if_deregister_com_alloc(IFT_ARCNET); 814147256Sbrooks break; 815147256Sbrooks default: 816147256Sbrooks return EOPNOTSUPP; 817147256Sbrooks } 818147256Sbrooks 819147256Sbrooks return (0); 820147256Sbrooks} 821147256Sbrooks 822147256Sbrooksstatic moduledata_t arc_mod = { 823147256Sbrooks "arcnet", 824147256Sbrooks arc_modevent, 825241394Skevlo 0 826147256Sbrooks}; 827147256Sbrooks 828147256SbrooksDECLARE_MODULE(arcnet, arc_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); 829147256SbrooksMODULE_VERSION(arcnet, 1); 830