xref: /freebsd/sys/kern/uipc_accf.c (revision b601c69bdbe8755d26570261d7fd4c02ee4eff74)
1 /*-
2  * Copyright (c) 2000 Alfred Perlstein <alfred@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *	$FreeBSD$
27  */
28 
29 #define ACCEPT_FILTER_MOD
30 
31 #include "opt_param.h"
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/domain.h>
35 #include <sys/kernel.h>
36 #include <sys/proc.h>
37 #include <sys/malloc.h>
38 #include <sys/mbuf.h>
39 #include <sys/protosw.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/queue.h>
43 
44 static SLIST_HEAD(, accept_filter) accept_filtlsthd =
45 	SLIST_HEAD_INITIALIZER(&accept_filtlsthd);
46 
47 MALLOC_DEFINE(M_ACCF, "accf", "accept filter data");
48 
49 /*
50  * must be passed a malloc'd structure so we don't explode if the kld
51  * is unloaded, we leak the struct on deallocation to deal with this,
52  * but if a filter is loaded with the same name as a leaked one we re-use
53  * the entry.
54  */
55 int
56 accept_filt_add(struct accept_filter *filt)
57 {
58 	struct accept_filter *p;
59 
60 	SLIST_FOREACH(p, &accept_filtlsthd, accf_next)
61 		if (strcmp(p->accf_name, filt->accf_name) == 0)  {
62 			if (p->accf_callback != NULL) {
63 				return (EEXIST);
64 			} else {
65 				p->accf_callback = filt->accf_callback;
66 				FREE(filt, M_ACCF);
67 				return (0);
68 			}
69 		}
70 
71 	if (p == NULL)
72 		SLIST_INSERT_HEAD(&accept_filtlsthd, filt, accf_next);
73 	return (0);
74 }
75 
76 int
77 accept_filt_del(char *name)
78 {
79 	struct accept_filter *p;
80 
81 	p = accept_filt_get(name);
82 	if (p == NULL)
83 		return (ENOENT);
84 
85 	p->accf_callback = NULL;
86 	return (0);
87 }
88 
89 struct accept_filter *
90 accept_filt_get(char *name)
91 {
92 	struct accept_filter *p;
93 
94 	SLIST_FOREACH(p, &accept_filtlsthd, accf_next)
95 		if (strcmp(p->accf_name, name) == 0)
96 			return (p);
97 
98 	return (NULL);
99 }
100 
101 int
102 accept_filt_generic_mod_event(module_t mod, int event, void *data)
103 {
104 	struct accept_filter *p;
105 	struct accept_filter *accfp = (struct accept_filter *) data;
106 	int	s, error;
107 
108 	switch (event) {
109 	case MOD_LOAD:
110 		MALLOC(p, struct accept_filter *, sizeof(*p), M_ACCF, M_WAITOK);
111 		bcopy(accfp, p, sizeof(*p));
112 		s = splnet();
113 		error = accept_filt_add(p);
114 		splx(s);
115 		break;
116 
117 	case MOD_UNLOAD:
118 		/*
119 		 * Do not support unloading yet. we don't keep track of refcounts
120 		 * and unloading an accept filter callback and then having it called
121 		 * is a bad thing.  A simple fix would be to track the refcount
122 		 * in the struct accept_filter.
123 		 */
124 #if 0
125 		s = splnet();
126 		error = accept_filt_del(accfp->accf_name);
127 		splx(s);
128 #endif
129 		error = EOPNOTSUPP;
130 		break;
131 
132 	case MOD_SHUTDOWN:
133 		error = 0;
134 		break;
135 
136 	default:
137 		error = EOPNOTSUPP;
138 		break;
139 	}
140 
141 	return (error);
142 }
143