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