if_arcsubr.c revision 93750
189099Sfjoe/* $NetBSD: if_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $ */ 289099Sfjoe/* $FreeBSD: head/sys/net/if_arcsubr.c 93750 2002-04-04 06:00:21Z luigi $ */ 389099Sfjoe 489099Sfjoe/* 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> 4789099Sfjoe#include <sys/malloc.h> 4889099Sfjoe#include <sys/mbuf.h> 4989099Sfjoe#include <sys/protosw.h> 5089099Sfjoe#include <sys/socket.h> 5189099Sfjoe#include <sys/sockio.h> 5289099Sfjoe#include <sys/errno.h> 5389099Sfjoe#include <sys/syslog.h> 5489099Sfjoe 5589099Sfjoe#include <machine/cpu.h> 5689099Sfjoe 5789099Sfjoe#include <net/if.h> 5889099Sfjoe#include <net/netisr.h> 5989099Sfjoe#include <net/route.h> 6089099Sfjoe#include <net/if_dl.h> 6189099Sfjoe#include <net/if_types.h> 6289099Sfjoe#include <net/if_arc.h> 6389099Sfjoe#include <net/if_arp.h> 6489099Sfjoe#include <net/bpf.h> 6589099Sfjoe 6689099Sfjoe#if defined(INET) || defined(INET6) 6789099Sfjoe#include <netinet/in.h> 6889099Sfjoe#include <netinet/in_var.h> 6989099Sfjoe#include <netinet/if_ether.h> 7089099Sfjoe#endif 7189099Sfjoe 7289099Sfjoe#ifdef INET6 7389099Sfjoe#include <netinet6/nd6.h> 7489099Sfjoe#endif 7589099Sfjoe 7689099SfjoeMODULE_VERSION(arcnet, 1); 7789099Sfjoe 7889099Sfjoe#define ARCNET_ALLOW_BROKEN_ARP 7989099Sfjoe 8092725Salfredstatic struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 8189099Sfjoe 8289099Sfjoeu_int8_t arcbroadcastaddr = 0; 8389099Sfjoe 8489099Sfjoe#define senderr(e) { error = (e); goto bad;} 8589099Sfjoe#define SIN(s) ((struct sockaddr_in *)s) 8689099Sfjoe 8789099Sfjoe/* 8889099Sfjoe * ARCnet output routine. 8989099Sfjoe * Encapsulate a packet of type family for the local net. 9089099Sfjoe * Assumes that ifp is actually pointer to arccom structure. 9189099Sfjoe */ 9289099Sfjoeint 9389099Sfjoearc_output(ifp, m, dst, rt0) 9489099Sfjoe struct ifnet *ifp; 9589099Sfjoe struct mbuf *m; 9689099Sfjoe struct sockaddr *dst; 9789099Sfjoe struct rtentry *rt0; 9889099Sfjoe{ 9989099Sfjoe struct mbuf *mcopy; 10089099Sfjoe struct rtentry *rt; 10189099Sfjoe struct arccom *ac; 10289099Sfjoe struct arc_header *ah; 10389099Sfjoe struct arphdr *arph; 10489099Sfjoe int error; 10589099Sfjoe u_int8_t atype, adst; 10689099Sfjoe#if __FreeBSD_version < 500000 10789099Sfjoe int s; 10889099Sfjoe#endif 10989099Sfjoe 11089099Sfjoe if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 11189099Sfjoe return(ENETDOWN); /* m, m1 aren't initialized yet */ 11289099Sfjoe 11389099Sfjoe error = 0; 11489099Sfjoe ac = (struct arccom *)ifp; 11589099Sfjoe mcopy = NULL; 11689099Sfjoe 11789099Sfjoe if ((rt = rt0)) { 11889099Sfjoe if ((rt->rt_flags & RTF_UP) == 0) { 11989099Sfjoe if ((rt0 = rt = rtalloc1(dst, 1, 0UL))) 12089099Sfjoe rt->rt_refcnt--; 12189099Sfjoe else 12289099Sfjoe senderr(EHOSTUNREACH); 12389099Sfjoe } 12489099Sfjoe if (rt->rt_flags & RTF_GATEWAY) { 12589099Sfjoe if (rt->rt_gwroute == 0) 12689099Sfjoe goto lookup; 12789099Sfjoe if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 12889099Sfjoe rtfree(rt); rt = rt0; 12989099Sfjoe lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL); 13089099Sfjoe if ((rt = rt->rt_gwroute) == 0) 13189099Sfjoe senderr(EHOSTUNREACH); 13289099Sfjoe } 13389099Sfjoe } 13489099Sfjoe if (rt->rt_flags & RTF_REJECT) 13589099Sfjoe if (rt->rt_rmx.rmx_expire == 0 || 13689099Sfjoe time_second < rt->rt_rmx.rmx_expire) 13789099Sfjoe senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 13889099Sfjoe } 13989099Sfjoe 14089099Sfjoe switch (dst->sa_family) { 14189099Sfjoe#ifdef INET 14289099Sfjoe case AF_INET: 14389099Sfjoe 14489099Sfjoe /* 14589099Sfjoe * For now, use the simple IP addr -> ARCnet addr mapping 14689099Sfjoe */ 14789099Sfjoe if (m->m_flags & (M_BCAST|M_MCAST)) 14889099Sfjoe adst = arcbroadcastaddr; /* ARCnet broadcast address */ 14989099Sfjoe else if (ifp->if_flags & IFF_NOARP) 15089099Sfjoe adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 15189099Sfjoe else if (!arpresolve(ifp, rt, m, dst, &adst, rt0)) 15289099Sfjoe return 0; /* not resolved yet */ 15389099Sfjoe 15489099Sfjoe /* If broadcasting on a simplex interface, loopback a copy */ 15589099Sfjoe if ((m->m_flags & (M_BCAST|M_MCAST)) && 15689099Sfjoe (ifp->if_flags & IFF_SIMPLEX)) 15789099Sfjoe mcopy = m_copy(m, 0, (int)M_COPYALL); 15889099Sfjoe atype = (ifp->if_flags & IFF_LINK0) ? 15989099Sfjoe ARCTYPE_IP_OLD : ARCTYPE_IP; 16089099Sfjoe break; 16189099Sfjoe#endif 16289099Sfjoe#ifdef INET6 16389099Sfjoe case AF_INET6: 16489099Sfjoe#ifdef OLDIP6OUTPUT 16589099Sfjoe if (!nd6_resolve(ifp, rt, m, dst, (u_char *)&adst)) 16689099Sfjoe return(0); /* if not yet resolves */ 16789099Sfjoe#else 16889099Sfjoe if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)&adst)) 16989099Sfjoe return(0); /* it must be impossible, but... */ 17089099Sfjoe#endif /* OLDIP6OUTPUT */ 17189099Sfjoe atype = ARCTYPE_INET6; 17289099Sfjoe break; 17389099Sfjoe#endif 17489099Sfjoe 17589099Sfjoe case AF_UNSPEC: 17689099Sfjoe ah = (struct arc_header *)dst->sa_data; 17789099Sfjoe adst = ah->arc_dhost; 17889099Sfjoe atype = ah->arc_type; 17989099Sfjoe 18089099Sfjoe if (atype == ARCTYPE_ARP) { 18189099Sfjoe atype = (ifp->if_flags & IFF_LINK0) ? 18289099Sfjoe ARCTYPE_ARP_OLD: ARCTYPE_ARP; 18389099Sfjoe 18489099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 18589099Sfjoe /* 18689099Sfjoe * XXX It's not clear per RFC826 if this is needed, but 18789099Sfjoe * "assigned numbers" say this is wrong. 18889099Sfjoe * However, e.g., AmiTCP 3.0Beta used it... we make this 18989099Sfjoe * switchable for emergency cases. Not perfect, but... 19089099Sfjoe */ 19189099Sfjoe arph = mtod(m, struct arphdr *); 19289099Sfjoe if (ifp->if_flags & IFF_LINK2) 19389099Sfjoe arph->ar_pro = atype - 1; 19489099Sfjoe#endif 19589099Sfjoe } 19689099Sfjoe break; 19789099Sfjoe 19889099Sfjoe default: 19989099Sfjoe printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 20089099Sfjoe dst->sa_family); 20189099Sfjoe senderr(EAFNOSUPPORT); 20289099Sfjoe } 20389099Sfjoe 20489099Sfjoe if (mcopy) 20589099Sfjoe (void) if_simloop(ifp, mcopy, dst->sa_family, 0); 20689099Sfjoe 20789099Sfjoe M_PREPEND(m, ARC_HDRLEN, M_DONTWAIT); 20889099Sfjoe if (m == 0) 20989099Sfjoe senderr(ENOBUFS); 21089099Sfjoe ah = mtod(m, struct arc_header *); 21189099Sfjoe ah->arc_type = atype; 21289099Sfjoe ah->arc_dhost = adst; 21389099Sfjoe ah->arc_shost = *IF_LLADDR(ifp); 21489099Sfjoe 21589099Sfjoe if (ifp->if_bpf) 21689099Sfjoe bpf_mtap(ifp, m); 21789099Sfjoe 21889099Sfjoe#if __FreeBSD_version < 500000 21989099Sfjoe s = splimp(); 22089099Sfjoe 22189099Sfjoe /* 22289099Sfjoe * Queue message on interface, and start output if interface 22389099Sfjoe * not yet active. 22489099Sfjoe */ 22589099Sfjoe if (IF_QFULL(&ifp->if_snd)) { 22689099Sfjoe IF_DROP(&ifp->if_snd); 22789099Sfjoe splx(s); 22889099Sfjoe senderr(ENOBUFS); 22989099Sfjoe } 23089099Sfjoe ifp->if_obytes += m->m_pkthdr.len; 23189099Sfjoe IF_ENQUEUE(&ifp->if_snd, m); 23289099Sfjoe if ((ifp->if_flags & IFF_OACTIVE) == 0) 23389099Sfjoe (*ifp->if_start)(ifp); 23489099Sfjoe splx(s); 23589099Sfjoe#else 23689099Sfjoe if (!IF_HANDOFF(&ifp->if_snd, m, ifp)) { 23789099Sfjoe m = 0; 23889099Sfjoe senderr(ENOBUFS); 23989099Sfjoe } 24089099Sfjoe#endif 24189099Sfjoe 24289099Sfjoe return (error); 24389099Sfjoe 24489099Sfjoebad: 24589099Sfjoe if (m) 24689099Sfjoe m_freem(m); 24789099Sfjoe return (error); 24889099Sfjoe} 24989099Sfjoe 25089099Sfjoevoid 25189099Sfjoearc_frag_init(ifp) 25289099Sfjoe struct ifnet *ifp; 25389099Sfjoe{ 25489099Sfjoe struct arccom *ac; 25589099Sfjoe 25689099Sfjoe ac = (struct arccom *)ifp; 25789099Sfjoe ac->curr_frag = 0; 25889099Sfjoe} 25989099Sfjoe 26089099Sfjoestruct mbuf * 26189099Sfjoearc_frag_next(ifp) 26289099Sfjoe struct ifnet *ifp; 26389099Sfjoe{ 26489099Sfjoe struct arccom *ac; 26589099Sfjoe struct mbuf *m; 26689099Sfjoe struct arc_header *ah; 26789099Sfjoe 26889099Sfjoe ac = (struct arccom *)ifp; 26989099Sfjoe if ((m = ac->curr_frag) == 0) { 27089099Sfjoe int tfrags; 27189099Sfjoe 27289099Sfjoe /* dequeue new packet */ 27389099Sfjoe IF_DEQUEUE(&ifp->if_snd, m); 27489099Sfjoe if (m == 0) 27589099Sfjoe return 0; 27689099Sfjoe 27789099Sfjoe ah = mtod(m, struct arc_header *); 27889099Sfjoe if (!arc_isphds(ah->arc_type)) 27989099Sfjoe return m; 28089099Sfjoe 28189099Sfjoe ++ac->ac_seqid; /* make the seqid unique */ 28289099Sfjoe tfrags = (m->m_pkthdr.len + 503) / 504; 28389099Sfjoe ac->fsflag = 2 * tfrags - 3; 28489099Sfjoe ac->sflag = 0; 28589099Sfjoe ac->rsflag = ac->fsflag; 28689099Sfjoe ac->arc_dhost = ah->arc_dhost; 28789099Sfjoe ac->arc_shost = ah->arc_shost; 28889099Sfjoe ac->arc_type = ah->arc_type; 28989099Sfjoe 29089099Sfjoe m_adj(m, ARC_HDRLEN); 29189099Sfjoe ac->curr_frag = m; 29289099Sfjoe } 29389099Sfjoe 29489099Sfjoe /* split out next fragment and return it */ 29589099Sfjoe if (ac->sflag < ac->fsflag) { 29689099Sfjoe /* we CAN'T have short packets here */ 29789099Sfjoe ac->curr_frag = m_split(m, 504, M_DONTWAIT); 29889099Sfjoe if (ac->curr_frag == 0) { 29993750Sluigi m_freem(m); 30089099Sfjoe return 0; 30189099Sfjoe } 30289099Sfjoe 30389099Sfjoe M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT); 30489099Sfjoe if (m == 0) { 30593750Sluigi m_freem(ac->curr_frag); 30689099Sfjoe ac->curr_frag = 0; 30789099Sfjoe 30889099Sfjoe return 0; 30989099Sfjoe } 31089099Sfjoe 31189099Sfjoe ah = mtod(m, struct arc_header *); 31289099Sfjoe ah->arc_flag = ac->rsflag; 31389099Sfjoe ah->arc_seqid = ac->ac_seqid; 31489099Sfjoe 31589099Sfjoe ac->sflag += 2; 31689099Sfjoe ac->rsflag = ac->sflag; 31789099Sfjoe } else if ((m->m_pkthdr.len >= 31889099Sfjoe ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && 31989099Sfjoe (m->m_pkthdr.len <= 32089099Sfjoe ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { 32189099Sfjoe ac->curr_frag = 0; 32289099Sfjoe 32389099Sfjoe M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_DONTWAIT); 32489099Sfjoe if (m == 0) 32589099Sfjoe return 0; 32689099Sfjoe 32789099Sfjoe ah = mtod(m, struct arc_header *); 32889099Sfjoe ah->arc_flag = 0xFF; 32989099Sfjoe ah->arc_seqid = 0xFFFF; 33089099Sfjoe ah->arc_type2 = ac->arc_type; 33189099Sfjoe ah->arc_flag2 = ac->sflag; 33289099Sfjoe ah->arc_seqid2 = ac->ac_seqid; 33389099Sfjoe } else { 33489099Sfjoe ac->curr_frag = 0; 33589099Sfjoe 33689099Sfjoe M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT); 33789099Sfjoe if (m == 0) 33889099Sfjoe return 0; 33989099Sfjoe 34089099Sfjoe ah = mtod(m, struct arc_header *); 34189099Sfjoe ah->arc_flag = ac->sflag; 34289099Sfjoe ah->arc_seqid = ac->ac_seqid; 34389099Sfjoe } 34489099Sfjoe 34589099Sfjoe ah->arc_dhost = ac->arc_dhost; 34689099Sfjoe ah->arc_shost = ac->arc_shost; 34789099Sfjoe ah->arc_type = ac->arc_type; 34889099Sfjoe 34989099Sfjoe return m; 35089099Sfjoe} 35189099Sfjoe 35289099Sfjoe/* 35389099Sfjoe * Defragmenter. Returns mbuf if last packet found, else 35489099Sfjoe * NULL. frees imcoming mbuf as necessary. 35589099Sfjoe */ 35689099Sfjoe 35789099Sfjoe__inline struct mbuf * 35889099Sfjoearc_defrag(ifp, m) 35989099Sfjoe struct ifnet *ifp; 36089099Sfjoe struct mbuf *m; 36189099Sfjoe{ 36289099Sfjoe struct arc_header *ah, *ah1; 36389099Sfjoe struct arccom *ac; 36489099Sfjoe struct ac_frag *af; 36589099Sfjoe struct mbuf *m1; 36689099Sfjoe char *s; 36789099Sfjoe int newflen; 36889099Sfjoe u_char src,dst,typ; 36989099Sfjoe 37089099Sfjoe ac = (struct arccom *)ifp; 37189099Sfjoe 37289099Sfjoe if (m->m_len < ARC_HDRNEWLEN) { 37389099Sfjoe m = m_pullup(m, ARC_HDRNEWLEN); 37489099Sfjoe if (m == NULL) { 37589099Sfjoe ++ifp->if_ierrors; 37689099Sfjoe return NULL; 37789099Sfjoe } 37889099Sfjoe } 37989099Sfjoe 38089099Sfjoe ah = mtod(m, struct arc_header *); 38189099Sfjoe typ = ah->arc_type; 38289099Sfjoe 38389099Sfjoe if (!arc_isphds(typ)) 38489099Sfjoe return m; 38589099Sfjoe 38689099Sfjoe src = ah->arc_shost; 38789099Sfjoe dst = ah->arc_dhost; 38889099Sfjoe 38989099Sfjoe if (ah->arc_flag == 0xff) { 39089099Sfjoe m_adj(m, 4); 39189099Sfjoe 39289099Sfjoe if (m->m_len < ARC_HDRNEWLEN) { 39389099Sfjoe m = m_pullup(m, ARC_HDRNEWLEN); 39489099Sfjoe if (m == NULL) { 39589099Sfjoe ++ifp->if_ierrors; 39689099Sfjoe return NULL; 39789099Sfjoe } 39889099Sfjoe } 39989099Sfjoe 40089099Sfjoe ah = mtod(m, struct arc_header *); 40189099Sfjoe } 40289099Sfjoe 40389099Sfjoe af = &ac->ac_fragtab[src]; 40489099Sfjoe m1 = af->af_packet; 40589099Sfjoe s = "debug code error"; 40689099Sfjoe 40789099Sfjoe if (ah->arc_flag & 1) { 40889099Sfjoe /* 40989099Sfjoe * first fragment. We always initialize, which is 41089099Sfjoe * about the right thing to do, as we only want to 41189099Sfjoe * accept one fragmented packet per src at a time. 41289099Sfjoe */ 41389099Sfjoe if (m1 != NULL) 41489099Sfjoe m_freem(m1); 41589099Sfjoe 41689099Sfjoe af->af_packet = m; 41789099Sfjoe m1 = m; 41889099Sfjoe af->af_maxflag = ah->arc_flag; 41989099Sfjoe af->af_lastseen = 0; 42089099Sfjoe af->af_seqid = ah->arc_seqid; 42189099Sfjoe 42289099Sfjoe return NULL; 42389099Sfjoe /* notreached */ 42489099Sfjoe } else { 42589099Sfjoe /* check for unfragmented packet */ 42689099Sfjoe if (ah->arc_flag == 0) 42789099Sfjoe return m; 42889099Sfjoe 42989099Sfjoe /* do we have a first packet from that src? */ 43089099Sfjoe if (m1 == NULL) { 43189099Sfjoe s = "no first frag"; 43289099Sfjoe goto outofseq; 43389099Sfjoe } 43489099Sfjoe 43589099Sfjoe ah1 = mtod(m1, struct arc_header *); 43689099Sfjoe 43789099Sfjoe if (ah->arc_seqid != ah1->arc_seqid) { 43889099Sfjoe s = "seqid differs"; 43989099Sfjoe goto outofseq; 44089099Sfjoe } 44189099Sfjoe 44289099Sfjoe if (typ != ah1->arc_type) { 44389099Sfjoe s = "type differs"; 44489099Sfjoe goto outofseq; 44589099Sfjoe } 44689099Sfjoe 44789099Sfjoe if (dst != ah1->arc_dhost) { 44889099Sfjoe s = "dest host differs"; 44989099Sfjoe goto outofseq; 45089099Sfjoe } 45189099Sfjoe 45289099Sfjoe /* typ, seqid and dst are ok here. */ 45389099Sfjoe 45489099Sfjoe if (ah->arc_flag == af->af_lastseen) { 45589099Sfjoe m_freem(m); 45689099Sfjoe return NULL; 45789099Sfjoe } 45889099Sfjoe 45989099Sfjoe if (ah->arc_flag == af->af_lastseen + 2) { 46089099Sfjoe /* ok, this is next fragment */ 46189099Sfjoe af->af_lastseen = ah->arc_flag; 46289099Sfjoe m_adj(m,ARC_HDRNEWLEN); 46389099Sfjoe 46489099Sfjoe /* 46589099Sfjoe * m_cat might free the first mbuf (with pkthdr) 46689099Sfjoe * in 2nd chain; therefore: 46789099Sfjoe */ 46889099Sfjoe 46989099Sfjoe newflen = m->m_pkthdr.len; 47089099Sfjoe 47189099Sfjoe m_cat(m1,m); 47289099Sfjoe 47389099Sfjoe m1->m_pkthdr.len += newflen; 47489099Sfjoe 47589099Sfjoe /* is it the last one? */ 47689099Sfjoe if (af->af_lastseen > af->af_maxflag) { 47789099Sfjoe af->af_packet = NULL; 47889099Sfjoe return(m1); 47989099Sfjoe } else 48089099Sfjoe return NULL; 48189099Sfjoe } 48289099Sfjoe s = "other reason"; 48389099Sfjoe /* if all else fails, it is out of sequence, too */ 48489099Sfjoe } 48589099Sfjoeoutofseq: 48689099Sfjoe if (m1) { 48789099Sfjoe m_freem(m1); 48889099Sfjoe af->af_packet = NULL; 48989099Sfjoe } 49089099Sfjoe 49189099Sfjoe if (m) 49289099Sfjoe m_freem(m); 49389099Sfjoe 49489099Sfjoe log(LOG_INFO,"%s%d: got out of seq. packet: %s\n", 49589099Sfjoe ifp->if_name, ifp->if_unit, s); 49689099Sfjoe 49789099Sfjoe return NULL; 49889099Sfjoe} 49989099Sfjoe 50089099Sfjoe/* 50189099Sfjoe * return 1 if Packet Header Definition Standard, else 0. 50289099Sfjoe * For now: old IP, old ARP aren't obviously. Lacking correct information, 50389099Sfjoe * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 50489099Sfjoe * (Apple and Novell corporations were involved, among others, in PHDS work). 50589099Sfjoe * Easiest is to assume that everybody else uses that, too. 50689099Sfjoe */ 50789099Sfjoeint 50889099Sfjoearc_isphds(type) 50989099Sfjoe u_int8_t type; 51089099Sfjoe{ 51189099Sfjoe return (type != ARCTYPE_IP_OLD && 51289099Sfjoe type != ARCTYPE_ARP_OLD && 51389099Sfjoe type != ARCTYPE_DIAGNOSE); 51489099Sfjoe} 51589099Sfjoe 51689099Sfjoe/* 51789099Sfjoe * Process a received Arcnet packet; 51889099Sfjoe * the packet is in the mbuf chain m with 51989099Sfjoe * the ARCnet header. 52089099Sfjoe */ 52189099Sfjoevoid 52289099Sfjoearc_input(ifp, m) 52389099Sfjoe struct ifnet *ifp; 52489099Sfjoe struct mbuf *m; 52589099Sfjoe{ 52689099Sfjoe struct arc_header *ah; 52789099Sfjoe struct ifqueue *inq; 52889099Sfjoe u_int8_t atype; 52989099Sfjoe#ifdef INET 53089099Sfjoe struct arphdr *arph; 53189099Sfjoe#endif 53289099Sfjoe#if __FreeBSD_version < 500000 53389099Sfjoe int s; 53489099Sfjoe#endif 53589099Sfjoe 53689099Sfjoe if ((ifp->if_flags & IFF_UP) == 0) { 53789099Sfjoe m_freem(m); 53889099Sfjoe return; 53989099Sfjoe } 54089099Sfjoe 54189099Sfjoe /* possibly defragment: */ 54289099Sfjoe m = arc_defrag(ifp, m); 54389099Sfjoe if (m == NULL) 54489099Sfjoe return; 54589099Sfjoe 54689099Sfjoe if (ifp->if_bpf) 54789099Sfjoe bpf_mtap(ifp, m); 54889099Sfjoe 54989099Sfjoe ah = mtod(m, struct arc_header *); 55089099Sfjoe 55189099Sfjoe ifp->if_ibytes += m->m_pkthdr.len; 55289099Sfjoe 55389099Sfjoe if (arcbroadcastaddr == ah->arc_dhost) { 55489099Sfjoe m->m_flags |= M_BCAST|M_MCAST; 55589099Sfjoe ifp->if_imcasts++; 55689099Sfjoe } 55789099Sfjoe 55889099Sfjoe atype = ah->arc_type; 55989099Sfjoe switch (atype) { 56089099Sfjoe#ifdef INET 56189099Sfjoe case ARCTYPE_IP: 56289099Sfjoe m_adj(m, ARC_HDRNEWLEN); 56389099Sfjoe schednetisr(NETISR_IP); 56489099Sfjoe inq = &ipintrq; 56589099Sfjoe break; 56689099Sfjoe 56789099Sfjoe case ARCTYPE_IP_OLD: 56889099Sfjoe m_adj(m, ARC_HDRLEN); 56989099Sfjoe schednetisr(NETISR_IP); 57089099Sfjoe inq = &ipintrq; 57189099Sfjoe break; 57289099Sfjoe 57389099Sfjoe case ARCTYPE_ARP: 57489099Sfjoe if (ifp->if_flags & IFF_NOARP) { 57589099Sfjoe /* Discard packet if ARP is disabled on interface */ 57689099Sfjoe m_freem(m); 57789099Sfjoe return; 57889099Sfjoe } 57989099Sfjoe m_adj(m, ARC_HDRNEWLEN); 58089099Sfjoe schednetisr(NETISR_ARP); 58189099Sfjoe inq = &arpintrq; 58289099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 58389099Sfjoe mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 58489099Sfjoe#endif 58589099Sfjoe break; 58689099Sfjoe 58789099Sfjoe case ARCTYPE_ARP_OLD: 58889099Sfjoe if (ifp->if_flags & IFF_NOARP) { 58989099Sfjoe /* Discard packet if ARP is disabled on interface */ 59089099Sfjoe m_freem(m); 59189099Sfjoe return; 59289099Sfjoe } 59389099Sfjoe m_adj(m, ARC_HDRLEN); 59489099Sfjoe schednetisr(NETISR_ARP); 59589099Sfjoe inq = &arpintrq; 59689099Sfjoe arph = mtod(m, struct arphdr *); 59789099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 59889099Sfjoe mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 59989099Sfjoe#endif 60089099Sfjoe break; 60189099Sfjoe#endif 60289099Sfjoe#ifdef INET6 60389099Sfjoe case ARCTYPE_INET6: 60489099Sfjoe m_adj(m, ARC_HDRNEWLEN); 60589099Sfjoe schednetisr(NETISR_IPV6); 60689099Sfjoe inq = &ip6intrq; 60789099Sfjoe break; 60889099Sfjoe#endif 60989099Sfjoe default: 61089099Sfjoe m_freem(m); 61189099Sfjoe return; 61289099Sfjoe } 61389099Sfjoe 61489099Sfjoe#if __FreeBSD_version < 500000 61589099Sfjoe s = splimp(); 61689099Sfjoe if (IF_QFULL(inq)) { 61789099Sfjoe IF_DROP(inq); 61889099Sfjoe m_freem(m); 61989099Sfjoe } else 62089099Sfjoe IF_ENQUEUE(inq, m); 62189099Sfjoe splx(s); 62289099Sfjoe#else 62389099Sfjoe IF_HANDOFF(inq, m, NULL); 62489099Sfjoe#endif 62589099Sfjoe} 62689099Sfjoe 62789099Sfjoe/* 62889099Sfjoe * Convert Arcnet address to printable (loggable) representation. 62989099Sfjoe */ 63089099Sfjoestatic char digits[] = "0123456789abcdef"; 63189099Sfjoechar * 63289099Sfjoearc_sprintf(ap) 63389099Sfjoe u_int8_t *ap; 63489099Sfjoe{ 63589099Sfjoe static char arcbuf[3]; 63689099Sfjoe char *cp = arcbuf; 63789099Sfjoe 63889099Sfjoe *cp++ = digits[*ap >> 4]; 63989099Sfjoe *cp++ = digits[*ap++ & 0xf]; 64089099Sfjoe *cp = 0; 64189099Sfjoe return (arcbuf); 64289099Sfjoe} 64389099Sfjoe 64489099Sfjoe/* 64589099Sfjoe * Register (new) link level address. 64689099Sfjoe */ 64789099Sfjoevoid 64889099Sfjoearc_storelladdr(ifp, lla) 64989099Sfjoe struct ifnet *ifp; 65089099Sfjoe u_int8_t lla; 65189099Sfjoe{ 65289099Sfjoe *IF_LLADDR(ifp) = lla; 65389099Sfjoe} 65489099Sfjoe 65589099Sfjoe/* 65689099Sfjoe * Perform common duties while attaching to interface list 65789099Sfjoe */ 65889099Sfjoevoid 65989099Sfjoearc_ifattach(ifp, lla) 66089099Sfjoe struct ifnet *ifp; 66189099Sfjoe u_int8_t lla; 66289099Sfjoe{ 66389099Sfjoe struct ifaddr *ifa; 66489099Sfjoe struct sockaddr_dl *sdl; 66589099Sfjoe struct arccom *ac; 66689099Sfjoe 66789099Sfjoe if_attach(ifp); 66889099Sfjoe ifp->if_type = IFT_ARCNET; 66989099Sfjoe ifp->if_addrlen = 1; 67089099Sfjoe ifp->if_hdrlen = ARC_HDRLEN; 67189099Sfjoe ifp->if_mtu = 1500; 67289099Sfjoe if (ifp->if_baudrate == 0) 67389099Sfjoe ifp->if_baudrate = 2500000; 67489099Sfjoe#if __FreeBSD_version < 500000 67589099Sfjoe ifa = ifnet_addrs[ifp->if_index - 1]; 67689099Sfjoe#else 67789099Sfjoe ifa = ifaddr_byindex(ifp->if_index); 67889099Sfjoe#endif 67989099Sfjoe KASSERT(ifa != NULL, ("%s: no lladdr!\n", __FUNCTION__)); 68089099Sfjoe sdl = (struct sockaddr_dl *)ifa->ifa_addr; 68189099Sfjoe sdl->sdl_type = IFT_ARCNET; 68289099Sfjoe sdl->sdl_alen = ifp->if_addrlen; 68389099Sfjoe 68489099Sfjoe if (ifp->if_flags & IFF_BROADCAST) 68589099Sfjoe ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 68689099Sfjoe 68789099Sfjoe ac = (struct arccom *)ifp; 68889099Sfjoe ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 68989099Sfjoe if (lla == 0) { 69089099Sfjoe /* XXX this message isn't entirely clear, to me -- cgd */ 69189099Sfjoe log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts. Please change it and ifconfig %s%d down up\n", 69289099Sfjoe ifp->if_name, ifp->if_unit, ifp->if_name, ifp->if_unit); 69389099Sfjoe } 69489099Sfjoe arc_storelladdr(ifp, lla); 69589099Sfjoe 69689099Sfjoe ifp->if_broadcastaddr = &arcbroadcastaddr; 69789099Sfjoe 69889099Sfjoe bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 69989099Sfjoe} 70089099Sfjoe 70189099Sfjoevoid 70289099Sfjoearc_ifdetach(ifp) 70389099Sfjoe struct ifnet *ifp; 70489099Sfjoe{ 70589099Sfjoe bpfdetach(ifp); 70689099Sfjoe if_detach(ifp); 70789099Sfjoe} 70889099Sfjoe 70989099Sfjoeint 71089099Sfjoearc_ioctl(ifp, command, data) 71189099Sfjoe struct ifnet *ifp; 71289099Sfjoe int command; 71389099Sfjoe caddr_t data; 71489099Sfjoe{ 71589099Sfjoe struct ifaddr *ifa = (struct ifaddr *) data; 71689099Sfjoe struct ifreq *ifr = (struct ifreq *) data; 71789099Sfjoe int error = 0; 71889099Sfjoe 71989099Sfjoe switch (command) { 72089099Sfjoe case SIOCSIFADDR: 72189099Sfjoe ifp->if_flags |= IFF_UP; 72289099Sfjoe switch (ifa->ifa_addr->sa_family) { 72389099Sfjoe#ifdef INET 72489099Sfjoe case AF_INET: 72589099Sfjoe ifp->if_init(ifp->if_softc); /* before arpwhohas */ 72689099Sfjoe arp_ifinit(ifp, ifa); 72789099Sfjoe break; 72889099Sfjoe#endif 72989099Sfjoe default: 73089099Sfjoe ifp->if_init(ifp->if_softc); 73189099Sfjoe break; 73289099Sfjoe } 73389099Sfjoe break; 73489099Sfjoe 73589099Sfjoe case SIOCADDMULTI: 73689099Sfjoe case SIOCDELMULTI: 73789099Sfjoe if (ifr == NULL) 73889099Sfjoe error = EAFNOSUPPORT; 73989099Sfjoe else { 74089099Sfjoe switch (ifr->ifr_addr.sa_family) { 74189099Sfjoe case AF_INET: 74289099Sfjoe case AF_INET6: 74389099Sfjoe error = 0; 74489099Sfjoe break; 74589099Sfjoe default: 74689099Sfjoe error = EAFNOSUPPORT; 74789099Sfjoe break; 74889099Sfjoe } 74989099Sfjoe } 75089099Sfjoe break; 75189099Sfjoe 75289099Sfjoe case SIOCSIFMTU: 75389099Sfjoe /* 75489099Sfjoe * Set the interface MTU. 75589099Sfjoe * mtu can't be larger than ARCMTU for RFC1051 75689099Sfjoe * and can't be larger than ARC_PHDS_MTU 75789099Sfjoe */ 75889099Sfjoe if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 75989099Sfjoe ifr->ifr_mtu > ARC_PHDS_MAXMTU) 76089099Sfjoe error = EINVAL; 76189099Sfjoe else 76289099Sfjoe ifp->if_mtu = ifr->ifr_mtu; 76389099Sfjoe break; 76489099Sfjoe 76589099Sfjoe#if 0 76689099Sfjoe case SIOCGIFADDR: 76789099Sfjoe { 76889099Sfjoe struct sockaddr *sa; 76989099Sfjoe 77089099Sfjoe sa = (struct sockaddr *) & ifr->ifr_data; 77189099Sfjoe bcopy(IFP2AC(ifp)->ac_enaddr, 77289099Sfjoe (caddr_t) sa->sa_data, ETHER_ADDR_LEN); 77389099Sfjoe } 77489099Sfjoe break; 77589099Sfjoe#endif 77689099Sfjoe } 77789099Sfjoe 77889099Sfjoe return (error); 77989099Sfjoe} 780