if_fwsubr.c revision 144114
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 144114 2005-03-25 16:05:42Z gallatin $ 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/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 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#define IFP2FC(IFP) ((struct fw_com *)IFP) 65 66struct fw_hwaddr firewire_broadcastaddr = { 67 0xffffffff, 68 0xffffffff, 69 0xff, 70 0xff, 71 0xffff, 72 0xffffffff 73}; 74 75static int 76firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 77 struct rtentry *rt0) 78{ 79 struct fw_com *fc = (struct fw_com *) ifp; 80 int error, type; 81 struct rtentry *rt; 82 struct m_tag *mtag; 83 union fw_encap *enc; 84 struct fw_hwaddr *destfw; 85 uint8_t speed; 86 uint16_t psize, fsize, dsize; 87 struct mbuf *mtail; 88 int unicast, dgl, foff; 89 static int next_dgl; 90 91#ifdef MAC 92 error = mac_check_ifnet_transmit(ifp, m); 93 if (error) 94 goto bad; 95#endif 96 97 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 98 error = ENETDOWN; 99 goto bad; 100 } 101 102 error = rt_check(&rt, &rt0, dst); 103 if (error) 104 goto bad; 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 AF_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, rt, m, dst, (u_char *) destfw); 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_if, rt, m, dst, 171 (u_char *) destfw); 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 (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 IFQ_HANDOFF(ifp, m, error); 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 IFQ_HANDOFF(ifp, m, error); 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 319bad: 320 if (m) 321 m_freem(m); 322 return (error); 323} 324 325static struct mbuf * 326firewire_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 GIANT_REQUIRED; 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 480bad: 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 492void 493firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src) 494{ 495 struct fw_com *fc = (struct fw_com *) ifp; 496 union fw_encap *enc; 497 int type, isr; 498 499 GIANT_REQUIRED; 500 501 /* 502 * The caller has already stripped off the packet header 503 * (stream or wreqb) and marked the mbuf's M_BCAST flag 504 * appropriately. We de-encapsulate the IP packet and pass it 505 * up the line after handling link-level fragmentation. 506 */ 507 if (m->m_pkthdr.len < sizeof(uint32_t)) { 508 if_printf(ifp, "discarding frame without " 509 "encapsulation header (len %u pkt len %u)\n", 510 m->m_len, m->m_pkthdr.len); 511 } 512 513 m = m_pullup(m, sizeof(uint32_t)); 514 enc = mtod(m, union fw_encap *); 515 516 /* 517 * Byte swap the encapsulation header manually. 518 */ 519 enc->ul[0] = htonl(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] = htonl(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_create_mbuf_from_ifnet(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 (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 (ip_fastforward(m)) 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 netisr_dispatch(isr, m); 632} 633 634int 635firewire_ioctl(struct ifnet *ifp, int command, caddr_t data) 636{ 637 struct ifaddr *ifa = (struct ifaddr *) data; 638 struct ifreq *ifr = (struct ifreq *) data; 639 int error = 0; 640 641 switch (command) { 642 case SIOCSIFADDR: 643 ifp->if_flags |= IFF_UP; 644 645 switch (ifa->ifa_addr->sa_family) { 646#ifdef INET 647 case AF_INET: 648 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 649 arp_ifinit(ifp, ifa); 650 break; 651#endif 652 default: 653 ifp->if_init(ifp->if_softc); 654 break; 655 } 656 break; 657 658 case SIOCGIFADDR: 659 { 660 struct sockaddr *sa; 661 662 sa = (struct sockaddr *) & ifr->ifr_data; 663 bcopy(&IFP2FC(ifp)->fc_hwaddr, 664 (caddr_t) sa->sa_data, sizeof(struct fw_hwaddr)); 665 } 666 break; 667 668 case SIOCSIFMTU: 669 /* 670 * Set the interface MTU. 671 */ 672 if (ifr->ifr_mtu > 1500) { 673 error = EINVAL; 674 } else { 675 ifp->if_mtu = ifr->ifr_mtu; 676 } 677 break; 678 default: 679 error = EINVAL; /* XXX netbsd has ENOTTY??? */ 680 break; 681 } 682 return (error); 683} 684 685static int 686firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 687 struct sockaddr *sa) 688{ 689#ifdef INET 690 struct sockaddr_in *sin; 691#endif 692#ifdef INET6 693 struct sockaddr_in6 *sin6; 694#endif 695 696 switch(sa->sa_family) { 697 case AF_LINK: 698 /* 699 * No mapping needed. 700 */ 701 *llsa = 0; 702 return 0; 703 704#ifdef INET 705 case AF_INET: 706 sin = (struct sockaddr_in *)sa; 707 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 708 return EADDRNOTAVAIL; 709 *llsa = 0; 710 return 0; 711#endif 712#ifdef INET6 713 case AF_INET6: 714 sin6 = (struct sockaddr_in6 *)sa; 715 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 716 /* 717 * An IP6 address of 0 means listen to all 718 * of the Ethernet multicast address used for IP6. 719 * (This is used for multicast routers.) 720 */ 721 ifp->if_flags |= IFF_ALLMULTI; 722 *llsa = 0; 723 return 0; 724 } 725 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 726 return EADDRNOTAVAIL; 727 *llsa = 0; 728 return 0; 729#endif 730 731 default: 732 /* 733 * Well, the text isn't quite right, but it's the name 734 * that counts... 735 */ 736 return EAFNOSUPPORT; 737 } 738} 739 740void 741firewire_ifattach(struct ifnet *ifp, struct fw_hwaddr *llc) 742{ 743 struct fw_com *fc = (struct fw_com *) ifp; 744 struct ifaddr *ifa; 745 struct sockaddr_dl *sdl; 746 static const char* speeds[] = { 747 "S100", "S200", "S400", "S800", 748 "S1600", "S3200" 749 }; 750 751 fc->fc_speed = llc->sspd; 752 STAILQ_INIT(&fc->fc_frags); 753 754 ifp->if_type = IFT_IEEE1394; 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 = ifaddr_byindex(ifp->if_index); 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 781void 782firewire_ifdetach(struct ifnet *ifp) 783{ 784 bpfdetach(ifp); 785 if_detach(ifp); 786} 787 788void 789firewire_busreset(struct ifnet *ifp) 790{ 791 struct fw_com *fc = (struct fw_com *) 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