uipc_accf.c revision 65534
165534Salfred/*
265534Salfred * Copyright (c) 2000 Paycounter, Inc.
365534Salfred * Author: Alfred Perlstein <alfred@paycounter.com>, <alfred@FreeBSD.org>
461837Salfred * All rights reserved.
561837Salfred *
661837Salfred * Redistribution and use in source and binary forms, with or without
761837Salfred * modification, are permitted provided that the following conditions
861837Salfred * are met:
961837Salfred * 1. Redistributions of source code must retain the above copyright
1061837Salfred *    notice, this list of conditions and the following disclaimer.
1161837Salfred * 2. Redistributions in binary form must reproduce the above copyright
1261837Salfred *    notice, this list of conditions and the following disclaimer in the
1361837Salfred *    documentation and/or other materials provided with the distribution.
1461837Salfred *
1561837Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1661837Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1761837Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1861837Salfred * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1961837Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2061837Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2161837Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2261837Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2361837Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2461837Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2561837Salfred * SUCH DAMAGE.
2661837Salfred *
2761837Salfred *	$FreeBSD: head/sys/kern/uipc_accf.c 65534 2000-09-06 18:49:13Z alfred $
2861837Salfred */
2961837Salfred
3061837Salfred#define ACCEPT_FILTER_MOD
3161837Salfred
3261837Salfred#include "opt_param.h"
3361837Salfred#include <sys/param.h>
3461837Salfred#include <sys/systm.h>
3561837Salfred#include <sys/domain.h>
3661837Salfred#include <sys/kernel.h>
3761837Salfred#include <sys/proc.h>
3861837Salfred#include <sys/malloc.h>
3961837Salfred#include <sys/mbuf.h>
4061837Salfred#include <sys/protosw.h>
4165534Salfred#include <sys/sysctl.h>
4261837Salfred#include <sys/socket.h>
4361837Salfred#include <sys/socketvar.h>
4461837Salfred#include <sys/queue.h>
4561837Salfred
4661837Salfredstatic SLIST_HEAD(, accept_filter) accept_filtlsthd =
4761837Salfred	SLIST_HEAD_INITIALIZER(&accept_filtlsthd);
4861837Salfred
4961837SalfredMALLOC_DEFINE(M_ACCF, "accf", "accept filter data");
5061837Salfred
5165534Salfredstatic int unloadable = 0;
5265534Salfred
5365534SalfredSYSCTL_DECL(_net_inet);	/* XXX: some header should do this for me */
5465534SalfredSYSCTL_NODE(_net_inet, OID_AUTO, accf, CTLFLAG_RW, 0, "Accept filters");
5565534SalfredSYSCTL_INT(_net_inet_accf, OID_AUTO, unloadable, CTLFLAG_RW, &unloadable, 0,
5665534Salfred	"Allow unload of accept filters (not recommended)");
5765534Salfred
5861837Salfred/*
5961837Salfred * must be passed a malloc'd structure so we don't explode if the kld
6061837Salfred * is unloaded, we leak the struct on deallocation to deal with this,
6161837Salfred * but if a filter is loaded with the same name as a leaked one we re-use
6261837Salfred * the entry.
6361837Salfred */
6461837Salfredint
6561837Salfredaccept_filt_add(struct accept_filter *filt)
6661837Salfred{
6761837Salfred	struct accept_filter *p;
6861837Salfred
6961837Salfred	SLIST_FOREACH(p, &accept_filtlsthd, accf_next)
7061837Salfred		if (strcmp(p->accf_name, filt->accf_name) == 0)  {
7161837Salfred			if (p->accf_callback != NULL) {
7261837Salfred				return (EEXIST);
7361837Salfred			} else {
7461837Salfred				p->accf_callback = filt->accf_callback;
7561837Salfred				FREE(filt, M_ACCF);
7661837Salfred				return (0);
7761837Salfred			}
7861837Salfred		}
7961837Salfred
8061837Salfred	if (p == NULL)
8161837Salfred		SLIST_INSERT_HEAD(&accept_filtlsthd, filt, accf_next);
8261837Salfred	return (0);
8361837Salfred}
8461837Salfred
8561837Salfredint
8661837Salfredaccept_filt_del(char *name)
8761837Salfred{
8861837Salfred	struct accept_filter *p;
8961837Salfred
9061837Salfred	p = accept_filt_get(name);
9161837Salfred	if (p == NULL)
9261837Salfred		return (ENOENT);
9361837Salfred
9461837Salfred	p->accf_callback = NULL;
9561837Salfred	return (0);
9661837Salfred}
9761837Salfred
9861837Salfredstruct accept_filter *
9961837Salfredaccept_filt_get(char *name)
10061837Salfred{
10161837Salfred	struct accept_filter *p;
10261837Salfred
10361837Salfred	SLIST_FOREACH(p, &accept_filtlsthd, accf_next)
10461837Salfred		if (strcmp(p->accf_name, name) == 0)
10561837Salfred			return (p);
10661837Salfred
10761837Salfred	return (NULL);
10861837Salfred}
10961837Salfred
11061837Salfredint
11161837Salfredaccept_filt_generic_mod_event(module_t mod, int event, void *data)
11261837Salfred{
11361837Salfred	struct accept_filter *p;
11461837Salfred	struct accept_filter *accfp = (struct accept_filter *) data;
11561837Salfred	int	s, error;
11661837Salfred
11761837Salfred	switch (event) {
11861837Salfred	case MOD_LOAD:
11961837Salfred		MALLOC(p, struct accept_filter *, sizeof(*p), M_ACCF, M_WAITOK);
12061837Salfred		bcopy(accfp, p, sizeof(*p));
12161837Salfred		s = splnet();
12261837Salfred		error = accept_filt_add(p);
12361837Salfred		splx(s);
12461837Salfred		break;
12561837Salfred
12661837Salfred	case MOD_UNLOAD:
12763645Salfred		/*
12863645Salfred		 * Do not support unloading yet. we don't keep track of refcounts
12963645Salfred		 * and unloading an accept filter callback and then having it called
13063645Salfred		 * is a bad thing.  A simple fix would be to track the refcount
13163645Salfred		 * in the struct accept_filter.
13263645Salfred		 */
13365534Salfred		if (unloadable != 0) {
13465534Salfred			s = splnet();
13565534Salfred			error = accept_filt_del(accfp->accf_name);
13665534Salfred			splx(s);
13765534Salfred		} else
13865534Salfred			error = EOPNOTSUPP;
13961837Salfred		break;
14061837Salfred
14161837Salfred	case MOD_SHUTDOWN:
14261837Salfred		error = 0;
14361837Salfred		break;
14461837Salfred
14561837Salfred	default:
14661837Salfred		error = EOPNOTSUPP;
14761837Salfred		break;
14861837Salfred	}
14961837Salfred
15061837Salfred	return (error);
15161837Salfred}
152