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