FreeBSD/Linux Kernel Cross Reference
sys/net/pfil.c
1 /* $FreeBSD: releng/5.1/sys/net/pfil.c 111119 2003-02-19 05:47:46Z imp $ */
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. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/param.h>
32 #include <sys/errno.h>
33 #include <sys/malloc.h>
34 #include <sys/socket.h>
35 #include <sys/socketvar.h>
36 #include <sys/systm.h>
37 #include <sys/queue.h>
38
39 #include <net/if.h>
40 #include <net/pfil.h>
41
42 static void pfil_init(struct pfil_head *);
43 static int pfil_list_add(pfil_list_t *,
44 int (*)(void *, int, struct ifnet *, int, struct mbuf **), int);
45 static int pfil_list_remove(pfil_list_t *,
46 int (*)(void *, int, struct ifnet *, int, struct mbuf **));
47
48 static void
49 pfil_init(ph)
50 struct pfil_head *ph;
51 {
52
53 TAILQ_INIT(&ph->ph_in);
54 TAILQ_INIT(&ph->ph_out);
55 ph->ph_init = 1;
56 }
57
58 /*
59 * pfil_add_hook() adds a function to the packet filter hook. the
60 * flags are:
61 * PFIL_IN call me on incoming packets
62 * PFIL_OUT call me on outgoing packets
63 * PFIL_ALL call me on all of the above
64 * PFIL_WAITOK OK to call malloc with M_WAITOK.
65 */
66 int
67 pfil_add_hook(func, flags, ph)
68 int (*func)(void *, int, struct ifnet *, int, struct mbuf **);
69 int flags;
70 struct pfil_head *ph;
71 {
72 int err = 0;
73
74 if (ph->ph_init == 0)
75 pfil_init(ph);
76
77 if (flags & PFIL_IN)
78 err = pfil_list_add(&ph->ph_in, func, flags & ~PFIL_OUT);
79 if (err)
80 return err;
81 if (flags & PFIL_OUT)
82 err = pfil_list_add(&ph->ph_out, func, flags & ~PFIL_IN);
83 if (err) {
84 if (flags & PFIL_IN)
85 pfil_list_remove(&ph->ph_in, func);
86 return err;
87 }
88 return 0;
89 }
90
91 static int
92 pfil_list_add(list, func, flags)
93 pfil_list_t *list;
94 int (*func)(void *, int, struct ifnet *, int, 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 return ENOMEM;
103 pfh->pfil_func = func;
104 /*
105 * insert the input list in reverse order of the output list
106 * so that the same path is followed in or out of the kernel.
107 */
108
109 if (flags & PFIL_IN)
110 TAILQ_INSERT_HEAD(list, pfh, pfil_link);
111 else
112 TAILQ_INSERT_TAIL(list, pfh, pfil_link);
113 return 0;
114 }
115
116 /*
117 * pfil_remove_hook removes a specific function from the packet filter
118 * hook list.
119 */
120 int
121 pfil_remove_hook(func, flags, ph)
122 int (*func)(void *, int, struct ifnet *, int, struct mbuf **);
123 int flags;
124 struct pfil_head *ph;
125 {
126 int err = 0;
127
128 if (ph->ph_init == 0)
129 pfil_init(ph);
130
131 if (flags & PFIL_IN)
132 err = pfil_list_remove(&ph->ph_in, func);
133 if ((err == 0) && (flags & PFIL_OUT))
134 err = pfil_list_remove(&ph->ph_out, func);
135 return err;
136 }
137
138 /*
139 * pfil_list_remove is an internal function that takes a function off the
140 * specified list.
141 */
142 static int
143 pfil_list_remove(list, func)
144 pfil_list_t *list;
145 int (*func)(void *, int, struct ifnet *, int, struct mbuf **);
146 {
147 struct packet_filter_hook *pfh;
148
149 TAILQ_FOREACH(pfh, list, pfil_link)
150 if (pfh->pfil_func == func) {
151 TAILQ_REMOVE(list, pfh, pfil_link);
152 free(pfh, M_IFADDR);
153 return 0;
154 }
155 return ENOENT;
156 }
157
158 struct packet_filter_hook *
159 pfil_hook_get(flag, ph)
160 int flag;
161 struct pfil_head *ph;
162 {
163 if (ph->ph_init != 0)
164 switch (flag) {
165 case PFIL_IN:
166 return (TAILQ_FIRST(&ph->ph_in));
167 case PFIL_OUT:
168 return (TAILQ_FIRST(&ph->ph_out));
169 }
170 return NULL;
171 }
Cache object: 4f2f68366127ff3e38b98915cadb5fdf
|