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
);
133 struct dlil_stats_str dlil_stats
;
136 struct dlil_filter_id_str
*dlil_filters
;
139 struct dl_tag_str
*dl_tag_array
;
142 TAILQ_HEAD(, dlil_ifnet
) dlil_ifnet_head
;
145 TAILQ_HEAD(, if_family_str
) if_family_head
;
147 static ifnet_inited
= 0;
148 static u_long dl_tag_nb
= 0;
149 static u_long dlil_filters_nb
= 0;
151 int dlil_initialized
= 0;
152 decl_simple_lock_data(, dlil_input_lock
)
153 int dlil_input_thread_wakeup
= 0;
155 static struct mbuf
*dlil_input_mbuf_head
= NULL
;
156 static struct mbuf
*dlil_input_mbuf_tail
= NULL
;
158 #error dlil_input() needs to be revised to support more than on loopback interface
160 static struct mbuf
*dlil_input_loop_head
= NULL
;
161 static struct mbuf
*dlil_input_loop_tail
= NULL
;
163 static void dlil_input_thread(void);
164 extern void run_netisr(void);
165 extern void bpfdetach(struct ifnet
*);
169 * Internal functions.
173 struct if_family_str
*find_family_module(u_long if_family
)
175 struct if_family_str
*mod
= NULL
;
177 TAILQ_FOREACH(mod
, &if_family_head
, if_fam_next
) {
178 if (mod
->if_family
== (if_family
& 0xffff))
190 struct ifnet
*ifbyfamily(u_long family
, short unit
)
194 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
195 if ((family
== ifp
->if_family
) &&
196 (ifp
->if_unit
== unit
))
202 struct if_proto
*dlttoproto(u_long dl_tag
)
204 if (dl_tag
< dl_tag_nb
&& dl_tag_array
[dl_tag
].ifp
)
205 return dl_tag_array
[dl_tag
].proto
;
210 static int dlil_ifp_proto_count(struct ifnet
* ifp
)
213 struct if_proto
* proto
;
214 struct dlil_proto_head
* tmp
;
216 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
218 TAILQ_FOREACH(proto
, tmp
, next
)
224 u_long
ifptodlt(struct ifnet
*ifp
, u_long proto_family
)
226 struct if_proto
*proto
;
227 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
230 TAILQ_FOREACH(proto
, tmp
, next
)
231 if (proto
->protocol_family
== proto_family
)
232 return proto
->dl_tag
;
238 int dlil_find_dltag(u_long if_family
, short unit
, u_long proto_family
, u_long
*dl_tag
)
242 ifp
= ifbyfamily(if_family
, unit
);
246 *dl_tag
= ifptodlt(ifp
, proto_family
);
248 return EPROTONOSUPPORT
;
254 void dlil_post_msg(struct ifnet
*ifp
, u_long event_subclass
, u_long event_code
,
255 struct net_event_data
*event_data
, u_long event_data_len
)
257 struct net_event_data ev_data
;
258 struct kev_msg ev_msg
;
261 * a net event always start with a net_event_data structure
262 * but the caller can generate a simple net event or
263 * provide a longer event structure to post
266 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
267 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
268 ev_msg
.kev_subclass
= event_subclass
;
269 ev_msg
.event_code
= event_code
;
271 if (event_data
== 0) {
272 event_data
= &ev_data
;
273 event_data_len
= sizeof(struct net_event_data
);
276 strncpy(&event_data
->if_name
[0], ifp
->if_name
, IFNAMSIZ
);
277 event_data
->if_family
= ifp
->if_family
;
278 event_data
->if_unit
= (unsigned long) ifp
->if_unit
;
280 ev_msg
.dv
[0].data_length
= event_data_len
;
281 ev_msg
.dv
[0].data_ptr
= event_data
;
282 ev_msg
.dv
[1].data_length
= 0;
284 kev_post_msg(&ev_msg
);
294 TAILQ_INIT(&dlil_ifnet_head
);
295 TAILQ_INIT(&if_family_head
);
297 // create the dl tag array
298 MALLOC(dl_tag_array
, void *, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
, M_NKE
, M_WAITOK
);
299 if (dl_tag_array
== 0) {
300 printf("dlil_init tags array allocation failed\n");
303 bzero(dl_tag_array
, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
);
304 dl_tag_nb
= MAX_DL_TAGS
;
306 // create the dl filters array
307 MALLOC(dlil_filters
, void *, sizeof(struct dlil_filter_id_str
) * MAX_DLIL_FILTERS
, M_NKE
, M_WAITOK
);
308 if (dlil_filters
== 0) {
309 printf("dlil_init filters array allocation failed\n");
312 bzero(dlil_filters
, sizeof(struct dlil_filter_id_str
) * MAX_DLIL_FILTERS
);
313 dlil_filters_nb
= MAX_DLIL_FILTERS
;
315 bzero(&dlil_stats
, sizeof(dlil_stats
));
317 simple_lock_init(&dlil_input_lock
);
320 * Start up the dlil input thread once everything is initialized
322 (void) kernel_thread(kernel_task
, dlil_input_thread
);
325 u_long
get_new_filter_id()
330 for (i
=1; i
< dlil_filters_nb
; i
++)
331 if (dlil_filters
[i
].type
== 0)
334 if (i
== dlil_filters_nb
) {
335 // expand the filters array by MAX_DLIL_FILTERS
336 MALLOC(p
, u_char
*, sizeof(struct dlil_filter_id_str
) * (dlil_filters_nb
+ MAX_DLIL_FILTERS
), M_NKE
, M_WAITOK
);
340 bcopy(dlil_filters
, p
, sizeof(struct dlil_filter_id_str
) * dlil_filters_nb
);
341 bzero(p
+ sizeof(struct dlil_filter_id_str
) * dlil_filters_nb
, sizeof(struct dlil_filter_id_str
) * MAX_DL_TAGS
);
342 dlil_filters_nb
+= MAX_DLIL_FILTERS
;
343 FREE(dlil_filters
, M_NKE
);
344 dlil_filters
= (struct dlil_filter_id_str
*)p
;
351 int dlil_attach_interface_filter(struct ifnet
*ifp
,
352 struct dlil_if_flt_str
*if_filter
,
358 struct dlil_filterq_entry
*tmp_ptr
;
359 struct dlil_filterq_entry
*if_filt
;
360 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
361 boolean_t funnel_state
;
363 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
367 bcopy((caddr_t
) if_filter
, (caddr_t
) &tmp_ptr
->variants
.if_filter
,
368 sizeof(struct dlil_if_flt_str
));
370 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
373 *filter_id
= get_new_filter_id();
374 if (*filter_id
== 0) {
375 FREE(tmp_ptr
, M_NKE
);
380 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
381 dlil_filters
[*filter_id
].head
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
382 dlil_filters
[*filter_id
].type
= DLIL_IF_FILTER
;
383 dlil_filters
[*filter_id
].ifp
= ifp
;
384 tmp_ptr
->filter_id
= *filter_id
;
385 tmp_ptr
->type
= DLIL_IF_FILTER
;
387 if (insertion_point
!= DLIL_LAST_FILTER
) {
388 TAILQ_FOREACH(if_filt
, fhead
, que
)
389 if (insertion_point
== if_filt
->filter_id
) {
390 TAILQ_INSERT_BEFORE(if_filt
, tmp_ptr
, que
);
395 TAILQ_INSERT_TAIL(fhead
, tmp_ptr
, que
);
399 thread_funnel_set(network_flock
, funnel_state
);
404 int dlil_attach_protocol_filter(u_long dl_tag
,
405 struct dlil_pr_flt_str
*pr_filter
,
409 struct dlil_filterq_entry
*tmp_ptr
, *pr_filt
;
412 boolean_t funnel_state
;
414 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0)
417 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
421 bcopy((caddr_t
) pr_filter
, (caddr_t
) &tmp_ptr
->variants
.pr_filter
,
422 sizeof(struct dlil_pr_flt_str
));
424 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
427 *filter_id
= get_new_filter_id();
428 if (*filter_id
== 0) {
429 FREE(tmp_ptr
, M_NKE
);
434 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
435 dlil_filters
[*filter_id
].head
= dl_tag_array
[dl_tag
].pr_flt_head
;
436 dlil_filters
[*filter_id
].type
= DLIL_PR_FILTER
;
437 dlil_filters
[*filter_id
].proto
= dl_tag_array
[dl_tag
].proto
;
438 dlil_filters
[*filter_id
].ifp
= dl_tag_array
[dl_tag
].ifp
;
439 tmp_ptr
->filter_id
= *filter_id
;
440 tmp_ptr
->type
= DLIL_PR_FILTER
;
442 if (insertion_point
!= DLIL_LAST_FILTER
) {
443 TAILQ_FOREACH(pr_filt
, dl_tag_array
[dl_tag
].pr_flt_head
, que
)
444 if (insertion_point
== pr_filt
->filter_id
) {
445 TAILQ_INSERT_BEFORE(pr_filt
, tmp_ptr
, que
);
450 TAILQ_INSERT_TAIL(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
454 thread_funnel_set(network_flock
, funnel_state
);
460 dlil_detach_filter(u_long filter_id
)
462 struct dlil_filter_id_str
*flt
;
464 boolean_t funnel_state
;
466 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
469 if (filter_id
>= dlil_filters_nb
|| dlil_filters
[filter_id
].type
== 0) {
474 flt
= &dlil_filters
[filter_id
];
476 if (flt
->type
== DLIL_IF_FILTER
) {
477 if (IFILT(flt
->filter_ptr
).filter_detach
)
478 (*IFILT(flt
->filter_ptr
).filter_detach
)(IFILT(flt
->filter_ptr
).cookie
);
481 if (flt
->type
== DLIL_PR_FILTER
) {
482 if (PFILT(flt
->filter_ptr
).filter_detach
)
483 (*PFILT(flt
->filter_ptr
).filter_detach
)(PFILT(flt
->filter_ptr
).cookie
);
487 TAILQ_REMOVE(flt
->head
, flt
->filter_ptr
, que
);
488 FREE(flt
->filter_ptr
, M_NKE
);
493 thread_funnel_set(network_flock
, funnel_state
);
499 dlil_input_thread_continue(void)
502 struct mbuf
*m
, *m_loop
;
505 usimple_lock(&dlil_input_lock
);
506 m
= dlil_input_mbuf_head
;
507 dlil_input_mbuf_head
= NULL
;
508 dlil_input_mbuf_tail
= NULL
;
509 m_loop
= dlil_input_loop_head
;
510 dlil_input_loop_head
= NULL
;
511 dlil_input_loop_tail
= NULL
;
512 usimple_unlock(&dlil_input_lock
);
515 expand_mcl
= dlil_expand_mcl
;
525 * NOTE warning %%% attention !!!!
526 * We should think about putting some thread starvation safeguards if
527 * we deal with long chains of packets.
530 struct mbuf
*m0
= m
->m_nextpkt
;
531 void *header
= m
->m_pkthdr
.header
;
534 m
->m_pkthdr
.header
= NULL
;
535 (void) dlil_input_packet(m
->m_pkthdr
.rcvif
, m
, header
);
540 struct mbuf
*m0
= m
->m_nextpkt
;
541 void *header
= m
->m_pkthdr
.header
;
542 struct ifnet
*ifp
= &loif
[0];
545 m
->m_pkthdr
.header
= NULL
;
546 (void) dlil_input_packet(ifp
, m
, header
);
553 if (dlil_input_mbuf_head
== NULL
&&
554 dlil_input_loop_head
== NULL
&&
556 assert_wait(&dlil_input_thread_wakeup
, THREAD_UNINT
);
557 (void) thread_block(dlil_input_thread_continue
);
563 void dlil_input_thread(void)
565 register thread_t self
= current_thread();
566 extern void stack_privilege(thread_t thread
);
569 * Make sure that this thread
570 * always has a kernel stack, and
571 * bind it to the master cpu.
573 stack_privilege(self
);
574 ml_thread_policy(current_thread(), MACHINE_GROUP
,
575 (MACHINE_NETWORK_GROUP
|MACHINE_NETWORK_NETISR
));
577 /* The dlil thread is always funneled */
578 thread_funnel_set(network_flock
, TRUE
);
579 dlil_initialized
= 1;
580 dlil_input_thread_continue();
584 dlil_input(struct ifnet
*ifp
, struct mbuf
*m_head
, struct mbuf
*m_tail
)
587 * Because of loopbacked multicast we cannot stuff the ifp in
588 * the rcvif of the packet header: loopback has its own dlil
592 usimple_lock(&dlil_input_lock
);
593 if (ifp
->if_type
!= IFT_LOOP
) {
594 if (dlil_input_mbuf_head
== NULL
)
595 dlil_input_mbuf_head
= m_head
;
596 else if (dlil_input_mbuf_tail
!= NULL
)
597 dlil_input_mbuf_tail
->m_nextpkt
= m_head
;
598 dlil_input_mbuf_tail
= m_tail
? m_tail
: m_head
;
600 if (dlil_input_loop_head
== NULL
)
601 dlil_input_loop_head
= m_head
;
602 else if (dlil_input_loop_tail
!= NULL
)
603 dlil_input_loop_tail
->m_nextpkt
= m_head
;
604 dlil_input_loop_tail
= m_tail
? m_tail
: m_head
;
606 usimple_unlock(&dlil_input_lock
);
608 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
614 dlil_input_packet(struct ifnet
*ifp
, struct mbuf
*m
,
617 struct ifnet
*orig_ifp
= 0;
618 struct dlil_filterq_entry
*tmp
;
620 struct if_proto
*ifproto
= 0;
621 struct if_proto
*proto
;
622 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
625 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_START
,0,0,0,0,0);
628 * Run interface filters
631 while (orig_ifp
!= ifp
) {
634 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
635 if (IFILT(tmp
).filter_if_input
) {
636 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
641 if (retval
== EJUSTRETURN
)
655 ifp
->if_lastchange
= time
;
658 * Call family demux module. If the demux module finds a match
659 * for the frame it will fill-in the ifproto pointer.
662 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
664 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
667 if ((retval
) && (retval
!= EJUSTRETURN
) && (ifp
->offercnt
)) {
669 * No match was found, look for any offers.
671 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
672 TAILQ_FOREACH(proto
, tmp
, next
) {
673 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
682 if (retval
!= EJUSTRETURN
) {
691 printf("ERROR - dlil_input - if_demux didn't return an if_proto pointer\n");
697 * Call any attached protocol filters.
700 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
701 if (PFILT(tmp
).filter_dl_input
) {
702 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
708 if (retval
== EJUSTRETURN
)
720 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
721 ifp
, ifproto
->dl_tag
,
724 if (retval
== EJUSTRETURN
)
730 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_END
,0,0,0,0,0);
736 void ether_input(ifp
, eh
, m
)
738 struct ether_header
*eh
;
742 kprintf("Someone is calling ether_input!!\n");
744 dlil_input(ifp
, m
, NULL
);
749 dlil_event(struct ifnet
*ifp
, struct kern_event_msg
*event
)
751 struct dlil_filterq_entry
*filt
;
753 struct ifnet
*orig_ifp
= 0;
754 struct if_proto
*proto
;
755 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
756 struct kev_msg kev_msg
;
757 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
758 boolean_t funnel_state
;
761 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
763 while (orig_ifp
!= ifp
) {
766 TAILQ_FOREACH_REVERSE(filt
, fhead
, que
, dlil_filterq_head
) {
767 if (IFILT(filt
).filter_if_event
) {
768 retval
= (*IFILT(filt
).filter_if_event
)(IFILT(filt
).cookie
,
773 (void) thread_funnel_set(network_flock
, funnel_state
);
774 if (retval
== EJUSTRETURN
)
788 * Call Interface Module event hook, if any.
792 retval
= ifp
->if_event(ifp
, (caddr_t
) event
);
795 (void) thread_funnel_set(network_flock
, funnel_state
);
797 if (retval
== EJUSTRETURN
)
805 * Call dl_event entry point for all protocols attached to this interface
808 TAILQ_FOREACH(proto
, tmp
, next
) {
810 * Call any attached protocol filters.
813 TAILQ_FOREACH_REVERSE(filt
, &proto
->pr_flt_head
, que
, dlil_filterq_head
) {
814 if (PFILT(filt
).filter_dl_event
) {
815 retval
= (*PFILT(filt
).filter_dl_event
)(PFILT(filt
).cookie
,
819 (void) thread_funnel_set(network_flock
, funnel_state
);
820 if (retval
== EJUSTRETURN
)
830 * Finally, call the dl_event entry point (if any)
834 retval
= (*proto
->dl_event
)(event
, proto
->dl_tag
);
836 if (retval
== EJUSTRETURN
) {
837 (void) thread_funnel_set(network_flock
, funnel_state
);
844 * Now, post this event to the Kernel Event message queue
847 kev_msg
.vendor_code
= event
->vendor_code
;
848 kev_msg
.kev_class
= event
->kev_class
;
849 kev_msg
.kev_subclass
= event
->kev_subclass
;
850 kev_msg
.event_code
= event
->event_code
;
851 kev_msg
.dv
[0].data_ptr
= &event
->event_data
[0];
852 kev_msg
.dv
[0].data_length
= event
->total_size
- KEV_MSG_HEADER_SIZE
;
853 kev_msg
.dv
[1].data_length
= 0;
855 kev_post_msg(&kev_msg
);
857 (void) thread_funnel_set(network_flock
, funnel_state
);
864 dlil_output(u_long dl_tag
,
867 struct sockaddr
*dest
,
873 struct ifnet
*orig_ifp
= 0;
875 struct if_proto
*proto
;
876 struct dlil_filterq_entry
*tmp
;
878 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
879 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
880 struct dlil_filterq_head
*fhead
;
882 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_START
,0,0,0,0,0);
884 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0) {
889 ifp
= dl_tag_array
[dl_tag
].ifp
;
890 proto
= dl_tag_array
[dl_tag
].proto
;
892 frame_type
= frame_type_buffer
;
893 dst_linkaddr
= dst_linkaddr_buffer
;
895 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
897 if ((raw
== 0) && (proto
->dl_pre_output
)) {
898 retval
= (*proto
->dl_pre_output
)(ifp
, &m
, dest
, route
,
899 frame_type
, dst_linkaddr
, dl_tag
);
901 if (retval
== EJUSTRETURN
)
911 * Run any attached protocol filters.
914 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
915 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
916 if (PFILT(tmp
).filter_dl_output
) {
917 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
918 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
920 if (retval
== EJUSTRETURN
)
933 * Call framing module
935 if ((raw
== 0) && (ifp
->if_framer
)) {
936 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
938 if (retval
== EJUSTRETURN
)
950 struct mbuf
*m0
= m
;
951 struct ether_header
*eh
= mtod(m
, struct ether_header
*);
953 if (m
->m_pkthdr
.rcvif
)
954 m
->m_pkthdr
.rcvif
= NULL
;
955 ifp
= bridge_dst_lookup(eh
);
956 bdg_forward(&m0
, ifp
);
966 * Let interface filters (if any) do their thing ...
969 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
970 if (TAILQ_EMPTY(fhead
) == 0) {
971 while (orig_ifp
!= ifp
) {
973 TAILQ_FOREACH(tmp
, fhead
, que
) {
974 if (IFILT(tmp
).filter_if_output
) {
975 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
979 if (retval
== EJUSTRETURN
)
996 * Finally, call the driver.
999 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_START
, 0,0,0,0,0);
1000 retval
= (*ifp
->if_output
)(ifp
, m
);
1001 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_END
, 0,0,0,0,0);
1003 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_END
,0,0,0,0,0);
1005 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1013 dlil_ioctl(u_long proto_fam
,
1018 struct dlil_filterq_entry
*tmp
;
1019 struct dlil_filterq_head
*fhead
;
1020 int retval
= EOPNOTSUPP
;
1021 int retval2
= EOPNOTSUPP
;
1023 struct if_family_str
*if_family
;
1027 retval
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
,
1028 proto_fam
, &dl_tag
);
1031 if (dl_tag_array
[dl_tag
].ifp
!= ifp
)
1035 * Run any attached protocol filters.
1037 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1038 if (PFILT(tmp
).filter_dl_ioctl
) {
1040 (*PFILT(tmp
).filter_dl_ioctl
)(PFILT(tmp
).cookie
,
1041 dl_tag_array
[dl_tag
].ifp
,
1046 if (retval
== EJUSTRETURN
)
1054 if (dl_tag_array
[dl_tag
].proto
->dl_ioctl
)
1056 (*dl_tag_array
[dl_tag
].proto
->dl_ioctl
)(dl_tag
,
1057 dl_tag_array
[dl_tag
].ifp
,
1061 retval
= EOPNOTSUPP
;
1067 if ((retval
) && (retval
!= EOPNOTSUPP
)) {
1068 if (retval
== EJUSTRETURN
)
1075 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1076 TAILQ_FOREACH(tmp
, fhead
, que
) {
1077 if (IFILT(tmp
).filter_if_ioctl
) {
1078 retval2
= (*IFILT(tmp
).filter_if_ioctl
)(IFILT(tmp
).cookie
, ifp
,
1079 ioctl_code
, ioctl_arg
);
1081 if (retval2
== EJUSTRETURN
)
1090 if_family
= find_family_module(ifp
->if_family
);
1091 if ((if_family
) && (if_family
->ifmod_ioctl
)) {
1092 retval2
= (*if_family
->ifmod_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1094 if ((retval2
) && (retval2
!= EOPNOTSUPP
)) {
1095 if (retval2
== EJUSTRETURN
)
1101 if (retval
== EOPNOTSUPP
)
1106 retval2
= (*ifp
->if_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1108 if (retval
== EOPNOTSUPP
)
1111 if (retval2
== EOPNOTSUPP
)
1120 dlil_attach_protocol(struct dlil_proto_reg_str
*proto
,
1124 struct if_proto
*ifproto
;
1126 struct if_family_str
*if_family
;
1127 struct dlil_proto_head
*tmp
;
1128 struct kev_dl_proto_data ev_pr_data
;
1130 boolean_t funnel_state
;
1133 if ((proto
->protocol_family
== 0) || (proto
->interface_family
== 0))
1136 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1138 if_family
= find_family_module(proto
->interface_family
);
1139 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1140 kprintf("dlil_attach_protocol -- no interface family module %d",
1141 proto
->interface_family
);
1146 ifp
= ifbyfamily(proto
->interface_family
, proto
->unit_number
);
1148 kprintf("dlil_attach_protocol -- no such interface %d unit %d\n",
1149 proto
->interface_family
, proto
->unit_number
);
1154 if (dlil_find_dltag(proto
->interface_family
, proto
->unit_number
,
1155 proto
->protocol_family
, &i
) == 0) {
1160 for (i
=1; i
< dl_tag_nb
; i
++)
1161 if (dl_tag_array
[i
].ifp
== 0)
1164 if (i
== dl_tag_nb
) {
1165 // expand the tag array by MAX_DL_TAGS
1166 MALLOC(p
, u_char
*, sizeof(struct dl_tag_str
) * (dl_tag_nb
+ MAX_DL_TAGS
), M_NKE
, M_WAITOK
);
1171 bcopy(dl_tag_array
, p
, sizeof(struct dl_tag_str
) * dl_tag_nb
);
1172 bzero(p
+ sizeof(struct dl_tag_str
) * dl_tag_nb
, sizeof(struct dl_tag_str
) * MAX_DL_TAGS
);
1173 dl_tag_nb
+= MAX_DL_TAGS
;
1174 FREE(dl_tag_array
, M_NKE
);
1175 dl_tag_array
= (struct dl_tag_str
*)p
;
1179 * Allocate and init a new if_proto structure
1182 ifproto
= _MALLOC(sizeof(struct if_proto
), M_IFADDR
, M_WAITOK
);
1184 printf("ERROR - DLIL failed if_proto allocation\n");
1189 bzero(ifproto
, sizeof(struct if_proto
));
1191 dl_tag_array
[i
].ifp
= ifp
;
1192 dl_tag_array
[i
].proto
= ifproto
;
1193 dl_tag_array
[i
].pr_flt_head
= &ifproto
->pr_flt_head
;
1194 ifproto
->dl_tag
= i
;
1197 if (proto
->default_proto
) {
1198 if (ifp
->if_data
.default_proto
== 0)
1199 ifp
->if_data
.default_proto
= i
;
1201 printf("ERROR - dlil_attach_protocol -- Attempt to attach more than one default protocol\n");
1204 ifproto
->protocol_family
= proto
->protocol_family
;
1205 ifproto
->dl_input
= proto
->input
;
1206 ifproto
->dl_pre_output
= proto
->pre_output
;
1207 ifproto
->dl_event
= proto
->event
;
1208 ifproto
->dl_offer
= proto
->offer
;
1209 ifproto
->dl_ioctl
= proto
->ioctl
;
1211 TAILQ_INIT(&ifproto
->pr_flt_head
);
1214 * Call family module add_proto routine so it can refine the
1215 * demux descriptors as it wishes.
1217 retval
= (*if_family
->add_proto
)(&proto
->demux_desc_head
, ifproto
, *dl_tag
);
1219 dl_tag_array
[i
].ifp
= 0;
1220 FREE(ifproto
, M_IFADDR
);
1225 * Add to if_proto list for this interface
1228 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1229 TAILQ_INSERT_TAIL(tmp
, ifproto
, next
);
1231 if (ifproto
->dl_offer
)
1234 /* the reserved field carries the number of protocol still attached (subject to change) */
1235 ev_pr_data
.proto_family
= proto
->protocol_family
;
1236 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1237 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_ATTACHED
,
1238 (struct net_event_data
*)&ev_pr_data
,
1239 sizeof(struct kev_dl_proto_data
));
1243 thread_funnel_set(network_flock
, funnel_state
);
1250 dlil_detach_protocol(u_long dl_tag
)
1253 struct ifnet
*orig_ifp
=0;
1254 struct if_proto
*proto
;
1255 struct dlil_proto_head
*tmp
;
1256 struct if_family_str
*if_family
;
1257 struct dlil_filterq_entry
*filter
;
1259 struct dlil_filterq_head
*fhead
;
1260 struct kev_dl_proto_data ev_pr_data
;
1261 boolean_t funnel_state
;
1263 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1266 if (dl_tag
>= dl_tag_nb
|| dl_tag_array
[dl_tag
].ifp
== 0) {
1271 ifp
= dl_tag_array
[dl_tag
].ifp
;
1272 proto
= dl_tag_array
[dl_tag
].proto
;
1274 if_family
= find_family_module(ifp
->if_family
);
1275 if (if_family
== NULL
) {
1280 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1283 * Call family module del_proto
1286 (*if_family
->del_proto
)(proto
, dl_tag
);
1290 * Remove and deallocate any attached protocol filters
1293 while (filter
= TAILQ_FIRST(&proto
->pr_flt_head
))
1294 dlil_detach_filter(filter
->filter_id
);
1296 if (proto
->dl_offer
)
1299 if (ifp
->if_data
.default_proto
== dl_tag
)
1300 ifp
->if_data
.default_proto
= 0;
1301 dl_tag_array
[dl_tag
].ifp
= 0;
1303 /* the reserved field carries the number of protocol still attached (subject to change) */
1304 ev_pr_data
.proto_family
= proto
->protocol_family
;
1307 * Cleanup routes that may still be in the routing table for that interface/protocol pair.
1310 if_rtproto_del(ifp
, proto
->protocol_family
);
1312 TAILQ_REMOVE(tmp
, proto
, next
);
1313 FREE(proto
, M_IFADDR
);
1316 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1317 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_DETACHED
,
1318 (struct net_event_data
*)&ev_pr_data
,
1319 sizeof(struct kev_dl_proto_data
));
1321 if (ifp
->refcnt
== 0) {
1323 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1325 (*if_family
->del_if
)(ifp
);
1327 if (--if_family
->refcnt
== 0) {
1328 if (if_family
->shutdown
)
1329 (*if_family
->shutdown
)();
1331 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1332 FREE(if_family
, M_IFADDR
);
1335 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1336 while (orig_ifp
!= ifp
) {
1339 TAILQ_FOREACH(filter
, fhead
, que
) {
1340 if (IFILT(filter
).filter_if_free
) {
1341 retval
= (*IFILT(filter
).filter_if_free
)(IFILT(filter
).cookie
, ifp
);
1344 thread_funnel_set(network_flock
, funnel_state
);
1348 if (ifp
!= orig_ifp
)
1353 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1355 (*ifp
->if_free
)(ifp
);
1360 thread_funnel_set(network_flock
, funnel_state
);
1369 dlil_if_attach(struct ifnet
*ifp
)
1371 u_long interface_family
= ifp
->if_family
;
1372 struct if_family_str
*if_family
;
1373 struct dlil_proto_head
*tmp
;
1376 boolean_t funnel_state
;
1378 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1380 if (ifnet_inited
== 0) {
1385 if_family
= find_family_module(interface_family
);
1387 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1389 kprintf("Attempt to attach interface without family module - %d\n",
1391 thread_funnel_set(network_flock
, funnel_state
);
1395 if (ifp
->refcnt
== 0) {
1397 * Call the family module to fill in the appropriate fields in the
1401 stat
= (*if_family
->add_if
)(ifp
);
1404 kprintf("dlil_if_attach -- add_if failed with %d\n", stat
);
1405 thread_funnel_set(network_flock
, funnel_state
);
1408 if_family
->refcnt
++;
1411 * Add the ifp to the interface list.
1414 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1417 ifp
->if_data
.default_proto
= 0;
1419 TAILQ_INIT(&ifp
->if_flt_head
);
1422 if (if_family
->init_if
) {
1423 stat
= (*if_family
->init_if
)(ifp
);
1425 kprintf("dlil_if_attach -- init_if failed with %d\n", stat
);
1432 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_ATTACHED
, 0, 0);
1435 thread_funnel_set(network_flock
, funnel_state
);
1441 dlil_if_detach(struct ifnet
*ifp
)
1443 struct if_proto
*proto
;
1444 struct dlil_filterq_entry
*if_filter
;
1445 struct if_family_str
*if_family
;
1446 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1448 struct kev_msg ev_msg
;
1449 boolean_t funnel_state
;
1451 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1454 if_family
= find_family_module(ifp
->if_family
);
1457 kprintf("Attempt to detach interface without family module - %s\n",
1460 thread_funnel_set(network_flock
, funnel_state
);
1464 while (if_filter
= TAILQ_FIRST(fhead
))
1465 dlil_detach_filter(if_filter
->filter_id
);
1469 if (ifp
->refcnt
== 0) {
1470 /* Let BPF know the interface is detaching. */
1472 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1474 (*if_family
->del_if
)(ifp
);
1476 if (--if_family
->refcnt
== 0) {
1477 if (if_family
->shutdown
)
1478 (*if_family
->shutdown
)();
1480 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1481 FREE(if_family
, M_IFADDR
);
1484 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1486 thread_funnel_set(network_flock
, funnel_state
);
1491 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHING
, 0, 0);
1493 thread_funnel_set(network_flock
, funnel_state
);
1494 return DLIL_WAIT_FOR_FREE
;
1500 dlil_reg_if_modules(u_long interface_family
,
1501 struct dlil_ifmod_reg_str
*ifmod
)
1503 struct if_family_str
*if_family
;
1505 boolean_t funnel_state
;
1508 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1510 if (find_family_module(interface_family
)) {
1511 kprintf("Attempt to register dlil family module more than once - %d\n",
1514 thread_funnel_set(network_flock
, funnel_state
);
1518 if ((!ifmod
->add_if
) || (!ifmod
->del_if
) ||
1519 (!ifmod
->add_proto
) || (!ifmod
->del_proto
)) {
1520 kprintf("dlil_reg_if_modules passed at least one null pointer\n");
1522 thread_funnel_set(network_flock
, funnel_state
);
1527 * The following is a gross hack to keep from breaking
1528 * Vicomsoft's internet gateway on Jaguar. Vicomsoft
1529 * does not zero the reserved fields in dlil_ifmod_reg_str.
1530 * As a result, we have to zero any function that used to
1531 * be reserved fields at the time Vicomsoft built their
1532 * kext. Radar #2974305
1534 if (ifmod
->reserved
[0] != 0 || ifmod
->reserved
[1] != 0 || ifmod
->reserved
[2]) {
1535 if (interface_family
== 123) { /* Vicom */
1539 thread_funnel_set(network_flock
, funnel_state
);
1544 if_family
= (struct if_family_str
*) _MALLOC(sizeof(struct if_family_str
), M_IFADDR
, M_WAITOK
);
1546 kprintf("dlil_reg_if_modules failed allocation\n");
1548 thread_funnel_set(network_flock
, funnel_state
);
1552 bzero(if_family
, sizeof(struct if_family_str
));
1554 if_family
->if_family
= interface_family
& 0xffff;
1555 if_family
->shutdown
= ifmod
->shutdown
;
1556 if_family
->add_if
= ifmod
->add_if
;
1557 if_family
->del_if
= ifmod
->del_if
;
1558 if_family
->init_if
= ifmod
->init_if
;
1559 if_family
->add_proto
= ifmod
->add_proto
;
1560 if_family
->del_proto
= ifmod
->del_proto
;
1561 if_family
->ifmod_ioctl
= ifmod
->ifmod_ioctl
;
1562 if_family
->refcnt
= 1;
1563 if_family
->flags
= 0;
1565 TAILQ_INSERT_TAIL(&if_family_head
, if_family
, if_fam_next
);
1567 thread_funnel_set(network_flock
, funnel_state
);
1571 int dlil_dereg_if_modules(u_long interface_family
)
1573 struct if_family_str
*if_family
;
1575 boolean_t funnel_state
;
1577 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1579 if_family
= find_family_module(interface_family
);
1580 if (if_family
== 0) {
1582 thread_funnel_set(network_flock
, funnel_state
);
1586 if (--if_family
->refcnt
== 0) {
1587 if (if_family
->shutdown
)
1588 (*if_family
->shutdown
)();
1590 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1591 FREE(if_family
, M_IFADDR
);
1594 if_family
->flags
|= DLIL_SHUTDOWN
;
1595 ret
= DLIL_WAIT_FOR_FREE
;
1599 thread_funnel_set(network_flock
, funnel_state
);
1608 * Old if_attach no-op'ed function defined here for temporary backwards compatibility
1614 dlil_if_attach(ifp
);
1620 dlil_inject_if_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1622 struct ifnet
*orig_ifp
= 0;
1624 struct if_proto
*ifproto
;
1625 struct if_proto
*proto
;
1626 struct dlil_filterq_entry
*tmp
;
1628 struct dlil_filterq_head
*fhead
;
1631 dlil_stats
.inject_if_in1
++;
1633 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1636 ifp
= dlil_filters
[from_id
].ifp
;
1639 * Let interface filters (if any) do their thing ...
1642 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1645 if (TAILQ_EMPTY(fhead
) == 0) {
1646 while (orig_ifp
!= ifp
) {
1648 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
1649 if ((match_found
) && (IFILT(tmp
).filter_if_input
)) {
1650 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
1655 if (retval
== EJUSTRETURN
)
1665 if (ifp
!= orig_ifp
)
1668 if (from_id
== tmp
->filter_id
)
1674 ifp
->if_lastchange
= time
;
1677 * Call family demux module. If the demux module finds a match
1678 * for the frame it will fill-in the ifproto pointer.
1681 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
1683 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
1686 if ((retval
) && (ifp
->offercnt
)) {
1688 * No match was found, look for any offers.
1690 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1691 TAILQ_FOREACH(proto
, tmp
, next
) {
1692 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
1701 if (retval
!= EJUSTRETURN
) {
1710 printf("ERROR - dlil_inject_if_input -- if_demux didn't return an if_proto pointer\n");
1716 * Call any attached protocol filters.
1718 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1719 if (PFILT(tmp
).filter_dl_input
) {
1720 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1726 if (retval
== EJUSTRETURN
)
1738 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1739 ifp
, ifproto
->dl_tag
,
1742 dlil_stats
.inject_if_in2
++;
1743 if (retval
== EJUSTRETURN
)
1758 dlil_inject_pr_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1760 struct ifnet
*orig_ifp
= 0;
1761 struct dlil_filterq_entry
*tmp
;
1763 struct if_proto
*ifproto
= 0;
1767 dlil_stats
.inject_pr_in1
++;
1768 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1771 ifproto
= dlil_filters
[from_id
].proto
;
1772 ifp
= dlil_filters
[from_id
].ifp
;
1775 * Call any attached protocol filters.
1779 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1780 if ((match_found
) && (PFILT(tmp
).filter_dl_input
)) {
1781 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1787 if (retval
== EJUSTRETURN
)
1796 if (tmp
->filter_id
== from_id
)
1801 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1802 ifp
, ifproto
->dl_tag
,
1805 if (retval
== EJUSTRETURN
)
1811 dlil_stats
.inject_pr_in2
++;
1818 dlil_inject_pr_output(struct mbuf
*m
,
1819 struct sockaddr
*dest
,
1825 struct ifnet
*orig_ifp
= 0;
1827 struct dlil_filterq_entry
*tmp
;
1829 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
1830 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
1831 struct dlil_filterq_head
*fhead
;
1835 dlil_stats
.inject_pr_out1
++;
1838 bcopy(frame_type
, &frame_type_buffer
[0], MAX_FRAME_TYPE_SIZE
* 4);
1843 bcopy(dst_linkaddr
, &dst_linkaddr_buffer
, MAX_LINKADDR
* 4);
1848 if (from_id
>= dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1851 ifp
= dlil_filters
[from_id
].ifp
;
1852 dl_tag
= dlil_filters
[from_id
].proto
->dl_tag
;
1854 frame_type
= frame_type_buffer
;
1855 dst_linkaddr
= dst_linkaddr_buffer
;
1857 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1860 * Run any attached protocol filters.
1864 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
1865 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1866 if ((match_found
) && (PFILT(tmp
).filter_dl_output
)) {
1867 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
1868 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
1870 if (retval
== EJUSTRETURN
)
1879 if (tmp
->filter_id
== from_id
)
1886 * Call framing module
1888 if ((raw
== 0) && (ifp
->if_framer
)) {
1889 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
1891 if (retval
== EJUSTRETURN
)
1904 struct mbuf
*m0
= m
;
1905 struct ether_header
*eh
= mtod(m
, struct ether_header
*);
1907 if (m
->m_pkthdr
.rcvif
)
1908 m
->m_pkthdr
.rcvif
= NULL
;
1909 ifp
= bridge_dst_lookup(eh
);
1910 bdg_forward(&m0
, ifp
);
1920 * Let interface filters (if any) do their thing ...
1923 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1924 if (TAILQ_EMPTY(fhead
) == 0) {
1925 while (orig_ifp
!= ifp
) {
1927 TAILQ_FOREACH(tmp
, fhead
, que
) {
1928 if (IFILT(tmp
).filter_if_output
) {
1929 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1933 if (retval
== EJUSTRETURN
)
1943 if (ifp
!= orig_ifp
)
1950 * Finally, call the driver.
1953 retval
= (*ifp
->if_output
)(ifp
, m
);
1954 dlil_stats
.inject_pr_out2
++;
1955 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1963 dlil_inject_if_output(struct mbuf
*m
, u_long from_id
)
1965 struct ifnet
*orig_ifp
= 0;
1967 struct dlil_filterq_entry
*tmp
;
1969 struct dlil_filterq_head
*fhead
;
1972 dlil_stats
.inject_if_out1
++;
1973 if (from_id
> dlil_filters_nb
|| dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1976 ifp
= dlil_filters
[from_id
].ifp
;
1979 * Let interface filters (if any) do their thing ...
1982 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1985 if (TAILQ_EMPTY(fhead
) == 0) {
1986 while (orig_ifp
!= ifp
) {
1988 TAILQ_FOREACH(tmp
, fhead
, que
) {
1989 if ((match_found
) && (IFILT(tmp
).filter_if_output
)) {
1990 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1994 if (retval
== EJUSTRETURN
)
2004 if (ifp
!= orig_ifp
)
2007 if (from_id
== tmp
->filter_id
)
2014 * Finally, call the driver.
2017 retval
= (*ifp
->if_output
)(ifp
, m
);
2018 dlil_stats
.inject_if_out2
++;
2019 if ((retval
== 0) || (retval
== EJUSTRETURN
))
2026 int dlil_recycle_ioctl(struct ifnet
*ifnet_ptr
, u_long ioctl_code
, void *ioctl_arg
)
2033 int dlil_recycle_output(struct ifnet
*ifnet_ptr
, struct mbuf
*m
)
2041 int dlil_recycle_free(struct ifnet
*ifnet_ptr
)
2047 int dlil_recycle_set_bpf_tap(struct ifnet
*ifp
, int mode
,
2048 int (*bpf_callback
)(struct ifnet
*, struct mbuf
*))
2050 /* XXX not sure what to do here */
2054 int dlil_if_acquire(u_long family
, void *uniqueid
, size_t uniqueid_len
,
2057 struct ifnet
*ifp1
= NULL
;
2058 struct dlil_ifnet
*dlifp1
= NULL
;
2060 boolean_t funnel_state
;
2062 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
2065 TAILQ_FOREACH(dlifp1
, &dlil_ifnet_head
, dl_if_link
) {
2067 ifp1
= (struct ifnet
*)dlifp1
;
2069 if (ifp1
->if_family
== family
) {
2071 /* same uniqueid and same len or no unique id specified */
2072 if ((uniqueid_len
== dlifp1
->if_uniqueid_len
)
2073 && !bcmp(uniqueid
, dlifp1
->if_uniqueid
, uniqueid_len
)) {
2075 /* check for matching interface in use */
2076 if (ifp1
->if_eflags
& IFEF_INUSE
) {
2084 ifp1
->if_eflags
|= (IFEF_INUSE
+ IFEF_REUSE
);
2092 /* no interface found, allocate a new one */
2093 MALLOC(dlifp1
, struct dlil_ifnet
*, sizeof(*dlifp1
), M_NKE
, M_WAITOK
);
2099 bzero(dlifp1
, sizeof(*dlifp1
));
2102 MALLOC(dlifp1
->if_uniqueid
, void *, uniqueid_len
, M_NKE
, M_WAITOK
);
2103 if (dlifp1
->if_uniqueid
== 0) {
2104 FREE(dlifp1
, M_NKE
);
2108 bcopy(uniqueid
, dlifp1
->if_uniqueid
, uniqueid_len
);
2109 dlifp1
->if_uniqueid_len
= uniqueid_len
;
2112 ifp1
= (struct ifnet
*)dlifp1
;
2113 ifp1
->if_eflags
|= IFEF_INUSE
;
2115 TAILQ_INSERT_TAIL(&dlil_ifnet_head
, dlifp1
, dl_if_link
);
2122 thread_funnel_set(network_flock
, funnel_state
);
2126 void dlil_if_release(struct ifnet
*ifp
)
2128 struct dlil_ifnet
*dlifp
= (struct dlil_ifnet
*)ifp
;
2130 boolean_t funnel_state
;
2132 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
2135 ifp
->if_eflags
&= ~IFEF_INUSE
;
2136 ifp
->if_ioctl
= dlil_recycle_ioctl
;
2137 ifp
->if_output
= dlil_recycle_output
;
2138 ifp
->if_free
= dlil_recycle_free
;
2139 ifp
->if_set_bpf_tap
= dlil_recycle_set_bpf_tap
;
2141 strncpy(dlifp
->if_namestorage
, ifp
->if_name
, IFNAMSIZ
);
2142 ifp
->if_name
= dlifp
->if_namestorage
;
2145 thread_funnel_set(network_flock
, funnel_state
);