2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc.
25 * Data Link Inteface Layer
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
36 #include <sys/socket.h>
37 #include <net/if_dl.h>
39 #include <net/if_var.h>
41 #include <sys/kern_event.h>
42 #include <sys/kdebug.h>
45 #include <kern/task.h>
46 #include <kern/thread.h>
47 #include <kern/sched_prim.h>
49 #include <net/netisr.h>
50 #include <net/if_types.h>
52 #include <machine/machine_routines.h>
54 #define DBG_LAYER_BEG DLILDBG_CODE(DBG_DLIL_STATIC, 0)
55 #define DBG_LAYER_END DLILDBG_CODE(DBG_DLIL_STATIC, 2)
56 #define DBG_FNC_DLIL_INPUT DLILDBG_CODE(DBG_DLIL_STATIC, (1 << 8))
57 #define DBG_FNC_DLIL_OUTPUT DLILDBG_CODE(DBG_DLIL_STATIC, (2 << 8))
58 #define DBG_FNC_DLIL_IFOUT DLILDBG_CODE(DBG_DLIL_STATIC, (3 << 8))
61 #define MAX_DL_TAGS 16
62 #define MAX_DLIL_FILTERS 16
63 #define MAX_FRAME_TYPE_SIZE 4 /* LONGWORDS */
64 #define MAX_LINKADDR 4 /* LONGWORDS */
65 #define M_NKE M_IFADDR
67 #define PFILT(x) ((struct dlil_filterq_entry *) (x))->variants.pr_filter
68 #define IFILT(x) ((struct dlil_filterq_entry *) (x))->variants.if_filter
72 struct if_proto
*proto
;
73 struct dlil_filterq_head
*pr_flt_head
;
78 /* ifnet and drvr_ext are used by the stack and drivers
79 drvr_ext extends the public ifnet and must follow dl_if */
80 struct ifnet dl_if
; /* public ifnet */
81 void *drvr_ext
[4]; /* driver reserved (e.g arpcom extension for enet) */
83 /* dlil private fields */
84 TAILQ_ENTRY(dlil_ifnet
) dl_if_link
; /* dlil_ifnet are link together */
85 /* it is not the ifnet list */
86 void *if_uniqueid
; /* unique id identifying the interface */
87 size_t if_uniqueid_len
;/* length of the unique id */
88 char if_namestorage
[IFNAMSIZ
]; /* interface name storage for detached interfaces */
91 struct dlil_stats_str
{
103 struct dlil_filter_id_str
{
105 struct dlil_filterq_head
*head
;
106 struct dlil_filterq_entry
*filter_ptr
;
108 struct if_proto
*proto
;
113 struct if_family_str
{
114 TAILQ_ENTRY(if_family_str
) if_fam_next
;
119 #define DLIL_SHUTDOWN 1
121 int (*add_if
)(struct ifnet
*ifp
);
122 int (*del_if
)(struct ifnet
*ifp
);
123 int (*init_if
)(struct ifnet
*ifp
);
124 int (*add_proto
)(struct ddesc_head_str
*demux_desc_head
,
125 struct if_proto
*proto
, u_long dl_tag
);
126 int (*del_proto
)(struct if_proto
*proto
, u_long dl_tag
);
127 int (*ifmod_ioctl
)(struct ifnet
*ifp
, u_long command
, caddr_t data
);
132 struct proto_family_str
{
133 TAILQ_ENTRY(proto_family_str
) proto_fam_next
;
137 int (*attach_proto
)(struct ifnet
*ifp
, u_long
*dl_tag
);
138 int (*detach_proto
)(struct ifnet
*ifp
, u_long dl_tag
);
143 struct dlil_stats_str dlil_stats
;
146 struct dlil_filter_id_str
*dlil_filters
;
149 struct dl_tag_str
*dl_tag_array
;
152 TAILQ_HEAD(, dlil_ifnet
) dlil_ifnet_head
;
155 TAILQ_HEAD(, if_family_str
) if_family_head
;
158 TAILQ_HEAD(, proto_family_str
) proto_family_head
;
160 static ifnet_inited
= 0;
161 static u_long dl_tag_nb
= 0;
162 static u_long dlil_filters_nb
= 0;
164 int dlil_initialized
= 0;
165 decl_simple_lock_data(, dlil_input_lock
)
166 int dlil_input_thread_wakeup
= 0;
167 static struct mbuf
*dlil_input_mbuf_head
= NULL
;
168 static struct mbuf
*dlil_input_mbuf_tail
= NULL
;
170 #error dlil_input() needs to be revised to support more than on loopback interface
172 static struct mbuf
*dlil_input_loop_head
= NULL
;
173 static struct mbuf
*dlil_input_loop_tail
= NULL
;
174 extern struct ifmultihead ifma_lostlist
;
176 static void dlil_input_thread(void);
177 extern void run_netisr(void);
178 extern void bpfdetach(struct ifnet
*);
183 * Internal functions.
187 struct if_family_str
*find_family_module(u_long if_family
)
189 struct if_family_str
*mod
= NULL
;
191 TAILQ_FOREACH(mod
, &if_family_head
, if_fam_next
) {
192 if (mod
->if_family
== (if_family
& 0xffff))
200 struct proto_family_str
*find_proto_module(u_long proto_family
, u_long if_family
)
202 struct proto_family_str
*mod
= NULL
;
204 TAILQ_FOREACH(mod
, &proto_family_head
, proto_fam_next
) {
205 if ((mod
->proto_family
== (proto_family
& 0xffff))
206 && (mod
->if_family
== (if_family
& 0xffff)))
218 struct ifnet
*ifbyfamily(u_long family
, short unit
)
222 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
223 if ((family
== ifp
->if_family
) &&
224 (ifp
->if_unit
== unit
))
230 struct if_proto
*dlttoproto(u_long dl_tag
)
232 if (dl_tag
< dl_tag_nb
&& dl_tag_array
[dl_tag
].ifp
)
233 return dl_tag_array
[dl_tag
].proto
;
238 static int dlil_ifp_proto_count(struct ifnet
* ifp
)
241 struct if_proto
* proto
;
242 struct dlil_proto_head
* tmp
;
244 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
246 TAILQ_FOREACH(proto
, tmp
, next
)
252 u_long
ifptodlt(struct ifnet
*ifp
, u_long proto_family
)
254 struct if_proto
*proto
;
255 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
258 TAILQ_FOREACH(proto
, tmp
, next
)
259 if (proto
->protocol_family
== proto_family
)
260 return proto
->dl_tag
;
266 int dlil_find_dltag(u_long if_family
, short unit
, u_long proto_family
, u_long
*dl_tag
)
270 ifp
= ifbyfamily(if_family
, unit
);
274 *dl_tag
= ifptodlt(ifp
, proto_family
);
276 return EPROTONOSUPPORT
;
282 void dlil_post_msg(struct ifnet
*ifp
, u_long event_subclass
, u_long event_code
,
283 struct net_event_data
*event_data
, u_long event_data_len
)
285 struct net_event_data ev_data
;
286 struct kev_msg ev_msg
;
289 * a net event always start with a net_event_data structure
290 * but the caller can generate a simple net event or
291 * provide a longer event structure to post
294 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
295 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
296 ev_msg
.kev_subclass
= event_subclass
;
297 ev_msg
.event_code
= event_code
;
299 if (event_data
== 0) {
300 event_data
= &ev_data
;
301 event_data_len
= sizeof(struct net_event_data
);
304 strncpy(&event_data
->if_name
[0], ifp
->if_name
, IFNAMSIZ
);
305 event_data
->if_family
= ifp
->if_family
;
306 event_data
->if_unit
= (unsigned long) ifp
->if_unit
;
308 ev_msg
.dv
[0].data_length
= event_data_len
;
309 ev_msg
.dv
[0].data_ptr
= event_data
;
310 ev_msg
.dv
[1].data_length
= 0;
312 kev_post_msg(&ev_msg
);
322 TAILQ_INIT(&dlil_ifnet_head
);
323 TAILQ_INIT(&if_family_head
);
324 TAILQ_INIT(&proto_family_head
);
326 // create the dl tag array
327 MALLOC(dl_tag_array
, void *, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
, M_NKE
, M_WAITOK
);
328 if (dl_tag_array
== 0) {
329 printf("dlil_init tags array allocation failed\n");
332 bzero(dl_tag_array
, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
);
333 dl_tag_nb
= MAX_DL_TAGS
;
335 // create the dl filters array
336 MALLOC(dlil_filters
, void *, sizeof(struct dlil_filter_id_str
) * MAX_DLIL_FILTERS
, M_NKE
, M_WAITOK
);
337 if (dlil_filters
== 0) {
338 printf("dlil_init filters array allocation failed\n");
341 bzero(dlil_filters
, sizeof(struct dlil_filter_id_str
) * MAX_DLIL_FILTERS
);
342 dlil_filters_nb
= MAX_DLIL_FILTERS
;
344 bzero(&dlil_stats
, sizeof(dlil_stats
));
346 simple_lock_init(&dlil_input_lock
);
349 * Start up the dlil input thread once everything is initialized
351 (void) kernel_thread(kernel_task
, dlil_input_thread
);
354 u_long
get_new_filter_id()
359 for (i
=1; i
< dlil_filters_nb
; i
++)
360 if (dlil_filters
[i
].type
== 0)
363 if (i
== dlil_filters_nb
) {
364 // expand the filters array by MAX_DLIL_FILTERS
365 MALLOC(p
, u_char
*, sizeof(struct dlil_filter_id_str
) * (dlil_filters_nb
+ MAX_DLIL_FILTERS
), M_NKE
, M_WAITOK
);
369 bcopy(dlil_filters
, p
, sizeof(struct dlil_filter_id_str
) * dlil_filters_nb
);
370 bzero(p
+ sizeof(struct dlil_filter_id_str
) * dlil_filters_nb
, sizeof(struct dlil_filter_id_str
) * MAX_DL_TAGS
);
371 dlil_filters_nb
+= MAX_DLIL_FILTERS
;
372 FREE(dlil_filters
, M_NKE
);
373 dlil_filters
= (struct dlil_filter_id_str
*)p
;
380 int dlil_attach_interface_filter(struct ifnet
*ifp
,
381 struct dlil_if_flt_str
*if_filter
,
387 struct dlil_filterq_entry
*tmp_ptr
;
388 struct dlil_filterq_entry
*if_filt
;
389 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
390 boolean_t funnel_state
;
392 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
396 bcopy((caddr_t
) if_filter
, (caddr_t
) &tmp_ptr
->variants
.if_filter
,
397 sizeof(struct dlil_if_flt_str
));
399 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
402 *filter_id
= get_new_filter_id();
403 if (*filter_id
== 0) {
404 FREE(tmp_ptr
, M_NKE
);
409 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
410 dlil_filters
[*filter_id
].head
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
411 dlil_filters
[*filter_id
].type
= DLIL_IF_FILTER
;
412 dlil_filters
[*filter_id
].ifp
= ifp
;
413 tmp_ptr
->filter_id
= *filter_id
;
414 tmp_ptr
->type
= DLIL_IF_FILTER
;
416 if (insertion_point
!= DLIL_LAST_FILTER
) {
417 TAILQ_FOREACH(if_filt
, fhead
, que
)
418 if (insertion_point
== if_filt
->filter_id
) {
419 TAILQ_INSERT_BEFORE(if_filt
, tmp_ptr
, que
);
424 TAILQ_INSERT_TAIL(fhead
, tmp_ptr
, que
);
428 thread_funnel_set(network_flock
, funnel_state
);
433 int dlil_attach_protocol_filter(u_long dl_tag
,
434 struct dlil_pr_flt_str
*pr_filter
,
438 struct dlil_filterq_entry
*tmp_ptr
, *pr_filt
;
441 boolean_t funnel_state
;
443 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0)
446 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
450 bcopy((caddr_t
) pr_filter
, (caddr_t
) &tmp_ptr
->variants
.pr_filter
,
451 sizeof(struct dlil_pr_flt_str
));
453 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
456 *filter_id
= get_new_filter_id();
457 if (*filter_id
== 0) {
458 FREE(tmp_ptr
, M_NKE
);
463 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
464 dlil_filters
[*filter_id
].head
= dl_tag_array
[dl_tag
].pr_flt_head
;
465 dlil_filters
[*filter_id
].type
= DLIL_PR_FILTER
;
466 dlil_filters
[*filter_id
].proto
= dl_tag_array
[dl_tag
].proto
;
467 dlil_filters
[*filter_id
].ifp
= dl_tag_array
[dl_tag
].ifp
;
468 tmp_ptr
->filter_id
= *filter_id
;
469 tmp_ptr
->type
= DLIL_PR_FILTER
;
471 if (insertion_point
!= DLIL_LAST_FILTER
) {
472 TAILQ_FOREACH(pr_filt
, dl_tag_array
[dl_tag
].pr_flt_head
, que
)
473 if (insertion_point
== pr_filt
->filter_id
) {
474 TAILQ_INSERT_BEFORE(pr_filt
, tmp_ptr
, que
);
479 TAILQ_INSERT_TAIL(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
483 thread_funnel_set(network_flock
, funnel_state
);
489 dlil_detach_filter(u_long filter_id
)
491 struct dlil_filter_id_str
*flt
;
493 boolean_t funnel_state
;
495 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
498 if (filter_id
>= dlil_filters_nb
|| dlil_filters
[filter_id
].type
== 0) {
503 flt
= &dlil_filters
[filter_id
];
505 if (flt
->type
== DLIL_IF_FILTER
) {
506 if (IFILT(flt
->filter_ptr
).filter_detach
)
507 (*IFILT(flt
->filter_ptr
).filter_detach
)(IFILT(flt
->filter_ptr
).cookie
);
510 if (flt
->type
== DLIL_PR_FILTER
) {
511 if (PFILT(flt
->filter_ptr
).filter_detach
)
512 (*PFILT(flt
->filter_ptr
).filter_detach
)(PFILT(flt
->filter_ptr
).cookie
);
516 TAILQ_REMOVE(flt
->head
, flt
->filter_ptr
, que
);
517 FREE(flt
->filter_ptr
, M_NKE
);
522 thread_funnel_set(network_flock
, funnel_state
);
527 dlil_input_thread_continue(void)
530 struct mbuf
*m
, *m_loop
;
532 usimple_lock(&dlil_input_lock
);
533 m
= dlil_input_mbuf_head
;
534 dlil_input_mbuf_head
= NULL
;
535 dlil_input_mbuf_tail
= NULL
;
536 m_loop
= dlil_input_loop_head
;
537 dlil_input_loop_head
= NULL
;
538 dlil_input_loop_tail
= NULL
;
539 usimple_unlock(&dlil_input_lock
);
542 * NOTE warning %%% attention !!!!
543 * We should think about putting some thread starvation safeguards if
544 * we deal with long chains of packets.
547 struct mbuf
*m0
= m
->m_nextpkt
;
548 void *header
= m
->m_pkthdr
.header
;
551 m
->m_pkthdr
.header
= NULL
;
552 (void) dlil_input_packet(m
->m_pkthdr
.rcvif
, m
, header
);
557 struct mbuf
*m0
= m
->m_nextpkt
;
558 void *header
= m
->m_pkthdr
.header
;
559 struct ifnet
*ifp
= &loif
[0];
562 m
->m_pkthdr
.header
= NULL
;
563 (void) dlil_input_packet(ifp
, m
, header
);
570 if (dlil_input_mbuf_head
== NULL
&&
571 dlil_input_loop_head
== NULL
&&
573 assert_wait(&dlil_input_thread_wakeup
, THREAD_UNINT
);
574 (void) thread_block(dlil_input_thread_continue
);
580 void dlil_input_thread(void)
582 register thread_t self
= current_act();
584 ml_thread_policy(self
, MACHINE_GROUP
,
585 (MACHINE_NETWORK_GROUP
|MACHINE_NETWORK_NETISR
));
587 /* The dlil thread is always funneled */
588 thread_funnel_set(network_flock
, TRUE
);
589 dlil_initialized
= 1;
590 dlil_input_thread_continue();
594 dlil_input(struct ifnet
*ifp
, struct mbuf
*m_head
, struct mbuf
*m_tail
)
597 * Because of loopbacked multicast we cannot stuff the ifp in
598 * the rcvif of the packet header: loopback has its own dlil
602 usimple_lock(&dlil_input_lock
);
603 if (ifp
->if_type
!= IFT_LOOP
) {
604 if (dlil_input_mbuf_head
== NULL
)
605 dlil_input_mbuf_head
= m_head
;
606 else if (dlil_input_mbuf_tail
!= NULL
)
607 dlil_input_mbuf_tail
->m_nextpkt
= m_head
;
608 dlil_input_mbuf_tail
= m_tail
? m_tail
: m_head
;
610 if (dlil_input_loop_head
== NULL
)
611 dlil_input_loop_head
= m_head
;
612 else if (dlil_input_loop_tail
!= NULL
)
613 dlil_input_loop_tail
->m_nextpkt
= m_head
;
614 dlil_input_loop_tail
= m_tail
? m_tail
: m_head
;
616 usimple_unlock(&dlil_input_lock
);
618 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
624 dlil_input_packet(struct ifnet
*ifp
, struct mbuf
*m
,
627 struct ifnet
*orig_ifp
= 0;
628 struct dlil_filterq_entry
*tmp
;
630 struct if_proto
*ifproto
= 0;
631 struct if_proto
*proto
;
632 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
635 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_START
,0,0,0,0,0);
638 * Run interface filters
641 while (orig_ifp
!= ifp
) {
644 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
645 if (IFILT(tmp
).filter_if_input
) {
646 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
651 if (retval
== EJUSTRETURN
)
665 ifp
->if_lastchange
= time
;
668 * Call family demux module. If the demux module finds a match
669 * for the frame it will fill-in the ifproto pointer.
672 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
674 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
677 if ((retval
) && (retval
!= EJUSTRETURN
) && (ifp
->offercnt
)) {
679 * No match was found, look for any offers.
681 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
682 TAILQ_FOREACH(proto
, tmp
, next
) {
683 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
692 if (retval
!= EJUSTRETURN
) {
701 printf("ERROR - dlil_input - if_demux didn't return an if_proto pointer\n");
707 * Call any attached protocol filters.
710 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
711 if (PFILT(tmp
).filter_dl_input
) {
712 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
718 if (retval
== EJUSTRETURN
)
730 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
731 ifp
, ifproto
->dl_tag
,
734 if (retval
== EJUSTRETURN
)
740 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_END
,0,0,0,0,0);
746 void ether_input(ifp
, eh
, m
)
748 struct ether_header
*eh
;
752 kprintf("Someone is calling ether_input!!\n");
754 dlil_input(ifp
, m
, NULL
);
759 dlil_event(struct ifnet
*ifp
, struct kern_event_msg
*event
)
761 struct dlil_filterq_entry
*filt
;
763 struct ifnet
*orig_ifp
= 0;
764 struct if_proto
*proto
;
765 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
766 struct kev_msg kev_msg
;
767 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
768 boolean_t funnel_state
;
771 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
773 while (orig_ifp
!= ifp
) {
776 TAILQ_FOREACH_REVERSE(filt
, fhead
, que
, dlil_filterq_head
) {
777 if (IFILT(filt
).filter_if_event
) {
778 retval
= (*IFILT(filt
).filter_if_event
)(IFILT(filt
).cookie
,
783 (void) thread_funnel_set(network_flock
, funnel_state
);
784 if (retval
== EJUSTRETURN
)
798 * Call Interface Module event hook, if any.
802 retval
= ifp
->if_event(ifp
, (caddr_t
) event
);
805 (void) thread_funnel_set(network_flock
, funnel_state
);
807 if (retval
== EJUSTRETURN
)
815 * Call dl_event entry point for all protocols attached to this interface
818 TAILQ_FOREACH(proto
, tmp
, next
) {
820 * Call any attached protocol filters.
823 TAILQ_FOREACH_REVERSE(filt
, &proto
->pr_flt_head
, que
, dlil_filterq_head
) {
824 if (PFILT(filt
).filter_dl_event
) {
825 retval
= (*PFILT(filt
).filter_dl_event
)(PFILT(filt
).cookie
,
829 (void) thread_funnel_set(network_flock
, funnel_state
);
830 if (retval
== EJUSTRETURN
)
840 * Finally, call the dl_event entry point (if any)
844 retval
= (*proto
->dl_event
)(event
, proto
->dl_tag
);
846 if (retval
== EJUSTRETURN
) {
847 (void) thread_funnel_set(network_flock
, funnel_state
);
854 * Now, post this event to the Kernel Event message queue
857 kev_msg
.vendor_code
= event
->vendor_code
;
858 kev_msg
.kev_class
= event
->kev_class
;
859 kev_msg
.kev_subclass
= event
->kev_subclass
;
860 kev_msg
.event_code
= event
->event_code
;
861 kev_msg
.dv
[0].data_ptr
= &event
->event_data
[0];
862 kev_msg
.dv
[0].data_length
= event
->total_size
- KEV_MSG_HEADER_SIZE
;
863 kev_msg
.dv
[1].data_length
= 0;
865 kev_post_msg(&kev_msg
);
867 (void) thread_funnel_set(network_flock
, funnel_state
);
874 dlil_output(u_long dl_tag
,
877 struct sockaddr
*dest
,
883 struct ifnet
*orig_ifp
= 0;
885 struct if_proto
*proto
;
886 struct dlil_filterq_entry
*tmp
;
888 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
889 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
890 struct dlil_filterq_head
*fhead
;
892 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_START
,0,0,0,0,0);
894 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0) {
899 ifp
= dl_tag_array
[dl_tag
].ifp
;
900 proto
= dl_tag_array
[dl_tag
].proto
;
902 frame_type
= frame_type_buffer
;
903 dst_linkaddr
= dst_linkaddr_buffer
;
905 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
907 if ((raw
== 0) && (proto
->dl_pre_output
)) {
908 retval
= (*proto
->dl_pre_output
)(ifp
, &m
, dest
, route
,
909 frame_type
, dst_linkaddr
, dl_tag
);
911 if (retval
== EJUSTRETURN
)
921 * Run any attached protocol filters.
924 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
925 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
926 if (PFILT(tmp
).filter_dl_output
) {
927 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
928 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
930 if (retval
== EJUSTRETURN
)
943 * Call framing module
945 if ((raw
== 0) && (ifp
->if_framer
)) {
946 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
948 if (retval
== EJUSTRETURN
)
960 struct mbuf
*m0
= m
;
961 struct ether_header
*eh
= mtod(m
, struct ether_header
*);
963 if (m
->m_pkthdr
.rcvif
)
964 m
->m_pkthdr
.rcvif
= NULL
;
965 ifp
= bridge_dst_lookup(eh
);
966 bdg_forward(&m0
, ifp
);
976 * Let interface filters (if any) do their thing ...
979 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
980 if (TAILQ_EMPTY(fhead
) == 0) {
981 while (orig_ifp
!= ifp
) {
983 TAILQ_FOREACH(tmp
, fhead
, que
) {
984 if (IFILT(tmp
).filter_if_output
) {
985 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
989 if (retval
== EJUSTRETURN
)
1006 * Finally, call the driver.
1009 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_START
, 0,0,0,0,0);
1010 retval
= (*ifp
->if_output
)(ifp
, m
);
1011 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_END
, 0,0,0,0,0);
1013 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_END
,0,0,0,0,0);
1015 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1023 dlil_ioctl(u_long proto_fam
,
1028 struct dlil_filterq_entry
*tmp
;
1029 struct dlil_filterq_head
*fhead
;
1030 int retval
= EOPNOTSUPP
;
1031 int retval2
= EOPNOTSUPP
;
1033 struct if_family_str
*if_family
;
1037 if (dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
,
1038 proto_fam
, &dl_tag
) == 0) {
1039 if (dl_tag_array
[dl_tag
].ifp
!= ifp
)
1043 * Run any attached protocol filters.
1045 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1046 if (PFILT(tmp
).filter_dl_ioctl
) {
1048 (*PFILT(tmp
).filter_dl_ioctl
)(PFILT(tmp
).cookie
,
1049 dl_tag_array
[dl_tag
].ifp
,
1054 if (retval
== EJUSTRETURN
)
1062 if (dl_tag_array
[dl_tag
].proto
->dl_ioctl
)
1064 (*dl_tag_array
[dl_tag
].proto
->dl_ioctl
)(dl_tag
,
1065 dl_tag_array
[dl_tag
].ifp
,
1069 retval
= EOPNOTSUPP
;
1073 if ((retval
) && (retval
!= EOPNOTSUPP
)) {
1074 if (retval
== EJUSTRETURN
)
1081 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1082 TAILQ_FOREACH(tmp
, fhead
, que
) {
1083 if (IFILT(tmp
).filter_if_ioctl
) {
1084 retval2
= (*IFILT(tmp
).filter_if_ioctl
)(IFILT(tmp
).cookie
, ifp
,
1085 ioctl_code
, ioctl_arg
);
1087 if (retval2
== EJUSTRETURN
)
1096 if_family
= find_family_module(ifp
->if_family
);
1097 if ((if_family
) && (if_family
->ifmod_ioctl
)) {
1098 retval2
= (*if_family
->ifmod_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1100 if ((retval2
) && (retval2
!= EOPNOTSUPP
)) {
1101 if (retval2
== EJUSTRETURN
)
1107 if (retval
== EOPNOTSUPP
)
1112 retval2
= (*ifp
->if_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1114 if (retval
== EOPNOTSUPP
)
1117 if (retval2
== EOPNOTSUPP
)
1126 dlil_attach_protocol(struct dlil_proto_reg_str
*proto
,
1130 struct if_proto
*ifproto
;
1132 struct if_family_str
*if_family
;
1133 struct dlil_proto_head
*tmp
;
1134 struct kev_dl_proto_data ev_pr_data
;
1136 boolean_t funnel_state
;
1139 if ((proto
->protocol_family
== 0) || (proto
->interface_family
== 0))
1142 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1144 if_family
= find_family_module(proto
->interface_family
);
1145 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1146 kprintf("dlil_attach_protocol -- no interface family module %d",
1147 proto
->interface_family
);
1152 ifp
= ifbyfamily(proto
->interface_family
, proto
->unit_number
);
1154 kprintf("dlil_attach_protocol -- no such interface %d unit %d\n",
1155 proto
->interface_family
, proto
->unit_number
);
1160 if (dlil_find_dltag(proto
->interface_family
, proto
->unit_number
,
1161 proto
->protocol_family
, &i
) == 0) {
1166 for (i
=1; i
< dl_tag_nb
; i
++)
1167 if (dl_tag_array
[i
].ifp
== 0)
1170 if (i
== dl_tag_nb
) {
1171 // expand the tag array by MAX_DL_TAGS
1172 MALLOC(p
, u_char
*, sizeof(struct dl_tag_str
) * (dl_tag_nb
+ MAX_DL_TAGS
), M_NKE
, M_WAITOK
);
1177 bcopy(dl_tag_array
, p
, sizeof(struct dl_tag_str
) * dl_tag_nb
);
1178 bzero(p
+ sizeof(struct dl_tag_str
) * dl_tag_nb
, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
);
1179 dl_tag_nb
+= MAX_DL_TAGS
;
1180 FREE(dl_tag_array
, M_NKE
);
1181 dl_tag_array
= (struct dl_tag_str
*)p
;
1185 * Allocate and init a new if_proto structure
1188 ifproto
= _MALLOC(sizeof(struct if_proto
), M_IFADDR
, M_WAITOK
);
1190 printf("ERROR - DLIL failed if_proto allocation\n");
1195 bzero(ifproto
, sizeof(struct if_proto
));
1197 dl_tag_array
[i
].ifp
= ifp
;
1198 dl_tag_array
[i
].proto
= ifproto
;
1199 dl_tag_array
[i
].pr_flt_head
= &ifproto
->pr_flt_head
;
1200 ifproto
->dl_tag
= i
;
1203 if (proto
->default_proto
) {
1204 if (ifp
->if_data
.default_proto
== 0)
1205 ifp
->if_data
.default_proto
= i
;
1207 printf("ERROR - dlil_attach_protocol -- Attempt to attach more than one default protocol\n");
1210 ifproto
->protocol_family
= proto
->protocol_family
;
1211 ifproto
->dl_input
= proto
->input
;
1212 ifproto
->dl_pre_output
= proto
->pre_output
;
1213 ifproto
->dl_event
= proto
->event
;
1214 ifproto
->dl_offer
= proto
->offer
;
1215 ifproto
->dl_ioctl
= proto
->ioctl
;
1217 TAILQ_INIT(&ifproto
->pr_flt_head
);
1220 * Call family module add_proto routine so it can refine the
1221 * demux descriptors as it wishes.
1223 retval
= (*if_family
->add_proto
)(&proto
->demux_desc_head
, ifproto
, *dl_tag
);
1225 dl_tag_array
[i
].ifp
= 0;
1226 FREE(ifproto
, M_IFADDR
);
1231 * Add to if_proto list for this interface
1234 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1235 TAILQ_INSERT_TAIL(tmp
, ifproto
, next
);
1237 if (ifproto
->dl_offer
)
1240 /* the reserved field carries the number of protocol still attached (subject to change) */
1241 ev_pr_data
.proto_family
= proto
->protocol_family
;
1242 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1243 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_ATTACHED
,
1244 (struct net_event_data
*)&ev_pr_data
,
1245 sizeof(struct kev_dl_proto_data
));
1249 thread_funnel_set(network_flock
, funnel_state
);
1256 dlil_detach_protocol(u_long dl_tag
)
1259 struct ifnet
*orig_ifp
=0;
1260 struct if_proto
*proto
;
1261 struct dlil_proto_head
*tmp
;
1262 struct if_family_str
*if_family
;
1263 struct dlil_filterq_entry
*filter
;
1265 struct dlil_filterq_head
*fhead
;
1266 struct kev_dl_proto_data ev_pr_data
;
1267 boolean_t funnel_state
;
1269 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1272 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0) {
1277 ifp
= dl_tag_array
[dl_tag
].ifp
;
1278 proto
= dl_tag_array
[dl_tag
].proto
;
1280 if_family
= find_family_module(ifp
->if_family
);
1281 if (if_family
== NULL
) {
1286 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1289 * Call family module del_proto
1292 (*if_family
->del_proto
)(proto
, dl_tag
);
1296 * Remove and deallocate any attached protocol filters
1299 while (filter
= TAILQ_FIRST(&proto
->pr_flt_head
))
1300 dlil_detach_filter(filter
->filter_id
);
1302 if (proto
->dl_offer
)
1305 if (ifp
->if_data
.default_proto
== dl_tag
)
1306 ifp
->if_data
.default_proto
= 0;
1307 dl_tag_array
[dl_tag
].ifp
= 0;
1309 /* the reserved field carries the number of protocol still attached (subject to change) */
1310 ev_pr_data
.proto_family
= proto
->protocol_family
;
1313 * Cleanup routes that may still be in the routing table for that interface/protocol pair.
1316 if_rtproto_del(ifp
, proto
->protocol_family
);
1318 TAILQ_REMOVE(tmp
, proto
, next
);
1319 FREE(proto
, M_IFADDR
);
1322 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1323 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_DETACHED
,
1324 (struct net_event_data
*)&ev_pr_data
,
1325 sizeof(struct kev_dl_proto_data
));
1327 if (ifp
->refcnt
== 0) {
1329 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1331 (*if_family
->del_if
)(ifp
);
1333 if (--if_family
->refcnt
== 0) {
1334 if (if_family
->shutdown
)
1335 (*if_family
->shutdown
)();
1337 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1338 FREE(if_family
, M_IFADDR
);
1341 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1342 while (orig_ifp
!= ifp
) {
1345 TAILQ_FOREACH(filter
, fhead
, que
) {
1346 if (IFILT(filter
).filter_if_free
) {
1347 retval
= (*IFILT(filter
).filter_if_free
)(IFILT(filter
).cookie
, ifp
);
1350 thread_funnel_set(network_flock
, funnel_state
);
1354 if (ifp
!= orig_ifp
)
1359 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1361 (*ifp
->if_free
)(ifp
);
1366 thread_funnel_set(network_flock
, funnel_state
);
1375 dlil_if_attach(struct ifnet
*ifp
)
1377 u_long interface_family
= ifp
->if_family
;
1378 struct if_family_str
*if_family
;
1379 struct dlil_proto_head
*tmp
;
1382 boolean_t funnel_state
;
1384 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1386 if (ifnet_inited
== 0) {
1391 if_family
= find_family_module(interface_family
);
1393 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1395 kprintf("Attempt to attach interface without family module - %d\n",
1397 thread_funnel_set(network_flock
, funnel_state
);
1401 if (ifp
->refcnt
== 0) {
1403 * Call the family module to fill in the appropriate fields in the
1407 stat
= (*if_family
->add_if
)(ifp
);
1410 kprintf("dlil_if_attach -- add_if failed with %d\n", stat
);
1411 thread_funnel_set(network_flock
, funnel_state
);
1414 if_family
->refcnt
++;
1417 * Add the ifp to the interface list.
1420 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1423 ifp
->if_data
.default_proto
= 0;
1425 TAILQ_INIT(&ifp
->if_flt_head
);
1428 if (if_family
->init_if
) {
1429 stat
= (*if_family
->init_if
)(ifp
);
1431 kprintf("dlil_if_attach -- init_if failed with %d\n", stat
);
1438 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_ATTACHED
, 0, 0);
1441 thread_funnel_set(network_flock
, funnel_state
);
1447 dlil_if_detach(struct ifnet
*ifp
)
1449 struct if_proto
*proto
;
1450 struct dlil_filterq_entry
*if_filter
;
1451 struct if_family_str
*if_family
;
1452 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1453 struct kev_msg ev_msg
;
1454 boolean_t funnel_state
;
1456 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1458 if_family
= find_family_module(ifp
->if_family
);
1461 kprintf("Attempt to detach interface without family module - %s\n",
1463 thread_funnel_set(network_flock
, funnel_state
);
1467 while (if_filter
= TAILQ_FIRST(fhead
))
1468 dlil_detach_filter(if_filter
->filter_id
);
1472 if (ifp
->refcnt
> 0) {
1473 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHING
, 0, 0);
1474 thread_funnel_set(network_flock
, funnel_state
);
1475 return DLIL_WAIT_FOR_FREE
;
1478 while (ifp
->if_multiaddrs
.lh_first
) {
1479 struct ifmultiaddr
*ifma
= ifp
->if_multiaddrs
.lh_first
;
1482 * When the interface is gone, we will no
1483 * longer be listening on these multicasts.
1484 * Various bits of the stack may be referencing
1485 * these multicasts, so we can't just free them.
1486 * We place them on a list so they may be cleaned
1487 * up later as the other bits of the stack release
1490 LIST_REMOVE(ifma
, ifma_link
);
1491 ifma
->ifma_ifp
= NULL
;
1492 LIST_INSERT_HEAD(&ifma_lostlist
, ifma
, ifma_link
);
1495 /* Let BPF know the interface is detaching. */
1497 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1499 (*if_family
->del_if
)(ifp
);
1501 if (--if_family
->refcnt
== 0) {
1502 if (if_family
->shutdown
)
1503 (*if_family
->shutdown
)();
1505 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1506 FREE(if_family
, M_IFADDR
);
1509 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1510 thread_funnel_set(network_flock
, funnel_state
);
1516 dlil_reg_if_modules(u_long interface_family
,
1517 struct dlil_ifmod_reg_str
*ifmod
)
1519 struct if_family_str
*if_family
;
1521 boolean_t funnel_state
;
1524 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1526 if (find_family_module(interface_family
)) {
1527 kprintf("Attempt to register dlil family module more than once - %d\n",
1530 thread_funnel_set(network_flock
, funnel_state
);
1534 if ((!ifmod
->add_if
) || (!ifmod
->del_if
) ||
1535 (!ifmod
->add_proto
) || (!ifmod
->del_proto
)) {
1536 kprintf("dlil_reg_if_modules passed at least one null pointer\n");
1538 thread_funnel_set(network_flock
, funnel_state
);
1543 * The following is a gross hack to keep from breaking
1544 * Vicomsoft's internet gateway on Jaguar. Vicomsoft
1545 * does not zero the reserved fields in dlil_ifmod_reg_str.
1546 * As a result, we have to zero any function that used to
1547 * be reserved fields at the time Vicomsoft built their
1548 * kext. Radar #2974305
1550 if (ifmod
->reserved
[0] != 0 || ifmod
->reserved
[1] != 0 || ifmod
->reserved
[2]) {
1551 if (interface_family
== 123) { /* Vicom */
1555 thread_funnel_set(network_flock
, funnel_state
);
1560 if_family
= (struct if_family_str
*) _MALLOC(sizeof(struct if_family_str
), M_IFADDR
, M_WAITOK
);
1562 kprintf("dlil_reg_if_modules failed allocation\n");
1564 thread_funnel_set(network_flock
, funnel_state
);
1568 bzero(if_family
, sizeof(struct if_family_str
));
1570 if_family
->if_family
= interface_family
& 0xffff;
1571 if_family
->shutdown
= ifmod
->shutdown
;
1572 if_family
->add_if
= ifmod
->add_if
;
1573 if_family
->del_if
= ifmod
->del_if
;
1574 if_family
->init_if
= ifmod
->init_if
;
1575 if_family
->add_proto
= ifmod
->add_proto
;
1576 if_family
->del_proto
= ifmod
->del_proto
;
1577 if_family
->ifmod_ioctl
= ifmod
->ifmod_ioctl
;
1578 if_family
->refcnt
= 1;
1579 if_family
->flags
= 0;
1581 TAILQ_INSERT_TAIL(&if_family_head
, if_family
, if_fam_next
);
1583 thread_funnel_set(network_flock
, funnel_state
);
1587 int dlil_dereg_if_modules(u_long interface_family
)
1589 struct if_family_str
*if_family
;
1591 boolean_t funnel_state
;
1593 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1595 if_family
= find_family_module(interface_family
);
1596 if (if_family
== 0) {
1598 thread_funnel_set(network_flock
, funnel_state
);
1602 if (--if_family
->refcnt
== 0) {
1603 if (if_family
->shutdown
)
1604 (*if_family
->shutdown
)();
1606 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1607 FREE(if_family
, M_IFADDR
);
1610 if_family
->flags
|= DLIL_SHUTDOWN
;
1611 ret
= DLIL_WAIT_FOR_FREE
;
1615 thread_funnel_set(network_flock
, funnel_state
);
1622 dlil_reg_proto_module(u_long protocol_family
, u_long interface_family
,
1623 struct dlil_protomod_reg_str
*protomod_reg
)
1625 struct proto_family_str
*proto_family
;
1627 boolean_t funnel_state
;
1630 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1632 if (find_proto_module(protocol_family
, interface_family
)) {
1634 thread_funnel_set(network_flock
, funnel_state
);
1638 if (protomod_reg
->reserved
[0] != 0 || protomod_reg
->reserved
[1] != 0
1639 || protomod_reg
->reserved
[2] != 0 || protomod_reg
->reserved
[3] !=0) {
1641 thread_funnel_set(network_flock
, funnel_state
);
1645 if (protomod_reg
->attach_proto
== NULL
) {
1647 thread_funnel_set(network_flock
, funnel_state
);
1651 proto_family
= (struct proto_family_str
*) _MALLOC(sizeof(struct proto_family_str
), M_IFADDR
, M_WAITOK
);
1652 if (!proto_family
) {
1654 thread_funnel_set(network_flock
, funnel_state
);
1658 bzero(proto_family
, sizeof(struct proto_family_str
));
1659 proto_family
->proto_family
= protocol_family
;
1660 proto_family
->if_family
= interface_family
& 0xffff;
1661 proto_family
->attach_proto
= protomod_reg
->attach_proto
;
1662 proto_family
->detach_proto
= protomod_reg
->detach_proto
;
1664 TAILQ_INSERT_TAIL(&proto_family_head
, proto_family
, proto_fam_next
);
1666 thread_funnel_set(network_flock
, funnel_state
);
1670 int dlil_dereg_proto_module(u_long protocol_family
, u_long interface_family
)
1672 struct proto_family_str
*proto_family
;
1674 boolean_t funnel_state
;
1676 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1678 proto_family
= find_proto_module(protocol_family
, interface_family
);
1679 if (proto_family
== 0) {
1681 thread_funnel_set(network_flock
, funnel_state
);
1685 TAILQ_REMOVE(&proto_family_head
, proto_family
, proto_fam_next
);
1686 FREE(proto_family
, M_IFADDR
);
1689 thread_funnel_set(network_flock
, funnel_state
);
1693 int dlil_plumb_protocol(u_long protocol_family
, struct ifnet
*ifp
, u_long
*dl_tag
)
1695 struct proto_family_str
*proto_family
;
1697 boolean_t funnel_state
;
1699 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1701 proto_family
= find_proto_module(protocol_family
, ifp
->if_family
);
1702 if (proto_family
== 0) {
1704 thread_funnel_set(network_flock
, funnel_state
);
1708 ret
= (*proto_family
->attach_proto
)(ifp
, dl_tag
);
1711 thread_funnel_set(network_flock
, funnel_state
);
1716 int dlil_unplumb_protocol(u_long protocol_family
, struct ifnet
*ifp
)
1718 struct proto_family_str
*proto_family
;
1721 boolean_t funnel_state
;
1723 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1726 ret
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
, protocol_family
, &tag
);
1729 proto_family
= find_proto_module(protocol_family
, ifp
->if_family
);
1730 if (proto_family
&& proto_family
->detach_proto
)
1731 ret
= (*proto_family
->detach_proto
)(ifp
, tag
);
1733 ret
= dlil_detach_protocol(tag
);
1737 thread_funnel_set(network_flock
, funnel_state
);
1744 * Old if_attach no-op'ed function defined here for temporary backwards compatibility
1750 dlil_if_attach(ifp
);
1756 dlil_inject_if_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1758 struct ifnet
*orig_ifp
= 0;
1760 struct if_proto
*ifproto
;
1761 struct if_proto
*proto
;
1762 struct dlil_filterq_entry
*tmp
;
1764 struct dlil_filterq_head
*fhead
;
1767 dlil_stats
.inject_if_in1
++;
1769 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1772 ifp
= dlil_filters
[from_id
].ifp
;
1775 * Let interface filters (if any) do their thing ...
1778 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1781 if (TAILQ_EMPTY(fhead
) == 0) {
1782 while (orig_ifp
!= ifp
) {
1784 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
1785 if ((match_found
) && (IFILT(tmp
).filter_if_input
)) {
1786 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
1791 if (retval
== EJUSTRETURN
)
1801 if (ifp
!= orig_ifp
)
1804 if (from_id
== tmp
->filter_id
)
1810 ifp
->if_lastchange
= time
;
1813 * Call family demux module. If the demux module finds a match
1814 * for the frame it will fill-in the ifproto pointer.
1817 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
1819 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
1822 if ((retval
) && (ifp
->offercnt
)) {
1824 * No match was found, look for any offers.
1826 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1827 TAILQ_FOREACH(proto
, tmp
, next
) {
1828 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
1837 if (retval
!= EJUSTRETURN
) {
1846 printf("ERROR - dlil_inject_if_input -- if_demux didn't return an if_proto pointer\n");
1852 * Call any attached protocol filters.
1854 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1855 if (PFILT(tmp
).filter_dl_input
) {
1856 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1862 if (retval
== EJUSTRETURN
)
1874 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1875 ifp
, ifproto
->dl_tag
,
1878 dlil_stats
.inject_if_in2
++;
1879 if (retval
== EJUSTRETURN
)
1894 dlil_inject_pr_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1896 struct ifnet
*orig_ifp
= 0;
1897 struct dlil_filterq_entry
*tmp
;
1899 struct if_proto
*ifproto
= 0;
1903 dlil_stats
.inject_pr_in1
++;
1904 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1907 ifproto
= dlil_filters
[from_id
].proto
;
1908 ifp
= dlil_filters
[from_id
].ifp
;
1911 * Call any attached protocol filters.
1915 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1916 if ((match_found
) && (PFILT(tmp
).filter_dl_input
)) {
1917 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1923 if (retval
== EJUSTRETURN
)
1932 if (tmp
->filter_id
== from_id
)
1937 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1938 ifp
, ifproto
->dl_tag
,
1941 if (retval
== EJUSTRETURN
)
1947 dlil_stats
.inject_pr_in2
++;
1954 dlil_inject_pr_output(struct mbuf
*m
,
1955 struct sockaddr
*dest
,
1961 struct ifnet
*orig_ifp
= 0;
1963 struct dlil_filterq_entry
*tmp
;
1965 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
1966 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
1967 struct dlil_filterq_head
*fhead
;
1971 dlil_stats
.inject_pr_out1
++;
1974 bcopy(frame_type
, &frame_type_buffer
[0], MAX_FRAME_TYPE_SIZE
* 4);
1979 bcopy(dst_linkaddr
, &dst_linkaddr_buffer
, MAX_LINKADDR
* 4);
1984 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1987 ifp
= dlil_filters
[from_id
].ifp
;
1988 dl_tag
= dlil_filters
[from_id
].proto
->dl_tag
;
1990 frame_type
= frame_type_buffer
;
1991 dst_linkaddr
= dst_linkaddr_buffer
;
1993 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1996 * Run any attached protocol filters.
2000 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
2001 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
2002 if ((match_found
) && (PFILT(tmp
).filter_dl_output
)) {
2003 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
2004 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
2006 if (retval
== EJUSTRETURN
)
2015 if (tmp
->filter_id
== from_id
)
2022 * Call framing module
2024 if ((raw
== 0) && (ifp
->if_framer
)) {
2025 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
2027 if (retval
== EJUSTRETURN
)
2040 struct mbuf
*m0
= m
;
2041 struct ether_header
*eh
= mtod(m
, struct ether_header
*);
2043 if (m
->m_pkthdr
.rcvif
)
2044 m
->m_pkthdr
.rcvif
= NULL
;
2045 ifp
= bridge_dst_lookup(eh
);
2046 bdg_forward(&m0
, ifp
);
2056 * Let interface filters (if any) do their thing ...
2059 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
2060 if (TAILQ_EMPTY(fhead
) == 0) {
2061 while (orig_ifp
!= ifp
) {
2063 TAILQ_FOREACH(tmp
, fhead
, que
) {
2064 if (IFILT(tmp
).filter_if_output
) {
2065 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
2069 if (retval
== EJUSTRETURN
)
2079 if (ifp
!= orig_ifp
)
2086 * Finally, call the driver.
2089 retval
= (*ifp
->if_output
)(ifp
, m
);
2090 dlil_stats
.inject_pr_out2
++;
2091 if ((retval
== 0) || (retval
== EJUSTRETURN
))
2099 dlil_inject_if_output(struct mbuf
*m
, u_long from_id
)
2101 struct ifnet
*orig_ifp
= 0;
2103 struct dlil_filterq_entry
*tmp
;
2105 struct dlil_filterq_head
*fhead
;
2108 dlil_stats
.inject_if_out1
++;
2109 if (from_id
> dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
2112 ifp
= dlil_filters
[from_id
].ifp
;
2115 * Let interface filters (if any) do their thing ...
2118 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
2121 if (TAILQ_EMPTY(fhead
) == 0) {
2122 while (orig_ifp
!= ifp
) {
2124 TAILQ_FOREACH(tmp
, fhead
, que
) {
2125 if ((match_found
) && (IFILT(tmp
).filter_if_output
)) {
2126 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
2130 if (retval
== EJUSTRETURN
)
2140 if (ifp
!= orig_ifp
)
2143 if (from_id
== tmp
->filter_id
)
2150 * Finally, call the driver.
2153 retval
= (*ifp
->if_output
)(ifp
, m
);
2154 dlil_stats
.inject_if_out2
++;
2155 if ((retval
== 0) || (retval
== EJUSTRETURN
))
2162 int dlil_recycle_ioctl(struct ifnet
*ifnet_ptr
, u_long ioctl_code
, void *ioctl_arg
)
2169 int dlil_recycle_output(struct ifnet
*ifnet_ptr
, struct mbuf
*m
)
2177 int dlil_recycle_free(struct ifnet
*ifnet_ptr
)
2183 int dlil_recycle_set_bpf_tap(struct ifnet
*ifp
, int mode
,
2184 int (*bpf_callback
)(struct ifnet
*, struct mbuf
*))
2186 /* XXX not sure what to do here */
2190 int dlil_if_acquire(u_long family
, void *uniqueid
, size_t uniqueid_len
,
2193 struct ifnet
*ifp1
= NULL
;
2194 struct dlil_ifnet
*dlifp1
= NULL
;
2196 boolean_t funnel_state
;
2198 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
2201 TAILQ_FOREACH(dlifp1
, &dlil_ifnet_head
, dl_if_link
) {
2203 ifp1
= (struct ifnet
*)dlifp1
;
2205 if (ifp1
->if_family
== family
) {
2207 /* same uniqueid and same len or no unique id specified */
2208 if ((uniqueid_len
== dlifp1
->if_uniqueid_len
)
2209 && !bcmp(uniqueid
, dlifp1
->if_uniqueid
, uniqueid_len
)) {
2211 /* check for matching interface in use */
2212 if (ifp1
->if_eflags
& IFEF_INUSE
) {
2220 ifp1
->if_eflags
|= (IFEF_INUSE
+ IFEF_REUSE
);
2228 /* no interface found, allocate a new one */
2229 MALLOC(dlifp1
, struct dlil_ifnet
*, sizeof(*dlifp1
), M_NKE
, M_WAITOK
);
2235 bzero(dlifp1
, sizeof(*dlifp1
));
2238 MALLOC(dlifp1
->if_uniqueid
, void *, uniqueid_len
, M_NKE
, M_WAITOK
);
2239 if (dlifp1
->if_uniqueid
== 0) {
2240 FREE(dlifp1
, M_NKE
);
2244 bcopy(uniqueid
, dlifp1
->if_uniqueid
, uniqueid_len
);
2245 dlifp1
->if_uniqueid_len
= uniqueid_len
;
2248 ifp1
= (struct ifnet
*)dlifp1
;
2249 ifp1
->if_eflags
|= IFEF_INUSE
;
2251 TAILQ_INSERT_TAIL(&dlil_ifnet_head
, dlifp1
, dl_if_link
);
2258 thread_funnel_set(network_flock
, funnel_state
);
2262 void dlil_if_release(struct ifnet
*ifp
)
2264 struct dlil_ifnet
*dlifp
= (struct dlil_ifnet
*)ifp
;
2266 boolean_t funnel_state
;
2268 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
2271 ifp
->if_eflags
&= ~IFEF_INUSE
;
2272 ifp
->if_ioctl
= dlil_recycle_ioctl
;
2273 ifp
->if_output
= dlil_recycle_output
;
2274 ifp
->if_free
= dlil_recycle_free
;
2275 ifp
->if_set_bpf_tap
= dlil_recycle_set_bpf_tap
;
2277 strncpy(dlifp
->if_namestorage
, ifp
->if_name
, IFNAMSIZ
);
2278 ifp
->if_name
= dlifp
->if_namestorage
;
2281 thread_funnel_set(network_flock
, funnel_state
);