xref: /illumos-gate/usr/src/uts/common/fs/sockfs/sockfilter.c (revision 41cf421d9c6400a15b7c05a8f75a59121e759f6c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <sys/systm.h>
26 #include <sys/sysmacros.h>
27 #include <sys/cmn_err.h>
28 #include <sys/disp.h>
29 #include <sys/list.h>
30 #include <sys/mutex.h>
31 #include <sys/note.h>
32 #include <sys/rwlock.h>
33 #include <sys/stropts.h>
34 #include <sys/taskq.h>
35 #include <sys/socketvar.h>
36 #include <fs/sockfs/sockcommon.h>
37 #include <fs/sockfs/sockfilter_impl.h>
38 
39 /*
40  * Socket Filter Framework
41  *
42  * Socket filter entry (sof_entry_t):
43  *
44  *   There exists one entry for each configured filter (done via soconfig(1M)),
45  *   and they are all in sof_entry_list. In addition to the global list, each
46  *   sockparams entry maintains a list of filters that is interested in that
47  *   particular socket type. So the filter entry may be referenced by multiple
48  *   sockparams. The set of sockparams referencing a filter may change as
49  *   socket types are added and/or removed from the system. Both sof_entry_list
50  *   and the sockparams list is protected by sockconf_lock.
51  *
52  *   Each filter entry has a ref count which is incremented whenever a filter
53  *   is attached to a socket. An entry is marked SOFEF_CONDEMED when it is
54  *   unconfigured, which will result in the entry being freed when its ref
55  *   count reaches zero.
56  *
57  * Socket filter module (sof_module_t):
58  *
59  *   Modules are created by sof_register() and placed in sof_module_list,
60  *   which is protected by sof_module_lock. Each module has a reference count
61  *   that is incremented when a filter entry is using the module. A module
62  *   can be destroyed by sof_register() only when it's ref count is zero.
63  *
64  * Socket filter instance (sof_instance_t):
65  *
66  *   Whenever a filter is attached to a socket (sonode), a new instance is
67  *   created. The socket is guaranteed to be single threaded when filters are
68  *   being attached/detached. The instance uses the sonode's so_lock for
69  *   protection.
70  *
71  *   The lifetime of an instance is the same as the socket it's attached to.
72  *
73  * How things link together:
74  *
75  *      sockparams.sp_{auto,prog}_filters -> sp_filter_t -> sp_filter_t
76  *      ^                                    |              |
77  *      |                                    |              |
78  *   sonode.so_filter_top -> sof_instance_t  |              |
79  *                                     |     |              |
80  *                                     v     v              v
81  *    sof_entry_list -> sof_entry_t -> sof_entry -> ... -> sof_entry_t
82  *                                     |
83  *                                     v
84  *           sof_module_list -> sof_module_t -> ... -> sof_module_t
85  */
86 
87 static list_t 	sof_entry_list;		/* list of configured filters */
88 
89 static list_t	sof_module_list;	/* list of loaded filter modules */
90 static kmutex_t	sof_module_lock;	/* protect the module list */
91 
92 static sof_kstat_t	sof_stat;
93 static kstat_t 		*sof_stat_ksp;
94 
95 #ifdef DEBUG
96 static int socket_filter_debug = 0;
97 #endif
98 
99 /*
100  * A connection that has been deferred for more than `sof_defer_drop_time'
101  * ticks can be dropped to make room for new connections. A connection that
102  * is to be dropped is moved over to `sof_close_deferred_list' where it will
103  * be closed by sof_close_deferred() (which is running on a taskq). Connections
104  * will not be moved over to the close list if it grows larger than
105  * `sof_close_deferred_max_backlog'.
106  */
107 clock_t		sof_defer_drop_time = 3000;
108 uint_t		sof_close_deferred_max_backlog = 1000;
109 
110 taskq_t		*sof_close_deferred_taskq;
111 boolean_t	sof_close_deferred_running;
112 uint_t		sof_close_deferred_backlog;
113 list_t		sof_close_deferred_list;
114 kmutex_t	sof_close_deferred_lock;
115 
116 static void	sof_close_deferred(void *);
117 
118 static void		sof_module_rele(sof_module_t *);
119 static sof_module_t 	*sof_module_hold_by_name(const char *, const char *);
120 
121 static int		sof_entry_load_module(sof_entry_t *);
122 static void 		sof_entry_hold(sof_entry_t *);
123 static void 		sof_entry_rele(sof_entry_t *);
124 static int 		sof_entry_kstat_create(sof_entry_t *);
125 static void 		sof_entry_kstat_destroy(sof_entry_t *);
126 
127 static sof_instance_t 	*sof_instance_create(sof_entry_t *, struct sonode *);
128 static void		sof_instance_destroy(sof_instance_t *);
129 
130 static int
131 sof_kstat_update(kstat_t *ksp, int rw)
132 {
133 	_NOTE(ARGUNUSED(ksp));
134 
135 	if (rw == KSTAT_WRITE)
136 		return (EACCES);
137 
138 	sof_stat.sofks_defer_close_backlog.value.ui64 =
139 	    sof_close_deferred_backlog;
140 
141 	return (0);
142 }
143 
144 void
145 sof_init(void)
146 {
147 	list_create(&sof_entry_list, sizeof (sof_entry_t),
148 	    offsetof(sof_entry_t, sofe_node));
149 	list_create(&sof_module_list, sizeof (sof_module_t),
150 	    offsetof(sof_module_t, sofm_node));
151 	list_create(&sof_close_deferred_list, sizeof (struct sonode),
152 	    offsetof(struct sonode, so_acceptq_node));
153 
154 	sof_close_deferred_taskq = taskq_create("sof_close_deferred_taskq",
155 	    1, minclsyspri, 1, INT_MAX, TASKQ_PREPOPULATE);
156 	sof_close_deferred_running = B_FALSE;
157 	sof_close_deferred_backlog = 0;
158 
159 	mutex_init(&sof_close_deferred_lock, NULL, MUTEX_DEFAULT, 0);
160 	mutex_init(&sof_module_lock, NULL, MUTEX_DEFAULT, 0);
161 
162 	sof_stat_ksp = kstat_create("sockfs", 0, "sockfilter", "misc",
163 	    KSTAT_TYPE_NAMED, sizeof (sof_kstat_t) / sizeof (kstat_named_t),
164 	    KSTAT_FLAG_VIRTUAL);
165 
166 	if (sof_stat_ksp == NULL)
167 		return;
168 
169 	kstat_named_init(&sof_stat.sofks_defer_closed, "defer_closed",
170 	    KSTAT_DATA_UINT64);
171 	kstat_named_init(&sof_stat.sofks_defer_close_backlog,
172 	    "defer_close_backlog", KSTAT_DATA_UINT64);
173 	kstat_named_init(&sof_stat.sofks_defer_close_failed_backlog_too_big,
174 	    "defer_close_failed_backlog_too_big", KSTAT_DATA_UINT64);
175 
176 	sof_stat_ksp->ks_data = &sof_stat;
177 	sof_stat_ksp->ks_update = sof_kstat_update;
178 	kstat_install(sof_stat_ksp);
179 }
180 
181 /*
182  * Process filter options.
183  */
184 static int
185 sof_setsockopt_impl(struct sonode *so, int option_name,
186     const void *optval, socklen_t optlen, struct cred *cr)
187 {
188 	struct sockparams *sp = so->so_sockparams;
189 	sof_entry_t *ent = NULL;
190 	sp_filter_t *fil;
191 	sof_instance_t *inst;
192 	sof_rval_t rval;
193 	int error;
194 
195 	_NOTE(ARGUNUSED(optlen));
196 
197 	/*
198 	 * Is the filter in a state where filters can be attached?
199 	 */
200 	if (!(so->so_state & SS_FILOP_OK))
201 		return (EINVAL);
202 
203 	if (option_name == FIL_ATTACH) {
204 		/*
205 		 * Make sure there isn't already another instance of the
206 		 * same filter attached to the socket.
207 		 */
208 		for (inst = so->so_filter_top; inst != NULL;
209 		    inst = inst->sofi_next) {
210 			if (strncmp(inst->sofi_filter->sofe_name,
211 			    (const char *)optval, SOF_MAXNAMELEN) == 0)
212 				return (EEXIST);
213 		}
214 		/* Look up the filter. */
215 		rw_enter(&sockconf_lock, RW_READER);
216 		for (fil = list_head(&sp->sp_prog_filters); fil != NULL;
217 		    fil = list_next(&sp->sp_prog_filters, fil)) {
218 			ent = fil->spf_filter;
219 			ASSERT(ent->sofe_flags & SOFEF_PROG);
220 
221 			if (strncmp(ent->sofe_name, (const char *)optval,
222 			    SOF_MAXNAMELEN) == 0)
223 				break;
224 		}
225 		/* No such filter */
226 		if (fil == NULL) {
227 			rw_exit(&sockconf_lock);
228 			return (ENOENT);
229 		}
230 		inst = sof_instance_create(ent, so);
231 		rw_exit(&sockconf_lock);
232 
233 		/* Failed to create an instance; must be out of memory */
234 		if (inst == NULL)
235 			return (ENOMEM);
236 
237 		/*
238 		 * This might be the first time the filter is being used,
239 		 * so try to load the module if it's not already registered.
240 		 */
241 		if (ent->sofe_mod == NULL &&
242 		    (error = sof_entry_load_module(ent)) != 0) {
243 			sof_instance_destroy(inst);
244 			return (error);
245 		}
246 
247 		/* Module loaded OK, so there must be an ops vector */
248 		ASSERT(ent->sofe_mod != NULL);
249 		inst->sofi_ops = &ent->sofe_mod->sofm_ops;
250 
251 		SOF_STAT_ADD(inst, tot_active_attach, 1);
252 		if (inst->sofi_ops->sofop_attach_active != NULL) {
253 			rval = inst->sofi_ops->sofop_attach_active(
254 			    (sof_handle_t)inst, so->so_family, so->so_type,
255 			    so->so_protocol, cr, &inst->sofi_cookie);
256 			if (rval != SOF_RVAL_CONTINUE) {
257 				sof_instance_destroy(inst);
258 				switch (rval) {
259 				case SOF_RVAL_DETACH:
260 					/*
261 					 * Filter does not want to to attach.
262 					 * An error is returned so the user
263 					 * knows the request did not go
264 					 * through.
265 					 */
266 					error = EINVAL;
267 					break;
268 				default:
269 					SOF_STAT_ADD(inst, attach_failures, 1);
270 					/* Not a valid rval for active attach */
271 					ASSERT(rval != SOF_RVAL_DEFER);
272 					error = sof_rval2errno(rval);
273 					break;
274 				}
275 				return (error);
276 			}
277 		}
278 		return (0);
279 	} else if (option_name == FIL_DETACH) {
280 		for (inst = so->so_filter_top; inst != NULL;
281 		    inst = inst->sofi_next) {
282 
283 			ent = inst->sofi_filter;
284 			if (strncmp(ent->sofe_name, (const char *)optval,
285 			    SOF_MAXNAMELEN) == 0)
286 				break;
287 		}
288 		if (inst == NULL)
289 			return (ENXIO);
290 
291 		/* automatic filters cannot be detached */
292 		if (inst->sofi_filter->sofe_flags & SOFEF_AUTO)
293 			return (EINVAL);
294 
295 		if (inst->sofi_ops->sofop_detach != NULL)
296 			inst->sofi_ops->sofop_detach((sof_handle_t)inst,
297 			    inst->sofi_cookie, cr);
298 		sof_instance_destroy(inst);
299 
300 		return (0);
301 	} else {
302 		return (EINVAL);
303 	}
304 }
305 
306 int
307 sof_setsockopt(struct sonode *so, int option_name,
308     const void *optval, socklen_t optlen, struct cred *cr)
309 {
310 	int error;
311 
312 	/*
313 	 * By grabbing the lock as a writer we ensure that no other socket
314 	 * operations can start while the filter stack is being manipulated.
315 	 *
316 	 * We do a tryenter so that in case there is an active thread we
317 	 * ask the caller to try again instead of blocking here until the
318 	 * other thread is done (which could be indefinitely in case of recv).
319 	 */
320 	if (!rw_tryenter(&so->so_fallback_rwlock, RW_WRITER)) {
321 		return (EAGAIN);
322 	}
323 
324 	/* Bail out if a fallback has taken place */
325 	if (so->so_state & SS_FALLBACK_COMP)
326 		error = EINVAL;
327 	else
328 		error = sof_setsockopt_impl(so, option_name, optval,
329 		    optlen, cr);
330 	rw_exit(&so->so_fallback_rwlock);
331 
332 	return (error);
333 }
334 
335 /*
336  * Get filter socket options.
337  */
338 static int
339 sof_getsockopt_impl(struct sonode *so, int option_name,
340     void *optval, socklen_t *optlenp, struct cred *cr)
341 {
342 	sof_instance_t *inst;
343 	struct fil_info *fi;
344 	socklen_t maxsz = *optlenp;
345 	int i;
346 	uint_t cnt;
347 
348 	_NOTE(ARGUNUSED(cr));
349 
350 	if (option_name == FIL_LIST) {
351 		fi = (struct fil_info *)optval;
352 
353 		if (maxsz < sizeof (*fi))
354 			return (EINVAL);
355 
356 		for (inst = so->so_filter_top, cnt = 0; inst != NULL;
357 		    inst = inst->sofi_next)
358 			cnt++;
359 		for (inst = so->so_filter_top, i = 0;
360 		    inst != NULL && (i+1) * sizeof (*fi) <= maxsz;
361 		    inst = inst->sofi_next, i++) {
362 			fi[i].fi_flags =
363 			    (inst->sofi_filter->sofe_flags & SOFEF_AUTO) ?
364 			    FILF_AUTO : FILF_PROG;
365 			if (inst->sofi_flags & SOFIF_BYPASS)
366 				fi[i].fi_flags |= FILF_BYPASS;
367 			(void) strncpy(fi[i].fi_name,
368 			    inst->sofi_filter->sofe_name, FILNAME_MAX);
369 			ASSERT(cnt > 0);
370 			fi[i].fi_pos = --cnt;
371 		}
372 		*optlenp = i * sizeof (*fi);
373 		return (0);
374 	} else {
375 		return (EINVAL);
376 	}
377 }
378 
379 int
380 sof_getsockopt(struct sonode *so, int option_name,
381     void *optval, socklen_t *optlenp, struct cred *cr)
382 {
383 	int error;
384 
385 	/*
386 	 * The fallback lock is used here to serialize set and get
387 	 * filter operations.
388 	 */
389 	rw_enter(&so->so_fallback_rwlock, RW_READER);
390 	if (so->so_state & SS_FALLBACK_COMP)
391 		error = EINVAL;
392 	else
393 		error = sof_getsockopt_impl(so, option_name, optval, optlenp,
394 		    cr);
395 	rw_exit(&so->so_fallback_rwlock);
396 
397 	return (error);
398 }
399 
400 /*
401  * The socket `so' wants to inherit the filter stack from `pso'.
402  * Returns 0 if all went well or an errno otherwise.
403  */
404 int
405 sof_sonode_inherit_filters(struct sonode *so, struct sonode *pso)
406 {
407 	sof_instance_t *inst, *pinst;
408 	sof_rval_t rval;
409 	int error;
410 	struct sockaddr_in6 laddrbuf, faddrbuf;
411 	struct sockaddr_in6 *laddr, *faddr;
412 	socklen_t laddrlen, faddrlen;
413 
414 	/*
415 	 * Make sure there is enough room to retrieve the addresses
416 	 */
417 	if (so->so_proto_props.sopp_maxaddrlen > sizeof (laddrbuf)) {
418 		laddr = kmem_zalloc(so->so_proto_props.sopp_maxaddrlen,
419 		    KM_NOSLEEP);
420 		if (laddr == NULL)
421 			return (ENOMEM);
422 		faddr = kmem_zalloc(so->so_proto_props.sopp_maxaddrlen,
423 		    KM_NOSLEEP);
424 		if (faddr == NULL) {
425 			kmem_free(laddr, so->so_proto_props.sopp_maxaddrlen);
426 			return (ENOMEM);
427 		}
428 		laddrlen = faddrlen = so->so_proto_props.sopp_maxaddrlen;
429 	} else {
430 		laddrlen = faddrlen = sizeof (laddrbuf);
431 		laddr = &laddrbuf;
432 		faddr = &faddrbuf;
433 	}
434 
435 	error = (*so->so_downcalls->sd_getpeername)
436 	    (so->so_proto_handle, (struct sockaddr *)faddr, &faddrlen, kcred);
437 	if (error != 0)
438 		goto out;
439 	error = (*so->so_downcalls->sd_getsockname)
440 	    (so->so_proto_handle, (struct sockaddr *)laddr, &laddrlen, kcred);
441 	if (error != 0)
442 		goto out;
443 
444 	/*
445 	 * The stack is built bottom up. Filters are allowed to modify the
446 	 * the foreign and local addresses during attach.
447 	 */
448 	for (pinst = pso->so_filter_bottom;
449 	    pinst != NULL && !(pinst->sofi_flags & SOFIF_BYPASS);
450 	    pinst = pinst->sofi_prev) {
451 		inst = sof_instance_create(pinst->sofi_filter, so);
452 		if (inst == NULL) {
453 			error = ENOMEM;
454 			goto out;
455 		}
456 		/*
457 		 * The filter module must be loaded since it's already
458 		 * attached to the listener.
459 		 */
460 		ASSERT(pinst->sofi_ops != NULL);
461 		inst->sofi_ops = pinst->sofi_ops;
462 
463 		SOF_STAT_ADD(inst, tot_passive_attach, 1);
464 		if (inst->sofi_ops->sofop_attach_passive != NULL) {
465 			rval = inst->sofi_ops->sofop_attach_passive(
466 			    (sof_handle_t)inst,
467 			    (sof_handle_t)pinst, pinst->sofi_cookie,
468 			    (struct sockaddr *)laddr, laddrlen,
469 			    (struct sockaddr *)faddr, faddrlen,
470 			    &inst->sofi_cookie);
471 			if (rval != SOF_RVAL_CONTINUE) {
472 				if (rval == SOF_RVAL_DEFER) {
473 					mutex_enter(&so->so_lock);
474 					inst->sofi_flags |= SOFIF_DEFER;
475 					so->so_state |= SS_FIL_DEFER;
476 					mutex_exit(&so->so_lock);
477 					so->so_filter_defertime =
478 					    ddi_get_lbolt();
479 					SOF_STAT_ADD(inst, ndeferred, 1);
480 				} else if (rval == SOF_RVAL_DETACH) {
481 					sof_instance_destroy(inst);
482 				} else {
483 					SOF_STAT_ADD(inst, attach_failures, 1);
484 					error = sof_rval2errno(rval);
485 					/*
486 					 * Filters that called attached will be
487 					 * destroyed when the socket goes away,
488 					 * after detach is called.
489 					 */
490 					goto out;
491 				}
492 			}
493 		}
494 	}
495 
496 out:
497 	if (laddr != &laddrbuf) {
498 		kmem_free(laddr, so->so_proto_props.sopp_maxaddrlen);
499 		kmem_free(faddr, so->so_proto_props.sopp_maxaddrlen);
500 	}
501 	return (error);
502 }
503 
504 /*
505  * Attach any automatic filters to sonode `so'. Returns 0 if all went well
506  * and an errno otherwise.
507  */
508 int
509 sof_sonode_autoattach_filters(struct sonode *so, cred_t *cr)
510 {
511 	struct sockparams *sp = so->so_sockparams;
512 	sp_filter_t *fil;
513 	sof_instance_t *inst;
514 	sof_rval_t rval;
515 	int error;
516 
517 	/*
518 	 * A created instance is added to the top of the sonode's filter
519 	 * stack, so traverse the config list in reverse order.
520 	 */
521 	rw_enter(&sockconf_lock, RW_READER);
522 	for (fil = list_tail(&sp->sp_auto_filters);
523 	    fil != NULL; fil = list_prev(&sp->sp_auto_filters, fil)) {
524 		ASSERT(fil->spf_filter->sofe_flags & SOFEF_AUTO);
525 		if (!sof_instance_create(fil->spf_filter, so)) {
526 			rw_exit(&sockconf_lock);
527 			error = ENOMEM; /* must have run out of memory */
528 			goto free_all;
529 		}
530 	}
531 	rw_exit(&sockconf_lock);
532 
533 	/*
534 	 * Notify each filter that it's being attached.
535 	 */
536 	inst = so->so_filter_top;
537 	while (inst != NULL) {
538 		sof_entry_t *ent = inst->sofi_filter;
539 		sof_instance_t *ninst = inst->sofi_next;
540 
541 		/*
542 		 * This might be the first time the filter is being used,
543 		 * so try to load the module if it's not already registered.
544 		 */
545 		if (ent->sofe_mod == NULL &&
546 		    (error = sof_entry_load_module(ent)) != 0)
547 			goto free_detached;
548 
549 		/* Module loaded OK, so there must be an ops vector */
550 		ASSERT(ent->sofe_mod != NULL);
551 		inst->sofi_ops = &ent->sofe_mod->sofm_ops;
552 
553 		SOF_STAT_ADD(inst, tot_active_attach, 1);
554 		if (inst->sofi_ops->sofop_attach_active != NULL) {
555 			rval = inst->sofi_ops->sofop_attach_active(
556 			    (sof_handle_t)inst, so->so_family, so->so_type,
557 			    so->so_protocol, cr, &inst->sofi_cookie);
558 			if (rval != SOF_RVAL_CONTINUE) {
559 				switch (rval) {
560 				case SOF_RVAL_DETACH:
561 					/* filter does not want to attach */
562 					sof_instance_destroy(inst);
563 					break;
564 				default:
565 					SOF_STAT_ADD(inst, attach_failures, 1);
566 					/* Not a valid rval for active attach */
567 					ASSERT(rval != SOF_RVAL_DEFER);
568 					error = sof_rval2errno(rval);
569 					goto free_detached;
570 				}
571 			}
572 		}
573 		inst = ninst;
574 	}
575 	return (0);
576 
577 free_all:
578 	inst = so->so_filter_top;
579 free_detached:
580 	ASSERT(inst != NULL);
581 	/*
582 	 * Destroy all filters for which attach was not called. The other
583 	 * filters will be destroyed (and detach called) when the socket
584 	 * is freed.
585 	 */
586 	do {
587 		sof_instance_t *t = inst->sofi_next;
588 		sof_instance_destroy(inst);
589 		inst = t;
590 	} while (inst != NULL);
591 
592 	return (error);
593 }
594 
595 /*
596  * Detaches and frees all filters attached to sonode `so'.
597  */
598 void
599 sof_sonode_cleanup(struct sonode *so)
600 {
601 	sof_instance_t *inst;
602 
603 	while ((inst = so->so_filter_top) != NULL) {
604 		(inst->sofi_ops->sofop_detach)((sof_handle_t)inst,
605 		    inst->sofi_cookie, kcred);
606 		sof_instance_destroy(inst);
607 	}
608 }
609 
610 /*
611  * Notifies all active filters attached to `so' about the `event' and
612  * where `arg' is an event specific argument.
613  */
614 void
615 sof_sonode_notify_filters(struct sonode *so, sof_event_t event, uintptr_t arg)
616 {
617 	sof_instance_t *inst;
618 
619 	for (inst = so->so_filter_bottom; inst != NULL;
620 	    inst = inst->sofi_prev) {
621 		if (SOF_INTERESTED(inst, notify))
622 			(inst->sofi_ops->sofop_notify)((sof_handle_t)inst,
623 			    inst->sofi_cookie, event, arg);
624 	}
625 }
626 
627 /*
628  * The socket `so' is closing. Notify filters and make sure that there
629  * are no pending tx operations.
630  */
631 void
632 sof_sonode_closing(struct sonode *so)
633 {
634 	/*
635 	 * Notify filters that the socket is being closed. It's OK for
636 	 * filters to inject data.
637 	 */
638 	sof_sonode_notify_filters(so, SOF_EV_CLOSING, (uintptr_t)B_TRUE);
639 
640 	/* wait for filters that are sending out data */
641 	mutex_enter(&so->so_lock);
642 	while (so->so_filter_tx > 0)
643 		cv_wait(&so->so_closing_cv, &so->so_lock);
644 	mutex_exit(&so->so_lock);
645 }
646 
647 /*
648  * Called when socket `so' wants to get rid of a deferred connection.
649  * Returns TRUE if a connection was dropped.
650  */
651 boolean_t
652 sof_sonode_drop_deferred(struct sonode *so)
653 {
654 	struct sonode *def;
655 	clock_t now = ddi_get_lbolt();
656 
657 	if (sof_close_deferred_backlog > sof_close_deferred_max_backlog) {
658 		SOF_GLOBAL_STAT_BUMP(defer_close_failed_backlog_too_big);
659 		return (B_FALSE);
660 	}
661 	mutex_enter(&so->so_acceptq_lock);
662 	if ((def = list_head(&so->so_acceptq_defer)) != NULL &&
663 	    (now - def->so_filter_defertime) > sof_defer_drop_time) {
664 		list_remove(&so->so_acceptq_defer, def);
665 		so->so_acceptq_len--;
666 		mutex_exit(&so->so_acceptq_lock);
667 		def->so_listener = NULL;
668 	} else {
669 		mutex_exit(&so->so_acceptq_lock);
670 		return (B_FALSE);
671 	}
672 
673 	mutex_enter(&sof_close_deferred_lock);
674 	list_insert_tail(&sof_close_deferred_list, def);
675 	sof_close_deferred_backlog++;
676 	if (!sof_close_deferred_running) {
677 		mutex_exit(&sof_close_deferred_lock);
678 		(void) taskq_dispatch(sof_close_deferred_taskq,
679 		    sof_close_deferred, NULL, TQ_NOSLEEP);
680 	} else {
681 		mutex_exit(&sof_close_deferred_lock);
682 	}
683 	return (B_TRUE);
684 }
685 
686 /*
687  * Called from a taskq to close connections that have been deferred for
688  * too long.
689  */
690 void
691 sof_close_deferred(void *unused)
692 {
693 	struct sonode *drop;
694 
695 	_NOTE(ARGUNUSED(unused));
696 
697 	mutex_enter(&sof_close_deferred_lock);
698 	if (!sof_close_deferred_running) {
699 		sof_close_deferred_running = B_TRUE;
700 		while ((drop =
701 		    list_remove_head(&sof_close_deferred_list)) != NULL) {
702 			sof_close_deferred_backlog--;
703 			mutex_exit(&sof_close_deferred_lock);
704 
705 			SOF_GLOBAL_STAT_BUMP(defer_closed);
706 			(void) socket_close(drop, 0, kcred);
707 			socket_destroy(drop);
708 
709 			mutex_enter(&sof_close_deferred_lock);
710 		}
711 		sof_close_deferred_running = B_FALSE;
712 		ASSERT(sof_close_deferred_backlog == 0);
713 	}
714 	mutex_exit(&sof_close_deferred_lock);
715 }
716 
717 /*
718  * Creates a new filter instance from the entry `ent' and attaches
719  * it to the sonode `so'. On success, return a pointer to the created
720  * instance.
721  *
722  * The new instance will be placed on the top of the filter stack.
723  *
724  * The caller is responsible for assigning the instance's ops vector and
725  * calling the filter's attach callback.
726  *
727  * No locks are held while manipulating the sonode fields because we are
728  * guaranteed that this operation is serialized.
729  *
730  * We can be sure that the entry `ent' will not disappear, because the
731  * caller is either holding sockconf_lock (in case of an active open), or is
732  * already holding a reference (in case of a passive open, the listener has
733  * one).
734  */
735 static sof_instance_t *
736 sof_instance_create(sof_entry_t *ent, struct sonode *so)
737 {
738 	sof_instance_t *inst;
739 
740 	inst = kmem_zalloc(sizeof (sof_instance_t), KM_NOSLEEP);
741 	if (inst == NULL)
742 		return (NULL);
743 	sof_entry_hold(ent);
744 	inst->sofi_filter = ent;
745 	inst->sofi_sonode = so;
746 
747 	inst->sofi_next = so->so_filter_top;
748 	if (so->so_filter_top != NULL)
749 		so->so_filter_top->sofi_prev = inst;
750 	else
751 		so->so_filter_bottom = inst;
752 	so->so_filter_top = inst;
753 	so->so_filter_active++;
754 
755 	return (inst);
756 }
757 /*
758  * Destroys the filter instance `inst' and unlinks it from the sonode.
759  *
760  * Any filter private state must be destroyed (via the detach callback)
761  * before the instance is destroyed.
762  */
763 static void
764 sof_instance_destroy(sof_instance_t *inst)
765 {
766 	struct sonode *so = inst->sofi_sonode;
767 
768 	ASSERT(inst->sofi_sonode != NULL);
769 	ASSERT(inst->sofi_filter != NULL);
770 	ASSERT(inst->sofi_prev != NULL || so->so_filter_top == inst);
771 	ASSERT(inst->sofi_next != NULL || so->so_filter_bottom == inst);
772 
773 	if (inst->sofi_prev != NULL)
774 		inst->sofi_prev->sofi_next = inst->sofi_next;
775 	else
776 		so->so_filter_top = inst->sofi_next;
777 
778 	if (inst->sofi_next != NULL)
779 		inst->sofi_next->sofi_prev = inst->sofi_prev;
780 	else
781 		so->so_filter_bottom = inst->sofi_prev;
782 
783 	if (!(inst->sofi_flags & SOFIF_BYPASS)) {
784 		ASSERT(so->so_filter_active > 0);
785 		so->so_filter_active--;
786 	}
787 	if (inst->sofi_flags & SOFIF_DEFER)
788 		SOF_STAT_ADD(inst, ndeferred, -1);
789 	sof_entry_rele(inst->sofi_filter);
790 	kmem_free(inst, sizeof (sof_instance_t));
791 }
792 
793 static sof_entry_t *
794 sof_entry_find(const char *name)
795 {
796 	sof_entry_t *ent;
797 
798 	for (ent = list_head(&sof_entry_list); ent != NULL;
799 	    ent = list_next(&sof_entry_list, ent)) {
800 		if (strncmp(ent->sofe_name, name, SOF_MAXNAMELEN) == 0)
801 			return (ent);
802 	}
803 	return (NULL);
804 }
805 
806 void
807 sof_entry_free(sof_entry_t *ent)
808 {
809 	ASSERT(ent->sofe_refcnt == 0);
810 	ASSERT(!list_link_active(&ent->sofe_node));
811 
812 	if (ent->sofe_hintarg != NULL) {
813 		ASSERT(ent->sofe_hint == SOF_HINT_BEFORE ||
814 		    ent->sofe_hint == SOF_HINT_AFTER);
815 		kmem_free(ent->sofe_hintarg, strlen(ent->sofe_hintarg) + 1);
816 		ent->sofe_hintarg = NULL;
817 	}
818 	if (ent->sofe_socktuple_cnt > 0) {
819 		ASSERT(ent->sofe_socktuple != NULL);
820 		kmem_free(ent->sofe_socktuple,
821 		    sizeof (sof_socktuple_t) * ent->sofe_socktuple_cnt);
822 		ent->sofe_socktuple = NULL;
823 		ent->sofe_socktuple_cnt = 0;
824 	}
825 	sof_entry_kstat_destroy(ent);
826 
827 	mutex_destroy(&ent->sofe_lock);
828 	kmem_free(ent, sizeof (sof_entry_t));
829 }
830 
831 static int
832 sof_entry_kstat_update(kstat_t *ksp, int rw)
833 {
834 	sof_entry_t *ent = ksp->ks_private;
835 
836 	if (rw == KSTAT_WRITE)
837 		return (EACCES);
838 
839 	ent->sofe_kstat.sofek_nactive.value.ui64 = ent->sofe_refcnt;
840 
841 	return (0);
842 }
843 
844 /*
845  * Create the kstat for filter entry `ent'.
846  */
847 static int
848 sof_entry_kstat_create(sof_entry_t *ent)
849 {
850 	char name[SOF_MAXNAMELEN + 7];
851 
852 	(void) snprintf(name, sizeof (name), "filter_%s", ent->sofe_name);
853 	ent->sofe_ksp = kstat_create("sockfs", 0, name, "misc",
854 	    KSTAT_TYPE_NAMED,
855 	    sizeof (sof_entry_kstat_t) / sizeof (kstat_named_t),
856 	    KSTAT_FLAG_VIRTUAL);
857 
858 	if (ent->sofe_ksp == NULL)
859 		return (ENOMEM);
860 
861 	kstat_named_init(&ent->sofe_kstat.sofek_nactive, "nactive",
862 	    KSTAT_DATA_UINT64);
863 	kstat_named_init(&ent->sofe_kstat.sofek_tot_active_attach,
864 	    "tot_active_attach", KSTAT_DATA_UINT64);
865 	kstat_named_init(&ent->sofe_kstat.sofek_tot_passive_attach,
866 	    "tot_passive_attach", KSTAT_DATA_UINT64);
867 	kstat_named_init(&ent->sofe_kstat.sofek_ndeferred, "ndeferred",
868 	    KSTAT_DATA_UINT64);
869 	kstat_named_init(&ent->sofe_kstat.sofek_attach_failures,
870 	    "attach_failures", KSTAT_DATA_UINT64);
871 
872 	ent->sofe_ksp->ks_data = &ent->sofe_kstat;
873 	ent->sofe_ksp->ks_update = sof_entry_kstat_update;
874 	ent->sofe_ksp->ks_private = ent;
875 	kstat_install(ent->sofe_ksp);
876 
877 	return (0);
878 }
879 
880 /*
881  * Destroys the kstat for filter entry `ent'.
882  */
883 static void
884 sof_entry_kstat_destroy(sof_entry_t *ent)
885 {
886 	if (ent->sofe_ksp != NULL) {
887 		kstat_delete(ent->sofe_ksp);
888 		ent->sofe_ksp = NULL;
889 	}
890 }
891 
892 static void
893 sof_entry_hold(sof_entry_t *ent)
894 {
895 	mutex_enter(&ent->sofe_lock);
896 	ent->sofe_refcnt++;
897 	mutex_exit(&ent->sofe_lock);
898 }
899 
900 /*
901  * Decrement the reference count for `ent'. The entry will
902  * drop its' reference on the filter module whenever its'
903  * ref count reaches zero.
904  */
905 static void
906 sof_entry_rele(sof_entry_t *ent)
907 {
908 	mutex_enter(&ent->sofe_lock);
909 	if (--ent->sofe_refcnt == 0) {
910 		sof_module_t *mod = ent->sofe_mod;
911 		ent->sofe_mod = NULL;
912 		if (ent->sofe_flags & SOFEF_CONDEMED) {
913 			mutex_exit(&ent->sofe_lock);
914 			sof_entry_free(ent);
915 		} else {
916 			mutex_exit(&ent->sofe_lock);
917 		}
918 		if (mod != NULL)
919 			sof_module_rele(mod);
920 	} else {
921 		mutex_exit(&ent->sofe_lock);
922 	}
923 }
924 
925 /*
926  * Loads the module used by `ent'
927  */
928 static int
929 sof_entry_load_module(sof_entry_t *ent)
930 {
931 	sof_module_t *mod = sof_module_hold_by_name(ent->sofe_name,
932 	    ent->sofe_modname);
933 
934 	if (mod == NULL)
935 		return (EINVAL);
936 
937 	mutex_enter(&ent->sofe_lock);
938 	/* Another thread might have already loaded the module */
939 	ASSERT(ent->sofe_mod == mod || ent->sofe_mod == NULL);
940 	if (ent->sofe_mod != NULL) {
941 		mutex_exit(&ent->sofe_lock);
942 		sof_module_rele(mod);
943 	} else {
944 		ent->sofe_mod = mod;
945 		mutex_exit(&ent->sofe_lock);
946 	}
947 
948 	return (0);
949 }
950 
951 /*
952  * Add filter entry `ent' to the global list and attach it to all sockparam
953  * entries which the filter is interested in. Upon successful return the filter
954  * will be available for applications to use.
955  */
956 int
957 sof_entry_add(sof_entry_t *ent)
958 {
959 	int error;
960 
961 	/*
962 	 * We hold sockconf_lock as a WRITER for the whole operation,
963 	 * so all operations must be non-blocking.
964 	 */
965 	rw_enter(&sockconf_lock, RW_WRITER);
966 	if (sof_entry_find(ent->sofe_name) != NULL) {
967 		rw_exit(&sockconf_lock);
968 		return (EEXIST);
969 	}
970 
971 	/* The entry is unique; create the kstats */
972 	if (sof_entry_kstat_create(ent) != 0) {
973 		rw_exit(&sockconf_lock);
974 		return (ENOMEM);
975 	}
976 
977 	/*
978 	 * Attach the filter to sockparams of interest.
979 	 */
980 	if ((error = sockparams_new_filter(ent)) != 0) {
981 		sof_entry_kstat_destroy(ent);
982 		rw_exit(&sockconf_lock);
983 		return (error);
984 	}
985 	/*
986 	 * Everything is OK; insert in global list.
987 	 */
988 	list_insert_tail(&sof_entry_list, ent);
989 	rw_exit(&sockconf_lock);
990 
991 	return (0);
992 }
993 
994 /*
995  * Removes the filter entry `ent' from global list and all sockparams.
996  */
997 sof_entry_t *
998 sof_entry_remove_by_name(const char *name)
999 {
1000 	sof_entry_t *ent;
1001 
1002 	rw_enter(&sockconf_lock, RW_WRITER);
1003 	if ((ent = sof_entry_find(name)) == NULL) {
1004 		rw_exit(&sockconf_lock);
1005 		return (NULL);
1006 	}
1007 	list_remove(&sof_entry_list, ent);
1008 	sockparams_filter_cleanup(ent);
1009 	sof_entry_kstat_destroy(ent);
1010 	rw_exit(&sockconf_lock);
1011 
1012 	return (ent);
1013 }
1014 
1015 /*
1016  * Filter entry `ent' will process sockparams entry `sp' to determine whether
1017  * it should be attached to the sockparams. It should be called whenever a new
1018  * filter or sockparams is being added. Returns zero either if the filter is
1019  * not interested in the sockparams or if it successfully attached to the
1020  * sockparams. On failure an errno is returned.
1021  */
1022 int
1023 sof_entry_proc_sockparams(sof_entry_t *ent, struct sockparams *sp)
1024 {
1025 	uint_t i;
1026 	sof_socktuple_t *t = ent->sofe_socktuple;
1027 	sp_filter_t *new, *fil;
1028 
1029 	/* Only interested in non-TPI sockets */
1030 	if (strcmp(sp->sp_smod_name, SOTPI_SMOD_NAME) == 0)
1031 		return (0);
1032 
1033 	for (i = 0; i < ent->sofe_socktuple_cnt; i++) {
1034 		if (t[i].sofst_family == sp->sp_family &&
1035 		    t[i].sofst_type == sp->sp_type &&
1036 		    t[i].sofst_protocol == sp->sp_protocol)
1037 			break;
1038 	}
1039 	/* This filter is not interested in the sockparams entry */
1040 	if (i == ent->sofe_socktuple_cnt)
1041 		return (0);
1042 
1043 	new = kmem_zalloc(sizeof (sp_filter_t), KM_NOSLEEP);
1044 	if (new == NULL)
1045 		return (ENOMEM);
1046 
1047 	new->spf_filter = ent;
1048 	if (ent->sofe_flags & SOFEF_PROG) {
1049 		/* placement is irrelevant for programmatic filters */
1050 		list_insert_head(&sp->sp_prog_filters, new);
1051 		return (0);
1052 	} else {
1053 		ASSERT(ent->sofe_flags & SOFEF_AUTO);
1054 		/*
1055 		 * If the filter specifies a placement hint, then make sure
1056 		 * it can be satisfied.
1057 		 */
1058 		switch (ent->sofe_hint) {
1059 		case SOF_HINT_TOP:
1060 			if ((fil = list_head(&sp->sp_auto_filters)) != NULL &&
1061 			    fil->spf_filter->sofe_hint == SOF_HINT_TOP)
1062 				break;
1063 			list_insert_head(&sp->sp_auto_filters, new);
1064 			return (0);
1065 		case SOF_HINT_BOTTOM:
1066 			if ((fil = list_tail(&sp->sp_auto_filters)) != NULL &&
1067 			    fil->spf_filter->sofe_hint == SOF_HINT_BOTTOM)
1068 				break;
1069 			list_insert_tail(&sp->sp_auto_filters, new);
1070 			return (0);
1071 		case SOF_HINT_BEFORE:
1072 		case SOF_HINT_AFTER:
1073 			for (fil = list_head(&sp->sp_auto_filters);
1074 			    fil != NULL;
1075 			    fil = list_next(&sp->sp_auto_filters, fil)) {
1076 				if (strncmp(ent->sofe_hintarg,
1077 				    fil->spf_filter->sofe_name,
1078 				    SOF_MAXNAMELEN) == 0)
1079 				break;
1080 			}
1081 
1082 			if (fil != NULL) {
1083 				if (ent->sofe_hint == SOF_HINT_BEFORE) {
1084 					if (fil->spf_filter->sofe_hint ==
1085 					    SOF_HINT_TOP)
1086 						break;
1087 					list_insert_before(&sp->sp_auto_filters,
1088 					    fil, new);
1089 				} else {
1090 					if (fil->spf_filter->sofe_hint ==
1091 					    SOF_HINT_BOTTOM)
1092 						break;
1093 					list_insert_after(&sp->sp_auto_filters,
1094 					    fil, new);
1095 				}
1096 				return (0);
1097 			}
1098 			/*FALLTHRU*/
1099 		case SOF_HINT_NONE:
1100 			/*
1101 			 * Insert the new filter at the beginning as long as it
1102 			 * does not violate a TOP hint, otherwise insert in the
1103 			 * next suitable location.
1104 			 */
1105 			if ((fil = list_head(&sp->sp_auto_filters)) != NULL &&
1106 			    fil->spf_filter->sofe_hint == SOF_HINT_TOP) {
1107 				list_insert_after(&sp->sp_auto_filters, fil,
1108 				    new);
1109 			} else {
1110 				list_insert_head(&sp->sp_auto_filters, new);
1111 			}
1112 			return (0);
1113 		}
1114 		/* Failed to insert the filter */
1115 		kmem_free(new, sizeof (sp_filter_t));
1116 		return (ENOSPC);
1117 	}
1118 }
1119 
1120 /*
1121  * Remove all filter entries attached to the sockparams entry `sp'.
1122  */
1123 void
1124 sof_sockparams_fini(struct sockparams *sp)
1125 {
1126 	sp_filter_t *fil;
1127 
1128 	ASSERT(!list_link_active(&sp->sp_node));
1129 
1130 	while ((fil = list_remove_head(&sp->sp_auto_filters)) != NULL)
1131 		kmem_free(fil, sizeof (sp_filter_t));
1132 	while ((fil = list_remove_head(&sp->sp_prog_filters)) != NULL)
1133 		kmem_free(fil, sizeof (sp_filter_t));
1134 }
1135 
1136 /*
1137  * A new sockparams is being added. Walk all filters and attach those that
1138  * are interested in the entry.
1139  *
1140  * It should be called when the sockparams entry is about to be made available
1141  * for use and while holding the sockconf_lock.
1142  */
1143 int
1144 sof_sockparams_init(struct sockparams *sp)
1145 {
1146 	sof_entry_t *ent;
1147 
1148 	ASSERT(RW_WRITE_HELD(&sockconf_lock));
1149 
1150 	for (ent = list_head(&sof_entry_list); ent != NULL;
1151 	    ent = list_next(&sof_entry_list, ent)) {
1152 		if (sof_entry_proc_sockparams(ent, sp) != 0) {
1153 			sof_sockparams_fini(sp);
1154 			return (ENOMEM);
1155 		}
1156 	}
1157 	return (0);
1158 }
1159 
1160 static sof_module_t *
1161 sof_module_find(const char *name)
1162 {
1163 	sof_module_t *ent;
1164 
1165 	ASSERT(MUTEX_HELD(&sof_module_lock));
1166 
1167 	for (ent = list_head(&sof_module_list); ent != NULL;
1168 	    ent = list_next(&sof_module_list, ent))
1169 		if (strcmp(ent->sofm_name, name) == 0)
1170 			return (ent);
1171 	return (NULL);
1172 }
1173 
1174 /*
1175  * Returns a pointer to a module identified by `name' with its ref count
1176  * bumped. An attempt to load the module is done if it's not found in the
1177  * global list.
1178  */
1179 sof_module_t *
1180 sof_module_hold_by_name(const char *name, const char *modname)
1181 {
1182 	ddi_modhandle_t handle = NULL;
1183 	sof_module_t *mod = NULL;
1184 	char *modpath;
1185 	int error;
1186 
1187 	/*
1188 	 * We'll go through the loop at most two times, which will only
1189 	 * happen if the module needs to be loaded.
1190 	 */
1191 	for (;;) {
1192 		mutex_enter(&sof_module_lock);
1193 		mod = sof_module_find(name);
1194 		if (mod != NULL || handle != NULL)
1195 			break;
1196 		mutex_exit(&sof_module_lock);
1197 
1198 		modpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1199 		(void) snprintf(modpath, MAXPATHLEN, "%s/%s", SOF_MODPATH,
1200 		    modname);
1201 		handle = ddi_modopen(modpath, KRTLD_MODE_FIRST, &error);
1202 		kmem_free(modpath, MAXPATHLEN);
1203 		/* Failed to load, then bail */
1204 		if (handle == NULL) {
1205 			cmn_err(CE_WARN,
1206 			    "Failed to load socket filter module: %s (err %d)",
1207 			    modname, error);
1208 			return (NULL);
1209 		}
1210 	}
1211 	if (mod != NULL)
1212 		mod->sofm_refcnt++;
1213 	mutex_exit(&sof_module_lock);
1214 
1215 	if (handle != NULL) {
1216 		(void) ddi_modclose(handle);
1217 		/*
1218 		 * The module was loaded, but the filter module could not be
1219 		 * found. It's likely a misconfigured filter.
1220 		 */
1221 		if (mod == NULL) {
1222 			cmn_err(CE_WARN,
1223 			    "Socket filter module %s was loaded, but did not" \
1224 			    "register. Filter %s is likely misconfigured.",
1225 			    modname, name);
1226 		}
1227 	}
1228 
1229 	return (mod);
1230 }
1231 
1232 void
1233 sof_module_rele(sof_module_t *mod)
1234 {
1235 	mutex_enter(&sof_module_lock);
1236 	mod->sofm_refcnt--;
1237 	mutex_exit(&sof_module_lock);
1238 }
1239 
1240 int
1241 sof_rval2errno(sof_rval_t rval)
1242 {
1243 	if (rval > SOF_RVAL_CONTINUE) {
1244 		return ((int)rval);
1245 	} else {
1246 #ifdef DEBUG
1247 		if (socket_filter_debug)
1248 			printf("sof_rval2errno: invalid rval '%d'\n", rval);
1249 #endif
1250 		return (EINVAL);
1251 	}
1252 }
1253 
1254 /*
1255  * Walk through all the filters attached to `so' and allow each filter
1256  * to process the data using its data_out callback. `mp' is a b_cont chain.
1257  *
1258  * Returns the processed mblk, or NULL if mblk was consumed. The mblk might
1259  * have been consumed as a result of an error, in which case `errp' is set to
1260  * the appropriate errno.
1261  */
1262 mblk_t *
1263 sof_filter_data_out_from(struct sonode *so, sof_instance_t *start,
1264     mblk_t *mp, struct nmsghdr *msg, cred_t *cr, int *errp)
1265 {
1266 	sof_instance_t *inst;
1267 	sof_rval_t rval;
1268 
1269 	_NOTE(ARGUNUSED(so));
1270 
1271 	for (inst = start; inst != NULL; inst = inst->sofi_next) {
1272 		if (!SOF_INTERESTED(inst, data_out))
1273 			continue;
1274 		mp = (inst->sofi_ops->sofop_data_out)((sof_handle_t)inst,
1275 		    inst->sofi_cookie, mp, msg, cr, &rval);
1276 		DTRACE_PROBE2(filter__data, (sof_instance_t), inst,
1277 		    (mblk_t *), mp);
1278 		if (mp == NULL) {
1279 			*errp = sof_rval2errno(rval);
1280 			break;
1281 		}
1282 	}
1283 	return (mp);
1284 }
1285 
1286 /*
1287  * Walk through all the filters attached to `so' and allow each filter
1288  * to process the data using its data_in_proc callback. `mp' is the start of
1289  * a possible b_next chain, and `lastmp' points to the last mblk in the chain.
1290  *
1291  * Returns the processed mblk, or NULL if all mblks in the chain were
1292  * consumed. `lastmp' is updated to point to the last mblk in the processed
1293  * chain.
1294  */
1295 mblk_t *
1296 sof_filter_data_in_proc(struct sonode *so, mblk_t *mp, mblk_t **lastmp)
1297 {
1298 	sof_instance_t *inst;
1299 	size_t len = 0, orig = 0;
1300 	ssize_t diff = 0;
1301 	mblk_t *retmp = NULL, *tailmp, *nextmp;
1302 
1303 	*lastmp = NULL;
1304 	do {
1305 		nextmp = mp->b_next;
1306 		mp->b_next = mp->b_prev = NULL;
1307 		len = orig = msgdsize(mp);
1308 		for (inst = so->so_filter_bottom; inst != NULL;
1309 		    inst = inst->sofi_prev) {
1310 			if (!SOF_INTERESTED(inst, data_in_proc))
1311 				continue;
1312 			mp = (inst->sofi_ops->sofop_data_in_proc)(
1313 			    (sof_handle_t)inst, inst->sofi_cookie, mp,
1314 			    kcred, &len);
1315 			if (mp == NULL)
1316 				break;
1317 		}
1318 		DTRACE_PROBE2(filter__data, (sof_instance_t), inst,
1319 		    (mblk_t *), mp);
1320 		diff += len - orig;
1321 		if (mp == NULL)
1322 			continue;
1323 
1324 		for (tailmp = mp; tailmp->b_cont != NULL;
1325 		    tailmp = tailmp->b_cont)
1326 			;
1327 		mp->b_prev = tailmp;
1328 
1329 		if (*lastmp == NULL)
1330 			retmp = mp;
1331 		else
1332 			(*lastmp)->b_next = mp;
1333 		*lastmp = mp;
1334 	} while ((mp = nextmp) != NULL);
1335 
1336 	/*
1337 	 * The size of the chain has changed; make sure the rcv queue
1338 	 * stays consistent and check if the flow control state should
1339 	 * change.
1340 	 */
1341 	if (diff != 0) {
1342 		DTRACE_PROBE2(filter__data__adjust__qlen,
1343 		    (struct sonode *), so, (size_t), diff);
1344 		mutex_enter(&so->so_lock);
1345 		so->so_rcv_queued += diff;
1346 		/* so_check_flow_control drops so_lock */
1347 		so_check_flow_control(so);
1348 	}
1349 
1350 	return (retmp);
1351 }
1352 
1353 int
1354 sof_filter_bind(struct sonode *so, struct sockaddr *addr,
1355     socklen_t *addrlen, cred_t *cr)
1356 {
1357 	__SOF_FILTER_OP(so, bind, cr, addr, addrlen)
1358 }
1359 
1360 int
1361 sof_filter_listen(struct sonode *so, int *backlogp, cred_t *cr)
1362 {
1363 	__SOF_FILTER_OP(so, listen, cr, backlogp)
1364 }
1365 
1366 int
1367 sof_filter_connect(struct sonode *so, struct sockaddr *addr,
1368     socklen_t *addrlen, cred_t *cr)
1369 {
1370 	__SOF_FILTER_OP(so, connect, cr, addr, addrlen)
1371 }
1372 
1373 int
1374 sof_filter_accept(struct sonode *so, cred_t *cr)
1375 {
1376 	sof_instance_t *inst;
1377 	sof_rval_t rval;
1378 
1379 	for (inst = so->so_filter_top; inst != NULL; inst = inst->sofi_next) {
1380 		if (!SOF_INTERESTED(inst, accept))
1381 			continue;
1382 		rval = (inst->sofi_ops->sofop_accept)((sof_handle_t)inst,
1383 		    inst->sofi_cookie, cr);
1384 		DTRACE_PROBE2(filter__action, (sof_instance_t), inst,
1385 		    (sof_rval_t), rval);
1386 		if (rval != SOF_RVAL_CONTINUE) {
1387 			ASSERT(rval != SOF_RVAL_RETURN);
1388 			return (sof_rval2errno(rval));
1389 		}
1390 	}
1391 	return (-1);
1392 }
1393 
1394 int
1395 sof_filter_shutdown(struct sonode *so, int *howp, cred_t *cr)
1396 {
1397 	__SOF_FILTER_OP(so, shutdown, cr, howp)
1398 }
1399 
1400 int
1401 sof_filter_getsockname(struct sonode *so, struct sockaddr *addr,
1402     socklen_t *addrlenp, cred_t *cr)
1403 {
1404 	__SOF_FILTER_OP(so, getsockname, cr, addr, addrlenp)
1405 }
1406 
1407 int
1408 sof_filter_getpeername(struct sonode *so, struct sockaddr *addr,
1409     socklen_t *addrlenp, cred_t *cr)
1410 {
1411 	__SOF_FILTER_OP(so, getpeername, cr, addr, addrlenp)
1412 }
1413 
1414 int
1415 sof_filter_setsockopt(struct sonode *so, int level, int option_name,
1416     void *optval, socklen_t *optlenp, cred_t *cr)
1417 {
1418 	__SOF_FILTER_OP(so, setsockopt, cr, level, option_name,
1419 	    optval, optlenp)
1420 }
1421 
1422 int
1423 sof_filter_getsockopt(struct sonode *so, int level, int option_name,
1424     void *optval, socklen_t *optlenp, cred_t *cr)
1425 {
1426 	__SOF_FILTER_OP(so, getsockopt, cr, level, option_name,
1427 	    optval, optlenp)
1428 }
1429 
1430 int
1431 sof_filter_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
1432     int32_t *rvalp, cred_t *cr)
1433 {
1434 	__SOF_FILTER_OP(so, ioctl, cr, cmd, arg, mode, rvalp)
1435 }
1436 
1437 /*
1438  * sof_register(version, name, ops, flags)
1439  *
1440  * Register a socket filter identified by name `name' and which should use
1441  * the ops vector `ops' for event notification. `flags' should be set to 0.
1442  * On success 0 is returned, otherwise an errno is returned.
1443  */
1444 int
1445 sof_register(int version, const char *name, const sof_ops_t *ops, int flags)
1446 {
1447 	sof_module_t *mod;
1448 
1449 	_NOTE(ARGUNUSED(flags));
1450 
1451 	if (version != SOF_VERSION)
1452 		return (EINVAL);
1453 
1454 	mod = kmem_zalloc(sizeof (sof_module_t), KM_SLEEP);
1455 	mod->sofm_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
1456 	(void) strcpy(mod->sofm_name, name);
1457 	mod->sofm_ops = *ops;
1458 
1459 	mutex_enter(&sof_module_lock);
1460 	if (sof_module_find(name) != NULL) {
1461 		mutex_exit(&sof_module_lock);
1462 		kmem_free(mod->sofm_name, strlen(mod->sofm_name) + 1);
1463 		kmem_free(mod, sizeof (sof_module_t));
1464 		return (EEXIST);
1465 	}
1466 	list_insert_tail(&sof_module_list, mod);
1467 	mutex_exit(&sof_module_lock);
1468 
1469 	return (0);
1470 }
1471 
1472 /*
1473  * sof_unregister(name)
1474  *
1475  * Try to unregister the socket filter identified by `name'. If the filter
1476  * is successfully unregistered, then 0 is returned, otherwise an errno is
1477  * returned.
1478  */
1479 int
1480 sof_unregister(const char *name)
1481 {
1482 	sof_module_t *mod;
1483 
1484 	mutex_enter(&sof_module_lock);
1485 	mod = sof_module_find(name);
1486 	if (mod != NULL) {
1487 		if (mod->sofm_refcnt == 0) {
1488 			list_remove(&sof_module_list, mod);
1489 			mutex_exit(&sof_module_lock);
1490 
1491 			kmem_free(mod->sofm_name, strlen(mod->sofm_name) + 1);
1492 			kmem_free(mod, sizeof (sof_module_t));
1493 			return (0);
1494 		} else {
1495 			mutex_exit(&sof_module_lock);
1496 			return (EBUSY);
1497 		}
1498 	}
1499 	mutex_exit(&sof_module_lock);
1500 
1501 	return (ENXIO);
1502 }
1503 
1504 /*
1505  * sof_newconn_ready(handle)
1506  *
1507  * The filter `handle` no longer wants to defer the socket it is attached
1508  * to. A newconn notification will be generated if there is no other filter
1509  * that wants the socket deferred.
1510  */
1511 void
1512 sof_newconn_ready(sof_handle_t handle)
1513 {
1514 	sof_instance_t *inst = (sof_instance_t *)handle;
1515 	struct sonode *so = inst->sofi_sonode;
1516 	struct sonode *pso = so->so_listener;
1517 
1518 	mutex_enter(&so->so_lock);
1519 	if (!(inst->sofi_flags & SOFIF_DEFER)) {
1520 		mutex_exit(&so->so_lock);
1521 		return;
1522 	}
1523 	ASSERT(so->so_state & SS_FIL_DEFER);
1524 	inst->sofi_flags &= ~SOFIF_DEFER;
1525 	SOF_STAT_ADD(inst, ndeferred, -1);
1526 
1527 	/*
1528 	 * Check if any other filter has deferred the socket. The last
1529 	 * filter to remove its DEFER flag will be the one generating the
1530 	 * wakeup.
1531 	 */
1532 	for (inst = so->so_filter_top; inst != NULL; inst = inst->sofi_next) {
1533 		/* Still deferred; nothing to do */
1534 		if (inst->sofi_flags & SOFIF_DEFER) {
1535 			mutex_exit(&so->so_lock);
1536 			return;
1537 		}
1538 	}
1539 	so->so_state &= ~SS_FIL_DEFER;
1540 	mutex_exit(&so->so_lock);
1541 
1542 	/*
1543 	 * The socket is no longer deferred; move it over to the regular
1544 	 * accept list and notify the user. However, it is possible that
1545 	 * the socket is being dropped by sof_sonode_drop_deferred(), so
1546 	 * first make sure the socket is on the deferred list.
1547 	 */
1548 	mutex_enter(&pso->so_acceptq_lock);
1549 	if (!list_link_active(&so->so_acceptq_node)) {
1550 		mutex_exit(&pso->so_acceptq_lock);
1551 		return;
1552 	}
1553 	list_remove(&pso->so_acceptq_defer, so);
1554 	list_insert_tail(&pso->so_acceptq_list, so);
1555 	cv_signal(&pso->so_acceptq_cv);
1556 	mutex_exit(&pso->so_acceptq_lock);
1557 
1558 	mutex_enter(&pso->so_lock);
1559 	so_notify_newconn(pso);		/* so_notify_newconn drops the lock */
1560 }
1561 
1562 /*
1563  * sof_bypass(handle)
1564  *
1565  * Stop generating callbacks for `handle'.
1566  */
1567 void
1568 sof_bypass(sof_handle_t handle)
1569 {
1570 	sof_instance_t *inst = (sof_instance_t *)handle;
1571 	struct sonode *so = inst->sofi_sonode;
1572 
1573 	mutex_enter(&so->so_lock);
1574 	if (!(inst->sofi_flags & SOFIF_BYPASS)) {
1575 		inst->sofi_flags |= SOFIF_BYPASS;
1576 		ASSERT(so->so_filter_active > 0);
1577 		so->so_filter_active--;
1578 	}
1579 	mutex_exit(&so->so_lock);
1580 }
1581 
1582 /*
1583  * sof_rcv_flowctrl(handle, enable)
1584  *
1585  * If `enable' is TRUE, then recv side flow control will be asserted for
1586  * the socket associated with `handle'. When `enable' is FALSE the filter
1587  * indicates that it no longer wants to assert flow control, however, the
1588  * condition will not be removed until there are no other filters asserting
1589  * flow control and there is space available in the receive buffer.
1590  */
1591 void
1592 sof_rcv_flowctrl(sof_handle_t handle, boolean_t enable)
1593 {
1594 	sof_instance_t *inst = (sof_instance_t *)handle;
1595 	struct sonode *so = inst->sofi_sonode;
1596 
1597 	mutex_enter(&so->so_lock);
1598 	if (enable) {
1599 		inst->sofi_flags |= SOFIF_RCV_FLOWCTRL;
1600 		so->so_flowctrld = B_TRUE;
1601 		so->so_state |= SS_FIL_RCV_FLOWCTRL;
1602 		mutex_exit(&so->so_lock);
1603 	} else {
1604 		inst->sofi_flags &= ~SOFIF_RCV_FLOWCTRL;
1605 		for (inst = so->so_filter_top; inst != NULL;
1606 		    inst = inst->sofi_next) {
1607 			/* another filter is asserting flow control */
1608 			if (inst->sofi_flags & SOFIF_RCV_FLOWCTRL) {
1609 				mutex_exit(&so->so_lock);
1610 				return;
1611 			}
1612 		}
1613 		so->so_state &= ~SS_FIL_RCV_FLOWCTRL;
1614 		/* so_check_flow_control drops so_lock */
1615 		so_check_flow_control(so);
1616 	}
1617 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
1618 }
1619 
1620 /*
1621  * sof_snd_flowctrl(handle, enable)
1622  *
1623  * If `enable' is TRUE, then send side flow control will be asserted for
1624  * the socket associated with `handle'. When `enable' is FALSE the filter
1625  * indicates that is no longer wants to assert flow control, however, the
1626  * condition will not be removed until there are no other filters asserting
1627  * flow control and there are tx buffers available.
1628  */
1629 void
1630 sof_snd_flowctrl(sof_handle_t handle, boolean_t enable)
1631 {
1632 	sof_instance_t *inst = (sof_instance_t *)handle;
1633 	struct sonode *so = inst->sofi_sonode;
1634 
1635 	mutex_enter(&so->so_lock);
1636 	if (enable) {
1637 		inst->sofi_flags |= SOFIF_SND_FLOWCTRL;
1638 		so->so_state |= SS_FIL_SND_FLOWCTRL;
1639 	} else {
1640 		inst->sofi_flags &= ~SOFIF_SND_FLOWCTRL;
1641 		for (inst = so->so_filter_top; inst != NULL;
1642 		    inst = inst->sofi_next) {
1643 			if (inst->sofi_flags & SOFIF_SND_FLOWCTRL) {
1644 				mutex_exit(&so->so_lock);
1645 				return;
1646 			}
1647 		}
1648 		so->so_state &= ~SS_FIL_SND_FLOWCTRL;
1649 		/*
1650 		 * Wake up writer if the socket is no longer flow controlled.
1651 		 */
1652 		if (!SO_SND_FLOWCTRLD(so)) {
1653 			/* so_notify_writable drops so_lock */
1654 			so_notify_writable(so);
1655 			return;
1656 		}
1657 	}
1658 	mutex_exit(&so->so_lock);
1659 }
1660 
1661 /*
1662  * sof_get_cookie(handle)
1663  *
1664  * Returns the cookie used by `handle'.
1665  */
1666 void *
1667 sof_get_cookie(sof_handle_t handle)
1668 {
1669 	return (((sof_instance_t *)handle)->sofi_cookie);
1670 }
1671 
1672 /*
1673  * sof_cas_cookie(handle, old, new)
1674  *
1675  * Compare-and-swap the cookie used by `handle'.
1676  */
1677 void *
1678 sof_cas_cookie(sof_handle_t handle, void *old, void *new)
1679 {
1680 	sof_instance_t *inst = (sof_instance_t *)handle;
1681 
1682 	return (atomic_cas_ptr(&inst->sofi_cookie, old, new));
1683 }
1684 
1685 /*
1686  * sof_inject_data_out(handle, mp, msg, flowctrld)
1687  *
1688  * Submit `mp' for transmission. `msg' cannot by NULL, and may contain
1689  * ancillary data and destination address. Returns 0 when successful
1690  * in which case `flowctrld' is updated. If flow controlled, no new data
1691  * should be injected until a SOF_EV_INJECT_DATA_OUT_OK event is observed.
1692  * In case of failure, an errno is returned.
1693  *
1694  * Filters that are lower in the stack than `handle' will see the data
1695  * before it is transmitted and may end up modifying or freeing the data.
1696  */
1697 int
1698 sof_inject_data_out(sof_handle_t handle, mblk_t *mp, struct nmsghdr *msg,
1699     boolean_t *flowctrld)
1700 {
1701 	sof_instance_t *inst = (sof_instance_t *)handle;
1702 	struct sonode *so = inst->sofi_sonode;
1703 	int error;
1704 
1705 	/*
1706 	 * Data cannot be sent down to the protocol once the socket has
1707 	 * started the process of closing.
1708 	 */
1709 	mutex_enter(&so->so_lock);
1710 	if (so->so_state & SS_CLOSING) {
1711 		mutex_exit(&so->so_lock);
1712 		freemsg(mp);
1713 		return (EPIPE);
1714 	}
1715 	so->so_filter_tx++;
1716 	mutex_exit(&so->so_lock);
1717 
1718 	error = so_sendmblk_impl(inst->sofi_sonode, msg, FNONBLOCK,
1719 	    kcred, &mp, inst->sofi_next, B_TRUE);
1720 
1721 	mutex_enter(&so->so_lock);
1722 	ASSERT(so->so_filter_tx > 0);
1723 	so->so_filter_tx--;
1724 	if (so->so_state & SS_CLOSING)
1725 		cv_signal(&so->so_closing_cv);
1726 	mutex_exit(&so->so_lock);
1727 
1728 	if (mp != NULL)
1729 		freemsg(mp);
1730 
1731 	if (error == ENOSPC) {
1732 		*flowctrld = B_TRUE;
1733 		error = 0;
1734 	} else {
1735 		*flowctrld = B_FALSE;
1736 	}
1737 
1738 	return (error);
1739 }
1740 
1741 /*
1742  * sof_inject_data_in(handle, mp, len, flag, flowctrld)
1743  *
1744  * Enqueue `mp' which contains `len' bytes of M_DATA onto the socket
1745  * associated with `handle'. `flags' should be set to 0. Returns 0 when
1746  * successful in which case `flowctrld' is updated. If flow controlled,
1747  * no new data should be injected until a SOF_EV_INJECT_DATA_IN_OK event
1748  * is observed.  In case of failure, an errno is returned.
1749  *
1750  * Filters that are higher in the stack than `handle' will see the data
1751  * before it is enqueued on the receive queue and may end up modifying or
1752  * freeing the data.
1753  */
1754 int
1755 sof_inject_data_in(sof_handle_t handle, mblk_t *mp, size_t len, int flags,
1756     boolean_t *flowctrld)
1757 {
1758 	sof_instance_t *inst = (sof_instance_t *)handle;
1759 	ssize_t avail;
1760 	int error = 0;
1761 
1762 	ASSERT(flags == 0);
1763 	avail = so_queue_msg_impl(inst->sofi_sonode, mp, len, flags, &error,
1764 	    NULL, inst->sofi_prev);
1765 	/* fallback should never happen when there is an active filter */
1766 	ASSERT(error != EOPNOTSUPP);
1767 
1768 	*flowctrld = (avail > 0) ? B_FALSE : B_TRUE;
1769 	return (error);
1770 }
1771 
1772 /*
1773  * sof_newconn_move(handle, newparent)
1774  *
1775  * Private interface only to be used by KSSL.
1776  *
1777  * Moves the socket associated with `handle' from its current listening
1778  * socket to the listener associated with `newparent'. The socket being
1779  * moved must be in a deferred state and it is up to the consumer of the
1780  * interface to ensure that the `newparent' does not go away while this
1781  * operation is pending.
1782  */
1783 boolean_t
1784 sof_newconn_move(sof_handle_t handle, sof_handle_t newparent)
1785 {
1786 	sof_instance_t *inst = (sof_instance_t *)handle;
1787 	sof_instance_t *newpinst = (sof_instance_t *)newparent;
1788 	struct sonode *so, *old, *new;
1789 
1790 	so = inst->sofi_sonode;
1791 	ASSERT(so->so_state & SS_FIL_DEFER);
1792 
1793 	if (inst->sofi_next != NULL || inst->sofi_prev != NULL ||
1794 	    !(so->so_state & SS_FIL_DEFER))
1795 		return (B_FALSE);
1796 
1797 	old = so->so_listener;
1798 	mutex_enter(&old->so_acceptq_lock);
1799 	list_remove(&old->so_acceptq_defer, so);
1800 	old->so_acceptq_len--;
1801 	mutex_exit(&old->so_acceptq_lock);
1802 
1803 	new = newpinst->sofi_sonode;
1804 	mutex_enter(&new->so_acceptq_lock);
1805 	list_insert_tail(&new->so_acceptq_defer, so);
1806 	new->so_acceptq_len++;
1807 	mutex_exit(&new->so_acceptq_lock);
1808 
1809 	so->so_listener = new;
1810 
1811 	return (B_TRUE);
1812 }
1813