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