if_fddisubr.c revision 93369
17055Sdg/* 221830Sjoerg * Copyright (c) 1995, 1996 321830Sjoerg * Matt Thomas <matt@3am-software.com>. All rights reserved. 47055Sdg * Copyright (c) 1982, 1989, 1993 57055Sdg * The Regents of the University of California. All rights reserved. 67055Sdg * 77055Sdg * Redistribution and use in source and binary forms, with or without 87055Sdg * modification, are permitted provided that the following conditions 97055Sdg * are met: 107055Sdg * 1. Redistributions of source code must retain the above copyright 117055Sdg * notice, this list of conditions and the following disclaimer. 127055Sdg * 2. Redistributions in binary form must reproduce the above copyright 137055Sdg * notice, this list of conditions and the following disclaimer in the 147055Sdg * documentation and/or other materials provided with the distribution. 157055Sdg * 3. All advertising materials mentioning features or use of this software 167055Sdg * must display the following acknowledgement: 177055Sdg * This product includes software developed by the University of 187055Sdg * California, Berkeley and its contributors. 197055Sdg * 4. Neither the name of the University nor the names of its contributors 207055Sdg * may be used to endorse or promote products derived from this software 217055Sdg * without specific prior written permission. 227055Sdg * 237055Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 247055Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 257055Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 267055Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 277055Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 287055Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 297055Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 307055Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 317055Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 327055Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 337055Sdg * SUCH DAMAGE. 347055Sdg * 357061Sdg * from: if_ethersubr.c,v 1.5 1994/12/13 22:31:45 wollman Exp 3650477Speter * $FreeBSD: head/sys/net/if_fddisubr.c 93369 2002-03-29 08:04:36Z mdodd $ 377055Sdg */ 387055Sdg 3932356Seivind#include "opt_atalk.h" 4032350Seivind#include "opt_inet.h" 4154263Sshin#include "opt_inet6.h" 4231742Seivind#include "opt_ipx.h" 4331742Seivind 447055Sdg#include <sys/param.h> 457055Sdg#include <sys/systm.h> 467055Sdg#include <sys/mbuf.h> 477055Sdg#include <sys/socket.h> 4868315Sume#include <sys/malloc.h> 497055Sdg 507055Sdg#include <net/if.h> 517055Sdg#include <net/netisr.h> 527055Sdg#include <net/route.h> 537055Sdg#include <net/if_llc.h> 547055Sdg#include <net/if_dl.h> 557055Sdg#include <net/if_types.h> 567055Sdg 5754263Sshin#if defined(INET) || defined(INET6) 587055Sdg#include <netinet/in.h> 597055Sdg#include <netinet/in_var.h> 6032350Seivind#include <netinet/if_ether.h> 617055Sdg#endif 6254263Sshin#ifdef INET6 6354263Sshin#include <netinet6/nd6.h> 6454263Sshin#endif 657055Sdg#include <netinet/if_fddi.h> 667055Sdg 6711819Sjulian#ifdef IPX 6821830Sjoerg#include <netipx/ipx.h> 6911819Sjulian#include <netipx/ipx_if.h> 7011819Sjulian#endif 7111819Sjulian 727055Sdg#ifdef NS 737055Sdg#include <netns/ns.h> 747055Sdg#include <netns/ns_if.h> 757055Sdg#endif 767055Sdg 777055Sdg#ifdef DECNET 787055Sdg#include <netdnet/dn.h> 797055Sdg#endif 807055Sdg 8121830Sjoerg#ifdef NETATALK 8221830Sjoerg#include <netatalk/at.h> 8321830Sjoerg#include <netatalk/at_var.h> 8421830Sjoerg#include <netatalk/at_extern.h> 8521830Sjoerg 8621830Sjoerg#define llc_snap_org_code llc_un.type_snap.org_code 8721830Sjoerg#define llc_snap_ether_type llc_un.type_snap.ether_type 8821830Sjoerg 8921830Sjoergextern u_char at_org_code[ 3 ]; 9021830Sjoergextern u_char aarp_org_code[ 3 ]; 9121830Sjoerg#endif /* NETATALK */ 9221830Sjoerg 9392725Salfredstatic int fddi_resolvemulti(struct ifnet *, struct sockaddr **, 9493084Sbde struct sockaddr *); 9568180Sume 967055Sdg/* 977055Sdg * This really should be defined in if_llc.h but in case it isn't. 987055Sdg */ 997055Sdg#ifndef llc_snap 1007055Sdg#define llc_snap llc_un.type_snap 1017055Sdg#endif 1027055Sdg 10393369Smdodd#define IFP2AC(IFP) ((struct arpcom *)IFP) 10493369Smdodd#define senderr(e) { error = (e); goto bad; } 10593369Smdodd 1067055Sdg/* 1077055Sdg * FDDI output routine. 1087055Sdg * Encapsulate a packet of type family for the local net. 1097055Sdg * Use trailer local net encapsulation if enough data in first 1107055Sdg * packet leaves a multiple of 512 bytes of data in remainder. 1117055Sdg * Assumes that ifp is actually pointer to arpcom structure. 1127055Sdg */ 1137055Sdgint 11454799Sgreenfddi_output(ifp, m, dst, rt0) 11593367Smdodd struct ifnet *ifp; 11654799Sgreen struct mbuf *m; 1177055Sdg struct sockaddr *dst; 1187055Sdg struct rtentry *rt0; 1197055Sdg{ 12021830Sjoerg u_int16_t type; 12169152Sjlemon int loop_copy = 0, error = 0, hdrcmplt = 0; 12252248Smsmith u_char esrc[6], edst[6]; 12393367Smdodd struct rtentry *rt; 12493367Smdodd struct fddi_header *fh; 12593369Smdodd struct arpcom *ac = IFP2AC(ifp); 1267055Sdg 1277055Sdg if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 1287055Sdg senderr(ENETDOWN); 12934961Sphk getmicrotime(&ifp->if_lastchange); 13043305Sdillon if ((rt = rt0) != NULL) { 1317055Sdg if ((rt->rt_flags & RTF_UP) == 0) { 13293369Smdodd if ((rt0 = rt = rtalloc1(dst, 1, 0UL)) != NULL) 1337055Sdg rt->rt_refcnt--; 13421830Sjoerg else 1357055Sdg senderr(EHOSTUNREACH); 1367055Sdg } 1377055Sdg if (rt->rt_flags & RTF_GATEWAY) { 1387055Sdg if (rt->rt_gwroute == 0) 1397055Sdg goto lookup; 1407055Sdg if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 1417055Sdg rtfree(rt); rt = rt0; 14293369Smdodd lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL); 1437055Sdg if ((rt = rt->rt_gwroute) == 0) 1447055Sdg senderr(EHOSTUNREACH); 1457055Sdg } 1467055Sdg } 1477055Sdg if (rt->rt_flags & RTF_REJECT) 1487055Sdg if (rt->rt_rmx.rmx_expire == 0 || 14934961Sphk time_second < rt->rt_rmx.rmx_expire) 1507055Sdg senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 1517055Sdg } 1527055Sdg switch (dst->sa_family) { 1537055Sdg 1547055Sdg#ifdef INET 15521830Sjoerg case AF_INET: { 15693369Smdodd if (!arpresolve(ifp, rt, m, dst, edst, rt0)) 1577055Sdg return (0); /* if not yet resolved */ 15821830Sjoerg type = htons(ETHERTYPE_IP); 1597055Sdg break; 16021830Sjoerg } 1617055Sdg#endif 16254263Sshin#ifdef INET6 16354263Sshin case AF_INET6: 16454263Sshin if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) { 16574093Sbmilekic /* Something bad happened */ 16693369Smdodd return (0); 16754263Sshin } 16854263Sshin type = htons(ETHERTYPE_IPV6); 16954263Sshin break; 17054263Sshin#endif 17111819Sjulian#ifdef IPX 17211819Sjulian case AF_IPX: 17321830Sjoerg type = htons(ETHERTYPE_IPX); 17411819Sjulian bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 17511819Sjulian (caddr_t)edst, sizeof (edst)); 17611819Sjulian break; 17711819Sjulian#endif 17821830Sjoerg#ifdef NETATALK 17921830Sjoerg case AF_APPLETALK: { 18021830Sjoerg struct at_ifaddr *aa; 18136908Sjulian if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) 18221830Sjoerg return (0); 18321830Sjoerg /* 18421830Sjoerg * ifaddr is the first thing in at_ifaddr 18521830Sjoerg */ 18630834Sjulian if ((aa = at_ifawithnet( (struct sockaddr_at *)dst)) == 0) 18721830Sjoerg goto bad; 18821830Sjoerg 18921830Sjoerg /* 19021830Sjoerg * In the phase 2 case, we need to prepend an mbuf for the llc header. 19121830Sjoerg * Since we must preserve the value of m, which is passed to us by 19221830Sjoerg * value, we m_copy() the first mbuf, and use it for our llc header. 19321830Sjoerg */ 19421830Sjoerg if (aa->aa_flags & AFA_PHASE2) { 19521830Sjoerg struct llc llc; 19621830Sjoerg 19770254Sbmilekic M_PREPEND(m, sizeof(struct llc), M_TRYWAIT); 19821830Sjoerg if (m == 0) 19921830Sjoerg senderr(ENOBUFS); 20021830Sjoerg llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 20121830Sjoerg llc.llc_control = LLC_UI; 20221830Sjoerg bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); 20321830Sjoerg llc.llc_snap_ether_type = htons(ETHERTYPE_AT); 20421830Sjoerg bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); 20521830Sjoerg type = 0; 20621830Sjoerg } else { 20721830Sjoerg type = htons(ETHERTYPE_AT); 20821830Sjoerg } 20921830Sjoerg break; 21021830Sjoerg } 21121830Sjoerg#endif /* NETATALK */ 2127055Sdg#ifdef NS 2137055Sdg case AF_NS: 21421830Sjoerg type = htons(ETHERTYPE_NS); 2157055Sdg bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 2167055Sdg (caddr_t)edst, sizeof (edst)); 2177055Sdg break; 2187055Sdg#endif 2197055Sdg 22052248Smsmith case pseudo_AF_HDRCMPLT: 22152248Smsmith { 22252248Smsmith struct ether_header *eh; 22352248Smsmith hdrcmplt = 1; 22452248Smsmith eh = (struct ether_header *)dst->sa_data; 22552248Smsmith (void)memcpy((caddr_t)esrc, (caddr_t)eh->ether_shost, sizeof (esrc)); 22652248Smsmith /* FALLTHROUGH */ 22752248Smsmith } 22852248Smsmith 2297055Sdg case AF_UNSPEC: 2307055Sdg { 2317055Sdg struct ether_header *eh; 23236992Sjulian loop_copy = -1; 2337055Sdg eh = (struct ether_header *)dst->sa_data; 2348384Sdg (void)memcpy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 2357055Sdg if (*edst & 1) 2367055Sdg m->m_flags |= (M_BCAST|M_MCAST); 2377055Sdg type = eh->ether_type; 2387055Sdg break; 2397055Sdg } 2407055Sdg 2417055Sdg case AF_IMPLINK: 2427055Sdg { 2437055Sdg fh = mtod(m, struct fddi_header *); 2447055Sdg error = EPROTONOSUPPORT; 2457055Sdg switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) { 2467055Sdg case FDDIFC_LLC_ASYNC: { 2477055Sdg /* legal priorities are 0 through 7 */ 2487055Sdg if ((fh->fddi_fc & FDDIFC_Z) > 7) 2497055Sdg goto bad; 2507055Sdg break; 2517055Sdg } 2527055Sdg case FDDIFC_LLC_SYNC: { 2537055Sdg /* FDDIFC_Z bits reserved, must be zero */ 2547055Sdg if (fh->fddi_fc & FDDIFC_Z) 2557055Sdg goto bad; 2567055Sdg break; 2577055Sdg } 2587055Sdg case FDDIFC_SMT: { 2597055Sdg /* FDDIFC_Z bits must be non zero */ 2607055Sdg if ((fh->fddi_fc & FDDIFC_Z) == 0) 2617055Sdg goto bad; 2627055Sdg break; 2637055Sdg } 2647055Sdg default: { 2657055Sdg /* anything else is too dangerous */ 2667055Sdg goto bad; 2677055Sdg } 2687055Sdg } 2697055Sdg error = 0; 2707055Sdg if (fh->fddi_dhost[0] & 1) 2717055Sdg m->m_flags |= (M_BCAST|M_MCAST); 2727055Sdg goto queue_it; 2737055Sdg } 2747055Sdg default: 2757055Sdg printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 2767055Sdg dst->sa_family); 2777055Sdg senderr(EAFNOSUPPORT); 2787055Sdg } 2797055Sdg 2807055Sdg if (type != 0) { 28193367Smdodd struct llc *l; 2827055Sdg M_PREPEND(m, sizeof (struct llc), M_DONTWAIT); 2837055Sdg if (m == 0) 2847055Sdg senderr(ENOBUFS); 2857055Sdg l = mtod(m, struct llc *); 2867055Sdg l->llc_control = LLC_UI; 2877055Sdg l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP; 2887055Sdg l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0; 2898384Sdg (void)memcpy((caddr_t) &l->llc_snap.ether_type, (caddr_t) &type, 29021830Sjoerg sizeof(u_int16_t)); 2917055Sdg } 29236908Sjulian 2937055Sdg /* 2947055Sdg * Add local net header. If no space in first mbuf, 2957055Sdg * allocate another. 2967055Sdg */ 2977055Sdg M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT); 2987055Sdg if (m == 0) 2997055Sdg senderr(ENOBUFS); 3007055Sdg fh = mtod(m, struct fddi_header *); 3017055Sdg fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; 3028384Sdg (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst)); 3037055Sdg queue_it: 30452248Smsmith if (hdrcmplt) 30552248Smsmith (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)esrc, 30652248Smsmith sizeof(fh->fddi_shost)); 30752248Smsmith else 30852248Smsmith (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr, 30952248Smsmith sizeof(fh->fddi_shost)); 31036908Sjulian /* 31136908Sjulian * If a simplex interface, and the packet is being sent to our 31236908Sjulian * Ethernet address or a broadcast address, loopback a copy. 31336908Sjulian * XXX To make a simplex device behave exactly like a duplex 31436908Sjulian * device, we should copy in the case of sending to our own 31536908Sjulian * ethernet address (thus letting the original actually appear 31636908Sjulian * on the wire). However, we don't do that here for security 31736908Sjulian * reasons and compatibility with the original behavior. 31836908Sjulian */ 31936992Sjulian if ((ifp->if_flags & IFF_SIMPLEX) && 32036992Sjulian (loop_copy != -1)) { 32136908Sjulian if ((m->m_flags & M_BCAST) || loop_copy) { 32236908Sjulian struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 32336908Sjulian 32436908Sjulian (void) if_simloop(ifp, 32560889Sarchie n, dst->sa_family, sizeof(struct fddi_header)); 32636908Sjulian } else if (bcmp(fh->fddi_dhost, 32736908Sjulian fh->fddi_shost, sizeof(fh->fddi_shost)) == 0) { 32836908Sjulian (void) if_simloop(ifp, 32960889Sarchie m, dst->sa_family, sizeof(struct fddi_header)); 33093369Smdodd return (0); /* XXX */ 33136908Sjulian } 33236908Sjulian } 33336908Sjulian 33469152Sjlemon if (! IF_HANDOFF(&ifp->if_snd, m, ifp)) 3357055Sdg senderr(ENOBUFS); 3367055Sdg return (error); 3377055Sdg 3387055Sdgbad: 3397055Sdg if (m) 3407055Sdg m_freem(m); 3417055Sdg return (error); 3427055Sdg} 3437055Sdg 3447055Sdg/* 3457055Sdg * Process a received FDDI packet; 3467055Sdg * the packet is in the mbuf chain m without 3477055Sdg * the fddi header, which is provided separately. 3487055Sdg */ 3497055Sdgvoid 3507055Sdgfddi_input(ifp, fh, m) 3517055Sdg struct ifnet *ifp; 35293367Smdodd struct fddi_header *fh; 3537055Sdg struct mbuf *m; 3547055Sdg{ 35593367Smdodd struct ifqueue *inq; 35693367Smdodd struct llc *l; 3577055Sdg 3587055Sdg if ((ifp->if_flags & IFF_UP) == 0) { 3597055Sdg m_freem(m); 3607055Sdg return; 3617055Sdg } 36234961Sphk getmicrotime(&ifp->if_lastchange); 3637055Sdg ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh); 36421830Sjoerg if (fh->fddi_dhost[0] & 1) { 36521830Sjoerg if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost, 36621830Sjoerg sizeof(fddibroadcastaddr)) == 0) 36721830Sjoerg m->m_flags |= M_BCAST; 36821830Sjoerg else 36921830Sjoerg m->m_flags |= M_MCAST; 3707055Sdg ifp->if_imcasts++; 37123910Sjoerg } else if ((ifp->if_flags & IFF_PROMISC) 37293369Smdodd && bcmp(IFP2AC(ifp)->ac_enaddr, (caddr_t)fh->fddi_dhost, 37323910Sjoerg sizeof(fh->fddi_dhost)) != 0) { 37423910Sjoerg m_freem(m); 37523910Sjoerg return; 37621830Sjoerg } 3777055Sdg 37821830Sjoerg#ifdef M_LINK0 37921830Sjoerg /* 38021830Sjoerg * If this has a LLC priority of 0, then mark it so upper 38121830Sjoerg * layers have a hint that it really came via a FDDI/Ethernet 38221830Sjoerg * bridge. 38321830Sjoerg */ 38421830Sjoerg if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0) 38521830Sjoerg m->m_flags |= M_LINK0; 38621830Sjoerg#endif 38721830Sjoerg 3887055Sdg l = mtod(m, struct llc *); 3897055Sdg switch (l->llc_dsap) { 39054263Sshin#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK) 3917055Sdg case LLC_SNAP_LSAP: 3927055Sdg { 39321830Sjoerg u_int16_t type; 3947055Sdg if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP) 3957055Sdg goto dropanyway; 39621830Sjoerg#ifdef NETATALK 39721830Sjoerg if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, 39821830Sjoerg sizeof(at_org_code)) == 0 && 39921830Sjoerg ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { 40021830Sjoerg inq = &atintrq2; 40121830Sjoerg m_adj( m, sizeof( struct llc )); 40221830Sjoerg schednetisr(NETISR_ATALK); 40321830Sjoerg break; 40421830Sjoerg } 40521830Sjoerg 40621830Sjoerg if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, 40721830Sjoerg sizeof(aarp_org_code)) == 0 && 40821830Sjoerg ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { 40921830Sjoerg m_adj( m, sizeof( struct llc )); 41093369Smdodd aarpinput(IFP2AC(ifp), m); /* XXX */ 41121830Sjoerg return; 41221830Sjoerg } 41321830Sjoerg#endif /* NETATALK */ 4147055Sdg if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0) 4157055Sdg goto dropanyway; 41621830Sjoerg type = ntohs(l->llc_snap.ether_type); 4177055Sdg m_adj(m, 8); 41821830Sjoerg switch (type) { 4197055Sdg#ifdef INET 4207055Sdg case ETHERTYPE_IP: 42136265Sdg if (ipflow_fastforward(m)) 42236192Sdg return; 4237055Sdg schednetisr(NETISR_IP); 4247055Sdg inq = &ipintrq; 4257055Sdg break; 4267055Sdg 4277055Sdg case ETHERTYPE_ARP: 42878295Sjlemon if (ifp->if_flags & IFF_NOARP) 42978295Sjlemon goto dropanyway; 4307055Sdg schednetisr(NETISR_ARP); 4317055Sdg inq = &arpintrq; 4327055Sdg break; 4337055Sdg#endif 43454263Sshin#ifdef INET6 43554263Sshin case ETHERTYPE_IPV6: 43654263Sshin schednetisr(NETISR_IPV6); 43754263Sshin inq = &ip6intrq; 43854263Sshin break; 43954263Sshin#endif 44021830Sjoerg#ifdef IPX 44121830Sjoerg case ETHERTYPE_IPX: 44221830Sjoerg schednetisr(NETISR_IPX); 44321830Sjoerg inq = &ipxintrq; 44421830Sjoerg break; 44521830Sjoerg#endif 4467055Sdg#ifdef NS 4477055Sdg case ETHERTYPE_NS: 4487055Sdg schednetisr(NETISR_NS); 4497055Sdg inq = &nsintrq; 4507055Sdg break; 4517055Sdg#endif 4527055Sdg#ifdef DECNET 45321830Sjoerg case ETHERTYPE_DECNET: 4547055Sdg schednetisr(NETISR_DECNET); 4557055Sdg inq = &decnetintrq; 4567055Sdg break; 4577055Sdg#endif 45821830Sjoerg#ifdef NETATALK 45921830Sjoerg case ETHERTYPE_AT: 46021830Sjoerg schednetisr(NETISR_ATALK); 46121830Sjoerg inq = &atintrq1; 46221830Sjoerg break; 46321830Sjoerg case ETHERTYPE_AARP: 46421830Sjoerg /* probably this should be done with a NETISR as well */ 46593369Smdodd aarpinput(IFP2AC(ifp), m); /* XXX */ 46621830Sjoerg return; 46721830Sjoerg#endif /* NETATALK */ 4687055Sdg default: 46921830Sjoerg /* printf("fddi_input: unknown protocol 0x%x\n", type); */ 4707055Sdg ifp->if_noproto++; 4717055Sdg goto dropanyway; 4727055Sdg } 4737055Sdg break; 4747055Sdg } 4757055Sdg#endif /* INET || NS */ 47621830Sjoerg 4777055Sdg default: 47821830Sjoerg /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */ 4797055Sdg ifp->if_noproto++; 4807055Sdg dropanyway: 4817055Sdg m_freem(m); 4827055Sdg return; 4837055Sdg } 4847055Sdg 48569152Sjlemon (void) IF_HANDOFF(inq, m, NULL); 4867055Sdg} 4877055Sdg/* 4887055Sdg * Perform common duties while attaching to interface list 4897055Sdg */ 49021830Sjoerg 4917055Sdgvoid 4927055Sdgfddi_ifattach(ifp) 49393367Smdodd struct ifnet *ifp; 4947055Sdg{ 49593367Smdodd struct ifaddr *ifa; 49693367Smdodd struct sockaddr_dl *sdl; 4977055Sdg 4987055Sdg ifp->if_type = IFT_FDDI; 4997055Sdg ifp->if_addrlen = 6; 5007055Sdg ifp->if_hdrlen = 21; 5017055Sdg ifp->if_mtu = FDDIMTU; 50268180Sume ifp->if_resolvemulti = fddi_resolvemulti; 50316063Sgpalmer ifp->if_baudrate = 100000000; 50421830Sjoerg#ifdef IFF_NOTRAILERS 50521830Sjoerg ifp->if_flags |= IFF_NOTRAILERS; 50621830Sjoerg#endif 50784931Sfjoe ifp->if_broadcastaddr = fddibroadcastaddr; 50883130Sjlemon ifa = ifaddr_byindex(ifp->if_index); 50921831Sjoerg sdl = (struct sockaddr_dl *)ifa->ifa_addr; 51021831Sjoerg sdl->sdl_type = IFT_FDDI; 51121831Sjoerg sdl->sdl_alen = ifp->if_addrlen; 51293369Smdodd bcopy(IFP2AC(ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); 5137055Sdg} 51468180Sume 51568180Sumestatic int 51668180Sumefddi_resolvemulti(ifp, llsa, sa) 51768180Sume struct ifnet *ifp; 51868180Sume struct sockaddr **llsa; 51968180Sume struct sockaddr *sa; 52068180Sume{ 52168180Sume struct sockaddr_dl *sdl; 52268180Sume struct sockaddr_in *sin; 52368180Sume#ifdef INET6 52468180Sume struct sockaddr_in6 *sin6; 52568180Sume#endif 52668180Sume u_char *e_addr; 52768180Sume 52868180Sume switch(sa->sa_family) { 52968180Sume case AF_LINK: 53068180Sume /* 53168180Sume * No mapping needed. Just check that it's a valid MC address. 53268180Sume */ 53368180Sume sdl = (struct sockaddr_dl *)sa; 53468180Sume e_addr = LLADDR(sdl); 53568180Sume if ((e_addr[0] & 1) != 1) 53693369Smdodd return (EADDRNOTAVAIL); 53768180Sume *llsa = 0; 53893369Smdodd return (0); 53968180Sume 54068180Sume#ifdef INET 54168180Sume case AF_INET: 54268180Sume sin = (struct sockaddr_in *)sa; 54368180Sume if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 54493369Smdodd return (EADDRNOTAVAIL); 54568180Sume MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 54668180Sume M_WAITOK); 54768180Sume sdl->sdl_len = sizeof *sdl; 54868180Sume sdl->sdl_family = AF_LINK; 54968180Sume sdl->sdl_index = ifp->if_index; 55068180Sume sdl->sdl_type = IFT_FDDI; 55168180Sume sdl->sdl_nlen = 0; 55268180Sume sdl->sdl_alen = ETHER_ADDR_LEN; /* XXX */ 55368180Sume sdl->sdl_slen = 0; 55468180Sume e_addr = LLADDR(sdl); 55568180Sume ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); 55668180Sume *llsa = (struct sockaddr *)sdl; 55793369Smdodd return (0); 55868180Sume#endif 55968180Sume#ifdef INET6 56068180Sume case AF_INET6: 56168180Sume sin6 = (struct sockaddr_in6 *)sa; 56268180Sume if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 56368180Sume /* 56468180Sume * An IP6 address of 0 means listen to all 56568180Sume * of the Ethernet multicast address used for IP6. 56668180Sume * (This is used for multicast routers.) 56768180Sume */ 56868180Sume ifp->if_flags |= IFF_ALLMULTI; 56968180Sume *llsa = 0; 57093369Smdodd return (0); 57168180Sume } 57268180Sume if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 57393369Smdodd return (EADDRNOTAVAIL); 57468180Sume MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 57568180Sume M_WAITOK); 57668180Sume sdl->sdl_len = sizeof *sdl; 57768180Sume sdl->sdl_family = AF_LINK; 57868180Sume sdl->sdl_index = ifp->if_index; 57968180Sume sdl->sdl_type = IFT_FDDI; 58068180Sume sdl->sdl_nlen = 0; 58168180Sume sdl->sdl_alen = ETHER_ADDR_LEN; /* XXX */ 58268180Sume sdl->sdl_slen = 0; 58368180Sume e_addr = LLADDR(sdl); 58468180Sume ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); 58568180Sume *llsa = (struct sockaddr *)sdl; 58693369Smdodd return (0); 58768180Sume#endif 58868180Sume 58968180Sume default: 59068180Sume /* 59168180Sume * Well, the text isn't quite right, but it's the name 59268180Sume * that counts... 59368180Sume */ 59493369Smdodd return (EAFNOSUPPORT); 59568180Sume } 59668180Sume} 597