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