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 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/module.h> 42 #include <sys/socket.h> 43 #include <sys/sockio.h> 44 45 #include <net/if.h> 46 #include <net/netisr.h> 47 #include <net/route.h> 48 #include <net/if_llc.h> 49 #include <net/if_dl.h> 50 #include <net/if_types.h> 51 #include <net/bpf.h> 52 #include <net/firewire.h> 53 #include <net/if_llatbl.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 #include <security/mac/mac_framework.h> 65 66 MALLOC_DEFINE(M_FWCOM, "fw_com", "firewire interface internals"); 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 route *ro) 80 { 81 struct fw_com *fc = IFP2FWC(ifp); 82 int error, type; 83 struct m_tag *mtag; 84 union fw_encap *enc; 85 struct fw_hwaddr *destfw; 86 uint8_t speed; 87 uint16_t psize, fsize, dsize; 88 struct mbuf *mtail; 89 int unicast, dgl, foff; 90 static int next_dgl; 91 #if defined(INET) || defined(INET6) 92 struct llentry *lle; 93 #endif 94 95 #ifdef MAC 96 error = mac_ifnet_check_transmit(ifp, m); 97 if (error) 98 goto bad; 99 #endif 100 101 if (!((ifp->if_flags & IFF_UP) && 102 (ifp->if_drv_flags & IFF_DRV_RUNNING))) { 103 error = ENETDOWN; 104 goto bad; 105 } 106 107 /* 108 * For unicast, we make a tag to store the lladdr of the 109 * destination. This might not be the first time we have seen 110 * the packet (for instance, the arp code might be trying to 111 * re-send it after receiving an arp reply) so we only 112 * allocate a tag if there isn't one there already. For 113 * multicast, we will eventually use a different tag to store 114 * the channel number. 115 */ 116 unicast = !(m->m_flags & (M_BCAST | M_MCAST)); 117 if (unicast) { 118 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, NULL); 119 if (!mtag) { 120 mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 121 sizeof (struct fw_hwaddr), M_NOWAIT); 122 if (!mtag) { 123 error = ENOMEM; 124 goto bad; 125 } 126 m_tag_prepend(m, mtag); 127 } 128 destfw = (struct fw_hwaddr *)(mtag + 1); 129 } else { 130 destfw = 0; 131 } 132 133 switch (dst->sa_family) { 134 #ifdef INET 135 case AF_INET: 136 /* 137 * Only bother with arp for unicast. Allocation of 138 * channels etc. for firewire is quite different and 139 * doesn't fit into the arp model. 140 */ 141 if (unicast) { 142 error = arpresolve(ifp, ro ? ro->ro_rt : NULL, m, dst, (u_char *) destfw, &lle); 143 if (error) 144 return (error == EWOULDBLOCK ? 0 : error); 145 } 146 type = ETHERTYPE_IP; 147 break; 148 149 case AF_ARP: 150 { 151 struct arphdr *ah; 152 ah = mtod(m, struct arphdr *); 153 ah->ar_hrd = htons(ARPHRD_IEEE1394); 154 type = ETHERTYPE_ARP; 155 if (unicast) 156 *destfw = *(struct fw_hwaddr *) ar_tha(ah); 157 158 /* 159 * The standard arp code leaves a hole for the target 160 * hardware address which we need to close up. 161 */ 162 bcopy(ar_tpa(ah), ar_tha(ah), ah->ar_pln); 163 m_adj(m, -ah->ar_hln); 164 break; 165 } 166 #endif 167 168 #ifdef INET6 169 case AF_INET6: 170 if (unicast) { 171 error = nd6_storelladdr(fc->fc_ifp, m, dst, 172 (u_char *) destfw, &lle); 173 if (error) 174 return (error); 175 } 176 type = ETHERTYPE_IPV6; 177 break; 178 #endif 179 180 default: 181 if_printf(ifp, "can't handle af%d\n", dst->sa_family); 182 error = EAFNOSUPPORT; 183 goto bad; 184 } 185 186 /* 187 * Let BPF tap off a copy before we encapsulate. 188 */ 189 if (bpf_peers_present(ifp->if_bpf)) { 190 struct fw_bpfhdr h; 191 if (unicast) 192 bcopy(destfw, h.firewire_dhost, 8); 193 else 194 bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 195 bcopy(&fc->fc_hwaddr, h.firewire_shost, 8); 196 h.firewire_type = htons(type); 197 bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 198 } 199 200 /* 201 * Punt on MCAP for now and send all multicast packets on the 202 * broadcast channel. 203 */ 204 if (m->m_flags & M_MCAST) 205 m->m_flags |= M_BCAST; 206 207 /* 208 * Figure out what speed to use and what the largest supported 209 * packet size is. For unicast, this is the minimum of what we 210 * can speak and what they can hear. For broadcast, lets be 211 * conservative and use S100. We could possibly improve that 212 * by examining the bus manager's speed map or similar. We 213 * also reduce the packet size for broadcast to account for 214 * the GASP header. 215 */ 216 if (unicast) { 217 speed = min(fc->fc_speed, destfw->sspd); 218 psize = min(512 << speed, 2 << destfw->sender_max_rec); 219 } else { 220 speed = 0; 221 psize = 512 - 2*sizeof(uint32_t); 222 } 223 224 /* 225 * Next, we encapsulate, possibly fragmenting the original 226 * datagram if it won't fit into a single packet. 227 */ 228 if (m->m_pkthdr.len <= psize - sizeof(uint32_t)) { 229 /* 230 * No fragmentation is necessary. 231 */ 232 M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); 233 if (!m) { 234 error = ENOBUFS; 235 goto bad; 236 } 237 enc = mtod(m, union fw_encap *); 238 enc->unfrag.ether_type = type; 239 enc->unfrag.lf = FW_ENCAP_UNFRAG; 240 enc->unfrag.reserved = 0; 241 242 /* 243 * Byte swap the encapsulation header manually. 244 */ 245 enc->ul[0] = htonl(enc->ul[0]); 246 247 error = (ifp->if_transmit)(ifp, m); 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.reserved1 = 0; 283 enc->firstfrag.reserved2 = 0; 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.reserved1 = 0; 293 enc->nextfrag.reserved2 = 0; 294 enc->nextfrag.reserved3 = 0; 295 enc->nextfrag.datagram_size = dsize - 1; 296 enc->nextfrag.fragment_offset = foff; 297 enc->nextfrag.dgl = dgl; 298 } 299 foff += m->m_pkthdr.len - 2*sizeof(uint32_t); 300 301 /* 302 * Byte swap the encapsulation header manually. 303 */ 304 enc->ul[0] = htonl(enc->ul[0]); 305 enc->ul[1] = htonl(enc->ul[1]); 306 307 error = (ifp->if_transmit)(ifp, m); 308 if (error) { 309 if (mtail) 310 m_freem(mtail); 311 return (ENOBUFS); 312 } 313 314 m = mtail; 315 } 316 317 return (0); 318 } 319 320 bad: 321 if (m) 322 m_freem(m); 323 return (error); 324 } 325 326 static struct mbuf * 327 firewire_input_fragment(struct fw_com *fc, struct mbuf *m, int src) 328 { 329 union fw_encap *enc; 330 struct fw_reass *r; 331 struct mbuf *mf, *mprev; 332 int dsize; 333 int fstart, fend, start, end, islast; 334 uint32_t id; 335 336 /* 337 * Find an existing reassembly buffer or create a new one. 338 */ 339 enc = mtod(m, union fw_encap *); 340 id = enc->firstfrag.dgl | (src << 16); 341 STAILQ_FOREACH(r, &fc->fc_frags, fr_link) 342 if (r->fr_id == id) 343 break; 344 if (!r) { 345 r = malloc(sizeof(struct fw_reass), M_TEMP, M_NOWAIT); 346 if (!r) { 347 m_freem(m); 348 return 0; 349 } 350 r->fr_id = id; 351 r->fr_frags = 0; 352 STAILQ_INSERT_HEAD(&fc->fc_frags, r, fr_link); 353 } 354 355 /* 356 * If this fragment overlaps any other fragment, we must discard 357 * the partial reassembly and start again. 358 */ 359 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 360 fstart = 0; 361 else 362 fstart = enc->nextfrag.fragment_offset; 363 fend = fstart + m->m_pkthdr.len - 2*sizeof(uint32_t); 364 dsize = enc->nextfrag.datagram_size; 365 islast = (enc->nextfrag.lf == FW_ENCAP_LAST); 366 367 for (mf = r->fr_frags; mf; mf = mf->m_nextpkt) { 368 enc = mtod(mf, union fw_encap *); 369 if (enc->nextfrag.datagram_size != dsize) { 370 /* 371 * This fragment must be from a different 372 * packet. 373 */ 374 goto bad; 375 } 376 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 377 start = 0; 378 else 379 start = enc->nextfrag.fragment_offset; 380 end = start + mf->m_pkthdr.len - 2*sizeof(uint32_t); 381 if ((fstart < end && fend > start) || 382 (islast && enc->nextfrag.lf == FW_ENCAP_LAST)) { 383 /* 384 * Overlap - discard reassembly buffer and start 385 * again with this fragment. 386 */ 387 goto bad; 388 } 389 } 390 391 /* 392 * Find where to put this fragment in the list. 393 */ 394 for (mf = r->fr_frags, mprev = NULL; mf; 395 mprev = mf, mf = mf->m_nextpkt) { 396 enc = mtod(mf, union fw_encap *); 397 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 398 start = 0; 399 else 400 start = enc->nextfrag.fragment_offset; 401 if (start >= fend) 402 break; 403 } 404 405 /* 406 * If this is a last fragment and we are not adding at the end 407 * of the list, discard the buffer. 408 */ 409 if (islast && mprev && mprev->m_nextpkt) 410 goto bad; 411 412 if (mprev) { 413 m->m_nextpkt = mprev->m_nextpkt; 414 mprev->m_nextpkt = m; 415 416 /* 417 * Coalesce forwards and see if we can make a whole 418 * datagram. 419 */ 420 enc = mtod(mprev, union fw_encap *); 421 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 422 start = 0; 423 else 424 start = enc->nextfrag.fragment_offset; 425 end = start + mprev->m_pkthdr.len - 2*sizeof(uint32_t); 426 while (end == fstart) { 427 /* 428 * Strip off the encap header from m and 429 * append it to mprev, freeing m. 430 */ 431 m_adj(m, 2*sizeof(uint32_t)); 432 mprev->m_nextpkt = m->m_nextpkt; 433 mprev->m_pkthdr.len += m->m_pkthdr.len; 434 m_cat(mprev, m); 435 436 if (mprev->m_pkthdr.len == dsize + 1 + 2*sizeof(uint32_t)) { 437 /* 438 * We have assembled a complete packet 439 * we must be finished. Make sure we have 440 * merged the whole chain. 441 */ 442 STAILQ_REMOVE(&fc->fc_frags, r, fw_reass, fr_link); 443 free(r, M_TEMP); 444 m = mprev->m_nextpkt; 445 while (m) { 446 mf = m->m_nextpkt; 447 m_freem(m); 448 m = mf; 449 } 450 mprev->m_nextpkt = NULL; 451 452 return (mprev); 453 } 454 455 /* 456 * See if we can continue merging forwards. 457 */ 458 end = fend; 459 m = mprev->m_nextpkt; 460 if (m) { 461 enc = mtod(m, union fw_encap *); 462 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 463 fstart = 0; 464 else 465 fstart = enc->nextfrag.fragment_offset; 466 fend = fstart + m->m_pkthdr.len 467 - 2*sizeof(uint32_t); 468 } else { 469 break; 470 } 471 } 472 } else { 473 m->m_nextpkt = 0; 474 r->fr_frags = m; 475 } 476 477 return (0); 478 479 bad: 480 while (r->fr_frags) { 481 mf = r->fr_frags; 482 r->fr_frags = mf->m_nextpkt; 483 m_freem(mf); 484 } 485 m->m_nextpkt = 0; 486 r->fr_frags = m; 487 488 return (0); 489 } 490 491 void 492 firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src) 493 { 494 struct fw_com *fc = IFP2FWC(ifp); 495 union fw_encap *enc; 496 int type, isr; 497 498 /* 499 * The caller has already stripped off the packet header 500 * (stream or wreqb) and marked the mbuf's M_BCAST flag 501 * appropriately. We de-encapsulate the IP packet and pass it 502 * up the line after handling link-level fragmentation. 503 */ 504 if (m->m_pkthdr.len < sizeof(uint32_t)) { 505 if_printf(ifp, "discarding frame without " 506 "encapsulation header (len %u pkt len %u)\n", 507 m->m_len, m->m_pkthdr.len); 508 } 509 510 m = m_pullup(m, sizeof(uint32_t)); 511 if (m == NULL) 512 return; 513 enc = mtod(m, union fw_encap *); 514 515 /* 516 * Byte swap the encapsulation header manually. 517 */ 518 enc->ul[0] = ntohl(enc->ul[0]); 519 520 if (enc->unfrag.lf != 0) { 521 m = m_pullup(m, 2*sizeof(uint32_t)); 522 if (!m) 523 return; 524 enc = mtod(m, union fw_encap *); 525 enc->ul[1] = ntohl(enc->ul[1]); 526 m = firewire_input_fragment(fc, m, src); 527 if (!m) 528 return; 529 enc = mtod(m, union fw_encap *); 530 type = enc->firstfrag.ether_type; 531 m_adj(m, 2*sizeof(uint32_t)); 532 } else { 533 type = enc->unfrag.ether_type; 534 m_adj(m, sizeof(uint32_t)); 535 } 536 537 if (m->m_pkthdr.rcvif == NULL) { 538 if_printf(ifp, "discard frame w/o interface pointer\n"); 539 ifp->if_ierrors++; 540 m_freem(m); 541 return; 542 } 543 #ifdef DIAGNOSTIC 544 if (m->m_pkthdr.rcvif != ifp) { 545 if_printf(ifp, "Warning, frame marked as received on %s\n", 546 m->m_pkthdr.rcvif->if_xname); 547 } 548 #endif 549 550 #ifdef MAC 551 /* 552 * Tag the mbuf with an appropriate MAC label before any other 553 * consumers can get to it. 554 */ 555 mac_ifnet_create_mbuf(ifp, m); 556 #endif 557 558 /* 559 * Give bpf a chance at the packet. The link-level driver 560 * should have left us a tag with the EUID of the sender. 561 */ 562 if (bpf_peers_present(ifp->if_bpf)) { 563 struct fw_bpfhdr h; 564 struct m_tag *mtag; 565 566 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 0); 567 if (mtag) 568 bcopy(mtag + 1, h.firewire_shost, 8); 569 else 570 bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 571 bcopy(&fc->fc_hwaddr, h.firewire_dhost, 8); 572 h.firewire_type = htons(type); 573 bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 574 } 575 576 if (ifp->if_flags & IFF_MONITOR) { 577 /* 578 * Interface marked for monitoring; discard packet. 579 */ 580 m_freem(m); 581 return; 582 } 583 584 ifp->if_ibytes += m->m_pkthdr.len; 585 586 /* Discard packet if interface is not up */ 587 if ((ifp->if_flags & IFF_UP) == 0) { 588 m_freem(m); 589 return; 590 } 591 592 if (m->m_flags & (M_BCAST|M_MCAST)) 593 ifp->if_imcasts++; 594 595 switch (type) { 596 #ifdef INET 597 case ETHERTYPE_IP: 598 if ((m = ip_fastforward(m)) == NULL) 599 return; 600 isr = NETISR_IP; 601 break; 602 603 case ETHERTYPE_ARP: 604 { 605 struct arphdr *ah; 606 ah = mtod(m, struct arphdr *); 607 608 /* 609 * Adjust the arp packet to insert an empty tha slot. 610 */ 611 m->m_len += ah->ar_hln; 612 m->m_pkthdr.len += ah->ar_hln; 613 bcopy(ar_tha(ah), ar_tpa(ah), ah->ar_pln); 614 isr = NETISR_ARP; 615 break; 616 } 617 #endif 618 619 #ifdef INET6 620 case ETHERTYPE_IPV6: 621 isr = NETISR_IPV6; 622 break; 623 #endif 624 625 default: 626 m_freem(m); 627 return; 628 } 629 630 netisr_dispatch(isr, m); 631 } 632 633 int 634 firewire_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 635 { 636 struct ifaddr *ifa = (struct ifaddr *) data; 637 struct ifreq *ifr = (struct ifreq *) data; 638 int error = 0; 639 640 switch (command) { 641 case SIOCSIFADDR: 642 ifp->if_flags |= IFF_UP; 643 644 switch (ifa->ifa_addr->sa_family) { 645 #ifdef INET 646 case AF_INET: 647 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 648 arp_ifinit(ifp, ifa); 649 break; 650 #endif 651 default: 652 ifp->if_init(ifp->if_softc); 653 break; 654 } 655 break; 656 657 case SIOCGIFADDR: 658 { 659 struct sockaddr *sa; 660 661 sa = (struct sockaddr *) & ifr->ifr_data; 662 bcopy(&IFP2FWC(ifp)->fc_hwaddr, 663 (caddr_t) sa->sa_data, sizeof(struct fw_hwaddr)); 664 } 665 break; 666 667 case SIOCSIFMTU: 668 /* 669 * Set the interface MTU. 670 */ 671 if (ifr->ifr_mtu > 1500) { 672 error = EINVAL; 673 } else { 674 ifp->if_mtu = ifr->ifr_mtu; 675 } 676 break; 677 default: 678 error = EINVAL; /* XXX netbsd has ENOTTY??? */ 679 break; 680 } 681 return (error); 682 } 683 684 static int 685 firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 686 struct sockaddr *sa) 687 { 688 #ifdef INET 689 struct sockaddr_in *sin; 690 #endif 691 #ifdef INET6 692 struct sockaddr_in6 *sin6; 693 #endif 694 695 switch(sa->sa_family) { 696 case AF_LINK: 697 /* 698 * No mapping needed. 699 */ 700 *llsa = 0; 701 return 0; 702 703 #ifdef INET 704 case AF_INET: 705 sin = (struct sockaddr_in *)sa; 706 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 707 return EADDRNOTAVAIL; 708 *llsa = 0; 709 return 0; 710 #endif 711 #ifdef INET6 712 case AF_INET6: 713 sin6 = (struct sockaddr_in6 *)sa; 714 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 715 /* 716 * An IP6 address of 0 means listen to all 717 * of the Ethernet multicast address used for IP6. 718 * (This is used for multicast routers.) 719 */ 720 ifp->if_flags |= IFF_ALLMULTI; 721 *llsa = 0; 722 return 0; 723 } 724 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 725 return EADDRNOTAVAIL; 726 *llsa = 0; 727 return 0; 728 #endif 729 730 default: 731 /* 732 * Well, the text isn't quite right, but it's the name 733 * that counts... 734 */ 735 return EAFNOSUPPORT; 736 } 737 } 738 739 void 740 firewire_ifattach(struct ifnet *ifp, struct fw_hwaddr *llc) 741 { 742 struct fw_com *fc = IFP2FWC(ifp); 743 struct ifaddr *ifa; 744 struct sockaddr_dl *sdl; 745 static const char* speeds[] = { 746 "S100", "S200", "S400", "S800", 747 "S1600", "S3200" 748 }; 749 750 fc->fc_speed = llc->sspd; 751 STAILQ_INIT(&fc->fc_frags); 752 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 = ifp->if_addr; 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 = IFP2FWC(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 807 static void * 808 firewire_alloc(u_char type, struct ifnet *ifp) 809 { 810 struct fw_com *fc; 811 812 fc = malloc(sizeof(struct fw_com), M_FWCOM, M_WAITOK | M_ZERO); 813 fc->fc_ifp = ifp; 814 815 return (fc); 816 } 817 818 static void 819 firewire_free(void *com, u_char type) 820 { 821 822 free(com, M_FWCOM); 823 } 824 825 static int 826 firewire_modevent(module_t mod, int type, void *data) 827 { 828 829 switch (type) { 830 case MOD_LOAD: 831 if_register_com_alloc(IFT_IEEE1394, 832 firewire_alloc, firewire_free); 833 break; 834 case MOD_UNLOAD: 835 if_deregister_com_alloc(IFT_IEEE1394); 836 break; 837 default: 838 return (EOPNOTSUPP); 839 } 840 841 return (0); 842 } 843 844 static moduledata_t firewire_mod = { 845 "if_firewire", 846 firewire_modevent, 847 0 848 }; 849 850 DECLARE_MODULE(if_firewire, firewire_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); 851 MODULE_VERSION(if_firewire, 1); 852