#define DLIL_PRINTF kprintf
#endif
-//#define DLIL_ALWAYS_DELAY_DETACH 1
-
enum {
kProtoKPI_DLIL = 0,
kProtoKPI_v1 = 1
/* Setup the lock groups we will use */
grp_attributes = lck_grp_attr_alloc_init();
- lck_grp_attr_setdefault(grp_attributes);
dlil_lock_group = lck_grp_alloc_init("dlil internal locks", grp_attributes);
#if IFNET_RW_LOCK
/* Setup the lock attributes we will use */
lck_attributes = lck_attr_alloc_init();
- lck_attr_setdefault(lck_attributes);
ifnet_lock_attr = lck_attr_alloc_init();
- lck_attr_setdefault(ifnet_lock_attr);
dlil_input_lock = lck_spin_alloc_init(input_lock_grp, lck_attributes);
input_lock_grp = 0;
{
int retval = 0;
-
- /* Take the write lock */
-#if DLIL_ALWAYS_DELAY_DETACH
- retval = EDEADLK;
-#else
- if (detached == 0 && (retval = dlil_write_begin()) != 0)
-#endif
- {
+ if (detached == 0) {
+ ifnet_t ifp = NULL;
+ interface_filter_t entry = NULL;
+
+ /* Take the write lock */
+ retval = dlil_write_begin();
+ if (retval != 0 && retval != EDEADLK)
+ return retval;
+
+ /*
+ * At this point either we have the write lock (retval == 0)
+ * or we couldn't get it (retval == EDEADLK) because someone
+ * else up the stack is holding the read lock. It is safe to
+ * read, either the read or write is held. Verify the filter
+ * parameter before proceeding.
+ */
+ ifnet_head_lock_shared();
+ TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
+ TAILQ_FOREACH(entry, &ifp->if_flt_head, filt_next) {
+ if (entry == filter)
+ break;
+ }
+ if (entry == filter)
+ break;
+ }
+ ifnet_head_done();
+
+ if (entry != filter) {
+ /* filter parameter is not a valid filter ref */
+ if (retval == 0) {
+ dlil_write_end();
+ }
+ return EINVAL;
+ }
+
if (retval == EDEADLK) {
/* Perform a delayed detach */
filter->filt_detaching = 1;
dlil_detach_waiting = 1;
wakeup(&dlil_detach_waiting);
- retval = 0;
+ return 0;
}
- return retval;
- }
-
- if (detached == 0)
- TAILQ_REMOVE(&filter->filt_ifp->if_flt_head, filter, filt_next);
-
- /* release the write lock */
- if (detached == 0)
+
+ /* Remove the filter from the list */
+ TAILQ_REMOVE(&ifp->if_flt_head, filter, filt_next);
dlil_write_end();
+ }
+ /* Call the detached funciton if there is one */
if (filter->filt_detached)
filter->filt_detached(filter->filt_cookie, filter->filt_ifp);
+ /* Free the filter */
FREE(filter, M_NKE);
return retval;
void
dlil_detach_filter(interface_filter_t filter)
{
+ if (filter == NULL)
+ return;
dlil_detach_filter_internal(filter, 0);
}
return result;
}
+int
dlil_output_list(
struct ifnet* ifp,
u_long proto_family,
int use_reached_zero = 0;
-#if DLIL_ALWAYS_DELAY_DETACH
- {
- retval = EDEADLK;
-#else
if ((retval = dlil_write_begin()) != 0) {
-#endif
if (retval == EDEADLK) {
retval = 0;
dlil_read_begin();