pfil.c revision 1.5
1/*	$NetBSD: pfil.c,v 1.5 1996/12/20 08:40:46 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;
50static int done_pfil_init;
51
52void pfil_init __P((void));
53void pfil_list_add(pfil_list_t *,
54    int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int);
55void pfil_list_remove(struct packet_filter_hook *,
56    int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)));
57
58void
59pfil_init()
60{
61	LIST_INIT(&pfil_in_list);
62	LIST_INIT(&pfil_out_list);
63	done_pfil_init = 1;
64}
65
66/*
67 * pfil_add_hook() adds a function to the packet filter hook.  the
68 * flags are:
69 *	PFIL_IN		call me on incoming packets
70 *	PFIL_OUT	call me on outgoing packets
71 *	PFIL_ALL	call me on all of the above
72 *	PFIL_WAITOK	OK to call malloc with M_WAITOK.
73 */
74void
75pfil_add_hook(func, flags)
76	int	(*func) __P((void *, int, struct ifnet *, int,
77			     struct mbuf **));
78	int	flags;
79{
80
81	if (done_pfil_init == 0)
82		pfil_init();
83
84	if (flags & PFIL_IN)
85		pfil_list_add(&pfil_in_list, func, flags);
86	if (flags & PFIL_OUT)
87		pfil_list_add(&pfil_out_list, func, flags);
88}
89
90void
91pfil_list_add(list, func, flags)
92	pfil_list_t *list;
93	int	(*func) __P((void *, int, struct ifnet *, int,
94			     struct mbuf **));
95	int	flags;
96{
97	struct packet_filter_hook *pfh;
98
99	pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR,
100	    flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT);
101	if (pfh == NULL)
102		panic("no memory for packet filter hook");
103
104	pfh->pfil_func = func;
105	LIST_INSERT_HEAD(list, pfh, pfil_link);
106}
107
108/*
109 * pfil_remove_hook removes a specific function from the packet filter
110 * hook list.
111 */
112void
113pfil_remove_hook(func, flags)
114	int	(*func) __P((void *, int, struct ifnet *, int,
115			     struct mbuf **));
116	int	flags;
117{
118
119	if (done_pfil_init == 0)
120		pfil_init();
121
122	if (flags & PFIL_IN)
123		pfil_list_remove(pfil_in_list.lh_first, func);
124	if (flags & PFIL_OUT)
125		pfil_list_remove(pfil_out_list.lh_first, func);
126}
127
128/*
129 * pfil_list_remove is an internal function that takes a function off the
130 * specified list.
131 */
132void
133pfil_list_remove(list, func)
134	struct packet_filter_hook *list;
135	int	(*func) __P((void *, int, struct ifnet *, int,
136			     struct mbuf **));
137{
138	struct packet_filter_hook *pfh;
139
140	for (pfh = list; pfh; pfh = pfh->pfil_link.le_next)
141		if (pfh->pfil_func == func) {
142			LIST_REMOVE(pfh, pfil_link);
143			free(pfh, M_IFADDR);
144			return;
145		}
146	printf("pfil_list_remove:  no function on list\n");
147#ifdef DIAGNOSTIC
148	panic("pfil_list_remove");
149#endif
150}
151
152struct packet_filter_hook *
153pfil_hook_get(flag)
154	int flag;
155{
156	if (done_pfil_init)
157		switch (flag) {
158		case PFIL_IN:
159			return (pfil_in_list.lh_first);
160		case PFIL_OUT:
161			return (pfil_out_list.lh_first);
162		}
163	return NULL;
164}
165