if_fwsubr.c revision 130407
1103285Sikob/* 2103285Sikob * Copyright (c) 2004 Doug Rabson 3103285Sikob * Copyright (c) 1982, 1989, 1993 4103285Sikob * The Regents of the University of California. All rights reserved. 5103285Sikob * 6103285Sikob * Redistribution and use in source and binary forms, with or without 7103285Sikob * modification, are permitted provided that the following conditions 8103285Sikob * are met: 9103285Sikob * 1. Redistributions of source code must retain the above copyright 10103285Sikob * notice, this list of conditions and the following disclaimer. 11103285Sikob * 2. Redistributions in binary form must reproduce the above copyright 12103285Sikob * notice, this list of conditions and the following disclaimer in the 13103285Sikob * documentation and/or other materials provided with the distribution. 14103285Sikob * 3. All advertising materials mentioning features or use of this software 15103285Sikob * must display the following acknowledgement: 16103285Sikob * This product includes software developed by the University of 17103285Sikob * California, Berkeley and its contributors. 18103285Sikob * 4. Neither the name of the University nor the names of its contributors 19103285Sikob * may be used to endorse or promote products derived from this software 20103285Sikob * without specific prior written permission. 21103285Sikob * 22103285Sikob * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23103285Sikob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24103285Sikob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25103285Sikob * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26103285Sikob * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27103285Sikob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28103285Sikob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29103285Sikob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30103285Sikob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31103285Sikob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32103285Sikob * SUCH DAMAGE. 33103285Sikob * 34103285Sikob * $FreeBSD: head/sys/net/if_fwsubr.c 130407 2004-06-13 10:54:36Z dfr $ 35103285Sikob */ 36103285Sikob 37103285Sikob#include "opt_inet.h" 38103285Sikob#include "opt_inet6.h" 39103285Sikob 40103285Sikob#include <sys/param.h> 41103285Sikob#include <sys/systm.h> 42103285Sikob#include <sys/kernel.h> 43103285Sikob#include <sys/malloc.h> 44103285Sikob#include <sys/mbuf.h> 45103285Sikob#include <sys/socket.h> 46103285Sikob#include <sys/sockio.h> 47103285Sikob 48103285Sikob#include <net/if.h> 49103285Sikob#include <net/netisr.h> 50103285Sikob#include <net/route.h> 51103285Sikob#include <net/if_llc.h> 52103285Sikob#include <net/if_dl.h> 53103285Sikob#include <net/if_types.h> 54103285Sikob#include <net/bpf.h> 55103285Sikob#include <net/firewire.h> 56103285Sikob 57103285Sikob#if defined(INET) || defined(INET6) 58103285Sikob#include <netinet/in.h> 59103285Sikob#include <netinet/in_var.h> 60103285Sikob#include <netinet/if_ether.h> 61103285Sikob#include <netinet/ip_fw.h> 62103285Sikob#include <netinet/ip_dummynet.h> 63103285Sikob#endif 64103285Sikob#ifdef INET6 65103285Sikob#include <netinet6/nd6.h> 66103285Sikob#endif 67103285Sikob 68103285Sikob#define IFP2FC(IFP) ((struct fw_com *)IFP) 69103285Sikob 70103285Sikobstruct fw_hwaddr firewire_broadcastaddr = { 71103285Sikob 0xffffffff, 72103285Sikob 0xffffffff, 73103285Sikob 0xff, 74103285Sikob 0xff, 75103285Sikob 0xffff, 76103285Sikob 0xffffffff 77103285Sikob}; 78103285Sikob 79103285Sikobstatic int 80103285Sikobfirewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 81103285Sikob struct rtentry *rt0) 82103285Sikob{ 83103285Sikob struct fw_com *fc = (struct fw_com *) ifp; 84103285Sikob int error, type; 85103285Sikob struct rtentry *rt; 86103285Sikob struct m_tag *mtag; 87103285Sikob union fw_encap *enc; 88103285Sikob struct fw_hwaddr *destfw; 89103285Sikob uint8_t speed; 90103285Sikob uint16_t psize, fsize, dsize; 91103285Sikob struct mbuf *mtail; 92103285Sikob int unicast, dgl, foff; 93103285Sikob static int next_dgl; 94103285Sikob 95103285Sikob GIANT_REQUIRED; 96103285Sikob 97103285Sikob if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 98103285Sikob error = ENETDOWN; 99103285Sikob goto bad; 100103285Sikob } 101103285Sikob 102103285Sikob error = rt_check(&rt, &rt0, dst); 103103285Sikob if (error) 104103285Sikob goto bad; 105103285Sikob 106103285Sikob /* 107103285Sikob * For unicast, we make a tag to store the lladdr of the 108103285Sikob * destination. This might not be the first time we have seen 109103285Sikob * the packet (for instance, the arp code might be trying to 110103285Sikob * re-send it after receiving an arp reply) so we only 111103285Sikob * allocate a tag if there isn't one there already. For 112103285Sikob * multicast, we will eventually use a different tag to store 113103285Sikob * the channel number. 114103285Sikob */ 115103285Sikob unicast = !(m->m_flags & (M_BCAST | M_MCAST)); 116103285Sikob if (unicast) { 117103285Sikob mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, NULL); 118103285Sikob if (!mtag) { 119103285Sikob mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 120103285Sikob sizeof (struct fw_hwaddr), M_NOWAIT); 121103285Sikob if (!mtag) { 122103285Sikob error = ENOMEM; 123103285Sikob goto bad; 124103285Sikob } 125103285Sikob m_tag_prepend(m, mtag); 126103285Sikob } 127103285Sikob destfw = (struct fw_hwaddr *)(mtag + 1); 128103285Sikob } else { 129103285Sikob destfw = 0; 130103285Sikob } 131103285Sikob 132103285Sikob switch (dst->sa_family) { 133103285Sikob#ifdef AF_INET 134103285Sikob case AF_INET: 135103285Sikob /* 136103285Sikob * Only bother with arp for unicast. Allocation of 137103285Sikob * channels etc. for firewire is quite different and 138103285Sikob * doesn't fit into the arp model. 139103285Sikob */ 140103285Sikob if (unicast) { 141103285Sikob error = arpresolve(ifp, rt, m, dst, (u_char *) destfw); 142103285Sikob if (error) 143103285Sikob return (error == EWOULDBLOCK ? 0 : error); 144103285Sikob } 145103285Sikob type = ETHERTYPE_IP; 146103285Sikob break; 147103285Sikob 148103285Sikob case AF_ARP: 149103285Sikob { 150103285Sikob struct arphdr *ah; 151103285Sikob ah = mtod(m, struct arphdr *); 152103285Sikob ah->ar_hrd = htons(ARPHRD_IEEE1394); 153103285Sikob type = ETHERTYPE_ARP; 154103285Sikob if (unicast) 155103285Sikob *destfw = *(struct fw_hwaddr *) ar_tha(ah); 156103285Sikob 157103285Sikob /* 158103285Sikob * The standard arp code leaves a hole for the target 159103285Sikob * hardware address which we need to close up. 160103285Sikob */ 161103285Sikob bcopy(ar_tpa(ah), ar_tha(ah), ah->ar_pln); 162103285Sikob m_adj(m, -ah->ar_hln); 163103285Sikob break; 164103285Sikob } 165103285Sikob#endif 166103285Sikob 167103285Sikob#ifdef INET6 168103285Sikob case AF_INET6: 169103285Sikob if (unicast) { 170103285Sikob error = nd6_storelladdr(&fc->fc_if, rt, m, dst, 171103285Sikob (u_char *) destfw); 172103285Sikob if (error) 173103285Sikob return (error); 174103285Sikob } 175103285Sikob type = ETHERTYPE_IPV6; 176103285Sikob break; 177103285Sikob#endif 178103285Sikob 179103285Sikob default: 180103285Sikob if_printf(ifp, "can't handle af%d\n", dst->sa_family); 181103285Sikob error = EAFNOSUPPORT; 182103285Sikob goto bad; 183103285Sikob } 184103285Sikob 185103285Sikob /* 186103285Sikob * Let BPF tap off a copy before we encapsulate. 187103285Sikob */ 188103285Sikob if (ifp->if_bpf) { 189103285Sikob struct fw_bpfhdr h; 190103285Sikob if (unicast) 191103285Sikob bcopy(destfw, h.firewire_dhost, 8); 192103285Sikob else 193103285Sikob bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8); 194103285Sikob bcopy(&fc->fc_hwaddr, h.firewire_shost, 8); 195103285Sikob h.firewire_type = htons(type); 196103285Sikob bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m); 197103285Sikob } 198103285Sikob 199103285Sikob /* 200103285Sikob * Punt on MCAP for now and send all multicast packets on the 201103285Sikob * broadcast channel. 202103285Sikob */ 203103285Sikob if (m->m_flags & M_MCAST) 204103285Sikob m->m_flags |= M_BCAST; 205103285Sikob 206103285Sikob /* 207103285Sikob * Figure out what speed to use and what the largest supported 208103285Sikob * packet size is. For unicast, this is the minimum of what we 209103285Sikob * can speak and what they can hear. For broadcast, lets be 210103285Sikob * conservative and use S100. We could possibly improve that 211103285Sikob * by examining the bus manager's speed map or similar. We 212103285Sikob * also reduce the packet size for broadcast to account for 213103285Sikob * the GASP header. 214103285Sikob */ 215103285Sikob if (unicast) { 216103285Sikob speed = min(fc->fc_speed, destfw->sspd); 217103285Sikob psize = min(512 << speed, 2 << destfw->sender_max_rec); 218103285Sikob } else { 219103285Sikob speed = 0; 220103285Sikob psize = 512 - 2*sizeof(uint32_t); 221103285Sikob } 222103285Sikob 223103285Sikob /* 224103285Sikob * Next, we encapsulate, possibly fragmenting the original 225103285Sikob * datagram if it won't fit into a single packet. 226103285Sikob */ 227103285Sikob if (m->m_pkthdr.len <= psize - sizeof(uint32_t)) { 228103285Sikob /* 229103285Sikob * No fragmentation is necessary. 230103285Sikob */ 231103285Sikob M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); 232103285Sikob if (!m) { 233103285Sikob error = ENOBUFS; 234103285Sikob goto bad; 235103285Sikob } 236103285Sikob enc = mtod(m, union fw_encap *); 237103285Sikob enc->unfrag.ether_type = type; 238103285Sikob enc->unfrag.lf = FW_ENCAP_UNFRAG; 239103285Sikob 240103285Sikob /* 241103285Sikob * Byte swap the encapsulation header manually. 242103285Sikob */ 243103285Sikob enc->ul[0] = htonl(enc->ul[0]); 244103285Sikob 245103285Sikob return (IF_HANDOFF(&ifp->if_snd, m, ifp) ? 0 : ENOBUFS); 246103285Sikob } else { 247103285Sikob /* 248103285Sikob * Fragment the datagram, making sure to leave enough 249103285Sikob * space for the encapsulation header in each packet. 250103285Sikob */ 251103285Sikob fsize = psize - 2*sizeof(uint32_t); 252103285Sikob dgl = next_dgl++; 253103285Sikob dsize = m->m_pkthdr.len; 254103285Sikob 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