if_fddisubr.c revision 93381
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1995, 1996 31590Srgrimes * Matt Thomas <matt@3am-software.com>. All rights reserved. 41590Srgrimes * Copyright (c) 1982, 1989, 1993 51590Srgrimes * The Regents of the University of California. All rights reserved. 61590Srgrimes * 71590Srgrimes * Redistribution and use in source and binary forms, with or without 81590Srgrimes * modification, are permitted provided that the following conditions 91590Srgrimes * are met: 101590Srgrimes * 1. Redistributions of source code must retain the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer. 121590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 131590Srgrimes * notice, this list of conditions and the following disclaimer in the 141590Srgrimes * documentation and/or other materials provided with the distribution. 151590Srgrimes * 3. All advertising materials mentioning features or use of this software 161590Srgrimes * must display the following acknowledgement: 171590Srgrimes * This product includes software developed by the University of 181590Srgrimes * California, Berkeley and its contributors. 191590Srgrimes * 4. Neither the name of the University nor the names of its contributors 201590Srgrimes * may be used to endorse or promote products derived from this software 211590Srgrimes * without specific prior written permission. 221590Srgrimes * 231590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 241590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 251590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 261590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 271590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 281590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 291590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 301590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 311590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3250477Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 331590Srgrimes * SUCH DAMAGE. 34264743Spfg * 351590Srgrimes * from: if_ethersubr.c,v 1.5 1994/12/13 22:31:45 wollman Exp 361590Srgrimes * $FreeBSD: head/sys/net/if_fddisubr.c 93381 2002-03-29 10:29:10Z mdodd $ 371590Srgrimes */ 381590Srgrimes 391590Srgrimes#include "opt_atalk.h" 401590Srgrimes#include "opt_inet.h" 4127887Scharnier#include "opt_inet6.h" 42131507Sru#include "opt_ipx.h" 431590Srgrimes 4495124Scharnier#include <sys/param.h> 4595124Scharnier#include <sys/systm.h> 4695124Scharnier#include <sys/kernel.h> 471590Srgrimes#include <sys/malloc.h> 48131507Sru#include <sys/mbuf.h> 491590Srgrimes#include <sys/module.h> 501590Srgrimes#include <sys/socket.h> 511590Srgrimes#include <sys/sockio.h> 521590Srgrimes 531590Srgrimes#include <net/if.h> 541590Srgrimes#include <net/if_llc.h> 55131507Sru#include <net/if_dl.h> 561590Srgrimes#include <net/if_types.h> 571590Srgrimes#include <net/netisr.h> 581590Srgrimes#include <net/route.h> 591590Srgrimes#include <net/bpf.h> 601590Srgrimes#include <net/fddi.h> 6197541Sru 621590Srgrimes#if defined(INET) || defined(INET6) 631590Srgrimes#include <netinet/in.h> 641590Srgrimes#include <netinet/in_var.h> 651590Srgrimes#include <netinet/if_ether.h> 661590Srgrimes#endif 671590Srgrimes#ifdef INET6 681590Srgrimes#include <netinet6/nd6.h> 691590Srgrimes#endif 7097541Sru 71222418Sjilles#ifdef IPX 721590Srgrimes#include <netipx/ipx.h> 731590Srgrimes#include <netipx/ipx_if.h> 741590Srgrimes#endif 75131507Sru 761590Srgrimes#ifdef NS 771590Srgrimes#include <netns/ns.h> 781590Srgrimes#include <netns/ns_if.h> 791590Srgrimes#endif 8095300Sjmallett 8195300Sjmallett#ifdef DECNET 821590Srgrimes#include <netdnet/dn.h> 831590Srgrimes#endif 8470197Sru 8570197Sru#ifdef NETATALK 861590Srgrimes#include <netatalk/at.h> 871590Srgrimes#include <netatalk/at_var.h> 881590Srgrimes#include <netatalk/at_extern.h> 891590Srgrimes 9095300Sjmallettextern u_char at_org_code[ 3 ]; 9195300Sjmallettextern u_char aarp_org_code[ 3 ]; 921590Srgrimes#endif /* NETATALK */ 931590Srgrimes 941590Srgrimesstatic int fddi_resolvemulti(struct ifnet *, struct sockaddr **, 951590Srgrimes struct sockaddr *); 961590Srgrimes 971590Srgrimes#define IFP2AC(IFP) ((struct arpcom *)IFP) 981590Srgrimes#define senderr(e) { error = (e); goto bad; } 991590Srgrimes 1001590Srgrimes/* 1011590Srgrimes * FDDI output routine. 1021590Srgrimes * Encapsulate a packet of type family for the local net. 1031590Srgrimes * Use trailer local net encapsulation if enough data in first 1041590Srgrimes * packet leaves a multiple of 512 bytes of data in remainder. 1051590Srgrimes * Assumes that ifp is actually pointer to arpcom structure. 10679755Sdd */ 107212244Sjillesint 1081590Srgrimesfddi_output(ifp, m, dst, rt0) 1091590Srgrimes struct ifnet *ifp; 1101590Srgrimes struct mbuf *m; 111212244Sjilles struct sockaddr *dst; 112212244Sjilles struct rtentry *rt0; 113212244Sjilles{ 1141590Srgrimes u_int16_t type; 1151590Srgrimes int loop_copy = 0, error = 0, hdrcmplt = 0; 1161590Srgrimes u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN]; 1171590Srgrimes struct rtentry *rt; 1181590Srgrimes struct fddi_header *fh; 1191590Srgrimes struct arpcom *ac = IFP2AC(ifp); 1201590Srgrimes 1211590Srgrimes if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 1221590Srgrimes senderr(ENETDOWN); 1231590Srgrimes getmicrotime(&ifp->if_lastchange); 1241590Srgrimes if ((rt = rt0) != NULL) { 1251590Srgrimes if ((rt->rt_flags & RTF_UP) == 0) { 1261590Srgrimes if ((rt0 = rt = rtalloc1(dst, 1, 0UL)) != NULL) 127221013Sjilles rt->rt_refcnt--; 1281590Srgrimes else 129221013Sjilles senderr(EHOSTUNREACH); 130131491Sru } 131131491Sru if (rt->rt_flags & RTF_GATEWAY) { 1321590Srgrimes if (rt->rt_gwroute == 0) 1331590Srgrimes goto lookup; 134131491Sru if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 135131491Sru rtfree(rt); rt = rt0; 1361590Srgrimes lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL); 1371590Srgrimes if ((rt = rt->rt_gwroute) == 0) 1381590Srgrimes senderr(EHOSTUNREACH); 1391590Srgrimes } 1401590Srgrimes } 141131491Sru if (rt->rt_flags & RTF_REJECT) 142131491Sru if (rt->rt_rmx.rmx_expire == 0 || 143221013Sjilles time_second < rt->rt_rmx.rmx_expire) 1441590Srgrimes senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 145221013Sjilles } 1461590Srgrimes switch (dst->sa_family) { 1471590Srgrimes 148131491Sru#ifdef INET 149131491Sru case AF_INET: { 1501590Srgrimes if (!arpresolve(ifp, rt, m, dst, edst, rt0)) 1511590Srgrimes return (0); /* if not yet resolved */ 1521590Srgrimes type = htons(ETHERTYPE_IP); 1531590Srgrimes break; 1541590Srgrimes } 1551590Srgrimes#endif 1561590Srgrimes#ifdef INET6 1571590Srgrimes case AF_INET6: 1581590Srgrimes if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)) { 1591590Srgrimes /* Something bad happened */ 1601590Srgrimes return (0); 1611590Srgrimes } 1621590Srgrimes type = htons(ETHERTYPE_IPV6); 1631590Srgrimes break; 164131491Sru#endif 165131491Sru#ifdef IPX 1661590Srgrimes case AF_IPX: 1671590Srgrimes type = htons(ETHERTYPE_IPX); 168131491Sru bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 169131491Sru (caddr_t)edst, FDDI_ADDR_LEN); 1701590Srgrimes break; 1711590Srgrimes#endif 1721590Srgrimes#ifdef NETATALK 1731590Srgrimes case AF_APPLETALK: { 174222421Sjilles struct at_ifaddr *aa; 1751590Srgrimes if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) 1761590Srgrimes return (0); 1771590Srgrimes /* 1781590Srgrimes * ifaddr is the first thing in at_ifaddr 1791590Srgrimes */ 1801590Srgrimes if ((aa = at_ifawithnet( (struct sockaddr_at *)dst)) == 0) 1811590Srgrimes goto bad; 1821590Srgrimes 1831590Srgrimes /* 1841590Srgrimes * In the phase 2 case, we need to prepend an mbuf for the llc header. 1851590Srgrimes * Since we must preserve the value of m, which is passed to us by 18679755Sdd * value, we m_copy() the first mbuf, and use it for our llc header. 1871590Srgrimes */ 188222421Sjilles if (aa->aa_flags & AFA_PHASE2) { 1891590Srgrimes struct llc llc; 1901590Srgrimes 1911590Srgrimes M_PREPEND(m, LLC_SNAPFRAMELEN, M_TRYWAIT); 1921590Srgrimes if (m == 0) 193130116Sdas senderr(ENOBUFS); 194130116Sdas llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 195130117Sdas llc.llc_control = LLC_UI; 196143906Sdas bcopy(at_org_code, llc.llc_snap.org_code, sizeof(at_org_code)); 197147370Sru llc.llc_snap.ether_type = htons(ETHERTYPE_AT); 198143906Sdas bcopy(&llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN); 199143906Sdas type = 0; 200143906Sdas } else { 2011590Srgrimes type = htons(ETHERTYPE_AT); 2021590Srgrimes } 2031590Srgrimes break; 2041590Srgrimes } 2051590Srgrimes#endif /* NETATALK */ 2061590Srgrimes#ifdef NS 2071590Srgrimes case AF_NS: 2081590Srgrimes type = htons(ETHERTYPE_NS); 2091590Srgrimes bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 2101590Srgrimes (caddr_t)edst, FDDI_ADDR_LEN); 2111590Srgrimes break; 2121590Srgrimes#endif 2131590Srgrimes 2141590Srgrimes case pseudo_AF_HDRCMPLT: 21515163Smpp { 2161590Srgrimes struct ether_header *eh; 217130116Sdas hdrcmplt = 1; 2181590Srgrimes eh = (struct ether_header *)dst->sa_data; 2191590Srgrimes bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, FDDI_ADDR_LEN); 2201590Srgrimes /* FALLTHROUGH */ 2211590Srgrimes } 2221590Srgrimes 2231590Srgrimes case AF_UNSPEC: 22463734Schris { 225130116Sdas struct ether_header *eh; 226130116Sdas loop_copy = -1; 227130116Sdas eh = (struct ether_header *)dst->sa_data; 228130116Sdas bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, FDDI_ADDR_LEN); 229130116Sdas if (*edst & 1) 2301590Srgrimes m->m_flags |= (M_BCAST|M_MCAST); 2311590Srgrimes type = eh->ether_type; 2321590Srgrimes break; 2331590Srgrimes } 2341590Srgrimes 23570197Sru case AF_IMPLINK: 23670197Sru { 23770197Sru fh = mtod(m, struct fddi_header *); 2381590Srgrimes error = EPROTONOSUPPORT; 2391590Srgrimes switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) { 2401590Srgrimes case FDDIFC_LLC_ASYNC: { 2411590Srgrimes /* legal priorities are 0 through 7 */ 242130116Sdas if ((fh->fddi_fc & FDDIFC_Z) > 7) 243130116Sdas goto bad; 244130116Sdas break; 245130116Sdas } 246130116Sdas case FDDIFC_LLC_SYNC: { 2471590Srgrimes /* FDDIFC_Z bits reserved, must be zero */ 2481590Srgrimes if (fh->fddi_fc & FDDIFC_Z) 2491590Srgrimes goto bad; 2501590Srgrimes break; 2511590Srgrimes } 252130116Sdas case FDDIFC_SMT: { 2531590Srgrimes /* FDDIFC_Z bits must be non zero */ 2541590Srgrimes if ((fh->fddi_fc & FDDIFC_Z) == 0) 2551590Srgrimes goto bad; 2561590Srgrimes break; 257130116Sdas } 258130116Sdas default: { 259130116Sdas /* anything else is too dangerous */ 260130116Sdas goto bad; 261130116Sdas } 262130116Sdas } 263130116Sdas error = 0; 264130116Sdas if (fh->fddi_dhost[0] & 1) 265130116Sdas m->m_flags |= (M_BCAST|M_MCAST); 266130116Sdas goto queue_it; 267130116Sdas } 268130116Sdas default: 269130116Sdas printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 270130116Sdas dst->sa_family); 271130116Sdas senderr(EAFNOSUPPORT); 272130116Sdas } 2731590Srgrimes 274222421Sjilles /* 2751590Srgrimes * Add LLC header. 2761590Srgrimes */ 2771590Srgrimes if (type != 0) { 278222421Sjilles struct llc *l; 2791590Srgrimes M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT); 280222421Sjilles if (m == 0) 2811590Srgrimes senderr(ENOBUFS); 282222421Sjilles l = mtod(m, struct llc *); 28395300Sjmallett l->llc_control = LLC_UI; 28495300Sjmallett l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP; 28595300Sjmallett l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0; 28695300Sjmallett bcopy((caddr_t)&type, (caddr_t)&l->llc_snap.ether_type, 28795300Sjmallett sizeof(u_int16_t)); 288212244Sjilles } 289212244Sjilles 290212244Sjilles /* 291212244Sjilles * Add local net header. If no space in first mbuf, 292212244Sjilles * allocate another. 293264743Spfg */ 294264743Spfg M_PREPEND(m, FDDI_HDR_LEN, M_DONTWAIT); 295264743Spfg if (m == 0) 2961590Srgrimes senderr(ENOBUFS); 2971590Srgrimes fh = mtod(m, struct fddi_header *); 2981590Srgrimes fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; 2991590Srgrimes bcopy((caddr_t)edst, (caddr_t)fh->fddi_dhost, FDDI_ADDR_LEN); 30072304Sache queue_it: 30172313Sru if (hdrcmplt) 30272313Sru bcopy((caddr_t)esrc, (caddr_t)fh->fddi_shost, FDDI_ADDR_LEN); 30372304Sache else 3041590Srgrimes bcopy((caddr_t)ac->ac_enaddr, (caddr_t)fh->fddi_shost, 3051590Srgrimes FDDI_ADDR_LEN); 3061590Srgrimes 307215520Sjilles /* 308215520Sjilles * If a simplex interface, and the packet is being sent to our 309215520Sjilles * Ethernet address or a broadcast address, loopback a copy. 310215520Sjilles * XXX To make a simplex device behave exactly like a duplex 311215520Sjilles * device, we should copy in the case of sending to our own 312215520Sjilles * ethernet address (thus letting the original actually appear 313215520Sjilles * on the wire). However, we don't do that here for security 314140368Sru * reasons and compatibility with the original behavior. 31586824Sdd */ 31695300Sjmallett if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 31795300Sjmallett if ((m->m_flags & M_BCAST) || loop_copy) { 31895300Sjmallett struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 31995300Sjmallett 32097541Sru (void) if_simloop(ifp, 32197541Sru n, dst->sa_family, FDDI_HDR_LEN); 32297643Skeramida } else if (bcmp(fh->fddi_dhost, 3231590Srgrimes fh->fddi_shost, FDDI_ADDR_LEN) == 0) { 324215520Sjilles (void) if_simloop(ifp, 32595300Sjmallett m, dst->sa_family, FDDI_HDR_LEN); 326215520Sjilles return (0); /* XXX */ 32779366Sru } 32895300Sjmallett } 32995300Sjmallett 33095300Sjmallett if (! IF_HANDOFF(&ifp->if_snd, m, ifp)) 33195300Sjmallett senderr(ENOBUFS); 33295300Sjmallett return (error); 33395300Sjmallett 3341590Srgrimesbad: 3351590Srgrimes ifp->if_oerrors++; 33627887Scharnier if (m) 3371590Srgrimes m_freem(m); 3381590Srgrimes return (error); 3391590Srgrimes} 3401590Srgrimes 3411590Srgrimes/* 342221026Sjilles * Process a received FDDI packet; 343221026Sjilles * the packet is in the mbuf chain m without 344221026Sjilles * the fddi header, which is provided separately. 345221026Sjilles */ 346221026Sjillesvoid 347221026Sjillesfddi_input(ifp, fh, m) 348221026Sjilles struct ifnet *ifp; 349221026Sjilles struct fddi_header *fh; 350233648Seadler struct mbuf *m; 351221026Sjilles{ 352222421Sjilles struct ifqueue *inq; 353222421Sjilles struct llc *l; 354222421Sjilles 355222421Sjilles /* 356222421Sjilles * Discard packet if interface is not up. 357222421Sjilles */ 358222421Sjilles if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 359222421Sjilles goto dropanyway; 360222421Sjilles 361222421Sjilles /* 362222421Sjilles * Discard non local unicast packets when interface 3631590Srgrimes * is in promiscuous mode. 3641590Srgrimes */ 3651590Srgrimes if ((ifp->if_flags & IFF_PROMISC) && ((fh->fddi_dhost[0] & 1) == 0) && 3661590Srgrimes (bcmp(IFP2AC(ifp)->ac_enaddr, (caddr_t)fh->fddi_dhost, 3671590Srgrimes FDDI_ADDR_LEN) != 0)) 368143906Sdas goto dropanyway; 369143906Sdas 370143906Sdas /* 371143906Sdas * Set mbuf flags for bcast/mcast. 372143906Sdas */ 3731590Srgrimes if (fh->fddi_dhost[0] & 1) { 374131491Sru if (bcmp((caddr_t)ifp->if_broadcastaddr, 375145084Sstefanf (caddr_t)fh->fddi_dhost, FDDI_ADDR_LEN) == 0) 376145084Sstefanf m->m_flags |= M_BCAST; 377145084Sstefanf else 378131511Stjr m->m_flags |= M_MCAST; 379131511Stjr ifp->if_imcasts++; 380131511Stjr } 381131519Stjr 382131519Stjr /* 383 * Update interface statistics. 384 */ 385 getmicrotime(&ifp->if_lastchange); 386 ifp->if_ibytes += (m->m_pkthdr.len + FDDI_HDR_LEN); 387 388#ifdef M_LINK0 389 /* 390 * If this has a LLC priority of 0, then mark it so upper 391 * layers have a hint that it really came via a FDDI/Ethernet 392 * bridge. 393 */ 394 if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0) 395 m->m_flags |= M_LINK0; 396#endif 397 398 m = m_pullup(m, sizeof(struct llc)); 399 if (m == 0) { 400 ifp->if_ierrors++; 401 goto dropanyway; 402 } 403 l = mtod(m, struct llc *); 404 405 switch (l->llc_dsap) { 406 case LLC_SNAP_LSAP: 407 { 408 u_int16_t type; 409 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP) { 410 ifp->if_noproto++; 411 goto dropanyway; 412 } 413#ifdef NETATALK 414 if (Bcmp(&(l->llc_snap.org_code)[0], at_org_code, 415 sizeof(at_org_code)) == 0 && 416 ntohs(l->llc_snap.ether_type) == ETHERTYPE_AT) { 417 inq = &atintrq2; 418 m_adj(m, LLC_SNAPFRAMELEN); 419 schednetisr(NETISR_ATALK); 420 break; 421 } 422 423 if (Bcmp(&(l->llc_snap.org_code)[0], aarp_org_code, 424 sizeof(aarp_org_code)) == 0 && 425 ntohs(l->llc_snap.ether_type) == ETHERTYPE_AARP) { 426 m_adj(m, LLC_SNAPFRAMELEN); 427 aarpinput(IFP2AC(ifp), m); /* XXX */ 428 return; 429 } 430#endif /* NETATALK */ 431 if (l->llc_snap.org_code[0] != 0 || 432 l->llc_snap.org_code[1] != 0 || 433 l->llc_snap.org_code[2] != 0) { 434 ifp->if_noproto++; 435 goto dropanyway; 436 } 437 438 type = ntohs(l->llc_snap.ether_type); 439 m_adj(m, LLC_SNAPFRAMELEN); 440 441 switch (type) { 442#ifdef INET 443 case ETHERTYPE_IP: 444 if (ipflow_fastforward(m)) 445 return; 446 schednetisr(NETISR_IP); 447 inq = &ipintrq; 448 break; 449 450 case ETHERTYPE_ARP: 451 if (ifp->if_flags & IFF_NOARP) 452 goto dropanyway; 453 schednetisr(NETISR_ARP); 454 inq = &arpintrq; 455 break; 456#endif 457#ifdef INET6 458 case ETHERTYPE_IPV6: 459 schednetisr(NETISR_IPV6); 460 inq = &ip6intrq; 461 break; 462#endif 463#ifdef IPX 464 case ETHERTYPE_IPX: 465 schednetisr(NETISR_IPX); 466 inq = &ipxintrq; 467 break; 468#endif 469#ifdef NS 470 case ETHERTYPE_NS: 471 schednetisr(NETISR_NS); 472 inq = &nsintrq; 473 break; 474#endif 475#ifdef DECNET 476 case ETHERTYPE_DECNET: 477 schednetisr(NETISR_DECNET); 478 inq = &decnetintrq; 479 break; 480#endif 481#ifdef NETATALK 482 case ETHERTYPE_AT: 483 schednetisr(NETISR_ATALK); 484 inq = &atintrq1; 485 break; 486 case ETHERTYPE_AARP: 487 /* probably this should be done with a NETISR as well */ 488 aarpinput(IFP2AC(ifp), m); /* XXX */ 489 return; 490#endif /* NETATALK */ 491 default: 492 /* printf("fddi_input: unknown protocol 0x%x\n", type); */ 493 ifp->if_noproto++; 494 goto dropanyway; 495 } 496 break; 497 } 498 499 default: 500 /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */ 501 ifp->if_noproto++; 502 goto dropanyway; 503 } 504 505 (void) IF_HANDOFF(inq, m, NULL); 506 return; 507 508dropanyway: 509 ifp->if_iqdrops++; 510 if (m) 511 m_freem(m); 512 return; 513} 514 515/* 516 * Perform common duties while attaching to interface list 517 */ 518void 519fddi_ifattach(ifp) 520 struct ifnet *ifp; 521{ 522 struct ifaddr *ifa; 523 struct sockaddr_dl *sdl; 524 525 ifp->if_type = IFT_FDDI; 526 ifp->if_addrlen = FDDI_ADDR_LEN; 527 ifp->if_hdrlen = 21; 528 529 if_attach(ifp); /* Must be called before additional assignments */ 530 531 ifp->if_mtu = FDDIMTU; 532 ifp->if_output = fddi_output; 533 ifp->if_resolvemulti = fddi_resolvemulti; 534 ifp->if_broadcastaddr = fddibroadcastaddr; 535 ifp->if_baudrate = 100000000; 536#ifdef IFF_NOTRAILERS 537 ifp->if_flags |= IFF_NOTRAILERS; 538#endif 539 ifa = ifaddr_byindex(ifp->if_index); 540 if (ifa == NULL) { 541 printf("%s(): no lladdr for %s%d!\n", __FUNCTION__, 542 ifp->if_name, ifp->if_unit); 543 return; 544 } 545 546 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 547 sdl->sdl_type = IFT_FDDI; 548 sdl->sdl_alen = ifp->if_addrlen; 549 bcopy(IFP2AC(ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); 550 551 return; 552} 553 554static int 555fddi_resolvemulti(ifp, llsa, sa) 556 struct ifnet *ifp; 557 struct sockaddr **llsa; 558 struct sockaddr *sa; 559{ 560 struct sockaddr_dl *sdl; 561 struct sockaddr_in *sin; 562#ifdef INET6 563 struct sockaddr_in6 *sin6; 564#endif 565 u_char *e_addr; 566 567 switch(sa->sa_family) { 568 case AF_LINK: 569 /* 570 * No mapping needed. Just check that it's a valid MC address. 571 */ 572 sdl = (struct sockaddr_dl *)sa; 573 e_addr = LLADDR(sdl); 574 if ((e_addr[0] & 1) != 1) 575 return (EADDRNOTAVAIL); 576 *llsa = 0; 577 return (0); 578 579#ifdef INET 580 case AF_INET: 581 sin = (struct sockaddr_in *)sa; 582 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 583 return (EADDRNOTAVAIL); 584 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 585 M_WAITOK); 586 sdl->sdl_len = sizeof *sdl; 587 sdl->sdl_family = AF_LINK; 588 sdl->sdl_index = ifp->if_index; 589 sdl->sdl_type = IFT_FDDI; 590 sdl->sdl_nlen = 0; 591 sdl->sdl_alen = FDDI_ADDR_LEN; 592 sdl->sdl_slen = 0; 593 e_addr = LLADDR(sdl); 594 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); 595 *llsa = (struct sockaddr *)sdl; 596 return (0); 597#endif 598#ifdef INET6 599 case AF_INET6: 600 sin6 = (struct sockaddr_in6 *)sa; 601 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 602 /* 603 * An IP6 address of 0 means listen to all 604 * of the Ethernet multicast address used for IP6. 605 * (This is used for multicast routers.) 606 */ 607 ifp->if_flags |= IFF_ALLMULTI; 608 *llsa = 0; 609 return (0); 610 } 611 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 612 return (EADDRNOTAVAIL); 613 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 614 M_WAITOK); 615 sdl->sdl_len = sizeof *sdl; 616 sdl->sdl_family = AF_LINK; 617 sdl->sdl_index = ifp->if_index; 618 sdl->sdl_type = IFT_FDDI; 619 sdl->sdl_nlen = 0; 620 sdl->sdl_alen = FDDI_ADDR_LEN; 621 sdl->sdl_slen = 0; 622 e_addr = LLADDR(sdl); 623 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); 624 *llsa = (struct sockaddr *)sdl; 625 return (0); 626#endif 627 628 default: 629 /* 630 * Well, the text isn't quite right, but it's the name 631 * that counts... 632 */ 633 return (EAFNOSUPPORT); 634 } 635 636 return (0); 637} 638 639static moduledata_t fddi_mod = { 640 "fddi", /* module name */ 641 NULL, /* event handler */ 642 0 /* extra data */ 643}; 644 645DECLARE_MODULE(fddi, fddi_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 646MODULE_VERSION(fddi, 1); 647