xref: /xnu-8020.101.4/bsd/net/ether_if_module.c (revision e7776783b89a353188416a9a346c6cdb4928faad)
1 /*
2  * Copyright (c) 2000-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * Copyright (c) 1982, 1989, 1993
30  *	The Regents of the University of California.  All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice, this list of conditions and the following disclaimer.
37  * 2. Redistributions in binary form must reproduce the above copyright
38  *    notice, this list of conditions and the following disclaimer in the
39  *    documentation and/or other materials provided with the distribution.
40  * 3. All advertising materials mentioning features or use of this software
41  *    must display the following acknowledgement:
42  *	This product includes software developed by the University of
43  *	California, Berkeley and its contributors.
44  * 4. Neither the name of the University nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58  * SUCH DAMAGE.
59  *
60  */
61 
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/kernel.h>
65 #include <sys/malloc.h>
66 #include <sys/mbuf.h>
67 #include <sys/socket.h>
68 #include <sys/sockio.h>
69 #include <sys/sysctl.h>
70 
71 #include <pexpert/pexpert.h>
72 
73 #define etherbroadcastaddr      fugly
74 #include <net/if.h>
75 #include <net/route.h>
76 #include <net/if_llc.h>
77 #include <net/if_dl.h>
78 #include <net/if_types.h>
79 #include <net/if_ether.h>
80 #include <net/if_gif.h>
81 #include <netinet/if_ether.h>
82 #include <netinet/in.h> /* For M_LOOP */
83 #include <net/kpi_interface.h>
84 #include <net/kpi_protocol.h>
85 #undef etherbroadcastaddr
86 
87 /*
88  #if INET
89  #include <netinet/in.h>
90  #include <netinet/in_var.h>
91  *
92  #include <netinet/in_systm.h>
93  #include <netinet/ip.h>
94  #endif
95  */
96 #include <net/ether_if_module.h>
97 #include <sys/socketvar.h>
98 #include <net/if_vlan_var.h>
99 #include <net/if_6lowpan_var.h>
100 #if BOND
101 #include <net/if_bond_internal.h>
102 #endif /* BOND */
103 #if IF_BRIDGE
104 #include <net/if_bridgevar.h>
105 #endif /* IF_BRIDGE */
106 #if IF_FAKE
107 #include <net/if_fake_var.h>
108 #endif /* IF_FAKE */
109 #if IF_HEADLESS
110 extern void if_headless_init(void);
111 #endif /* IF_HEADLESS */
112 
113 #include <net/dlil.h>
114 
115 SYSCTL_DECL(_net_link);
116 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
117     "Ethernet");
118 
119 struct en_desc {
120 	u_int16_t type;                 /* Type of protocol stored in data */
121 	u_int32_t protocol_family;      /* Protocol family */
122 	u_int32_t data[2];              /* Protocol data */
123 };
124 
125 /* descriptors are allocated in blocks of ETHER_DESC_BLK_SIZE */
126 #if !XNU_TARGET_OS_OSX
127 #define ETHER_DESC_BLK_SIZE (2) /* IP, ARP */
128 #else /* XNU_TARGET_OS_OSX */
129 #define ETHER_DESC_BLK_SIZE (10)
130 #endif /* XNU_TARGET_OS_OSX */
131 
132 /*
133  * Header for the demux list, hangs off of IFP at if_family_cookie
134  */
135 struct ether_desc_blk_str {
136 	u_int32_t  n_max_used;
137 	u_int32_t       n_count;
138 	u_int32_t       n_used;
139 	struct en_desc  block_ptr[1];
140 };
141 
142 /* Size of the above struct before the array of struct en_desc */
143 #define ETHER_DESC_HEADER_SIZE  \
144 	((size_t) offsetof(struct ether_desc_blk_str, block_ptr))
145 
146 __private_extern__ u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
147 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
148 
149 /*
150  * Release all descriptor entries owned by this protocol (there may be several).
151  * Setting the type to 0 releases the entry. Eventually we should compact-out
152  * the unused entries.
153  */
154 int
ether_del_proto(ifnet_t ifp,protocol_family_t protocol_family)155 ether_del_proto(ifnet_t ifp, protocol_family_t protocol_family)
156 {
157 	struct ether_desc_blk_str *desc_blk =
158 	    (struct ether_desc_blk_str *)ifp->if_family_cookie;
159 	u_int32_t current = 0;
160 	int found = 0;
161 
162 	if (desc_blk == NULL) {
163 		return 0;
164 	}
165 
166 	for (current = desc_blk->n_max_used; current > 0; current--) {
167 		if (desc_blk->block_ptr[current - 1].protocol_family ==
168 		    protocol_family) {
169 			found = 1;
170 			desc_blk->block_ptr[current - 1].type = 0;
171 			desc_blk->n_used--;
172 		}
173 	}
174 
175 	if (desc_blk->n_used == 0) {
176 		u_int32_t size = desc_blk->n_count * sizeof(struct en_desc) +
177 		    ETHER_DESC_HEADER_SIZE;
178 		kfree_data(ifp->if_family_cookie, size);
179 		ifp->if_family_cookie = 0;
180 	} else {
181 		/* Decrement n_max_used */
182 		for (; desc_blk->n_max_used > 0 &&
183 		    desc_blk->block_ptr[desc_blk->n_max_used - 1].type == 0;
184 		    desc_blk->n_max_used--) {
185 			;
186 		}
187 	}
188 
189 	return 0;
190 }
191 
192 static int
ether_add_proto_internal(struct ifnet * ifp,protocol_family_t protocol,const struct ifnet_demux_desc * demux)193 ether_add_proto_internal(struct ifnet *ifp, protocol_family_t protocol,
194     const struct ifnet_demux_desc *demux)
195 {
196 	struct en_desc *ed;
197 	struct ether_desc_blk_str *desc_blk =
198 	    (struct ether_desc_blk_str *)ifp->if_family_cookie;
199 	u_int32_t i;
200 
201 	switch (demux->type) {
202 	/* These types are supported */
203 	/* Top three are preferred */
204 	case DLIL_DESC_ETYPE2:
205 		if (demux->datalen != 2) {
206 			return EINVAL;
207 		}
208 		break;
209 
210 	case DLIL_DESC_SAP:
211 		if (demux->datalen != 3) {
212 			return EINVAL;
213 		}
214 		break;
215 
216 	case DLIL_DESC_SNAP:
217 		if (demux->datalen != 5) {
218 			return EINVAL;
219 		}
220 		break;
221 
222 	default:
223 		return ENOTSUP;
224 	}
225 
226 	/* Verify a matching descriptor does not exist */
227 	if (desc_blk != NULL) {
228 		switch (demux->type) {
229 		case DLIL_DESC_ETYPE2:
230 			for (i = 0; i < desc_blk->n_max_used; i++) {
231 				if (desc_blk->block_ptr[i].type ==
232 				    DLIL_DESC_ETYPE2 &&
233 				    desc_blk->block_ptr[i].data[0] ==
234 				    *(u_int16_t*)demux->data) {
235 					return EADDRINUSE;
236 				}
237 			}
238 			break;
239 		case DLIL_DESC_SAP:
240 		case DLIL_DESC_SNAP:
241 			for (i = 0; i < desc_blk->n_max_used; i++) {
242 				if (desc_blk->block_ptr[i].type ==
243 				    demux->type &&
244 				    bcmp(desc_blk->block_ptr[i].data,
245 				    demux->data, demux->datalen) == 0) {
246 					return EADDRINUSE;
247 				}
248 			}
249 			break;
250 		}
251 	}
252 
253 	/* Check for case where all of the descriptor blocks are in use */
254 	if (desc_blk == NULL || desc_blk->n_used == desc_blk->n_count) {
255 		struct ether_desc_blk_str *tmp;
256 		u_int32_t new_count = ETHER_DESC_BLK_SIZE;
257 		u_int32_t new_size;
258 		u_int32_t old_size = 0;
259 
260 		i = 0;
261 
262 		if (desc_blk) {
263 			new_count += desc_blk->n_count;
264 			old_size = desc_blk->n_count * sizeof(struct en_desc) +
265 			    ETHER_DESC_HEADER_SIZE;
266 			i = desc_blk->n_used;
267 		}
268 
269 		new_size = new_count * sizeof(struct en_desc) +
270 		    ETHER_DESC_HEADER_SIZE;
271 
272 		tmp = (struct ether_desc_blk_str *)kalloc_data(new_size, Z_WAITOK);
273 		if (tmp == NULL) {
274 			/*
275 			 * Remove any previous descriptors set in the call.
276 			 */
277 			return ENOMEM;
278 		}
279 
280 		bzero(((char *)tmp) + old_size, new_size - old_size);
281 		if (desc_blk) {
282 			bcopy(desc_blk, tmp, old_size);
283 			kfree_data(desc_blk, old_size);
284 		}
285 		desc_blk = tmp;
286 		ifp->if_family_cookie = (uintptr_t)desc_blk;
287 		desc_blk->n_count = new_count;
288 	} else {
289 		/* Find a free entry */
290 		for (i = 0; i < desc_blk->n_count; i++) {
291 			if (desc_blk->block_ptr[i].type == 0) {
292 				break;
293 			}
294 		}
295 	}
296 
297 	/* Bump n_max_used if appropriate */
298 	if (i + 1 > desc_blk->n_max_used) {
299 		desc_blk->n_max_used = i + 1;
300 	}
301 
302 	ed = &desc_blk->block_ptr[i];
303 	ed->protocol_family = protocol;
304 	ed->data[0] = 0;
305 	ed->data[1] = 0;
306 
307 	switch (demux->type) {
308 	case DLIL_DESC_ETYPE2:
309 		/* 2 byte ethernet raw protocol type is at native_type */
310 		/* prtocol must be in network byte order */
311 		ed->type = DLIL_DESC_ETYPE2;
312 		ed->data[0] = *(u_int16_t*)demux->data;
313 		break;
314 
315 	case DLIL_DESC_SAP:
316 		ed->type = DLIL_DESC_SAP;
317 		bcopy(demux->data, &ed->data[0], 3);
318 		break;
319 
320 	case DLIL_DESC_SNAP: {
321 		u_int8_t*       pDest = ((u_int8_t*)&ed->data[0]) + 3;
322 		ed->type = DLIL_DESC_SNAP;
323 		bcopy(demux->data, pDest, 5);
324 		break;
325 	}
326 	}
327 
328 	desc_blk->n_used++;
329 
330 	return 0;
331 }
332 
333 int
ether_add_proto(ifnet_t ifp,protocol_family_t protocol,const struct ifnet_demux_desc * demux_list,u_int32_t demux_count)334 ether_add_proto(ifnet_t  ifp, protocol_family_t protocol,
335     const struct ifnet_demux_desc *demux_list, u_int32_t demux_count)
336 {
337 	int error = 0;
338 	u_int32_t i;
339 
340 	for (i = 0; i < demux_count; i++) {
341 		error = ether_add_proto_internal(ifp, protocol, &demux_list[i]);
342 		if (error) {
343 			ether_del_proto(ifp, protocol);
344 			break;
345 		}
346 	}
347 
348 	return error;
349 }
350 
351 int
ether_demux(ifnet_t ifp,mbuf_t m,char * frame_header,protocol_family_t * protocol_family)352 ether_demux(ifnet_t ifp, mbuf_t m, char *frame_header,
353     protocol_family_t *protocol_family)
354 {
355 	struct ether_header *eh = (struct ether_header *)(void *)frame_header;
356 	u_short  ether_type = eh->ether_type;
357 	u_int16_t type;
358 	u_int8_t *data;
359 	u_int32_t i = 0;
360 	struct ether_desc_blk_str *desc_blk =
361 	    (struct ether_desc_blk_str *)ifp->if_family_cookie;
362 	u_int32_t maxd = desc_blk ? desc_blk->n_max_used : 0;
363 	struct en_desc  *ed = desc_blk ? desc_blk->block_ptr : NULL;
364 	u_int32_t extProto1 = 0;
365 	u_int32_t extProto2 = 0;
366 
367 	if (eh->ether_dhost[0] & 1) {
368 		/* Check for broadcast */
369 		if (_ether_cmp(etherbroadcastaddr, eh->ether_dhost) == 0) {
370 			m->m_flags |= M_BCAST;
371 		} else {
372 			m->m_flags |= M_MCAST;
373 		}
374 	}
375 
376 	if (m->m_flags & M_HASFCS) {
377 		/*
378 		 * If the M_HASFCS is set by the driver we want to make sure
379 		 * that we strip off the trailing FCS data before handing it
380 		 * up the stack.
381 		 */
382 		m_adj(m, -ETHER_CRC_LEN);
383 		m->m_flags &= ~M_HASFCS;
384 	}
385 
386 	if ((eh->ether_dhost[0] & 1) == 0) {
387 		/*
388 		 * When the driver is put into promiscuous mode we may receive
389 		 * unicast frames that are not intended for our interfaces.
390 		 * They are marked here as being promiscuous so the caller may
391 		 * dispose of them after passing the packets to any interface
392 		 * filters.
393 		 */
394 		if (_ether_cmp(eh->ether_dhost, IF_LLADDR(ifp))) {
395 			m->m_flags |= M_PROMISC;
396 		}
397 	}
398 
399 	/* check for IEEE 802.15.4 */
400 	if (ether_type == htons(ETHERTYPE_IEEE802154)) {
401 		*protocol_family = PF_802154;
402 		return 0;
403 	}
404 
405 	/* check for VLAN */
406 	if ((m->m_pkthdr.csum_flags & CSUM_VLAN_TAG_VALID) != 0) {
407 		if (EVL_VLANOFTAG(m->m_pkthdr.vlan_tag) != 0) {
408 			*protocol_family = PF_VLAN;
409 			return 0;
410 		}
411 		/* the packet is just priority-tagged, clear the bit */
412 		m->m_pkthdr.csum_flags &= ~CSUM_VLAN_TAG_VALID;
413 	} else if (ether_type == htons(ETHERTYPE_VLAN)) {
414 		struct ether_vlan_header *      evl;
415 
416 		evl = (struct ether_vlan_header *)(void *)frame_header;
417 		if (m->m_len < ETHER_VLAN_ENCAP_LEN ||
418 		    ntohs(evl->evl_proto) == ETHERTYPE_VLAN ||
419 		    EVL_VLANOFTAG(ntohs(evl->evl_tag)) != 0) {
420 			*protocol_family = PF_VLAN;
421 			return 0;
422 		}
423 		/* the packet is just priority-tagged */
424 
425 		/* make the encapsulated ethertype the actual ethertype */
426 		ether_type = evl->evl_encap_proto = evl->evl_proto;
427 
428 		/* remove the encapsulation header */
429 		m->m_len -= ETHER_VLAN_ENCAP_LEN;
430 		m->m_data += ETHER_VLAN_ENCAP_LEN;
431 		m->m_pkthdr.len -= ETHER_VLAN_ENCAP_LEN;
432 		m->m_pkthdr.csum_flags = 0; /* can't trust hardware checksum */
433 	} else if (ether_type == htons(ETHERTYPE_ARP)) {
434 		m->m_pkthdr.pkt_flags |= PKTF_INET_RESOLVE; /* ARP packet */
435 	}
436 	data = mtod(m, u_int8_t*);
437 
438 	/*
439 	 * Determine the packet's protocol type and stuff the protocol into
440 	 * longs for quick compares.
441 	 */
442 	if (ntohs(ether_type) <= 1500) {
443 		bcopy(data, &extProto1, sizeof(u_int32_t));
444 
445 		/* SAP or SNAP */
446 		if ((extProto1 & htonl(0xFFFFFF00)) == htonl(0xAAAA0300)) {
447 			/* SNAP */
448 			type = DLIL_DESC_SNAP;
449 			bcopy(data + sizeof(u_int32_t), &extProto2,
450 			    sizeof(u_int32_t));
451 			extProto1 &= htonl(0x000000FF);
452 		} else {
453 			type = DLIL_DESC_SAP;
454 			extProto1 &= htonl(0xFFFFFF00);
455 		}
456 	} else {
457 		type = DLIL_DESC_ETYPE2;
458 	}
459 
460 	/*
461 	 * Search through the connected protocols for a match.
462 	 */
463 	switch (type) {
464 	case DLIL_DESC_ETYPE2:
465 		for (i = 0; i < maxd; i++) {
466 			if ((ed[i].type == type) &&
467 			    (ed[i].data[0] == ether_type)) {
468 				*protocol_family = ed[i].protocol_family;
469 				return 0;
470 			}
471 		}
472 		break;
473 
474 	case DLIL_DESC_SAP:
475 		for (i = 0; i < maxd; i++) {
476 			if ((ed[i].type == type) &&
477 			    (ed[i].data[0] == extProto1)) {
478 				*protocol_family = ed[i].protocol_family;
479 				return 0;
480 			}
481 		}
482 		break;
483 
484 	case DLIL_DESC_SNAP:
485 		for (i = 0; i < maxd; i++) {
486 			if ((ed[i].type == type) &&
487 			    (ed[i].data[0] == extProto1) &&
488 			    (ed[i].data[1] == extProto2)) {
489 				*protocol_family = ed[i].protocol_family;
490 				return 0;
491 			}
492 		}
493 		break;
494 	}
495 
496 	return ENOENT;
497 }
498 
499 /*
500  * On embedded, ether_frameout is practicaly ether_frameout_extended.
501  * On non-embedded, ether_frameout has long been exposed as a public KPI,
502  * and therefore its signature must remain the same (without the pre- and
503  * postpend length parameters.)
504  */
505 #if KPI_INTERFACE_EMBEDDED
506 int
ether_frameout(struct ifnet * ifp,struct mbuf ** m,const struct sockaddr * ndest,const char * edst,const char * ether_type,u_int32_t * prepend_len,u_int32_t * postpend_len)507 ether_frameout(struct ifnet *ifp, struct mbuf **m,
508     const struct sockaddr *ndest, const char *edst,
509     const char *ether_type, u_int32_t *prepend_len, u_int32_t *postpend_len)
510 #else /* !KPI_INTERFACE_EMBEDDED */
511 int
512 ether_frameout(struct ifnet *ifp, struct mbuf **m,
513     const struct sockaddr *ndest, const char *edst,
514     const char *ether_type)
515 #endif /* KPI_INTERFACE_EMBEDDED */
516 {
517 #if KPI_INTERFACE_EMBEDDED
518 	return ether_frameout_extended(ifp, m, ndest, edst, ether_type,
519 	           prepend_len, postpend_len);
520 #else /* !KPI_INTERFACE_EMBEDDED */
521 	return ether_frameout_extended(ifp, m, ndest, edst, ether_type,
522 	           NULL, NULL);
523 #endif /* !KPI_INTERFACE_EMBEDDED */
524 }
525 
526 /*
527  * Ethernet output routine.
528  * Encapsulate a packet of type family for the local net.
529  * Use trailer local net encapsulation if enough data in first
530  * packet leaves a multiple of 512 bytes of data in remainder.
531  */
532 int
ether_frameout_extended(struct ifnet * ifp,struct mbuf ** m,const struct sockaddr * ndest,const char * edst,const char * ether_type,u_int32_t * prepend_len,u_int32_t * postpend_len)533 ether_frameout_extended(struct ifnet *ifp, struct mbuf **m,
534     const struct sockaddr *ndest, const char *edst,
535     const char *ether_type, u_int32_t *prepend_len, u_int32_t *postpend_len)
536 {
537 	struct ether_header *eh;
538 	int hlen;       /* link layer header length */
539 
540 	hlen = ETHER_HDR_LEN;
541 
542 	/*
543 	 * If a simplex interface, and the packet is being sent to our
544 	 * Ethernet address or a broadcast address, loopback a copy.
545 	 * XXX To make a simplex device behave exactly like a duplex
546 	 * device, we should copy in the case of sending to our own
547 	 * ethernet address (thus letting the original actually appear
548 	 * on the wire). However, we don't do that here for security
549 	 * reasons and compatibility with the original behavior.
550 	 */
551 	if ((ifp->if_flags & IFF_SIMPLEX) &&
552 	    ((*m)->m_flags & M_LOOP) && lo_ifp != NULL) {
553 		if ((*m)->m_flags & M_BCAST) {
554 			struct mbuf *n = m_copy(*m, 0, (int)M_COPYALL);
555 			if (n != NULL) {
556 				dlil_output(lo_ifp, ndest->sa_family,
557 				    n, NULL, ndest, 0, NULL);
558 			}
559 		} else if (_ether_cmp(edst, IF_LLADDR(ifp)) == 0) {
560 			dlil_output(lo_ifp, ndest->sa_family, *m,
561 			    NULL, ndest, 0, NULL);
562 			return EJUSTRETURN;
563 		}
564 	}
565 
566 	/*
567 	 * Add local net header.  If no space in first mbuf,
568 	 * allocate another.
569 	 */
570 	M_PREPEND(*m, sizeof(struct ether_header), M_DONTWAIT, 0);
571 	if (*m == NULL) {
572 		return EJUSTRETURN;
573 	}
574 
575 	if (prepend_len != NULL) {
576 		*prepend_len = sizeof(struct ether_header);
577 	}
578 	if (postpend_len != NULL) {
579 		*postpend_len = 0;
580 	}
581 
582 	eh = mtod(*m, struct ether_header *);
583 	(void) memcpy(&eh->ether_type, ether_type, sizeof(eh->ether_type));
584 	(void) memcpy(eh->ether_dhost, edst, ETHER_ADDR_LEN);
585 	ifnet_lladdr_copy_bytes(ifp, eh->ether_shost, ETHER_ADDR_LEN);
586 
587 	return 0;
588 }
589 
590 errno_t
ether_check_multi(ifnet_t ifp,const struct sockaddr * proto_addr)591 ether_check_multi(ifnet_t ifp, const struct sockaddr *proto_addr)
592 {
593 #pragma unused(ifp)
594 	errno_t result = EAFNOSUPPORT;
595 	const u_char *e_addr;
596 
597 	/*
598 	 * AF_SPEC and AF_LINK don't require translation. We do
599 	 * want to verify that they specify a valid multicast.
600 	 */
601 	switch (proto_addr->sa_family) {
602 	case AF_UNSPEC:
603 		e_addr = (const u_char*)&proto_addr->sa_data[0];
604 		if ((e_addr[0] & 0x01) != 0x01) {
605 			result = EADDRNOTAVAIL;
606 		} else {
607 			result = 0;
608 		}
609 		break;
610 
611 	case AF_LINK:
612 		e_addr = CONST_LLADDR((const struct sockaddr_dl*)
613 		    (uintptr_t)(size_t)proto_addr);
614 		if ((e_addr[0] & 0x01) != 0x01) {
615 			result = EADDRNOTAVAIL;
616 		} else {
617 			result = 0;
618 		}
619 		break;
620 	}
621 
622 	return result;
623 }
624 
625 int
ether_ioctl(ifnet_t ifp,u_int32_t command,void * data)626 ether_ioctl(ifnet_t ifp, u_int32_t command, void *data)
627 {
628 #pragma unused(ifp, command, data)
629 	return EOPNOTSUPP;
630 }
631 
632 __private_extern__ int
ether_family_init(void)633 ether_family_init(void)
634 {
635 	errno_t error = 0;
636 
637 	/* Register protocol registration functions */
638 	if ((error = proto_register_plumber(PF_INET, APPLE_IF_FAM_ETHERNET,
639 	    ether_attach_inet, ether_detach_inet)) != 0) {
640 		printf("proto_register_plumber failed for PF_INET error=%d\n",
641 		    error);
642 		goto done;
643 	}
644 	if ((error = proto_register_plumber(PF_INET6, APPLE_IF_FAM_ETHERNET,
645 	    ether_attach_inet6, ether_detach_inet6)) != 0) {
646 		printf("proto_register_plumber failed for PF_INET6 error=%d\n",
647 		    error);
648 		goto done;
649 	}
650 #if VLAN
651 	vlan_family_init();
652 #endif /* VLAN */
653 #if BOND
654 	bond_family_init();
655 #endif /* BOND */
656 #if IF_BRIDGE
657 	bridgeattach(0);
658 #endif /* IF_BRIDGE */
659 #if IF_FAKE
660 	if_fake_init();
661 #endif /* IF_FAKE */
662 #if IF_HEADLESS
663 	if_headless_init();
664 #endif /* IF_HEADLESS */
665 #if SIXLOWPAN
666 	sixlowpan_family_init();
667 #endif /* VLAN */
668 done:
669 
670 	return error;
671 }
672