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