xref: /openbsd-src/sys/net/if_ethersubr.c (revision aa997e528a848ca5596493c2a801bdd6fb26ae61)
1 /*	$OpenBSD: if_ethersubr.c,v 1.253 2018/03/13 01:31:48 dlg 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 	sa_family_t af = dst->sa_family;
197 	int error = 0;
198 
199 	KASSERT(rt != NULL || ISSET(m->m_flags, M_MCAST|M_BCAST) ||
200 		af == AF_UNSPEC || af == pseudo_AF_HDRCMPLT);
201 
202 #ifdef DIAGNOSTIC
203 	if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
204 		printf("%s: trying to send packet on wrong domain. "
205 		    "if %d vs. mbuf %d\n", ifp->if_xname,
206 		    ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid));
207 	}
208 #endif
209 
210 	esrc = ac->ac_enaddr;
211 
212 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
213 		senderr(ENETDOWN);
214 
215 	switch (af) {
216 	case AF_INET:
217 		error = arpresolve(ifp, rt, m, dst, edst);
218 		if (error)
219 			return (error == EAGAIN ? 0 : error);
220 		/* If broadcasting on a simplex interface, loopback a copy */
221 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
222 		    !m->m_pkthdr.pf.routed)
223 			mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT);
224 		etype = htons(ETHERTYPE_IP);
225 		break;
226 #ifdef INET6
227 	case AF_INET6:
228 		error = nd6_resolve(ifp, rt, m, dst, edst);
229 		if (error)
230 			return (error == EAGAIN ? 0 : error);
231 		etype = htons(ETHERTYPE_IPV6);
232 		break;
233 #endif
234 #ifdef MPLS
235 	case AF_MPLS:
236 		if (rt)
237 			dst = rt_key(rt);
238 		else
239 			senderr(EHOSTUNREACH);
240 
241 		if (!ISSET(ifp->if_xflags, IFXF_MPLS))
242 			senderr(ENETUNREACH);
243 
244 		switch (dst->sa_family) {
245 			case AF_LINK:
246 				if (satosdl(dst)->sdl_alen < sizeof(edst))
247 					senderr(EHOSTUNREACH);
248 				memcpy(edst, LLADDR(satosdl(dst)),
249 				    sizeof(edst));
250 				break;
251 #ifdef INET6
252 			case AF_INET6:
253 				error = nd6_resolve(ifp, rt, m, dst, edst);
254 				if (error)
255 					return (error == EAGAIN ? 0 : error);
256 				break;
257 #endif
258 			case AF_INET:
259 			case AF_MPLS:
260 				error = arpresolve(ifp, rt, m, dst, edst);
261 				if (error)
262 					return (error == EAGAIN ? 0 : error);
263 				break;
264 			default:
265 				senderr(EHOSTUNREACH);
266 		}
267 		/* XXX handling for simplex devices in case of M/BCAST ?? */
268 		if (m->m_flags & (M_BCAST | M_MCAST))
269 			etype = htons(ETHERTYPE_MPLS_MCAST);
270 		else
271 			etype = htons(ETHERTYPE_MPLS);
272 		break;
273 #endif /* MPLS */
274 	case pseudo_AF_HDRCMPLT:
275 		eh = (struct ether_header *)dst->sa_data;
276 		esrc = eh->ether_shost;
277 		/* FALLTHROUGH */
278 
279 	case AF_UNSPEC:
280 		eh = (struct ether_header *)dst->sa_data;
281 		memcpy(edst, eh->ether_dhost, sizeof(edst));
282 		/* AF_UNSPEC doesn't swap the byte order of the ether_type. */
283 		etype = eh->ether_type;
284 		break;
285 
286 	default:
287 		printf("%s: can't handle af%d\n", ifp->if_xname,
288 			dst->sa_family);
289 		senderr(EAFNOSUPPORT);
290 	}
291 
292 	/* XXX Should we feed-back an unencrypted IPsec packet ? */
293 	if (mcopy)
294 		if_input_local(ifp, mcopy, dst->sa_family);
295 
296 	M_PREPEND(m, sizeof(struct ether_header) + ETHER_ALIGN, M_DONTWAIT);
297 	if (m == NULL)
298 		return (ENOBUFS);
299 	m_adj(m, ETHER_ALIGN);
300 	eh = mtod(m, struct ether_header *);
301 	eh->ether_type = etype;
302 	memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost));
303 	memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
304 
305 	return (if_enqueue(ifp, m));
306 bad:
307 	m_freem(m);
308 	return (error);
309 }
310 
311 /*
312  * Process a received Ethernet packet;
313  * the packet is in the mbuf chain m without
314  * the ether header, which is provided separately.
315  */
316 int
317 ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie)
318 {
319 	struct ether_header *eh;
320 	void (*input)(struct ifnet *, struct mbuf *);
321 	u_int16_t etype;
322 	struct arpcom *ac;
323 
324 	/* Drop short frames */
325 	if (m->m_len < ETHER_HDR_LEN)
326 		goto dropanyway;
327 
328 	ac = (struct arpcom *)ifp;
329 	eh = mtod(m, struct ether_header *);
330 
331 	/* Is the packet for us? */
332 	if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) != 0) {
333 
334 		/* If not, it must be multicast or broadcast to go further */
335 		if (!ETHER_IS_MULTICAST(eh->ether_dhost))
336 			goto dropanyway;
337 
338 		/*
339 		 * If this is not a simplex interface, drop the packet
340 		 * if it came from us.
341 		 */
342 		if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
343 			if (memcmp(ac->ac_enaddr, eh->ether_shost,
344 			    ETHER_ADDR_LEN) == 0)
345 				goto dropanyway;
346 		}
347 
348 		if (memcmp(etherbroadcastaddr, eh->ether_dhost,
349 		    ETHER_ADDR_LEN) == 0)
350 			m->m_flags |= M_BCAST;
351 		else
352 			m->m_flags |= M_MCAST;
353 		ifp->if_imcasts++;
354 	}
355 
356 	/*
357 	 * HW vlan tagged packets that were not collected by vlan(4) must
358 	 * be dropped now.
359 	 */
360 	if (m->m_flags & M_VLANTAG)
361 		goto dropanyway;
362 
363 	etype = ntohs(eh->ether_type);
364 
365 	switch (etype) {
366 	case ETHERTYPE_IP:
367 		input = ipv4_input;
368 		break;
369 
370 	case ETHERTYPE_ARP:
371 		if (ifp->if_flags & IFF_NOARP)
372 			goto dropanyway;
373 		input = arpinput;
374 		break;
375 
376 	case ETHERTYPE_REVARP:
377 		if (ifp->if_flags & IFF_NOARP)
378 			goto dropanyway;
379 		input = revarpinput;
380 		break;
381 
382 #ifdef INET6
383 	/*
384 	 * Schedule IPv6 software interrupt for incoming IPv6 packet.
385 	 */
386 	case ETHERTYPE_IPV6:
387 		input = ipv6_input;
388 		break;
389 #endif /* INET6 */
390 #if NPPPOE > 0 || defined(PIPEX)
391 	case ETHERTYPE_PPPOEDISC:
392 	case ETHERTYPE_PPPOE:
393 		if (m->m_flags & (M_MCAST | M_BCAST))
394 			goto dropanyway;
395 #ifdef PIPEX
396 		if (pipex_enable) {
397 			struct pipex_session *session;
398 
399 			if ((session = pipex_pppoe_lookup_session(m)) != NULL) {
400 				pipex_pppoe_input(m, session);
401 				return (1);
402 			}
403 		}
404 #endif
405 		if (etype == ETHERTYPE_PPPOEDISC)
406 			niq_enqueue(&pppoediscinq, m);
407 		else
408 			niq_enqueue(&pppoeinq, m);
409 		return (1);
410 #endif
411 #ifdef MPLS
412 	case ETHERTYPE_MPLS:
413 	case ETHERTYPE_MPLS_MCAST:
414 		input = mpls_input;
415 		break;
416 #endif
417 	default:
418 		goto dropanyway;
419 	}
420 
421 	m_adj(m, sizeof(*eh));
422 	(*input)(ifp, m);
423 	return (1);
424 dropanyway:
425 	m_freem(m);
426 	return (1);
427 }
428 
429 /*
430  * Convert Ethernet address to printable (loggable) representation.
431  */
432 static char digits[] = "0123456789abcdef";
433 char *
434 ether_sprintf(u_char *ap)
435 {
436 	int i;
437 	static char etherbuf[ETHER_ADDR_LEN * 3];
438 	char *cp = etherbuf;
439 
440 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
441 		*cp++ = digits[*ap >> 4];
442 		*cp++ = digits[*ap++ & 0xf];
443 		*cp++ = ':';
444 	}
445 	*--cp = 0;
446 	return (etherbuf);
447 }
448 
449 /*
450  * Generate a (hopefully) acceptable MAC address, if asked.
451  */
452 void
453 ether_fakeaddr(struct ifnet *ifp)
454 {
455 	static int unit;
456 	int rng = arc4random();
457 
458 	/* Non-multicast; locally administered address */
459 	((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe;
460 	((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1;
461 	((struct arpcom *)ifp)->ac_enaddr[2] = 0xba;
462 	((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf);
463 	((struct arpcom *)ifp)->ac_enaddr[4] = rng;
464 	((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8;
465 }
466 
467 /*
468  * Perform common duties while attaching to interface list
469  */
470 void
471 ether_ifattach(struct ifnet *ifp)
472 {
473 	struct arpcom *ac = (struct arpcom *)ifp;
474 
475 	/*
476 	 * Any interface which provides a MAC address which is obviously
477 	 * invalid gets whacked, so that users will notice.
478 	 */
479 	if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr))
480 		ether_fakeaddr(ifp);
481 
482 	ifp->if_type = IFT_ETHER;
483 	ifp->if_addrlen = ETHER_ADDR_LEN;
484 	ifp->if_hdrlen = ETHER_HDR_LEN;
485 	ifp->if_mtu = ETHERMTU;
486 	ifp->if_output = ether_output;
487 	ifp->if_rtrequest = ether_rtrequest;
488 
489 	if_ih_insert(ifp, ether_input, NULL);
490 
491 	if (ifp->if_hardmtu == 0)
492 		ifp->if_hardmtu = ETHERMTU;
493 
494 	if_alloc_sadl(ifp);
495 	memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen);
496 	LIST_INIT(&ac->ac_multiaddrs);
497 #if NBPFILTER > 0
498 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
499 #endif
500 }
501 
502 void
503 ether_ifdetach(struct ifnet *ifp)
504 {
505 	struct arpcom *ac = (struct arpcom *)ifp;
506 	struct ether_multi *enm;
507 
508 	/* Undo pseudo-driver changes. */
509 	if_deactivate(ifp);
510 
511 	if_ih_remove(ifp, ether_input, NULL);
512 
513 	KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs));
514 
515 	for (enm = LIST_FIRST(&ac->ac_multiaddrs);
516 	    enm != NULL;
517 	    enm = LIST_FIRST(&ac->ac_multiaddrs)) {
518 		LIST_REMOVE(enm, enm_list);
519 		free(enm, M_IFMADDR, sizeof *enm);
520 	}
521 }
522 
523 #if 0
524 /*
525  * This is for reference.  We have table-driven versions of the
526  * crc32 generators, which are faster than the double-loop.
527  */
528 u_int32_t __pure
529 ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
530 {
531 	u_int32_t c, carry;
532 	size_t i, j;
533 
534 	for (i = 0; i < len; i++) {
535 		c = buf[i];
536 		for (j = 0; j < 8; j++) {
537 			carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
538 			crc >>= 1;
539 			c >>= 1;
540 			if (carry)
541 				crc = (crc ^ ETHER_CRC_POLY_LE);
542 		}
543 	}
544 
545 	return (crc);
546 }
547 
548 u_int32_t __pure
549 ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
550 {
551 	u_int32_t c, carry;
552 	size_t i, j;
553 
554 	for (i = 0; i < len; i++) {
555 		c = buf[i];
556 		for (j = 0; j < 8; j++) {
557 			carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
558 			crc <<= 1;
559 			c >>= 1;
560 			if (carry)
561 				crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
562 		}
563 	}
564 
565 	return (crc);
566 }
567 #else
568 u_int32_t __pure
569 ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len)
570 {
571 	static const u_int32_t crctab[] = {
572 		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
573 		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
574 		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
575 		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
576 	};
577 	size_t i;
578 
579 	for (i = 0; i < len; i++) {
580 		crc ^= buf[i];
581 		crc = (crc >> 4) ^ crctab[crc & 0xf];
582 		crc = (crc >> 4) ^ crctab[crc & 0xf];
583 	}
584 
585 	return (crc);
586 }
587 
588 u_int32_t __pure
589 ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len)
590 {
591 	static const u_int8_t rev[] = {
592 		0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
593 		0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
594 	};
595 	static const u_int32_t crctab[] = {
596 		0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
597 		0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
598 		0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
599 		0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd
600 	};
601 	size_t i;
602 	u_int8_t data;
603 
604 	for (i = 0; i < len; i++) {
605 		data = buf[i];
606 		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]];
607 		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]];
608 	}
609 
610 	return (crc);
611 }
612 #endif
613 
614 u_int32_t
615 ether_crc32_le(const u_int8_t *buf, size_t len)
616 {
617 	return ether_crc32_le_update(0xffffffff, buf, len);
618 }
619 
620 u_int32_t
621 ether_crc32_be(const u_int8_t *buf, size_t len)
622 {
623 	return ether_crc32_be_update(0xffffffff, buf, len);
624 }
625 
626 u_char	ether_ipmulticast_min[ETHER_ADDR_LEN] =
627     { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
628 u_char	ether_ipmulticast_max[ETHER_ADDR_LEN] =
629     { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
630 
631 #ifdef INET6
632 u_char	ether_ip6multicast_min[ETHER_ADDR_LEN] =
633     { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
634 u_char	ether_ip6multicast_max[ETHER_ADDR_LEN] =
635     { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
636 #endif
637 
638 /*
639  * Convert a sockaddr into an Ethernet address or range of Ethernet
640  * addresses.
641  */
642 int
643 ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
644     u_int8_t addrhi[ETHER_ADDR_LEN])
645 {
646 	struct sockaddr_in *sin;
647 #ifdef INET6
648 	struct sockaddr_in6 *sin6;
649 #endif /* INET6 */
650 
651 	switch (sa->sa_family) {
652 
653 	case AF_UNSPEC:
654 		memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN);
655 		memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
656 		break;
657 
658 	case AF_INET:
659 		sin = satosin(sa);
660 		if (sin->sin_addr.s_addr == INADDR_ANY) {
661 			/*
662 			 * An IP address of INADDR_ANY means listen to
663 			 * or stop listening to all of the Ethernet
664 			 * multicast addresses used for IP.
665 			 * (This is for the sake of IP multicast routers.)
666 			 */
667 			memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN);
668 			memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN);
669 		} else {
670 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
671 			memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
672 		}
673 		break;
674 #ifdef INET6
675 	case AF_INET6:
676 		sin6 = satosin6(sa);
677 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
678 			/*
679 			 * An IP6 address of 0 means listen to or stop
680 			 * listening to all of the Ethernet multicast
681 			 * address used for IP6.
682 			 *
683 			 * (This might not be healthy, given IPv6's reliance on
684 			 * multicast for things like neighbor discovery.
685 			 * Perhaps initializing all-nodes, solicited nodes, and
686 			 * possibly all-routers for this interface afterwards
687 			 * is not a bad idea.)
688 			 */
689 
690 			memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN);
691 			memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN);
692 		} else {
693 			ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
694 			memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
695 		}
696 		break;
697 #endif
698 
699 	default:
700 		return (EAFNOSUPPORT);
701 	}
702 	return (0);
703 }
704 
705 /*
706  * Add an Ethernet multicast address or range of addresses to the list for a
707  * given interface.
708  */
709 int
710 ether_addmulti(struct ifreq *ifr, struct arpcom *ac)
711 {
712 	struct ether_multi *enm;
713 	u_char addrlo[ETHER_ADDR_LEN];
714 	u_char addrhi[ETHER_ADDR_LEN];
715 	int s = splnet(), error;
716 
717 	error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
718 	if (error != 0) {
719 		splx(s);
720 		return (error);
721 	}
722 
723 	/*
724 	 * Verify that we have valid Ethernet multicast addresses.
725 	 */
726 	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
727 		splx(s);
728 		return (EINVAL);
729 	}
730 	/*
731 	 * See if the address range is already in the list.
732 	 */
733 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
734 	if (enm != NULL) {
735 		/*
736 		 * Found it; just increment the reference count.
737 		 */
738 		++enm->enm_refcount;
739 		splx(s);
740 		return (0);
741 	}
742 	/*
743 	 * New address or range; malloc a new multicast record
744 	 * and link it into the interface's multicast list.
745 	 */
746 	enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
747 	if (enm == NULL) {
748 		splx(s);
749 		return (ENOBUFS);
750 	}
751 	memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN);
752 	memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN);
753 	enm->enm_refcount = 1;
754 	LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);
755 	ac->ac_multicnt++;
756 	if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
757 		ac->ac_multirangecnt++;
758 	splx(s);
759 	/*
760 	 * Return ENETRESET to inform the driver that the list has changed
761 	 * and its reception filter should be adjusted accordingly.
762 	 */
763 	return (ENETRESET);
764 }
765 
766 /*
767  * Delete a multicast address record.
768  */
769 int
770 ether_delmulti(struct ifreq *ifr, struct arpcom *ac)
771 {
772 	struct ether_multi *enm;
773 	u_char addrlo[ETHER_ADDR_LEN];
774 	u_char addrhi[ETHER_ADDR_LEN];
775 	int s = splnet(), error;
776 
777 	error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
778 	if (error != 0) {
779 		splx(s);
780 		return (error);
781 	}
782 
783 	/*
784 	 * Look up the address in our list.
785 	 */
786 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
787 	if (enm == NULL) {
788 		splx(s);
789 		return (ENXIO);
790 	}
791 	if (--enm->enm_refcount != 0) {
792 		/*
793 		 * Still some claims to this record.
794 		 */
795 		splx(s);
796 		return (0);
797 	}
798 	/*
799 	 * No remaining claims to this record; unlink and free it.
800 	 */
801 	LIST_REMOVE(enm, enm_list);
802 	free(enm, M_IFMADDR, sizeof *enm);
803 	ac->ac_multicnt--;
804 	if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
805 		ac->ac_multirangecnt--;
806 	splx(s);
807 	/*
808 	 * Return ENETRESET to inform the driver that the list has changed
809 	 * and its reception filter should be adjusted accordingly.
810 	 */
811 	return (ENETRESET);
812 }
813