pfil.c revision 1.2
1/*	$NetBSD: pfil.c,v 1.2 1996/10/05 23:41:53 mrg Exp $	*/
2
3/*
4 * Copyright (c) 1996 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed by Matthew R. Green for
18 *      the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/param.h>
36#include <sys/errno.h>
37#include <sys/malloc.h>
38#include <sys/socket.h>
39#include <sys/socketvar.h>
40#include <sys/systm.h>
41#include <sys/proc.h>
42#include <sys/queue.h>
43
44#include <net/if.h>
45#include <net/pfil.h>
46
47typedef LIST_HEAD(, packet_filter_hook) pfil_list_t;
48pfil_list_t pfil_in_list;
49pfil_list_t pfil_out_list;
50pfil_list_t pfil_bad_list;
51static int done_pfil_init;
52
53void pfil_init __P((void));
54void pfil_list_add(pfil_list_t *,
55    int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int);
56void pfil_list_remove(struct packet_filter_hook *,
57    int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)));
58
59void
60pfil_init()
61{
62	LIST_INIT(&pfil_in_list);
63	LIST_INIT(&pfil_out_list);
64	LIST_INIT(&pfil_bad_list);
65	done_pfil_init = 1;
66}
67
68/*
69 * pfil_add_hook() adds a function to the packet filter hook.  the
70 * flags are:
71 *	PFIL_IN		call me on incoming packets
72 *	PFIL_OUT	call me on outgoing packets
73 *	PFIL_BAD	call me when rejecting a packet (that was
74 *			not already reject by in/out filters).
75 *	PFIL_ALL	call me on all of the above
76 *	PFIL_WAITOK	OK to call malloc with M_WAITOK.
77 */
78void
79pfil_add_hook(func, flags)
80	int	(*func) __P((void *, int, struct ifnet *, int,
81			     struct mbuf **));
82	int	flags;
83{
84
85	if (done_pfil_init == 0)
86		pfil_init();
87
88	if (flags & PFIL_IN)
89		pfil_list_add(&pfil_in_list, func, flags);
90	if (flags & PFIL_OUT)
91		pfil_list_add(&pfil_out_list, func, flags);
92	if (flags & PFIL_BAD)
93		pfil_list_add(&pfil_bad_list, func, flags);
94}
95
96void
97pfil_list_add(list, func, flags)
98	pfil_list_t *list;
99	int	(*func) __P((void *, int, struct ifnet *, int,
100			     struct mbuf **));
101	int	flags;
102{
103	struct packet_filter_hook *pfh;
104
105	pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR,
106	    flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT);
107	if (pfh == NULL)
108		panic("no memory for packet filter hook");
109
110	pfh->pfil_func = func;
111	LIST_INSERT_HEAD(list, pfh, pfil_link);
112}
113
114/*
115 * pfil_remove_hook removes a specific function from the packet filter
116 * hook list.
117 */
118void
119pfil_remove_hook(func, flags)
120	int	(*func) __P((void *, int, struct ifnet *, int,
121			     struct mbuf **));
122	int	flags;
123{
124
125	if (done_pfil_init == 0)
126		pfil_init();
127
128	if (flags & PFIL_IN)
129		pfil_list_remove(pfil_in_list.lh_first, func);
130	if (flags & PFIL_OUT)
131		pfil_list_remove(pfil_out_list.lh_first, func);
132	if (flags & PFIL_BAD)
133		pfil_list_remove(pfil_bad_list.lh_first, func);
134}
135
136/*
137 * pfil_list_remove is an internal function that takes a function off the
138 * specified list.
139 */
140void
141pfil_list_remove(list, func)
142	struct packet_filter_hook *list;
143	int	(*func) __P((void *, int, struct ifnet *, int,
144			     struct mbuf **));
145{
146	struct packet_filter_hook *pfh;
147
148	for (pfh = list; pfh; pfh = pfh->pfil_link.le_next)
149		if (pfh->pfil_func == func) {
150			LIST_REMOVE(pfh, pfil_link);
151			free(pfh, M_IFADDR);
152			return;
153		}
154	printf("pfil_list_remove:  no function on list\n");
155#ifdef DIAGNOSTIC
156	panic("pfil_list_remove");
157#endif
158}
159
160struct packet_filter_hook *
161pfil_hook_get(flag)
162	int flag;
163{
164	if (done_pfil_init)
165		switch (flag) {
166		case PFIL_IN:
167			return (pfil_in_list.lh_first);
168		case PFIL_OUT:
169			return (pfil_out_list.lh_first);
170		case PFIL_BAD:
171			return (pfil_bad_list.lh_first);
172		}
173	return NULL;
174}
175