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