xref: /openbsd-src/sys/net/if_ethersubr.c (revision 2777ee89d0e541ec819d05abee114837837abbec)
1 /*	$OpenBSD: if_ethersubr.c,v 1.235 2016/04/01 04:03:35 jsg Exp $	*/
2 /*	$NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * 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 project 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 PROJECT 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 PROJECT 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 /*
34  * Copyright (c) 1982, 1989, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. Neither the name of the University nor the names of its contributors
46  *    may be used to endorse or promote products derived from this software
47  *    without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  *
61  *	@(#)if_ethersubr.c	8.1 (Berkeley) 6/10/93
62  */
63 
64 /*
65 %%% portions-copyright-nrl-95
66 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
67 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
68 Reserved. All rights under this copyright have been assigned to the US
69 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
70 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
71 software.
72 You should have received a copy of the license with this software. If you
73 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
74 */
75 
76 #include "bpfilter.h"
77 
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/kernel.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/protosw.h>
84 #include <sys/socket.h>
85 #include <sys/ioctl.h>
86 #include <sys/errno.h>
87 #include <sys/syslog.h>
88 #include <sys/timeout.h>
89 
90 #include <net/if.h>
91 #include <net/netisr.h>
92 #include <net/route.h>
93 #include <net/if_llc.h>
94 #include <net/if_dl.h>
95 #include <net/if_media.h>
96 #include <net/if_types.h>
97 
98 #include <netinet/in.h>
99 #include <netinet/if_ether.h>
100 #include <netinet/ip_ipsp.h>
101 
102 #if NBPFILTER > 0
103 #include <net/bpf.h>
104 #endif
105 
106 #include "pppoe.h"
107 #if NPPPOE > 0
108 #include <net/if_pppoe.h>
109 #endif
110 
111 #ifdef INET6
112 #include <netinet6/in6_var.h>
113 #include <netinet6/nd6.h>
114 #endif
115 
116 #ifdef PIPEX
117 #include <net/pipex.h>
118 #endif
119 
120 #ifdef MPLS
121 #include <netmpls/mpls.h>
122 #endif /* MPLS */
123 
124 u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
125     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
126 u_int8_t etheranyaddr[ETHER_ADDR_LEN] =
127     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
128 #define senderr(e) { error = (e); goto bad;}
129 
130 int
131 ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data)
132 {
133 	struct ifreq *ifr = (struct ifreq *)data;
134 	int error = 0;
135 
136 	switch (cmd) {
137 	case SIOCSIFADDR:
138 		break;
139 
140 	case SIOCSIFMTU:
141 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
142 			error = EINVAL;
143 		else
144 			ifp->if_mtu = ifr->ifr_mtu;
145 		break;
146 
147 	case SIOCADDMULTI:
148 	case SIOCDELMULTI:
149 		if (ifp->if_flags & IFF_MULTICAST) {
150 			error = (cmd == SIOCADDMULTI) ?
151 			    ether_addmulti(ifr, arp) :
152 			    ether_delmulti(ifr, arp);
153 		} else
154 			error = ENOTTY;
155 		break;
156 
157 	default:
158 		error = ENOTTY;
159 	}
160 
161 	return (error);
162 }
163 
164 
165 void
166 ether_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
167 {
168 	switch (rt_key(rt)->sa_family) {
169 	case AF_INET:
170 		arp_rtrequest(ifp, req, rt);
171 		break;
172 #ifdef INET6
173 	case AF_INET6:
174 		nd6_rtrequest(ifp, req, rt);
175 		break;
176 #endif
177 	default:
178 		break;
179 	}
180 }
181 /*
182  * Ethernet output routine.
183  * Encapsulate a packet of type family for the local net.
184  * Assumes that ifp is actually pointer to arpcom structure.
185  */
186 int
187 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
188     struct rtentry *rt)
189 {
190 	u_int16_t etype;
191 	u_char edst[ETHER_ADDR_LEN];
192 	u_char *esrc;
193 	struct mbuf *mcopy = NULL;
194 	struct ether_header *eh;
195 	struct arpcom *ac = (struct arpcom *)ifp;
196 	int error = 0;
197 
198 #ifdef DIAGNOSTIC
199 	if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
200 		printf("%s: trying to send packet on wrong domain. "
201 		    "if %d vs. mbuf %d\n", ifp->if_xname,
202 		    ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid));
203 	}
204 #endif
205 
206 	esrc = ac->ac_enaddr;
207 
208 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
209 		senderr(ENETDOWN);
210 
211 	switch (dst->sa_family) {
212 	case AF_INET:
213 		error = arpresolve(ifp, rt, m, dst, edst);
214 		if (error)
215 			return (error == EAGAIN ? 0 : error);
216 		/* If broadcasting on a simplex interface, loopback a copy */
217 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
218 		    !m->m_pkthdr.pf.routed)
219 			mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT);
220 		etype = htons(ETHERTYPE_IP);
221 		break;
222 #ifdef INET6
223 	case AF_INET6:
224 		error = nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst);
225 		if (error)
226 			return (error);
227 		etype = htons(ETHERTYPE_IPV6);
228 		break;
229 #endif
230 #ifdef MPLS
231        case AF_MPLS:
232 		if (rt)
233 			dst = rt_key(rt);
234 		else
235 			senderr(EHOSTUNREACH);
236 
237 		if (!ISSET(ifp->if_xflags, IFXF_MPLS))
238 			senderr(ENETUNREACH);
239 
240 		switch (dst->sa_family) {
241 			case AF_LINK:
242 				if (satosdl(dst)->sdl_alen < sizeof(edst))
243 					senderr(EHOSTUNREACH);
244 				memcpy(edst, LLADDR(satosdl(dst)),
245 				    sizeof(edst));
246 				break;
247 			case AF_INET:
248 			case AF_MPLS:
249 				error = arpresolve(ifp, rt, m, dst, edst);
250 				if (error)
251 					return (error == EAGAIN ? 0 : error);
252 				break;
253 			default:
254 				senderr(EHOSTUNREACH);
255 		}
256 		/* XXX handling for simplex devices in case of M/BCAST ?? */
257 		if (m->m_flags & (M_BCAST | M_MCAST))
258 			etype = htons(ETHERTYPE_MPLS_MCAST);
259 		else
260 			etype = htons(ETHERTYPE_MPLS);
261 		break;
262 #endif /* MPLS */
263 	case pseudo_AF_HDRCMPLT:
264 		eh = (struct ether_header *)dst->sa_data;
265 		esrc = eh->ether_shost;
266 		/* FALLTHROUGH */
267 
268 	case AF_UNSPEC:
269 		eh = (struct ether_header *)dst->sa_data;
270 		memcpy(edst, eh->ether_dhost, sizeof(edst));
271 		/* AF_UNSPEC doesn't swap the byte order of the ether_type. */
272 		etype = eh->ether_type;
273 		break;
274 
275 	default:
276 		printf("%s: can't handle af%d\n", ifp->if_xname,
277 			dst->sa_family);
278 		senderr(EAFNOSUPPORT);
279 	}
280 
281 	/* XXX Should we feed-back an unencrypted IPsec packet ? */
282 	if (mcopy)
283 		if_input_local(ifp, mcopy, dst->sa_family);
284 
285 	M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
286 	if (m == NULL)
287 		return (ENOBUFS);
288 	eh = mtod(m, struct ether_header *);
289 	eh->ether_type = etype;
290 	memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost));
291 	memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
292 
293 	return (if_enqueue(ifp, m));
294 bad:
295 	m_freem(m);
296 	return (error);
297 }
298 
299 /*
300  * Process a received Ethernet packet;
301  * the packet is in the mbuf chain m without
302  * the ether header, which is provided separately.
303  */
304 int
305 ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie)
306 {
307 	struct ether_header *eh;
308 	struct niqueue *inq;
309 	u_int16_t etype;
310 	int llcfound = 0;
311 	struct llc *l;
312 	struct arpcom *ac;
313 #if NPPPOE > 0
314 	struct ether_header *eh_tmp;
315 #endif
316 
317 	ac = (struct arpcom *)ifp;
318 	eh = mtod(m, struct ether_header *);
319 	m_adj(m, ETHER_HDR_LEN);
320 
321 	if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
322 		/*
323 		 * If this is not a simplex interface, drop the packet
324 		 * if it came from us.
325 		 */
326 		if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
327 			if (memcmp(ac->ac_enaddr, eh->ether_shost,
328 			    ETHER_ADDR_LEN) == 0) {
329 				m_freem(m);
330 				return (1);
331 			}
332 		}
333 
334 		if (memcmp(etherbroadcastaddr, eh->ether_dhost,
335 		    sizeof(etherbroadcastaddr)) == 0)
336 			m->m_flags |= M_BCAST;
337 		else
338 			m->m_flags |= M_MCAST;
339 		ifp->if_imcasts++;
340 	}
341 
342 	/*
343 	 * If packet has been filtered by the bpf listener, drop it now
344 	 * also HW vlan tagged packets that were not collected by vlan(4)
345 	 * must be dropped now.
346 	 */
347 	if (m->m_flags & (M_FILDROP | M_VLANTAG)) {
348 		m_freem(m);
349 		return (1);
350 	}
351 
352 	/*
353 	 * If packet is unicast, make sure it is for us.  Drop otherwise.
354 	 * This check is required in promiscous mode, and for some hypervisors
355 	 * where the MAC filter is 'best effort' only.
356 	 */
357 	if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
358 		if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) {
359 			m_freem(m);
360 			return (1);
361 		}
362 	}
363 
364 	etype = ntohs(eh->ether_type);
365 
366 decapsulate:
367 	switch (etype) {
368 	case ETHERTYPE_IP:
369 		inq = &ipintrq;
370 		break;
371 
372 	case ETHERTYPE_ARP:
373 		if (ifp->if_flags & IFF_NOARP)
374 			goto dropanyway;
375 		arpinput(m);
376 		return (1);
377 
378 	case ETHERTYPE_REVARP:
379 		if (ifp->if_flags & IFF_NOARP)
380 			goto dropanyway;
381 		revarpinput(m);
382 		return (1);
383 
384 #ifdef INET6
385 	/*
386 	 * Schedule IPv6 software interrupt for incoming IPv6 packet.
387 	 */
388 	case ETHERTYPE_IPV6:
389 		inq = &ip6intrq;
390 		break;
391 #endif /* INET6 */
392 #if NPPPOE > 0 || defined(PIPEX)
393 	case ETHERTYPE_PPPOEDISC:
394 	case ETHERTYPE_PPPOE:
395 		if (m->m_flags & (M_MCAST | M_BCAST))
396 			goto dropanyway;
397 		M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
398 		if (m == NULL)
399 			return (1);
400 
401 		eh_tmp = mtod(m, struct ether_header *);
402 		/*
403 		 * danger!
404 		 * eh_tmp and eh may overlap because eh
405 		 * is stolen from the mbuf above.
406 		 */
407 		memmove(eh_tmp, eh, sizeof(struct ether_header));
408 #ifdef PIPEX
409 		if (pipex_enable) {
410 			struct pipex_session *session;
411 
412 			KERNEL_LOCK();
413 			if ((session = pipex_pppoe_lookup_session(m)) != NULL) {
414 				pipex_pppoe_input(m, session);
415 				KERNEL_UNLOCK();
416 				return (1);
417 			}
418 			KERNEL_UNLOCK();
419 		}
420 #endif
421 		if (etype == ETHERTYPE_PPPOEDISC)
422 			inq = &pppoediscinq;
423 		else
424 			inq = &pppoeinq;
425 		break;
426 #endif
427 #ifdef MPLS
428 	case ETHERTYPE_MPLS:
429 	case ETHERTYPE_MPLS_MCAST:
430 		mpls_input(m);
431 		return (1);
432 #endif
433 	default:
434 		if (llcfound || etype > ETHERMTU)
435 			goto dropanyway;
436 		llcfound = 1;
437 		l = mtod(m, struct llc *);
438 		switch (l->llc_dsap) {
439 		case LLC_SNAP_LSAP:
440 			if (l->llc_control == LLC_UI &&
441 			    l->llc_dsap == LLC_SNAP_LSAP &&
442 			    l->llc_ssap == LLC_SNAP_LSAP) {
443 				/* SNAP */
444 				if (m->m_pkthdr.len > etype)
445 					m_adj(m, etype - m->m_pkthdr.len);
446 				m_adj(m, 6);
447 				M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
448 				if (m == NULL)
449 					return (1);
450 				*mtod(m, struct ether_header *) = *eh;
451 				goto decapsulate;
452 			}
453 		default:
454 			goto dropanyway;
455 		}
456 	}
457 
458 	niq_enqueue(inq, m);
459 	return (1);
460 dropanyway:
461 	m_freem(m);
462 	return (1);
463 }
464 
465 /*
466  * Convert Ethernet address to printable (loggable) representation.
467  */
468 static char digits[] = "0123456789abcdef";
469 char *
470 ether_sprintf(u_char *ap)
471 {
472 	int i;
473 	static char etherbuf[ETHER_ADDR_LEN * 3];
474 	char *cp = etherbuf;
475 
476 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
477 		*cp++ = digits[*ap >> 4];
478 		*cp++ = digits[*ap++ & 0xf];
479 		*cp++ = ':';
480 	}
481 	*--cp = 0;
482 	return (etherbuf);
483 }
484 
485 /*
486  * Generate a (hopefully) acceptable MAC address, if asked.
487  */
488 void
489 ether_fakeaddr(struct ifnet *ifp)
490 {
491 	static int unit;
492 	int rng = arc4random();
493 
494 	/* Non-multicast; locally administered address */
495 	((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe;
496 	((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1;
497 	((struct arpcom *)ifp)->ac_enaddr[2] = 0xba;
498 	((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf);
499 	((struct arpcom *)ifp)->ac_enaddr[4] = rng;
500 	((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8;
501 }
502 
503 /*
504  * Perform common duties while attaching to interface list
505  */
506 void
507 ether_ifattach(struct ifnet *ifp)
508 {
509 	struct arpcom *ac = (struct arpcom *)ifp;
510 
511 	/*
512 	 * Any interface which provides a MAC address which is obviously
513 	 * invalid gets whacked, so that users will notice.
514 	 */
515 	if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr))
516 		ether_fakeaddr(ifp);
517 
518 	ifp->if_type = IFT_ETHER;
519 	ifp->if_addrlen = ETHER_ADDR_LEN;
520 	ifp->if_hdrlen = ETHER_HDR_LEN;
521 	ifp->if_mtu = ETHERMTU;
522 	ifp->if_output = ether_output;
523 	ifp->if_rtrequest = ether_rtrequest;
524 
525 	if_ih_insert(ifp, ether_input, NULL);
526 
527 	if (ifp->if_hardmtu == 0)
528 		ifp->if_hardmtu = ETHERMTU;
529 
530 	if_alloc_sadl(ifp);
531 	memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen);
532 	LIST_INIT(&ac->ac_multiaddrs);
533 #if NBPFILTER > 0
534 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
535 #endif
536 }
537 
538 void
539 ether_ifdetach(struct ifnet *ifp)
540 {
541 	struct arpcom *ac = (struct arpcom *)ifp;
542 	struct ether_multi *enm;
543 
544 	/* Undo pseudo-driver changes. */
545 	if_deactivate(ifp);
546 
547 	if_ih_remove(ifp, ether_input, NULL);
548 
549 	KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs));
550 
551 	for (enm = LIST_FIRST(&ac->ac_multiaddrs);
552 	    enm != NULL;
553 	    enm = LIST_FIRST(&ac->ac_multiaddrs)) {
554 		LIST_REMOVE(enm, enm_list);
555 		free(enm, M_IFMADDR, sizeof *enm);
556 	}
557 }
558 
559 #if 0
560 /*
561  * This is for reference.  We have table-driven versions of the
562  * crc32 generators, which are faster than the double-loop.
563  */
564 u_int32_t __pure
565 ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
566 {
567 	u_int32_t c, carry;
568 	size_t i, j;
569 
570 	for (i = 0; i < len; i++) {
571 		c = buf[i];
572 		for (j = 0; j < 8; j++) {
573 			carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
574 			crc >>= 1;
575 			c >>= 1;
576 			if (carry)
577 				crc = (crc ^ ETHER_CRC_POLY_LE);
578 		}
579 	}
580 
581 	return (crc);
582 }
583 
584 u_int32_t __pure
585 ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
586 {
587 	u_int32_t c, carry;
588 	size_t i, j;
589 
590 	for (i = 0; i < len; i++) {
591 		c = buf[i];
592 		for (j = 0; j < 8; j++) {
593 			carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
594 			crc <<= 1;
595 			c >>= 1;
596 			if (carry)
597 				crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
598 		}
599 	}
600 
601 	return (crc);
602 }
603 #else
604 u_int32_t __pure
605 ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len)
606 {
607 	static const u_int32_t crctab[] = {
608 		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
609 		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
610 		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
611 		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
612 	};
613 	size_t i;
614 
615 	for (i = 0; i < len; i++) {
616 		crc ^= buf[i];
617 		crc = (crc >> 4) ^ crctab[crc & 0xf];
618 		crc = (crc >> 4) ^ crctab[crc & 0xf];
619 	}
620 
621 	return (crc);
622 }
623 
624 u_int32_t __pure
625 ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len)
626 {
627 	static const u_int8_t rev[] = {
628 		0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
629 		0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
630 	};
631 	static const u_int32_t crctab[] = {
632 		0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
633 		0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
634 		0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
635 		0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd
636 	};
637 	size_t i;
638 	u_int8_t data;
639 
640 	for (i = 0; i < len; i++) {
641 		data = buf[i];
642 		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]];
643 		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]];
644 	}
645 
646 	return (crc);
647 }
648 #endif
649 
650 u_int32_t
651 ether_crc32_le(const u_int8_t *buf, size_t len)
652 {
653 	return ether_crc32_le_update(0xffffffff, buf, len);
654 }
655 
656 u_int32_t
657 ether_crc32_be(const u_int8_t *buf, size_t len)
658 {
659 	return ether_crc32_be_update(0xffffffff, buf, len);
660 }
661 
662 u_char	ether_ipmulticast_min[ETHER_ADDR_LEN] =
663     { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
664 u_char	ether_ipmulticast_max[ETHER_ADDR_LEN] =
665     { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
666 
667 #ifdef INET6
668 u_char	ether_ip6multicast_min[ETHER_ADDR_LEN] =
669     { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
670 u_char	ether_ip6multicast_max[ETHER_ADDR_LEN] =
671     { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
672 #endif
673 
674 /*
675  * Convert a sockaddr into an Ethernet address or range of Ethernet
676  * addresses.
677  */
678 int
679 ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
680     u_int8_t addrhi[ETHER_ADDR_LEN])
681 {
682 	struct sockaddr_in *sin;
683 #ifdef INET6
684 	struct sockaddr_in6 *sin6;
685 #endif /* INET6 */
686 
687 	switch (sa->sa_family) {
688 
689 	case AF_UNSPEC:
690 		memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN);
691 		memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
692 		break;
693 
694 	case AF_INET:
695 		sin = satosin(sa);
696 		if (sin->sin_addr.s_addr == INADDR_ANY) {
697 			/*
698 			 * An IP address of INADDR_ANY means listen to
699 			 * or stop listening to all of the Ethernet
700 			 * multicast addresses used for IP.
701 			 * (This is for the sake of IP multicast routers.)
702 			 */
703 			memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN);
704 			memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN);
705 		} else {
706 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
707 			memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
708 		}
709 		break;
710 #ifdef INET6
711 	case AF_INET6:
712 		sin6 = satosin6(sa);
713 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
714 			/*
715 			 * An IP6 address of 0 means listen to or stop
716 			 * listening to all of the Ethernet multicast
717 			 * address used for IP6.
718 			 *
719 			 * (This might not be healthy, given IPv6's reliance on
720 			 * multicast for things like neighbor discovery.
721 			 * Perhaps initializing all-nodes, solicited nodes, and
722 			 * possibly all-routers for this interface afterwards
723 			 * is not a bad idea.)
724 			 */
725 
726 			memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN);
727 			memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN);
728 		} else {
729 			ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
730 			memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
731 		}
732 		break;
733 #endif
734 
735 	default:
736 		return (EAFNOSUPPORT);
737 	}
738 	return (0);
739 }
740 
741 /*
742  * Add an Ethernet multicast address or range of addresses to the list for a
743  * given interface.
744  */
745 int
746 ether_addmulti(struct ifreq *ifr, struct arpcom *ac)
747 {
748 	struct ether_multi *enm;
749 	u_char addrlo[ETHER_ADDR_LEN];
750 	u_char addrhi[ETHER_ADDR_LEN];
751 	int s = splnet(), error;
752 
753 	error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
754 	if (error != 0) {
755 		splx(s);
756 		return (error);
757 	}
758 
759 	/*
760 	 * Verify that we have valid Ethernet multicast addresses.
761 	 */
762 	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
763 		splx(s);
764 		return (EINVAL);
765 	}
766 	/*
767 	 * See if the address range is already in the list.
768 	 */
769 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
770 	if (enm != NULL) {
771 		/*
772 		 * Found it; just increment the reference count.
773 		 */
774 		++enm->enm_refcount;
775 		splx(s);
776 		return (0);
777 	}
778 	/*
779 	 * New address or range; malloc a new multicast record
780 	 * and link it into the interface's multicast list.
781 	 */
782 	enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
783 	if (enm == NULL) {
784 		splx(s);
785 		return (ENOBUFS);
786 	}
787 	memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN);
788 	memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN);
789 	enm->enm_refcount = 1;
790 	LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);
791 	ac->ac_multicnt++;
792 	if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
793 		ac->ac_multirangecnt++;
794 	splx(s);
795 	/*
796 	 * Return ENETRESET to inform the driver that the list has changed
797 	 * and its reception filter should be adjusted accordingly.
798 	 */
799 	return (ENETRESET);
800 }
801 
802 /*
803  * Delete a multicast address record.
804  */
805 int
806 ether_delmulti(struct ifreq *ifr, struct arpcom *ac)
807 {
808 	struct ether_multi *enm;
809 	u_char addrlo[ETHER_ADDR_LEN];
810 	u_char addrhi[ETHER_ADDR_LEN];
811 	int s = splnet(), error;
812 
813 	error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
814 	if (error != 0) {
815 		splx(s);
816 		return (error);
817 	}
818 
819 	/*
820 	 * Look up the address in our list.
821 	 */
822 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
823 	if (enm == NULL) {
824 		splx(s);
825 		return (ENXIO);
826 	}
827 	if (--enm->enm_refcount != 0) {
828 		/*
829 		 * Still some claims to this record.
830 		 */
831 		splx(s);
832 		return (0);
833 	}
834 	/*
835 	 * No remaining claims to this record; unlink and free it.
836 	 */
837 	LIST_REMOVE(enm, enm_list);
838 	free(enm, M_IFMADDR, sizeof *enm);
839 	ac->ac_multicnt--;
840 	if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
841 		ac->ac_multirangecnt--;
842 	splx(s);
843 	/*
844 	 * Return ENETRESET to inform the driver that the list has changed
845 	 * and its reception filter should be adjusted accordingly.
846 	 */
847 	return (ENETRESET);
848 }
849