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/if_var.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 #include <net/if_llatbl.h> 55 56 #if defined(INET) || defined(INET6) 57 #include <netinet/in.h> 58 #include <netinet/in_var.h> 59 #include <netinet/if_ether.h> 60 #endif 61 #ifdef INET6 62 #include <netinet6/nd6.h> 63 #endif 64 65 #include <security/mac/mac_framework.h> 66 67 static MALLOC_DEFINE(M_FWCOM, "fw_com", "firewire interface internals"); 68 69 struct fw_hwaddr firewire_broadcastaddr = { 70 0xffffffff, 71 0xffffffff, 72 0xff, 73 0xff, 74 0xffff, 75 0xffffffff 76 }; 77 78 static int 79 firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 80 struct route *ro) 81 { 82 struct fw_com *fc = IFP2FWC(ifp); 83 int error, type; 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 #if defined(INET) || defined(INET6) 93 struct llentry *lle; 94 #endif 95 96 #ifdef MAC 97 error = mac_ifnet_check_transmit(ifp, m); 98 if (error) 99 goto bad; 100 #endif 101 102 if (!((ifp->if_flags & IFF_UP) && 103 (ifp->if_drv_flags & IFF_DRV_RUNNING))) { 104 error = ENETDOWN; 105 goto bad; 106 } 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 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, ro ? ro->ro_rt : NULL, m, dst, (u_char *) destfw, &lle); 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_ifp, m, dst, 173 (u_char *) destfw, &lle); 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 (bpf_peers_present(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_NOWAIT); 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 enc->unfrag.reserved = 0; 242 243 /* 244 * Byte swap the encapsulation header manually. 245 */ 246 enc->ul[0] = htonl(enc->ul[0]); 247 248 error = (ifp->if_transmit)(ifp, m); 249 return (error); 250 } else { 251 /* 252 * Fragment the datagram, making sure to leave enough 253 * space for the encapsulation header in each packet. 254 */ 255 fsize = psize - 2*sizeof(uint32_t); 256 dgl = next_dgl++; 257 dsize = m->m_pkthdr.len; 258 foff = 0; 259 while (m) { 260 if (m->m_pkthdr.len > fsize) { 261 /* 262 * Split off the tail segment from the 263 * datagram, copying our tags over. 264 */ 265 mtail = m_split(m, fsize, M_NOWAIT); 266 m_tag_copy_chain(mtail, m, M_NOWAIT); 267 } else { 268 mtail = 0; 269 } 270 271 /* 272 * Add our encapsulation header to this 273 * fragment and hand it off to the link. 274 */ 275 M_PREPEND(m, 2*sizeof(uint32_t), M_NOWAIT); 276 if (!m) { 277 error = ENOBUFS; 278 goto bad; 279 } 280 enc = mtod(m, union fw_encap *); 281 if (foff == 0) { 282 enc->firstfrag.lf = FW_ENCAP_FIRST; 283 enc->firstfrag.reserved1 = 0; 284 enc->firstfrag.reserved2 = 0; 285 enc->firstfrag.datagram_size = dsize - 1; 286 enc->firstfrag.ether_type = type; 287 enc->firstfrag.dgl = dgl; 288 } else { 289 if (mtail) 290 enc->nextfrag.lf = FW_ENCAP_NEXT; 291 else 292 enc->nextfrag.lf = FW_ENCAP_LAST; 293 enc->nextfrag.reserved1 = 0; 294 enc->nextfrag.reserved2 = 0; 295 enc->nextfrag.reserved3 = 0; 296 enc->nextfrag.datagram_size = dsize - 1; 297 enc->nextfrag.fragment_offset = foff; 298 enc->nextfrag.dgl = dgl; 299 } 300 foff += m->m_pkthdr.len - 2*sizeof(uint32_t); 301 302 /* 303 * Byte swap the encapsulation header manually. 304 */ 305 enc->ul[0] = htonl(enc->ul[0]); 306 enc->ul[1] = htonl(enc->ul[1]); 307 308 error = (ifp->if_transmit)(ifp, m); 309 if (error) { 310 if (mtail) 311 m_freem(mtail); 312 return (ENOBUFS); 313 } 314 315 m = mtail; 316 } 317 318 return (0); 319 } 320 321 bad: 322 if (m) 323 m_freem(m); 324 return (error); 325 } 326 327 static struct mbuf * 328 firewire_input_fragment(struct fw_com *fc, struct mbuf *m, int src) 329 { 330 union fw_encap *enc; 331 struct fw_reass *r; 332 struct mbuf *mf, *mprev; 333 int dsize; 334 int fstart, fend, start, end, islast; 335 uint32_t id; 336 337 /* 338 * Find an existing reassembly buffer or create a new one. 339 */ 340 enc = mtod(m, union fw_encap *); 341 id = enc->firstfrag.dgl | (src << 16); 342 STAILQ_FOREACH(r, &fc->fc_frags, fr_link) 343 if (r->fr_id == id) 344 break; 345 if (!r) { 346 r = malloc(sizeof(struct fw_reass), M_TEMP, M_NOWAIT); 347 if (!r) { 348 m_freem(m); 349 return 0; 350 } 351 r->fr_id = id; 352 r->fr_frags = 0; 353 STAILQ_INSERT_HEAD(&fc->fc_frags, r, fr_link); 354 } 355 356 /* 357 * If this fragment overlaps any other fragment, we must discard 358 * the partial reassembly and start again. 359 */ 360 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 361 fstart = 0; 362 else 363 fstart = enc->nextfrag.fragment_offset; 364 fend = fstart + m->m_pkthdr.len - 2*sizeof(uint32_t); 365 dsize = enc->nextfrag.datagram_size; 366 islast = (enc->nextfrag.lf == FW_ENCAP_LAST); 367 368 for (mf = r->fr_frags; mf; mf = mf->m_nextpkt) { 369 enc = mtod(mf, union fw_encap *); 370 if (enc->nextfrag.datagram_size != dsize) { 371 /* 372 * This fragment must be from a different 373 * packet. 374 */ 375 goto bad; 376 } 377 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 378 start = 0; 379 else 380 start = enc->nextfrag.fragment_offset; 381 end = start + mf->m_pkthdr.len - 2*sizeof(uint32_t); 382 if ((fstart < end && fend > start) || 383 (islast && enc->nextfrag.lf == FW_ENCAP_LAST)) { 384 /* 385 * Overlap - discard reassembly buffer and start 386 * again with this fragment. 387 */ 388 goto bad; 389 } 390 } 391 392 /* 393 * Find where to put this fragment in the list. 394 */ 395 for (mf = r->fr_frags, mprev = NULL; mf; 396 mprev = mf, mf = mf->m_nextpkt) { 397 enc = mtod(mf, union fw_encap *); 398 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 399 start = 0; 400 else 401 start = enc->nextfrag.fragment_offset; 402 if (start >= fend) 403 break; 404 } 405 406 /* 407 * If this is a last fragment and we are not adding at the end 408 * of the list, discard the buffer. 409 */ 410 if (islast && mprev && mprev->m_nextpkt) 411 goto bad; 412 413 if (mprev) { 414 m->m_nextpkt = mprev->m_nextpkt; 415 mprev->m_nextpkt = m; 416 417 /* 418 * Coalesce forwards and see if we can make a whole 419 * datagram. 420 */ 421 enc = mtod(mprev, union fw_encap *); 422 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 423 start = 0; 424 else 425 start = enc->nextfrag.fragment_offset; 426 end = start + mprev->m_pkthdr.len - 2*sizeof(uint32_t); 427 while (end == fstart) { 428 /* 429 * Strip off the encap header from m and 430 * append it to mprev, freeing m. 431 */ 432 m_adj(m, 2*sizeof(uint32_t)); 433 mprev->m_nextpkt = m->m_nextpkt; 434 mprev->m_pkthdr.len += m->m_pkthdr.len; 435 m_cat(mprev, m); 436 437 if (mprev->m_pkthdr.len == dsize + 1 + 2*sizeof(uint32_t)) { 438 /* 439 * We have assembled a complete packet 440 * we must be finished. Make sure we have 441 * merged the whole chain. 442 */ 443 STAILQ_REMOVE(&fc->fc_frags, r, fw_reass, fr_link); 444 free(r, M_TEMP); 445 m = mprev->m_nextpkt; 446 while (m) { 447 mf = m->m_nextpkt; 448 m_freem(m); 449 m = mf; 450 } 451 mprev->m_nextpkt = NULL; 452 453 return (mprev); 454 } 455 456 /* 457 * See if we can continue merging forwards. 458 */ 459 end = fend; 460 m = mprev->m_nextpkt; 461 if (m) { 462 enc = mtod(m, union fw_encap *); 463 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 464 fstart = 0; 465 else 466 fstart = enc->nextfrag.fragment_offset; 467 fend = fstart + m->m_pkthdr.len 468 - 2*sizeof(uint32_t); 469 } else { 470 break; 471 } 472 } 473 } else { 474 m->m_nextpkt = 0; 475 r->fr_frags = m; 476 } 477 478 return (0); 479 480 bad: 481 while (r->fr_frags) { 482 mf = r->fr_frags; 483 r->fr_frags = mf->m_nextpkt; 484 m_freem(mf); 485 } 486 m->m_nextpkt = 0; 487 r->fr_frags = m; 488 489 return (0); 490 } 491 492 void 493 firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src) 494 { 495 struct fw_com *fc = IFP2FWC(ifp); 496 union fw_encap *enc; 497 int type, isr; 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 if (m == NULL) 513 return; 514 enc = mtod(m, union fw_encap *); 515 516 /* 517 * Byte swap the encapsulation header manually. 518 */ 519 enc->ul[0] = ntohl(enc->ul[0]); 520 521 if (enc->unfrag.lf != 0) { 522 m = m_pullup(m, 2*sizeof(uint32_t)); 523 if (!m) 524 return; 525 enc = mtod(m, union fw_encap *); 526 enc->ul[1] = ntohl(enc->ul[1]); 527 m = firewire_input_fragment(fc, m, src); 528 if (!m) 529 return; 530 enc = mtod(m, union fw_encap *); 531 type = enc->firstfrag.ether_type; 532 m_adj(m, 2*sizeof(uint32_t)); 533 } else { 534 type = enc->unfrag.ether_type; 535 m_adj(m, sizeof(uint32_t)); 536 } 537 538 if (m->m_pkthdr.rcvif == NULL) { 539 if_printf(ifp, "discard frame w/o interface pointer\n"); 540 ifp->if_ierrors++; 541 m_freem(m); 542 return; 543 } 544 #ifdef DIAGNOSTIC 545 if (m->m_pkthdr.rcvif != ifp) { 546 if_printf(ifp, "Warning, frame marked as received on %s\n", 547 m->m_pkthdr.rcvif->if_xname); 548 } 549 #endif 550 551 #ifdef MAC 552 /* 553 * Tag the mbuf with an appropriate MAC label before any other 554 * consumers can get to it. 555 */ 556 mac_ifnet_create_mbuf(ifp, m); 557 #endif 558 559 /* 560 * Give bpf a chance at the packet. The link-level driver 561 * should have left us a tag with the EUID of the sender. 562 */ 563 if (bpf_peers_present(ifp->if_bpf)) { 564 struct fw_bpfhdr h; 565 struct m_tag *mtag; 566 567 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 0); 568 if (mtag) 569 bcopy(mtag + 1, h.firewire_shost, 8); 570 else 571 bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 572 bcopy(&fc->fc_hwaddr, h.firewire_dhost, 8); 573 h.firewire_type = htons(type); 574 bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 575 } 576 577 if (ifp->if_flags & IFF_MONITOR) { 578 /* 579 * Interface marked for monitoring; discard packet. 580 */ 581 m_freem(m); 582 return; 583 } 584 585 ifp->if_ibytes += m->m_pkthdr.len; 586 587 /* Discard packet if interface is not up */ 588 if ((ifp->if_flags & IFF_UP) == 0) { 589 m_freem(m); 590 return; 591 } 592 593 if (m->m_flags & (M_BCAST|M_MCAST)) 594 ifp->if_imcasts++; 595 596 switch (type) { 597 #ifdef INET 598 case ETHERTYPE_IP: 599 if ((m = ip_fastforward(m)) == NULL) 600 return; 601 isr = NETISR_IP; 602 break; 603 604 case ETHERTYPE_ARP: 605 { 606 struct arphdr *ah; 607 ah = mtod(m, struct arphdr *); 608 609 /* 610 * Adjust the arp packet to insert an empty tha slot. 611 */ 612 m->m_len += ah->ar_hln; 613 m->m_pkthdr.len += ah->ar_hln; 614 bcopy(ar_tha(ah), ar_tpa(ah), ah->ar_pln); 615 isr = NETISR_ARP; 616 break; 617 } 618 #endif 619 620 #ifdef INET6 621 case ETHERTYPE_IPV6: 622 isr = NETISR_IPV6; 623 break; 624 #endif 625 626 default: 627 m_freem(m); 628 return; 629 } 630 631 M_SETFIB(m, ifp->if_fib); 632 netisr_dispatch(isr, m); 633 } 634 635 int 636 firewire_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 637 { 638 struct ifaddr *ifa = (struct ifaddr *) data; 639 struct ifreq *ifr = (struct ifreq *) data; 640 int error = 0; 641 642 switch (command) { 643 case SIOCSIFADDR: 644 ifp->if_flags |= IFF_UP; 645 646 switch (ifa->ifa_addr->sa_family) { 647 #ifdef INET 648 case AF_INET: 649 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 650 arp_ifinit(ifp, ifa); 651 break; 652 #endif 653 default: 654 ifp->if_init(ifp->if_softc); 655 break; 656 } 657 break; 658 659 case SIOCGIFADDR: 660 { 661 struct sockaddr *sa; 662 663 sa = (struct sockaddr *) & ifr->ifr_data; 664 bcopy(&IFP2FWC(ifp)->fc_hwaddr, 665 (caddr_t) sa->sa_data, sizeof(struct fw_hwaddr)); 666 } 667 break; 668 669 case SIOCSIFMTU: 670 /* 671 * Set the interface MTU. 672 */ 673 if (ifr->ifr_mtu > 1500) { 674 error = EINVAL; 675 } else { 676 ifp->if_mtu = ifr->ifr_mtu; 677 } 678 break; 679 default: 680 error = EINVAL; /* XXX netbsd has ENOTTY??? */ 681 break; 682 } 683 return (error); 684 } 685 686 static int 687 firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 688 struct sockaddr *sa) 689 { 690 #ifdef INET 691 struct sockaddr_in *sin; 692 #endif 693 #ifdef INET6 694 struct sockaddr_in6 *sin6; 695 #endif 696 697 switch(sa->sa_family) { 698 case AF_LINK: 699 /* 700 * No mapping needed. 701 */ 702 *llsa = 0; 703 return 0; 704 705 #ifdef INET 706 case AF_INET: 707 sin = (struct sockaddr_in *)sa; 708 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 709 return EADDRNOTAVAIL; 710 *llsa = 0; 711 return 0; 712 #endif 713 #ifdef INET6 714 case AF_INET6: 715 sin6 = (struct sockaddr_in6 *)sa; 716 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 717 /* 718 * An IP6 address of 0 means listen to all 719 * of the Ethernet multicast address used for IP6. 720 * (This is used for multicast routers.) 721 */ 722 ifp->if_flags |= IFF_ALLMULTI; 723 *llsa = 0; 724 return 0; 725 } 726 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 727 return EADDRNOTAVAIL; 728 *llsa = 0; 729 return 0; 730 #endif 731 732 default: 733 /* 734 * Well, the text isn't quite right, but it's the name 735 * that counts... 736 */ 737 return EAFNOSUPPORT; 738 } 739 } 740 741 void 742 firewire_ifattach(struct ifnet *ifp, struct fw_hwaddr *llc) 743 { 744 struct fw_com *fc = IFP2FWC(ifp); 745 struct ifaddr *ifa; 746 struct sockaddr_dl *sdl; 747 static const char* speeds[] = { 748 "S100", "S200", "S400", "S800", 749 "S1600", "S3200" 750 }; 751 752 fc->fc_speed = llc->sspd; 753 STAILQ_INIT(&fc->fc_frags); 754 755 ifp->if_addrlen = sizeof(struct fw_hwaddr); 756 ifp->if_hdrlen = 0; 757 if_attach(ifp); 758 ifp->if_mtu = 1500; /* XXX */ 759 ifp->if_output = firewire_output; 760 ifp->if_resolvemulti = firewire_resolvemulti; 761 ifp->if_broadcastaddr = (u_char *) &firewire_broadcastaddr; 762 763 ifa = ifp->if_addr; 764 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); 765 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 766 sdl->sdl_type = IFT_IEEE1394; 767 sdl->sdl_alen = ifp->if_addrlen; 768 bcopy(llc, LLADDR(sdl), ifp->if_addrlen); 769 770 bpfattach(ifp, DLT_APPLE_IP_OVER_IEEE1394, 771 sizeof(struct fw_hwaddr)); 772 773 if_printf(ifp, "Firewire address: %8D @ 0x%04x%08x, %s, maxrec %d\n", 774 (uint8_t *) &llc->sender_unique_ID_hi, ":", 775 ntohs(llc->sender_unicast_FIFO_hi), 776 ntohl(llc->sender_unicast_FIFO_lo), 777 speeds[llc->sspd], 778 (2 << llc->sender_max_rec)); 779 } 780 781 void 782 firewire_ifdetach(struct ifnet *ifp) 783 { 784 bpfdetach(ifp); 785 if_detach(ifp); 786 } 787 788 void 789 firewire_busreset(struct ifnet *ifp) 790 { 791 struct fw_com *fc = IFP2FWC(ifp); 792 struct fw_reass *r; 793 struct mbuf *m; 794 795 /* 796 * Discard any partial datagrams since the host ids may have changed. 797 */ 798 while ((r = STAILQ_FIRST(&fc->fc_frags))) { 799 STAILQ_REMOVE_HEAD(&fc->fc_frags, fr_link); 800 while (r->fr_frags) { 801 m = r->fr_frags; 802 r->fr_frags = m->m_nextpkt; 803 m_freem(m); 804 } 805 free(r, M_TEMP); 806 } 807 } 808 809 static void * 810 firewire_alloc(u_char type, struct ifnet *ifp) 811 { 812 struct fw_com *fc; 813 814 fc = malloc(sizeof(struct fw_com), M_FWCOM, M_WAITOK | M_ZERO); 815 fc->fc_ifp = ifp; 816 817 return (fc); 818 } 819 820 static void 821 firewire_free(void *com, u_char type) 822 { 823 824 free(com, M_FWCOM); 825 } 826 827 static int 828 firewire_modevent(module_t mod, int type, void *data) 829 { 830 831 switch (type) { 832 case MOD_LOAD: 833 if_register_com_alloc(IFT_IEEE1394, 834 firewire_alloc, firewire_free); 835 break; 836 case MOD_UNLOAD: 837 if_deregister_com_alloc(IFT_IEEE1394); 838 break; 839 default: 840 return (EOPNOTSUPP); 841 } 842 843 return (0); 844 } 845 846 static moduledata_t firewire_mod = { 847 "if_firewire", 848 firewire_modevent, 849 0 850 }; 851 852 DECLARE_MODULE(if_firewire, firewire_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); 853 MODULE_VERSION(if_firewire, 1); 854