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