if_fwsubr.c revision 130407
1166124Srafan/* 2166124Srafan * Copyright (c) 2004 Doug Rabson 3184989Srafan * Copyright (c) 1982, 1989, 1993 4166124Srafan * The Regents of the University of California. All rights reserved. 5166124Srafan * 6166124Srafan * Redistribution and use in source and binary forms, with or without 7166124Srafan * modification, are permitted provided that the following conditions 8166124Srafan * are met: 9166124Srafan * 1. Redistributions of source code must retain the above copyright 10166124Srafan * notice, this list of conditions and the following disclaimer. 11166124Srafan * 2. Redistributions in binary form must reproduce the above copyright 12166124Srafan * notice, this list of conditions and the following disclaimer in the 13166124Srafan * documentation and/or other materials provided with the distribution. 14166124Srafan * 3. All advertising materials mentioning features or use of this software 15166124Srafan * must display the following acknowledgement: 16166124Srafan * This product includes software developed by the University of 17166124Srafan * California, Berkeley and its contributors. 18166124Srafan * 4. Neither the name of the University nor the names of its contributors 19166124Srafan * may be used to endorse or promote products derived from this software 20166124Srafan * without specific prior written permission. 21166124Srafan * 22166124Srafan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23166124Srafan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24166124Srafan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25166124Srafan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26166124Srafan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27166124Srafan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28166124Srafan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29184989Srafan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30166124Srafan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31166124Srafan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32166124Srafan * SUCH DAMAGE. 33166124Srafan * 34166124Srafan * $FreeBSD: head/sys/net/if_fwsubr.c 130407 2004-06-13 10:54:36Z dfr $ 35166124Srafan */ 36166124Srafan 37166124Srafan#include "opt_inet.h" 38166124Srafan#include "opt_inet6.h" 39166124Srafan 40166124Srafan#include <sys/param.h> 41166124Srafan#include <sys/systm.h> 42166124Srafan#include <sys/kernel.h> 43166124Srafan#include <sys/malloc.h> 44166124Srafan#include <sys/mbuf.h> 45166124Srafan#include <sys/socket.h> 46166124Srafan#include <sys/sockio.h> 47166124Srafan 48166124Srafan#include <net/if.h> 49166124Srafan#include <net/netisr.h> 50166124Srafan#include <net/route.h> 51166124Srafan#include <net/if_llc.h> 52166124Srafan#include <net/if_dl.h> 53166124Srafan#include <net/if_types.h> 54166124Srafan#include <net/bpf.h> 55166124Srafan#include <net/firewire.h> 56166124Srafan 57166124Srafan#if defined(INET) || defined(INET6) 58166124Srafan#include <netinet/in.h> 59166124Srafan#include <netinet/in_var.h> 60166124Srafan#include <netinet/if_ether.h> 61166124Srafan#include <netinet/ip_fw.h> 62166124Srafan#include <netinet/ip_dummynet.h> 63166124Srafan#endif 64166124Srafan#ifdef INET6 65166124Srafan#include <netinet6/nd6.h> 66166124Srafan#endif 67166124Srafan 68166124Srafan#define IFP2FC(IFP) ((struct fw_com *)IFP) 69166124Srafan 70166124Srafanstruct fw_hwaddr firewire_broadcastaddr = { 71166124Srafan 0xffffffff, 72166124Srafan 0xffffffff, 73166124Srafan 0xff, 74166124Srafan 0xff, 75166124Srafan 0xffff, 76166124Srafan 0xffffffff 77166124Srafan}; 78166124Srafan 79166124Srafanstatic int 80166124Srafanfirewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 81166124Srafan struct rtentry *rt0) 82166124Srafan{ 83166124Srafan struct fw_com *fc = (struct fw_com *) ifp; 84166124Srafan int error, type; 85166124Srafan struct rtentry *rt; 86166124Srafan struct m_tag *mtag; 87166124Srafan union fw_encap *enc; 88166124Srafan struct fw_hwaddr *destfw; 89166124Srafan uint8_t speed; 90184989Srafan uint16_t psize, fsize, dsize; 91166124Srafan struct mbuf *mtail; 92166124Srafan int unicast, dgl, foff; 93166124Srafan static int next_dgl; 94166124Srafan 95166124Srafan GIANT_REQUIRED; 96166124Srafan 97166124Srafan if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 98166124Srafan error = ENETDOWN; 99166124Srafan goto bad; 100166124Srafan } 101166124Srafan 102184989Srafan error = rt_check(&rt, &rt0, dst); 103166124Srafan if (error) 104166124Srafan goto bad; 105166124Srafan 106166124Srafan /* 107166124Srafan * For unicast, we make a tag to store the lladdr of the 108166124Srafan * destination. This might not be the first time we have seen 109166124Srafan * the packet (for instance, the arp code might be trying to 110166124Srafan * re-send it after receiving an arp reply) so we only 111166124Srafan * allocate a tag if there isn't one there already. For 112166124Srafan * multicast, we will eventually use a different tag to store 113166124Srafan * the channel number. 114166124Srafan */ 115166124Srafan unicast = !(m->m_flags & (M_BCAST | M_MCAST)); 116166124Srafan if (unicast) { 117166124Srafan mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, NULL); 118166124Srafan if (!mtag) { 119166124Srafan mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 120166124Srafan sizeof (struct fw_hwaddr), M_NOWAIT); 121166124Srafan if (!mtag) { 122166124Srafan error = ENOMEM; 123166124Srafan goto bad; 124166124Srafan } 125166124Srafan m_tag_prepend(m, mtag); 126166124Srafan } 127166124Srafan destfw = (struct fw_hwaddr *)(mtag + 1); 128166124Srafan } else { 129166124Srafan destfw = 0; 130166124Srafan } 131166124Srafan 132166124Srafan 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 240 /* 241 * Byte swap the encapsulation header manually. 242 */ 243 enc->ul[0] = htonl(enc->ul[0]); 244 245 return (IF_HANDOFF(&ifp->if_snd, m, ifp) ? 0 : ENOBUFS); 246 } else { 247 /* 248 * Fragment the datagram, making sure to leave enough 249 * space for the encapsulation header in each packet. 250 */ 251 fsize = psize - 2*sizeof(uint32_t); 252 dgl = next_dgl++; 253 dsize = m->m_pkthdr.len; 254 foff = 0; 255 while (m) { 256 if (m->m_pkthdr.len > fsize) { 257 /* 258 * Split off the tail segment from the 259 * datagram, copying our tags over. 260 */ 261 mtail = m_split(m, fsize, M_DONTWAIT); 262 m_tag_copy_chain(mtail, m, M_NOWAIT); 263 } else { 264 mtail = 0; 265 } 266 267 /* 268 * Add our encapsulation header to this 269 * fragment and hand it off to the link. 270 */ 271 M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT); 272 if (!m) { 273 error = ENOBUFS; 274 goto bad; 275 } 276 enc = mtod(m, union fw_encap *); 277 if (foff == 0) { 278 enc->firstfrag.lf = FW_ENCAP_FIRST; 279 enc->firstfrag.datagram_size = dsize - 1; 280 enc->firstfrag.ether_type = type; 281 enc->firstfrag.dgl = dgl; 282 } else { 283 if (mtail) 284 enc->nextfrag.lf = FW_ENCAP_NEXT; 285 else 286 enc->nextfrag.lf = FW_ENCAP_LAST; 287 enc->nextfrag.datagram_size = dsize - 1; 288 enc->nextfrag.fragment_offset = foff; 289 enc->nextfrag.dgl = dgl; 290 } 291 foff += m->m_pkthdr.len - 2*sizeof(uint32_t); 292 293 /* 294 * Byte swap the encapsulation header manually. 295 */ 296 enc->ul[0] = htonl(enc->ul[0]); 297 enc->ul[1] = htonl(enc->ul[1]); 298 299 if (!IF_HANDOFF(&ifp->if_snd, m, ifp)) { 300 if (mtail) 301 m_freem(mtail); 302 return (ENOBUFS); 303 } 304 305 m = mtail; 306 } 307 308 return (0); 309 } 310 311bad: 312 if (m) 313 m_freem(m); 314 return (error); 315} 316 317static struct mbuf * 318firewire_input_fragment(struct fw_com *fc, struct mbuf *m, int src) 319{ 320 union fw_encap *enc; 321 struct fw_reass *r; 322 struct mbuf *mf, *mprev; 323 int dsize; 324 int fstart, fend, start, end, islast; 325 uint32_t id; 326 327 GIANT_REQUIRED; 328 329 /* 330 * Find an existing reassembly buffer or create a new one. 331 */ 332 enc = mtod(m, union fw_encap *); 333 id = enc->firstfrag.dgl | (src << 16); 334 STAILQ_FOREACH(r, &fc->fc_frags, fr_link) 335 if (r->fr_id == id) 336 break; 337 if (!r) { 338 r = malloc(sizeof(struct fw_reass), M_TEMP, M_NOWAIT); 339 if (!r) { 340 m_freem(m); 341 return 0; 342 } 343 r->fr_id = id; 344 r->fr_frags = 0; 345 STAILQ_INSERT_HEAD(&fc->fc_frags, r, fr_link); 346 } 347 348 /* 349 * If this fragment overlaps any other fragment, we must discard 350 * the partial reassembly and start again. 351 */ 352 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 353 fstart = 0; 354 else 355 fstart = enc->nextfrag.fragment_offset; 356 fend = fstart + m->m_pkthdr.len - 2*sizeof(uint32_t); 357 dsize = enc->nextfrag.datagram_size; 358 islast = (enc->nextfrag.lf == FW_ENCAP_LAST); 359 360 for (mf = r->fr_frags; mf; mf = mf->m_nextpkt) { 361 enc = mtod(mf, union fw_encap *); 362 if (enc->nextfrag.datagram_size != dsize) { 363 /* 364 * This fragment must be from a different 365 * packet. 366 */ 367 goto bad; 368 } 369 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 370 start = 0; 371 else 372 start = enc->nextfrag.fragment_offset; 373 end = start + mf->m_pkthdr.len - 2*sizeof(uint32_t); 374 if ((fstart < end && fend > start) || 375 (islast && enc->nextfrag.lf == FW_ENCAP_LAST)) { 376 /* 377 * Overlap - discard reassembly buffer and start 378 * again with this fragment. 379 */ 380 goto bad; 381 } 382 } 383 384 /* 385 * Find where to put this fragment in the list. 386 */ 387 for (mf = r->fr_frags, mprev = NULL; mf; 388 mprev = mf, mf = mf->m_nextpkt) { 389 enc = mtod(mf, union fw_encap *); 390 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 391 start = 0; 392 else 393 start = enc->nextfrag.fragment_offset; 394 if (start >= fend) 395 break; 396 } 397 398 /* 399 * If this is a last fragment and we are not adding at the end 400 * of the list, discard the buffer. 401 */ 402 if (islast && mprev && mprev->m_nextpkt) 403 goto bad; 404 405 if (mprev) { 406 m->m_nextpkt = mprev->m_nextpkt; 407 mprev->m_nextpkt = m; 408 409 /* 410 * Coalesce forwards and see if we can make a whole 411 * datagram. 412 */ 413 enc = mtod(mprev, union fw_encap *); 414 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 415 start = 0; 416 else 417 start = enc->nextfrag.fragment_offset; 418 end = start + mprev->m_pkthdr.len - 2*sizeof(uint32_t); 419 while (end == fstart) { 420 /* 421 * Strip off the encap header from m and 422 * append it to mprev, freeing m. 423 */ 424 m_adj(m, 2*sizeof(uint32_t)); 425 mprev->m_nextpkt = m->m_nextpkt; 426 mprev->m_pkthdr.len += m->m_pkthdr.len; 427 m_cat(mprev, m); 428 429 if (mprev->m_pkthdr.len == dsize + 1 + 2*sizeof(uint32_t)) { 430 /* 431 * We have assembled a complete packet 432 * we must be finished. Make sure we have 433 * merged the whole chain. 434 */ 435 STAILQ_REMOVE(&fc->fc_frags, r, fw_reass, fr_link); 436 free(r, M_TEMP); 437 m = mprev->m_nextpkt; 438 while (m) { 439 mf = m->m_nextpkt; 440 m_freem(m); 441 m = mf; 442 } 443 mprev->m_nextpkt = NULL; 444 445 return (mprev); 446 } 447 448 /* 449 * See if we can continue merging forwards. 450 */ 451 end = fend; 452 m = mprev->m_nextpkt; 453 if (m) { 454 enc = mtod(m, union fw_encap *); 455 if (enc->firstfrag.lf == FW_ENCAP_FIRST) 456 fstart = 0; 457 else 458 fstart = enc->nextfrag.fragment_offset; 459 fend = fstart + m->m_pkthdr.len 460 - 2*sizeof(uint32_t); 461 } else { 462 break; 463 } 464 } 465 } else { 466 m->m_nextpkt = 0; 467 r->fr_frags = m; 468 } 469 470 return (0); 471 472bad: 473 while (r->fr_frags) { 474 mf = r->fr_frags; 475 r->fr_frags = mf->m_nextpkt; 476 m_freem(mf); 477 } 478 m->m_nextpkt = 0; 479 r->fr_frags = m; 480 481 return (0); 482} 483 484void 485firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src) 486{ 487 struct fw_com *fc = (struct fw_com *) ifp; 488 union fw_encap *enc; 489 int type, isr; 490 491 GIANT_REQUIRED; 492 493 /* 494 * The caller has already stripped off the packet header 495 * (stream or wreqb) and marked the mbuf's M_BCAST flag 496 * appropriately. We de-encapsulate the IP packet and pass it 497 * up the line after handling link-level fragmentation. 498 */ 499 if (m->m_pkthdr.len < sizeof(uint32_t)) { 500 if_printf(ifp, "discarding frame without " 501 "encapsulation header (len %u pkt len %u)\n", 502 m->m_len, m->m_pkthdr.len); 503 } 504 505 m = m_pullup(m, sizeof(uint32_t)); 506 enc = mtod(m, union fw_encap *); 507 508 /* 509 * Byte swap the encapsulation header manually. 510 */ 511 enc->ul[0] = htonl(enc->ul[0]); 512 513 if (enc->unfrag.lf != 0) { 514 m = m_pullup(m, 2*sizeof(uint32_t)); 515 if (!m) 516 return; 517 enc = mtod(m, union fw_encap *); 518 enc->ul[1] = htonl(enc->ul[1]); 519 m = firewire_input_fragment(fc, m, src); 520 if (!m) 521 return; 522 enc = mtod(m, union fw_encap *); 523 type = enc->firstfrag.ether_type; 524 m_adj(m, 2*sizeof(uint32_t)); 525 } else { 526 type = enc->unfrag.ether_type; 527 m_adj(m, sizeof(uint32_t)); 528 } 529 530 if (m->m_pkthdr.rcvif == NULL) { 531 if_printf(ifp, "discard frame w/o interface pointer\n"); 532 ifp->if_ierrors++; 533 m_freem(m); 534 return; 535 } 536#ifdef DIAGNOSTIC 537 if (m->m_pkthdr.rcvif != ifp) { 538 if_printf(ifp, "Warning, frame marked as received on %s\n", 539 m->m_pkthdr.rcvif->if_xname); 540 } 541#endif 542 543#ifdef MAC 544 /* 545 * Tag the mbuf with an appropriate MAC label before any other 546 * consumers can get to it. 547 */ 548 mac_create_mbuf_from_ifnet(ifp, m); 549#endif 550 551 /* 552 * Give bpf a chance at the packet. The link-level driver 553 * should have left us a tag with the EUID of the sender. 554 */ 555 if (ifp->if_bpf) { 556 struct fw_bpfhdr h; 557 struct m_tag *mtag; 558 559 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 0); 560 if (mtag) 561 bcopy(mtag + 1, h.firewire_shost, 8); 562 else 563 bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 564 bcopy(&fc->fc_hwaddr, h.firewire_dhost, 8); 565 h.firewire_type = htons(type); 566 bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 567 } 568 569 if (ifp->if_flags & IFF_MONITOR) { 570 /* 571 * Interface marked for monitoring; discard packet. 572 */ 573 m_freem(m); 574 return; 575 } 576 577 ifp->if_ibytes += m->m_pkthdr.len; 578 579 /* Discard packet if interface is not up */ 580 if ((ifp->if_flags & IFF_UP) == 0) { 581 m_freem(m); 582 return; 583 } 584 585 if (m->m_flags & (M_BCAST|M_MCAST)) 586 ifp->if_imcasts++; 587 588 switch (type) { 589#ifdef INET 590 case ETHERTYPE_IP: 591 if (ip_fastforward(m)) 592 return; 593 isr = NETISR_IP; 594 break; 595 596 case ETHERTYPE_ARP: 597 { 598 struct arphdr *ah; 599 ah = mtod(m, struct arphdr *); 600 601 /* 602 * Adjust the arp packet to insert an empty tha slot. 603 */ 604 m->m_len += ah->ar_hln; 605 m->m_pkthdr.len += ah->ar_hln; 606 bcopy(ar_tha(ah), ar_tpa(ah), ah->ar_pln); 607 isr = NETISR_ARP; 608 break; 609 } 610#endif 611 612#ifdef INET6 613 case ETHERTYPE_IPV6: 614 isr = NETISR_IPV6; 615 break; 616#endif 617 618 default: 619 m_freem(m); 620 return; 621 } 622 623 netisr_dispatch(isr, m); 624} 625 626int 627firewire_ioctl(struct ifnet *ifp, int command, caddr_t data) 628{ 629 struct ifaddr *ifa = (struct ifaddr *) data; 630 struct ifreq *ifr = (struct ifreq *) data; 631 int error = 0; 632 633 switch (command) { 634 case SIOCSIFADDR: 635 ifp->if_flags |= IFF_UP; 636 637 switch (ifa->ifa_addr->sa_family) { 638#ifdef INET 639 case AF_INET: 640 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 641 arp_ifinit(ifp, ifa); 642 break; 643#endif 644 default: 645 ifp->if_init(ifp->if_softc); 646 break; 647 } 648 break; 649 650 case SIOCGIFADDR: 651 { 652 struct sockaddr *sa; 653 654 sa = (struct sockaddr *) & ifr->ifr_data; 655 bcopy(&IFP2FC(ifp)->fc_hwaddr, 656 (caddr_t) sa->sa_data, sizeof(struct fw_hwaddr)); 657 } 658 break; 659 660 case SIOCSIFMTU: 661 /* 662 * Set the interface MTU. 663 */ 664 if (ifr->ifr_mtu > 1500) { 665 error = EINVAL; 666 } else { 667 ifp->if_mtu = ifr->ifr_mtu; 668 } 669 break; 670 default: 671 error = EINVAL; /* XXX netbsd has ENOTTY??? */ 672 break; 673 } 674 return (error); 675} 676 677static int 678firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 679 struct sockaddr *sa) 680{ 681#ifdef INET 682 struct sockaddr_in *sin; 683#endif 684#ifdef INET6 685 struct sockaddr_in6 *sin6; 686#endif 687 688 switch(sa->sa_family) { 689 case AF_LINK: 690 /* 691 * No mapping needed. 692 */ 693 *llsa = 0; 694 return 0; 695 696#ifdef INET 697 case AF_INET: 698 sin = (struct sockaddr_in *)sa; 699 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 700 return EADDRNOTAVAIL; 701 *llsa = 0; 702 return 0; 703#endif 704#ifdef INET6 705 case AF_INET6: 706 sin6 = (struct sockaddr_in6 *)sa; 707 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 708 /* 709 * An IP6 address of 0 means listen to all 710 * of the Ethernet multicast address used for IP6. 711 * (This is used for multicast routers.) 712 */ 713 ifp->if_flags |= IFF_ALLMULTI; 714 *llsa = 0; 715 return 0; 716 } 717 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 718 return EADDRNOTAVAIL; 719 *llsa = 0; 720 return 0; 721#endif 722 723 default: 724 /* 725 * Well, the text isn't quite right, but it's the name 726 * that counts... 727 */ 728 return EAFNOSUPPORT; 729 } 730} 731 732void 733firewire_ifattach(struct ifnet *ifp, struct fw_hwaddr *llc) 734{ 735 struct fw_com *fc = (struct fw_com *) ifp; 736 struct ifaddr *ifa; 737 struct sockaddr_dl *sdl; 738 static const char* speeds[] = { 739 "S100", "S200", "S400", "S800", 740 "S1600", "S3200" 741 }; 742 743 fc->fc_speed = llc->sspd; 744 STAILQ_INIT(&fc->fc_frags); 745 746 ifp->if_type = IFT_IEEE1394; 747 ifp->if_addrlen = sizeof(struct fw_hwaddr); 748 ifp->if_hdrlen = 0; 749 if_attach(ifp); 750 ifp->if_mtu = 1500; /* XXX */ 751 ifp->if_output = firewire_output; 752 ifp->if_resolvemulti = firewire_resolvemulti; 753 ifp->if_broadcastaddr = (u_char *) &firewire_broadcastaddr; 754 755 ifa = ifaddr_byindex(ifp->if_index); 756 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); 757 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 758 sdl->sdl_type = IFT_IEEE1394; 759 sdl->sdl_alen = ifp->if_addrlen; 760 bcopy(llc, LLADDR(sdl), ifp->if_addrlen); 761 762 bpfattach(ifp, DLT_APPLE_IP_OVER_IEEE1394, 763 sizeof(struct fw_hwaddr)); 764 765 if_printf(ifp, "Firewire address: %8D @ 0x%04x%08x, %s, maxrec %d\n", 766 (uint8_t *) &llc->sender_unique_ID_hi, ":", 767 ntohs(llc->sender_unicast_FIFO_hi), 768 ntohl(llc->sender_unicast_FIFO_lo), 769 speeds[llc->sspd], 770 (2 << llc->sender_max_rec)); 771} 772 773void 774firewire_ifdetach(struct ifnet *ifp) 775{ 776 bpfdetach(ifp); 777 if_detach(ifp); 778} 779 780void 781firewire_busreset(struct ifnet *ifp) 782{ 783 struct fw_com *fc = (struct fw_com *) ifp; 784 struct fw_reass *r; 785 struct mbuf *m; 786 787 /* 788 * Discard any partial datagrams since the host ids may have changed. 789 */ 790 while ((r = STAILQ_FIRST(&fc->fc_frags))) { 791 STAILQ_REMOVE_HEAD(&fc->fc_frags, fr_link); 792 while (r->fr_frags) { 793 m = r->fr_frags; 794 r->fr_frags = m->m_nextpkt; 795 m_freem(m); 796 } 797 free(r, M_TEMP); 798 } 799} 800