2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1999 Apple Computer, Inc.
28 * Data Link Inteface Layer
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
39 #include <sys/socket.h>
40 #include <net/if_dl.h>
42 #include <net/if_var.h>
44 #include <sys/kern_event.h>
45 #include <sys/kdebug.h>
48 #include <kern/task.h>
49 #include <kern/thread.h>
50 #include <kern/sched_prim.h>
52 #include <net/netisr.h>
53 #include <net/if_types.h>
55 #include <machine/machine_routines.h>
57 #define DBG_LAYER_BEG DLILDBG_CODE(DBG_DLIL_STATIC, 0)
58 #define DBG_LAYER_END DLILDBG_CODE(DBG_DLIL_STATIC, 2)
59 #define DBG_FNC_DLIL_INPUT DLILDBG_CODE(DBG_DLIL_STATIC, (1 << 8))
60 #define DBG_FNC_DLIL_OUTPUT DLILDBG_CODE(DBG_DLIL_STATIC, (2 << 8))
61 #define DBG_FNC_DLIL_IFOUT DLILDBG_CODE(DBG_DLIL_STATIC, (3 << 8))
64 #define MAX_DL_TAGS 16
65 #define MAX_DLIL_FILTERS 16
66 #define MAX_FRAME_TYPE_SIZE 4 /* LONGWORDS */
67 #define MAX_LINKADDR 4 /* LONGWORDS */
68 #define M_NKE M_IFADDR
70 #define PFILT(x) ((struct dlil_filterq_entry *) (x))->variants.pr_filter
71 #define IFILT(x) ((struct dlil_filterq_entry *) (x))->variants.if_filter
75 struct if_proto
*proto
;
76 struct dlil_filterq_head
*pr_flt_head
;
81 /* ifnet and drvr_ext are used by the stack and drivers
82 drvr_ext extends the public ifnet and must follow dl_if */
83 struct ifnet dl_if
; /* public ifnet */
84 void *drvr_ext
[4]; /* driver reserved (e.g arpcom extension for enet) */
86 /* dlil private fields */
87 TAILQ_ENTRY(dlil_ifnet
) dl_if_link
; /* dlil_ifnet are link together */
88 /* it is not the ifnet list */
89 void *if_uniqueid
; /* unique id identifying the interface */
90 size_t if_uniqueid_len
;/* length of the unique id */
91 char if_namestorage
[IFNAMSIZ
]; /* interface name storage for detached interfaces */
94 struct dlil_stats_str
{
106 struct dlil_filter_id_str
{
108 struct dlil_filterq_head
*head
;
109 struct dlil_filterq_entry
*filter_ptr
;
111 struct if_proto
*proto
;
116 struct if_family_str
{
117 TAILQ_ENTRY(if_family_str
) if_fam_next
;
122 #define DLIL_SHUTDOWN 1
124 int (*add_if
)(struct ifnet
*ifp
);
125 int (*del_if
)(struct ifnet
*ifp
);
126 int (*init_if
)(struct ifnet
*ifp
);
127 int (*add_proto
)(struct ddesc_head_str
*demux_desc_head
,
128 struct if_proto
*proto
, u_long dl_tag
);
129 int (*del_proto
)(struct if_proto
*proto
, u_long dl_tag
);
130 int (*ifmod_ioctl
)(struct ifnet
*ifp
, u_long command
, caddr_t data
);
136 struct dlil_stats_str dlil_stats
;
139 struct dlil_filter_id_str
*dlil_filters
;
142 struct dl_tag_str
*dl_tag_array
;
145 TAILQ_HEAD(, dlil_ifnet
) dlil_ifnet_head
;
148 TAILQ_HEAD(, if_family_str
) if_family_head
;
150 static ifnet_inited
= 0;
151 static u_long dl_tag_nb
= 0;
152 static u_long dlil_filters_nb
= 0;
154 int dlil_initialized
= 0;
155 decl_simple_lock_data(, dlil_input_lock
)
156 int dlil_input_thread_wakeup
= 0;
158 static struct mbuf
*dlil_input_mbuf_head
= NULL
;
159 static struct mbuf
*dlil_input_mbuf_tail
= NULL
;
161 #error dlil_input() needs to be revised to support more than on loopback interface
163 static struct mbuf
*dlil_input_loop_head
= NULL
;
164 static struct mbuf
*dlil_input_loop_tail
= NULL
;
166 static void dlil_input_thread(void);
167 extern void run_netisr(void);
168 extern void bpfdetach(struct ifnet
*);
172 * Internal functions.
176 struct if_family_str
*find_family_module(u_long if_family
)
178 struct if_family_str
*mod
= NULL
;
180 TAILQ_FOREACH(mod
, &if_family_head
, if_fam_next
) {
181 if (mod
->if_family
== (if_family
& 0xffff))
193 struct ifnet
*ifbyfamily(u_long family
, short unit
)
197 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
198 if ((family
== ifp
->if_family
) &&
199 (ifp
->if_unit
== unit
))
205 struct if_proto
*dlttoproto(u_long dl_tag
)
207 if (dl_tag
< dl_tag_nb
&& dl_tag_array
[dl_tag
].ifp
)
208 return dl_tag_array
[dl_tag
].proto
;
213 static int dlil_ifp_proto_count(struct ifnet
* ifp
)
216 struct if_proto
* proto
;
217 struct dlil_proto_head
* tmp
;
219 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
221 TAILQ_FOREACH(proto
, tmp
, next
)
227 u_long
ifptodlt(struct ifnet
*ifp
, u_long proto_family
)
229 struct if_proto
*proto
;
230 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
233 TAILQ_FOREACH(proto
, tmp
, next
)
234 if (proto
->protocol_family
== proto_family
)
235 return proto
->dl_tag
;
241 int dlil_find_dltag(u_long if_family
, short unit
, u_long proto_family
, u_long
*dl_tag
)
245 ifp
= ifbyfamily(if_family
, unit
);
249 *dl_tag
= ifptodlt(ifp
, proto_family
);
251 return EPROTONOSUPPORT
;
257 void dlil_post_msg(struct ifnet
*ifp
, u_long event_subclass
, u_long event_code
,
258 struct net_event_data
*event_data
, u_long event_data_len
)
260 struct net_event_data ev_data
;
261 struct kev_msg ev_msg
;
264 * a net event always start with a net_event_data structure
265 * but the caller can generate a simple net event or
266 * provide a longer event structure to post
269 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
270 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
271 ev_msg
.kev_subclass
= event_subclass
;
272 ev_msg
.event_code
= event_code
;
274 if (event_data
== 0) {
275 event_data
= &ev_data
;
276 event_data_len
= sizeof(struct net_event_data
);
279 strncpy(&event_data
->if_name
[0], ifp
->if_name
, IFNAMSIZ
);
280 event_data
->if_family
= ifp
->if_family
;
281 event_data
->if_unit
= (unsigned long) ifp
->if_unit
;
283 ev_msg
.dv
[0].data_length
= event_data_len
;
284 ev_msg
.dv
[0].data_ptr
= event_data
;
285 ev_msg
.dv
[1].data_length
= 0;
287 kev_post_msg(&ev_msg
);
297 TAILQ_INIT(&dlil_ifnet_head
);
298 TAILQ_INIT(&if_family_head
);
300 // create the dl tag array
301 MALLOC(dl_tag_array
, void *, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
, M_NKE
, M_WAITOK
);
302 if (dl_tag_array
== 0) {
303 printf("dlil_init tags array allocation failed\n");
306 bzero(dl_tag_array
, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
);
307 dl_tag_nb
= MAX_DL_TAGS
;
309 // create the dl filters array
310 MALLOC(dlil_filters
, void *, sizeof(struct dlil_filter_id_str
) * MAX_DLIL_FILTERS
, M_NKE
, M_WAITOK
);
311 if (dlil_filters
== 0) {
312 printf("dlil_init filters array allocation failed\n");
315 bzero(dlil_filters
, sizeof(struct dlil_filter_id_str
) * MAX_DLIL_FILTERS
);
316 dlil_filters_nb
= MAX_DLIL_FILTERS
;
318 bzero(&dlil_stats
, sizeof(dlil_stats
));
320 simple_lock_init(&dlil_input_lock
);
323 * Start up the dlil input thread once everything is initialized
325 (void) kernel_thread(kernel_task
, dlil_input_thread
);
328 u_long
get_new_filter_id()
333 for (i
=1; i
< dlil_filters_nb
; i
++)
334 if (dlil_filters
[i
].type
== 0)
337 if (i
== dlil_filters_nb
) {
338 // expand the filters array by MAX_DLIL_FILTERS
339 MALLOC(p
, u_char
*, sizeof(struct dlil_filter_id_str
) * (dlil_filters_nb
+ MAX_DLIL_FILTERS
), M_NKE
, M_WAITOK
);
343 bcopy(dlil_filters
, p
, sizeof(struct dlil_filter_id_str
) * dlil_filters_nb
);
344 bzero(p
+ sizeof(struct dlil_filter_id_str
) * dlil_filters_nb
, sizeof(struct dlil_filter_id_str
) * MAX_DL_TAGS
);
345 dlil_filters_nb
+= MAX_DLIL_FILTERS
;
346 FREE(dlil_filters
, M_NKE
);
347 dlil_filters
= (struct dlil_filter_id_str
*)p
;
354 int dlil_attach_interface_filter(struct ifnet
*ifp
,
355 struct dlil_if_flt_str
*if_filter
,
361 struct dlil_filterq_entry
*tmp_ptr
;
362 struct dlil_filterq_entry
*if_filt
;
363 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
364 boolean_t funnel_state
;
366 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
370 bcopy((caddr_t
) if_filter
, (caddr_t
) &tmp_ptr
->variants
.if_filter
,
371 sizeof(struct dlil_if_flt_str
));
373 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
376 *filter_id
= get_new_filter_id();
377 if (*filter_id
== 0) {
378 FREE(tmp_ptr
, M_NKE
);
383 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
384 dlil_filters
[*filter_id
].head
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
385 dlil_filters
[*filter_id
].type
= DLIL_IF_FILTER
;
386 dlil_filters
[*filter_id
].ifp
= ifp
;
387 tmp_ptr
->filter_id
= *filter_id
;
388 tmp_ptr
->type
= DLIL_IF_FILTER
;
390 if (insertion_point
!= DLIL_LAST_FILTER
) {
391 TAILQ_FOREACH(if_filt
, fhead
, que
)
392 if (insertion_point
== if_filt
->filter_id
) {
393 TAILQ_INSERT_BEFORE(if_filt
, tmp_ptr
, que
);
398 TAILQ_INSERT_TAIL(fhead
, tmp_ptr
, que
);
402 thread_funnel_set(network_flock
, funnel_state
);
407 int dlil_attach_protocol_filter(u_long dl_tag
,
408 struct dlil_pr_flt_str
*pr_filter
,
412 struct dlil_filterq_entry
*tmp_ptr
, *pr_filt
;
415 boolean_t funnel_state
;
417 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0)
420 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
424 bcopy((caddr_t
) pr_filter
, (caddr_t
) &tmp_ptr
->variants
.pr_filter
,
425 sizeof(struct dlil_pr_flt_str
));
427 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
430 *filter_id
= get_new_filter_id();
431 if (*filter_id
== 0) {
432 FREE(tmp_ptr
, M_NKE
);
437 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
438 dlil_filters
[*filter_id
].head
= dl_tag_array
[dl_tag
].pr_flt_head
;
439 dlil_filters
[*filter_id
].type
= DLIL_PR_FILTER
;
440 dlil_filters
[*filter_id
].proto
= dl_tag_array
[dl_tag
].proto
;
441 dlil_filters
[*filter_id
].ifp
= dl_tag_array
[dl_tag
].ifp
;
442 tmp_ptr
->filter_id
= *filter_id
;
443 tmp_ptr
->type
= DLIL_PR_FILTER
;
445 if (insertion_point
!= DLIL_LAST_FILTER
) {
446 TAILQ_FOREACH(pr_filt
, dl_tag_array
[dl_tag
].pr_flt_head
, que
)
447 if (insertion_point
== pr_filt
->filter_id
) {
448 TAILQ_INSERT_BEFORE(pr_filt
, tmp_ptr
, que
);
453 TAILQ_INSERT_TAIL(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
457 thread_funnel_set(network_flock
, funnel_state
);
463 dlil_detach_filter(u_long filter_id
)
465 struct dlil_filter_id_str
*flt
;
467 boolean_t funnel_state
;
469 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
472 if (filter_id
>= dlil_filters_nb
|| dlil_filters
[filter_id
].type
== 0) {
477 flt
= &dlil_filters
[filter_id
];
479 if (flt
->type
== DLIL_IF_FILTER
) {
480 if (IFILT(flt
->filter_ptr
).filter_detach
)
481 (*IFILT(flt
->filter_ptr
).filter_detach
)(IFILT(flt
->filter_ptr
).cookie
);
484 if (flt
->type
== DLIL_PR_FILTER
) {
485 if (PFILT(flt
->filter_ptr
).filter_detach
)
486 (*PFILT(flt
->filter_ptr
).filter_detach
)(PFILT(flt
->filter_ptr
).cookie
);
490 TAILQ_REMOVE(flt
->head
, flt
->filter_ptr
, que
);
491 FREE(flt
->filter_ptr
, M_NKE
);
496 thread_funnel_set(network_flock
, funnel_state
);
502 dlil_input_thread_continue(void)
505 struct mbuf
*m
, *m_loop
;
508 usimple_lock(&dlil_input_lock
);
509 m
= dlil_input_mbuf_head
;
510 dlil_input_mbuf_head
= NULL
;
511 dlil_input_mbuf_tail
= NULL
;
512 m_loop
= dlil_input_loop_head
;
513 dlil_input_loop_head
= NULL
;
514 dlil_input_loop_tail
= NULL
;
515 usimple_unlock(&dlil_input_lock
);
518 expand_mcl
= dlil_expand_mcl
;
528 * NOTE warning %%% attention !!!!
529 * We should think about putting some thread starvation safeguards if
530 * we deal with long chains of packets.
533 struct mbuf
*m0
= m
->m_nextpkt
;
534 void *header
= m
->m_pkthdr
.header
;
537 m
->m_pkthdr
.header
= NULL
;
538 (void) dlil_input_packet(m
->m_pkthdr
.rcvif
, m
, header
);
543 struct mbuf
*m0
= m
->m_nextpkt
;
544 void *header
= m
->m_pkthdr
.header
;
545 struct ifnet
*ifp
= &loif
[0];
548 m
->m_pkthdr
.header
= NULL
;
549 (void) dlil_input_packet(ifp
, m
, header
);
556 if (dlil_input_mbuf_head
== NULL
&&
557 dlil_input_loop_head
== NULL
&&
559 assert_wait(&dlil_input_thread_wakeup
, THREAD_UNINT
);
560 (void) thread_block(dlil_input_thread_continue
);
566 void dlil_input_thread(void)
568 register thread_t self
= current_thread();
569 extern void stack_privilege(thread_t thread
);
572 * Make sure that this thread
573 * always has a kernel stack, and
574 * bind it to the master cpu.
576 stack_privilege(self
);
577 ml_thread_policy(current_thread(), MACHINE_GROUP
,
578 (MACHINE_NETWORK_GROUP
|MACHINE_NETWORK_NETISR
));
580 /* The dlil thread is always funneled */
581 thread_funnel_set(network_flock
, TRUE
);
582 dlil_initialized
= 1;
583 dlil_input_thread_continue();
587 dlil_input(struct ifnet
*ifp
, struct mbuf
*m_head
, struct mbuf
*m_tail
)
590 * Because of loopbacked multicast we cannot stuff the ifp in
591 * the rcvif of the packet header: loopback has its own dlil
595 usimple_lock(&dlil_input_lock
);
596 if (ifp
->if_type
!= IFT_LOOP
) {
597 if (dlil_input_mbuf_head
== NULL
)
598 dlil_input_mbuf_head
= m_head
;
599 else if (dlil_input_mbuf_tail
!= NULL
)
600 dlil_input_mbuf_tail
->m_nextpkt
= m_head
;
601 dlil_input_mbuf_tail
= m_tail
? m_tail
: m_head
;
603 if (dlil_input_loop_head
== NULL
)
604 dlil_input_loop_head
= m_head
;
605 else if (dlil_input_loop_tail
!= NULL
)
606 dlil_input_loop_tail
->m_nextpkt
= m_head
;
607 dlil_input_loop_tail
= m_tail
? m_tail
: m_head
;
609 usimple_unlock(&dlil_input_lock
);
611 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
617 dlil_input_packet(struct ifnet
*ifp
, struct mbuf
*m
,
620 struct ifnet
*orig_ifp
= 0;
621 struct dlil_filterq_entry
*tmp
;
623 struct if_proto
*ifproto
= 0;
624 struct if_proto
*proto
;
625 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
628 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_START
,0,0,0,0,0);
631 * Run interface filters
634 while (orig_ifp
!= ifp
) {
637 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
638 if (IFILT(tmp
).filter_if_input
) {
639 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
644 if (retval
== EJUSTRETURN
)
658 ifp
->if_lastchange
= time
;
661 * Call family demux module. If the demux module finds a match
662 * for the frame it will fill-in the ifproto pointer.
665 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
667 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
670 if ((retval
) && (retval
!= EJUSTRETURN
) && (ifp
->offercnt
)) {
672 * No match was found, look for any offers.
674 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
675 TAILQ_FOREACH(proto
, tmp
, next
) {
676 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
685 if (retval
!= EJUSTRETURN
) {
694 printf("ERROR - dlil_input - if_demux didn't return an if_proto pointer\n");
700 * Call any attached protocol filters.
703 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
704 if (PFILT(tmp
).filter_dl_input
) {
705 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
711 if (retval
== EJUSTRETURN
)
723 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
724 ifp
, ifproto
->dl_tag
,
727 if (retval
== EJUSTRETURN
)
733 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_END
,0,0,0,0,0);
739 void ether_input(ifp
, eh
, m
)
741 struct ether_header
*eh
;
745 kprintf("Someone is calling ether_input!!\n");
747 dlil_input(ifp
, m
, NULL
);
752 dlil_event(struct ifnet
*ifp
, struct kern_event_msg
*event
)
754 struct dlil_filterq_entry
*filt
;
756 struct ifnet
*orig_ifp
= 0;
757 struct if_proto
*proto
;
758 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
759 struct kev_msg kev_msg
;
760 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
761 boolean_t funnel_state
;
764 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
766 while (orig_ifp
!= ifp
) {
769 TAILQ_FOREACH_REVERSE(filt
, fhead
, que
, dlil_filterq_head
) {
770 if (IFILT(filt
).filter_if_event
) {
771 retval
= (*IFILT(filt
).filter_if_event
)(IFILT(filt
).cookie
,
776 (void) thread_funnel_set(network_flock
, funnel_state
);
777 if (retval
== EJUSTRETURN
)
791 * Call Interface Module event hook, if any.
795 retval
= ifp
->if_event(ifp
, (caddr_t
) event
);
798 (void) thread_funnel_set(network_flock
, funnel_state
);
800 if (retval
== EJUSTRETURN
)
808 * Call dl_event entry point for all protocols attached to this interface
811 TAILQ_FOREACH(proto
, tmp
, next
) {
813 * Call any attached protocol filters.
816 TAILQ_FOREACH_REVERSE(filt
, &proto
->pr_flt_head
, que
, dlil_filterq_head
) {
817 if (PFILT(filt
).filter_dl_event
) {
818 retval
= (*PFILT(filt
).filter_dl_event
)(PFILT(filt
).cookie
,
822 (void) thread_funnel_set(network_flock
, funnel_state
);
823 if (retval
== EJUSTRETURN
)
833 * Finally, call the dl_event entry point (if any)
837 retval
= (*proto
->dl_event
)(event
, proto
->dl_tag
);
839 if (retval
== EJUSTRETURN
) {
840 (void) thread_funnel_set(network_flock
, funnel_state
);
847 * Now, post this event to the Kernel Event message queue
850 kev_msg
.vendor_code
= event
->vendor_code
;
851 kev_msg
.kev_class
= event
->kev_class
;
852 kev_msg
.kev_subclass
= event
->kev_subclass
;
853 kev_msg
.event_code
= event
->event_code
;
854 kev_msg
.dv
[0].data_ptr
= &event
->event_data
[0];
855 kev_msg
.dv
[0].data_length
= event
->total_size
- KEV_MSG_HEADER_SIZE
;
856 kev_msg
.dv
[1].data_length
= 0;
858 kev_post_msg(&kev_msg
);
860 (void) thread_funnel_set(network_flock
, funnel_state
);
867 dlil_output(u_long dl_tag
,
870 struct sockaddr
*dest
,
876 struct ifnet
*orig_ifp
= 0;
878 struct if_proto
*proto
;
879 struct dlil_filterq_entry
*tmp
;
881 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
882 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
883 struct dlil_filterq_head
*fhead
;
885 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_START
,0,0,0,0,0);
887 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0) {
892 ifp
= dl_tag_array
[dl_tag
].ifp
;
893 proto
= dl_tag_array
[dl_tag
].proto
;
895 frame_type
= frame_type_buffer
;
896 dst_linkaddr
= dst_linkaddr_buffer
;
898 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
900 if ((raw
== 0) && (proto
->dl_pre_output
)) {
901 retval
= (*proto
->dl_pre_output
)(ifp
, &m
, dest
, route
,
902 frame_type
, dst_linkaddr
, dl_tag
);
904 if (retval
== EJUSTRETURN
)
914 * Run any attached protocol filters.
917 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
918 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
919 if (PFILT(tmp
).filter_dl_output
) {
920 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
921 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
923 if (retval
== EJUSTRETURN
)
936 * Call framing module
938 if ((raw
== 0) && (ifp
->if_framer
)) {
939 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
941 if (retval
== EJUSTRETURN
)
953 struct mbuf
*m0
= m
;
954 struct ether_header
*eh
= mtod(m
, struct ether_header
*);
956 if (m
->m_pkthdr
.rcvif
)
957 m
->m_pkthdr
.rcvif
= NULL
;
958 ifp
= bridge_dst_lookup(eh
);
959 bdg_forward(&m0
, ifp
);
969 * Let interface filters (if any) do their thing ...
972 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
973 if (TAILQ_EMPTY(fhead
) == 0) {
974 while (orig_ifp
!= ifp
) {
976 TAILQ_FOREACH(tmp
, fhead
, que
) {
977 if (IFILT(tmp
).filter_if_output
) {
978 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
982 if (retval
== EJUSTRETURN
)
999 * Finally, call the driver.
1002 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_START
, 0,0,0,0,0);
1003 retval
= (*ifp
->if_output
)(ifp
, m
);
1004 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_END
, 0,0,0,0,0);
1006 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_END
,0,0,0,0,0);
1008 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1016 dlil_ioctl(u_long proto_fam
,
1021 struct dlil_filterq_entry
*tmp
;
1022 struct dlil_filterq_head
*fhead
;
1023 int retval
= EOPNOTSUPP
;
1024 int retval2
= EOPNOTSUPP
;
1026 struct if_family_str
*if_family
;
1030 retval
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
,
1031 proto_fam
, &dl_tag
);
1034 if (dl_tag_array
[dl_tag
].ifp
!= ifp
)
1038 * Run any attached protocol filters.
1040 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1041 if (PFILT(tmp
).filter_dl_ioctl
) {
1043 (*PFILT(tmp
).filter_dl_ioctl
)(PFILT(tmp
).cookie
,
1044 dl_tag_array
[dl_tag
].ifp
,
1049 if (retval
== EJUSTRETURN
)
1057 if (dl_tag_array
[dl_tag
].proto
->dl_ioctl
)
1059 (*dl_tag_array
[dl_tag
].proto
->dl_ioctl
)(dl_tag
,
1060 dl_tag_array
[dl_tag
].ifp
,
1064 retval
= EOPNOTSUPP
;
1070 if ((retval
) && (retval
!= EOPNOTSUPP
)) {
1071 if (retval
== EJUSTRETURN
)
1078 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1079 TAILQ_FOREACH(tmp
, fhead
, que
) {
1080 if (IFILT(tmp
).filter_if_ioctl
) {
1081 retval2
= (*IFILT(tmp
).filter_if_ioctl
)(IFILT(tmp
).cookie
, ifp
,
1082 ioctl_code
, ioctl_arg
);
1084 if (retval2
== EJUSTRETURN
)
1093 if_family
= find_family_module(ifp
->if_family
);
1094 if ((if_family
) && (if_family
->ifmod_ioctl
)) {
1095 retval2
= (*if_family
->ifmod_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1097 if ((retval2
) && (retval2
!= EOPNOTSUPP
)) {
1098 if (retval2
== EJUSTRETURN
)
1104 if (retval
== EOPNOTSUPP
)
1109 retval2
= (*ifp
->if_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1111 if (retval
== EOPNOTSUPP
)
1114 if (retval2
== EOPNOTSUPP
)
1123 dlil_attach_protocol(struct dlil_proto_reg_str
*proto
,
1127 struct if_proto
*ifproto
;
1129 struct if_family_str
*if_family
;
1130 struct dlil_proto_head
*tmp
;
1131 struct kev_dl_proto_data ev_pr_data
;
1133 boolean_t funnel_state
;
1136 if ((proto
->protocol_family
== 0) || (proto
->interface_family
== 0))
1139 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1141 if_family
= find_family_module(proto
->interface_family
);
1142 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1143 kprintf("dlil_attach_protocol -- no interface family module %d",
1144 proto
->interface_family
);
1149 ifp
= ifbyfamily(proto
->interface_family
, proto
->unit_number
);
1151 kprintf("dlil_attach_protocol -- no such interface %d unit %d\n",
1152 proto
->interface_family
, proto
->unit_number
);
1157 if (dlil_find_dltag(proto
->interface_family
, proto
->unit_number
,
1158 proto
->protocol_family
, &i
) == 0) {
1163 for (i
=1; i
< dl_tag_nb
; i
++)
1164 if (dl_tag_array
[i
].ifp
== 0)
1167 if (i
== dl_tag_nb
) {
1168 // expand the tag array by MAX_DL_TAGS
1169 MALLOC(p
, u_char
*, sizeof(struct dl_tag_str
) * (dl_tag_nb
+ MAX_DL_TAGS
), M_NKE
, M_WAITOK
);
1174 bcopy(dl_tag_array
, p
, sizeof(struct dl_tag_str
) * dl_tag_nb
);
1175 bzero(p
+ sizeof(struct dl_tag_str
) * dl_tag_nb
, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
);
1176 dl_tag_nb
+= MAX_DL_TAGS
;
1177 FREE(dl_tag_array
, M_NKE
);
1178 dl_tag_array
= (struct dl_tag_str
*)p
;
1182 * Allocate and init a new if_proto structure
1185 ifproto
= _MALLOC(sizeof(struct if_proto
), M_IFADDR
, M_WAITOK
);
1187 printf("ERROR - DLIL failed if_proto allocation\n");
1192 bzero(ifproto
, sizeof(struct if_proto
));
1194 dl_tag_array
[i
].ifp
= ifp
;
1195 dl_tag_array
[i
].proto
= ifproto
;
1196 dl_tag_array
[i
].pr_flt_head
= &ifproto
->pr_flt_head
;
1197 ifproto
->dl_tag
= i
;
1200 if (proto
->default_proto
) {
1201 if (ifp
->if_data
.default_proto
== 0)
1202 ifp
->if_data
.default_proto
= i
;
1204 printf("ERROR - dlil_attach_protocol -- Attempt to attach more than one default protocol\n");
1207 ifproto
->protocol_family
= proto
->protocol_family
;
1208 ifproto
->dl_input
= proto
->input
;
1209 ifproto
->dl_pre_output
= proto
->pre_output
;
1210 ifproto
->dl_event
= proto
->event
;
1211 ifproto
->dl_offer
= proto
->offer
;
1212 ifproto
->dl_ioctl
= proto
->ioctl
;
1214 TAILQ_INIT(&ifproto
->pr_flt_head
);
1217 * Call family module add_proto routine so it can refine the
1218 * demux descriptors as it wishes.
1220 retval
= (*if_family
->add_proto
)(&proto
->demux_desc_head
, ifproto
, *dl_tag
);
1222 dl_tag_array
[i
].ifp
= 0;
1223 FREE(ifproto
, M_IFADDR
);
1228 * Add to if_proto list for this interface
1231 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1232 TAILQ_INSERT_TAIL(tmp
, ifproto
, next
);
1234 if (ifproto
->dl_offer
)
1237 /* the reserved field carries the number of protocol still attached (subject to change) */
1238 ev_pr_data
.proto_family
= proto
->protocol_family
;
1239 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1240 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_ATTACHED
,
1241 (struct net_event_data
*)&ev_pr_data
,
1242 sizeof(struct kev_dl_proto_data
));
1246 thread_funnel_set(network_flock
, funnel_state
);
1253 dlil_detach_protocol(u_long dl_tag
)
1256 struct ifnet
*orig_ifp
=0;
1257 struct if_proto
*proto
;
1258 struct dlil_proto_head
*tmp
;
1259 struct if_family_str
*if_family
;
1260 struct dlil_filterq_entry
*filter
;
1262 struct dlil_filterq_head
*fhead
;
1263 struct kev_dl_proto_data ev_pr_data
;
1264 boolean_t funnel_state
;
1266 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1269 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0) {
1274 ifp
= dl_tag_array
[dl_tag
].ifp
;
1275 proto
= dl_tag_array
[dl_tag
].proto
;
1277 if_family
= find_family_module(ifp
->if_family
);
1278 if (if_family
== NULL
) {
1283 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1286 * Call family module del_proto
1289 (*if_family
->del_proto
)(proto
, dl_tag
);
1293 * Remove and deallocate any attached protocol filters
1296 while (filter
= TAILQ_FIRST(&proto
->pr_flt_head
))
1297 dlil_detach_filter(filter
->filter_id
);
1299 if (proto
->dl_offer
)
1302 if (ifp
->if_data
.default_proto
== dl_tag
)
1303 ifp
->if_data
.default_proto
= 0;
1304 dl_tag_array
[dl_tag
].ifp
= 0;
1306 /* the reserved field carries the number of protocol still attached (subject to change) */
1307 ev_pr_data
.proto_family
= proto
->protocol_family
;
1310 * Cleanup routes that may still be in the routing table for that interface/protocol pair.
1313 if_rtproto_del(ifp
, proto
->protocol_family
);
1315 TAILQ_REMOVE(tmp
, proto
, next
);
1316 FREE(proto
, M_IFADDR
);
1319 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1320 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_DETACHED
,
1321 (struct net_event_data
*)&ev_pr_data
,
1322 sizeof(struct kev_dl_proto_data
));
1324 if (ifp
->refcnt
== 0) {
1326 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1328 (*if_family
->del_if
)(ifp
);
1330 if (--if_family
->refcnt
== 0) {
1331 if (if_family
->shutdown
)
1332 (*if_family
->shutdown
)();
1334 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1335 FREE(if_family
, M_IFADDR
);
1338 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1339 while (orig_ifp
!= ifp
) {
1342 TAILQ_FOREACH(filter
, fhead
, que
) {
1343 if (IFILT(filter
).filter_if_free
) {
1344 retval
= (*IFILT(filter
).filter_if_free
)(IFILT(filter
).cookie
, ifp
);
1347 thread_funnel_set(network_flock
, funnel_state
);
1351 if (ifp
!= orig_ifp
)
1356 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1358 (*ifp
->if_free
)(ifp
);
1363 thread_funnel_set(network_flock
, funnel_state
);
1372 dlil_if_attach(struct ifnet
*ifp
)
1374 u_long interface_family
= ifp
->if_family
;
1375 struct if_family_str
*if_family
;
1376 struct dlil_proto_head
*tmp
;
1379 boolean_t funnel_state
;
1381 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1383 if (ifnet_inited
== 0) {
1388 if_family
= find_family_module(interface_family
);
1390 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1392 kprintf("Attempt to attach interface without family module - %d\n",
1394 thread_funnel_set(network_flock
, funnel_state
);
1398 if (ifp
->refcnt
== 0) {
1400 * Call the family module to fill in the appropriate fields in the
1404 stat
= (*if_family
->add_if
)(ifp
);
1407 kprintf("dlil_if_attach -- add_if failed with %d\n", stat
);
1408 thread_funnel_set(network_flock
, funnel_state
);
1411 if_family
->refcnt
++;
1414 * Add the ifp to the interface list.
1417 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1420 ifp
->if_data
.default_proto
= 0;
1422 TAILQ_INIT(&ifp
->if_flt_head
);
1425 if (if_family
->init_if
) {
1426 stat
= (*if_family
->init_if
)(ifp
);
1428 kprintf("dlil_if_attach -- init_if failed with %d\n", stat
);
1435 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_ATTACHED
, 0, 0);
1438 thread_funnel_set(network_flock
, funnel_state
);
1444 dlil_if_detach(struct ifnet
*ifp
)
1446 struct if_proto
*proto
;
1447 struct dlil_filterq_entry
*if_filter
;
1448 struct if_family_str
*if_family
;
1449 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1451 struct kev_msg ev_msg
;
1452 boolean_t funnel_state
;
1454 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1457 if_family
= find_family_module(ifp
->if_family
);
1460 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 /* Let BPF know the interface is detaching. */
1475 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1477 (*if_family
->del_if
)(ifp
);
1479 if (--if_family
->refcnt
== 0) {
1480 if (if_family
->shutdown
)
1481 (*if_family
->shutdown
)();
1483 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1484 FREE(if_family
, M_IFADDR
);
1487 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1489 thread_funnel_set(network_flock
, funnel_state
);
1494 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHING
, 0, 0);
1496 thread_funnel_set(network_flock
, funnel_state
);
1497 return DLIL_WAIT_FOR_FREE
;
1503 dlil_reg_if_modules(u_long interface_family
,
1504 struct dlil_ifmod_reg_str
*ifmod
)
1506 struct if_family_str
*if_family
;
1508 boolean_t funnel_state
;
1511 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1513 if (find_family_module(interface_family
)) {
1514 kprintf("Attempt to register dlil family module more than once - %d\n",
1517 thread_funnel_set(network_flock
, funnel_state
);
1521 if ((!ifmod
->add_if
) || (!ifmod
->del_if
) ||
1522 (!ifmod
->add_proto
) || (!ifmod
->del_proto
)) {
1523 kprintf("dlil_reg_if_modules passed at least one null pointer\n");
1525 thread_funnel_set(network_flock
, funnel_state
);
1530 * The following is a gross hack to keep from breaking
1531 * Vicomsoft's internet gateway on Jaguar. Vicomsoft
1532 * does not zero the reserved fields in dlil_ifmod_reg_str.
1533 * As a result, we have to zero any function that used to
1534 * be reserved fields at the time Vicomsoft built their
1535 * kext. Radar #2974305
1537 if (ifmod
->reserved
[0] != 0 || ifmod
->reserved
[1] != 0 || ifmod
->reserved
[2]) {
1538 if (interface_family
== 123) { /* Vicom */
1542 thread_funnel_set(network_flock
, funnel_state
);
1547 if_family
= (struct if_family_str
*) _MALLOC(sizeof(struct if_family_str
), M_IFADDR
, M_WAITOK
);
1549 kprintf("dlil_reg_if_modules failed allocation\n");
1551 thread_funnel_set(network_flock
, funnel_state
);
1555 bzero(if_family
, sizeof(struct if_family_str
));
1557 if_family
->if_family
= interface_family
& 0xffff;
1558 if_family
->shutdown
= ifmod
->shutdown
;
1559 if_family
->add_if
= ifmod
->add_if
;
1560 if_family
->del_if
= ifmod
->del_if
;
1561 if_family
->init_if
= ifmod
->init_if
;
1562 if_family
->add_proto
= ifmod
->add_proto
;
1563 if_family
->del_proto
= ifmod
->del_proto
;
1564 if_family
->ifmod_ioctl
= ifmod
->ifmod_ioctl
;
1565 if_family
->refcnt
= 1;
1566 if_family
->flags
= 0;
1568 TAILQ_INSERT_TAIL(&if_family_head
, if_family
, if_fam_next
);
1570 thread_funnel_set(network_flock
, funnel_state
);
1574 int dlil_dereg_if_modules(u_long interface_family
)
1576 struct if_family_str
*if_family
;
1578 boolean_t funnel_state
;
1580 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1582 if_family
= find_family_module(interface_family
);
1583 if (if_family
== 0) {
1585 thread_funnel_set(network_flock
, funnel_state
);
1589 if (--if_family
->refcnt
== 0) {
1590 if (if_family
->shutdown
)
1591 (*if_family
->shutdown
)();
1593 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1594 FREE(if_family
, M_IFADDR
);
1597 if_family
->flags
|= DLIL_SHUTDOWN
;
1598 ret
= DLIL_WAIT_FOR_FREE
;
1602 thread_funnel_set(network_flock
, funnel_state
);
1611 * Old if_attach no-op'ed function defined here for temporary backwards compatibility
1617 dlil_if_attach(ifp
);
1623 dlil_inject_if_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1625 struct ifnet
*orig_ifp
= 0;
1627 struct if_proto
*ifproto
;
1628 struct if_proto
*proto
;
1629 struct dlil_filterq_entry
*tmp
;
1631 struct dlil_filterq_head
*fhead
;
1634 dlil_stats
.inject_if_in1
++;
1636 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1639 ifp
= dlil_filters
[from_id
].ifp
;
1642 * Let interface filters (if any) do their thing ...
1645 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1648 if (TAILQ_EMPTY(fhead
) == 0) {
1649 while (orig_ifp
!= ifp
) {
1651 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
1652 if ((match_found
) && (IFILT(tmp
).filter_if_input
)) {
1653 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
1658 if (retval
== EJUSTRETURN
)
1668 if (ifp
!= orig_ifp
)
1671 if (from_id
== tmp
->filter_id
)
1677 ifp
->if_lastchange
= time
;
1680 * Call family demux module. If the demux module finds a match
1681 * for the frame it will fill-in the ifproto pointer.
1684 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
1686 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
1689 if ((retval
) && (ifp
->offercnt
)) {
1691 * No match was found, look for any offers.
1693 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1694 TAILQ_FOREACH(proto
, tmp
, next
) {
1695 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
1704 if (retval
!= EJUSTRETURN
) {
1713 printf("ERROR - dlil_inject_if_input -- if_demux didn't return an if_proto pointer\n");
1719 * Call any attached protocol filters.
1721 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1722 if (PFILT(tmp
).filter_dl_input
) {
1723 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1729 if (retval
== EJUSTRETURN
)
1741 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1742 ifp
, ifproto
->dl_tag
,
1745 dlil_stats
.inject_if_in2
++;
1746 if (retval
== EJUSTRETURN
)
1761 dlil_inject_pr_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1763 struct ifnet
*orig_ifp
= 0;
1764 struct dlil_filterq_entry
*tmp
;
1766 struct if_proto
*ifproto
= 0;
1770 dlil_stats
.inject_pr_in1
++;
1771 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1774 ifproto
= dlil_filters
[from_id
].proto
;
1775 ifp
= dlil_filters
[from_id
].ifp
;
1778 * Call any attached protocol filters.
1782 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1783 if ((match_found
) && (PFILT(tmp
).filter_dl_input
)) {
1784 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1790 if (retval
== EJUSTRETURN
)
1799 if (tmp
->filter_id
== from_id
)
1804 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1805 ifp
, ifproto
->dl_tag
,
1808 if (retval
== EJUSTRETURN
)
1814 dlil_stats
.inject_pr_in2
++;
1821 dlil_inject_pr_output(struct mbuf
*m
,
1822 struct sockaddr
*dest
,
1828 struct ifnet
*orig_ifp
= 0;
1830 struct dlil_filterq_entry
*tmp
;
1832 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
1833 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
1834 struct dlil_filterq_head
*fhead
;
1838 dlil_stats
.inject_pr_out1
++;
1841 bcopy(frame_type
, &frame_type_buffer
[0], MAX_FRAME_TYPE_SIZE
* 4);
1846 bcopy(dst_linkaddr
, &dst_linkaddr_buffer
, MAX_LINKADDR
* 4);
1851 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1854 ifp
= dlil_filters
[from_id
].ifp
;
1855 dl_tag
= dlil_filters
[from_id
].proto
->dl_tag
;
1857 frame_type
= frame_type_buffer
;
1858 dst_linkaddr
= dst_linkaddr_buffer
;
1860 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1863 * Run any attached protocol filters.
1867 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
1868 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1869 if ((match_found
) && (PFILT(tmp
).filter_dl_output
)) {
1870 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
1871 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
1873 if (retval
== EJUSTRETURN
)
1882 if (tmp
->filter_id
== from_id
)
1889 * Call framing module
1891 if ((raw
== 0) && (ifp
->if_framer
)) {
1892 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
1894 if (retval
== EJUSTRETURN
)
1907 struct mbuf
*m0
= m
;
1908 struct ether_header
*eh
= mtod(m
, struct ether_header
*);
1910 if (m
->m_pkthdr
.rcvif
)
1911 m
->m_pkthdr
.rcvif
= NULL
;
1912 ifp
= bridge_dst_lookup(eh
);
1913 bdg_forward(&m0
, ifp
);
1923 * Let interface filters (if any) do their thing ...
1926 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1927 if (TAILQ_EMPTY(fhead
) == 0) {
1928 while (orig_ifp
!= ifp
) {
1930 TAILQ_FOREACH(tmp
, fhead
, que
) {
1931 if (IFILT(tmp
).filter_if_output
) {
1932 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1936 if (retval
== EJUSTRETURN
)
1946 if (ifp
!= orig_ifp
)
1953 * Finally, call the driver.
1956 retval
= (*ifp
->if_output
)(ifp
, m
);
1957 dlil_stats
.inject_pr_out2
++;
1958 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1966 dlil_inject_if_output(struct mbuf
*m
, u_long from_id
)
1968 struct ifnet
*orig_ifp
= 0;
1970 struct dlil_filterq_entry
*tmp
;
1972 struct dlil_filterq_head
*fhead
;
1975 dlil_stats
.inject_if_out1
++;
1976 if (from_id
> dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1979 ifp
= dlil_filters
[from_id
].ifp
;
1982 * Let interface filters (if any) do their thing ...
1985 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1988 if (TAILQ_EMPTY(fhead
) == 0) {
1989 while (orig_ifp
!= ifp
) {
1991 TAILQ_FOREACH(tmp
, fhead
, que
) {
1992 if ((match_found
) && (IFILT(tmp
).filter_if_output
)) {
1993 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1997 if (retval
== EJUSTRETURN
)
2007 if (ifp
!= orig_ifp
)
2010 if (from_id
== tmp
->filter_id
)
2017 * Finally, call the driver.
2020 retval
= (*ifp
->if_output
)(ifp
, m
);
2021 dlil_stats
.inject_if_out2
++;
2022 if ((retval
== 0) || (retval
== EJUSTRETURN
))
2029 int dlil_recycle_ioctl(struct ifnet
*ifnet_ptr
, u_long ioctl_code
, void *ioctl_arg
)
2036 int dlil_recycle_output(struct ifnet
*ifnet_ptr
, struct mbuf
*m
)
2044 int dlil_recycle_free(struct ifnet
*ifnet_ptr
)
2050 int dlil_recycle_set_bpf_tap(struct ifnet
*ifp
, int mode
,
2051 int (*bpf_callback
)(struct ifnet
*, struct mbuf
*))
2053 /* XXX not sure what to do here */
2057 int dlil_if_acquire(u_long family
, void *uniqueid
, size_t uniqueid_len
,
2060 struct ifnet
*ifp1
= NULL
;
2061 struct dlil_ifnet
*dlifp1
= NULL
;
2063 boolean_t funnel_state
;
2065 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
2068 TAILQ_FOREACH(dlifp1
, &dlil_ifnet_head
, dl_if_link
) {
2070 ifp1
= (struct ifnet
*)dlifp1
;
2072 if (ifp1
->if_family
== family
) {
2074 /* same uniqueid and same len or no unique id specified */
2075 if ((uniqueid_len
== dlifp1
->if_uniqueid_len
)
2076 && !bcmp(uniqueid
, dlifp1
->if_uniqueid
, uniqueid_len
)) {
2078 /* check for matching interface in use */
2079 if (ifp1
->if_eflags
& IFEF_INUSE
) {
2087 ifp1
->if_eflags
|= (IFEF_INUSE
+ IFEF_REUSE
);
2095 /* no interface found, allocate a new one */
2096 MALLOC(dlifp1
, struct dlil_ifnet
*, sizeof(*dlifp1
), M_NKE
, M_WAITOK
);
2102 bzero(dlifp1
, sizeof(*dlifp1
));
2105 MALLOC(dlifp1
->if_uniqueid
, void *, uniqueid_len
, M_NKE
, M_WAITOK
);
2106 if (dlifp1
->if_uniqueid
== 0) {
2107 FREE(dlifp1
, M_NKE
);
2111 bcopy(uniqueid
, dlifp1
->if_uniqueid
, uniqueid_len
);
2112 dlifp1
->if_uniqueid_len
= uniqueid_len
;
2115 ifp1
= (struct ifnet
*)dlifp1
;
2116 ifp1
->if_eflags
|= IFEF_INUSE
;
2118 TAILQ_INSERT_TAIL(&dlil_ifnet_head
, dlifp1
, dl_if_link
);
2125 thread_funnel_set(network_flock
, funnel_state
);
2129 void dlil_if_release(struct ifnet
*ifp
)
2131 struct dlil_ifnet
*dlifp
= (struct dlil_ifnet
*)ifp
;
2133 boolean_t funnel_state
;
2135 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
2138 ifp
->if_eflags
&= ~IFEF_INUSE
;
2139 ifp
->if_ioctl
= dlil_recycle_ioctl
;
2140 ifp
->if_output
= dlil_recycle_output
;
2141 ifp
->if_free
= dlil_recycle_free
;
2142 ifp
->if_set_bpf_tap
= dlil_recycle_set_bpf_tap
;
2144 strncpy(dlifp
->if_namestorage
, ifp
->if_name
, IFNAMSIZ
);
2145 ifp
->if_name
= dlifp
->if_namestorage
;
2148 thread_funnel_set(network_flock
, funnel_state
);