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/thread.h>
46 #include <kern/task.h>
47 #include <net/netisr.h>
48 #include <net/if_types.h>
51 #define DBG_LAYER_BEG DLILDBG_CODE(DBG_DLIL_STATIC, 0)
52 #define DBG_LAYER_END DLILDBG_CODE(DBG_DLIL_STATIC, 2)
53 #define DBG_FNC_DLIL_INPUT DLILDBG_CODE(DBG_DLIL_STATIC, (1 << 8))
54 #define DBG_FNC_DLIL_OUTPUT DLILDBG_CODE(DBG_DLIL_STATIC, (2 << 8))
55 #define DBG_FNC_DLIL_IFOUT DLILDBG_CODE(DBG_DLIL_STATIC, (3 << 8))
58 #define MAX_DL_TAGS 50
59 #define MAX_DLIL_FILTERS 50
60 #define MAX_FRAME_TYPE_SIZE 4 /* LONGWORDS */
61 #define MAX_LINKADDR 4 /* LONGWORDS */
62 #define M_NKE M_IFADDR
64 #define PFILT(x) ((struct dlil_filterq_entry *) (x))->variants.pr_filter
65 #define IFILT(x) ((struct dlil_filterq_entry *) (x))->variants.if_filter
69 struct if_proto
*proto
;
70 struct dlil_filterq_head
*pr_flt_head
;
74 struct dlil_stats_str
{
86 struct dlil_filter_id_str
{
88 struct dlil_filterq_head
*head
;
89 struct dlil_filterq_entry
*filter_ptr
;
91 struct if_proto
*proto
;
96 struct if_family_str
{
97 TAILQ_ENTRY(if_family_str
) if_fam_next
;
102 #define DLIL_SHUTDOWN 1
104 int (*add_if
)(struct ifnet
*ifp
);
105 int (*del_if
)(struct ifnet
*ifp
);
106 int (*add_proto
)(struct ddesc_head_str
*demux_desc_head
,
107 struct if_proto
*proto
, u_long dl_tag
);
108 int (*del_proto
)(struct if_proto
*proto
, u_long dl_tag
);
109 int (*ifmod_ioctl
)(struct ifnet
*ifp
, u_long command
, caddr_t data
);
115 struct dlil_stats_str dlil_stats
;
118 struct dlil_filter_id_str dlil_filters
[MAX_DLIL_FILTERS
+1];
121 struct dl_tag_str dl_tag_array
[MAX_DL_TAGS
+1];
124 TAILQ_HEAD(, if_family_str
) if_family_head
;
126 static ifnet_inited
= 0;
128 int dlil_initialized
= 0;
129 decl_simple_lock_data(, dlil_input_lock
)
130 int dlil_input_thread_wakeup
= 0;
132 static struct mbuf
*dlil_input_mbuf_head
= NULL
;
133 static struct mbuf
*dlil_input_mbuf_tail
= NULL
;
134 static struct mbuf
*dlil_input_loop_head
= NULL
;
135 static struct mbuf
*dlil_input_loop_tail
= NULL
;
137 static void dlil_input_thread(void);
138 extern void run_netisr(void);
142 * Internal functions.
146 struct if_family_str
*find_family_module(u_long if_family
)
148 struct if_family_str
*mod
= NULL
;
150 TAILQ_FOREACH(mod
, &if_family_head
, if_fam_next
) {
151 if (mod
->if_family
== (if_family
& 0xffff))
163 struct ifnet
*ifbyfamily(u_long family
, short unit
)
167 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
168 if ((family
== ifp
->if_family
) &&
169 (ifp
->if_unit
== unit
))
175 struct if_proto
*dlttoproto(dl_tag
)
178 return dl_tag_array
[dl_tag
].proto
;
182 u_long
ifptodlt(struct ifnet
*ifp
, u_long proto_family
)
184 struct if_proto
*proto
;
185 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
188 TAILQ_FOREACH(proto
, tmp
, next
)
189 if (proto
->ifp
== ifp
)
190 if (proto
->protocol_family
== proto_family
)
191 return proto
->dl_tag
;
197 int dlil_find_dltag(u_long if_family
, short unit
, u_long proto_family
, u_long
*dl_tag
)
201 ifp
= ifbyfamily(if_family
, unit
);
205 *dl_tag
= ifptodlt(ifp
, proto_family
);
207 return EPROTONOSUPPORT
;
213 int dlil_get_next_dl_tag(u_long current_tag
, struct dl_tag_attr_str
*next
)
217 for (i
= (current_tag
+1); i
< MAX_DL_TAGS
; i
++)
218 if (dl_tag_array
[i
].ifp
) {
220 next
->if_flags
= dl_tag_array
[i
].ifp
->if_flags
;
221 next
->if_unit
= dl_tag_array
[i
].ifp
->if_unit
;
222 next
->protocol_family
= dl_tag_array
[i
].proto
->protocol_family
;
223 next
->if_family
= dl_tag_array
[i
].ifp
->if_family
;
228 * If we got here, there are no more entries
240 printf("dlil_init\n");
242 TAILQ_INIT(&if_family_head
);
243 for (i
=0; i
< MAX_DL_TAGS
; i
++)
244 dl_tag_array
[i
].ifp
= 0;
246 for (i
=0; i
< MAX_DLIL_FILTERS
; i
++)
247 dlil_filters
[i
].type
= 0;
249 bzero(&dlil_stats
, sizeof(dlil_stats
));
251 simple_lock_init(&dlil_input_lock
);
254 * Start up the dlil input thread once everything is initialized
256 (void) kernel_thread(kernel_task
, dlil_input_thread
);
260 u_long
get_new_filter_id()
264 for (i
=1; i
< MAX_DLIL_FILTERS
; i
++)
265 if (dlil_filters
[i
].type
== 0)
272 int dlil_attach_interface_filter(struct ifnet
*ifp
,
273 struct dlil_if_flt_str
*if_filter
,
279 struct dlil_filterq_entry
*tmp_ptr
;
280 struct dlil_filterq_entry
*if_filt
;
281 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
282 boolean_t funnel_state
;
285 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
286 bcopy((caddr_t
) if_filter
, (caddr_t
) &tmp_ptr
->variants
.if_filter
,
287 sizeof(struct dlil_if_flt_str
));
289 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
293 if (insertion_point
!= DLIL_LAST_FILTER
) {
294 TAILQ_FOREACH(if_filt
, fhead
, que
)
295 if (insertion_point
== if_filt
->filter_id
) {
296 TAILQ_INSERT_BEFORE(if_filt
, tmp_ptr
, que
);
301 TAILQ_INSERT_TAIL(fhead
, tmp_ptr
, que
);
303 if (*filter_id
= get_new_filter_id()) {
304 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
305 dlil_filters
[*filter_id
].head
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
306 dlil_filters
[*filter_id
].type
= DLIL_IF_FILTER
;
307 dlil_filters
[*filter_id
].ifp
= ifp
;
308 tmp_ptr
->filter_id
= *filter_id
;
309 tmp_ptr
->type
= DLIL_IF_FILTER
;
313 kprintf("dlil_attach_interface_filter - can't alloc filter_id\n");
314 TAILQ_REMOVE(fhead
, tmp_ptr
, que
);
315 FREE(tmp_ptr
, M_NKE
);
320 thread_funnel_set(network_flock
, funnel_state
);
325 int dlil_attach_protocol_filter(u_long dl_tag
,
326 struct dlil_pr_flt_str
*pr_filter
,
330 struct dlil_filterq_entry
*tmp_ptr
;
331 struct dlil_filterq_entry
*pr_filt
;
334 boolean_t funnel_state
;
336 if (dl_tag
> MAX_DL_TAGS
)
339 if (dl_tag_array
[dl_tag
].ifp
== 0)
342 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
343 bcopy((caddr_t
) pr_filter
, (caddr_t
) &tmp_ptr
->variants
.pr_filter
,
344 sizeof(struct dlil_pr_flt_str
));
346 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
349 if (insertion_point
!= DLIL_LAST_FILTER
) {
350 TAILQ_FOREACH(pr_filt
, dl_tag_array
[dl_tag
].pr_flt_head
, que
)
351 if (insertion_point
== pr_filt
->filter_id
) {
352 TAILQ_INSERT_BEFORE(pr_filt
, tmp_ptr
, que
);
357 TAILQ_INSERT_TAIL(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
360 if (*filter_id
= get_new_filter_id()) {
361 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
362 dlil_filters
[*filter_id
].head
= dl_tag_array
[dl_tag
].pr_flt_head
;
363 dlil_filters
[*filter_id
].type
= DLIL_PR_FILTER
;
364 dlil_filters
[*filter_id
].proto
= dl_tag_array
[dl_tag
].proto
;
365 dlil_filters
[*filter_id
].ifp
= dl_tag_array
[dl_tag
].ifp
;
366 tmp_ptr
->filter_id
= *filter_id
;
367 tmp_ptr
->type
= DLIL_PR_FILTER
;
371 kprintf("dlil_attach_protocol_filter - can't alloc filter_id\n");
372 TAILQ_REMOVE(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
373 FREE(tmp_ptr
, M_NKE
);
378 thread_funnel_set(network_flock
, funnel_state
);
384 dlil_detach_filter(u_long filter_id
)
386 struct dlil_filter_id_str
*flt
;
388 boolean_t funnel_state
;
390 if (filter_id
> MAX_DLIL_FILTERS
) {
391 kprintf("dlil_detach_filter - Bad filter_id value %d\n", filter_id
);
395 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
397 flt
= &dlil_filters
[filter_id
];
398 if (flt
->type
== 0) {
399 kprintf("dlil_detach_filter - no such filter_id %d\n", filter_id
);
400 thread_funnel_set(network_flock
, funnel_state
);
405 if (flt
->type
== DLIL_IF_FILTER
) {
406 if (IFILT(flt
->filter_ptr
).filter_detach
)
407 (*IFILT(flt
->filter_ptr
).filter_detach
)(IFILT(flt
->filter_ptr
).cookie
);
410 if (flt
->type
== DLIL_PR_FILTER
) {
411 if (PFILT(flt
->filter_ptr
).filter_detach
)
412 (*PFILT(flt
->filter_ptr
).filter_detach
)(PFILT(flt
->filter_ptr
).cookie
);
416 TAILQ_REMOVE(flt
->head
, flt
->filter_ptr
, que
);
417 FREE(flt
->filter_ptr
, M_NKE
);
420 thread_funnel_set(network_flock
, funnel_state
);
426 dlil_input_thread_continue(void)
429 struct mbuf
*m
, *m_loop
;
432 simple_lock(&dlil_input_lock
);
433 m
= dlil_input_mbuf_head
;
434 dlil_input_mbuf_head
= NULL
;
435 dlil_input_mbuf_tail
= NULL
;
436 m_loop
= dlil_input_loop_head
;
437 dlil_input_loop_head
= NULL
;
438 dlil_input_loop_tail
= NULL
;
439 simple_unlock(&dlil_input_lock
);
442 expand_mcl
= dlil_expand_mcl
;
452 * NOTE warning %%% attention !!!!
453 * We should think about putting some thread starvation safeguards if
454 * we deal with long chains of packets.
457 struct mbuf
*m0
= m
->m_nextpkt
;
458 void *header
= m
->m_pkthdr
.header
;
461 m
->m_pkthdr
.header
= NULL
;
462 (void) dlil_input_packet(m
->m_pkthdr
.rcvif
, m
, header
);
467 struct mbuf
*m0
= m
->m_nextpkt
;
468 void *header
= m
->m_pkthdr
.header
;
469 struct ifnet
*ifp
= (struct ifnet
*) m
->m_pkthdr
.aux
;
472 m
->m_pkthdr
.header
= NULL
;
473 m
->m_pkthdr
.aux
= NULL
;
474 (void) dlil_input_packet(ifp
, m
, header
);
481 if (dlil_input_mbuf_head
== NULL
&&
482 dlil_input_loop_head
== NULL
&&
484 assert_wait(&dlil_input_thread_wakeup
, THREAD_UNINT
);
485 #if defined (__i386__)
488 thread_block(dlil_input_thread_continue
);
495 void dlil_input_thread(void)
497 register thread_t self
= current_thread();
498 extern void stack_privilege(thread_t thread
);
500 printf("dlil_input_thread %x\n", self
);
503 * Make sure that this thread
504 * always has a kernel stack, and
505 * bind it to the master cpu.
507 stack_privilege(self
);
509 /* The dlil thread is always funneled */
510 thread_funnel_set(network_flock
, TRUE
);
511 dlil_initialized
= 1;
512 dlil_input_thread_continue();
516 dlil_input(struct ifnet
*ifp
, struct mbuf
*m_head
, struct mbuf
*m_tail
)
519 * Because of loopbacked multicast we cannot stuff the ifp in
520 * the rcvif of the packet header: loopback has its own dlil
524 simple_lock(&dlil_input_lock
);
525 if (ifp
->if_type
!= IFT_LOOP
) {
526 if (dlil_input_mbuf_head
== NULL
)
527 dlil_input_mbuf_head
= m_head
;
528 else if (dlil_input_mbuf_tail
!= NULL
)
529 dlil_input_mbuf_tail
->m_nextpkt
= m_head
;
530 dlil_input_mbuf_tail
= m_tail
? m_tail
: m_head
;
532 if (dlil_input_loop_head
== NULL
)
533 dlil_input_loop_head
= m_head
;
534 else if (dlil_input_loop_tail
!= NULL
)
535 dlil_input_loop_tail
->m_nextpkt
= m_head
;
536 dlil_input_loop_tail
= m_tail
? m_tail
: m_head
;
538 simple_unlock(&dlil_input_lock
);
540 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
546 dlil_input_packet(struct ifnet
*ifp
, struct mbuf
*m
,
549 struct ifnet
*orig_ifp
= 0;
550 struct dlil_filterq_entry
*tmp
;
552 struct if_proto
*ifproto
= 0;
553 struct if_proto
*proto
;
554 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
557 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_START
,0,0,0,0,0);
560 * Run interface filters
563 while (orig_ifp
!= ifp
) {
566 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
567 if (IFILT(tmp
).filter_if_input
) {
568 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
573 if (retval
== EJUSTRETURN
)
587 ifp
->if_lastchange
= time
;
590 * Call family demux module. If the demux module finds a match
591 * for the frame it will fill-in the ifproto pointer.
594 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
596 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
599 if ((retval
) && (retval
!= EJUSTRETURN
) && (ifp
->offercnt
)) {
601 * No match was found, look for any offers.
603 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
604 TAILQ_FOREACH(proto
, tmp
, next
) {
605 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
614 if (retval
!= EJUSTRETURN
) {
623 printf("ERROR - dlil_input - if_demux didn't return an if_proto pointer\n");
629 * Call any attached protocol filters.
632 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
633 if (PFILT(tmp
).filter_dl_input
) {
634 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
640 if (retval
== EJUSTRETURN
)
652 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
653 ifp
, ifproto
->dl_tag
,
656 if (retval
== EJUSTRETURN
)
662 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_END
,0,0,0,0,0);
668 void ether_input(ifp
, eh
, m
)
670 struct ether_header
*eh
;
674 kprintf("Someone is calling ether_input!!\n");
676 dlil_input(ifp
, m
, NULL
);
681 dlil_event(struct ifnet
*ifp
, struct kern_event_msg
*event
)
683 struct dlil_filterq_entry
*filt
;
685 struct ifnet
*orig_ifp
= 0;
686 struct if_proto
*proto
;
687 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
688 struct kev_msg kev_msg
;
689 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
690 boolean_t funnel_state
;
693 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
695 while (orig_ifp
!= ifp
) {
698 TAILQ_FOREACH_REVERSE(filt
, fhead
, que
, dlil_filterq_head
) {
699 if (IFILT(filt
).filter_if_event
) {
700 retval
= (*IFILT(filt
).filter_if_event
)(IFILT(filt
).cookie
,
705 (void) thread_funnel_set(network_flock
, funnel_state
);
706 if (retval
== EJUSTRETURN
)
720 * Call Interface Module event hook, if any.
724 retval
= ifp
->if_event(ifp
, (caddr_t
) event
);
727 (void) thread_funnel_set(network_flock
, funnel_state
);
729 if (retval
== EJUSTRETURN
)
737 * Call dl_event entry point for all protocols attached to this interface
740 TAILQ_FOREACH(proto
, tmp
, next
) {
742 * Call any attached protocol filters.
745 TAILQ_FOREACH_REVERSE(filt
, &proto
->pr_flt_head
, que
, dlil_filterq_head
) {
746 if (PFILT(filt
).filter_dl_event
) {
747 retval
= (*PFILT(filt
).filter_dl_event
)(PFILT(filt
).cookie
,
751 (void) thread_funnel_set(network_flock
, funnel_state
);
752 if (retval
== EJUSTRETURN
)
762 * Finally, call the dl_event entry point (if any)
766 retval
= (*proto
->dl_event
)(event
, proto
->dl_tag
);
768 if (retval
== EJUSTRETURN
) {
769 (void) thread_funnel_set(network_flock
, funnel_state
);
776 * Now, post this event to the Kernel Event message queue
779 kev_msg
.vendor_code
= event
->vendor_code
;
780 kev_msg
.kev_class
= event
->kev_class
;
781 kev_msg
.kev_subclass
= event
->kev_subclass
;
782 kev_msg
.event_code
= event
->event_code
;
783 kev_msg
.dv
[0].data_ptr
= &event
->event_data
[0];
784 kev_msg
.dv
[0].data_length
= event
->total_size
- KEV_MSG_HEADER_SIZE
;
785 kev_msg
.dv
[1].data_length
= 0;
787 kev_post_msg(&kev_msg
);
789 (void) thread_funnel_set(network_flock
, funnel_state
);
796 dlil_output(u_long dl_tag
,
799 struct sockaddr
*dest
,
805 struct ifnet
*orig_ifp
= 0;
807 struct if_proto
*proto
;
808 struct dlil_filterq_entry
*tmp
;
810 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
811 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
812 struct dlil_filterq_head
*fhead
;
815 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_START
,0,0,0,0,0);
818 * Temporary hackery until all the existing protocols can become fully
819 * "dl_tag aware". Some things only have the ifp, so this handles that
820 * case for the time being.
823 if (dl_tag
> MAX_DL_TAGS
) {
824 /* dl_tag is really an ifnet pointer! */
826 ifp
= (struct ifnet
*) dl_tag
;
827 dl_tag
= ifp
->if_data
.default_proto
;
829 proto
= dl_tag_array
[dl_tag
].proto
;
834 if ((dl_tag
== 0) || (dl_tag_array
[dl_tag
].ifp
== 0))
837 ifp
= dl_tag_array
[dl_tag
].ifp
;
838 proto
= dl_tag_array
[dl_tag
].proto
;
847 frame_type
= frame_type_buffer
;
848 dst_linkaddr
= dst_linkaddr_buffer
;
850 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
852 if ((raw
== 0) && (proto
->dl_pre_output
)) {
853 retval
= (*proto
->dl_pre_output
)(ifp
, &m
, dest
, route
,
854 frame_type
, dst_linkaddr
, dl_tag
);
856 if (retval
== EJUSTRETURN
)
866 * Run any attached protocol filters.
869 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
870 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
871 if (PFILT(tmp
).filter_dl_output
) {
872 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
873 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
875 if (retval
== EJUSTRETURN
)
888 * Call framing module
890 if ((raw
== 0) && (ifp
->if_framer
)) {
891 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
893 if (retval
== EJUSTRETURN
)
905 struct mbuf
*m0
= m
;
907 if (m
->m_pkthdr
.rcvif
)
908 m
->m_pkthdr
.rcvif
= NULL
;
909 ifp
= bridge_dst_lookup(m
);
910 bdg_forward(&m0
, ifp
);
920 * Let interface filters (if any) do their thing ...
923 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
924 if (TAILQ_EMPTY(fhead
) == 0) {
925 while (orig_ifp
!= ifp
) {
927 TAILQ_FOREACH(tmp
, fhead
, que
) {
928 if (IFILT(tmp
).filter_if_output
) {
929 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
933 if (retval
== EJUSTRETURN
)
950 * Finally, call the driver.
953 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_START
, 0,0,0,0,0);
954 retval
= (*ifp
->if_output
)(ifp
, m
);
955 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_END
, 0,0,0,0,0);
957 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_END
,0,0,0,0,0);
959 if ((retval
== 0) || (retval
== EJUSTRETURN
))
967 dlil_ioctl(u_long proto_fam
,
972 struct dlil_filterq_entry
*tmp
;
973 struct dlil_filterq_head
*fhead
;
974 int retval
= EOPNOTSUPP
;
975 int retval2
= EOPNOTSUPP
;
977 struct if_family_str
*if_family
;
981 retval
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
,
985 if (dl_tag_array
[dl_tag
].ifp
!= ifp
)
989 * Run any attached protocol filters.
991 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
992 if (PFILT(tmp
).filter_dl_ioctl
) {
994 (*PFILT(tmp
).filter_dl_ioctl
)(PFILT(tmp
).cookie
,
995 dl_tag_array
[dl_tag
].ifp
,
1000 if (retval
== EJUSTRETURN
)
1008 if (dl_tag_array
[dl_tag
].proto
->dl_ioctl
)
1010 (*dl_tag_array
[dl_tag
].proto
->dl_ioctl
)(dl_tag
,
1011 dl_tag_array
[dl_tag
].ifp
,
1015 retval
= EOPNOTSUPP
;
1021 if ((retval
) && (retval
!= EOPNOTSUPP
)) {
1022 if (retval
== EJUSTRETURN
)
1029 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1030 TAILQ_FOREACH(tmp
, fhead
, que
) {
1031 if (IFILT(tmp
).filter_if_ioctl
) {
1032 retval2
= (*IFILT(tmp
).filter_if_ioctl
)(IFILT(tmp
).cookie
, ifp
,
1033 ioctl_code
, ioctl_arg
);
1035 if (retval2
== EJUSTRETURN
)
1044 if_family
= find_family_module(ifp
->if_family
);
1045 if ((if_family
) && (if_family
->ifmod_ioctl
)) {
1046 retval2
= (*if_family
->ifmod_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1048 if ((retval2
) && (retval2
!= EOPNOTSUPP
)) {
1049 if (retval2
== EJUSTRETURN
)
1055 if (retval
== EOPNOTSUPP
)
1060 retval2
= (*ifp
->if_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1062 if (retval
== EOPNOTSUPP
)
1065 if (retval2
== EOPNOTSUPP
)
1074 dlil_attach_protocol(struct dlil_proto_reg_str
*proto
,
1078 struct if_proto
*ifproto
;
1080 struct if_family_str
*if_family
;
1082 struct dlil_proto_head
*tmp
;
1084 boolean_t funnel_state
;
1087 if ((proto
->protocol_family
== 0) || (proto
->interface_family
== 0))
1090 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1092 if_family
= find_family_module(proto
->interface_family
);
1093 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1094 kprintf("dlil_attach_protocol -- no interface family module %d",
1095 proto
->interface_family
);
1097 thread_funnel_set(network_flock
, funnel_state
);
1101 ifp
= ifbyfamily(proto
->interface_family
, proto
->unit_number
);
1103 kprintf("dlil_attach_protocol -- no such interface %d unit %d\n",
1104 proto
->interface_family
, proto
->unit_number
);
1106 thread_funnel_set(network_flock
, funnel_state
);
1110 if (dlil_find_dltag(proto
->interface_family
, proto
->unit_number
,
1111 proto
->protocol_family
, &i
) == 0) {
1112 thread_funnel_set(network_flock
, funnel_state
);
1116 for (i
=1; i
< MAX_DL_TAGS
; i
++)
1117 if (dl_tag_array
[i
].ifp
== 0)
1120 if (i
>= MAX_DL_TAGS
) {
1122 thread_funnel_set(network_flock
, funnel_state
);
1127 * Allocate and init a new if_proto structure
1130 ifproto
= _MALLOC(sizeof(struct if_proto
), M_IFADDR
, M_WAITOK
);
1132 printf("ERROR - DLIL failed if_proto allocation\n");
1133 thread_funnel_set(network_flock
, funnel_state
);
1137 bzero(ifproto
, sizeof(struct if_proto
));
1139 dl_tag_array
[i
].ifp
= ifp
;
1140 dl_tag_array
[i
].proto
= ifproto
;
1141 dl_tag_array
[i
].pr_flt_head
= &ifproto
->pr_flt_head
;
1142 ifproto
->dl_tag
= i
;
1145 if (proto
->default_proto
) {
1146 if (ifp
->if_data
.default_proto
== 0)
1147 ifp
->if_data
.default_proto
= i
;
1149 printf("ERROR - dlil_attach_protocol -- Attempt to attach more than one default protocol\n");
1152 ifproto
->protocol_family
= proto
->protocol_family
;
1153 ifproto
->dl_input
= proto
->input
;
1154 ifproto
->dl_pre_output
= proto
->pre_output
;
1155 ifproto
->dl_event
= proto
->event
;
1156 ifproto
->dl_offer
= proto
->offer
;
1157 ifproto
->dl_ioctl
= proto
->ioctl
;
1159 TAILQ_INIT(&ifproto
->pr_flt_head
);
1162 * Call family module add_proto routine so it can refine the
1163 * demux descriptors as it wishes.
1165 error
= (*if_family
->add_proto
)(&proto
->demux_desc_head
, ifproto
, *dl_tag
);
1167 dl_tag_array
[*dl_tag
].ifp
= 0;
1168 FREE(ifproto
, M_IFADDR
);
1170 thread_funnel_set(network_flock
, funnel_state
);
1176 * Add to if_proto list for this interface
1179 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1180 TAILQ_INSERT_TAIL(tmp
, ifproto
, next
);
1182 if (ifproto
->dl_offer
)
1186 thread_funnel_set(network_flock
, funnel_state
);
1193 dlil_detach_protocol(u_long dl_tag
)
1196 struct ifnet
*orig_ifp
=0;
1197 struct if_proto
*proto
;
1198 struct dlil_proto_head
*tmp
;
1199 struct if_family_str
*if_family
;
1200 struct dlil_filterq_entry
*filter
;
1202 struct dlil_filterq_head
*fhead
;
1203 struct kev_msg ev_msg
;
1204 struct net_event_data ev_data
;
1205 boolean_t funnel_state
;
1208 if (dl_tag
> MAX_DL_TAGS
)
1211 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1214 if (dl_tag_array
[dl_tag
].ifp
== 0) {
1216 thread_funnel_set(network_flock
, funnel_state
);
1220 ifp
= dl_tag_array
[dl_tag
].ifp
;
1221 proto
= dl_tag_array
[dl_tag
].proto
;
1223 if_family
= find_family_module(ifp
->if_family
);
1224 if (if_family
== NULL
) {
1226 thread_funnel_set(network_flock
, funnel_state
);
1230 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1233 * Call family module del_proto
1236 (*if_family
->del_proto
)(proto
, dl_tag
);
1240 * Remove and deallocate any attached protocol filters
1243 while (filter
= TAILQ_FIRST(&proto
->pr_flt_head
))
1244 dlil_detach_filter(filter
->filter_id
);
1246 if (proto
->dl_offer
)
1249 dl_tag_array
[dl_tag
].ifp
= 0;
1251 TAILQ_REMOVE(tmp
, proto
, next
);
1252 FREE(proto
, M_IFADDR
);
1254 if (--ifp
->refcnt
== 0) {
1255 if (ifp
->if_flags
& IFF_UP
)
1256 printf("WARNING - dlil_detach_protocol - ifp refcnt 0, but IF still up\n");
1258 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1260 (*if_family
->del_if
)(ifp
);
1262 if (--if_family
->refcnt
== 0) {
1263 if (if_family
->shutdown
)
1264 (*if_family
->shutdown
)();
1266 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1267 FREE(if_family
, M_IFADDR
);
1270 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1271 while (orig_ifp
!= ifp
) {
1274 TAILQ_FOREACH(filter
, fhead
, que
) {
1275 if (IFILT(filter
).filter_if_free
) {
1276 retval
= (*IFILT(filter
).filter_if_free
)(IFILT(filter
).cookie
, ifp
);
1279 thread_funnel_set(network_flock
, funnel_state
);
1283 if (ifp
!= orig_ifp
)
1288 (*ifp
->if_free
)(ifp
);
1290 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
1291 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
1292 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
1294 ev_msg
.event_code
= KEV_DL_IF_DETACHED
;
1295 strncpy(&ev_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
1296 ev_data
.if_family
= ifp
->if_family
;
1297 ev_data
.if_unit
= (unsigned long) ifp
->if_unit
;
1299 ev_msg
.dv
[0].data_length
= sizeof(struct net_event_data
);
1300 ev_msg
.dv
[0].data_ptr
= &ev_data
;
1301 ev_msg
.dv
[1].data_length
= 0;
1303 kev_post_msg(&ev_msg
);
1307 thread_funnel_set(network_flock
, funnel_state
);
1316 dlil_if_attach(struct ifnet
*ifp
)
1318 u_long interface_family
= ifp
->if_family
;
1319 struct if_family_str
*if_family
;
1320 struct dlil_proto_head
*tmp
;
1323 struct kev_msg ev_msg
;
1324 struct net_event_data ev_data
;
1325 boolean_t funnel_state
;
1327 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1329 if (ifnet_inited
== 0) {
1334 if_family
= find_family_module(interface_family
);
1336 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1338 kprintf("Attempt to attach interface without family module - %d\n",
1340 thread_funnel_set(network_flock
, funnel_state
);
1346 * Call the family module to fill in the appropriate fields in the
1350 stat
= (*if_family
->add_if
)(ifp
);
1353 kprintf("dlil_if_attach -- add_if failed with %d\n", stat
);
1354 thread_funnel_set(network_flock
, funnel_state
);
1359 * Add the ifp to the interface list.
1362 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1365 ifp
->if_data
.default_proto
= 0;
1368 TAILQ_INIT(&ifp
->if_flt_head
);
1370 if_family
->refcnt
++;
1372 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
1373 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
1374 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
1376 ev_msg
.event_code
= KEV_DL_IF_ATTACHED
;
1377 strncpy(&ev_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
1378 ev_data
.if_family
= ifp
->if_family
;
1379 ev_data
.if_unit
= (unsigned long) ifp
->if_unit
;
1381 ev_msg
.dv
[0].data_length
= sizeof(struct net_event_data
);
1382 ev_msg
.dv
[0].data_ptr
= &ev_data
;
1384 ev_msg
.dv
[1].data_length
= 0;
1386 kev_post_msg(&ev_msg
);
1389 thread_funnel_set(network_flock
, funnel_state
);
1395 dlil_if_detach(struct ifnet
*ifp
)
1397 struct if_proto
*proto
;
1398 struct dlil_filterq_entry
*if_filter
;
1399 struct if_family_str
*if_family
;
1400 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1402 struct kev_msg ev_msg
;
1403 struct net_event_data ev_data
;
1404 boolean_t funnel_state
;
1406 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1408 if (ifp
->if_flags
& IFF_UP
)
1409 printf("WARNING - dlil_if_detach called for UP interface\n");
1411 if_family
= find_family_module(ifp
->if_family
);
1414 kprintf("Attempt to detach interface without family module - %s\n",
1417 thread_funnel_set(network_flock
, funnel_state
);
1421 while (if_filter
= TAILQ_FIRST(fhead
))
1422 dlil_detach_filter(if_filter
->filter_id
);
1424 if (--ifp
->refcnt
== 0) {
1425 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1427 (*if_family
->del_if
)(ifp
);
1429 if (--if_family
->refcnt
== 0) {
1430 if (if_family
->shutdown
)
1431 (*if_family
->shutdown
)();
1433 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1434 FREE(if_family
, M_IFADDR
);
1437 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
1438 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
1439 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
1441 ev_msg
.event_code
= KEV_DL_IF_DETACHED
;
1442 strncpy(&ev_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
1443 ev_data
.if_family
= ifp
->if_family
;
1444 ev_data
.if_unit
= (unsigned long) ifp
->if_unit
;
1446 ev_msg
.dv
[0].data_length
= sizeof(struct net_event_data
);
1447 ev_msg
.dv
[0].data_ptr
= &ev_data
;
1449 ev_msg
.dv
[1].data_length
= 0;
1450 kev_post_msg(&ev_msg
);
1452 thread_funnel_set(network_flock
, funnel_state
);
1457 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
1458 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
1459 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
1461 ev_msg
.event_code
= KEV_DL_IF_DETACHING
;
1462 strncpy(&ev_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
1463 ev_data
.if_family
= ifp
->if_family
;
1464 ev_data
.if_unit
= (unsigned long) ifp
->if_unit
;
1465 ev_msg
.dv
[0].data_length
= sizeof(struct net_event_data
);
1466 ev_msg
.dv
[0].data_ptr
= &ev_data
;
1467 ev_msg
.dv
[1].data_length
= 0;
1469 kev_post_msg(&ev_msg
);
1472 thread_funnel_set(network_flock
, funnel_state
);
1473 return DLIL_WAIT_FOR_FREE
;
1479 dlil_reg_if_modules(u_long interface_family
,
1480 struct dlil_ifmod_reg_str
*ifmod
)
1482 struct if_family_str
*if_family
;
1484 boolean_t funnel_state
;
1487 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1489 if (find_family_module(interface_family
)) {
1490 kprintf("Attempt to register dlil family module more than once - %d\n",
1493 thread_funnel_set(network_flock
, funnel_state
);
1497 if ((!ifmod
->add_if
) || (!ifmod
->del_if
) ||
1498 (!ifmod
->add_proto
) || (!ifmod
->del_proto
)) {
1499 kprintf("dlil_reg_if_modules passed at least one null pointer\n");
1501 thread_funnel_set(network_flock
, funnel_state
);
1505 if_family
= (struct if_family_str
*) _MALLOC(sizeof(struct if_family_str
), M_IFADDR
, M_WAITOK
);
1507 kprintf("dlil_reg_if_modules failed allocation\n");
1509 thread_funnel_set(network_flock
, funnel_state
);
1513 bzero(if_family
, sizeof(struct if_family_str
));
1515 if_family
->if_family
= interface_family
& 0xffff;
1516 if_family
->shutdown
= ifmod
->shutdown
;
1517 if_family
->add_if
= ifmod
->add_if
;
1518 if_family
->del_if
= ifmod
->del_if
;
1519 if_family
->add_proto
= ifmod
->add_proto
;
1520 if_family
->del_proto
= ifmod
->del_proto
;
1521 if_family
->ifmod_ioctl
= ifmod
->ifmod_ioctl
;
1522 if_family
->refcnt
= 1;
1523 if_family
->flags
= 0;
1525 TAILQ_INSERT_TAIL(&if_family_head
, if_family
, if_fam_next
);
1527 thread_funnel_set(network_flock
, funnel_state
);
1531 int dlil_dereg_if_modules(u_long interface_family
)
1533 struct if_family_str
*if_family
;
1535 boolean_t funnel_state
;
1537 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1539 if_family
= find_family_module(interface_family
);
1540 if (if_family
== 0) {
1542 thread_funnel_set(network_flock
, funnel_state
);
1546 if (--if_family
->refcnt
== 0) {
1547 if (if_family
->shutdown
)
1548 (*if_family
->shutdown
)();
1550 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1551 FREE(if_family
, M_IFADDR
);
1554 if_family
->flags
|= DLIL_SHUTDOWN
;
1557 thread_funnel_set(network_flock
, funnel_state
);
1566 * Old if_attach no-op'ed function defined here for temporary backwards compatibility
1572 dlil_if_attach(ifp
);
1578 dlil_inject_if_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1580 struct ifnet
*orig_ifp
= 0;
1582 struct if_proto
*ifproto
;
1583 struct if_proto
*proto
;
1584 struct dlil_filterq_entry
*tmp
;
1586 struct dlil_filterq_head
*fhead
;
1590 dlil_stats
.inject_if_in1
++;
1591 if (from_id
> MAX_DLIL_FILTERS
)
1594 if (dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1597 ifp
= dlil_filters
[from_id
].ifp
;
1600 * Let interface filters (if any) do their thing ...
1603 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1606 if (TAILQ_EMPTY(fhead
) == 0) {
1607 while (orig_ifp
!= ifp
) {
1609 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
1610 if ((match_found
) && (IFILT(tmp
).filter_if_input
)) {
1611 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
1616 if (retval
== EJUSTRETURN
)
1626 if (ifp
!= orig_ifp
)
1629 if (from_id
== tmp
->filter_id
)
1635 ifp
->if_lastchange
= time
;
1638 * Call family demux module. If the demux module finds a match
1639 * for the frame it will fill-in the ifproto pointer.
1642 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
1644 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
1647 if ((retval
) && (ifp
->offercnt
)) {
1649 * No match was found, look for any offers.
1651 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1652 TAILQ_FOREACH(proto
, tmp
, next
) {
1653 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
1662 if (retval
!= EJUSTRETURN
) {
1671 printf("ERROR - dlil_inject_if_input -- if_demux didn't return an if_proto pointer\n");
1677 * Call any attached protocol filters.
1679 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1680 if (PFILT(tmp
).filter_dl_input
) {
1681 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1687 if (retval
== EJUSTRETURN
)
1699 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1700 ifp
, ifproto
->dl_tag
,
1703 dlil_stats
.inject_if_in2
++;
1704 if (retval
== EJUSTRETURN
)
1719 dlil_inject_pr_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1721 struct ifnet
*orig_ifp
= 0;
1722 struct dlil_filterq_entry
*tmp
;
1724 struct if_proto
*ifproto
= 0;
1729 dlil_stats
.inject_pr_in1
++;
1730 if (from_id
> MAX_DLIL_FILTERS
)
1733 if (dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1736 ifproto
= dlil_filters
[from_id
].proto
;
1737 ifp
= dlil_filters
[from_id
].ifp
;
1741 * Call any attached protocol filters.
1745 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1746 if ((match_found
) && (PFILT(tmp
).filter_dl_input
)) {
1747 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1753 if (retval
== EJUSTRETURN
)
1762 if (tmp
->filter_id
== from_id
)
1767 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1768 ifp
, ifproto
->dl_tag
,
1771 if (retval
== EJUSTRETURN
)
1777 dlil_stats
.inject_pr_in2
++;
1784 dlil_inject_pr_output(struct mbuf
*m
,
1785 struct sockaddr
*dest
,
1791 struct ifnet
*orig_ifp
= 0;
1793 struct dlil_filterq_entry
*tmp
;
1795 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
1796 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
1797 struct dlil_filterq_head
*fhead
;
1802 dlil_stats
.inject_pr_out1
++;
1805 bcopy(frame_type
, &frame_type_buffer
[0], MAX_FRAME_TYPE_SIZE
* 4);
1810 bcopy(dst_linkaddr
, &dst_linkaddr_buffer
, MAX_LINKADDR
* 4);
1815 if (from_id
> MAX_DLIL_FILTERS
)
1818 if (dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1821 ifp
= dlil_filters
[from_id
].ifp
;
1822 dl_tag
= dlil_filters
[from_id
].proto
->dl_tag
;
1825 frame_type
= frame_type_buffer
;
1826 dst_linkaddr
= dst_linkaddr_buffer
;
1828 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1831 * Run any attached protocol filters.
1835 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
1836 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1837 if ((match_found
) && (PFILT(tmp
).filter_dl_output
)) {
1838 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
1839 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
1841 if (retval
== EJUSTRETURN
)
1850 if (tmp
->filter_id
== from_id
)
1857 * Call framing module
1859 if ((raw
== 0) && (ifp
->if_framer
)) {
1860 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
1862 if (retval
== EJUSTRETURN
)
1875 struct mbuf
*m0
= m
;
1877 if (m
->m_pkthdr
.rcvif
)
1878 m
->m_pkthdr
.rcvif
= NULL
;
1879 ifp
= bridge_dst_lookup(m
);
1880 bdg_forward(&m0
, ifp
);
1890 * Let interface filters (if any) do their thing ...
1893 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1894 if (TAILQ_EMPTY(fhead
) == 0) {
1895 while (orig_ifp
!= ifp
) {
1897 TAILQ_FOREACH(tmp
, fhead
, que
) {
1898 if (IFILT(tmp
).filter_if_output
) {
1899 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1903 if (retval
== EJUSTRETURN
)
1913 if (ifp
!= orig_ifp
)
1920 * Finally, call the driver.
1923 retval
= (*ifp
->if_output
)(ifp
, m
);
1924 dlil_stats
.inject_pr_out2
++;
1925 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1933 dlil_inject_if_output(struct mbuf
*m
, u_long from_id
)
1935 struct ifnet
*orig_ifp
= 0;
1937 struct dlil_filterq_entry
*tmp
;
1939 struct dlil_filterq_head
*fhead
;
1943 dlil_stats
.inject_if_out1
++;
1944 if (from_id
> MAX_DLIL_FILTERS
)
1947 if (dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1950 ifp
= dlil_filters
[from_id
].ifp
;
1953 * Let interface filters (if any) do their thing ...
1956 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1959 if (TAILQ_EMPTY(fhead
) == 0) {
1960 while (orig_ifp
!= ifp
) {
1962 TAILQ_FOREACH(tmp
, fhead
, que
) {
1963 if ((match_found
) && (IFILT(tmp
).filter_if_output
)) {
1964 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1968 if (retval
== EJUSTRETURN
)
1978 if (ifp
!= orig_ifp
)
1981 if (from_id
== tmp
->filter_id
)
1988 * Finally, call the driver.
1991 retval
= (*ifp
->if_output
)(ifp
, m
);
1992 dlil_stats
.inject_if_out2
++;
1993 if ((retval
== 0) || (retval
== EJUSTRETURN
))