if_fddisubr.c revision 25653
1/* 2 * Copyright (c) 1995, 1996 3 * Matt Thomas <matt@3am-software.com>. All rights reserved. 4 * Copyright (c) 1982, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: if_ethersubr.c,v 1.5 1994/12/13 22:31:45 wollman Exp 36 * $Id: if_fddisubr.c,v 1.18 1997/03/24 11:24:46 bde Exp $ 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/malloc.h> 43#include <sys/mbuf.h> 44#include <sys/protosw.h> 45#include <sys/socket.h> 46#include <sys/errno.h> 47#include <sys/syslog.h> 48 49#include <machine/cpu.h> 50 51#include <net/if.h> 52#include <net/netisr.h> 53#include <net/route.h> 54#include <net/if_llc.h> 55#include <net/if_dl.h> 56#include <net/if_types.h> 57 58#ifdef INET 59#include <netinet/in.h> 60#include <netinet/in_var.h> 61#endif 62#include <netinet/if_ether.h> 63#if defined(__FreeBSD__) 64#include <netinet/if_fddi.h> 65#else 66#include <net/if_fddi.h> 67#endif 68 69#ifdef IPX 70#include <netipx/ipx.h> 71#include <netipx/ipx_if.h> 72#endif 73 74#ifdef NS 75#include <netns/ns.h> 76#include <netns/ns_if.h> 77#endif 78 79#ifdef DECNET 80#include <netdnet/dn.h> 81#endif 82 83#ifdef ISO 84#include <netiso/argo_debug.h> 85#include <netiso/iso.h> 86#include <netiso/iso_var.h> 87#include <netiso/iso_snpac.h> 88#endif 89 90#ifdef LLC 91#include <netccitt/dll.h> 92#include <netccitt/llc_var.h> 93#endif 94 95#ifdef NETATALK 96#include <netatalk/at.h> 97#include <netatalk/at_var.h> 98#include <netatalk/at_extern.h> 99 100#define llc_snap_org_code llc_un.type_snap.org_code 101#define llc_snap_ether_type llc_un.type_snap.ether_type 102 103extern u_char at_org_code[ 3 ]; 104extern u_char aarp_org_code[ 3 ]; 105#endif /* NETATALK */ 106 107#if defined(LLC) && defined(CCITT) 108extern struct ifqueue pkintrq; 109#endif 110 111#include "bpfilter.h" 112 113#define senderr(e) { error = (e); goto bad;} 114 115/* 116 * This really should be defined in if_llc.h but in case it isn't. 117 */ 118#ifndef llc_snap 119#define llc_snap llc_un.type_snap 120#endif 121 122#if defined(__bsdi__) || defined(__NetBSD__) 123#define RTALLOC1(a, b) rtalloc1(a, b) 124#define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e) 125#elif defined(__FreeBSD__) 126#define RTALLOC1(a, b) rtalloc1(a, b, 0UL) 127#define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e, f) 128#endif 129/* 130 * FDDI output routine. 131 * Encapsulate a packet of type family for the local net. 132 * Use trailer local net encapsulation if enough data in first 133 * packet leaves a multiple of 512 bytes of data in remainder. 134 * Assumes that ifp is actually pointer to arpcom structure. 135 */ 136int 137fddi_output(ifp, m0, dst, rt0) 138 register struct ifnet *ifp; 139 struct mbuf *m0; 140 struct sockaddr *dst; 141 struct rtentry *rt0; 142{ 143 u_int16_t type; 144 int s, error = 0; 145 u_char edst[6]; 146 register struct mbuf *m = m0; 147 register struct rtentry *rt; 148 register struct fddi_header *fh; 149 struct mbuf *mcopy = (struct mbuf *)0; 150 struct arpcom *ac = (struct arpcom *)ifp; 151 152 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 153 senderr(ENETDOWN); 154 ifp->if_lastchange = time; 155#if !defined(__bsdi__) || _BSDI_VERSION >= 199401 156 if (rt = rt0) { 157 if ((rt->rt_flags & RTF_UP) == 0) { 158 if (rt0 = rt = RTALLOC1(dst, 1)) 159 rt->rt_refcnt--; 160 else 161 senderr(EHOSTUNREACH); 162 } 163 if (rt->rt_flags & RTF_GATEWAY) { 164 if (rt->rt_gwroute == 0) 165 goto lookup; 166 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 167 rtfree(rt); rt = rt0; 168 lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1); 169 if ((rt = rt->rt_gwroute) == 0) 170 senderr(EHOSTUNREACH); 171 } 172 } 173 if (rt->rt_flags & RTF_REJECT) 174 if (rt->rt_rmx.rmx_expire == 0 || 175 time.tv_sec < rt->rt_rmx.rmx_expire) 176 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 177 } 178#endif 179 switch (dst->sa_family) { 180 181#ifdef INET 182 case AF_INET: { 183#if !defined(__bsdi__) || _BSDI_VERSION >= 199401 184 if (!ARPRESOLVE(ac, rt, m, dst, edst, rt0)) 185 return (0); /* if not yet resolved */ 186#else 187 int usetrailers; 188 if (!arpresolve(ac, m, &((struct sockaddr_in *)dst)->sin_addr, edst, &usetrailers)) 189 return (0); /* if not yet resolved */ 190#endif 191 /* If broadcasting on a simplex interface, loopback a copy */ 192 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 193 mcopy = m_copy(m, 0, (int)M_COPYALL); 194 type = htons(ETHERTYPE_IP); 195 break; 196 } 197#endif 198#ifdef IPX 199 case AF_IPX: 200 { 201 struct ifaddr *ia; 202 203 type = htons(ETHERTYPE_IPX); 204 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 205 (caddr_t)edst, sizeof (edst)); 206 207 for(ia = ifp->if_addrhead.tqh_first; ia != 0; 208 ia = ia->ifa_link.tqe_next) { 209 if(ia->ifa_addr->sa_family == AF_IPX && 210 !bcmp((caddr_t)edst, 211 (caddr_t)&((struct ipx_ifaddr *)ia)->ia_addr.sipx_addr.x_host, 212 sizeof(edst)) ) 213 return (looutput(ifp, m, dst, rt)); 214 } 215 216 /* If broadcasting on a simplex interface, loopback a copy */ 217 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 218 mcopy = m_copy(m, 0, (int)M_COPYALL); 219 break; 220 } 221#endif 222#ifdef NETATALK 223 case AF_APPLETALK: { 224 struct at_ifaddr *aa; 225 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) { 226#ifdef NETATALKDEBUG 227 extern char *prsockaddr(struct sockaddr *); 228 printf("aarpresolv: failed for %s\n", prsockaddr(dst)); 229#endif 230 return (0); 231 } 232 /* 233 * ifaddr is the first thing in at_ifaddr 234 */ 235 if ((aa = (struct at_ifaddr *)at_ifawithnet( 236 (struct sockaddr_at *)dst, &ifp->if_addrhead)) 237 == 0) 238 goto bad; 239 240 /* 241 * In the phase 2 case, we need to prepend an mbuf for the llc header. 242 * Since we must preserve the value of m, which is passed to us by 243 * value, we m_copy() the first mbuf, and use it for our llc header. 244 */ 245 if (aa->aa_flags & AFA_PHASE2) { 246 struct llc llc; 247 248 M_PREPEND(m, sizeof(struct llc), M_WAIT); 249 if (m == 0) 250 senderr(ENOBUFS); 251 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 252 llc.llc_control = LLC_UI; 253 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); 254 llc.llc_snap_ether_type = htons(ETHERTYPE_AT); 255 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); 256 type = 0; 257 } else { 258 type = htons(ETHERTYPE_AT); 259 } 260 break; 261 } 262#endif /* NETATALK */ 263#ifdef NS 264 case AF_NS: 265 type = htons(ETHERTYPE_NS); 266 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 267 (caddr_t)edst, sizeof (edst)); 268 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) 269 return (looutput(ifp, m, dst, rt)); 270 /* If broadcasting on a simplex interface, loopback a copy */ 271 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 272 mcopy = m_copy(m, 0, (int)M_COPYALL); 273 break; 274#endif 275#ifdef ISO 276 case AF_ISO: { 277 int snpalen; 278 struct llc *l; 279 register struct sockaddr_dl *sdl; 280 281 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 282 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 283 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 284 } else if (error = 285 iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 286 (char *)edst, &snpalen)) 287 goto bad; /* Not Resolved */ 288 /* If broadcasting on a simplex interface, loopback a copy */ 289 if (*edst & 1) 290 m->m_flags |= (M_BCAST|M_MCAST); 291 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && 292 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 293 M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT); 294 if (mcopy) { 295 fh = mtod(mcopy, struct fddi_header *); 296 bcopy((caddr_t)edst, 297 (caddr_t)fh->fddi_dhost, sizeof (edst)); 298 bcopy((caddr_t)ac->ac_enaddr, 299 (caddr_t)fh->fddi_shost, sizeof (edst)); 300 } 301 } 302 M_PREPEND(m, 3, M_DONTWAIT); 303 if (m == NULL) 304 return (0); 305 type = 0; 306 l = mtod(m, struct llc *); 307 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 308 l->llc_control = LLC_UI; 309 IFDEBUG(D_ETHER) 310 int i; 311 printf("unoutput: sending pkt to: "); 312 for (i=0; i<6; i++) 313 printf("%x ", edst[i] & 0xff); 314 printf("\n"); 315 ENDDEBUG 316 } break; 317#endif /* ISO */ 318#ifdef LLC 319/* case AF_NSAP: */ 320 case AF_CCITT: { 321 register struct sockaddr_dl *sdl = 322 (struct sockaddr_dl *) rt -> rt_gateway; 323 324 if (sdl && sdl->sdl_family != AF_LINK && sdl->sdl_alen <= 0) 325 goto bad; /* Not a link interface ? Funny ... */ 326 bcopy(LLADDR(sdl), (char *)edst, sizeof(edst)); 327 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && 328 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 329 M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT); 330 if (mcopy) { 331 fh = mtod(mcopy, struct fddi_header *); 332 bcopy((caddr_t)edst, 333 (caddr_t)fh->fddi_dhost, sizeof (edst)); 334 bcopy((caddr_t)ac->ac_enaddr, 335 (caddr_t)fh->fddi_shost, sizeof (edst)); 336 fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; 337 } 338 } 339 type = 0; 340#ifdef LLC_DEBUG 341 { 342 int i; 343 register struct llc *l = mtod(m, struct llc *); 344 345 printf("fddi_output: sending LLC2 pkt to: "); 346 for (i=0; i<6; i++) 347 printf("%x ", edst[i] & 0xff); 348 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 349 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, 350 l->llc_control & 0xff); 351 352 } 353#endif /* LLC_DEBUG */ 354 } break; 355#endif /* LLC */ 356 357 case AF_UNSPEC: 358 { 359 struct ether_header *eh; 360 eh = (struct ether_header *)dst->sa_data; 361 (void)memcpy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 362 if (*edst & 1) 363 m->m_flags |= (M_BCAST|M_MCAST); 364 type = eh->ether_type; 365 break; 366 } 367 368#if NBPFILTER > 0 369 case AF_IMPLINK: 370 { 371 fh = mtod(m, struct fddi_header *); 372 error = EPROTONOSUPPORT; 373 switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) { 374 case FDDIFC_LLC_ASYNC: { 375 /* legal priorities are 0 through 7 */ 376 if ((fh->fddi_fc & FDDIFC_Z) > 7) 377 goto bad; 378 break; 379 } 380 case FDDIFC_LLC_SYNC: { 381 /* FDDIFC_Z bits reserved, must be zero */ 382 if (fh->fddi_fc & FDDIFC_Z) 383 goto bad; 384 break; 385 } 386 case FDDIFC_SMT: { 387 /* FDDIFC_Z bits must be non zero */ 388 if ((fh->fddi_fc & FDDIFC_Z) == 0) 389 goto bad; 390 break; 391 } 392 default: { 393 /* anything else is too dangerous */ 394 goto bad; 395 } 396 } 397 error = 0; 398 if (fh->fddi_dhost[0] & 1) 399 m->m_flags |= (M_BCAST|M_MCAST); 400 goto queue_it; 401 } 402#endif 403 default: 404 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 405 dst->sa_family); 406 senderr(EAFNOSUPPORT); 407 } 408 409 410 if (mcopy) 411 (void) looutput(ifp, mcopy, dst, rt); 412 if (type != 0) { 413 register struct llc *l; 414 M_PREPEND(m, sizeof (struct llc), M_DONTWAIT); 415 if (m == 0) 416 senderr(ENOBUFS); 417 l = mtod(m, struct llc *); 418 l->llc_control = LLC_UI; 419 l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP; 420 l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0; 421 (void)memcpy((caddr_t) &l->llc_snap.ether_type, (caddr_t) &type, 422 sizeof(u_int16_t)); 423 } 424 /* 425 * Add local net header. If no space in first mbuf, 426 * allocate another. 427 */ 428 M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT); 429 if (m == 0) 430 senderr(ENOBUFS); 431 fh = mtod(m, struct fddi_header *); 432 fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; 433 (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst)); 434 queue_it: 435 (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr, 436 sizeof(fh->fddi_shost)); 437 s = splimp(); 438 /* 439 * Queue message on interface, and start output if interface 440 * not yet active. 441 */ 442 if (IF_QFULL(&ifp->if_snd)) { 443 IF_DROP(&ifp->if_snd); 444 splx(s); 445 senderr(ENOBUFS); 446 } 447 ifp->if_obytes += m->m_pkthdr.len; 448 IF_ENQUEUE(&ifp->if_snd, m); 449 if ((ifp->if_flags & IFF_OACTIVE) == 0) 450 (*ifp->if_start)(ifp); 451 splx(s); 452 if (m->m_flags & M_MCAST) 453 ifp->if_omcasts++; 454 return (error); 455 456bad: 457 if (m) 458 m_freem(m); 459 return (error); 460} 461 462/* 463 * Process a received FDDI packet; 464 * the packet is in the mbuf chain m without 465 * the fddi header, which is provided separately. 466 */ 467void 468fddi_input(ifp, fh, m) 469 struct ifnet *ifp; 470 register struct fddi_header *fh; 471 struct mbuf *m; 472{ 473 register struct ifqueue *inq; 474 register struct llc *l; 475 int s; 476 477 if ((ifp->if_flags & IFF_UP) == 0) { 478 m_freem(m); 479 return; 480 } 481 ifp->if_lastchange = time; 482 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh); 483 if (fh->fddi_dhost[0] & 1) { 484 if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost, 485 sizeof(fddibroadcastaddr)) == 0) 486 m->m_flags |= M_BCAST; 487 else 488 m->m_flags |= M_MCAST; 489 ifp->if_imcasts++; 490 } else if ((ifp->if_flags & IFF_PROMISC) 491 && bcmp(((struct arpcom *)ifp)->ac_enaddr, (caddr_t)fh->fddi_dhost, 492 sizeof(fh->fddi_dhost)) != 0) { 493 m_freem(m); 494 return; 495 } 496 497#ifdef M_LINK0 498 /* 499 * If this has a LLC priority of 0, then mark it so upper 500 * layers have a hint that it really came via a FDDI/Ethernet 501 * bridge. 502 */ 503 if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0) 504 m->m_flags |= M_LINK0; 505#endif 506 507 l = mtod(m, struct llc *); 508 switch (l->llc_dsap) { 509#if defined(INET) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK) 510 case LLC_SNAP_LSAP: 511 { 512 u_int16_t type; 513 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP) 514 goto dropanyway; 515#ifdef NETATALK 516 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, 517 sizeof(at_org_code)) == 0 && 518 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { 519 inq = &atintrq2; 520 m_adj( m, sizeof( struct llc )); 521 schednetisr(NETISR_ATALK); 522 break; 523 } 524 525 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, 526 sizeof(aarp_org_code)) == 0 && 527 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { 528 m_adj( m, sizeof( struct llc )); 529 aarpinput((struct arpcom *)ifp, m); /* XXX */ 530 return; 531 } 532#endif /* NETATALK */ 533 if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0) 534 goto dropanyway; 535 type = ntohs(l->llc_snap.ether_type); 536 m_adj(m, 8); 537 switch (type) { 538#ifdef INET 539 case ETHERTYPE_IP: 540 schednetisr(NETISR_IP); 541 inq = &ipintrq; 542 break; 543 544 case ETHERTYPE_ARP: 545#if !defined(__bsdi__) || _BSDI_VERSION >= 199401 546 schednetisr(NETISR_ARP); 547 inq = &arpintrq; 548 break; 549#else 550 arpinput((struct arpcom *)ifp, m); 551 return; 552#endif 553#endif 554#ifdef IPX 555 case ETHERTYPE_IPX: 556 schednetisr(NETISR_IPX); 557 inq = &ipxintrq; 558 break; 559#endif 560#ifdef NS 561 case ETHERTYPE_NS: 562 schednetisr(NETISR_NS); 563 inq = &nsintrq; 564 break; 565#endif 566#ifdef DECNET 567 case ETHERTYPE_DECNET: 568 schednetisr(NETISR_DECNET); 569 inq = &decnetintrq; 570 break; 571#endif 572#ifdef NETATALK 573 case ETHERTYPE_AT: 574 schednetisr(NETISR_ATALK); 575 inq = &atintrq1; 576 break; 577 case ETHERTYPE_AARP: 578 /* probably this should be done with a NETISR as well */ 579 aarpinput((struct arpcom *)ifp, m); /* XXX */ 580 return; 581#endif /* NETATALK */ 582 default: 583 /* printf("fddi_input: unknown protocol 0x%x\n", type); */ 584 ifp->if_noproto++; 585 goto dropanyway; 586 } 587 break; 588 } 589#endif /* INET || NS */ 590#ifdef ISO 591 case LLC_ISO_LSAP: 592 switch (l->llc_control) { 593 case LLC_UI: 594 /* LLC_UI_P forbidden in class 1 service */ 595 if ((l->llc_dsap == LLC_ISO_LSAP) && 596 (l->llc_ssap == LLC_ISO_LSAP)) { 597 /* LSAP for ISO */ 598 m->m_data += 3; /* XXX */ 599 m->m_len -= 3; /* XXX */ 600 m->m_pkthdr.len -= 3; /* XXX */ 601 M_PREPEND(m, sizeof *fh, M_DONTWAIT); 602 if (m == 0) 603 return; 604 *mtod(m, struct fddi_header *) = *fh; 605 IFDEBUG(D_ETHER) 606 printf("clnp packet"); 607 ENDDEBUG 608 schednetisr(NETISR_ISO); 609 inq = &clnlintrq; 610 break; 611 } 612 goto dropanyway; 613 614 case LLC_XID: 615 case LLC_XID_P: 616 if(m->m_len < 6) 617 goto dropanyway; 618 l->llc_window = 0; 619 l->llc_fid = 9; 620 l->llc_class = 1; 621 l->llc_dsap = l->llc_ssap = 0; 622 /* Fall through to */ 623 case LLC_TEST: 624 case LLC_TEST_P: 625 { 626 struct sockaddr sa; 627 register struct ether_header *eh; 628 struct arpcom *ac = (struct arpcom *) ifp; 629 int i; 630 u_char c = l->llc_dsap; 631 632 l->llc_dsap = l->llc_ssap; 633 l->llc_ssap = c; 634 if (m->m_flags & (M_BCAST | M_MCAST)) 635 bcopy((caddr_t)ac->ac_enaddr, 636 (caddr_t)eh->ether_dhost, 6); 637 sa.sa_family = AF_UNSPEC; 638 sa.sa_len = sizeof(sa); 639 eh = (struct ether_header *)sa.sa_data; 640 for (i = 0; i < 6; i++) { 641 eh->ether_shost[i] = fh->fddi_dhost[i]; 642 eh->ether_dhost[i] = fh->fddi_shost[i]; 643 } 644 eh->ether_type = 0; 645 ifp->if_output(ifp, m, &sa, NULL); 646 return; 647 } 648 default: 649 m_freem(m); 650 return; 651 } 652 break; 653#endif /* ISO */ 654#ifdef LLC 655 case LLC_X25_LSAP: 656 { 657 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 658 if (m == 0) 659 return; 660 if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP, 661 fh->fddi_dhost, LLC_X25_LSAP, 6, 662 mtod(m, struct sdl_hdr *))) 663 panic("ETHER cons addr failure"); 664 mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr); 665#ifdef LLC_DEBUG 666 printf("llc packet\n"); 667#endif /* LLC_DEBUG */ 668 schednetisr(NETISR_CCITT); 669 inq = &llcintrq; 670 break; 671 } 672#endif /* LLC */ 673 674 default: 675 /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */ 676 ifp->if_noproto++; 677 dropanyway: 678 m_freem(m); 679 return; 680 } 681 682 s = splimp(); 683 if (IF_QFULL(inq)) { 684 IF_DROP(inq); 685 m_freem(m); 686 } else 687 IF_ENQUEUE(inq, m); 688 splx(s); 689} 690/* 691 * Perform common duties while attaching to interface list 692 */ 693#ifdef __NetBSD__ 694#define ifa_next ifa_list.tqe_next 695#endif 696 697void 698fddi_ifattach(ifp) 699 register struct ifnet *ifp; 700{ 701 register struct ifaddr *ifa; 702 register struct sockaddr_dl *sdl; 703 704 ifp->if_type = IFT_FDDI; 705 ifp->if_addrlen = 6; 706 ifp->if_hdrlen = 21; 707 ifp->if_mtu = FDDIMTU; 708 ifp->if_baudrate = 100000000; 709#ifdef IFF_NOTRAILERS 710 ifp->if_flags |= IFF_NOTRAILERS; 711#endif 712#if defined(__FreeBSD__) 713 ifa = ifnet_addrs[ifp->if_index - 1]; 714 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 715 sdl->sdl_type = IFT_FDDI; 716 sdl->sdl_alen = ifp->if_addrlen; 717 bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); 718#elif defined(__NetBSD__) 719 LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs); 720 for (ifa = ifp->if_addrlist.tqh_first; ifa != NULL; ifa = ifa->ifa_list.tqe_next) 721#else 722 for (ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next) 723#endif 724#if !defined(__FreeBSD__) 725 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 726 sdl->sdl_family == AF_LINK) { 727 sdl->sdl_type = IFT_FDDI; 728 sdl->sdl_alen = ifp->if_addrlen; 729 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, 730 LLADDR(sdl), ifp->if_addrlen); 731 break; 732 } 733#endif 734} 735