1 /* 2 * Copyright (c) 2004 Doug Rabson 3 * Copyright (c) 1982, 1989, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 4. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD$ 31 */ 32 33 #include "opt_inet.h" 34 #include "opt_inet6.h" 35 #include "opt_mac.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/mac.h> 41 #include <sys/malloc.h> 42 #include <sys/mbuf.h> 43 #include <sys/socket.h> 44 #include <sys/sockio.h> 45 46 #include <net/if.h> 47 #include <net/netisr.h> 48 #include <net/route.h> 49 #include <net/if_llc.h> 50 #include <net/if_dl.h> 51 #include <net/if_types.h> 52 #include <net/bpf.h> 53 #include <net/firewire.h> 54 55 #if defined(INET) || defined(INET6) 56 #include <netinet/in.h> 57 #include <netinet/in_var.h> 58 #include <netinet/if_ether.h> 59 #include <netinet/ip_fw.h> 60 #include <netinet/ip_dummynet.h> 61 #endif 62 #ifdef INET6 63 #include <netinet6/nd6.h> 64 #endif 65 66 #define IFP2FC(IFP) ((struct fw_com *)IFP) 67 68 struct fw_hwaddr firewire_broadcastaddr = { 69 0xffffffff, 70 0xffffffff, 71 0xff, 72 0xff, 73 0xffff, 74 0xffffffff 75 }; 76 77 static int 78 firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 79 struct rtentry *rt0) 80 { 81 struct fw_com *fc = (struct fw_com *) ifp; 82 int error, type; 83 struct rtentry *rt; 84 struct m_tag *mtag; 85 union fw_encap *enc; 86 struct fw_hwaddr *destfw; 87 uint8_t speed; 88 uint16_t psize, fsize, dsize; 89 struct mbuf *mtail; 90 int unicast, dgl, foff; 91 static int next_dgl; 92 93 GIANT_REQUIRED; 94 95 #ifdef MAC 96 error = mac_check_ifnet_transmit(ifp, m); 97 if (error) 98 goto bad; 99 #endif 100 101 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 102 error = ENETDOWN; 103 goto bad; 104 } 105 106 error = rt_check(&rt, &rt0, dst); 107 if (error) 108 goto bad; 109 110 /* 111 * For unicast, we make a tag to store the lladdr of the 112 * destination. This might not be the first time we have seen 113 * the packet (for instance, the arp code might be trying to 114 * re-send it after receiving an arp reply) so we only 115 * allocate a tag if there isn't one there already. For 116 * multicast, we will eventually use a different tag to store 117 * the channel number. 118 */ 119 unicast = !(m->m_flags & (M_BCAST | M_MCAST)); 120 if (unicast) { 121 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, NULL); 122 if (!mtag) { 123 mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 124 sizeof (struct fw_hwaddr), M_NOWAIT); 125 if (!mtag) { 126 error = ENOMEM; 127 goto bad; 128 } 129 m_tag_prepend(m, mtag); 130 } 131 destfw = (struct fw_hwaddr *)(mtag + 1); 132 } else { 133 destfw = 0; 134 } 135 136 switch (dst->sa_family) { 137 #ifdef AF_INET 138 case AF_INET: 139 /* 140 * Only bother with arp for unicast. Allocation of 141 * channels etc. for firewire is quite different and 142 * doesn't fit into the arp model. 143 */ 144 if (unicast) { 145 error = arpresolve(ifp, rt, m, dst, (u_char *) destfw); 146 if (error) 147 return (error == EWOULDBLOCK ? 0 : error); 148 } 149 type = ETHERTYPE_IP; 150 break; 151 152 case AF_ARP: 153 { 154 struct arphdr *ah; 155 ah = mtod(m, struct arphdr *); 156 ah->ar_hrd = htons(ARPHRD_IEEE1394); 157 type = ETHERTYPE_ARP; 158 if (unicast) 159 *destfw = *(struct fw_hwaddr *) ar_tha(ah); 160 161 /* 162 * The standard arp code leaves a hole for the target 163 * hardware address which we need to close up. 164 */ 165 bcopy(ar_tpa(ah), ar_tha(ah), ah->ar_pln); 166 m_adj(m, -ah->ar_hln); 167 break; 168 } 169 #endif 170 171 #ifdef INET6 172 case AF_INET6: 173 if (unicast) { 174 error = nd6_storelladdr(&fc->fc_if, rt, m, dst, 175 (u_char *) destfw); 176 if (error) 177 return (error); 178 } 179 type = ETHERTYPE_IPV6; 180 break; 181 #endif 182 183 default: 184 if_printf(ifp, "can't handle af%d\n", dst->sa_family); 185 error = EAFNOSUPPORT; 186 goto bad; 187 } 188 189 /* 190 * Let BPF tap off a copy before we encapsulate. 191 */ 192 if (ifp->if_bpf) { 193 struct fw_bpfhdr h; 194 if (unicast) 195 bcopy(destfw, h.firewire_dhost, 8); 196 else 197 bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 198 bcopy(&fc->fc_hwaddr, h.firewire_shost, 8); 199 h.firewire_type = htons(type); 200 bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 201 } 202 203 /* 204 * Punt on MCAP for now and send all multicast packets on the 205 * broadcast channel. 206 */ 207 if (m->m_flags & M_MCAST) 208 m->m_flags |= M_BCAST; 209 210 /* 211 * Figure out what speed to use and what the largest supported 212 * packet size is. For unicast, this is the minimum of what we 213 * can speak and what they can hear. For broadcast, lets be 214 * conservative and use S100. We could possibly improve that 215 * by examining the bus manager's speed map or similar. We 216 * also reduce the packet size for broadcast to account for 217 * the GASP header. 218 */ 219 if (unicast) { 220 speed = min(fc->fc_speed, destfw->sspd); 221 psize = min(512 << speed, 2 << destfw->sender_max_rec); 222 } else { 223 speed = 0; 224 psize = 512 - 2*sizeof(uint32_t); 225 } 226 227 /* 228 * Next, we encapsulate, possibly fragmenting the original 229 * datagram if it won't fit into a single packet. 230 */ 231 if (m->m_pkthdr.len <= psize - sizeof(uint32_t)) { 232 /* 233 * No fragmentation is necessary. 234 */ 235 M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); 236 if (!m) { 237 error = ENOBUFS; 238 goto bad; 239 } 240 enc = mtod(m, union fw_encap *); 241 enc->unfrag.ether_type = type; 242 enc->unfrag.lf = FW_ENCAP_UNFRAG; 243 244 /* 245 * Byte swap the encapsulation header manually. 246 */ 247 enc->ul[0] = htonl(enc->ul[0]); 248 249 IFQ_HANDOFF(ifp, m, error); 250 return (error); 251 } else { 252 /* 253 * Fragment the datagram, making sure to leave enough 254 * space for the encapsulation header in each packet. 255 */ 256 fsize = psize - 2*sizeof(uint32_t); 257 dgl = next_dgl++; 258 dsize = m->m_pkthdr.len; 259 foff = 0; 260 while (m) { 261 if (m->m_pkthdr.len > fsize) { 262 /* 263 * Split off the tail segment from the 264 * datagram, copying our tags over. 265 */ 266 mtail = m_split(m, fsize, M_DONTWAIT); 267 m_tag_copy_chain(mtail, m, M_NOWAIT); 268 } else { 269 mtail = 0; 270 } 271 272 /* 273 * Add our encapsulation header to this 274 * fragment and hand it off to the link. 275 */ 276 M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT); 277 if (!m) { 278 error = ENOBUFS; 279 goto bad; 280 } 281 enc = mtod(m, union fw_encap *); 282 if (foff == 0) { 283 enc->firstfrag.lf = FW_ENCAP_FIRST; 284 enc->firstfrag.datagram_size = dsize - 1; 285 enc->firstfrag.ether_type = type; 286 enc->firstfrag.dgl = dgl; 287 } else { 288 if (mtail) 289 enc->nextfrag.lf = FW_ENCAP_NEXT; 290 else 291 enc->nextfrag.lf = FW_ENCAP_LAST; 292 enc->nextfrag.datagram_size = dsize - 1; 293 enc->nextfrag.fragment_offset = foff; 294 enc->nextfrag.dgl = dgl; 295 } 296 foff += m->m_pkthdr.len - 2*sizeof(uint32_t); 297 298 /* 299 * Byte swap the encapsulation header manually. 300 */ 301 enc->ul[0] = htonl(enc->ul[0]); 302 enc->ul[1] = htonl(enc->ul[1]); 303 304 IFQ_HANDOFF(ifp, m, error); 305 if (error) { 306 if (mtail) 307 m_freem(mtail); 308 return (ENOBUFS); 309 } 310 311 m = mtail; 312 } 313 314 return (0); 315 } 316 317 bad: 318 if (m) 319 m_freem(m); 320 return (error); 321 } 322 323 static struct mbuf * 324 firewire_input_fragment(struct fw_com *fc, struct mbuf *m, int src) 325 { 326 union fw_encap *enc; 327 struct fw_reass *r; 328 struct mbuf *mf, *mprev; 329 int dsize; 330 int fstart, fend, start, end, islast; 331 uint32_t id; 332 333 GIANT_REQUIRED; 334 335 /* 336 * Find an existing reassembly buffer or create a new one. 337 */ 338 enc = mtod(m, union fw_encap *); 339 id = enc->firstfrag.dgl | (src << 16); 340 STAILQ_FOREACH(r, &fc->fc_frags, fr_link) 341 if (r->fr_id == id) 342 break; 343 if (!r) { 344 r = malloc(sizeof(struct fw_reass), M_TEMP, M_NOWAIT); 345 if (!r) { 346 m_freem(m); 347 return 0; 348 } 349 r->fr_id = id; 350 r->fr_frags = 0; 351 STAILQ_INSERT_HEAD(&fc->fc_frags, r, fr_link); 352 } 353 354 /* 355 * If this fragment overlaps any other fragment, we must discard 356 * the partial reassembly and start again. 357 */ 358 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 359 fstart = 0; 360 else 361 fstart = enc->nextfrag.fragment_offset; 362 fend = fstart + m->m_pkthdr.len - 2*sizeof(uint32_t); 363 dsize = enc->nextfrag.datagram_size; 364 islast = (enc->nextfrag.lf == FW_ENCAP_LAST); 365 366 for (mf = r->fr_frags; mf; mf = mf->m_nextpkt) { 367 enc = mtod(mf, union fw_encap *); 368 if (enc->nextfrag.datagram_size != dsize) { 369 /* 370 * This fragment must be from a different 371 * packet. 372 */ 373 goto bad; 374 } 375 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 376 start = 0; 377 else 378 start = enc->nextfrag.fragment_offset; 379 end = start + mf->m_pkthdr.len - 2*sizeof(uint32_t); 380 if ((fstart < end && fend > start) || 381 (islast && enc->nextfrag.lf == FW_ENCAP_LAST)) { 382 /* 383 * Overlap - discard reassembly buffer and start 384 * again with this fragment. 385 */ 386 goto bad; 387 } 388 } 389 390 /* 391 * Find where to put this fragment in the list. 392 */ 393 for (mf = r->fr_frags, mprev = NULL; mf; 394 mprev = mf, mf = mf->m_nextpkt) { 395 enc = mtod(mf, union fw_encap *); 396 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 397 start = 0; 398 else 399 start = enc->nextfrag.fragment_offset; 400 if (start >= fend) 401 break; 402 } 403 404 /* 405 * If this is a last fragment and we are not adding at the end 406 * of the list, discard the buffer. 407 */ 408 if (islast && mprev && mprev->m_nextpkt) 409 goto bad; 410 411 if (mprev) { 412 m->m_nextpkt = mprev->m_nextpkt; 413 mprev->m_nextpkt = m; 414 415 /* 416 * Coalesce forwards and see if we can make a whole 417 * datagram. 418 */ 419 enc = mtod(mprev, union fw_encap *); 420 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 421 start = 0; 422 else 423 start = enc->nextfrag.fragment_offset; 424 end = start + mprev->m_pkthdr.len - 2*sizeof(uint32_t); 425 while (end == fstart) { 426 /* 427 * Strip off the encap header from m and 428 * append it to mprev, freeing m. 429 */ 430 m_adj(m, 2*sizeof(uint32_t)); 431 mprev->m_nextpkt = m->m_nextpkt; 432 mprev->m_pkthdr.len += m->m_pkthdr.len; 433 m_cat(mprev, m); 434 435 if (mprev->m_pkthdr.len == dsize + 1 + 2*sizeof(uint32_t)) { 436 /* 437 * We have assembled a complete packet 438 * we must be finished. Make sure we have 439 * merged the whole chain. 440 */ 441 STAILQ_REMOVE(&fc->fc_frags, r, fw_reass, fr_link); 442 free(r, M_TEMP); 443 m = mprev->m_nextpkt; 444 while (m) { 445 mf = m->m_nextpkt; 446 m_freem(m); 447 m = mf; 448 } 449 mprev->m_nextpkt = NULL; 450 451 return (mprev); 452 } 453 454 /* 455 * See if we can continue merging forwards. 456 */ 457 end = fend; 458 m = mprev->m_nextpkt; 459 if (m) { 460 enc = mtod(m, union fw_encap *); 461 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 462 fstart = 0; 463 else 464 fstart = enc->nextfrag.fragment_offset; 465 fend = fstart + m->m_pkthdr.len 466 - 2*sizeof(uint32_t); 467 } else { 468 break; 469 } 470 } 471 } else { 472 m->m_nextpkt = 0; 473 r->fr_frags = m; 474 } 475 476 return (0); 477 478 bad: 479 while (r->fr_frags) { 480 mf = r->fr_frags; 481 r->fr_frags = mf->m_nextpkt; 482 m_freem(mf); 483 } 484 m->m_nextpkt = 0; 485 r->fr_frags = m; 486 487 return (0); 488 } 489 490 void 491 firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src) 492 { 493 struct fw_com *fc = (struct fw_com *) ifp; 494 union fw_encap *enc; 495 int type, isr; 496 497 GIANT_REQUIRED; 498 499 /* 500 * The caller has already stripped off the packet header 501 * (stream or wreqb) and marked the mbuf's M_BCAST flag 502 * appropriately. We de-encapsulate the IP packet and pass it 503 * up the line after handling link-level fragmentation. 504 */ 505 if (m->m_pkthdr.len < sizeof(uint32_t)) { 506 if_printf(ifp, "discarding frame without " 507 "encapsulation header (len %u pkt len %u)\n", 508 m->m_len, m->m_pkthdr.len); 509 } 510 511 m = m_pullup(m, sizeof(uint32_t)); 512 enc = mtod(m, union fw_encap *); 513 514 /* 515 * Byte swap the encapsulation header manually. 516 */ 517 enc->ul[0] = htonl(enc->ul[0]); 518 519 if (enc->unfrag.lf != 0) { 520 m = m_pullup(m, 2*sizeof(uint32_t)); 521 if (!m) 522 return; 523 enc = mtod(m, union fw_encap *); 524 enc->ul[1] = htonl(enc->ul[1]); 525 m = firewire_input_fragment(fc, m, src); 526 if (!m) 527 return; 528 enc = mtod(m, union fw_encap *); 529 type = enc->firstfrag.ether_type; 530 m_adj(m, 2*sizeof(uint32_t)); 531 } else { 532 type = enc->unfrag.ether_type; 533 m_adj(m, sizeof(uint32_t)); 534 } 535 536 if (m->m_pkthdr.rcvif == NULL) { 537 if_printf(ifp, "discard frame w/o interface pointer\n"); 538 ifp->if_ierrors++; 539 m_freem(m); 540 return; 541 } 542 #ifdef DIAGNOSTIC 543 if (m->m_pkthdr.rcvif != ifp) { 544 if_printf(ifp, "Warning, frame marked as received on %s\n", 545 m->m_pkthdr.rcvif->if_xname); 546 } 547 #endif 548 549 #ifdef MAC 550 /* 551 * Tag the mbuf with an appropriate MAC label before any other 552 * consumers can get to it. 553 */ 554 mac_create_mbuf_from_ifnet(ifp, m); 555 #endif 556 557 /* 558 * Give bpf a chance at the packet. The link-level driver 559 * should have left us a tag with the EUID of the sender. 560 */ 561 if (ifp->if_bpf) { 562 struct fw_bpfhdr h; 563 struct m_tag *mtag; 564 565 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 0); 566 if (mtag) 567 bcopy(mtag + 1, h.firewire_shost, 8); 568 else 569 bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 570 bcopy(&fc->fc_hwaddr, h.firewire_dhost, 8); 571 h.firewire_type = htons(type); 572 bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 573 } 574 575 if (ifp->if_flags & IFF_MONITOR) { 576 /* 577 * Interface marked for monitoring; discard packet. 578 */ 579 m_freem(m); 580 return; 581 } 582 583 ifp->if_ibytes += m->m_pkthdr.len; 584 585 /* Discard packet if interface is not up */ 586 if ((ifp->if_flags & IFF_UP) == 0) { 587 m_freem(m); 588 return; 589 } 590 591 if (m->m_flags & (M_BCAST|M_MCAST)) 592 ifp->if_imcasts++; 593 594 switch (type) { 595 #ifdef INET 596 case ETHERTYPE_IP: 597 if (ip_fastforward(m)) 598 return; 599 isr = NETISR_IP; 600 break; 601 602 case ETHERTYPE_ARP: 603 { 604 struct arphdr *ah; 605 ah = mtod(m, struct arphdr *); 606 607 /* 608 * Adjust the arp packet to insert an empty tha slot. 609 */ 610 m->m_len += ah->ar_hln; 611 m->m_pkthdr.len += ah->ar_hln; 612 bcopy(ar_tha(ah), ar_tpa(ah), ah->ar_pln); 613 isr = NETISR_ARP; 614 break; 615 } 616 #endif 617 618 #ifdef INET6 619 case ETHERTYPE_IPV6: 620 isr = NETISR_IPV6; 621 break; 622 #endif 623 624 default: 625 m_freem(m); 626 return; 627 } 628 629 netisr_dispatch(isr, m); 630 } 631 632 int 633 firewire_ioctl(struct ifnet *ifp, int command, caddr_t data) 634 { 635 struct ifaddr *ifa = (struct ifaddr *) data; 636 struct ifreq *ifr = (struct ifreq *) data; 637 int error = 0; 638 639 switch (command) { 640 case SIOCSIFADDR: 641 ifp->if_flags |= IFF_UP; 642 643 switch (ifa->ifa_addr->sa_family) { 644 #ifdef INET 645 case AF_INET: 646 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 647 arp_ifinit(ifp, ifa); 648 break; 649 #endif 650 default: 651 ifp->if_init(ifp->if_softc); 652 break; 653 } 654 break; 655 656 case SIOCGIFADDR: 657 { 658 struct sockaddr *sa; 659 660 sa = (struct sockaddr *) & ifr->ifr_data; 661 bcopy(&IFP2FC(ifp)->fc_hwaddr, 662 (caddr_t) sa->sa_data, sizeof(struct fw_hwaddr)); 663 } 664 break; 665 666 case SIOCSIFMTU: 667 /* 668 * Set the interface MTU. 669 */ 670 if (ifr->ifr_mtu > 1500) { 671 error = EINVAL; 672 } else { 673 ifp->if_mtu = ifr->ifr_mtu; 674 } 675 break; 676 default: 677 error = EINVAL; /* XXX netbsd has ENOTTY??? */ 678 break; 679 } 680 return (error); 681 } 682 683 static int 684 firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 685 struct sockaddr *sa) 686 { 687 #ifdef INET 688 struct sockaddr_in *sin; 689 #endif 690 #ifdef INET6 691 struct sockaddr_in6 *sin6; 692 #endif 693 694 switch(sa->sa_family) { 695 case AF_LINK: 696 /* 697 * No mapping needed. 698 */ 699 *llsa = 0; 700 return 0; 701 702 #ifdef INET 703 case AF_INET: 704 sin = (struct sockaddr_in *)sa; 705 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 706 return EADDRNOTAVAIL; 707 *llsa = 0; 708 return 0; 709 #endif 710 #ifdef INET6 711 case AF_INET6: 712 sin6 = (struct sockaddr_in6 *)sa; 713 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 714 /* 715 * An IP6 address of 0 means listen to all 716 * of the Ethernet multicast address used for IP6. 717 * (This is used for multicast routers.) 718 */ 719 ifp->if_flags |= IFF_ALLMULTI; 720 *llsa = 0; 721 return 0; 722 } 723 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 724 return EADDRNOTAVAIL; 725 *llsa = 0; 726 return 0; 727 #endif 728 729 default: 730 /* 731 * Well, the text isn't quite right, but it's the name 732 * that counts... 733 */ 734 return EAFNOSUPPORT; 735 } 736 } 737 738 void 739 firewire_ifattach(struct ifnet *ifp, struct fw_hwaddr *llc) 740 { 741 struct fw_com *fc = (struct fw_com *) ifp; 742 struct ifaddr *ifa; 743 struct sockaddr_dl *sdl; 744 static const char* speeds[] = { 745 "S100", "S200", "S400", "S800", 746 "S1600", "S3200" 747 }; 748 749 fc->fc_speed = llc->sspd; 750 STAILQ_INIT(&fc->fc_frags); 751 752 ifp->if_type = IFT_IEEE1394; 753 ifp->if_addrlen = sizeof(struct fw_hwaddr); 754 ifp->if_hdrlen = 0; 755 if_attach(ifp); 756 ifp->if_mtu = 1500; /* XXX */ 757 ifp->if_output = firewire_output; 758 ifp->if_resolvemulti = firewire_resolvemulti; 759 ifp->if_broadcastaddr = (u_char *) &firewire_broadcastaddr; 760 761 ifa = ifaddr_byindex(ifp->if_index); 762 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); 763 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 764 sdl->sdl_type = IFT_IEEE1394; 765 sdl->sdl_alen = ifp->if_addrlen; 766 bcopy(llc, LLADDR(sdl), ifp->if_addrlen); 767 768 bpfattach(ifp, DLT_APPLE_IP_OVER_IEEE1394, 769 sizeof(struct fw_hwaddr)); 770 771 if_printf(ifp, "Firewire address: %8D @ 0x%04x%08x, %s, maxrec %d\n", 772 (uint8_t *) &llc->sender_unique_ID_hi, ":", 773 ntohs(llc->sender_unicast_FIFO_hi), 774 ntohl(llc->sender_unicast_FIFO_lo), 775 speeds[llc->sspd], 776 (2 << llc->sender_max_rec)); 777 } 778 779 void 780 firewire_ifdetach(struct ifnet *ifp) 781 { 782 bpfdetach(ifp); 783 if_detach(ifp); 784 } 785 786 void 787 firewire_busreset(struct ifnet *ifp) 788 { 789 struct fw_com *fc = (struct fw_com *) ifp; 790 struct fw_reass *r; 791 struct mbuf *m; 792 793 /* 794 * Discard any partial datagrams since the host ids may have changed. 795 */ 796 while ((r = STAILQ_FIRST(&fc->fc_frags))) { 797 STAILQ_REMOVE_HEAD(&fc->fc_frags, fr_link); 798 while (r->fr_frags) { 799 m = r->fr_frags; 800 r->fr_frags = m->m_nextpkt; 801 m_freem(m); 802 } 803 free(r, M_TEMP); 804 } 805 } 806