3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * CDDL HEADER START
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The contents of this file are subject to the terms of the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Common Development and Distribution License (the "License").
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * You may not use this file except in compliance with the License.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * or http://www.opensolaris.org/os/licensing.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * See the License for the specific language governing permissions
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * and limitations under the License.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * When distributing Covered Code, include this CDDL HEADER in each
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * If applicable, add the following below this CDDL HEADER, with the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * fields enclosed by brackets "[]" replaced with your own identifying
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * information: Portions Copyright [yyyy] [name of copyright owner]
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * CDDL HEADER END
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/systm.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/sysmacros.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/cmn_err.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/disp.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/list.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/mutex.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/note.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/rwlock.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/stropts.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/taskq.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <sys/socketvar.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <fs/sockfs/sockcommon.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <fs/sockfs/sockfilter_impl.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Socket Filter Framework
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Socket filter entry (sof_entry_t):
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * There exists one entry for each configured filter (done via soconfig(1M)),
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * and they are all in sof_entry_list. In addition to the global list, each
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sockparams entry maintains a list of filters that is interested in that
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * particular socket type. So the filter entry may be referenced by multiple
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sockparams. The set of sockparams referencing a filter may change as
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * socket types are added and/or removed from the system. Both sof_entry_list
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * and the sockparams list is protected by sockconf_lock.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Each filter entry has a ref count which is incremented whenever a filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * is attached to a socket. An entry is marked SOFEF_CONDEMED when it is
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * unconfigured, which will result in the entry being freed when its ref
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * count reaches zero.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Socket filter module (sof_module_t):
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Modules are created by sof_register() and placed in sof_module_list,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * which is protected by sof_module_lock. Each module has a reference count
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * that is incremented when a filter entry is using the module. A module
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson * can be destroyed by sof_unregister() only when its ref count is zero.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Socket filter instance (sof_instance_t):
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Whenever a filter is attached to a socket (sonode), a new instance is
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * created. The socket is guaranteed to be single threaded when filters are
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * being attached/detached. The instance uses the sonode's so_lock for
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * protection.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The lifetime of an instance is the same as the socket it's attached to.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * How things link together:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sockparams.sp_{auto,prog}_filters -> sp_filter_t -> sp_filter_t
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * ^ | |
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * | | |
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sonode.so_filter_top -> sof_instance_t | |
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * | | |
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * v v v
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_entry_list -> sof_entry_t -> sof_entry -> ... -> sof_entry_t
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * |
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * v
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_module_list -> sof_module_t -> ... -> sof_module_t
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic list_t sof_entry_list; /* list of configured filters */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic list_t sof_module_list; /* list of loaded filter modules */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic kmutex_t sof_module_lock; /* protect the module list */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic sof_kstat_t sof_stat;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic kstat_t *sof_stat_ksp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#ifdef DEBUG
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int socket_filter_debug = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#endif
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * A connection that has been deferred for more than `sof_defer_drop_time'
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * ticks can be dropped to make room for new connections. A connection that
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * is to be dropped is moved over to `sof_close_deferred_list' where it will
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * be closed by sof_close_deferred() (which is running on a taskq). Connections
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * will not be moved over to the close list if it grows larger than
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * `sof_close_deferred_max_backlog'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonclock_t sof_defer_drop_time = 3000;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonuint_t sof_close_deferred_max_backlog = 1000;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssontaskq_t *sof_close_deferred_taskq;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonboolean_t sof_close_deferred_running;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonuint_t sof_close_deferred_backlog;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonlist_t sof_close_deferred_list;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonkmutex_t sof_close_deferred_lock;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void sof_close_deferred(void *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void sof_module_rele(sof_module_t *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic sof_module_t *sof_module_hold_by_name(const char *, const char *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int sof_entry_load_module(sof_entry_t *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void sof_entry_hold(sof_entry_t *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void sof_entry_rele(sof_entry_t *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int sof_entry_kstat_create(sof_entry_t *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void sof_entry_kstat_destroy(sof_entry_t *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic sof_instance_t *sof_instance_create(sof_entry_t *, struct sonode *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void sof_instance_destroy(sof_instance_t *);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_kstat_update(kstat_t *ksp, int rw)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson _NOTE(ARGUNUSED(ksp));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rw == KSTAT_WRITE)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EACCES);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_stat.sofks_defer_close_backlog.value.ui64 =
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_backlog;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_init(void)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_create(&sof_entry_list, sizeof (sof_entry_t),
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson offsetof(sof_entry_t, sofe_node));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_create(&sof_module_list, sizeof (sof_module_t),
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson offsetof(sof_module_t, sofm_node));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_create(&sof_close_deferred_list, sizeof (struct sonode),
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson offsetof(struct sonode, so_acceptq_node));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_taskq = taskq_create("sof_close_deferred_taskq",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson 1, minclsyspri, 1, INT_MAX, TASKQ_PREPOPULATE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_running = B_FALSE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_backlog = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_init(&sof_close_deferred_lock, NULL, MUTEX_DEFAULT, 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_init(&sof_module_lock, NULL, MUTEX_DEFAULT, 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_stat_ksp = kstat_create("sockfs", 0, "sockfilter", "misc",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSTAT_TYPE_NAMED, sizeof (sof_kstat_t) / sizeof (kstat_named_t),
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSTAT_FLAG_VIRTUAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (sof_stat_ksp == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&sof_stat.sofks_defer_closed, "defer_closed",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&sof_stat.sofks_defer_close_backlog,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "defer_close_backlog", KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&sof_stat.sofks_defer_close_failed_backlog_too_big,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "defer_close_failed_backlog_too_big", KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_stat_ksp->ks_data = &sof_stat;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_stat_ksp->ks_update = sof_kstat_update;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_install(sof_stat_ksp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Process filter options.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_setsockopt_impl(struct sonode *so, int option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson const void *optval, socklen_t optlen, struct cred *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sockparams *sp = so->so_sockparams;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_t *ent = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sp_filter_t *fil;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_rval_t rval;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson _NOTE(ARGUNUSED(optlen));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Is the filter in a state where filters can be attached?
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!(so->so_state & SS_FILOP_OK))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (option_name == FIL_ATTACH) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Make sure there isn't already another instance of the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * same filter attached to the socket.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_next) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (strncmp(inst->sofi_filter->sofe_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (const char *)optval, SOF_MAXNAMELEN) == 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EEXIST);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Look up the filter. */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_enter(&sockconf_lock, RW_READER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (fil = list_head(&sp->sp_prog_filters); fil != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil = list_next(&sp->sp_prog_filters, fil)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent = fil->spf_filter;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_flags & SOFEF_PROG);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (strncmp(ent->sofe_name, (const char *)optval,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_MAXNAMELEN) == 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* No such filter */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (fil == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOENT);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = sof_instance_create(ent, so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Failed to create an instance; must be out of memory */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOMEM);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * This might be the first time the filter is being used,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * so try to load the module if it's not already registered.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_mod == NULL &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_entry_load_module(ent)) != 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_destroy(inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Module loaded OK, so there must be an ops vector */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_mod != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_ops = &ent->sofe_mod->sofm_ops;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, tot_active_attach, 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_ops->sofop_attach_active != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rval = inst->sofi_ops->sofop_attach_active(
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)inst, so->so_family, so->so_type,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_protocol, cr, &inst->sofi_cookie);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rval != SOF_RVAL_CONTINUE) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson switch (rval) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case SOF_RVAL_DETACH:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Filter does not want to to attach.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * An error is returned so the user
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * knows the request did not go
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * through.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = EINVAL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson default:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, attach_failures, 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Not a valid rval for active attach */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(rval != SOF_RVAL_DEFER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = sof_rval2errno(rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
700f2bdf63820e30238ab3d63d8f6b61d731ff54Anil udupa sof_instance_destroy(inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else if (option_name == FIL_DETACH) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_next) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent = inst->sofi_filter;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (strncmp(ent->sofe_name, (const char *)optval,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_MAXNAMELEN) == 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENXIO);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* automatic filters cannot be detached */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_filter->sofe_flags & SOFEF_AUTO)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_ops->sofop_detach != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_ops->sofop_detach((sof_handle_t)inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_cookie, cr);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_destroy(inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_setsockopt(struct sonode *so, int option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson const void *optval, socklen_t optlen, struct cred *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * By grabbing the lock as a writer we ensure that no other socket
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * operations can start while the filter stack is being manipulated.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * We do a tryenter so that in case there is an active thread we
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * ask the caller to try again instead of blocking here until the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * other thread is done (which could be indefinitely in case of recv).
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!rw_tryenter(&so->so_fallback_rwlock, RW_WRITER)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EAGAIN);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Bail out if a fallback has taken place */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & SS_FALLBACK_COMP)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = EINVAL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson else
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = sof_setsockopt_impl(so, option_name, optval,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson optlen, cr);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&so->so_fallback_rwlock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Get filter socket options.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_getsockopt_impl(struct sonode *so, int option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson void *optval, socklen_t *optlenp, struct cred *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct fil_info *fi;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socklen_t maxsz = *optlenp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int i;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson uint_t cnt;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson _NOTE(ARGUNUSED(cr));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (option_name == FIL_LIST) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fi = (struct fil_info *)optval;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (maxsz < sizeof (*fi))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top, cnt = 0; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_next)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cnt++;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top, i = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst != NULL && (i+1) * sizeof (*fi) <= maxsz;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_next, i++) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fi[i].fi_flags =
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (inst->sofi_filter->sofe_flags & SOFEF_AUTO) ?
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson FILF_AUTO : FILF_PROG;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_flags & SOFIF_BYPASS)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fi[i].fi_flags |= FILF_BYPASS;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) strncpy(fi[i].fi_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_filter->sofe_name, FILNAME_MAX);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(cnt > 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fi[i].fi_pos = --cnt;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *optlenp = i * sizeof (*fi);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_getsockopt(struct sonode *so, int option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson void *optval, socklen_t *optlenp, struct cred *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The fallback lock is used here to serialize set and get
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * filter operations.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_enter(&so->so_fallback_rwlock, RW_READER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & SS_FALLBACK_COMP)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = EINVAL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson else
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = sof_getsockopt_impl(so, option_name, optval, optlenp,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cr);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&so->so_fallback_rwlock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The socket `so' wants to inherit the filter stack from `pso'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Returns 0 if all went well or an errno otherwise.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sonode_inherit_filters(struct sonode *so, struct sonode *pso)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst, *pinst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_rval_t rval;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sockaddr_in6 laddrbuf, faddrbuf;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sockaddr_in6 *laddr, *faddr;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socklen_t laddrlen, faddrlen;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Make sure there is enough room to retrieve the addresses
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_proto_props.sopp_maxaddrlen > sizeof (laddrbuf)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson laddr = kmem_zalloc(so->so_proto_props.sopp_maxaddrlen,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KM_NOSLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (laddr == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOMEM);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson faddr = kmem_zalloc(so->so_proto_props.sopp_maxaddrlen,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KM_NOSLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (faddr == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(laddr, so->so_proto_props.sopp_maxaddrlen);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOMEM);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson laddrlen = faddrlen = so->so_proto_props.sopp_maxaddrlen;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson laddrlen = faddrlen = sizeof (laddrbuf);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson laddr = &laddrbuf;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson faddr = &faddrbuf;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_getpeername)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (so->so_proto_handle, (struct sockaddr *)faddr, &faddrlen, kcred);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (error != 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto out;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_getsockname)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (so->so_proto_handle, (struct sockaddr *)laddr, &laddrlen, kcred);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (error != 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto out;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The stack is built bottom up. Filters are allowed to modify the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * the foreign and local addresses during attach.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (pinst = pso->so_filter_bottom;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson pinst != NULL && !(pinst->sofi_flags & SOFIF_BYPASS);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson pinst = pinst->sofi_prev) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = sof_instance_create(pinst->sofi_filter, so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = ENOMEM;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto out;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The filter module must be loaded since it's already
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * attached to the listener.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(pinst->sofi_ops != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_ops = pinst->sofi_ops;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, tot_passive_attach, 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_ops->sofop_attach_passive != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rval = inst->sofi_ops->sofop_attach_passive(
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)pinst, pinst->sofi_cookie,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (struct sockaddr *)laddr, laddrlen,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (struct sockaddr *)faddr, faddrlen,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson &inst->sofi_cookie);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rval != SOF_RVAL_CONTINUE) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rval == SOF_RVAL_DEFER) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_flags |= SOFIF_DEFER;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_state |= SS_FIL_DEFER;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_defertime =
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ddi_get_lbolt();
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, ndeferred, 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else if (rval == SOF_RVAL_DETACH) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_destroy(inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, attach_failures, 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = sof_rval2errno(rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Filters that called attached will be
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * destroyed when the socket goes away,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * after detach is called.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto out;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonout:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (laddr != &laddrbuf) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(laddr, so->so_proto_props.sopp_maxaddrlen);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(faddr, so->so_proto_props.sopp_maxaddrlen);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Attach any automatic filters to sonode `so'. Returns 0 if all went well
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * and an errno otherwise.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sonode_autoattach_filters(struct sonode *so, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sockparams *sp = so->so_sockparams;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sp_filter_t *fil;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_rval_t rval;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * A created instance is added to the top of the sonode's filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * stack, so traverse the config list in reverse order.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_enter(&sockconf_lock, RW_READER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (fil = list_tail(&sp->sp_auto_filters);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil != NULL; fil = list_prev(&sp->sp_auto_filters, fil)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(fil->spf_filter->sofe_flags & SOFEF_AUTO);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!sof_instance_create(fil->spf_filter, so)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = ENOMEM; /* must have run out of memory */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto free_all;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Notify each filter that it's being attached.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = so->so_filter_top;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson while (inst != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_t *ent = inst->sofi_filter;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *ninst = inst->sofi_next;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * This might be the first time the filter is being used,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * so try to load the module if it's not already registered.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_mod == NULL &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_entry_load_module(ent)) != 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto free_detached;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Module loaded OK, so there must be an ops vector */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_mod != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_ops = &ent->sofe_mod->sofm_ops;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, tot_active_attach, 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_ops->sofop_attach_active != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rval = inst->sofi_ops->sofop_attach_active(
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)inst, so->so_family, so->so_type,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_protocol, cr, &inst->sofi_cookie);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rval != SOF_RVAL_CONTINUE) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson switch (rval) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case SOF_RVAL_DETACH:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* filter does not want to attach */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_destroy(inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson default:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, attach_failures, 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Not a valid rval for active attach */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(rval != SOF_RVAL_DEFER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = sof_rval2errno(rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto free_detached;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = ninst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonfree_all:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = so->so_filter_top;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonfree_detached:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(inst != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Destroy all filters for which attach was not called. The other
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * filters will be destroyed (and detach called) when the socket
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * is freed.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson do {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *t = inst->sofi_next;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_destroy(inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = t;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } while (inst != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Detaches and frees all filters attached to sonode `so'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sonode_cleanup(struct sonode *so)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson while ((inst = so->so_filter_top) != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (inst->sofi_ops->sofop_detach)((sof_handle_t)inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_cookie, kcred);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_destroy(inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Notifies all active filters attached to `so' about the `event' and
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * where `arg' is an event specific argument.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sonode_notify_filters(struct sonode *so, sof_event_t event, uintptr_t arg)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_bottom; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_prev) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (SOF_INTERESTED(inst, notify))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (inst->sofi_ops->sofop_notify)((sof_handle_t)inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_cookie, event, arg);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The socket `so' is closing. Notify filters and make sure that there
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * are no pending tx operations.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sonode_closing(struct sonode *so)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Notify filters that the socket is being closed. It's OK for
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * filters to inject data.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_sonode_notify_filters(so, SOF_EV_CLOSING, (uintptr_t)B_TRUE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson /*
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson * Stop any future attempts to inject data, and wait for any
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson * pending operations to complete. This has to be done to ensure
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson * that no data is sent down to the protocol once a close
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson * downcall has been made.
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson so->so_state |= SS_FIL_STOP;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson while (so->so_filter_tx > 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cv_wait(&so->so_closing_cv, &so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Called when socket `so' wants to get rid of a deferred connection.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Returns TRUE if a connection was dropped.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonboolean_t
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sonode_drop_deferred(struct sonode *so)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *def;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson clock_t now = ddi_get_lbolt();
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (sof_close_deferred_backlog > sof_close_deferred_max_backlog) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_GLOBAL_STAT_BUMP(defer_close_failed_backlog_too_big);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (B_FALSE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((def = list_head(&so->so_acceptq_defer)) != NULL &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (now - def->so_filter_defertime) > sof_defer_drop_time) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_remove(&so->so_acceptq_defer, def);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_acceptq_len--;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson def->so_listener = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (B_FALSE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&sof_close_deferred_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&sof_close_deferred_list, def);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_backlog++;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!sof_close_deferred_running) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_close_deferred_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) taskq_dispatch(sof_close_deferred_taskq,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred, NULL, TQ_NOSLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_close_deferred_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (B_TRUE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Called from a taskq to close connections that have been deferred for
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * too long.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_close_deferred(void *unused)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *drop;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson _NOTE(ARGUNUSED(unused));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&sof_close_deferred_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!sof_close_deferred_running) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_running = B_TRUE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson while ((drop =
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_remove_head(&sof_close_deferred_list)) != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_backlog--;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_close_deferred_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_GLOBAL_STAT_BUMP(defer_closed);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) socket_close(drop, 0, kcred);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socket_destroy(drop);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&sof_close_deferred_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_close_deferred_running = B_FALSE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(sof_close_deferred_backlog == 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_close_deferred_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Creates a new filter instance from the entry `ent' and attaches
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * it to the sonode `so'. On success, return a pointer to the created
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * instance.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The new instance will be placed on the top of the filter stack.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The caller is responsible for assigning the instance's ops vector and
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * calling the filter's attach callback.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * No locks are held while manipulating the sonode fields because we are
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * guaranteed that this operation is serialized.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * We can be sure that the entry `ent' will not disappear, because the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * caller is either holding sockconf_lock (in case of an active open), or is
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * already holding a reference (in case of a passive open, the listener has
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * one).
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic sof_instance_t *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_instance_create(sof_entry_t *ent, struct sonode *so)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = kmem_zalloc(sizeof (sof_instance_t), KM_NOSLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_hold(ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_filter = ent;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_sonode = so;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_next = so->so_filter_top;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_top != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_top->sofi_prev = inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson else
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_bottom = inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_top = inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_active++;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Destroys the filter instance `inst' and unlinks it from the sonode.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Any filter private state must be destroyed (via the detach callback)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * before the instance is destroyed.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_instance_destroy(sof_instance_t *inst)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = inst->sofi_sonode;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(inst->sofi_sonode != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(inst->sofi_filter != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(inst->sofi_prev != NULL || so->so_filter_top == inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(inst->sofi_next != NULL || so->so_filter_bottom == inst);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_prev != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_prev->sofi_next = inst->sofi_next;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson else
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_top = inst->sofi_next;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_next != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_next->sofi_prev = inst->sofi_prev;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson else
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_bottom = inst->sofi_prev;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!(inst->sofi_flags & SOFIF_BYPASS)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(so->so_filter_active > 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_active--;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_flags & SOFIF_DEFER)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, ndeferred, -1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_rele(inst->sofi_filter);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(inst, sizeof (sof_instance_t));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic sof_entry_t *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_find(const char *name)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_t *ent;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (ent = list_head(&sof_entry_list); ent != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent = list_next(&sof_entry_list, ent)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (strncmp(ent->sofe_name, name, SOF_MAXNAMELEN) == 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_free(sof_entry_t *ent)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_refcnt == 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(!list_link_active(&ent->sofe_node));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_hintarg != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_hint == SOF_HINT_BEFORE ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_hint == SOF_HINT_AFTER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(ent->sofe_hintarg, strlen(ent->sofe_hintarg) + 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_hintarg = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_socktuple_cnt > 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_socktuple != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(ent->sofe_socktuple,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sizeof (sof_socktuple_t) * ent->sofe_socktuple_cnt);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_socktuple = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_socktuple_cnt = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_kstat_destroy(ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_destroy(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(ent, sizeof (sof_entry_t));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_kstat_update(kstat_t *ksp, int rw)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_t *ent = ksp->ks_private;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rw == KSTAT_WRITE)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EACCES);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_kstat.sofek_nactive.value.ui64 = ent->sofe_refcnt;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Create the kstat for filter entry `ent'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_kstat_create(sof_entry_t *ent)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson char name[SOF_MAXNAMELEN + 7];
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) snprintf(name, sizeof (name), "filter_%s", ent->sofe_name);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_ksp = kstat_create("sockfs", 0, name, "misc",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSTAT_TYPE_NAMED,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sizeof (sof_entry_kstat_t) / sizeof (kstat_named_t),
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSTAT_FLAG_VIRTUAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_ksp == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOMEM);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&ent->sofe_kstat.sofek_nactive, "nactive",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&ent->sofe_kstat.sofek_tot_active_attach,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "tot_active_attach", KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&ent->sofe_kstat.sofek_tot_passive_attach,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "tot_passive_attach", KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&ent->sofe_kstat.sofek_ndeferred, "ndeferred",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_named_init(&ent->sofe_kstat.sofek_attach_failures,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "attach_failures", KSTAT_DATA_UINT64);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_ksp->ks_data = &ent->sofe_kstat;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_ksp->ks_update = sof_entry_kstat_update;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_ksp->ks_private = ent;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_install(ent->sofe_ksp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Destroys the kstat for filter entry `ent'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_kstat_destroy(sof_entry_t *ent)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_ksp != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kstat_delete(ent->sofe_ksp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_ksp = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_hold(sof_entry_t *ent)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_refcnt++;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Decrement the reference count for `ent'. The entry will
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * drop its' reference on the filter module whenever its'
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * ref count reaches zero.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_rele(sof_entry_t *ent)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (--ent->sofe_refcnt == 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_t *mod = ent->sofe_mod;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_mod = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_flags & SOFEF_CONDEMED) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_free(ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mod != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_rele(mod);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Loads the module used by `ent'
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic int
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_load_module(sof_entry_t *ent)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_t *mod = sof_module_hold_by_name(ent->sofe_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_modname);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mod == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Another thread might have already loaded the module */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_mod == mod || ent->sofe_mod == NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_mod != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_rele(mod);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent->sofe_mod = mod;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&ent->sofe_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Add filter entry `ent' to the global list and attach it to all sockparam
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * entries which the filter is interested in. Upon successful return the filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * will be available for applications to use.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_add(sof_entry_t *ent)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * We hold sockconf_lock as a WRITER for the whole operation,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * so all operations must be non-blocking.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_enter(&sockconf_lock, RW_WRITER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (sof_entry_find(ent->sofe_name) != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EEXIST);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* The entry is unique; create the kstats */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (sof_entry_kstat_create(ent) != 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOMEM);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Attach the filter to sockparams of interest.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((error = sockparams_new_filter(ent)) != 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_kstat_destroy(ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Everything is OK; insert in global list.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&sof_entry_list, ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Removes the filter entry `ent' from global list and all sockparams.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_t *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_remove_by_name(const char *name)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_t *ent;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_enter(&sockconf_lock, RW_WRITER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((ent = sof_entry_find(name)) == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_remove(&sof_entry_list, ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sockparams_filter_cleanup(ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_kstat_destroy(ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rw_exit(&sockconf_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Filter entry `ent' will process sockparams entry `sp' to determine whether
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * it should be attached to the sockparams. It should be called whenever a new
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * filter or sockparams is being added. Returns zero either if the filter is
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * not interested in the sockparams or if it successfully attached to the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sockparams. On failure an errno is returned.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_entry_proc_sockparams(sof_entry_t *ent, struct sockparams *sp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson uint_t i;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_socktuple_t *t = ent->sofe_socktuple;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sp_filter_t *new, *fil;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Only interested in non-TPI sockets */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (strcmp(sp->sp_smod_name, SOTPI_SMOD_NAME) == 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (i = 0; i < ent->sofe_socktuple_cnt; i++) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (t[i].sofst_family == sp->sp_family &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson t[i].sofst_type == sp->sp_type &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson t[i].sofst_protocol == sp->sp_protocol)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* This filter is not interested in the sockparams entry */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (i == ent->sofe_socktuple_cnt)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson new = kmem_zalloc(sizeof (sp_filter_t), KM_NOSLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (new == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOMEM);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson new->spf_filter = ent;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_flags & SOFEF_PROG) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* placement is irrelevant for programmatic filters */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_head(&sp->sp_prog_filters, new);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(ent->sofe_flags & SOFEF_AUTO);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * If the filter specifies a placement hint, then make sure
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * it can be satisfied.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson switch (ent->sofe_hint) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case SOF_HINT_TOP:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((fil = list_head(&sp->sp_auto_filters)) != NULL &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil->spf_filter->sofe_hint == SOF_HINT_TOP)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_head(&sp->sp_auto_filters, new);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case SOF_HINT_BOTTOM:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((fil = list_tail(&sp->sp_auto_filters)) != NULL &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil->spf_filter->sofe_hint == SOF_HINT_BOTTOM)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&sp->sp_auto_filters, new);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case SOF_HINT_BEFORE:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case SOF_HINT_AFTER:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (fil = list_head(&sp->sp_auto_filters);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil = list_next(&sp->sp_auto_filters, fil)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (strncmp(ent->sofe_hintarg,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil->spf_filter->sofe_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_MAXNAMELEN) == 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (fil != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (ent->sofe_hint == SOF_HINT_BEFORE) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (fil->spf_filter->sofe_hint ==
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_HINT_TOP)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_before(&sp->sp_auto_filters,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil, new);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (fil->spf_filter->sofe_hint ==
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_HINT_BOTTOM)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_after(&sp->sp_auto_filters,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil, new);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*FALLTHRU*/
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case SOF_HINT_NONE:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Insert the new filter at the beginning as long as it
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * does not violate a TOP hint, otherwise insert in the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * next suitable location.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((fil = list_head(&sp->sp_auto_filters)) != NULL &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fil->spf_filter->sofe_hint == SOF_HINT_TOP) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_after(&sp->sp_auto_filters, fil,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson new);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_head(&sp->sp_auto_filters, new);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Failed to insert the filter */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(new, sizeof (sp_filter_t));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOSPC);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Remove all filter entries attached to the sockparams entry `sp'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sockparams_fini(struct sockparams *sp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sp_filter_t *fil;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(!list_link_active(&sp->sp_node));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson while ((fil = list_remove_head(&sp->sp_auto_filters)) != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(fil, sizeof (sp_filter_t));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson while ((fil = list_remove_head(&sp->sp_prog_filters)) != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(fil, sizeof (sp_filter_t));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * A new sockparams is being added. Walk all filters and attach those that
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * are interested in the entry.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * It should be called when the sockparams entry is about to be made available
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * for use and while holding the sockconf_lock.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_sockparams_init(struct sockparams *sp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_entry_t *ent;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(RW_WRITE_HELD(&sockconf_lock));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (ent = list_head(&sof_entry_list); ent != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent = list_next(&sof_entry_list, ent)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (sof_entry_proc_sockparams(ent, sp) != 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_sockparams_fini(sp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENOMEM);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic sof_module_t *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_module_find(const char *name)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_t *ent;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(MUTEX_HELD(&sof_module_lock));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (ent = list_head(&sof_module_list); ent != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ent = list_next(&sof_module_list, ent))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (strcmp(ent->sofm_name, name) == 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ent);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Returns a pointer to a module identified by `name' with its ref count
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * bumped. An attempt to load the module is done if it's not found in the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * global list.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_module_t *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_module_hold_by_name(const char *name, const char *modname)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ddi_modhandle_t handle = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_t *mod = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson char *modpath;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * We'll go through the loop at most two times, which will only
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * happen if the module needs to be loaded.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (;;) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mod = sof_module_find(name);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mod != NULL || handle != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson modpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) snprintf(modpath, MAXPATHLEN, "%s/%s", SOF_MODPATH,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson modname);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson handle = ddi_modopen(modpath, KRTLD_MODE_FIRST, &error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(modpath, MAXPATHLEN);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Failed to load, then bail */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (handle == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cmn_err(CE_WARN,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "Failed to load socket filter module: %s (err %d)",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson modname, error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mod != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mod->sofm_refcnt++;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (handle != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) ddi_modclose(handle);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The module was loaded, but the filter module could not be
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * found. It's likely a misconfigured filter.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mod == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cmn_err(CE_WARN,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "Socket filter module %s was loaded, but did not" \
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson "register. Filter %s is likely misconfigured.",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson modname, name);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (mod);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_module_rele(sof_module_t *mod)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mod->sofm_refcnt--;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_rval2errno(sof_rval_t rval)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rval > SOF_RVAL_CONTINUE) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return ((int)rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#ifdef DEBUG
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (socket_filter_debug)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson printf("sof_rval2errno: invalid rval '%d'\n", rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#endif
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Walk through all the filters attached to `so' and allow each filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * to process the data using its data_out callback. `mp' is a b_cont chain.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Returns the processed mblk, or NULL if mblk was consumed. The mblk might
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * have been consumed as a result of an error, in which case `errp' is set to
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * the appropriate errno.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonmblk_t *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_data_out_from(struct sonode *so, sof_instance_t *start,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mblk_t *mp, struct nmsghdr *msg, cred_t *cr, int *errp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_rval_t rval;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson _NOTE(ARGUNUSED(so));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = start; inst != NULL; inst = inst->sofi_next) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!SOF_INTERESTED(inst, data_out))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson continue;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mp = (inst->sofi_ops->sofop_data_out)((sof_handle_t)inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_cookie, mp, msg, cr, &rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson DTRACE_PROBE2(filter__data, (sof_instance_t), inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (mblk_t *), mp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mp == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *errp = sof_rval2errno(rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (mp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Walk through all the filters attached to `so' and allow each filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * to process the data using its data_in_proc callback. `mp' is the start of
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * a possible b_next chain, and `lastmp' points to the last mblk in the chain.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Returns the processed mblk, or NULL if all mblks in the chain were
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * consumed. `lastmp' is updated to point to the last mblk in the processed
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * chain.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonmblk_t *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_data_in_proc(struct sonode *so, mblk_t *mp, mblk_t **lastmp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson size_t len = 0, orig = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ssize_t diff = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mblk_t *retmp = NULL, *tailmp, *nextmp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *lastmp = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson do {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson nextmp = mp->b_next;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mp->b_next = mp->b_prev = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson len = orig = msgdsize(mp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_bottom; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_prev) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!SOF_INTERESTED(inst, data_in_proc))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson continue;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mp = (inst->sofi_ops->sofop_data_in_proc)(
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)inst, inst->sofi_cookie, mp,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kcred, &len);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mp == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson DTRACE_PROBE2(filter__data, (sof_instance_t), inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (mblk_t *), mp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson diff += len - orig;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mp == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson continue;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (tailmp = mp; tailmp->b_cont != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson tailmp = tailmp->b_cont)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mp->b_prev = tailmp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (*lastmp == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson retmp = mp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson else
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (*lastmp)->b_next = mp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *lastmp = mp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } while ((mp = nextmp) != NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The size of the chain has changed; make sure the rcv queue
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * stays consistent and check if the flow control state should
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * change.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (diff != 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson DTRACE_PROBE2(filter__data__adjust__qlen,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (struct sonode *), so, (size_t), diff);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_rcv_queued += diff;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* so_check_flow_control drops so_lock */
a215d4eb400e2ff52f7a17e0781964c37aabfc04Kacheong Poon (void) so_check_flow_control(so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (retmp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_bind(struct sonode *so, struct sockaddr *addr,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socklen_t *addrlen, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, bind, cr, addr, addrlen)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_listen(struct sonode *so, int *backlogp, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, listen, cr, backlogp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_connect(struct sonode *so, struct sockaddr *addr,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socklen_t *addrlen, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, connect, cr, addr, addrlen)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_accept(struct sonode *so, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_rval_t rval;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top; inst != NULL; inst = inst->sofi_next) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!SOF_INTERESTED(inst, accept))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson continue;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rval = (inst->sofi_ops->sofop_accept)((sof_handle_t)inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_cookie, cr);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson DTRACE_PROBE2(filter__action, (sof_instance_t), inst,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_rval_t), rval);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (rval != SOF_RVAL_CONTINUE) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(rval != SOF_RVAL_RETURN);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (sof_rval2errno(rval));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (-1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_shutdown(struct sonode *so, int *howp, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, shutdown, cr, howp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_getsockname(struct sonode *so, struct sockaddr *addr,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socklen_t *addrlenp, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, getsockname, cr, addr, addrlenp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_getpeername(struct sonode *so, struct sockaddr *addr,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socklen_t *addrlenp, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, getpeername, cr, addr, addrlenp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_setsockopt(struct sonode *so, int level, int option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson void *optval, socklen_t *optlenp, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, setsockopt, cr, level, option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson optval, optlenp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_getsockopt(struct sonode *so, int level, int option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson void *optval, socklen_t *optlenp, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, getsockopt, cr, level, option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson optval, optlenp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_filter_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int32_t *rvalp, cred_t *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson __SOF_FILTER_OP(so, ioctl, cr, cmd, arg, mode, rvalp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_register(version, name, ops, flags)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Register a socket filter identified by name `name' and which should use
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * the ops vector `ops' for event notification. `flags' should be set to 0.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * On success 0 is returned, otherwise an errno is returned.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_register(int version, const char *name, const sof_ops_t *ops, int flags)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_t *mod;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson _NOTE(ARGUNUSED(flags));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (version != SOF_VERSION)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EINVAL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mod = kmem_zalloc(sizeof (sof_module_t), KM_SLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mod->sofm_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) strcpy(mod->sofm_name, name);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mod->sofm_ops = *ops;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (sof_module_find(name) != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(mod->sofm_name, strlen(mod->sofm_name) + 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(mod, sizeof (sof_module_t));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EEXIST);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&sof_module_list, mod);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_unregister(name)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Try to unregister the socket filter identified by `name'. If the filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * is successfully unregistered, then 0 is returned, otherwise an errno is
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * returned.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_unregister(const char *name)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_module_t *mod;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mod = sof_module_find(name);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mod != NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mod->sofm_refcnt == 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_remove(&sof_module_list, mod);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(mod->sofm_name, strlen(mod->sofm_name) + 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kmem_free(mod, sizeof (sof_module_t));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EBUSY);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&sof_module_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (ENXIO);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_newconn_ready(handle)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The filter `handle` no longer wants to defer the socket it is attached
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * to. A newconn notification will be generated if there is no other filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * that wants the socket deferred.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_newconn_ready(sof_handle_t handle)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = inst->sofi_sonode;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *pso = so->so_listener;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!(inst->sofi_flags & SOFIF_DEFER)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(so->so_state & SS_FIL_DEFER);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_flags &= ~SOFIF_DEFER;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_STAT_ADD(inst, ndeferred, -1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Check if any other filter has deferred the socket. The last
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * filter to remove its DEFER flag will be the one generating the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * wakeup.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top; inst != NULL; inst = inst->sofi_next) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Still deferred; nothing to do */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_flags & SOFIF_DEFER) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_state &= ~SS_FIL_DEFER;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The socket is no longer deferred; move it over to the regular
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * accept list and notify the user. However, it is possible that
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * the socket is being dropped by sof_sonode_drop_deferred(), so
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * first make sure the socket is on the deferred list.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&pso->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!list_link_active(&so->so_acceptq_node)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&pso->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_remove(&pso->so_acceptq_defer, so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&pso->so_acceptq_list, so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cv_signal(&pso->so_acceptq_cv);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&pso->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&pso->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_notify_newconn(pso); /* so_notify_newconn drops the lock */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_bypass(handle)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Stop generating callbacks for `handle'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_bypass(sof_handle_t handle)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = inst->sofi_sonode;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!(inst->sofi_flags & SOFIF_BYPASS)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_flags |= SOFIF_BYPASS;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(so->so_filter_active > 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_active--;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_rcv_flowctrl(handle, enable)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * If `enable' is TRUE, then recv side flow control will be asserted for
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * the socket associated with `handle'. When `enable' is FALSE the filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * indicates that it no longer wants to assert flow control, however, the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * condition will not be removed until there are no other filters asserting
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * flow control and there is space available in the receive buffer.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_rcv_flowctrl(sof_handle_t handle, boolean_t enable)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = inst->sofi_sonode;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (enable) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_flags |= SOFIF_RCV_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_flowctrld = B_TRUE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_state |= SS_FIL_RCV_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_flags &= ~SOFIF_RCV_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_next) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* another filter is asserting flow control */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_flags & SOFIF_RCV_FLOWCTRL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_state &= ~SS_FIL_RCV_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* so_check_flow_control drops so_lock */
a215d4eb400e2ff52f7a17e0781964c37aabfc04Kacheong Poon (void) so_check_flow_control(so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(MUTEX_NOT_HELD(&so->so_lock));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_snd_flowctrl(handle, enable)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * If `enable' is TRUE, then send side flow control will be asserted for
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * the socket associated with `handle'. When `enable' is FALSE the filter
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * indicates that is no longer wants to assert flow control, however, the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * condition will not be removed until there are no other filters asserting
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * flow control and there are tx buffers available.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_snd_flowctrl(sof_handle_t handle, boolean_t enable)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = inst->sofi_sonode;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (enable) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_flags |= SOFIF_SND_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_state |= SS_FIL_SND_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst->sofi_flags &= ~SOFIF_SND_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_top; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_next) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (inst->sofi_flags & SOFIF_SND_FLOWCTRL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_state &= ~SS_FIL_SND_FLOWCTRL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Wake up writer if the socket is no longer flow controlled.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!SO_SND_FLOWCTRLD(so)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* so_notify_writable drops so_lock */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_notify_writable(so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_get_cookie(handle)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Returns the cookie used by `handle'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_get_cookie(sof_handle_t handle)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (((sof_instance_t *)handle)->sofi_cookie);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_cas_cookie(handle, old, new)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Compare-and-swap the cookie used by `handle'.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_cas_cookie(sof_handle_t handle, void *old, void *new)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (atomic_cas_ptr(&inst->sofi_cookie, old, new));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_inject_data_out(handle, mp, msg, flowctrld)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Submit `mp' for transmission. `msg' cannot by NULL, and may contain
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * ancillary data and destination address. Returns 0 when successful
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * in which case `flowctrld' is updated. If flow controlled, no new data
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * should be injected until a SOF_EV_INJECT_DATA_OUT_OK event is observed.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * In case of failure, an errno is returned.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Filters that are lower in the stack than `handle' will see the data
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * before it is transmitted and may end up modifying or freeing the data.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_inject_data_out(sof_handle_t handle, mblk_t *mp, struct nmsghdr *msg,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson boolean_t *flowctrld)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = inst->sofi_sonode;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson if (so->so_state & SS_FIL_STOP) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson freemsg(mp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EPIPE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_tx++;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = so_sendmblk_impl(inst->sofi_sonode, msg, FNONBLOCK,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson kcred, &mp, inst->sofi_next, B_TRUE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(so->so_filter_tx > 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_tx--;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & SS_CLOSING)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cv_signal(&so->so_closing_cv);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (mp != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson freemsg(mp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (error == ENOSPC) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *flowctrld = B_TRUE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *flowctrld = B_FALSE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * sof_inject_data_in(handle, mp, len, flag, flowctrld)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Enqueue `mp' which contains `len' bytes of M_DATA onto the socket
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * associated with `handle'. `flags' should be set to 0. Returns 0 when
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * successful in which case `flowctrld' is updated. If flow controlled,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * no new data should be injected until a SOF_EV_INJECT_DATA_IN_OK event
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * is observed. In case of failure, an errno is returned.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Filters that are higher in the stack than `handle' will see the data
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * before it is enqueued on the receive queue and may end up modifying or
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * freeing the data.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonsof_inject_data_in(sof_handle_t handle, mblk_t *mp, size_t len, int flags,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson boolean_t *flowctrld)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ssize_t avail;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(flags == 0);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson avail = so_queue_msg_impl(inst->sofi_sonode, mp, len, flags, &error,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson NULL, inst->sofi_prev);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* fallback should never happen when there is an active filter */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(error != EOPNOTSUPP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *flowctrld = (avail > 0) ? B_FALSE : B_TRUE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson/*
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * sof_newconn_move(handle, newparent)
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson *
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * Private interface only to be used by KSSL.
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson *
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * Moves the socket associated with `handle' from its current listening
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * socket to the listener associated with `newparent'. The socket being
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * moved must be in a deferred state and it is up to the consumer of the
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * interface to ensure that the `newparent' does not go away while this
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * operation is pending.
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson */
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Perssonboolean_t
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Perssonsof_newconn_move(sof_handle_t handle, sof_handle_t newparent)
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson{
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson sof_instance_t *inst = (sof_instance_t *)handle;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson sof_instance_t *newpinst = (sof_instance_t *)newparent;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson struct sonode *so, *old, *new;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson so = inst->sofi_sonode;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson ASSERT(so->so_state & SS_FIL_DEFER);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson if (inst->sofi_next != NULL || inst->sofi_prev != NULL ||
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson !(so->so_state & SS_FIL_DEFER))
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson return (B_FALSE);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson old = so->so_listener;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson mutex_enter(&old->so_acceptq_lock);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson list_remove(&old->so_acceptq_defer, so);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson old->so_acceptq_len--;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson mutex_exit(&old->so_acceptq_lock);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson new = newpinst->sofi_sonode;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson mutex_enter(&new->so_acceptq_lock);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson list_insert_tail(&new->so_acceptq_defer, so);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson new->so_acceptq_len++;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson mutex_exit(&new->so_acceptq_lock);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson so->so_listener = new;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson return (B_TRUE);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson}