if_fwsubr.c revision 134245
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 134245 2004-08-24 14:16:08Z rwatson $ 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 68struct fw_hwaddr firewire_broadcastaddr = { 69 0xffffffff, 70 0xffffffff, 71 0xff, 72 0xff, 73 0xffff, 74 0xffffffff 75}; 76 77static int 78firewire_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#ifdef MAC 94 error = mac_check_ifnet_transmit(ifp, m); 95 if (error) 96 goto bad; 97#endif 98 99 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 100 error = ENETDOWN; 101 goto bad; 102 } 103 104 error = rt_check(&rt, &rt0, dst); 105 if (error) 106 goto bad; 107 108 /* 109 * For unicast, we make a tag to store the lladdr of the 110 * destination. This might not be the first time we have seen 111 * the packet (for instance, the arp code might be trying to 112 * re-send it after receiving an arp reply) so we only 113 * allocate a tag if there isn't one there already. For 114 * multicast, we will eventually use a different tag to store 115 * the channel number. 116 */ 117 unicast = !(m->m_flags & (M_BCAST | M_MCAST)); 118 if (unicast) { 119 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, NULL); 120 if (!mtag) { 121 mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 122 sizeof (struct fw_hwaddr), M_NOWAIT); 123 if (!mtag) { 124 error = ENOMEM; 125 goto bad; 126 } 127 m_tag_prepend(m, mtag); 128 } 129 destfw = (struct fw_hwaddr *)(mtag + 1); 130 } else { 131 destfw = 0; 132 } 133 134 switch (dst->sa_family) { 135#ifdef AF_INET 136 case AF_INET: 137 /* 138 * Only bother with arp for unicast. Allocation of 139 * channels etc. for firewire is quite different and 140 * doesn't fit into the arp model. 141 */ 142 if (unicast) { 143 error = arpresolve(ifp, rt, m, dst, (u_char *) destfw); 144 if (error) 145 return (error == EWOULDBLOCK ? 0 : error); 146 } 147 type = ETHERTYPE_IP; 148 break; 149 150 case AF_ARP: 151 { 152 struct arphdr *ah; 153 ah = mtod(m, struct arphdr *); 154 ah->ar_hrd = htons(ARPHRD_IEEE1394); 155 type = ETHERTYPE_ARP; 156 if (unicast) 157 *destfw = *(struct fw_hwaddr *) ar_tha(ah); 158 159 /* 160 * The standard arp code leaves a hole for the target 161 * hardware address which we need to close up. 162 */ 163 bcopy(ar_tpa(ah), ar_tha(ah), ah->ar_pln); 164 m_adj(m, -ah->ar_hln); 165 break; 166 } 167#endif 168 169#ifdef INET6 170 case AF_INET6: 171 if (unicast) { 172 error = nd6_storelladdr(&fc->fc_if, rt, m, dst, 173 (u_char *) destfw); 174 if (error) 175 return (error); 176 } 177 type = ETHERTYPE_IPV6; 178 break; 179#endif 180 181 default: 182 if_printf(ifp, "can't handle af%d\n", dst->sa_family); 183 error = EAFNOSUPPORT; 184 goto bad; 185 } 186 187 /* 188 * Let BPF tap off a copy before we encapsulate. 189 */ 190 if (ifp->if_bpf) { 191 struct fw_bpfhdr h; 192 if (unicast) 193 bcopy(destfw, h.firewire_dhost, 8); 194 else 195 bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 196 bcopy(&fc->fc_hwaddr, h.firewire_shost, 8); 197 h.firewire_type = htons(type); 198 bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 199 } 200 201 /* 202 * Punt on MCAP for now and send all multicast packets on the 203 * broadcast channel. 204 */ 205 if (m->m_flags & M_MCAST) 206 m->m_flags |= M_BCAST; 207 208 /* 209 * Figure out what speed to use and what the largest supported 210 * packet size is. For unicast, this is the minimum of what we 211 * can speak and what they can hear. For broadcast, lets be 212 * conservative and use S100. We could possibly improve that 213 * by examining the bus manager's speed map or similar. We 214 * also reduce the packet size for broadcast to account for 215 * the GASP header. 216 */ 217 if (unicast) { 218 speed = min(fc->fc_speed, destfw->sspd); 219 psize = min(512 << speed, 2 << destfw->sender_max_rec); 220 } else { 221 speed = 0; 222 psize = 512 - 2*sizeof(uint32_t); 223 } 224 225 /* 226 * Next, we encapsulate, possibly fragmenting the original 227 * datagram if it won't fit into a single packet. 228 */ 229 if (m->m_pkthdr.len <= psize - sizeof(uint32_t)) { 230 /* 231 * No fragmentation is necessary. 232 */ 233 M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); 234 if (!m) { 235 error = ENOBUFS; 236 goto bad; 237 } 238 enc = mtod(m, union fw_encap *); 239 enc->unfrag.ether_type = type; 240 enc->unfrag.lf = FW_ENCAP_UNFRAG; 241 242 /* 243 * Byte swap the encapsulation header manually. 244 */ 245 enc->ul[0] = htonl(enc->ul[0]); 246 247 IFQ_HANDOFF(ifp, m, error); 248 return (error); 249 } else { 250 /* 251 * Fragment the datagram, making sure to leave enough 252 * space for the encapsulation header in each packet. 253 */ 254 fsize = psize - 2*sizeof(uint32_t); 255 dgl = next_dgl++; 256 dsize = m->m_pkthdr.len; 257 foff = 0; 258 while (m) { 259 if (m->m_pkthdr.len > fsize) { 260 /* 261 * Split off the tail segment from the 262 * datagram, copying our tags over. 263 */ 264 mtail = m_split(m, fsize, M_DONTWAIT); 265 m_tag_copy_chain(mtail, m, M_NOWAIT); 266 } else { 267 mtail = 0; 268 } 269 270 /* 271 * Add our encapsulation header to this 272 * fragment and hand it off to the link. 273 */ 274 M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT); 275 if (!m) { 276 error = ENOBUFS; 277 goto bad; 278 } 279 enc = mtod(m, union fw_encap *); 280 if (foff == 0) { 281 enc->firstfrag.lf = FW_ENCAP_FIRST; 282 enc->firstfrag.datagram_size = dsize - 1; 283 enc->firstfrag.ether_type = type; 284 enc->firstfrag.dgl = dgl; 285 } else { 286 if (mtail) 287 enc->nextfrag.lf = FW_ENCAP_NEXT; 288 else 289 enc->nextfrag.lf = FW_ENCAP_LAST; 290 enc->nextfrag.datagram_size = dsize - 1; 291 enc->nextfrag.fragment_offset = foff; 292 enc->nextfrag.dgl = dgl; 293 } 294 foff += m->m_pkthdr.len - 2*sizeof(uint32_t); 295 296 /* 297 * Byte swap the encapsulation header manually. 298 */ 299 enc->ul[0] = htonl(enc->ul[0]); 300 enc->ul[1] = htonl(enc->ul[1]); 301 302 IFQ_HANDOFF(ifp, m, error); 303 if (error) { 304 if (mtail) 305 m_freem(mtail); 306 return (ENOBUFS); 307 } 308 309 m = mtail; 310 } 311 312 return (0); 313 } 314 315bad: 316 if (m) 317 m_freem(m); 318 return (error); 319} 320 321static struct mbuf * 322firewire_input_fragment(struct fw_com *fc, struct mbuf *m, int src) 323{ 324 union fw_encap *enc; 325 struct fw_reass *r; 326 struct mbuf *mf, *mprev; 327 int dsize; 328 int fstart, fend, start, end, islast; 329 uint32_t id; 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 474bad: 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 486void 487firewire_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 628int 629firewire_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 679static int 680firewire_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 734void 735firewire_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 775void 776firewire_ifdetach(struct ifnet *ifp) 777{ 778 bpfdetach(ifp); 779 if_detach(ifp); 780} 781 782void 783firewire_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