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