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