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