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