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