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
47 typedef LIST_HEAD(, packet_filter_hook) pfil_list_t;
48 pfil_list_t pfil_in_list;
49 pfil_list_t pfil_out_list;
50 pfil_list_t pfil_bad_list;
51 static int done_pfil_init;
52
53 void pfil_init __P((void));
54 void pfil_list_add(pfil_list_t *,
55 int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int);
56 void pfil_list_remove(struct packet_filter_hook *,
57 int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)));
58
59 void
60 pfil_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 */
78 void
79 pfil_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
96 void
97 pfil_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 */
118 void
119 pfil_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 */
140 void
141 pfil_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
160 struct packet_filter_hook *
161 pfil_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