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