Deleted Added
full compact
pf_ioctl.c (126259) pf_ioctl.c (126261)
1/* $FreeBSD: head/sys/contrib/pf/net/pf_ioctl.c 126261 2004-02-26 02:34:12Z mlaier $ */
1/* $OpenBSD: pf_ioctl.c,v 1.81 2003/08/22 21:50:34 david Exp $ */
2
3/*
4 * Copyright (c) 2001 Daniel Hartmeier
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

--- 20 unchanged lines hidden (view full) ---

29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Effort sponsored in part by the Defense Advanced Research Projects
32 * Agency (DARPA) and Air Force Research Laboratory, Air Force
33 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
34 *
35 */
36
2/* $OpenBSD: pf_ioctl.c,v 1.81 2003/08/22 21:50:34 david Exp $ */
3
4/*
5 * Copyright (c) 2001 Daniel Hartmeier
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions

--- 20 unchanged lines hidden (view full) ---

30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * Effort sponsored in part by the Defense Advanced Research Projects
33 * Agency (DARPA) and Air Force Research Laboratory, Air Force
34 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
35 *
36 */
37
38#if defined(__FreeBSD__)
39#include "opt_inet.h"
40#include "opt_inet6.h"
41#endif
42
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/mbuf.h>
40#include <sys/filio.h>
41#include <sys/fcntl.h>
42#include <sys/socket.h>
43#include <sys/socketvar.h>
44#include <sys/kernel.h>
45#include <sys/time.h>
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/mbuf.h>
46#include <sys/filio.h>
47#include <sys/fcntl.h>
48#include <sys/socket.h>
49#include <sys/socketvar.h>
50#include <sys/kernel.h>
51#include <sys/time.h>
52#include <sys/malloc.h>
53#if defined(__FreeBSD__)
54#include <sys/conf.h>
55#else
46#include <sys/timeout.h>
47#include <sys/pool.h>
56#include <sys/timeout.h>
57#include <sys/pool.h>
48#include <sys/malloc.h>
58#endif
49
50#include <net/if.h>
51#include <net/if_types.h>
52#include <net/route.h>
53
54#include <netinet/in.h>
55#include <netinet/in_var.h>
56#include <netinet/in_systm.h>
57#include <netinet/ip.h>
58#include <netinet/ip_var.h>
59#include <netinet/ip_icmp.h>
60
61#include <net/pfvar.h>
62
63#ifdef INET6
64#include <netinet/ip6.h>
65#include <netinet/in_pcb.h>
59
60#include <net/if.h>
61#include <net/if_types.h>
62#include <net/route.h>
63
64#include <netinet/in.h>
65#include <netinet/in_var.h>
66#include <netinet/in_systm.h>
67#include <netinet/ip.h>
68#include <netinet/ip_var.h>
69#include <netinet/ip_icmp.h>
70
71#include <net/pfvar.h>
72
73#ifdef INET6
74#include <netinet/ip6.h>
75#include <netinet/in_pcb.h>
76#if defined(__FreeBSD__) && (__FreeBSD_version < 501108)
77#include <netinet6/ip6protosw.h>
78#endif
66#endif /* INET6 */
67
68#ifdef ALTQ
69#include <altq/altq.h>
70#endif
71
79#endif /* INET6 */
80
81#ifdef ALTQ
82#include <altq/altq.h>
83#endif
84
85#if defined(__FreeBSD__)
86#if (__FreeBSD_version >= 500112)
87#include <sys/limits.h>
88#else
89#include <machine/limits.h>
90#endif
91#include <sys/lock.h>
92#include <sys/mutex.h>
93#if __FreeBSD_version < 501108
94#include <sys/protosw.h>
95#endif
96#include <net/pfil.h>
97#endif /* __FreeBSD__ */
98
99#if defined(__FreeBSD__)
100void init_zone_var(void);
101void cleanup_pf_zone(void);
102int pfattach(void);
103#else
72void pfattach(int);
73int pfopen(dev_t, int, int, struct proc *);
74int pfclose(dev_t, int, int, struct proc *);
104void pfattach(int);
105int pfopen(dev_t, int, int, struct proc *);
106int pfclose(dev_t, int, int, struct proc *);
107#endif
75struct pf_pool *pf_get_pool(char *, char *, u_int32_t,
76 u_int8_t, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
77int pf_get_ruleset_number(u_int8_t);
78void pf_init_ruleset(struct pf_ruleset *);
79void pf_mv_pool(struct pf_palist *, struct pf_palist *);
80void pf_empty_pool(struct pf_palist *);
108struct pf_pool *pf_get_pool(char *, char *, u_int32_t,
109 u_int8_t, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
110int pf_get_ruleset_number(u_int8_t);
111void pf_init_ruleset(struct pf_ruleset *);
112void pf_mv_pool(struct pf_palist *, struct pf_palist *);
113void pf_empty_pool(struct pf_palist *);
114#if defined(__FreeBSD__)
115int pfioctl(dev_t, u_long, caddr_t, int, struct thread *);
116#else
81int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
117int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
118#endif
82
119
120#if defined(__FreeBSD__)
121extern struct callout pf_expire_to;
122#if __FreeBSD_version < 501108
123extern struct protosw inetsw[];
124#endif
125#else
83extern struct timeout pf_expire_to;
126extern struct timeout pf_expire_to;
127#endif
84
85struct pf_rule pf_default_rule;
86
87#define TAGID_MAX 50000
88TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags);
89
90#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
91
128
129struct pf_rule pf_default_rule;
130
131#define TAGID_MAX 50000
132TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags);
133
134#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
135
136
137#if defined(__FreeBSD__)
138static dev_t pf_dev;
139
140/*
141 * XXX - These are new and need to be checked when moveing to a new version
142 */
143static int pf_beginrules(void *addr);
144static int pf_commitrules(void *addr);
145#if defined(ALTQ)
146static int pf_beginaltqs(void *addr);
147static int pf_commitaltqs(void *addr);
148static int pf_stopaltq(void);
149#endif
150static void pf_clearstates(void);
151static int pf_clear_tables(void *addr);
152/*
153 * XXX - These are new and need to be checked when moveing to a new version
154 */
155
156#if (__FreeBSD_version < 501108)
157static int pf_check_in(void *ip, int hlen, struct ifnet *ifp, int dir,
158 struct mbuf **m);
159static int pf_check_out(void *ip, int hlen, struct ifnet *ifp, int dir,
160 struct mbuf **m);
161#if defined(INET6)
162static int pf_check6_in(void *ip, int hlen, struct ifnet *ifp, int dir,
163 struct mbuf **m);
164static int pf_check6_out(void *ip, int hlen, struct ifnet *ifp, int dir,
165 struct mbuf **m);
166#endif
167#else /* (__FreeBSD_version >= 501108) */
168static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
169 int dir);
170static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
171 int dir);
172#if defined(INET6)
173static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
174 int dir);
175static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
176 int dir);
177#endif
178#endif /* (__FreeBSD_version >= 501108) */
179static int hook_pf(void);
180static int dehook_pf(void);
181static int shutdown_pf(void);
182static int pf_load(void);
183static int pf_unload(void);
184
185
186
187static struct cdevsw pf_cdevsw = {
188#if (__FreeBSD_version < 500105)
189 /* open */ noopen,
190 /* close */ noclose,
191 /* read */ noread,
192 /* write */ nowrite,
193 /* ioctl */ pfioctl,
194 /* poll */ nopoll,
195 /* mmap */ nommap,
196 /* strategy */ nostrategy,
197 /* name */ PF_NAME,
198 /* maj */ PF_CDEV_MAJOR,
199 /* dump */ nodump,
200 /* psize */ nopsize,
201 /* flags */ 0,
202 /* kqfilter */ nokqfilter,
203#elif (__FreeBSD_version < 501110)
204 .d_open = noopen,
205 .d_close = noclose,
206 .d_read = noread,
207 .d_write = nowrite,
208 .d_ioctl = pfioctl,
209 .d_poll = nopoll,
210 .d_mmap = nommap,
211 .d_strategy = nostrategy,
212 .d_name = PF_NAME,
213 .d_maj = MAJOR_AUTO, /* PF_CDEV_MAJOR */
214 .d_dump = nodump,
215 .d_flags = 0,
216 .d_kqfilter = nokqfilter,
217#else
218 .d_ioctl = pfioctl,
219 .d_name = PF_NAME,
220 .d_version = D_VERSION,
221#endif
222};
223#endif /* __FreeBSD__ */
224
225#if defined(__FreeBSD__)
226static volatile int pf_pfil_hooked = 0;
227struct mtx pf_task_mtx;
228
92void
229void
230init_pf_mutex(void)
231{
232 mtx_init(&pf_task_mtx, "pf task mtx", NULL, MTX_DEF);
233/*
234 * pf_altq_mtx is initialized at altq_subr.c.
235 *
236 * #if defined(ALTQ) && !defined(ALTQ3_COMPAT)
237 * mtx_init(&pf_altq_mtx, "pf altq mtx", NULL, MTX_DEF);
238 * #endif
239 */
240}
241
242void
243destroy_pf_mutex(void)
244{
245 mtx_destroy(&pf_task_mtx);
246/*
247 * pf_altq_mtx is initialized at altq_subr.c.
248 *
249 * #if defined(ALTQ) && !defined(ALTQ3_COMPAT)
250 * mtx_destroy(&pf_altq_mtx);
251 * #endif
252 */
253}
254
255void
256init_zone_var(void)
257{
258 pf_tree_pl = pf_rule_pl = pf_addr_pl = NULL;
259 pf_state_pl = pf_altq_pl = pf_pooladdr_pl = NULL;
260 pf_frent_pl = pf_frag_pl = pf_cache_pl = pf_cent_pl = NULL;
261 pf_state_scrub_pl = NULL;
262 pfr_ktable_pl = pfr_kentry_pl = NULL;
263}
264
265void
266cleanup_pf_zone(void)
267{
268 UMA_DESTROY(pf_tree_pl);
269 UMA_DESTROY(pf_rule_pl);
270 UMA_DESTROY(pf_addr_pl);
271 UMA_DESTROY(pf_state_pl);
272 UMA_DESTROY(pf_altq_pl);
273 UMA_DESTROY(pf_pooladdr_pl);
274 UMA_DESTROY(pf_frent_pl);
275 UMA_DESTROY(pf_frag_pl);
276 UMA_DESTROY(pf_cache_pl);
277 UMA_DESTROY(pf_cent_pl);
278 UMA_DESTROY(pfr_ktable_pl);
279 UMA_DESTROY(pfr_kentry_pl);
280 UMA_DESTROY(pf_state_scrub_pl);
281}
282#endif /* __FreeBSD__ */
283
284#if defined(__FreeBSD__)
285int
286pfattach(void)
287{
288 u_int32_t *my_timeout = pf_default_rule.timeout;
289 int error = 1;
290
291 do {
292 UMA_CREATE(pf_tree_pl, struct pf_tree_node, "pftrpl");
293 UMA_CREATE(pf_rule_pl, struct pf_rule, "pfrulepl");
294 UMA_CREATE(pf_addr_pl, struct pf_addr_dyn, "pfaddrpl");
295 UMA_CREATE(pf_state_pl, struct pf_state, "pfstatepl");
296 UMA_CREATE(pf_altq_pl, struct pf_altq, "pfaltqpl");
297 UMA_CREATE(pf_pooladdr_pl, struct pf_pooladdr, "pfpooladdrpl");
298 UMA_CREATE(pfr_ktable_pl, struct pfr_ktable, "pfrktable");
299 UMA_CREATE(pfr_kentry_pl, struct pfr_kentry, "pfrkentry");
300 UMA_CREATE(pf_frent_pl, struct pf_frent, "pffrent");
301 UMA_CREATE(pf_frag_pl, struct pf_fragment, "pffrag");
302 UMA_CREATE(pf_cache_pl, struct pf_fragment, "pffrcache");
303 UMA_CREATE(pf_cent_pl, struct pf_frcache, "pffrcent");
304 UMA_CREATE(pf_state_scrub_pl, struct pf_state_scrub,
305 "pfstatescrub");
306 error = 0;
307 } while(0);
308 if (error) {
309 cleanup_pf_zone();
310 return (error);
311 }
312 pfr_initialize();
313 if ( (error = pf_osfp_initialize()) ) {
314 cleanup_pf_zone();
315 pf_osfp_cleanup();
316 return (error);
317 }
318
319 pf_pool_limits[PF_LIMIT_STATES].pp = pf_state_pl;
320 pf_pool_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
321 pf_pool_limits[PF_LIMIT_FRAGS].pp = pf_frent_pl;
322 pf_pool_limits[PF_LIMIT_FRAGS].limit = PFFRAG_FRENT_HIWAT;
323 uma_zone_set_max(pf_pool_limits[PF_LIMIT_STATES].pp,
324 pf_pool_limits[PF_LIMIT_STATES].limit);
325
326 RB_INIT(&tree_lan_ext);
327 RB_INIT(&tree_ext_gwy);
328 TAILQ_INIT(&pf_anchors);
329 pf_init_ruleset(&pf_main_ruleset);
330 TAILQ_INIT(&pf_altqs[0]);
331 TAILQ_INIT(&pf_altqs[1]);
332 TAILQ_INIT(&pf_pabuf);
333 pf_altqs_active = &pf_altqs[0];
334 pf_altqs_inactive = &pf_altqs[1];
335
336 /* default rule should never be garbage collected */
337 pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
338 pf_default_rule.action = PF_PASS;
339 pf_default_rule.nr = -1;
340
341 /* initialize default timeouts */
342 my_timeout[PFTM_TCP_FIRST_PACKET] = 120; /* First TCP packet */
343 my_timeout[PFTM_TCP_OPENING] = 30; /* No response yet */
344 my_timeout[PFTM_TCP_ESTABLISHED] = 24*60*60; /* Established */
345 my_timeout[PFTM_TCP_CLOSING] = 15 * 60; /* Half closed */
346 my_timeout[PFTM_TCP_FIN_WAIT] = 45; /* Got both FINs */
347 my_timeout[PFTM_TCP_CLOSED] = 90; /* Got a RST */
348 my_timeout[PFTM_UDP_FIRST_PACKET] = 60; /* First UDP packet */
349 my_timeout[PFTM_UDP_SINGLE] = 30; /* Unidirectional */
350 my_timeout[PFTM_UDP_MULTIPLE] = 60; /* Bidirectional */
351 my_timeout[PFTM_ICMP_FIRST_PACKET] = 20; /* First ICMP packet */
352 my_timeout[PFTM_ICMP_ERROR_REPLY] = 10; /* Got error response */
353 my_timeout[PFTM_OTHER_FIRST_PACKET] = 60; /* First packet */
354 my_timeout[PFTM_OTHER_SINGLE] = 30; /* Unidirectional */
355 my_timeout[PFTM_OTHER_MULTIPLE] = 60; /* Bidirectional */
356 my_timeout[PFTM_FRAG] = 30; /* Fragment expire */
357 my_timeout[PFTM_INTERVAL] = 10; /* Expire interval */
358
359 /*
360 * XXX
361 * The 2nd arg. 0 to callout_init(9) shoule be set to CALLOUT_MPSAFE
362 * if Gaint lock is removed from the network stack.
363 */
364 callout_init(&pf_expire_to, 0);
365 callout_reset(&pf_expire_to, my_timeout[PFTM_INTERVAL] * hz,
366 pf_purge_timeout, &pf_expire_to);
367
368 pf_normalize_init();
369 pf_status.debug = PF_DEBUG_URGENT;
370 pf_pfil_hooked = 0;
371 return (error);
372}
373#else /* !__FreeBSD__ */
374void
93pfattach(int num)
94{
95 u_int32_t *timeout = pf_default_rule.timeout;
96
97 pool_init(&pf_tree_pl, sizeof(struct pf_tree_node), 0, 0, 0, "pftrpl",
98 NULL);
99 pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
100 &pool_allocator_nointr);

--- 23 unchanged lines hidden (view full) ---

124
125 /* default rule should never be garbage collected */
126 pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
127 pf_default_rule.action = PF_PASS;
128 pf_default_rule.nr = -1;
129
130 /* initialize default timeouts */
131 timeout[PFTM_TCP_FIRST_PACKET] = 120; /* First TCP packet */
375pfattach(int num)
376{
377 u_int32_t *timeout = pf_default_rule.timeout;
378
379 pool_init(&pf_tree_pl, sizeof(struct pf_tree_node), 0, 0, 0, "pftrpl",
380 NULL);
381 pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
382 &pool_allocator_nointr);

--- 23 unchanged lines hidden (view full) ---

406
407 /* default rule should never be garbage collected */
408 pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
409 pf_default_rule.action = PF_PASS;
410 pf_default_rule.nr = -1;
411
412 /* initialize default timeouts */
413 timeout[PFTM_TCP_FIRST_PACKET] = 120; /* First TCP packet */
132 timeout[PFTM_TCP_OPENING] = 30; /* No response yet */
414 timeout[PFTM_TCP_OPENING] = 30; /* No response yet */
133 timeout[PFTM_TCP_ESTABLISHED] = 24*60*60; /* Established */
134 timeout[PFTM_TCP_CLOSING] = 15 * 60; /* Half closed */
135 timeout[PFTM_TCP_FIN_WAIT] = 45; /* Got both FINs */
136 timeout[PFTM_TCP_CLOSED] = 90; /* Got a RST */
137 timeout[PFTM_UDP_FIRST_PACKET] = 60; /* First UDP packet */
138 timeout[PFTM_UDP_SINGLE] = 30; /* Unidirectional */
139 timeout[PFTM_UDP_MULTIPLE] = 60; /* Bidirectional */
140 timeout[PFTM_ICMP_FIRST_PACKET] = 20; /* First ICMP packet */

--- 5 unchanged lines hidden (view full) ---

146 timeout[PFTM_INTERVAL] = 10; /* Expire interval */
147
148 timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to);
149 timeout_add(&pf_expire_to, timeout[PFTM_INTERVAL] * hz);
150
151 pf_normalize_init();
152 pf_status.debug = PF_DEBUG_URGENT;
153}
415 timeout[PFTM_TCP_ESTABLISHED] = 24*60*60; /* Established */
416 timeout[PFTM_TCP_CLOSING] = 15 * 60; /* Half closed */
417 timeout[PFTM_TCP_FIN_WAIT] = 45; /* Got both FINs */
418 timeout[PFTM_TCP_CLOSED] = 90; /* Got a RST */
419 timeout[PFTM_UDP_FIRST_PACKET] = 60; /* First UDP packet */
420 timeout[PFTM_UDP_SINGLE] = 30; /* Unidirectional */
421 timeout[PFTM_UDP_MULTIPLE] = 60; /* Bidirectional */
422 timeout[PFTM_ICMP_FIRST_PACKET] = 20; /* First ICMP packet */

--- 5 unchanged lines hidden (view full) ---

428 timeout[PFTM_INTERVAL] = 10; /* Expire interval */
429
430 timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to);
431 timeout_add(&pf_expire_to, timeout[PFTM_INTERVAL] * hz);
432
433 pf_normalize_init();
434 pf_status.debug = PF_DEBUG_URGENT;
435}
436#endif /* __FreeBSD__ */
154
437
438#if !defined(__FreeBSD__)
155int
156pfopen(dev_t dev, int flags, int fmt, struct proc *p)
157{
158 if (minor(dev) >= 1)
159 return (ENXIO);
160 return (0);
161}
439int
440pfopen(dev_t dev, int flags, int fmt, struct proc *p)
441{
442 if (minor(dev) >= 1)
443 return (ENXIO);
444 return (0);
445}
446#endif
162
447
448#if !defined(__FreeBSD__)
163int
164pfclose(dev_t dev, int flags, int fmt, struct proc *p)
165{
166 if (minor(dev) >= 1)
167 return (ENXIO);
168 return (0);
169}
449int
450pfclose(dev_t dev, int flags, int fmt, struct proc *p)
451{
452 if (minor(dev) >= 1)
453 return (ENXIO);
454 return (0);
455}
456#endif
170
171struct pf_pool *
172pf_get_pool(char *anchorname, char *rulesetname, u_int32_t ticket,
173 u_int8_t rule_action, u_int8_t rule_number, u_int8_t r_last,
174 u_int8_t active, u_int8_t check_ticket)
175{
176 struct pf_ruleset *ruleset;
177 struct pf_rule *rule;

--- 166 unchanged lines hidden (view full) ---

344}
345
346void
347pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
348{
349 struct pf_anchor *anchor;
350 int i;
351
457
458struct pf_pool *
459pf_get_pool(char *anchorname, char *rulesetname, u_int32_t ticket,
460 u_int8_t rule_action, u_int8_t rule_number, u_int8_t r_last,
461 u_int8_t active, u_int8_t check_ticket)
462{
463 struct pf_ruleset *ruleset;
464 struct pf_rule *rule;

--- 166 unchanged lines hidden (view full) ---

631}
632
633void
634pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
635{
636 struct pf_anchor *anchor;
637 int i;
638
352 if (ruleset == NULL || ruleset->anchor == NULL || ruleset->tables > 0 || ruleset->topen)
639 if (ruleset == NULL || ruleset->anchor == NULL || ruleset->tables > 0 ||
640 ruleset->topen)
353 return;
354 for (i = 0; i < PF_RULESET_MAX; ++i)
355 if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
356 !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr))
357 return;
358
359 anchor = ruleset->anchor;
360 TAILQ_REMOVE(&anchor->rulesets, ruleset, entries);

--- 132 unchanged lines hidden (view full) ---

493 TAILQ_REMOVE(&pf_tags, p, entries);
494 free(p, M_TEMP);
495 }
496 break;
497 }
498 }
499}
500
641 return;
642 for (i = 0; i < PF_RULESET_MAX; ++i)
643 if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
644 !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr))
645 return;
646
647 anchor = ruleset->anchor;
648 TAILQ_REMOVE(&anchor->rulesets, ruleset, entries);

--- 132 unchanged lines hidden (view full) ---

781 TAILQ_REMOVE(&pf_tags, p, entries);
782 free(p, M_TEMP);
783 }
784 break;
785 }
786 }
787}
788
789#if defined(__FreeBSD__)
501int
790int
791pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
792#else
793int
502pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
794pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
795#endif
503{
504 struct pf_pooladdr *pa = NULL;
505 struct pf_pool *pool = NULL;
506 int s;
507 int error = 0;
508
509 /* XXX keep in sync with switch() below */
510 if (securelevel > 1)

--- 26 unchanged lines hidden (view full) ---

537 case DIOCRADDADDRS:
538 case DIOCRDELADDRS:
539 case DIOCRSETADDRS:
540 case DIOCRGETADDRS:
541 case DIOCRGETASTATS:
542 case DIOCRCLRASTATS:
543 case DIOCRTSTADDRS:
544 case DIOCOSFPGET:
796{
797 struct pf_pooladdr *pa = NULL;
798 struct pf_pool *pool = NULL;
799 int s;
800 int error = 0;
801
802 /* XXX keep in sync with switch() below */
803 if (securelevel > 1)

--- 26 unchanged lines hidden (view full) ---

830 case DIOCRADDADDRS:
831 case DIOCRDELADDRS:
832 case DIOCRSETADDRS:
833 case DIOCRGETADDRS:
834 case DIOCRGETASTATS:
835 case DIOCRCLRASTATS:
836 case DIOCRTSTADDRS:
837 case DIOCOSFPGET:
838#if defined(__FreeBSD__)
839 case DIOCGIFSPEED:
840#endif
545 break;
546 default:
547 return (EPERM);
548 }
549
550 if (!(flags & FWRITE))
551 switch (cmd) {
552 case DIOCGETRULES:

--- 13 unchanged lines hidden (view full) ---

566 case DIOCGETRULESETS:
567 case DIOCGETRULESET:
568 case DIOCRGETTABLES:
569 case DIOCRGETTSTATS:
570 case DIOCRGETADDRS:
571 case DIOCRGETASTATS:
572 case DIOCRTSTADDRS:
573 case DIOCOSFPGET:
841 break;
842 default:
843 return (EPERM);
844 }
845
846 if (!(flags & FWRITE))
847 switch (cmd) {
848 case DIOCGETRULES:

--- 13 unchanged lines hidden (view full) ---

862 case DIOCGETRULESETS:
863 case DIOCGETRULESET:
864 case DIOCRGETTABLES:
865 case DIOCRGETTSTATS:
866 case DIOCRGETADDRS:
867 case DIOCRGETASTATS:
868 case DIOCRTSTADDRS:
869 case DIOCOSFPGET:
870#if defined(__FreeBSD__)
871 case DIOCGIFSPEED:
872#endif
574 break;
575 default:
576 return (EACCES);
577 }
578
873 break;
874 default:
875 return (EACCES);
876 }
877
878#if defined(__FreeBSD__)
879 PF_LOCK();
880#endif
881
579 switch (cmd) {
580
581 case DIOCSTART:
582 if (pf_status.running)
583 error = EEXIST;
584 else {
585 u_int32_t states = pf_status.states;
882 switch (cmd) {
883
884 case DIOCSTART:
885 if (pf_status.running)
886 error = EEXIST;
887 else {
888 u_int32_t states = pf_status.states;
889#if defined(__FreeBSD__)
890 PF_UNLOCK();
891 error = hook_pf();
892 PF_LOCK();
893 if (error) {
894 DPFPRINTF(PF_DEBUG_MISC,
895 ("pf: pfil registeration fail\n"));
896 break;
897 }
898#endif
586 bzero(&pf_status, sizeof(struct pf_status));
587 pf_status.running = 1;
588 pf_status.states = states;
899 bzero(&pf_status, sizeof(struct pf_status));
900 pf_status.running = 1;
901 pf_status.states = states;
902#if defined(__FreeBSD__)
903 pf_status.since = time_second;
904#else
589 pf_status.since = time.tv_sec;
905 pf_status.since = time.tv_sec;
906#endif
590 if (status_ifp != NULL)
907 if (status_ifp != NULL)
908#if defined(__FreeBSD__) && (__FreeBSD_version < 501113)
909 snprintf(pf_status.ifname, IFNAMSIZ, "%s%d",
910 status_ifp->if_name, status_ifp->if_unit);
911#else
591 strlcpy(pf_status.ifname,
592 status_ifp->if_xname, IFNAMSIZ);
912 strlcpy(pf_status.ifname,
913 status_ifp->if_xname, IFNAMSIZ);
914#endif
593 DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
594 }
595 break;
596
597 case DIOCSTOP:
598 if (!pf_status.running)
599 error = ENOENT;
600 else {
601 pf_status.running = 0;
915 DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
916 }
917 break;
918
919 case DIOCSTOP:
920 if (!pf_status.running)
921 error = ENOENT;
922 else {
923 pf_status.running = 0;
924#if defined(__FreeBSD__)
925 PF_UNLOCK();
926 error = dehook_pf();
927 PF_LOCK();
928 if (error) {
929 pf_status.running = 1;
930 DPFPRINTF(PF_DEBUG_MISC,
931 ("pf: pfil unregisteration failed\n"));
932 }
933#endif
602 DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
603 }
604 break;
605
606 case DIOCBEGINRULES: {
607 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
608 struct pf_ruleset *ruleset;
609 struct pf_rule *rule;

--- 493 unchanged lines hidden (view full) ---

1103 break;
1104 }
1105 s = splsoftnet();
1106 bcopy(&ps->state, state, sizeof(struct pf_state));
1107 state->rule.ptr = NULL;
1108 state->nat_rule.ptr = NULL;
1109 state->anchor.ptr = NULL;
1110 state->rt_ifp = NULL;
934 DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
935 }
936 break;
937
938 case DIOCBEGINRULES: {
939 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
940 struct pf_ruleset *ruleset;
941 struct pf_rule *rule;

--- 493 unchanged lines hidden (view full) ---

1435 break;
1436 }
1437 s = splsoftnet();
1438 bcopy(&ps->state, state, sizeof(struct pf_state));
1439 state->rule.ptr = NULL;
1440 state->nat_rule.ptr = NULL;
1441 state->anchor.ptr = NULL;
1442 state->rt_ifp = NULL;
1443#if defined(__FreeBSD__)
1444 state->creation = time_second;
1445#else
1111 state->creation = time.tv_sec;
1446 state->creation = time.tv_sec;
1447#endif
1112 state->packets[0] = state->packets[1] = 0;
1113 state->bytes[0] = state->bytes[1] = 0;
1114 if (pf_insert_state(state)) {
1115 pool_put(&pf_state_pl, state);
1116 error = ENOMEM;
1117 }
1118 splx(s);
1119 break;

--- 19 unchanged lines hidden (view full) ---

1139 bcopy(n->state, &ps->state, sizeof(struct pf_state));
1140 ps->state.rule.nr = n->state->rule.ptr->nr;
1141 ps->state.nat_rule.nr = (n->state->nat_rule.ptr == NULL) ?
1142 -1 : n->state->nat_rule.ptr->nr;
1143 ps->state.anchor.nr = (n->state->anchor.ptr == NULL) ?
1144 -1 : n->state->anchor.ptr->nr;
1145 splx(s);
1146 ps->state.expire = pf_state_expires(n->state);
1448 state->packets[0] = state->packets[1] = 0;
1449 state->bytes[0] = state->bytes[1] = 0;
1450 if (pf_insert_state(state)) {
1451 pool_put(&pf_state_pl, state);
1452 error = ENOMEM;
1453 }
1454 splx(s);
1455 break;

--- 19 unchanged lines hidden (view full) ---

1475 bcopy(n->state, &ps->state, sizeof(struct pf_state));
1476 ps->state.rule.nr = n->state->rule.ptr->nr;
1477 ps->state.nat_rule.nr = (n->state->nat_rule.ptr == NULL) ?
1478 -1 : n->state->nat_rule.ptr->nr;
1479 ps->state.anchor.nr = (n->state->anchor.ptr == NULL) ?
1480 -1 : n->state->anchor.ptr->nr;
1481 splx(s);
1482 ps->state.expire = pf_state_expires(n->state);
1483#if defined(__FreeBSD__)
1484 if (ps->state.expire > time_second)
1485 ps->state.expire -= time_second;
1486#else
1147 if (ps->state.expire > time.tv_sec)
1148 ps->state.expire -= time.tv_sec;
1487 if (ps->state.expire > time.tv_sec)
1488 ps->state.expire -= time.tv_sec;
1489#endif
1149 else
1150 ps->state.expire = 0;
1151 break;
1152 }
1153
1154 case DIOCGETSTATES: {
1155 struct pfioc_states *ps = (struct pfioc_states *)addr;
1156 struct pf_tree_node *n;
1157 struct pf_state *p, pstore;
1158 u_int32_t nr = 0;
1159 int space = ps->ps_len;
1160
1161 if (space == 0) {
1162 s = splsoftnet();
1163 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
1164 nr++;
1165 splx(s);
1166 ps->ps_len = sizeof(struct pf_state) * nr;
1490 else
1491 ps->state.expire = 0;
1492 break;
1493 }
1494
1495 case DIOCGETSTATES: {
1496 struct pfioc_states *ps = (struct pfioc_states *)addr;
1497 struct pf_tree_node *n;
1498 struct pf_state *p, pstore;
1499 u_int32_t nr = 0;
1500 int space = ps->ps_len;
1501
1502 if (space == 0) {
1503 s = splsoftnet();
1504 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
1505 nr++;
1506 splx(s);
1507 ps->ps_len = sizeof(struct pf_state) * nr;
1508#if defined(__FreeBSD__)
1509 PF_UNLOCK();
1510#endif
1167 return (0);
1168 }
1169
1170 s = splsoftnet();
1171 p = ps->ps_states;
1172 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
1511 return (0);
1512 }
1513
1514 s = splsoftnet();
1515 p = ps->ps_states;
1516 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
1517#if defined(__FreeBSD__)
1518 int secs = time_second;
1519#else
1173 int secs = time.tv_sec;
1520 int secs = time.tv_sec;
1521#endif
1174
1175 if ((nr + 1) * sizeof(*p) > (unsigned)ps->ps_len)
1176 break;
1177
1178 bcopy(n->state, &pstore, sizeof(pstore));
1179 pstore.rule.nr = n->state->rule.ptr->nr;
1180 pstore.nat_rule.nr = (n->state->nat_rule.ptr == NULL) ?
1181 -1 : n->state->nat_rule.ptr->nr;
1182 pstore.anchor.nr = (n->state->anchor.ptr == NULL) ?
1183 -1 : n->state->anchor.ptr->nr;
1184 pstore.creation = secs - pstore.creation;
1185 pstore.expire = pf_state_expires(n->state);
1186 if (pstore.expire > secs)
1187 pstore.expire -= secs;
1188 else
1189 pstore.expire = 0;
1522
1523 if ((nr + 1) * sizeof(*p) > (unsigned)ps->ps_len)
1524 break;
1525
1526 bcopy(n->state, &pstore, sizeof(pstore));
1527 pstore.rule.nr = n->state->rule.ptr->nr;
1528 pstore.nat_rule.nr = (n->state->nat_rule.ptr == NULL) ?
1529 -1 : n->state->nat_rule.ptr->nr;
1530 pstore.anchor.nr = (n->state->anchor.ptr == NULL) ?
1531 -1 : n->state->anchor.ptr->nr;
1532 pstore.creation = secs - pstore.creation;
1533 pstore.expire = pf_state_expires(n->state);
1534 if (pstore.expire > secs)
1535 pstore.expire -= secs;
1536 else
1537 pstore.expire = 0;
1538#if defined(__FreeBSD__)
1539 PF_COPYOUT(&pstore, p, sizeof(*p), error);
1540#else
1190 error = copyout(&pstore, p, sizeof(*p));
1541 error = copyout(&pstore, p, sizeof(*p));
1542#endif
1191 if (error) {
1192 splx(s);
1193 goto fail;
1194 }
1195 p++;
1196 nr++;
1197 }
1198 ps->ps_len = sizeof(struct pf_state) * nr;

--- 32 unchanged lines hidden (view full) ---

1231 u_int32_t debug = pf_status.debug;
1232
1233 bzero(&pf_status, sizeof(struct pf_status));
1234 pf_status.running = running;
1235 pf_status.states = states;
1236 pf_status.since = since;
1237 pf_status.debug = debug;
1238 if (status_ifp != NULL)
1543 if (error) {
1544 splx(s);
1545 goto fail;
1546 }
1547 p++;
1548 nr++;
1549 }
1550 ps->ps_len = sizeof(struct pf_state) * nr;

--- 32 unchanged lines hidden (view full) ---

1583 u_int32_t debug = pf_status.debug;
1584
1585 bzero(&pf_status, sizeof(struct pf_status));
1586 pf_status.running = running;
1587 pf_status.states = states;
1588 pf_status.since = since;
1589 pf_status.debug = debug;
1590 if (status_ifp != NULL)
1591#if defined(__FreeBSD__) && (__FreeBSD_version < 501113)
1592 snprintf(pf_status.ifname, IFNAMSIZ, "%s%d",
1593 status_ifp->if_name, status_ifp->if_unit);
1594#else
1239 strlcpy(pf_status.ifname,
1240 status_ifp->if_xname, IFNAMSIZ);
1595 strlcpy(pf_status.ifname,
1596 status_ifp->if_xname, IFNAMSIZ);
1597#endif
1241 break;
1242 }
1243
1244 case DIOCNATLOOK: {
1245 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
1246 struct pf_state *st;
1247 struct pf_tree_node key;
1248 int direction = pnl->direction;

--- 85 unchanged lines hidden (view full) ---

1334 case DIOCSETLIMIT: {
1335 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
1336 int old_limit;
1337
1338 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
1339 error = EINVAL;
1340 goto fail;
1341 }
1598 break;
1599 }
1600
1601 case DIOCNATLOOK: {
1602 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
1603 struct pf_state *st;
1604 struct pf_tree_node key;
1605 int direction = pnl->direction;

--- 85 unchanged lines hidden (view full) ---

1691 case DIOCSETLIMIT: {
1692 struct pfioc_limit *pl = (struct pfioc_limit *)addr;
1693 int old_limit;
1694
1695 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
1696 error = EINVAL;
1697 goto fail;
1698 }
1699#if defined(__FreeBSD__)
1700 uma_zone_set_max(pf_pool_limits[pl->index].pp, pl->limit);
1701#else
1342 if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
1343 pl->limit, NULL, 0) != 0) {
1344 error = EBUSY;
1345 goto fail;
1346 }
1702 if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
1703 pl->limit, NULL, 0) != 0) {
1704 error = EBUSY;
1705 goto fail;
1706 }
1707#endif
1347 old_limit = pf_pool_limits[pl->index].limit;
1348 pf_pool_limits[pl->index].limit = pl->limit;
1349 pl->limit = old_limit;
1350 break;
1351 }
1352
1353 case DIOCSETDEBUG: {
1354 u_int32_t *level = (u_int32_t *)addr;

--- 10 unchanged lines hidden (view full) ---

1365 TAILQ_FOREACH(rule,
1366 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries)
1367 rule->evaluations = rule->packets =
1368 rule->bytes = 0;
1369 splx(s);
1370 break;
1371 }
1372
1708 old_limit = pf_pool_limits[pl->index].limit;
1709 pf_pool_limits[pl->index].limit = pl->limit;
1710 pl->limit = old_limit;
1711 break;
1712 }
1713
1714 case DIOCSETDEBUG: {
1715 u_int32_t *level = (u_int32_t *)addr;

--- 10 unchanged lines hidden (view full) ---

1726 TAILQ_FOREACH(rule,
1727 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries)
1728 rule->evaluations = rule->packets =
1729 rule->bytes = 0;
1730 splx(s);
1731 break;
1732 }
1733
1734#if defined(__FreeBSD__)
1735 case DIOCGIFSPEED: {
1736 struct pf_ifspeed *psp = (struct pf_ifspeed *)addr;
1737 struct pf_ifspeed ps;
1738 struct ifnet *ifp;
1739
1740 if (psp->ifname[0] != 0) {
1741 /* Can we completely trust user-land? */
1742 strlcpy(ps.ifname, psp->ifname, IFNAMSIZ);
1743 ifp = ifunit(ps.ifname);
1744 if (ifp )
1745 psp->baudrate = ifp->if_baudrate;
1746 else
1747 error = EINVAL;
1748 } else
1749 error = EINVAL;
1750 break;
1751 }
1752#endif /* __FreeBSD__ */
1753
1373#ifdef ALTQ
1374 case DIOCSTARTALTQ: {
1375 struct pf_altq *altq;
1376 struct ifnet *ifp;
1377 struct tb_profile tb;
1378
1379 /* enable all altq interfaces on active list */
1380 s = splsoftnet();

--- 10 unchanged lines hidden (view full) ---

1391 /* set tokenbucket regulator */
1392 tb.rate = altq->ifbandwidth;
1393 tb.depth = altq->tbrsize;
1394 error = tbr_set(&ifp->if_snd, &tb);
1395 if (error != 0)
1396 break;
1397 }
1398 }
1754#ifdef ALTQ
1755 case DIOCSTARTALTQ: {
1756 struct pf_altq *altq;
1757 struct ifnet *ifp;
1758 struct tb_profile tb;
1759
1760 /* enable all altq interfaces on active list */
1761 s = splsoftnet();

--- 10 unchanged lines hidden (view full) ---

1772 /* set tokenbucket regulator */
1773 tb.rate = altq->ifbandwidth;
1774 tb.depth = altq->tbrsize;
1775 error = tbr_set(&ifp->if_snd, &tb);
1776 if (error != 0)
1777 break;
1778 }
1779 }
1780#if defined(__FreeBSD__)
1781 if (error == 0) {
1782 mtx_lock(&pf_altq_mtx);
1783 pfaltq_running = 1;
1784 mtx_unlock(&pf_altq_mtx);
1785 }
1786#else
1399 if (error == 0)
1400 pfaltq_running = 1;
1787 if (error == 0)
1788 pfaltq_running = 1;
1789#endif
1401 splx(s);
1402 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
1403 break;
1404 }
1405
1406 case DIOCSTOPALTQ: {
1407 struct pf_altq *altq;
1408 struct ifnet *ifp;

--- 15 unchanged lines hidden (view full) ---

1424 }
1425 /* clear tokenbucket regulator */
1426 tb.rate = 0;
1427 err = tbr_set(&ifp->if_snd, &tb);
1428 if (err != 0 && error == 0)
1429 error = err;
1430 }
1431 }
1790 splx(s);
1791 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
1792 break;
1793 }
1794
1795 case DIOCSTOPALTQ: {
1796 struct pf_altq *altq;
1797 struct ifnet *ifp;

--- 15 unchanged lines hidden (view full) ---

1813 }
1814 /* clear tokenbucket regulator */
1815 tb.rate = 0;
1816 err = tbr_set(&ifp->if_snd, &tb);
1817 if (err != 0 && error == 0)
1818 error = err;
1819 }
1820 }
1821#if defined(__FreeBSD__)
1822 if (error == 0) {
1823 mtx_lock(&pf_altq_mtx);
1824 pfaltq_running = 0;
1825 mtx_unlock(&pf_altq_mtx);
1826 }
1827#else
1432 if (error == 0)
1433 pfaltq_running = 0;
1828 if (error == 0)
1829 pfaltq_running = 0;
1830#endif
1434 splx(s);
1435 DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
1436 break;
1437 }
1438
1439 case DIOCBEGINALTQS: {
1440 u_int32_t *ticket = (u_int32_t *)addr;
1441 struct pf_altq *altq;
1442
1443 /* Purge the old altq list */
1444 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
1445 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
1446 if (altq->qname[0] == 0) {
1447 /* detach and destroy the discipline */
1831 splx(s);
1832 DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
1833 break;
1834 }
1835
1836 case DIOCBEGINALTQS: {
1837 u_int32_t *ticket = (u_int32_t *)addr;
1838 struct pf_altq *altq;
1839
1840 /* Purge the old altq list */
1841 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
1842 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
1843 if (altq->qname[0] == 0) {
1844 /* detach and destroy the discipline */
1845#if defined(__FreeBSD__)
1846 PF_UNLOCK();
1847#endif
1448 error = altq_remove(altq);
1848 error = altq_remove(altq);
1849#if defined(__FreeBSD__)
1850 PF_LOCK();
1851#endif
1449 }
1450 pool_put(&pf_altq_pl, altq);
1451 }
1452 *ticket = ++ticket_altqs_inactive;
1453 break;
1454 }
1455
1456 case DIOCADDALTQ: {

--- 20 unchanged lines hidden (view full) ---

1477 if (strncmp(a->ifname, altq->ifname,
1478 IFNAMSIZ) == 0 && a->qname[0] == 0) {
1479 altq->altq_disc = a->altq_disc;
1480 break;
1481 }
1482 }
1483 }
1484
1852 }
1853 pool_put(&pf_altq_pl, altq);
1854 }
1855 *ticket = ++ticket_altqs_inactive;
1856 break;
1857 }
1858
1859 case DIOCADDALTQ: {

--- 20 unchanged lines hidden (view full) ---

1880 if (strncmp(a->ifname, altq->ifname,
1881 IFNAMSIZ) == 0 && a->qname[0] == 0) {
1882 altq->altq_disc = a->altq_disc;
1883 break;
1884 }
1885 }
1886 }
1887
1888#if defined(__FreeBSD__)
1889 PF_UNLOCK();
1890#endif
1485 error = altq_add(altq);
1891 error = altq_add(altq);
1892#if defined(__FreeBSD__)
1893 PF_LOCK();
1894#endif
1486 if (error) {
1487 pool_put(&pf_altq_pl, altq);
1488 break;
1489 }
1490
1491 TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
1492 bcopy(altq, &pa->altq, sizeof(struct pf_altq));
1493 break;

--- 18 unchanged lines hidden (view full) ---

1512 pf_altqs_active = pf_altqs_inactive;
1513 pf_altqs_inactive = old_altqs;
1514 ticket_altqs_active = ticket_altqs_inactive;
1515
1516 /* Attach new disciplines */
1517 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1518 if (altq->qname[0] == 0) {
1519 /* attach the discipline */
1895 if (error) {
1896 pool_put(&pf_altq_pl, altq);
1897 break;
1898 }
1899
1900 TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
1901 bcopy(altq, &pa->altq, sizeof(struct pf_altq));
1902 break;

--- 18 unchanged lines hidden (view full) ---

1921 pf_altqs_active = pf_altqs_inactive;
1922 pf_altqs_inactive = old_altqs;
1923 ticket_altqs_active = ticket_altqs_inactive;
1924
1925 /* Attach new disciplines */
1926 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1927 if (altq->qname[0] == 0) {
1928 /* attach the discipline */
1929#if defined(__FreeBSD__)
1930 PF_UNLOCK();
1931#endif
1520 error = altq_pfattach(altq);
1932 error = altq_pfattach(altq);
1933#if defined(__FreeBSD__)
1934 PF_LOCK();
1935#endif
1521 if (error) {
1522 splx(s);
1523 goto fail;
1524 }
1525 }
1526 }
1527
1528 /* Purge the old altq list */
1529 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
1530 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
1531 if (altq->qname[0] == 0) {
1532 /* detach and destroy the discipline */
1936 if (error) {
1937 splx(s);
1938 goto fail;
1939 }
1940 }
1941 }
1942
1943 /* Purge the old altq list */
1944 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
1945 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
1946 if (altq->qname[0] == 0) {
1947 /* detach and destroy the discipline */
1948#if defined(__FreeBSD__)
1949 PF_UNLOCK();
1950#endif
1533 err = altq_pfdetach(altq);
1534 if (err != 0 && error == 0)
1535 error = err;
1536 err = altq_remove(altq);
1537 if (err != 0 && error == 0)
1538 error = err;
1951 err = altq_pfdetach(altq);
1952 if (err != 0 && error == 0)
1953 error = err;
1954 err = altq_remove(altq);
1955 if (err != 0 && error == 0)
1956 error = err;
1957#if defined(__FreeBSD__)
1958 PF_LOCK();
1959#endif
1539 }
1540 pool_put(&pf_altq_pl, altq);
1541 }
1542 splx(s);
1543
1544 /* update queue IDs */
1545 pf_rule_set_qid(
1546 pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);

--- 69 unchanged lines hidden (view full) ---

1616 altq = TAILQ_NEXT(altq, entries);
1617 nr++;
1618 }
1619 if (altq == NULL) {
1620 error = EBUSY;
1621 splx(s);
1622 break;
1623 }
1960 }
1961 pool_put(&pf_altq_pl, altq);
1962 }
1963 splx(s);
1964
1965 /* update queue IDs */
1966 pf_rule_set_qid(
1967 pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);

--- 69 unchanged lines hidden (view full) ---

2037 altq = TAILQ_NEXT(altq, entries);
2038 nr++;
2039 }
2040 if (altq == NULL) {
2041 error = EBUSY;
2042 splx(s);
2043 break;
2044 }
2045#if defined(__FreeBSD__)
2046 PF_UNLOCK();
2047#endif
1624 error = altq_getqstats(altq, pq->buf, &nbytes);
2048 error = altq_getqstats(altq, pq->buf, &nbytes);
2049#if defined(__FreeBSD__)
2050 PF_LOCK();
2051#endif
1625 splx(s);
1626 if (error == 0) {
1627 pq->scheduler = altq->scheduler;
1628 pq->nbytes = nbytes;
1629 }
1630 break;
1631 }
1632#endif /* ALTQ */

--- 515 unchanged lines hidden (view full) ---

2148 break;
2149 }
2150
2151 default:
2152 error = ENODEV;
2153 break;
2154 }
2155fail:
2052 splx(s);
2053 if (error == 0) {
2054 pq->scheduler = altq->scheduler;
2055 pq->nbytes = nbytes;
2056 }
2057 break;
2058 }
2059#endif /* ALTQ */

--- 515 unchanged lines hidden (view full) ---

2575 break;
2576 }
2577
2578 default:
2579 error = ENODEV;
2580 break;
2581 }
2582fail:
2583#if defined(__FreeBSD__)
2584 PF_UNLOCK();
2585#endif
2586 return (error);
2587}
2156
2588
2589#if defined(__FreeBSD__)
2590/*
2591 * XXX - Check for version missmatch!!!
2592 */
2593static int
2594pf_beginrules(void *addr)
2595{
2596 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
2597 struct pf_ruleset *ruleset;
2598 struct pf_rule *rule;
2599 int rs_num;
2600 int error = 0;
2601
2602 do {
2603 ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset);
2604 if (ruleset == NULL) {
2605 error = EINVAL;
2606 break;
2607 }
2608 rs_num = pf_get_ruleset_number(pr->rule.action);
2609 if (rs_num >= PF_RULESET_MAX) {
2610 error = EINVAL;
2611 break;
2612 }
2613 while ((rule =
2614 TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr)) != NULL)
2615 pf_rm_rule(ruleset->rules[rs_num].inactive.ptr, rule);
2616 pr->ticket = ++ruleset->rules[rs_num].inactive.ticket;
2617 } while(0);
2618
2157 return (error);
2158}
2619 return (error);
2620}
2621
2622static int
2623pf_commitrules(void *addr)
2624{
2625 struct pfioc_rule *pr = (struct pfioc_rule *)addr;
2626 struct pf_ruleset *ruleset;
2627 struct pf_rulequeue *old_rules;
2628 struct pf_rule *rule;
2629 int rs_num, s;
2630 int error = 0;
2631
2632 do {
2633 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
2634 if (ruleset == NULL) {
2635 error = EINVAL;
2636 break;
2637 }
2638 rs_num = pf_get_ruleset_number(pr->rule.action);
2639 if (rs_num >= PF_RULESET_MAX) {
2640 error = EINVAL;
2641 break;
2642 }
2643 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
2644 error = EBUSY;
2645 break;
2646 }
2647
2648#ifdef ALTQ
2649 /* set queue IDs */
2650 if (rs_num == PF_RULESET_FILTER)
2651 pf_rule_set_qid(ruleset->rules[rs_num].inactive.ptr);
2652#endif
2653
2654 /* Swap rules, keep the old. */
2655 s = splsoftnet();
2656 old_rules = ruleset->rules[rs_num].active.ptr;
2657 ruleset->rules[rs_num].active.ptr =
2658 ruleset->rules[rs_num].inactive.ptr;
2659 ruleset->rules[rs_num].inactive.ptr = old_rules;
2660 ruleset->rules[rs_num].active.ticket =
2661 ruleset->rules[rs_num].inactive.ticket;
2662 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
2663
2664 /* Purge the old rule list. */
2665 while ((rule = TAILQ_FIRST(old_rules)) != NULL)
2666 pf_rm_rule(old_rules, rule);
2667 pf_remove_if_empty_ruleset(ruleset);
2668 pf_update_anchor_rules();
2669 splx(s);
2670 } while (0);
2671
2672 return (error);
2673}
2674
2675#if defined(ALTQ)
2676static int
2677pf_beginaltqs(void *addr)
2678{
2679 u_int32_t *ticket = (u_int32_t *)addr;
2680 struct pf_altq *altq;
2681 int error = 0;
2682
2683 /* Purge the old altq list */
2684 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
2685 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
2686 if (altq->qname[0] == 0) {
2687#if defined(__FreeBSD__)
2688 PF_UNLOCK();
2689#endif
2690 /* detach and destroy the discipline */
2691 error = altq_remove(altq);
2692#if defined(__FreeBSD__)
2693 PF_LOCK();
2694#endif
2695 }
2696 uma_zfree(pf_altq_pl, altq);
2697 }
2698 *ticket = ++ticket_altqs_inactive;
2699
2700 return (error);
2701}
2702
2703static int
2704pf_commitaltqs(void *addr)
2705{
2706 u_int32_t *ticket = (u_int32_t *)addr;
2707 struct pf_altqqueue *old_altqs;
2708 struct pf_altq *altq;
2709 struct pf_anchor *anchor;
2710 struct pf_ruleset *ruleset;
2711 int err;
2712 int s;
2713 int error = 0;
2714
2715 do {
2716 if (*ticket != ticket_altqs_inactive) {
2717 error = EBUSY;
2718 break;
2719 }
2720
2721 /* Swap altqs, keep the old. */
2722 s = splsoftnet();
2723 old_altqs = pf_altqs_active;
2724 pf_altqs_active = pf_altqs_inactive;
2725 pf_altqs_inactive = old_altqs;
2726 ticket_altqs_active = ticket_altqs_inactive;
2727
2728 /* Attach new disciplines */
2729 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
2730 if (altq->qname[0] == 0) {
2731 /* attach the discipline */
2732#if defined(__FreeBSD__)
2733 PF_UNLOCK();
2734#endif
2735 error = altq_pfattach(altq);
2736#if defined(__FreeBSD__)
2737 PF_LOCK();
2738#endif
2739 if (error) {
2740 splx(s);
2741 goto altq_fail;
2742 }
2743 }
2744 }
2745
2746 /* Purge the old altq list */
2747 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
2748 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
2749 if (altq->qname[0] == 0) {
2750 /* detach and destroy the discipline */
2751#if defined(__FreeBSD__)
2752 PF_UNLOCK();
2753#endif
2754 err = altq_pfdetach(altq);
2755 if (err != 0 && error == 0)
2756 error = err;
2757 err = altq_remove(altq);
2758 if (err != 0 && error == 0)
2759 error = err;
2760#if defined(__FreeBSD__)
2761 PF_LOCK();
2762#endif
2763 }
2764 uma_zfree(pf_altq_pl, altq);
2765 }
2766 splx(s);
2767
2768 /* update queue IDs */
2769 pf_rule_set_qid(
2770 pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
2771 TAILQ_FOREACH(anchor, &pf_anchors, entries) {
2772 TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) {
2773 pf_rule_set_qid(
2774 ruleset->rules[PF_RULESET_FILTER].active.ptr
2775 );
2776 }
2777 }
2778 } while (0);
2779
2780altq_fail:
2781
2782 return (error);
2783}
2784
2785static int
2786pf_stopaltq(void)
2787{
2788 struct pf_altq *altq;
2789 struct ifnet *ifp;
2790 struct tb_profile tb;
2791 int err;
2792 int s;
2793 int error = 0;
2794
2795 do {
2796 /* disable all altq interfaces on active list */
2797 s = splsoftnet();
2798 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
2799 if (altq->qname[0] == 0) {
2800 if ((ifp = ifunit(altq->ifname)) == NULL) {
2801 error = EINVAL;
2802 break;
2803 }
2804 if (ifp->if_snd.altq_type != ALTQT_NONE) {
2805 err = altq_disable(&ifp->if_snd);
2806 if (err != 0 && error == 0)
2807 error = err;
2808 }
2809 /* clear tokenbucket regulator */
2810 tb.rate = 0;
2811 err = tbr_set(&ifp->if_snd, &tb);
2812 if (err != 0 && error == 0)
2813 error = err;
2814 }
2815 }
2816#if defined(__FreeBSD__)
2817 if (error == 0) {
2818 mtx_lock(&pf_altq_mtx);
2819 pfaltq_running = 0;
2820 mtx_unlock(&pf_altq_mtx);
2821 }
2822#else
2823 if (error == 0)
2824 pfaltq_running = 0;
2825#endif
2826 splx(s);
2827 } while (0);
2828
2829 return (error);
2830}
2831#endif
2832
2833static void
2834pf_clearstates(void)
2835{
2836 struct pf_tree_node *n;
2837 int s;
2838
2839 s = splsoftnet();
2840 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
2841 n->state->timeout = PFTM_PURGE;
2842 pf_purge_expired_states();
2843 pf_status.states = 0;
2844 splx(s);
2845}
2846
2847static int
2848pf_clear_tables(void *addr)
2849{
2850 struct pfioc_table *io = (struct pfioc_table *)addr;
2851 int error;
2852
2853 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
2854 io->pfrio_flags);
2855
2856 return (error);
2857}
2858
2859static int
2860shutdown_pf(void)
2861{
2862 struct pfioc_rule pr;
2863#if defined(ALTQ)
2864 struct pfioc_altq pa;
2865#endif
2866 struct pfioc_table io;
2867 int error = 0;
2868
2869 callout_stop(&pf_expire_to);
2870
2871 PF_LOCK();
2872 pf_status.running = 0;
2873 do {
2874#if defined(ALTQ)
2875 if ((error = pf_stopaltq())) {
2876 DPFPRINTF(PF_DEBUG_MISC,
2877 ("ALTQ: stop(%i)\n", error));
2878 break;
2879 }
2880#endif
2881 bzero(&pr, sizeof(pr));
2882 pr.rule.action = PF_SCRUB;
2883 if ((error = pf_beginrules(&pr))) {
2884 DPFPRINTF(PF_DEBUG_MISC,
2885 ("PF_SCRUB: begin(%i)\n", error));
2886 break;
2887 }
2888 if ((error = pf_commitrules(&pr))) {
2889 DPFPRINTF(PF_DEBUG_MISC,
2890 ("PF_SCRUB: commit(%i)\n", error));
2891 break;
2892 }
2893
2894 pr.rule.action = PF_PASS;
2895 if ((error = pf_beginrules(&pr))) {
2896 DPFPRINTF(PF_DEBUG_MISC,
2897 ("PF_PASS: begin(%i)\n", error));
2898 break;
2899 }
2900 if ((error = pf_commitrules(&pr))) {
2901 DPFPRINTF(PF_DEBUG_MISC,
2902 ("PF_PASS: commit(%i)\n", error));
2903 break;
2904 }
2905
2906/*
2907 * XXX not sure, but can't hurt:
2908 */
2909 bzero(&pr, sizeof(pr));
2910 pr.rule.action = PF_NAT;
2911 if ((error = pf_beginrules(&pr))) {
2912 DPFPRINTF(PF_DEBUG_MISC,
2913 ("PF_NAT: begin(%i)\n", error));
2914 break;
2915 }
2916 if ((error = pf_commitrules(&pr))) {
2917 DPFPRINTF(PF_DEBUG_MISC,
2918 ("PF_NAT: commit(%i)\n", error));
2919 break;
2920 }
2921
2922 pr.rule.action = PF_BINAT;
2923 if ((error = pf_beginrules(&pr))) {
2924 DPFPRINTF(PF_DEBUG_MISC,
2925 ("PF_BINAT: begin(%i)\n", error));
2926 break;
2927 }
2928 if ((error = pf_commitrules(&pr))) {
2929 DPFPRINTF(PF_DEBUG_MISC,
2930 ("PF_BINAT: begin(%i)\n", error));
2931 break;
2932 }
2933
2934 pr.rule.action = PF_RDR;
2935 if ((error = pf_beginrules(&pr))) {
2936 DPFPRINTF(PF_DEBUG_MISC,
2937 ("PF_RDR: begin(%i)\n", error));
2938 break;
2939 }
2940 if ((error = pf_commitrules(&pr))) {
2941 DPFPRINTF(PF_DEBUG_MISC,
2942 ("PF_RDR: commit(%i)\n", error));
2943 break;
2944 }
2945
2946#if defined(ALTQ)
2947 bzero(&pa, sizeof(pa));
2948 if ((error = pf_beginaltqs(&pa))) {
2949 DPFPRINTF(PF_DEBUG_MISC,
2950 ("ALTQ: begin(%i)\n", error));
2951 break;
2952 }
2953 if ((error = pf_commitaltqs(&pa))) {
2954 DPFPRINTF(PF_DEBUG_MISC,
2955 ("ALTQ: commit(%i)\n", error));
2956 break;
2957 }
2958#endif
2959 pf_clearstates();
2960
2961 bzero(&io, sizeof(io));
2962 if ((error = pf_clear_tables(&io))) {
2963 DPFPRINTF(PF_DEBUG_MISC,
2964 ("TABLES: clear(%i)\n", error));
2965 break;
2966 }
2967 pf_osfp_flush();
2968 } while(0);
2969
2970 PF_UNLOCK();
2971 return (error);
2972}
2973
2974static int
2975#if (__FreeBSD_version < 501108)
2976pf_check_in(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
2977#else
2978pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
2979#endif
2980{
2981 /*
2982 * XXX Wed Jul 9 22:03:16 2003 UTC
2983 * OpenBSD has changed its byte ordering convention on ip_len/ip_off
2984 * in network stack. OpenBSD's network stack have converted
2985 * ip_len/ip_off to host byte order frist as FreeBSD.
2986 * Now this is not true anymore , so we should convert back to network
2987 * byte order.
2988 */
2989 struct ip *h = NULL;
2990 int chk;
2991
2992 if ((*m)->m_pkthdr.len >= (int)sizeof(struct ip)) {
2993 /* if m_pkthdr.len is less than ip header, pf will handle. */
2994 h = mtod(*m, struct ip *);
2995 HTONS(h->ip_len);
2996 HTONS(h->ip_off);
2997 }
2998 chk = pf_test(PF_IN, ifp, m);
2999 if (chk && *m) {
3000 m_freem(*m);
3001 *m = NULL;
3002 }
3003 if (*m != NULL) {
3004 /* pf_test can change ip header location */
3005 h = mtod(*m, struct ip *);
3006 NTOHS(h->ip_len);
3007 NTOHS(h->ip_off);
3008 }
3009 return chk;
3010}
3011
3012static int
3013#if (__FreeBSD_version < 501108)
3014pf_check_out(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
3015#else
3016pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
3017#endif
3018{
3019 /*
3020 * XXX Wed Jul 9 22:03:16 2003 UTC
3021 * OpenBSD has changed its byte ordering convention on ip_len/ip_off
3022 * in network stack. OpenBSD's network stack have converted
3023 * ip_len/ip_off to host byte order frist as FreeBSD.
3024 * Now this is not true anymore , so we should convert back to network
3025 * byte order.
3026 */
3027 struct ip *h = NULL;
3028 int chk;
3029
3030 /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
3031 if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
3032 in_delayed_cksum(*m);
3033 (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
3034 }
3035 if ((*m)->m_pkthdr.len >= (int)sizeof(*h)) {
3036 /* if m_pkthdr.len is less than ip header, pf will handle. */
3037 h = mtod(*m, struct ip *);
3038 HTONS(h->ip_len);
3039 HTONS(h->ip_off);
3040 }
3041 chk = pf_test(PF_OUT, ifp, m);
3042 if (chk && *m) {
3043 m_freem(*m);
3044 *m = NULL;
3045 }
3046 if (*m != NULL) {
3047 /* pf_test can change ip header location */
3048 h = mtod(*m, struct ip *);
3049 NTOHS(h->ip_len);
3050 NTOHS(h->ip_off);
3051 }
3052 return chk;
3053}
3054
3055#ifdef INET6
3056static int
3057#if (__FreeBSD_version < 501108)
3058pf_check6_in(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
3059#else
3060pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
3061#endif
3062{
3063 /*
3064 * IPv6 does not affected ip_len/ip_off byte order changes.
3065 */
3066 int chk;
3067
3068 chk = pf_test6(PF_IN, ifp, m);
3069 if (chk && *m) {
3070 m_freem(*m);
3071 *m = NULL;
3072 }
3073 return chk;
3074}
3075
3076static int
3077#if (__FreeBSD_version < 501108)
3078pf_check6_out(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
3079#else
3080pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
3081#endif
3082{
3083 /*
3084 * IPv6 does not affected ip_len/ip_off byte order changes.
3085 */
3086 int chk;
3087
3088 /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
3089 if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
3090 in_delayed_cksum(*m);
3091 (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
3092 }
3093 chk = pf_test6(PF_OUT, ifp, m);
3094 if (chk && *m) {
3095 m_freem(*m);
3096 *m = NULL;
3097 }
3098 return chk;
3099}
3100#endif /* INET6 */
3101
3102static int
3103hook_pf(void)
3104{
3105#if (__FreeBSD_version >= 501108)
3106 struct pfil_head *pfh_inet;
3107#if defined(INET6)
3108 struct pfil_head *pfh_inet6;
3109#endif
3110#endif
3111
3112 PF_ASSERT(MA_NOTOWNED);
3113
3114 if (pf_pfil_hooked)
3115 return (0);
3116
3117#if (__FreeBSD_version < 501108)
3118 /*
3119 * XXX
3120 * There is no easy way to get pfil header pointer with address
3121 * family such as AF_INET, AF_INET6.
3122 * Needs direct variable reference.
3123 */
3124
3125 pfil_add_hook(pf_check_in, PFIL_IN,
3126 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
3127 pfil_add_hook(pf_check_out, PFIL_OUT,
3128 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
3129#if defined(INET6)
3130 pfil_add_hook(pf_check6_in, PFIL_IN,
3131 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
3132 pfil_add_hook(pf_check6_out, PFIL_OUT,
3133 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
3134#endif
3135#else /* __FreeBSD_version >= 501108 */
3136 pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
3137 if (pfh_inet == NULL)
3138 return (ESRCH); /* XXX */
3139 pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
3140 pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
3141#if defined(INET6)
3142 pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
3143 if (pfh_inet6 == NULL) {
3144 pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
3145 pfh_inet);
3146 pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
3147 pfh_inet);
3148 return (ESRCH); /* XXX */
3149 }
3150 pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
3151 pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
3152#endif
3153#endif /* __FreeBSD_version >= 501108 */
3154
3155 pf_pfil_hooked = 1;
3156 return (0);
3157}
3158
3159static int
3160dehook_pf(void)
3161{
3162#if (__FreeBSD_version >= 501108)
3163 struct pfil_head *pfh_inet;
3164#if defined(INET6)
3165 struct pfil_head *pfh_inet6;
3166#endif
3167#endif
3168
3169 PF_ASSERT(MA_NOTOWNED);
3170
3171 if (pf_pfil_hooked == 0)
3172 return (0);
3173
3174#if (__FreeBSD_version < 501108)
3175 pfil_remove_hook(pf_check_in, PFIL_IN,
3176 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
3177 pfil_remove_hook(pf_check_out, PFIL_OUT,
3178 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
3179#if defined(INET6)
3180 pfil_remove_hook(pf_check6_in, PFIL_IN,
3181 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
3182 pfil_remove_hook(pf_check6_out, PFIL_OUT,
3183 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
3184#endif
3185#else /* __FreeBSD_version >= 501108 */
3186 pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
3187 if (pfh_inet == NULL)
3188 return (ESRCH); /* XXX */
3189 pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
3190 pfh_inet);
3191 pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
3192 pfh_inet);
3193#if defined(INET6)
3194 pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
3195 if (pfh_inet6 == NULL)
3196 return (ESRCH); /* XXX */
3197 pfil_remove_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK,
3198 pfh_inet6);
3199 pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK,
3200 pfh_inet6);
3201#endif
3202#endif /* __FreeBSD_version >= 501108 */
3203
3204 pf_pfil_hooked = 0;
3205 return (0);
3206}
3207
3208static int
3209pf_load(void)
3210{
3211 init_zone_var();
3212 init_pf_mutex();
3213 pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME);
3214 if (pfattach() < 0) {
3215 destroy_dev(pf_dev);
3216 destroy_pf_mutex();
3217 return (ENOMEM);
3218 }
3219#if defined(ALTQ)
3220 mtx_lock(&pf_altq_mtx);
3221 ++pfaltq_ref;
3222 mtx_unlock(&pf_altq_mtx);
3223#endif
3224 printf("pf: $Name: $\n");
3225 return (0);
3226}
3227
3228static int
3229pf_unload(void)
3230{
3231 int error = 0;
3232
3233 PF_LOCK();
3234 pf_status.running = 0;
3235 PF_UNLOCK();
3236 error = dehook_pf();
3237 if (error) {
3238 /*
3239 * Should not happen!
3240 * XXX Due to error code ESRCH, kldunload will show
3241 * a message like 'No such process'.
3242 */
3243 printf("%s : pfil unregisteration fail\n", __FUNCTION__);
3244 return error;
3245 }
3246 shutdown_pf();
3247 cleanup_pf_zone();
3248 pf_osfp_cleanup();
3249 destroy_dev(pf_dev);
3250#if defined(ALTQ)
3251 mtx_lock(&pf_altq_mtx);
3252 --pfaltq_ref;
3253 mtx_unlock(&pf_altq_mtx);
3254#endif
3255 destroy_pf_mutex();
3256 return error;
3257}
3258
3259static int
3260pf_modevent(module_t mod, int type, void *data)
3261{
3262 int error = 0;
3263
3264 switch(type) {
3265 case MOD_LOAD:
3266 error = pf_load();
3267 break;
3268
3269 case MOD_UNLOAD:
3270 error = pf_unload();
3271 break;
3272 default:
3273 error = EINVAL;
3274 break;
3275 }
3276 return error;
3277}
3278
3279static moduledata_t pf_mod = {
3280 "pf",
3281 pf_modevent,
3282 0
3283};
3284
3285DECLARE_MODULE(pf, pf_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
3286MODULE_DEPEND(pf, pflog, PFLOG_MINVER, PFLOG_PREFVER, PFLOG_MAXVER);
3287MODULE_DEPEND(pf, pfsync, PFSYNC_MINVER, PFSYNC_PREFVER, PFSYNC_MAXVER);
3288#if defined(ALTQ)
3289MODULE_DEPEND(pf, pfaltq, PFALTQ_MINVER, PFALTQ_PREFVER, PFALTQ_MAXVER);
3290#endif
3291MODULE_VERSION(pf, PF_MODVER);
3292#endif /* __FreeBSD__ */