189099Sfjoe/* $NetBSD: if_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $ */ 289099Sfjoe/* $FreeBSD$ */ 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" 43109771Sfjoe#include "opt_ipx.h" 4489099Sfjoe 4589099Sfjoe#include <sys/param.h> 4689099Sfjoe#include <sys/systm.h> 4789099Sfjoe#include <sys/kernel.h> 48129880Sphk#include <sys/module.h> 4989099Sfjoe#include <sys/malloc.h> 5089099Sfjoe#include <sys/mbuf.h> 5189099Sfjoe#include <sys/protosw.h> 5289099Sfjoe#include <sys/socket.h> 5389099Sfjoe#include <sys/sockio.h> 5489099Sfjoe#include <sys/errno.h> 5589099Sfjoe#include <sys/syslog.h> 5689099Sfjoe 5789099Sfjoe#include <machine/cpu.h> 5889099Sfjoe 5989099Sfjoe#include <net/if.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 79109771Sfjoe#ifdef IPX 80109771Sfjoe#include <netipx/ipx.h> 81109771Sfjoe#include <netipx/ipx_if.h> 82109771Sfjoe#endif 83109771Sfjoe 8489099Sfjoe#define ARCNET_ALLOW_BROKEN_ARP 8589099Sfjoe 8692725Salfredstatic struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 87109771Sfjoestatic int arc_resolvemulti(struct ifnet *, struct sockaddr **, 88109771Sfjoe struct sockaddr *); 8989099Sfjoe 9089099Sfjoeu_int8_t arcbroadcastaddr = 0; 9189099Sfjoe 92110106Sfjoe#define ARC_LLADDR(ifp) (*(u_int8_t *)IF_LLADDR(ifp)) 93110106Sfjoe 9489099Sfjoe#define senderr(e) { error = (e); goto bad;} 95109771Sfjoe#define SIN(s) ((struct sockaddr_in *)s) 96109771Sfjoe#define SIPX(s) ((struct sockaddr_ipx *)s) 9789099Sfjoe 9889099Sfjoe/* 9989099Sfjoe * ARCnet output routine. 10089099Sfjoe * Encapsulate a packet of type family for the local net. 10189099Sfjoe * Assumes that ifp is actually pointer to arccom structure. 10289099Sfjoe */ 10389099Sfjoeint 104157681Srwatsonarc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 105191148Skmacy struct route *ro) 10689099Sfjoe{ 10789099Sfjoe struct arc_header *ah; 10889099Sfjoe int error; 10989099Sfjoe u_int8_t atype, adst; 110109771Sfjoe int loop_copy = 0; 111110106Sfjoe int isphds; 112193891Sbz#if defined(INET) || defined(INET6) 113186119Sqingli struct llentry *lle; 114193891Sbz#endif 11589099Sfjoe 116148887Srwatson if (!((ifp->if_flags & IFF_UP) && 117148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING))) 11889099Sfjoe return(ENETDOWN); /* m, m1 aren't initialized yet */ 11989099Sfjoe 12089099Sfjoe error = 0; 12189099Sfjoe 12289099Sfjoe switch (dst->sa_family) { 12389099Sfjoe#ifdef INET 12489099Sfjoe case AF_INET: 12589099Sfjoe 12689099Sfjoe /* 12789099Sfjoe * For now, use the simple IP addr -> ARCnet addr mapping 12889099Sfjoe */ 12989099Sfjoe if (m->m_flags & (M_BCAST|M_MCAST)) 13089099Sfjoe adst = arcbroadcastaddr; /* ARCnet broadcast address */ 13189099Sfjoe else if (ifp->if_flags & IFF_NOARP) 13289099Sfjoe adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 133128636Sluigi else { 134191148Skmacy error = arpresolve(ifp, ro ? ro->ro_rt : NULL, 135191148Skmacy m, dst, &adst, &lle); 136128636Sluigi if (error) 137128636Sluigi return (error == EWOULDBLOCK ? 0 : error); 138128636Sluigi } 13989099Sfjoe 14089099Sfjoe atype = (ifp->if_flags & IFF_LINK0) ? 14189099Sfjoe ARCTYPE_IP_OLD : ARCTYPE_IP; 14289099Sfjoe break; 143127260Smdodd case AF_ARP: 144127260Smdodd { 145127260Smdodd struct arphdr *ah; 146127260Smdodd ah = mtod(m, struct arphdr *); 147127260Smdodd ah->ar_hrd = htons(ARPHRD_ARCNET); 148127260Smdodd 149127260Smdodd loop_copy = -1; /* if this is for us, don't do it */ 150127260Smdodd 151127260Smdodd switch(ntohs(ah->ar_op)) { 152127260Smdodd case ARPOP_REVREQUEST: 153127260Smdodd case ARPOP_REVREPLY: 154127275Smdodd atype = ARCTYPE_REVARP; 155127260Smdodd break; 156127260Smdodd case ARPOP_REQUEST: 157127260Smdodd case ARPOP_REPLY: 158127260Smdodd default: 159127275Smdodd atype = ARCTYPE_ARP; 160127260Smdodd break; 161127260Smdodd } 162127260Smdodd 163127260Smdodd if (m->m_flags & M_BCAST) 164127290Smdodd bcopy(ifp->if_broadcastaddr, &adst, ARC_ADDR_LEN); 165127260Smdodd else 166127290Smdodd bcopy(ar_tha(ah), &adst, ARC_ADDR_LEN); 167127260Smdodd 168127260Smdodd } 169127260Smdodd break; 17089099Sfjoe#endif 17189099Sfjoe#ifdef INET6 17289099Sfjoe case AF_INET6: 173186217Sqingli error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, &lle); 174128636Sluigi if (error) 175128636Sluigi return (error); 17689099Sfjoe atype = ARCTYPE_INET6; 17789099Sfjoe break; 17889099Sfjoe#endif 179109771Sfjoe#ifdef IPX 180109771Sfjoe case AF_IPX: 181109771Sfjoe adst = SIPX(dst)->sipx_addr.x_host.c_host[5]; 182109771Sfjoe atype = ARCTYPE_IPX; 183109771Sfjoe if (adst == 0xff) 184109771Sfjoe adst = arcbroadcastaddr; 185109771Sfjoe break; 186109771Sfjoe#endif 18789099Sfjoe 18889099Sfjoe case AF_UNSPEC: 189109771Sfjoe loop_copy = -1; 19089099Sfjoe ah = (struct arc_header *)dst->sa_data; 19189099Sfjoe adst = ah->arc_dhost; 19289099Sfjoe atype = ah->arc_type; 19389099Sfjoe 19489099Sfjoe if (atype == ARCTYPE_ARP) { 19589099Sfjoe atype = (ifp->if_flags & IFF_LINK0) ? 19689099Sfjoe ARCTYPE_ARP_OLD: ARCTYPE_ARP; 19789099Sfjoe 19889099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 19989099Sfjoe /* 20089099Sfjoe * XXX It's not clear per RFC826 if this is needed, but 20189099Sfjoe * "assigned numbers" say this is wrong. 20289099Sfjoe * However, e.g., AmiTCP 3.0Beta used it... we make this 20389099Sfjoe * switchable for emergency cases. Not perfect, but... 20489099Sfjoe */ 20589099Sfjoe if (ifp->if_flags & IFF_LINK2) 206109771Sfjoe mtod(m, struct arphdr *)->ar_pro = atype - 1; 20789099Sfjoe#endif 20889099Sfjoe } 20989099Sfjoe break; 21089099Sfjoe 21189099Sfjoe default: 212105598Sbrooks if_printf(ifp, "can't handle af%d\n", dst->sa_family); 21389099Sfjoe senderr(EAFNOSUPPORT); 21489099Sfjoe } 21589099Sfjoe 216110106Sfjoe isphds = arc_isphds(atype); 217111119Simp M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_DONTWAIT); 21889099Sfjoe if (m == 0) 21989099Sfjoe senderr(ENOBUFS); 22089099Sfjoe ah = mtod(m, struct arc_header *); 22189099Sfjoe ah->arc_type = atype; 22289099Sfjoe ah->arc_dhost = adst; 223110106Sfjoe ah->arc_shost = ARC_LLADDR(ifp); 224110106Sfjoe if (isphds) { 225110106Sfjoe ah->arc_flag = 0; 226110106Sfjoe ah->arc_seqid = 0; 227110106Sfjoe } 22889099Sfjoe 229109771Sfjoe if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 230109771Sfjoe if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 231109771Sfjoe struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 232109771Sfjoe 233109771Sfjoe (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); 234109771Sfjoe } else if (ah->arc_dhost == ah->arc_shost) { 235109771Sfjoe (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); 236109771Sfjoe return (0); /* XXX */ 237109771Sfjoe } 238109771Sfjoe } 239109771Sfjoe 240106939Ssam BPF_MTAP(ifp, m); 24189099Sfjoe 242191605Skmacy error = ifp->if_transmit(ifp, m); 24389099Sfjoe 24489099Sfjoe return (error); 24589099Sfjoe 24689099Sfjoebad: 24789099Sfjoe if (m) 24889099Sfjoe m_freem(m); 24989099Sfjoe return (error); 25089099Sfjoe} 25189099Sfjoe 25289099Sfjoevoid 253157681Srwatsonarc_frag_init(struct ifnet *ifp) 25489099Sfjoe{ 25589099Sfjoe struct arccom *ac; 25689099Sfjoe 257147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 25889099Sfjoe ac->curr_frag = 0; 25989099Sfjoe} 26089099Sfjoe 26189099Sfjoestruct mbuf * 262157681Srwatsonarc_frag_next(struct ifnet *ifp) 26389099Sfjoe{ 26489099Sfjoe struct arccom *ac; 26589099Sfjoe struct mbuf *m; 26689099Sfjoe struct arc_header *ah; 26789099Sfjoe 268147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 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 */ 282109771Sfjoe tfrags = (m->m_pkthdr.len + ARC_MAX_DATA - 1) / ARC_MAX_DATA; 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 290110106Sfjoe m_adj(m, ARC_HDRNEWLEN); 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 */ 297111119Simp ac->curr_frag = m_split(m, ARC_MAX_DATA, M_DONTWAIT); 29889099Sfjoe if (ac->curr_frag == 0) { 29993750Sluigi m_freem(m); 30089099Sfjoe return 0; 30189099Sfjoe } 30289099Sfjoe 303111119Simp M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT); 30489099Sfjoe if (m == 0) { 30593750Sluigi m_freem(ac->curr_frag); 30689099Sfjoe ac->curr_frag = 0; 30789099Sfjoe return 0; 30889099Sfjoe } 30989099Sfjoe 31089099Sfjoe ah = mtod(m, struct arc_header *); 31189099Sfjoe ah->arc_flag = ac->rsflag; 31289099Sfjoe ah->arc_seqid = ac->ac_seqid; 31389099Sfjoe 31489099Sfjoe ac->sflag += 2; 31589099Sfjoe ac->rsflag = ac->sflag; 31689099Sfjoe } else if ((m->m_pkthdr.len >= 31789099Sfjoe ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && 31889099Sfjoe (m->m_pkthdr.len <= 31989099Sfjoe ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { 32089099Sfjoe ac->curr_frag = 0; 32189099Sfjoe 322111119Simp M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_DONTWAIT); 32389099Sfjoe if (m == 0) 32489099Sfjoe return 0; 32589099Sfjoe 32689099Sfjoe ah = mtod(m, struct arc_header *); 32789099Sfjoe ah->arc_flag = 0xFF; 32889099Sfjoe ah->arc_seqid = 0xFFFF; 32989099Sfjoe ah->arc_type2 = ac->arc_type; 33089099Sfjoe ah->arc_flag2 = ac->sflag; 33189099Sfjoe ah->arc_seqid2 = ac->ac_seqid; 33289099Sfjoe } else { 33389099Sfjoe ac->curr_frag = 0; 33489099Sfjoe 335111119Simp M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT); 33689099Sfjoe if (m == 0) 33789099Sfjoe return 0; 33889099Sfjoe 33989099Sfjoe ah = mtod(m, struct arc_header *); 34089099Sfjoe ah->arc_flag = ac->sflag; 34189099Sfjoe ah->arc_seqid = ac->ac_seqid; 34289099Sfjoe } 34389099Sfjoe 34489099Sfjoe ah->arc_dhost = ac->arc_dhost; 34589099Sfjoe ah->arc_shost = ac->arc_shost; 34689099Sfjoe ah->arc_type = ac->arc_type; 34789099Sfjoe 34889099Sfjoe return m; 34989099Sfjoe} 35089099Sfjoe 35189099Sfjoe/* 35289099Sfjoe * Defragmenter. Returns mbuf if last packet found, else 35389099Sfjoe * NULL. frees imcoming mbuf as necessary. 35489099Sfjoe */ 35589099Sfjoe 356105228Sphkstatic __inline struct mbuf * 357157681Srwatsonarc_defrag(struct ifnet *ifp, struct mbuf *m) 35889099Sfjoe{ 35989099Sfjoe struct arc_header *ah, *ah1; 36089099Sfjoe struct arccom *ac; 36189099Sfjoe struct ac_frag *af; 36289099Sfjoe struct mbuf *m1; 36389099Sfjoe char *s; 36489099Sfjoe int newflen; 36589099Sfjoe u_char src,dst,typ; 36689099Sfjoe 367147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 36889099Sfjoe 36989099Sfjoe if (m->m_len < ARC_HDRNEWLEN) { 37089099Sfjoe m = m_pullup(m, ARC_HDRNEWLEN); 37189099Sfjoe if (m == NULL) { 37289099Sfjoe ++ifp->if_ierrors; 37389099Sfjoe return NULL; 37489099Sfjoe } 37589099Sfjoe } 37689099Sfjoe 37789099Sfjoe ah = mtod(m, struct arc_header *); 37889099Sfjoe typ = ah->arc_type; 37989099Sfjoe 38089099Sfjoe if (!arc_isphds(typ)) 38189099Sfjoe return m; 38289099Sfjoe 38389099Sfjoe src = ah->arc_shost; 38489099Sfjoe dst = ah->arc_dhost; 38589099Sfjoe 38689099Sfjoe if (ah->arc_flag == 0xff) { 38789099Sfjoe m_adj(m, 4); 38889099Sfjoe 38989099Sfjoe if (m->m_len < ARC_HDRNEWLEN) { 39089099Sfjoe m = m_pullup(m, ARC_HDRNEWLEN); 39189099Sfjoe if (m == NULL) { 39289099Sfjoe ++ifp->if_ierrors; 39389099Sfjoe return NULL; 39489099Sfjoe } 39589099Sfjoe } 39689099Sfjoe 39789099Sfjoe ah = mtod(m, struct arc_header *); 39889099Sfjoe } 39989099Sfjoe 40089099Sfjoe af = &ac->ac_fragtab[src]; 40189099Sfjoe m1 = af->af_packet; 40289099Sfjoe s = "debug code error"; 40389099Sfjoe 40489099Sfjoe if (ah->arc_flag & 1) { 40589099Sfjoe /* 40689099Sfjoe * first fragment. We always initialize, which is 40789099Sfjoe * about the right thing to do, as we only want to 40889099Sfjoe * accept one fragmented packet per src at a time. 40989099Sfjoe */ 41089099Sfjoe if (m1 != NULL) 41189099Sfjoe m_freem(m1); 41289099Sfjoe 41389099Sfjoe af->af_packet = m; 41489099Sfjoe m1 = m; 41589099Sfjoe af->af_maxflag = ah->arc_flag; 41689099Sfjoe af->af_lastseen = 0; 41789099Sfjoe af->af_seqid = ah->arc_seqid; 41889099Sfjoe 41989099Sfjoe return NULL; 42089099Sfjoe /* notreached */ 42189099Sfjoe } else { 42289099Sfjoe /* check for unfragmented packet */ 42389099Sfjoe if (ah->arc_flag == 0) 42489099Sfjoe return m; 42589099Sfjoe 42689099Sfjoe /* do we have a first packet from that src? */ 42789099Sfjoe if (m1 == NULL) { 42889099Sfjoe s = "no first frag"; 42989099Sfjoe goto outofseq; 43089099Sfjoe } 43189099Sfjoe 43289099Sfjoe ah1 = mtod(m1, struct arc_header *); 43389099Sfjoe 43489099Sfjoe if (ah->arc_seqid != ah1->arc_seqid) { 43589099Sfjoe s = "seqid differs"; 43689099Sfjoe goto outofseq; 43789099Sfjoe } 43889099Sfjoe 43989099Sfjoe if (typ != ah1->arc_type) { 44089099Sfjoe s = "type differs"; 44189099Sfjoe goto outofseq; 44289099Sfjoe } 44389099Sfjoe 44489099Sfjoe if (dst != ah1->arc_dhost) { 44589099Sfjoe s = "dest host differs"; 44689099Sfjoe goto outofseq; 44789099Sfjoe } 44889099Sfjoe 44989099Sfjoe /* typ, seqid and dst are ok here. */ 45089099Sfjoe 45189099Sfjoe if (ah->arc_flag == af->af_lastseen) { 45289099Sfjoe m_freem(m); 45389099Sfjoe return NULL; 45489099Sfjoe } 45589099Sfjoe 45689099Sfjoe if (ah->arc_flag == af->af_lastseen + 2) { 45789099Sfjoe /* ok, this is next fragment */ 45889099Sfjoe af->af_lastseen = ah->arc_flag; 45989099Sfjoe m_adj(m,ARC_HDRNEWLEN); 46089099Sfjoe 46189099Sfjoe /* 46289099Sfjoe * m_cat might free the first mbuf (with pkthdr) 46389099Sfjoe * in 2nd chain; therefore: 46489099Sfjoe */ 46589099Sfjoe 46689099Sfjoe newflen = m->m_pkthdr.len; 46789099Sfjoe 46889099Sfjoe m_cat(m1,m); 46989099Sfjoe 47089099Sfjoe m1->m_pkthdr.len += newflen; 47189099Sfjoe 47289099Sfjoe /* is it the last one? */ 47389099Sfjoe if (af->af_lastseen > af->af_maxflag) { 47489099Sfjoe af->af_packet = NULL; 47589099Sfjoe return(m1); 47689099Sfjoe } else 47789099Sfjoe return NULL; 47889099Sfjoe } 47989099Sfjoe s = "other reason"; 48089099Sfjoe /* if all else fails, it is out of sequence, too */ 48189099Sfjoe } 48289099Sfjoeoutofseq: 48389099Sfjoe if (m1) { 48489099Sfjoe m_freem(m1); 48589099Sfjoe af->af_packet = NULL; 48689099Sfjoe } 48789099Sfjoe 48889099Sfjoe if (m) 48989099Sfjoe m_freem(m); 49089099Sfjoe 491121816Sbrooks log(LOG_INFO,"%s: got out of seq. packet: %s\n", 492121816Sbrooks ifp->if_xname, s); 49389099Sfjoe 49489099Sfjoe return NULL; 49589099Sfjoe} 49689099Sfjoe 49789099Sfjoe/* 49889099Sfjoe * return 1 if Packet Header Definition Standard, else 0. 49989099Sfjoe * For now: old IP, old ARP aren't obviously. Lacking correct information, 50089099Sfjoe * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 50189099Sfjoe * (Apple and Novell corporations were involved, among others, in PHDS work). 50289099Sfjoe * Easiest is to assume that everybody else uses that, too. 50389099Sfjoe */ 50489099Sfjoeint 505157681Srwatsonarc_isphds(u_int8_t type) 50689099Sfjoe{ 50789099Sfjoe return (type != ARCTYPE_IP_OLD && 50889099Sfjoe type != ARCTYPE_ARP_OLD && 50989099Sfjoe type != ARCTYPE_DIAGNOSE); 51089099Sfjoe} 51189099Sfjoe 51289099Sfjoe/* 51389099Sfjoe * Process a received Arcnet packet; 51489099Sfjoe * the packet is in the mbuf chain m with 51589099Sfjoe * the ARCnet header. 51689099Sfjoe */ 51789099Sfjoevoid 518157681Srwatsonarc_input(struct ifnet *ifp, struct mbuf *m) 51989099Sfjoe{ 52089099Sfjoe struct arc_header *ah; 521111888Sjlemon int isr; 52289099Sfjoe u_int8_t atype; 52389099Sfjoe 52489099Sfjoe if ((ifp->if_flags & IFF_UP) == 0) { 52589099Sfjoe m_freem(m); 52689099Sfjoe return; 52789099Sfjoe } 52889099Sfjoe 52989099Sfjoe /* possibly defragment: */ 53089099Sfjoe m = arc_defrag(ifp, m); 53189099Sfjoe if (m == NULL) 53289099Sfjoe return; 53389099Sfjoe 534106939Ssam BPF_MTAP(ifp, m); 53589099Sfjoe 53689099Sfjoe ah = mtod(m, struct arc_header *); 537109771Sfjoe /* does this belong to us? */ 538110106Sfjoe if ((ifp->if_flags & IFF_PROMISC) == 0 539109771Sfjoe && ah->arc_dhost != arcbroadcastaddr 540110106Sfjoe && ah->arc_dhost != ARC_LLADDR(ifp)) { 541109771Sfjoe m_freem(m); 542109771Sfjoe return; 543109771Sfjoe } 54489099Sfjoe 54589099Sfjoe ifp->if_ibytes += m->m_pkthdr.len; 54689099Sfjoe 547109771Sfjoe if (ah->arc_dhost == arcbroadcastaddr) { 54889099Sfjoe m->m_flags |= M_BCAST|M_MCAST; 54989099Sfjoe ifp->if_imcasts++; 55089099Sfjoe } 55189099Sfjoe 55289099Sfjoe atype = ah->arc_type; 55389099Sfjoe switch (atype) { 55489099Sfjoe#ifdef INET 55589099Sfjoe case ARCTYPE_IP: 55689099Sfjoe m_adj(m, ARC_HDRNEWLEN); 557154518Sandre if ((m = ip_fastforward(m)) == NULL) 558109771Sfjoe return; 559111888Sjlemon isr = NETISR_IP; 56089099Sfjoe break; 56189099Sfjoe 56289099Sfjoe case ARCTYPE_IP_OLD: 56389099Sfjoe m_adj(m, ARC_HDRLEN); 564154518Sandre if ((m = ip_fastforward(m)) == NULL) 565109771Sfjoe return; 566111888Sjlemon isr = NETISR_IP; 56789099Sfjoe break; 56889099Sfjoe 56989099Sfjoe case ARCTYPE_ARP: 57089099Sfjoe if (ifp->if_flags & IFF_NOARP) { 57189099Sfjoe /* Discard packet if ARP is disabled on interface */ 57289099Sfjoe m_freem(m); 57389099Sfjoe return; 57489099Sfjoe } 57589099Sfjoe m_adj(m, ARC_HDRNEWLEN); 576111888Sjlemon isr = NETISR_ARP; 57789099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 57889099Sfjoe mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 57989099Sfjoe#endif 58089099Sfjoe break; 58189099Sfjoe 58289099Sfjoe case ARCTYPE_ARP_OLD: 58389099Sfjoe if (ifp->if_flags & IFF_NOARP) { 58489099Sfjoe /* Discard packet if ARP is disabled on interface */ 58589099Sfjoe m_freem(m); 58689099Sfjoe return; 58789099Sfjoe } 58889099Sfjoe m_adj(m, ARC_HDRLEN); 589111888Sjlemon isr = NETISR_ARP; 59089099Sfjoe#ifdef ARCNET_ALLOW_BROKEN_ARP 59189099Sfjoe mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 59289099Sfjoe#endif 59389099Sfjoe break; 59489099Sfjoe#endif 59589099Sfjoe#ifdef INET6 59689099Sfjoe case ARCTYPE_INET6: 59789099Sfjoe m_adj(m, ARC_HDRNEWLEN); 598111888Sjlemon isr = NETISR_IPV6; 59989099Sfjoe break; 60089099Sfjoe#endif 601109771Sfjoe#ifdef IPX 602109771Sfjoe case ARCTYPE_IPX: 603109771Sfjoe m_adj(m, ARC_HDRNEWLEN); 604111888Sjlemon isr = NETISR_IPX; 605109771Sfjoe break; 606109771Sfjoe#endif 60789099Sfjoe default: 60889099Sfjoe m_freem(m); 60989099Sfjoe return; 61089099Sfjoe } 611223741Sbz M_SETFIB(m, ifp->if_fib); 612111888Sjlemon netisr_dispatch(isr, m); 61389099Sfjoe} 61489099Sfjoe 61589099Sfjoe/* 61689099Sfjoe * Register (new) link level address. 61789099Sfjoe */ 61889099Sfjoevoid 619157681Srwatsonarc_storelladdr(struct ifnet *ifp, u_int8_t lla) 62089099Sfjoe{ 621110106Sfjoe ARC_LLADDR(ifp) = lla; 62289099Sfjoe} 62389099Sfjoe 62489099Sfjoe/* 62589099Sfjoe * Perform common duties while attaching to interface list 62689099Sfjoe */ 62789099Sfjoevoid 628157681Srwatsonarc_ifattach(struct ifnet *ifp, u_int8_t lla) 62989099Sfjoe{ 63089099Sfjoe struct ifaddr *ifa; 63189099Sfjoe struct sockaddr_dl *sdl; 63289099Sfjoe struct arccom *ac; 63389099Sfjoe 63489099Sfjoe if_attach(ifp); 63589099Sfjoe ifp->if_addrlen = 1; 63689099Sfjoe ifp->if_hdrlen = ARC_HDRLEN; 63789099Sfjoe ifp->if_mtu = 1500; 638109771Sfjoe ifp->if_resolvemulti = arc_resolvemulti; 63989099Sfjoe if (ifp->if_baudrate == 0) 64089099Sfjoe ifp->if_baudrate = 2500000; 64189099Sfjoe#if __FreeBSD_version < 500000 64289099Sfjoe ifa = ifnet_addrs[ifp->if_index - 1]; 64389099Sfjoe#else 644152315Sru ifa = ifp->if_addr; 64589099Sfjoe#endif 646135577Sstefanf KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); 64789099Sfjoe sdl = (struct sockaddr_dl *)ifa->ifa_addr; 64889099Sfjoe sdl->sdl_type = IFT_ARCNET; 64989099Sfjoe sdl->sdl_alen = ifp->if_addrlen; 65089099Sfjoe 65189099Sfjoe if (ifp->if_flags & IFF_BROADCAST) 65289099Sfjoe ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 65389099Sfjoe 654147256Sbrooks ac = (struct arccom *)ifp->if_l2com; 65589099Sfjoe ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 65689099Sfjoe if (lla == 0) { 65789099Sfjoe /* XXX this message isn't entirely clear, to me -- cgd */ 658121816Sbrooks log(LOG_ERR,"%s: link address 0 reserved for broadcasts. Please change it and ifconfig %s down up\n", 659121816Sbrooks ifp->if_xname, ifp->if_xname); 66089099Sfjoe } 66189099Sfjoe arc_storelladdr(ifp, lla); 66289099Sfjoe 66389099Sfjoe ifp->if_broadcastaddr = &arcbroadcastaddr; 66489099Sfjoe 66589099Sfjoe bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 66689099Sfjoe} 66789099Sfjoe 66889099Sfjoevoid 669157681Srwatsonarc_ifdetach(struct ifnet *ifp) 67089099Sfjoe{ 67189099Sfjoe bpfdetach(ifp); 67289099Sfjoe if_detach(ifp); 67389099Sfjoe} 67489099Sfjoe 67589099Sfjoeint 676194581Srdivackyarc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 67789099Sfjoe{ 67889099Sfjoe struct ifaddr *ifa = (struct ifaddr *) data; 67989099Sfjoe struct ifreq *ifr = (struct ifreq *) data; 68089099Sfjoe int error = 0; 68189099Sfjoe 68289099Sfjoe switch (command) { 68389099Sfjoe case SIOCSIFADDR: 68489099Sfjoe ifp->if_flags |= IFF_UP; 68589099Sfjoe switch (ifa->ifa_addr->sa_family) { 68689099Sfjoe#ifdef INET 68789099Sfjoe case AF_INET: 68889099Sfjoe ifp->if_init(ifp->if_softc); /* before arpwhohas */ 68989099Sfjoe arp_ifinit(ifp, ifa); 69089099Sfjoe break; 69189099Sfjoe#endif 692109771Sfjoe#ifdef IPX 693109771Sfjoe /* 694109771Sfjoe * XXX This code is probably wrong 695109771Sfjoe */ 696109771Sfjoe case AF_IPX: 697109771Sfjoe { 698109771Sfjoe struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 699109771Sfjoe 700109771Sfjoe if (ipx_nullhost(*ina)) 701110106Sfjoe ina->x_host.c_host[5] = ARC_LLADDR(ifp); 702109771Sfjoe else 703109771Sfjoe arc_storelladdr(ifp, ina->x_host.c_host[5]); 704109771Sfjoe 705109771Sfjoe /* 706109771Sfjoe * Set new address 707109771Sfjoe */ 708109771Sfjoe ifp->if_init(ifp->if_softc); 709109771Sfjoe break; 710109771Sfjoe } 711109771Sfjoe#endif 71289099Sfjoe default: 71389099Sfjoe ifp->if_init(ifp->if_softc); 71489099Sfjoe break; 71589099Sfjoe } 71689099Sfjoe break; 71789099Sfjoe 718109771Sfjoe case SIOCGIFADDR: 719109771Sfjoe { 720109771Sfjoe struct sockaddr *sa; 721109771Sfjoe 722109771Sfjoe sa = (struct sockaddr *) &ifr->ifr_data; 723110106Sfjoe *(u_int8_t *)sa->sa_data = ARC_LLADDR(ifp); 724109771Sfjoe } 725109771Sfjoe break; 726109771Sfjoe 72789099Sfjoe case SIOCADDMULTI: 72889099Sfjoe case SIOCDELMULTI: 72989099Sfjoe if (ifr == NULL) 73089099Sfjoe error = EAFNOSUPPORT; 73189099Sfjoe else { 73289099Sfjoe switch (ifr->ifr_addr.sa_family) { 73389099Sfjoe case AF_INET: 73489099Sfjoe case AF_INET6: 73589099Sfjoe error = 0; 73689099Sfjoe break; 73789099Sfjoe default: 73889099Sfjoe error = EAFNOSUPPORT; 73989099Sfjoe break; 74089099Sfjoe } 74189099Sfjoe } 74289099Sfjoe break; 74389099Sfjoe 74489099Sfjoe case SIOCSIFMTU: 74589099Sfjoe /* 74689099Sfjoe * Set the interface MTU. 74789099Sfjoe * mtu can't be larger than ARCMTU for RFC1051 74889099Sfjoe * and can't be larger than ARC_PHDS_MTU 74989099Sfjoe */ 75089099Sfjoe if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 75189099Sfjoe ifr->ifr_mtu > ARC_PHDS_MAXMTU) 75289099Sfjoe error = EINVAL; 75389099Sfjoe else 75489099Sfjoe ifp->if_mtu = ifr->ifr_mtu; 75589099Sfjoe break; 756109771Sfjoe } 75789099Sfjoe 758109771Sfjoe return (error); 759109771Sfjoe} 76089099Sfjoe 761109771Sfjoe/* based on ether_resolvemulti() */ 762109771Sfjoeint 763157681Srwatsonarc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 764157681Srwatson struct sockaddr *sa) 765109771Sfjoe{ 766109771Sfjoe struct sockaddr_dl *sdl; 767184680Sbz#ifdef INET 768109771Sfjoe struct sockaddr_in *sin; 769184680Sbz#endif 770109771Sfjoe#ifdef INET6 771109771Sfjoe struct sockaddr_in6 *sin6; 772109771Sfjoe#endif 773109771Sfjoe 774109771Sfjoe switch(sa->sa_family) { 775109771Sfjoe case AF_LINK: 776109771Sfjoe /* 777109771Sfjoe * No mapping needed. Just check that it's a valid MC address. 778109771Sfjoe */ 779109771Sfjoe sdl = (struct sockaddr_dl *)sa; 780109771Sfjoe if (*LLADDR(sdl) != arcbroadcastaddr) 781109771Sfjoe return EADDRNOTAVAIL; 782109771Sfjoe *llsa = 0; 783109771Sfjoe return 0; 784109771Sfjoe#ifdef INET 785109771Sfjoe case AF_INET: 786109771Sfjoe sin = (struct sockaddr_in *)sa; 787109771Sfjoe if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 788109771Sfjoe return EADDRNOTAVAIL; 789184205Sdes sdl = malloc(sizeof *sdl, M_IFMADDR, 790148641Srwatson M_NOWAIT | M_ZERO); 791148641Srwatson if (sdl == NULL) 792148641Srwatson return ENOMEM; 793109771Sfjoe sdl->sdl_len = sizeof *sdl; 794109771Sfjoe sdl->sdl_family = AF_LINK; 795109771Sfjoe sdl->sdl_index = ifp->if_index; 796109771Sfjoe sdl->sdl_type = IFT_ARCNET; 797109771Sfjoe sdl->sdl_alen = ARC_ADDR_LEN; 798109771Sfjoe *LLADDR(sdl) = 0; 799109771Sfjoe *llsa = (struct sockaddr *)sdl; 800109771Sfjoe return 0; 801109771Sfjoe#endif 802109771Sfjoe#ifdef INET6 803109771Sfjoe case AF_INET6: 804109771Sfjoe sin6 = (struct sockaddr_in6 *)sa; 805109771Sfjoe if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 806109771Sfjoe /* 807109771Sfjoe * An IP6 address of 0 means listen to all 808109771Sfjoe * of the Ethernet multicast address used for IP6. 809109771Sfjoe * (This is used for multicast routers.) 810109771Sfjoe */ 811109771Sfjoe ifp->if_flags |= IFF_ALLMULTI; 812109771Sfjoe *llsa = 0; 813109771Sfjoe return 0; 81489099Sfjoe } 815109771Sfjoe if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 816109771Sfjoe return EADDRNOTAVAIL; 817184205Sdes sdl = malloc(sizeof *sdl, M_IFMADDR, 818148641Srwatson M_NOWAIT | M_ZERO); 819148641Srwatson if (sdl == NULL) 820148641Srwatson return ENOMEM; 821109771Sfjoe sdl->sdl_len = sizeof *sdl; 822109771Sfjoe sdl->sdl_family = AF_LINK; 823109771Sfjoe sdl->sdl_index = ifp->if_index; 824109771Sfjoe sdl->sdl_type = IFT_ARCNET; 825109771Sfjoe sdl->sdl_alen = ARC_ADDR_LEN; 826109771Sfjoe *LLADDR(sdl) = 0; 827109771Sfjoe *llsa = (struct sockaddr *)sdl; 828109771Sfjoe return 0; 82989099Sfjoe#endif 830109771Sfjoe 831109771Sfjoe default: 832109771Sfjoe /* 833109771Sfjoe * Well, the text isn't quite right, but it's the name 834109771Sfjoe * that counts... 835109771Sfjoe */ 836109771Sfjoe return EAFNOSUPPORT; 83789099Sfjoe } 83889099Sfjoe} 839147256Sbrooks 840249132Smavstatic MALLOC_DEFINE(M_ARCCOM, "arccom", "ARCNET interface internals"); 841147256Sbrooks 842147256Sbrooksstatic void* 843147256Sbrooksarc_alloc(u_char type, struct ifnet *ifp) 844147256Sbrooks{ 845147256Sbrooks struct arccom *ac; 846147256Sbrooks 847147256Sbrooks ac = malloc(sizeof(struct arccom), M_ARCCOM, M_WAITOK | M_ZERO); 848147256Sbrooks ac->ac_ifp = ifp; 849147256Sbrooks 850147256Sbrooks return (ac); 851147256Sbrooks} 852147256Sbrooks 853147256Sbrooksstatic void 854147256Sbrooksarc_free(void *com, u_char type) 855147256Sbrooks{ 856147256Sbrooks 857147256Sbrooks free(com, M_ARCCOM); 858147256Sbrooks} 859147256Sbrooks 860147256Sbrooksstatic int 861147256Sbrooksarc_modevent(module_t mod, int type, void *data) 862147256Sbrooks{ 863147256Sbrooks 864147256Sbrooks switch (type) { 865147256Sbrooks case MOD_LOAD: 866147256Sbrooks if_register_com_alloc(IFT_ARCNET, arc_alloc, arc_free); 867147256Sbrooks break; 868147256Sbrooks case MOD_UNLOAD: 869147256Sbrooks if_deregister_com_alloc(IFT_ARCNET); 870147256Sbrooks break; 871147256Sbrooks default: 872147256Sbrooks return EOPNOTSUPP; 873147256Sbrooks } 874147256Sbrooks 875147256Sbrooks return (0); 876147256Sbrooks} 877147256Sbrooks 878147256Sbrooksstatic moduledata_t arc_mod = { 879147256Sbrooks "arcnet", 880147256Sbrooks arc_modevent, 881147256Sbrooks 0 882147256Sbrooks}; 883147256Sbrooks 884147256SbrooksDECLARE_MODULE(arcnet, arc_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); 885147256SbrooksMODULE_VERSION(arcnet, 1); 886