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