| 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 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 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 10 * are met: 11 * 12 * - Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * - Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 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); 101 pool_init(&pf_addr_pl, sizeof(struct pf_addr_dyn), 0, 0, 0, "pfaddrpl", 102 &pool_allocator_nointr); 103 pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl", 104 NULL); 105 pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl", 106 NULL); 107 pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0, 108 "pfpooladdrpl", NULL); 109 pfr_initialize(); 110 pf_osfp_initialize(); 111 112 pool_sethardlimit(&pf_state_pl, pf_pool_limits[PF_LIMIT_STATES].limit, 113 NULL, 0); 114 115 RB_INIT(&tree_lan_ext); 116 RB_INIT(&tree_ext_gwy); 117 TAILQ_INIT(&pf_anchors); 118 pf_init_ruleset(&pf_main_ruleset); 119 TAILQ_INIT(&pf_altqs[0]); 120 TAILQ_INIT(&pf_altqs[1]); 121 TAILQ_INIT(&pf_pabuf); 122 pf_altqs_active = &pf_altqs[0]; 123 pf_altqs_inactive = &pf_altqs[1]; 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); 383 pool_init(&pf_addr_pl, sizeof(struct pf_addr_dyn), 0, 0, 0, "pfaddrpl", 384 &pool_allocator_nointr); 385 pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl", 386 NULL); 387 pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl", 388 NULL); 389 pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0, 390 "pfpooladdrpl", NULL); 391 pfr_initialize(); 392 pf_osfp_initialize(); 393 394 pool_sethardlimit(&pf_state_pl, pf_pool_limits[PF_LIMIT_STATES].limit, 395 NULL, 0); 396 397 RB_INIT(&tree_lan_ext); 398 RB_INIT(&tree_ext_gwy); 399 TAILQ_INIT(&pf_anchors); 400 pf_init_ruleset(&pf_main_ruleset); 401 TAILQ_INIT(&pf_altqs[0]); 402 TAILQ_INIT(&pf_altqs[1]); 403 TAILQ_INIT(&pf_pabuf); 404 pf_altqs_active = &pf_altqs[0]; 405 pf_altqs_inactive = &pf_altqs[1]; 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 */ 141 timeout[PFTM_ICMP_ERROR_REPLY] = 10; /* Got error response */ 142 timeout[PFTM_OTHER_FIRST_PACKET] = 60; /* First packet */ 143 timeout[PFTM_OTHER_SINGLE] = 30; /* Unidirectional */ 144 timeout[PFTM_OTHER_MULTIPLE] = 60; /* Bidirectional */ 145 timeout[PFTM_FRAG] = 30; /* Fragment expire */ 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 */ 423 timeout[PFTM_ICMP_ERROR_REPLY] = 10; /* Got error response */ 424 timeout[PFTM_OTHER_FIRST_PACKET] = 60; /* First packet */ 425 timeout[PFTM_OTHER_SINGLE] = 30; /* Unidirectional */ 426 timeout[PFTM_OTHER_MULTIPLE] = 60; /* Bidirectional */ 427 timeout[PFTM_FRAG] = 30; /* Fragment expire */ 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; 178 int rs_num; 179 180 ruleset = pf_find_ruleset(anchorname, rulesetname); 181 if (ruleset == NULL) 182 return (NULL); 183 rs_num = pf_get_ruleset_number(rule_action); 184 if (rs_num >= PF_RULESET_MAX) 185 return (NULL); 186 if (active) { 187 if (check_ticket && ticket != 188 ruleset->rules[rs_num].active.ticket) 189 return (NULL); 190 if (r_last) 191 rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, 192 pf_rulequeue); 193 else 194 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); 195 } else { 196 if (check_ticket && ticket != 197 ruleset->rules[rs_num].inactive.ticket) 198 return (NULL); 199 if (r_last) 200 rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, 201 pf_rulequeue); 202 else 203 rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr); 204 } 205 if (!r_last) { 206 while ((rule != NULL) && (rule->nr != rule_number)) 207 rule = TAILQ_NEXT(rule, entries); 208 } 209 if (rule == NULL) 210 return (NULL); 211 212 return (&rule->rpool); 213} 214 215int 216pf_get_ruleset_number(u_int8_t action) 217{ 218 switch (action) { 219 case PF_SCRUB: 220 return (PF_RULESET_SCRUB); 221 break; 222 case PF_PASS: 223 case PF_DROP: 224 return (PF_RULESET_FILTER); 225 break; 226 case PF_NAT: 227 case PF_NONAT: 228 return (PF_RULESET_NAT); 229 break; 230 case PF_BINAT: 231 case PF_NOBINAT: 232 return (PF_RULESET_BINAT); 233 break; 234 case PF_RDR: 235 case PF_NORDR: 236 return (PF_RULESET_RDR); 237 break; 238 default: 239 return (PF_RULESET_MAX); 240 break; 241 } 242} 243 244void 245pf_init_ruleset(struct pf_ruleset *ruleset) 246{ 247 int i; 248 249 memset(ruleset, 0, sizeof(struct pf_ruleset)); 250 for (i = 0; i < PF_RULESET_MAX; i++) { 251 TAILQ_INIT(&ruleset->rules[i].queues[0]); 252 TAILQ_INIT(&ruleset->rules[i].queues[1]); 253 ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0]; 254 ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1]; 255 } 256} 257 258struct pf_anchor * 259pf_find_anchor(const char *anchorname) 260{ 261 struct pf_anchor *anchor; 262 int n = -1; 263 264 anchor = TAILQ_FIRST(&pf_anchors); 265 while (anchor != NULL && (n = strcmp(anchor->name, anchorname)) < 0) 266 anchor = TAILQ_NEXT(anchor, entries); 267 if (n == 0) 268 return (anchor); 269 else 270 return (NULL); 271} 272 273struct pf_ruleset * 274pf_find_ruleset(char *anchorname, char *rulesetname) 275{ 276 struct pf_anchor *anchor; 277 struct pf_ruleset *ruleset; 278 279 if (!anchorname[0] && !rulesetname[0]) 280 return (&pf_main_ruleset); 281 if (!anchorname[0] || !rulesetname[0]) 282 return (NULL); 283 anchorname[PF_ANCHOR_NAME_SIZE-1] = 0; 284 rulesetname[PF_RULESET_NAME_SIZE-1] = 0; 285 anchor = pf_find_anchor(anchorname); 286 if (anchor == NULL) 287 return (NULL); 288 ruleset = TAILQ_FIRST(&anchor->rulesets); 289 while (ruleset != NULL && strcmp(ruleset->name, rulesetname) < 0) 290 ruleset = TAILQ_NEXT(ruleset, entries); 291 if (ruleset != NULL && !strcmp(ruleset->name, rulesetname)) 292 return (ruleset); 293 else 294 return (NULL); 295} 296 297struct pf_ruleset * 298pf_find_or_create_ruleset(char *anchorname, char *rulesetname) 299{ 300 struct pf_anchor *anchor, *a; 301 struct pf_ruleset *ruleset, *r; 302 303 if (!anchorname[0] && !rulesetname[0]) 304 return (&pf_main_ruleset); 305 if (!anchorname[0] || !rulesetname[0]) 306 return (NULL); 307 anchorname[PF_ANCHOR_NAME_SIZE-1] = 0; 308 rulesetname[PF_RULESET_NAME_SIZE-1] = 0; 309 a = TAILQ_FIRST(&pf_anchors); 310 while (a != NULL && strcmp(a->name, anchorname) < 0) 311 a = TAILQ_NEXT(a, entries); 312 if (a != NULL && !strcmp(a->name, anchorname)) 313 anchor = a; 314 else { 315 anchor = (struct pf_anchor *)malloc(sizeof(struct pf_anchor), 316 M_TEMP, M_NOWAIT); 317 if (anchor == NULL) 318 return (NULL); 319 memset(anchor, 0, sizeof(struct pf_anchor)); 320 bcopy(anchorname, anchor->name, sizeof(anchor->name)); 321 TAILQ_INIT(&anchor->rulesets); 322 if (a != NULL) 323 TAILQ_INSERT_BEFORE(a, anchor, entries); 324 else 325 TAILQ_INSERT_TAIL(&pf_anchors, anchor, entries); 326 } 327 r = TAILQ_FIRST(&anchor->rulesets); 328 while (r != NULL && strcmp(r->name, rulesetname) < 0) 329 r = TAILQ_NEXT(r, entries); 330 if (r != NULL && !strcmp(r->name, rulesetname)) 331 return (r); 332 ruleset = (struct pf_ruleset *)malloc(sizeof(struct pf_ruleset), 333 M_TEMP, M_NOWAIT); 334 if (ruleset != NULL) { 335 pf_init_ruleset(ruleset); 336 bcopy(rulesetname, ruleset->name, sizeof(ruleset->name)); 337 ruleset->anchor = anchor; 338 if (r != NULL) 339 TAILQ_INSERT_BEFORE(r, ruleset, entries); 340 else 341 TAILQ_INSERT_TAIL(&anchor->rulesets, ruleset, entries); 342 } 343 return (ruleset); 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; 465 int rs_num; 466 467 ruleset = pf_find_ruleset(anchorname, rulesetname); 468 if (ruleset == NULL) 469 return (NULL); 470 rs_num = pf_get_ruleset_number(rule_action); 471 if (rs_num >= PF_RULESET_MAX) 472 return (NULL); 473 if (active) { 474 if (check_ticket && ticket != 475 ruleset->rules[rs_num].active.ticket) 476 return (NULL); 477 if (r_last) 478 rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, 479 pf_rulequeue); 480 else 481 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); 482 } else { 483 if (check_ticket && ticket != 484 ruleset->rules[rs_num].inactive.ticket) 485 return (NULL); 486 if (r_last) 487 rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, 488 pf_rulequeue); 489 else 490 rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr); 491 } 492 if (!r_last) { 493 while ((rule != NULL) && (rule->nr != rule_number)) 494 rule = TAILQ_NEXT(rule, entries); 495 } 496 if (rule == NULL) 497 return (NULL); 498 499 return (&rule->rpool); 500} 501 502int 503pf_get_ruleset_number(u_int8_t action) 504{ 505 switch (action) { 506 case PF_SCRUB: 507 return (PF_RULESET_SCRUB); 508 break; 509 case PF_PASS: 510 case PF_DROP: 511 return (PF_RULESET_FILTER); 512 break; 513 case PF_NAT: 514 case PF_NONAT: 515 return (PF_RULESET_NAT); 516 break; 517 case PF_BINAT: 518 case PF_NOBINAT: 519 return (PF_RULESET_BINAT); 520 break; 521 case PF_RDR: 522 case PF_NORDR: 523 return (PF_RULESET_RDR); 524 break; 525 default: 526 return (PF_RULESET_MAX); 527 break; 528 } 529} 530 531void 532pf_init_ruleset(struct pf_ruleset *ruleset) 533{ 534 int i; 535 536 memset(ruleset, 0, sizeof(struct pf_ruleset)); 537 for (i = 0; i < PF_RULESET_MAX; i++) { 538 TAILQ_INIT(&ruleset->rules[i].queues[0]); 539 TAILQ_INIT(&ruleset->rules[i].queues[1]); 540 ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0]; 541 ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1]; 542 } 543} 544 545struct pf_anchor * 546pf_find_anchor(const char *anchorname) 547{ 548 struct pf_anchor *anchor; 549 int n = -1; 550 551 anchor = TAILQ_FIRST(&pf_anchors); 552 while (anchor != NULL && (n = strcmp(anchor->name, anchorname)) < 0) 553 anchor = TAILQ_NEXT(anchor, entries); 554 if (n == 0) 555 return (anchor); 556 else 557 return (NULL); 558} 559 560struct pf_ruleset * 561pf_find_ruleset(char *anchorname, char *rulesetname) 562{ 563 struct pf_anchor *anchor; 564 struct pf_ruleset *ruleset; 565 566 if (!anchorname[0] && !rulesetname[0]) 567 return (&pf_main_ruleset); 568 if (!anchorname[0] || !rulesetname[0]) 569 return (NULL); 570 anchorname[PF_ANCHOR_NAME_SIZE-1] = 0; 571 rulesetname[PF_RULESET_NAME_SIZE-1] = 0; 572 anchor = pf_find_anchor(anchorname); 573 if (anchor == NULL) 574 return (NULL); 575 ruleset = TAILQ_FIRST(&anchor->rulesets); 576 while (ruleset != NULL && strcmp(ruleset->name, rulesetname) < 0) 577 ruleset = TAILQ_NEXT(ruleset, entries); 578 if (ruleset != NULL && !strcmp(ruleset->name, rulesetname)) 579 return (ruleset); 580 else 581 return (NULL); 582} 583 584struct pf_ruleset * 585pf_find_or_create_ruleset(char *anchorname, char *rulesetname) 586{ 587 struct pf_anchor *anchor, *a; 588 struct pf_ruleset *ruleset, *r; 589 590 if (!anchorname[0] && !rulesetname[0]) 591 return (&pf_main_ruleset); 592 if (!anchorname[0] || !rulesetname[0]) 593 return (NULL); 594 anchorname[PF_ANCHOR_NAME_SIZE-1] = 0; 595 rulesetname[PF_RULESET_NAME_SIZE-1] = 0; 596 a = TAILQ_FIRST(&pf_anchors); 597 while (a != NULL && strcmp(a->name, anchorname) < 0) 598 a = TAILQ_NEXT(a, entries); 599 if (a != NULL && !strcmp(a->name, anchorname)) 600 anchor = a; 601 else { 602 anchor = (struct pf_anchor *)malloc(sizeof(struct pf_anchor), 603 M_TEMP, M_NOWAIT); 604 if (anchor == NULL) 605 return (NULL); 606 memset(anchor, 0, sizeof(struct pf_anchor)); 607 bcopy(anchorname, anchor->name, sizeof(anchor->name)); 608 TAILQ_INIT(&anchor->rulesets); 609 if (a != NULL) 610 TAILQ_INSERT_BEFORE(a, anchor, entries); 611 else 612 TAILQ_INSERT_TAIL(&pf_anchors, anchor, entries); 613 } 614 r = TAILQ_FIRST(&anchor->rulesets); 615 while (r != NULL && strcmp(r->name, rulesetname) < 0) 616 r = TAILQ_NEXT(r, entries); 617 if (r != NULL && !strcmp(r->name, rulesetname)) 618 return (r); 619 ruleset = (struct pf_ruleset *)malloc(sizeof(struct pf_ruleset), 620 M_TEMP, M_NOWAIT); 621 if (ruleset != NULL) { 622 pf_init_ruleset(ruleset); 623 bcopy(rulesetname, ruleset->name, sizeof(ruleset->name)); 624 ruleset->anchor = anchor; 625 if (r != NULL) 626 TAILQ_INSERT_BEFORE(r, ruleset, entries); 627 else 628 TAILQ_INSERT_TAIL(&anchor->rulesets, ruleset, entries); 629 } 630 return (ruleset); 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); 361 free(ruleset, M_TEMP); 362 363 if (TAILQ_EMPTY(&anchor->rulesets)) { 364 TAILQ_REMOVE(&pf_anchors, anchor, entries); 365 free(anchor, M_TEMP); 366 } 367} 368 369void 370pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb) 371{ 372 struct pf_pooladdr *mv_pool_pa; 373 374 while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) { 375 TAILQ_REMOVE(poola, mv_pool_pa, entries); 376 TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries); 377 } 378} 379 380void 381pf_empty_pool(struct pf_palist *poola) 382{ 383 struct pf_pooladdr *empty_pool_pa; 384 385 while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) { 386 pf_dynaddr_remove(&empty_pool_pa->addr); 387 pf_tbladdr_remove(&empty_pool_pa->addr); 388 TAILQ_REMOVE(poola, empty_pool_pa, entries); 389 pool_put(&pf_pooladdr_pl, empty_pool_pa); 390 } 391} 392 393void 394pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) 395{ 396 if (rulequeue != NULL) { 397 if (rule->states <= 0) { 398 /* 399 * XXX - we need to remove the table *before* detaching 400 * the rule to make sure the table code does not delete 401 * the anchor under our feet. 402 */ 403 pf_tbladdr_remove(&rule->src.addr); 404 pf_tbladdr_remove(&rule->dst.addr); 405 } 406 TAILQ_REMOVE(rulequeue, rule, entries); 407 rule->entries.tqe_prev = NULL; 408 rule->nr = -1; 409 } 410 if (rule->states > 0 || rule->entries.tqe_prev != NULL) 411 return; 412 pf_tag_unref(rule->tag); 413 pf_tag_unref(rule->match_tag); 414 pf_dynaddr_remove(&rule->src.addr); 415 pf_dynaddr_remove(&rule->dst.addr); 416 if (rulequeue == NULL) { 417 pf_tbladdr_remove(&rule->src.addr); 418 pf_tbladdr_remove(&rule->dst.addr); 419 } 420 pf_empty_pool(&rule->rpool.list); 421 pool_put(&pf_rule_pl, rule); 422} 423 424u_int16_t 425pf_tagname2tag(char *tagname) 426{ 427 struct pf_tagname *tag, *p = NULL; 428 u_int16_t new_tagid = 1; 429 430 TAILQ_FOREACH(tag, &pf_tags, entries) 431 if (strcmp(tagname, tag->name) == 0) { 432 tag->ref++; 433 return (tag->tag); 434 } 435 436 /* 437 * to avoid fragmentation, we do a linear search from the beginning 438 * and take the first free slot we find. if there is none or the list 439 * is empty, append a new entry at the end. 440 */ 441 442 /* new entry */ 443 if (!TAILQ_EMPTY(&pf_tags)) 444 for (p = TAILQ_FIRST(&pf_tags); p != NULL && 445 p->tag == new_tagid; p = TAILQ_NEXT(p, entries)) 446 new_tagid = p->tag + 1; 447 448 if (new_tagid > TAGID_MAX) 449 return (0); 450 451 /* allocate and fill new struct pf_tagname */ 452 tag = (struct pf_tagname *)malloc(sizeof(struct pf_tagname), 453 M_TEMP, M_NOWAIT); 454 if (tag == NULL) 455 return (0); 456 bzero(tag, sizeof(struct pf_tagname)); 457 strlcpy(tag->name, tagname, sizeof(tag->name)); 458 tag->tag = new_tagid; 459 tag->ref++; 460 461 if (p != NULL) /* insert new entry before p */ 462 TAILQ_INSERT_BEFORE(p, tag, entries); 463 else /* either list empty or no free slot in between */ 464 TAILQ_INSERT_TAIL(&pf_tags, tag, entries); 465 466 return (tag->tag); 467} 468 469void 470pf_tag2tagname(u_int16_t tagid, char *p) 471{ 472 struct pf_tagname *tag; 473 474 TAILQ_FOREACH(tag, &pf_tags, entries) 475 if (tag->tag == tagid) { 476 strlcpy(p, tag->name, PF_TAG_NAME_SIZE); 477 return; 478 } 479} 480 481void 482pf_tag_unref(u_int16_t tag) 483{ 484 struct pf_tagname *p, *next; 485 486 if (tag == 0) 487 return; 488 489 for (p = TAILQ_FIRST(&pf_tags); p != NULL; p = next) { 490 next = TAILQ_NEXT(p, entries); 491 if (tag == p->tag) { 492 if (--p->ref == 0) { 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); 649 free(ruleset, M_TEMP); 650 651 if (TAILQ_EMPTY(&anchor->rulesets)) { 652 TAILQ_REMOVE(&pf_anchors, anchor, entries); 653 free(anchor, M_TEMP); 654 } 655} 656 657void 658pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb) 659{ 660 struct pf_pooladdr *mv_pool_pa; 661 662 while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) { 663 TAILQ_REMOVE(poola, mv_pool_pa, entries); 664 TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries); 665 } 666} 667 668void 669pf_empty_pool(struct pf_palist *poola) 670{ 671 struct pf_pooladdr *empty_pool_pa; 672 673 while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) { 674 pf_dynaddr_remove(&empty_pool_pa->addr); 675 pf_tbladdr_remove(&empty_pool_pa->addr); 676 TAILQ_REMOVE(poola, empty_pool_pa, entries); 677 pool_put(&pf_pooladdr_pl, empty_pool_pa); 678 } 679} 680 681void 682pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) 683{ 684 if (rulequeue != NULL) { 685 if (rule->states <= 0) { 686 /* 687 * XXX - we need to remove the table *before* detaching 688 * the rule to make sure the table code does not delete 689 * the anchor under our feet. 690 */ 691 pf_tbladdr_remove(&rule->src.addr); 692 pf_tbladdr_remove(&rule->dst.addr); 693 } 694 TAILQ_REMOVE(rulequeue, rule, entries); 695 rule->entries.tqe_prev = NULL; 696 rule->nr = -1; 697 } 698 if (rule->states > 0 || rule->entries.tqe_prev != NULL) 699 return; 700 pf_tag_unref(rule->tag); 701 pf_tag_unref(rule->match_tag); 702 pf_dynaddr_remove(&rule->src.addr); 703 pf_dynaddr_remove(&rule->dst.addr); 704 if (rulequeue == NULL) { 705 pf_tbladdr_remove(&rule->src.addr); 706 pf_tbladdr_remove(&rule->dst.addr); 707 } 708 pf_empty_pool(&rule->rpool.list); 709 pool_put(&pf_rule_pl, rule); 710} 711 712u_int16_t 713pf_tagname2tag(char *tagname) 714{ 715 struct pf_tagname *tag, *p = NULL; 716 u_int16_t new_tagid = 1; 717 718 TAILQ_FOREACH(tag, &pf_tags, entries) 719 if (strcmp(tagname, tag->name) == 0) { 720 tag->ref++; 721 return (tag->tag); 722 } 723 724 /* 725 * to avoid fragmentation, we do a linear search from the beginning 726 * and take the first free slot we find. if there is none or the list 727 * is empty, append a new entry at the end. 728 */ 729 730 /* new entry */ 731 if (!TAILQ_EMPTY(&pf_tags)) 732 for (p = TAILQ_FIRST(&pf_tags); p != NULL && 733 p->tag == new_tagid; p = TAILQ_NEXT(p, entries)) 734 new_tagid = p->tag + 1; 735 736 if (new_tagid > TAGID_MAX) 737 return (0); 738 739 /* allocate and fill new struct pf_tagname */ 740 tag = (struct pf_tagname *)malloc(sizeof(struct pf_tagname), 741 M_TEMP, M_NOWAIT); 742 if (tag == NULL) 743 return (0); 744 bzero(tag, sizeof(struct pf_tagname)); 745 strlcpy(tag->name, tagname, sizeof(tag->name)); 746 tag->tag = new_tagid; 747 tag->ref++; 748 749 if (p != NULL) /* insert new entry before p */ 750 TAILQ_INSERT_BEFORE(p, tag, entries); 751 else /* either list empty or no free slot in between */ 752 TAILQ_INSERT_TAIL(&pf_tags, tag, entries); 753 754 return (tag->tag); 755} 756 757void 758pf_tag2tagname(u_int16_t tagid, char *p) 759{ 760 struct pf_tagname *tag; 761 762 TAILQ_FOREACH(tag, &pf_tags, entries) 763 if (tag->tag == tagid) { 764 strlcpy(p, tag->name, PF_TAG_NAME_SIZE); 765 return; 766 } 767} 768 769void 770pf_tag_unref(u_int16_t tag) 771{ 772 struct pf_tagname *p, *next; 773 774 if (tag == 0) 775 return; 776 777 for (p = TAILQ_FIRST(&pf_tags); p != NULL; p = next) { 778 next = TAILQ_NEXT(p, entries); 779 if (tag == p->tag) { 780 if (--p->ref == 0) { 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) 511 switch (cmd) { 512 case DIOCGETRULES: 513 case DIOCGETRULE: 514 case DIOCGETADDRS: 515 case DIOCGETADDR: 516 case DIOCGETSTATE: 517 case DIOCSETSTATUSIF: 518 case DIOCGETSTATUS: 519 case DIOCCLRSTATUS: 520 case DIOCNATLOOK: 521 case DIOCSETDEBUG: 522 case DIOCGETSTATES: 523 case DIOCGETTIMEOUT: 524 case DIOCCLRRULECTRS: 525 case DIOCGETLIMIT: 526 case DIOCGETALTQS: 527 case DIOCGETALTQ: 528 case DIOCGETQSTATS: 529 case DIOCGETANCHORS: 530 case DIOCGETANCHOR: 531 case DIOCGETRULESETS: 532 case DIOCGETRULESET: 533 case DIOCRGETTABLES: 534 case DIOCRGETTSTATS: 535 case DIOCRCLRTSTATS: 536 case DIOCRCLRADDRS: 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) 804 switch (cmd) { 805 case DIOCGETRULES: 806 case DIOCGETRULE: 807 case DIOCGETADDRS: 808 case DIOCGETADDR: 809 case DIOCGETSTATE: 810 case DIOCSETSTATUSIF: 811 case DIOCGETSTATUS: 812 case DIOCCLRSTATUS: 813 case DIOCNATLOOK: 814 case DIOCSETDEBUG: 815 case DIOCGETSTATES: 816 case DIOCGETTIMEOUT: 817 case DIOCCLRRULECTRS: 818 case DIOCGETLIMIT: 819 case DIOCGETALTQS: 820 case DIOCGETALTQ: 821 case DIOCGETQSTATS: 822 case DIOCGETANCHORS: 823 case DIOCGETANCHOR: 824 case DIOCGETRULESETS: 825 case DIOCGETRULESET: 826 case DIOCRGETTABLES: 827 case DIOCRGETTSTATS: 828 case DIOCRCLRTSTATS: 829 case DIOCRCLRADDRS: 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: 553 case DIOCGETRULE: 554 case DIOCGETADDRS: 555 case DIOCGETADDR: 556 case DIOCGETSTATE: 557 case DIOCGETSTATUS: 558 case DIOCGETSTATES: 559 case DIOCGETTIMEOUT: 560 case DIOCGETLIMIT: 561 case DIOCGETALTQS: 562 case DIOCGETALTQ: 563 case DIOCGETQSTATS: 564 case DIOCGETANCHORS: 565 case DIOCGETANCHOR: 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: 849 case DIOCGETRULE: 850 case DIOCGETADDRS: 851 case DIOCGETADDR: 852 case DIOCGETSTATE: 853 case DIOCGETSTATUS: 854 case DIOCGETSTATES: 855 case DIOCGETTIMEOUT: 856 case DIOCGETLIMIT: 857 case DIOCGETALTQS: 858 case DIOCGETALTQ: 859 case DIOCGETQSTATS: 860 case DIOCGETANCHORS: 861 case DIOCGETANCHOR: 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; 610 int rs_num; 611 612 ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset); 613 if (ruleset == NULL) { 614 error = EINVAL; 615 break; 616 } 617 rs_num = pf_get_ruleset_number(pr->rule.action); 618 if (rs_num >= PF_RULESET_MAX) { 619 error = EINVAL; 620 break; 621 } 622 while ((rule = 623 TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr)) != NULL) 624 pf_rm_rule(ruleset->rules[rs_num].inactive.ptr, rule); 625 pr->ticket = ++ruleset->rules[rs_num].inactive.ticket; 626 break; 627 } 628 629 case DIOCADDRULE: { 630 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 631 struct pf_ruleset *ruleset; 632 struct pf_rule *rule, *tail; 633 struct pf_pooladdr *pa; 634 int rs_num; 635 636 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 637 if (ruleset == NULL) { 638 error = EINVAL; 639 break; 640 } 641 rs_num = pf_get_ruleset_number(pr->rule.action); 642 if (rs_num >= PF_RULESET_MAX) { 643 error = EINVAL; 644 break; 645 } 646 if (pr->rule.anchorname[0] && ruleset != &pf_main_ruleset) { 647 error = EINVAL; 648 break; 649 } 650 if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { 651 error = EINVAL; 652 break; 653 } 654 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { 655 error = EBUSY; 656 break; 657 } 658 if (pr->pool_ticket != ticket_pabuf) { 659 error = EBUSY; 660 break; 661 } 662 rule = pool_get(&pf_rule_pl, PR_NOWAIT); 663 if (rule == NULL) { 664 error = ENOMEM; 665 break; 666 } 667 bcopy(&pr->rule, rule, sizeof(struct pf_rule)); 668 rule->anchor = NULL; 669 rule->ifp = NULL; 670 TAILQ_INIT(&rule->rpool.list); 671 /* initialize refcounting */ 672 rule->states = 0; 673 rule->entries.tqe_prev = NULL; 674#ifndef INET 675 if (rule->af == AF_INET) { 676 pool_put(&pf_rule_pl, rule); 677 error = EAFNOSUPPORT; 678 break; 679 } 680#endif /* INET */ 681#ifndef INET6 682 if (rule->af == AF_INET6) { 683 pool_put(&pf_rule_pl, rule); 684 error = EAFNOSUPPORT; 685 break; 686 } 687#endif /* INET6 */ 688 tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, 689 pf_rulequeue); 690 if (tail) 691 rule->nr = tail->nr + 1; 692 else 693 rule->nr = 0; 694 if (rule->ifname[0]) { 695 rule->ifp = ifunit(rule->ifname); 696 if (rule->ifp == NULL) { 697 pool_put(&pf_rule_pl, rule); 698 error = EINVAL; 699 break; 700 } 701 } 702 703 if (rule->tagname[0]) 704 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0) 705 error = EBUSY; 706 if (rule->match_tagname[0]) 707 if ((rule->match_tag = 708 pf_tagname2tag(rule->match_tagname)) == 0) 709 error = EBUSY; 710 if (rule->rt && !rule->direction) 711 error = EINVAL; 712 if (pf_dynaddr_setup(&rule->src.addr, rule->af)) 713 error = EINVAL; 714 if (pf_dynaddr_setup(&rule->dst.addr, rule->af)) 715 error = EINVAL; 716 if (pf_tbladdr_setup(ruleset, &rule->src.addr)) 717 error = EINVAL; 718 if (pf_tbladdr_setup(ruleset, &rule->dst.addr)) 719 error = EINVAL; 720 TAILQ_FOREACH(pa, &pf_pabuf, entries) 721 if (pf_tbladdr_setup(ruleset, &pa->addr)) 722 error = EINVAL; 723 724 pf_mv_pool(&pf_pabuf, &rule->rpool.list); 725 if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) || 726 (rule->action == PF_BINAT)) && !rule->anchorname[0]) || 727 (rule->rt > PF_FASTROUTE)) && 728 (TAILQ_FIRST(&rule->rpool.list) == NULL)) 729 error = EINVAL; 730 731 if (error) { 732 pf_rm_rule(NULL, rule); 733 break; 734 } 735 rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list); 736 rule->evaluations = rule->packets = rule->bytes = 0; 737 TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr, 738 rule, entries); 739 break; 740 } 741 742 case DIOCCOMMITRULES: { 743 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 744 struct pf_ruleset *ruleset; 745 struct pf_rulequeue *old_rules; 746 struct pf_rule *rule; 747 int rs_num; 748 749 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 750 if (ruleset == NULL) { 751 error = EINVAL; 752 break; 753 } 754 rs_num = pf_get_ruleset_number(pr->rule.action); 755 if (rs_num >= PF_RULESET_MAX) { 756 error = EINVAL; 757 break; 758 } 759 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { 760 error = EBUSY; 761 break; 762 } 763 764#ifdef ALTQ 765 /* set queue IDs */ 766 if (rs_num == PF_RULESET_FILTER) 767 pf_rule_set_qid(ruleset->rules[rs_num].inactive.ptr); 768#endif 769 770 /* Swap rules, keep the old. */ 771 s = splsoftnet(); 772 old_rules = ruleset->rules[rs_num].active.ptr; 773 ruleset->rules[rs_num].active.ptr = 774 ruleset->rules[rs_num].inactive.ptr; 775 ruleset->rules[rs_num].inactive.ptr = old_rules; 776 ruleset->rules[rs_num].active.ticket = 777 ruleset->rules[rs_num].inactive.ticket; 778 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); 779 780 /* Purge the old rule list. */ 781 while ((rule = TAILQ_FIRST(old_rules)) != NULL) 782 pf_rm_rule(old_rules, rule); 783 pf_remove_if_empty_ruleset(ruleset); 784 pf_update_anchor_rules(); 785 splx(s); 786 break; 787 } 788 789 case DIOCGETRULES: { 790 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 791 struct pf_ruleset *ruleset; 792 struct pf_rule *tail; 793 int rs_num; 794 795 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 796 if (ruleset == NULL) { 797 error = EINVAL; 798 break; 799 } 800 rs_num = pf_get_ruleset_number(pr->rule.action); 801 if (rs_num >= PF_RULESET_MAX) { 802 error = EINVAL; 803 break; 804 } 805 s = splsoftnet(); 806 tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, 807 pf_rulequeue); 808 if (tail) 809 pr->nr = tail->nr + 1; 810 else 811 pr->nr = 0; 812 pr->ticket = ruleset->rules[rs_num].active.ticket; 813 splx(s); 814 break; 815 } 816 817 case DIOCGETRULE: { 818 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 819 struct pf_ruleset *ruleset; 820 struct pf_rule *rule; 821 int rs_num, i; 822 823 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 824 if (ruleset == NULL) { 825 error = EINVAL; 826 break; 827 } 828 rs_num = pf_get_ruleset_number(pr->rule.action); 829 if (rs_num >= PF_RULESET_MAX) { 830 error = EINVAL; 831 break; 832 } 833 if (pr->ticket != ruleset->rules[rs_num].active.ticket) { 834 error = EBUSY; 835 break; 836 } 837 s = splsoftnet(); 838 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); 839 while ((rule != NULL) && (rule->nr != pr->nr)) 840 rule = TAILQ_NEXT(rule, entries); 841 if (rule == NULL) { 842 error = EBUSY; 843 splx(s); 844 break; 845 } 846 bcopy(rule, &pr->rule, sizeof(struct pf_rule)); 847 pf_dynaddr_copyout(&pr->rule.src.addr); 848 pf_dynaddr_copyout(&pr->rule.dst.addr); 849 pf_tbladdr_copyout(&pr->rule.src.addr); 850 pf_tbladdr_copyout(&pr->rule.dst.addr); 851 for (i = 0; i < PF_SKIP_COUNT; ++i) 852 if (rule->skip[i].ptr == NULL) 853 pr->rule.skip[i].nr = -1; 854 else 855 pr->rule.skip[i].nr = 856 rule->skip[i].ptr->nr; 857 splx(s); 858 break; 859 } 860 861 case DIOCCHANGERULE: { 862 struct pfioc_rule *pcr = (struct pfioc_rule *)addr; 863 struct pf_ruleset *ruleset; 864 struct pf_rule *oldrule = NULL, *newrule = NULL; 865 u_int32_t nr = 0; 866 int rs_num; 867 868 if (!(pcr->action == PF_CHANGE_REMOVE || 869 pcr->action == PF_CHANGE_GET_TICKET) && 870 pcr->pool_ticket != ticket_pabuf) { 871 error = EBUSY; 872 break; 873 } 874 875 if (pcr->action < PF_CHANGE_ADD_HEAD || 876 pcr->action > PF_CHANGE_GET_TICKET) { 877 error = EINVAL; 878 break; 879 } 880 ruleset = pf_find_ruleset(pcr->anchor, pcr->ruleset); 881 if (ruleset == NULL) { 882 error = EINVAL; 883 break; 884 } 885 rs_num = pf_get_ruleset_number(pcr->rule.action); 886 if (rs_num >= PF_RULESET_MAX) { 887 error = EINVAL; 888 break; 889 } 890 891 if (pcr->action == PF_CHANGE_GET_TICKET) { 892 pcr->ticket = ++ruleset->rules[rs_num].active.ticket; 893 break; 894 } else { 895 if (pcr->ticket != 896 ruleset->rules[rs_num].active.ticket) { 897 error = EINVAL; 898 break; 899 } 900 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { 901 error = EINVAL; 902 break; 903 } 904 } 905 906 if (pcr->action != PF_CHANGE_REMOVE) { 907 newrule = pool_get(&pf_rule_pl, PR_NOWAIT); 908 if (newrule == NULL) { 909 error = ENOMEM; 910 break; 911 } 912 bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); 913 TAILQ_INIT(&newrule->rpool.list); 914 /* initialize refcounting */ 915 newrule->states = 0; 916 newrule->entries.tqe_prev = NULL; 917#ifndef INET 918 if (newrule->af == AF_INET) { 919 pool_put(&pf_rule_pl, newrule); 920 error = EAFNOSUPPORT; 921 break; 922 } 923#endif /* INET */ 924#ifndef INET6 925 if (newrule->af == AF_INET6) { 926 pool_put(&pf_rule_pl, newrule); 927 error = EAFNOSUPPORT; 928 break; 929 } 930#endif /* INET6 */ 931 if (newrule->ifname[0]) { 932 newrule->ifp = ifunit(newrule->ifname); 933 if (newrule->ifp == NULL) { 934 pool_put(&pf_rule_pl, newrule); 935 error = EINVAL; 936 break; 937 } 938 } else 939 newrule->ifp = NULL; 940 941#ifdef ALTQ 942 /* set queue IDs */ 943 if (newrule->qname[0] != 0) { 944 newrule->qid = pf_qname_to_qid(newrule->qname); 945 if (newrule->pqname[0] != 0) 946 newrule->pqid = 947 pf_qname_to_qid(newrule->pqname); 948 else 949 newrule->pqid = newrule->qid; 950 } 951#endif 952 if (newrule->tagname[0]) 953 if ((newrule->tag = 954 pf_tagname2tag(newrule->tagname)) == 0) 955 error = EBUSY; 956 if (newrule->match_tagname[0]) 957 if ((newrule->match_tag = pf_tagname2tag( 958 newrule->match_tagname)) == 0) 959 error = EBUSY; 960 961 if (newrule->rt && !newrule->direction) 962 error = EINVAL; 963 if (pf_dynaddr_setup(&newrule->src.addr, newrule->af)) 964 error = EINVAL; 965 if (pf_dynaddr_setup(&newrule->dst.addr, newrule->af)) 966 error = EINVAL; 967 if (pf_tbladdr_setup(ruleset, &newrule->src.addr)) 968 error = EINVAL; 969 if (pf_tbladdr_setup(ruleset, &newrule->dst.addr)) 970 error = EINVAL; 971 972 pf_mv_pool(&pf_pabuf, &newrule->rpool.list); 973 if (((((newrule->action == PF_NAT) || 974 (newrule->action == PF_RDR) || 975 (newrule->action == PF_BINAT) || 976 (newrule->rt > PF_FASTROUTE)) && 977 !newrule->anchorname[0])) && 978 (TAILQ_FIRST(&newrule->rpool.list) == NULL)) 979 error = EINVAL; 980 981 if (error) { 982 pf_rm_rule(NULL, newrule); 983 break; 984 } 985 newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list); 986 newrule->evaluations = newrule->packets = 0; 987 newrule->bytes = 0; 988 } 989 pf_empty_pool(&pf_pabuf); 990 991 s = splsoftnet(); 992 993 if (pcr->action == PF_CHANGE_ADD_HEAD) 994 oldrule = TAILQ_FIRST( 995 ruleset->rules[rs_num].active.ptr); 996 else if (pcr->action == PF_CHANGE_ADD_TAIL) 997 oldrule = TAILQ_LAST( 998 ruleset->rules[rs_num].active.ptr, pf_rulequeue); 999 else { 1000 oldrule = TAILQ_FIRST( 1001 ruleset->rules[rs_num].active.ptr); 1002 while ((oldrule != NULL) && (oldrule->nr != pcr->nr)) 1003 oldrule = TAILQ_NEXT(oldrule, entries); 1004 if (oldrule == NULL) { 1005 pf_rm_rule(NULL, newrule); 1006 error = EINVAL; 1007 splx(s); 1008 break; 1009 } 1010 } 1011 1012 if (pcr->action == PF_CHANGE_REMOVE) 1013 pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule); 1014 else { 1015 if (oldrule == NULL) 1016 TAILQ_INSERT_TAIL( 1017 ruleset->rules[rs_num].active.ptr, 1018 newrule, entries); 1019 else if (pcr->action == PF_CHANGE_ADD_HEAD || 1020 pcr->action == PF_CHANGE_ADD_BEFORE) 1021 TAILQ_INSERT_BEFORE(oldrule, newrule, entries); 1022 else 1023 TAILQ_INSERT_AFTER( 1024 ruleset->rules[rs_num].active.ptr, 1025 oldrule, newrule, entries); 1026 } 1027 1028 nr = 0; 1029 TAILQ_FOREACH(oldrule, 1030 ruleset->rules[rs_num].active.ptr, entries) 1031 oldrule->nr = nr++; 1032 1033 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); 1034 pf_remove_if_empty_ruleset(ruleset); 1035 pf_update_anchor_rules(); 1036 1037 ruleset->rules[rs_num].active.ticket++; 1038 splx(s); 1039 break; 1040 } 1041 1042 case DIOCCLRSTATES: { 1043 struct pf_tree_node *n; 1044 1045 s = splsoftnet(); 1046 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) 1047 n->state->timeout = PFTM_PURGE; 1048 pf_purge_expired_states(); 1049 pf_status.states = 0; 1050 splx(s); 1051 break; 1052 } 1053 1054 case DIOCKILLSTATES: { 1055 struct pf_tree_node *n; 1056 struct pf_state *st; 1057 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; 1058 int killed = 0; 1059 1060 s = splsoftnet(); 1061 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) { 1062 st = n->state; 1063 if ((!psk->psk_af || st->af == psk->psk_af) && 1064 (!psk->psk_proto || psk->psk_proto == st->proto) && 1065 PF_MATCHA(psk->psk_src.not, 1066 &psk->psk_src.addr.v.a.addr, 1067 &psk->psk_src.addr.v.a.mask, &st->lan.addr, 1068 st->af) && 1069 PF_MATCHA(psk->psk_dst.not, 1070 &psk->psk_dst.addr.v.a.addr, 1071 &psk->psk_dst.addr.v.a.mask, &st->ext.addr, 1072 st->af) && 1073 (psk->psk_src.port_op == 0 || 1074 pf_match_port(psk->psk_src.port_op, 1075 psk->psk_src.port[0], psk->psk_src.port[1], 1076 st->lan.port)) && 1077 (psk->psk_dst.port_op == 0 || 1078 pf_match_port(psk->psk_dst.port_op, 1079 psk->psk_dst.port[0], psk->psk_dst.port[1], 1080 st->ext.port))) { 1081 st->timeout = PFTM_PURGE; 1082 killed++; 1083 } 1084 } 1085 pf_purge_expired_states(); 1086 splx(s); 1087 psk->psk_af = killed; 1088 break; 1089 } 1090 1091 case DIOCADDSTATE: { 1092 struct pfioc_state *ps = (struct pfioc_state *)addr; 1093 struct pf_state *state; 1094 1095 if (ps->state.timeout >= PFTM_MAX && 1096 ps->state.timeout != PFTM_UNTIL_PACKET) { 1097 error = EINVAL; 1098 break; 1099 } 1100 state = pool_get(&pf_state_pl, PR_NOWAIT); 1101 if (state == NULL) { 1102 error = ENOMEM; 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; 942 int rs_num; 943 944 ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset); 945 if (ruleset == NULL) { 946 error = EINVAL; 947 break; 948 } 949 rs_num = pf_get_ruleset_number(pr->rule.action); 950 if (rs_num >= PF_RULESET_MAX) { 951 error = EINVAL; 952 break; 953 } 954 while ((rule = 955 TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr)) != NULL) 956 pf_rm_rule(ruleset->rules[rs_num].inactive.ptr, rule); 957 pr->ticket = ++ruleset->rules[rs_num].inactive.ticket; 958 break; 959 } 960 961 case DIOCADDRULE: { 962 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 963 struct pf_ruleset *ruleset; 964 struct pf_rule *rule, *tail; 965 struct pf_pooladdr *pa; 966 int rs_num; 967 968 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 969 if (ruleset == NULL) { 970 error = EINVAL; 971 break; 972 } 973 rs_num = pf_get_ruleset_number(pr->rule.action); 974 if (rs_num >= PF_RULESET_MAX) { 975 error = EINVAL; 976 break; 977 } 978 if (pr->rule.anchorname[0] && ruleset != &pf_main_ruleset) { 979 error = EINVAL; 980 break; 981 } 982 if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { 983 error = EINVAL; 984 break; 985 } 986 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { 987 error = EBUSY; 988 break; 989 } 990 if (pr->pool_ticket != ticket_pabuf) { 991 error = EBUSY; 992 break; 993 } 994 rule = pool_get(&pf_rule_pl, PR_NOWAIT); 995 if (rule == NULL) { 996 error = ENOMEM; 997 break; 998 } 999 bcopy(&pr->rule, rule, sizeof(struct pf_rule)); 1000 rule->anchor = NULL; 1001 rule->ifp = NULL; 1002 TAILQ_INIT(&rule->rpool.list); 1003 /* initialize refcounting */ 1004 rule->states = 0; 1005 rule->entries.tqe_prev = NULL; 1006#ifndef INET 1007 if (rule->af == AF_INET) { 1008 pool_put(&pf_rule_pl, rule); 1009 error = EAFNOSUPPORT; 1010 break; 1011 } 1012#endif /* INET */ 1013#ifndef INET6 1014 if (rule->af == AF_INET6) { 1015 pool_put(&pf_rule_pl, rule); 1016 error = EAFNOSUPPORT; 1017 break; 1018 } 1019#endif /* INET6 */ 1020 tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, 1021 pf_rulequeue); 1022 if (tail) 1023 rule->nr = tail->nr + 1; 1024 else 1025 rule->nr = 0; 1026 if (rule->ifname[0]) { 1027 rule->ifp = ifunit(rule->ifname); 1028 if (rule->ifp == NULL) { 1029 pool_put(&pf_rule_pl, rule); 1030 error = EINVAL; 1031 break; 1032 } 1033 } 1034 1035 if (rule->tagname[0]) 1036 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0) 1037 error = EBUSY; 1038 if (rule->match_tagname[0]) 1039 if ((rule->match_tag = 1040 pf_tagname2tag(rule->match_tagname)) == 0) 1041 error = EBUSY; 1042 if (rule->rt && !rule->direction) 1043 error = EINVAL; 1044 if (pf_dynaddr_setup(&rule->src.addr, rule->af)) 1045 error = EINVAL; 1046 if (pf_dynaddr_setup(&rule->dst.addr, rule->af)) 1047 error = EINVAL; 1048 if (pf_tbladdr_setup(ruleset, &rule->src.addr)) 1049 error = EINVAL; 1050 if (pf_tbladdr_setup(ruleset, &rule->dst.addr)) 1051 error = EINVAL; 1052 TAILQ_FOREACH(pa, &pf_pabuf, entries) 1053 if (pf_tbladdr_setup(ruleset, &pa->addr)) 1054 error = EINVAL; 1055 1056 pf_mv_pool(&pf_pabuf, &rule->rpool.list); 1057 if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) || 1058 (rule->action == PF_BINAT)) && !rule->anchorname[0]) || 1059 (rule->rt > PF_FASTROUTE)) && 1060 (TAILQ_FIRST(&rule->rpool.list) == NULL)) 1061 error = EINVAL; 1062 1063 if (error) { 1064 pf_rm_rule(NULL, rule); 1065 break; 1066 } 1067 rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list); 1068 rule->evaluations = rule->packets = rule->bytes = 0; 1069 TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr, 1070 rule, entries); 1071 break; 1072 } 1073 1074 case DIOCCOMMITRULES: { 1075 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1076 struct pf_ruleset *ruleset; 1077 struct pf_rulequeue *old_rules; 1078 struct pf_rule *rule; 1079 int rs_num; 1080 1081 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 1082 if (ruleset == NULL) { 1083 error = EINVAL; 1084 break; 1085 } 1086 rs_num = pf_get_ruleset_number(pr->rule.action); 1087 if (rs_num >= PF_RULESET_MAX) { 1088 error = EINVAL; 1089 break; 1090 } 1091 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { 1092 error = EBUSY; 1093 break; 1094 } 1095 1096#ifdef ALTQ 1097 /* set queue IDs */ 1098 if (rs_num == PF_RULESET_FILTER) 1099 pf_rule_set_qid(ruleset->rules[rs_num].inactive.ptr); 1100#endif 1101 1102 /* Swap rules, keep the old. */ 1103 s = splsoftnet(); 1104 old_rules = ruleset->rules[rs_num].active.ptr; 1105 ruleset->rules[rs_num].active.ptr = 1106 ruleset->rules[rs_num].inactive.ptr; 1107 ruleset->rules[rs_num].inactive.ptr = old_rules; 1108 ruleset->rules[rs_num].active.ticket = 1109 ruleset->rules[rs_num].inactive.ticket; 1110 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); 1111 1112 /* Purge the old rule list. */ 1113 while ((rule = TAILQ_FIRST(old_rules)) != NULL) 1114 pf_rm_rule(old_rules, rule); 1115 pf_remove_if_empty_ruleset(ruleset); 1116 pf_update_anchor_rules(); 1117 splx(s); 1118 break; 1119 } 1120 1121 case DIOCGETRULES: { 1122 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1123 struct pf_ruleset *ruleset; 1124 struct pf_rule *tail; 1125 int rs_num; 1126 1127 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 1128 if (ruleset == NULL) { 1129 error = EINVAL; 1130 break; 1131 } 1132 rs_num = pf_get_ruleset_number(pr->rule.action); 1133 if (rs_num >= PF_RULESET_MAX) { 1134 error = EINVAL; 1135 break; 1136 } 1137 s = splsoftnet(); 1138 tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, 1139 pf_rulequeue); 1140 if (tail) 1141 pr->nr = tail->nr + 1; 1142 else 1143 pr->nr = 0; 1144 pr->ticket = ruleset->rules[rs_num].active.ticket; 1145 splx(s); 1146 break; 1147 } 1148 1149 case DIOCGETRULE: { 1150 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1151 struct pf_ruleset *ruleset; 1152 struct pf_rule *rule; 1153 int rs_num, i; 1154 1155 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 1156 if (ruleset == NULL) { 1157 error = EINVAL; 1158 break; 1159 } 1160 rs_num = pf_get_ruleset_number(pr->rule.action); 1161 if (rs_num >= PF_RULESET_MAX) { 1162 error = EINVAL; 1163 break; 1164 } 1165 if (pr->ticket != ruleset->rules[rs_num].active.ticket) { 1166 error = EBUSY; 1167 break; 1168 } 1169 s = splsoftnet(); 1170 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); 1171 while ((rule != NULL) && (rule->nr != pr->nr)) 1172 rule = TAILQ_NEXT(rule, entries); 1173 if (rule == NULL) { 1174 error = EBUSY; 1175 splx(s); 1176 break; 1177 } 1178 bcopy(rule, &pr->rule, sizeof(struct pf_rule)); 1179 pf_dynaddr_copyout(&pr->rule.src.addr); 1180 pf_dynaddr_copyout(&pr->rule.dst.addr); 1181 pf_tbladdr_copyout(&pr->rule.src.addr); 1182 pf_tbladdr_copyout(&pr->rule.dst.addr); 1183 for (i = 0; i < PF_SKIP_COUNT; ++i) 1184 if (rule->skip[i].ptr == NULL) 1185 pr->rule.skip[i].nr = -1; 1186 else 1187 pr->rule.skip[i].nr = 1188 rule->skip[i].ptr->nr; 1189 splx(s); 1190 break; 1191 } 1192 1193 case DIOCCHANGERULE: { 1194 struct pfioc_rule *pcr = (struct pfioc_rule *)addr; 1195 struct pf_ruleset *ruleset; 1196 struct pf_rule *oldrule = NULL, *newrule = NULL; 1197 u_int32_t nr = 0; 1198 int rs_num; 1199 1200 if (!(pcr->action == PF_CHANGE_REMOVE || 1201 pcr->action == PF_CHANGE_GET_TICKET) && 1202 pcr->pool_ticket != ticket_pabuf) { 1203 error = EBUSY; 1204 break; 1205 } 1206 1207 if (pcr->action < PF_CHANGE_ADD_HEAD || 1208 pcr->action > PF_CHANGE_GET_TICKET) { 1209 error = EINVAL; 1210 break; 1211 } 1212 ruleset = pf_find_ruleset(pcr->anchor, pcr->ruleset); 1213 if (ruleset == NULL) { 1214 error = EINVAL; 1215 break; 1216 } 1217 rs_num = pf_get_ruleset_number(pcr->rule.action); 1218 if (rs_num >= PF_RULESET_MAX) { 1219 error = EINVAL; 1220 break; 1221 } 1222 1223 if (pcr->action == PF_CHANGE_GET_TICKET) { 1224 pcr->ticket = ++ruleset->rules[rs_num].active.ticket; 1225 break; 1226 } else { 1227 if (pcr->ticket != 1228 ruleset->rules[rs_num].active.ticket) { 1229 error = EINVAL; 1230 break; 1231 } 1232 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { 1233 error = EINVAL; 1234 break; 1235 } 1236 } 1237 1238 if (pcr->action != PF_CHANGE_REMOVE) { 1239 newrule = pool_get(&pf_rule_pl, PR_NOWAIT); 1240 if (newrule == NULL) { 1241 error = ENOMEM; 1242 break; 1243 } 1244 bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); 1245 TAILQ_INIT(&newrule->rpool.list); 1246 /* initialize refcounting */ 1247 newrule->states = 0; 1248 newrule->entries.tqe_prev = NULL; 1249#ifndef INET 1250 if (newrule->af == AF_INET) { 1251 pool_put(&pf_rule_pl, newrule); 1252 error = EAFNOSUPPORT; 1253 break; 1254 } 1255#endif /* INET */ 1256#ifndef INET6 1257 if (newrule->af == AF_INET6) { 1258 pool_put(&pf_rule_pl, newrule); 1259 error = EAFNOSUPPORT; 1260 break; 1261 } 1262#endif /* INET6 */ 1263 if (newrule->ifname[0]) { 1264 newrule->ifp = ifunit(newrule->ifname); 1265 if (newrule->ifp == NULL) { 1266 pool_put(&pf_rule_pl, newrule); 1267 error = EINVAL; 1268 break; 1269 } 1270 } else 1271 newrule->ifp = NULL; 1272 1273#ifdef ALTQ 1274 /* set queue IDs */ 1275 if (newrule->qname[0] != 0) { 1276 newrule->qid = pf_qname_to_qid(newrule->qname); 1277 if (newrule->pqname[0] != 0) 1278 newrule->pqid = 1279 pf_qname_to_qid(newrule->pqname); 1280 else 1281 newrule->pqid = newrule->qid; 1282 } 1283#endif 1284 if (newrule->tagname[0]) 1285 if ((newrule->tag = 1286 pf_tagname2tag(newrule->tagname)) == 0) 1287 error = EBUSY; 1288 if (newrule->match_tagname[0]) 1289 if ((newrule->match_tag = pf_tagname2tag( 1290 newrule->match_tagname)) == 0) 1291 error = EBUSY; 1292 1293 if (newrule->rt && !newrule->direction) 1294 error = EINVAL; 1295 if (pf_dynaddr_setup(&newrule->src.addr, newrule->af)) 1296 error = EINVAL; 1297 if (pf_dynaddr_setup(&newrule->dst.addr, newrule->af)) 1298 error = EINVAL; 1299 if (pf_tbladdr_setup(ruleset, &newrule->src.addr)) 1300 error = EINVAL; 1301 if (pf_tbladdr_setup(ruleset, &newrule->dst.addr)) 1302 error = EINVAL; 1303 1304 pf_mv_pool(&pf_pabuf, &newrule->rpool.list); 1305 if (((((newrule->action == PF_NAT) || 1306 (newrule->action == PF_RDR) || 1307 (newrule->action == PF_BINAT) || 1308 (newrule->rt > PF_FASTROUTE)) && 1309 !newrule->anchorname[0])) && 1310 (TAILQ_FIRST(&newrule->rpool.list) == NULL)) 1311 error = EINVAL; 1312 1313 if (error) { 1314 pf_rm_rule(NULL, newrule); 1315 break; 1316 } 1317 newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list); 1318 newrule->evaluations = newrule->packets = 0; 1319 newrule->bytes = 0; 1320 } 1321 pf_empty_pool(&pf_pabuf); 1322 1323 s = splsoftnet(); 1324 1325 if (pcr->action == PF_CHANGE_ADD_HEAD) 1326 oldrule = TAILQ_FIRST( 1327 ruleset->rules[rs_num].active.ptr); 1328 else if (pcr->action == PF_CHANGE_ADD_TAIL) 1329 oldrule = TAILQ_LAST( 1330 ruleset->rules[rs_num].active.ptr, pf_rulequeue); 1331 else { 1332 oldrule = TAILQ_FIRST( 1333 ruleset->rules[rs_num].active.ptr); 1334 while ((oldrule != NULL) && (oldrule->nr != pcr->nr)) 1335 oldrule = TAILQ_NEXT(oldrule, entries); 1336 if (oldrule == NULL) { 1337 pf_rm_rule(NULL, newrule); 1338 error = EINVAL; 1339 splx(s); 1340 break; 1341 } 1342 } 1343 1344 if (pcr->action == PF_CHANGE_REMOVE) 1345 pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule); 1346 else { 1347 if (oldrule == NULL) 1348 TAILQ_INSERT_TAIL( 1349 ruleset->rules[rs_num].active.ptr, 1350 newrule, entries); 1351 else if (pcr->action == PF_CHANGE_ADD_HEAD || 1352 pcr->action == PF_CHANGE_ADD_BEFORE) 1353 TAILQ_INSERT_BEFORE(oldrule, newrule, entries); 1354 else 1355 TAILQ_INSERT_AFTER( 1356 ruleset->rules[rs_num].active.ptr, 1357 oldrule, newrule, entries); 1358 } 1359 1360 nr = 0; 1361 TAILQ_FOREACH(oldrule, 1362 ruleset->rules[rs_num].active.ptr, entries) 1363 oldrule->nr = nr++; 1364 1365 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); 1366 pf_remove_if_empty_ruleset(ruleset); 1367 pf_update_anchor_rules(); 1368 1369 ruleset->rules[rs_num].active.ticket++; 1370 splx(s); 1371 break; 1372 } 1373 1374 case DIOCCLRSTATES: { 1375 struct pf_tree_node *n; 1376 1377 s = splsoftnet(); 1378 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) 1379 n->state->timeout = PFTM_PURGE; 1380 pf_purge_expired_states(); 1381 pf_status.states = 0; 1382 splx(s); 1383 break; 1384 } 1385 1386 case DIOCKILLSTATES: { 1387 struct pf_tree_node *n; 1388 struct pf_state *st; 1389 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; 1390 int killed = 0; 1391 1392 s = splsoftnet(); 1393 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) { 1394 st = n->state; 1395 if ((!psk->psk_af || st->af == psk->psk_af) && 1396 (!psk->psk_proto || psk->psk_proto == st->proto) && 1397 PF_MATCHA(psk->psk_src.not, 1398 &psk->psk_src.addr.v.a.addr, 1399 &psk->psk_src.addr.v.a.mask, &st->lan.addr, 1400 st->af) && 1401 PF_MATCHA(psk->psk_dst.not, 1402 &psk->psk_dst.addr.v.a.addr, 1403 &psk->psk_dst.addr.v.a.mask, &st->ext.addr, 1404 st->af) && 1405 (psk->psk_src.port_op == 0 || 1406 pf_match_port(psk->psk_src.port_op, 1407 psk->psk_src.port[0], psk->psk_src.port[1], 1408 st->lan.port)) && 1409 (psk->psk_dst.port_op == 0 || 1410 pf_match_port(psk->psk_dst.port_op, 1411 psk->psk_dst.port[0], psk->psk_dst.port[1], 1412 st->ext.port))) { 1413 st->timeout = PFTM_PURGE; 1414 killed++; 1415 } 1416 } 1417 pf_purge_expired_states(); 1418 splx(s); 1419 psk->psk_af = killed; 1420 break; 1421 } 1422 1423 case DIOCADDSTATE: { 1424 struct pfioc_state *ps = (struct pfioc_state *)addr; 1425 struct pf_state *state; 1426 1427 if (ps->state.timeout >= PFTM_MAX && 1428 ps->state.timeout != PFTM_UNTIL_PACKET) { 1429 error = EINVAL; 1430 break; 1431 } 1432 state = pool_get(&pf_state_pl, PR_NOWAIT); 1433 if (state == NULL) { 1434 error = ENOMEM; 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; 1120 } 1121 1122 case DIOCGETSTATE: { 1123 struct pfioc_state *ps = (struct pfioc_state *)addr; 1124 struct pf_tree_node *n; 1125 u_int32_t nr; 1126 1127 nr = 0; 1128 s = splsoftnet(); 1129 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) { 1130 if (nr >= ps->nr) 1131 break; 1132 nr++; 1133 } 1134 if (n == NULL) { 1135 error = EBUSY; 1136 splx(s); 1137 break; 1138 } 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; 1456 } 1457 1458 case DIOCGETSTATE: { 1459 struct pfioc_state *ps = (struct pfioc_state *)addr; 1460 struct pf_tree_node *n; 1461 u_int32_t nr; 1462 1463 nr = 0; 1464 s = splsoftnet(); 1465 RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) { 1466 if (nr >= ps->nr) 1467 break; 1468 nr++; 1469 } 1470 if (n == NULL) { 1471 error = EBUSY; 1472 splx(s); 1473 break; 1474 } 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; 1199 splx(s); 1200 break; 1201 } 1202 1203 case DIOCGETSTATUS: { 1204 struct pf_status *s = (struct pf_status *)addr; 1205 bcopy(&pf_status, s, sizeof(struct pf_status)); 1206 break; 1207 } 1208 1209 case DIOCSETSTATUSIF: { 1210 struct pfioc_if *pi = (struct pfioc_if *)addr; 1211 struct ifnet *ifp; 1212 1213 if (pi->ifname[0] == 0) { 1214 status_ifp = NULL; 1215 bzero(pf_status.ifname, IFNAMSIZ); 1216 break; 1217 } 1218 if ((ifp = ifunit(pi->ifname)) == NULL) { 1219 error = EINVAL; 1220 break; 1221 } else if (ifp == status_ifp) 1222 break; 1223 status_ifp = ifp; 1224 /* fallthrough into DIOCCLRSTATUS */ 1225 } 1226 1227 case DIOCCLRSTATUS: { 1228 u_int32_t running = pf_status.running; 1229 u_int32_t states = pf_status.states; 1230 u_int32_t since = pf_status.since; 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; 1551 splx(s); 1552 break; 1553 } 1554 1555 case DIOCGETSTATUS: { 1556 struct pf_status *s = (struct pf_status *)addr; 1557 bcopy(&pf_status, s, sizeof(struct pf_status)); 1558 break; 1559 } 1560 1561 case DIOCSETSTATUSIF: { 1562 struct pfioc_if *pi = (struct pfioc_if *)addr; 1563 struct ifnet *ifp; 1564 1565 if (pi->ifname[0] == 0) { 1566 status_ifp = NULL; 1567 bzero(pf_status.ifname, IFNAMSIZ); 1568 break; 1569 } 1570 if ((ifp = ifunit(pi->ifname)) == NULL) { 1571 error = EINVAL; 1572 break; 1573 } else if (ifp == status_ifp) 1574 break; 1575 status_ifp = ifp; 1576 /* fallthrough into DIOCCLRSTATUS */ 1577 } 1578 1579 case DIOCCLRSTATUS: { 1580 u_int32_t running = pf_status.running; 1581 u_int32_t states = pf_status.states; 1582 u_int32_t since = pf_status.since; 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; 1249 1250 key.af = pnl->af; 1251 key.proto = pnl->proto; 1252 1253 /* 1254 * userland gives us source and dest of connection, reverse 1255 * the lookup so we ask for what happens with the return 1256 * traffic, enabling us to find it in the state tree. 1257 */ 1258 PF_ACPY(&key.addr[1], &pnl->saddr, pnl->af); 1259 key.port[1] = pnl->sport; 1260 PF_ACPY(&key.addr[0], &pnl->daddr, pnl->af); 1261 key.port[0] = pnl->dport; 1262 1263 if (!pnl->proto || 1264 PF_AZERO(&pnl->saddr, pnl->af) || 1265 PF_AZERO(&pnl->daddr, pnl->af) || 1266 !pnl->dport || !pnl->sport) 1267 error = EINVAL; 1268 else { 1269 s = splsoftnet(); 1270 if (direction == PF_IN) 1271 st = pf_find_state(&tree_ext_gwy, &key); 1272 else 1273 st = pf_find_state(&tree_lan_ext, &key); 1274 if (st != NULL) { 1275 if (direction == PF_IN) { 1276 PF_ACPY(&pnl->rsaddr, &st->lan.addr, 1277 st->af); 1278 pnl->rsport = st->lan.port; 1279 PF_ACPY(&pnl->rdaddr, &pnl->daddr, 1280 pnl->af); 1281 pnl->rdport = pnl->dport; 1282 } else { 1283 PF_ACPY(&pnl->rdaddr, &st->gwy.addr, 1284 st->af); 1285 pnl->rdport = st->gwy.port; 1286 PF_ACPY(&pnl->rsaddr, &pnl->saddr, 1287 pnl->af); 1288 pnl->rsport = pnl->sport; 1289 } 1290 } else 1291 error = ENOENT; 1292 splx(s); 1293 } 1294 break; 1295 } 1296 1297 case DIOCSETTIMEOUT: { 1298 struct pfioc_tm *pt = (struct pfioc_tm *)addr; 1299 int old; 1300 1301 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX || 1302 pt->seconds < 0) { 1303 error = EINVAL; 1304 goto fail; 1305 } 1306 old = pf_default_rule.timeout[pt->timeout]; 1307 pf_default_rule.timeout[pt->timeout] = pt->seconds; 1308 pt->seconds = old; 1309 break; 1310 } 1311 1312 case DIOCGETTIMEOUT: { 1313 struct pfioc_tm *pt = (struct pfioc_tm *)addr; 1314 1315 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) { 1316 error = EINVAL; 1317 goto fail; 1318 } 1319 pt->seconds = pf_default_rule.timeout[pt->timeout]; 1320 break; 1321 } 1322 1323 case DIOCGETLIMIT: { 1324 struct pfioc_limit *pl = (struct pfioc_limit *)addr; 1325 1326 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) { 1327 error = EINVAL; 1328 goto fail; 1329 } 1330 pl->limit = pf_pool_limits[pl->index].limit; 1331 break; 1332 } 1333 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; 1606 1607 key.af = pnl->af; 1608 key.proto = pnl->proto; 1609 1610 /* 1611 * userland gives us source and dest of connection, reverse 1612 * the lookup so we ask for what happens with the return 1613 * traffic, enabling us to find it in the state tree. 1614 */ 1615 PF_ACPY(&key.addr[1], &pnl->saddr, pnl->af); 1616 key.port[1] = pnl->sport; 1617 PF_ACPY(&key.addr[0], &pnl->daddr, pnl->af); 1618 key.port[0] = pnl->dport; 1619 1620 if (!pnl->proto || 1621 PF_AZERO(&pnl->saddr, pnl->af) || 1622 PF_AZERO(&pnl->daddr, pnl->af) || 1623 !pnl->dport || !pnl->sport) 1624 error = EINVAL; 1625 else { 1626 s = splsoftnet(); 1627 if (direction == PF_IN) 1628 st = pf_find_state(&tree_ext_gwy, &key); 1629 else 1630 st = pf_find_state(&tree_lan_ext, &key); 1631 if (st != NULL) { 1632 if (direction == PF_IN) { 1633 PF_ACPY(&pnl->rsaddr, &st->lan.addr, 1634 st->af); 1635 pnl->rsport = st->lan.port; 1636 PF_ACPY(&pnl->rdaddr, &pnl->daddr, 1637 pnl->af); 1638 pnl->rdport = pnl->dport; 1639 } else { 1640 PF_ACPY(&pnl->rdaddr, &st->gwy.addr, 1641 st->af); 1642 pnl->rdport = st->gwy.port; 1643 PF_ACPY(&pnl->rsaddr, &pnl->saddr, 1644 pnl->af); 1645 pnl->rsport = pnl->sport; 1646 } 1647 } else 1648 error = ENOENT; 1649 splx(s); 1650 } 1651 break; 1652 } 1653 1654 case DIOCSETTIMEOUT: { 1655 struct pfioc_tm *pt = (struct pfioc_tm *)addr; 1656 int old; 1657 1658 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX || 1659 pt->seconds < 0) { 1660 error = EINVAL; 1661 goto fail; 1662 } 1663 old = pf_default_rule.timeout[pt->timeout]; 1664 pf_default_rule.timeout[pt->timeout] = pt->seconds; 1665 pt->seconds = old; 1666 break; 1667 } 1668 1669 case DIOCGETTIMEOUT: { 1670 struct pfioc_tm *pt = (struct pfioc_tm *)addr; 1671 1672 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) { 1673 error = EINVAL; 1674 goto fail; 1675 } 1676 pt->seconds = pf_default_rule.timeout[pt->timeout]; 1677 break; 1678 } 1679 1680 case DIOCGETLIMIT: { 1681 struct pfioc_limit *pl = (struct pfioc_limit *)addr; 1682 1683 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) { 1684 error = EINVAL; 1685 goto fail; 1686 } 1687 pl->limit = pf_pool_limits[pl->index].limit; 1688 break; 1689 } 1690 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; 1355 1356 pf_status.debug = *level; 1357 break; 1358 } 1359 1360 case DIOCCLRRULECTRS: { 1361 struct pf_ruleset *ruleset = &pf_main_ruleset; 1362 struct pf_rule *rule; 1363 1364 s = splsoftnet(); 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; 1716 1717 pf_status.debug = *level; 1718 break; 1719 } 1720 1721 case DIOCCLRRULECTRS: { 1722 struct pf_ruleset *ruleset = &pf_main_ruleset; 1723 struct pf_rule *rule; 1724 1725 s = splsoftnet(); 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(); 1381 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 1382 if (altq->qname[0] == 0) { 1383 if ((ifp = ifunit(altq->ifname)) == NULL) { 1384 error = EINVAL; 1385 break; 1386 } 1387 if (ifp->if_snd.altq_type != ALTQT_NONE) 1388 error = altq_enable(&ifp->if_snd); 1389 if (error != 0) 1390 break; 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(); 1762 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 1763 if (altq->qname[0] == 0) { 1764 if ((ifp = ifunit(altq->ifname)) == NULL) { 1765 error = EINVAL; 1766 break; 1767 } 1768 if (ifp->if_snd.altq_type != ALTQT_NONE) 1769 error = altq_enable(&ifp->if_snd); 1770 if (error != 0) 1771 break; 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; 1409 struct tb_profile tb; 1410 int err; 1411 1412 /* disable all altq interfaces on active list */ 1413 s = splsoftnet(); 1414 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 1415 if (altq->qname[0] == 0) { 1416 if ((ifp = ifunit(altq->ifname)) == NULL) { 1417 error = EINVAL; 1418 break; 1419 } 1420 if (ifp->if_snd.altq_type != ALTQT_NONE) { 1421 err = altq_disable(&ifp->if_snd); 1422 if (err != 0 && error == 0) 1423 error = err; 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; 1798 struct tb_profile tb; 1799 int err; 1800 1801 /* disable all altq interfaces on active list */ 1802 s = splsoftnet(); 1803 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 1804 if (altq->qname[0] == 0) { 1805 if ((ifp = ifunit(altq->ifname)) == NULL) { 1806 error = EINVAL; 1807 break; 1808 } 1809 if (ifp->if_snd.altq_type != ALTQT_NONE) { 1810 err = altq_disable(&ifp->if_snd); 1811 if (err != 0 && error == 0) 1812 error = err; 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: { 1457 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1458 struct pf_altq *altq, *a; 1459 1460 if (pa->ticket != ticket_altqs_inactive) { 1461 error = EBUSY; 1462 break; 1463 } 1464 altq = pool_get(&pf_altq_pl, PR_NOWAIT); 1465 if (altq == NULL) { 1466 error = ENOMEM; 1467 break; 1468 } 1469 bcopy(&pa->altq, altq, sizeof(struct pf_altq)); 1470 1471 /* 1472 * if this is for a queue, find the discipline and 1473 * copy the necessary fields 1474 */ 1475 if (altq->qname[0] != 0) { 1476 TAILQ_FOREACH(a, pf_altqs_inactive, entries) { 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: { 1860 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1861 struct pf_altq *altq, *a; 1862 1863 if (pa->ticket != ticket_altqs_inactive) { 1864 error = EBUSY; 1865 break; 1866 } 1867 altq = pool_get(&pf_altq_pl, PR_NOWAIT); 1868 if (altq == NULL) { 1869 error = ENOMEM; 1870 break; 1871 } 1872 bcopy(&pa->altq, altq, sizeof(struct pf_altq)); 1873 1874 /* 1875 * if this is for a queue, find the discipline and 1876 * copy the necessary fields 1877 */ 1878 if (altq->qname[0] != 0) { 1879 TAILQ_FOREACH(a, pf_altqs_inactive, entries) { 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; 1494 } 1495 1496 case DIOCCOMMITALTQS: { 1497 u_int32_t *ticket = (u_int32_t *)addr; 1498 struct pf_altqqueue *old_altqs; 1499 struct pf_altq *altq; 1500 struct pf_anchor *anchor; 1501 struct pf_ruleset *ruleset; 1502 int err; 1503 1504 if (*ticket != ticket_altqs_inactive) { 1505 error = EBUSY; 1506 break; 1507 } 1508 1509 /* Swap altqs, keep the old. */ 1510 s = splsoftnet(); 1511 old_altqs = pf_altqs_active; 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; 1903 } 1904 1905 case DIOCCOMMITALTQS: { 1906 u_int32_t *ticket = (u_int32_t *)addr; 1907 struct pf_altqqueue *old_altqs; 1908 struct pf_altq *altq; 1909 struct pf_anchor *anchor; 1910 struct pf_ruleset *ruleset; 1911 int err; 1912 1913 if (*ticket != ticket_altqs_inactive) { 1914 error = EBUSY; 1915 break; 1916 } 1917 1918 /* Swap altqs, keep the old. */ 1919 s = splsoftnet(); 1920 old_altqs = pf_altqs_active; 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); 1547 TAILQ_FOREACH(anchor, &pf_anchors, entries) { 1548 TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) { 1549 pf_rule_set_qid( 1550 ruleset->rules[PF_RULESET_FILTER].active.ptr 1551 ); 1552 } 1553 } 1554 break; 1555 } 1556 1557 case DIOCGETALTQS: { 1558 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1559 struct pf_altq *altq; 1560 1561 pa->nr = 0; 1562 s = splsoftnet(); 1563 TAILQ_FOREACH(altq, pf_altqs_active, entries) 1564 pa->nr++; 1565 pa->ticket = ticket_altqs_active; 1566 splx(s); 1567 break; 1568 } 1569 1570 case DIOCGETALTQ: { 1571 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1572 struct pf_altq *altq; 1573 u_int32_t nr; 1574 1575 if (pa->ticket != ticket_altqs_active) { 1576 error = EBUSY; 1577 break; 1578 } 1579 nr = 0; 1580 s = splsoftnet(); 1581 altq = TAILQ_FIRST(pf_altqs_active); 1582 while ((altq != NULL) && (nr < pa->nr)) { 1583 altq = TAILQ_NEXT(altq, entries); 1584 nr++; 1585 } 1586 if (altq == NULL) { 1587 error = EBUSY; 1588 splx(s); 1589 break; 1590 } 1591 bcopy(altq, &pa->altq, sizeof(struct pf_altq)); 1592 splx(s); 1593 break; 1594 } 1595 1596 case DIOCCHANGEALTQ: 1597 /* CHANGEALTQ not supported yet! */ 1598 error = ENODEV; 1599 break; 1600 1601 case DIOCGETQSTATS: { 1602 struct pfioc_qstats *pq = (struct pfioc_qstats *)addr; 1603 struct pf_altq *altq; 1604 u_int32_t nr; 1605 int nbytes; 1606 1607 if (pq->ticket != ticket_altqs_active) { 1608 error = EBUSY; 1609 break; 1610 } 1611 nbytes = pq->nbytes; 1612 nr = 0; 1613 s = splsoftnet(); 1614 altq = TAILQ_FIRST(pf_altqs_active); 1615 while ((altq != NULL) && (nr < pq->nr)) { 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); 1968 TAILQ_FOREACH(anchor, &pf_anchors, entries) { 1969 TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) { 1970 pf_rule_set_qid( 1971 ruleset->rules[PF_RULESET_FILTER].active.ptr 1972 ); 1973 } 1974 } 1975 break; 1976 } 1977 1978 case DIOCGETALTQS: { 1979 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1980 struct pf_altq *altq; 1981 1982 pa->nr = 0; 1983 s = splsoftnet(); 1984 TAILQ_FOREACH(altq, pf_altqs_active, entries) 1985 pa->nr++; 1986 pa->ticket = ticket_altqs_active; 1987 splx(s); 1988 break; 1989 } 1990 1991 case DIOCGETALTQ: { 1992 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1993 struct pf_altq *altq; 1994 u_int32_t nr; 1995 1996 if (pa->ticket != ticket_altqs_active) { 1997 error = EBUSY; 1998 break; 1999 } 2000 nr = 0; 2001 s = splsoftnet(); 2002 altq = TAILQ_FIRST(pf_altqs_active); 2003 while ((altq != NULL) && (nr < pa->nr)) { 2004 altq = TAILQ_NEXT(altq, entries); 2005 nr++; 2006 } 2007 if (altq == NULL) { 2008 error = EBUSY; 2009 splx(s); 2010 break; 2011 } 2012 bcopy(altq, &pa->altq, sizeof(struct pf_altq)); 2013 splx(s); 2014 break; 2015 } 2016 2017 case DIOCCHANGEALTQ: 2018 /* CHANGEALTQ not supported yet! */ 2019 error = ENODEV; 2020 break; 2021 2022 case DIOCGETQSTATS: { 2023 struct pfioc_qstats *pq = (struct pfioc_qstats *)addr; 2024 struct pf_altq *altq; 2025 u_int32_t nr; 2026 int nbytes; 2027 2028 if (pq->ticket != ticket_altqs_active) { 2029 error = EBUSY; 2030 break; 2031 } 2032 nbytes = pq->nbytes; 2033 nr = 0; 2034 s = splsoftnet(); 2035 altq = TAILQ_FIRST(pf_altqs_active); 2036 while ((altq != NULL) && (nr < pq->nr)) { 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 */ 1633 1634 case DIOCBEGINADDRS: { 1635 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 1636 1637 pf_empty_pool(&pf_pabuf); 1638 pp->ticket = ++ticket_pabuf; 1639 break; 1640 } 1641 1642 case DIOCADDADDR: { 1643 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 1644 1645#ifndef INET 1646 if (pp->af == AF_INET) { 1647 error = EAFNOSUPPORT; 1648 break; 1649 } 1650#endif /* INET */ 1651#ifndef INET6 1652 if (pp->af == AF_INET6) { 1653 error = EAFNOSUPPORT; 1654 break; 1655 } 1656#endif /* INET6 */ 1657 if (pp->addr.addr.type != PF_ADDR_ADDRMASK && 1658 pp->addr.addr.type != PF_ADDR_DYNIFTL && 1659 pp->addr.addr.type != PF_ADDR_TABLE) { 1660 error = EINVAL; 1661 break; 1662 } 1663 pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT); 1664 if (pa == NULL) { 1665 error = ENOMEM; 1666 break; 1667 } 1668 bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr)); 1669 if (pa->ifname[0]) { 1670 pa->ifp = ifunit(pa->ifname); 1671 if (pa->ifp == NULL) { 1672 pool_put(&pf_pooladdr_pl, pa); 1673 error = EINVAL; 1674 break; 1675 } 1676 } 1677 if (pf_dynaddr_setup(&pa->addr, pp->af)) { 1678 pf_dynaddr_remove(&pa->addr); 1679 pool_put(&pf_pooladdr_pl, pa); 1680 error = EINVAL; 1681 break; 1682 } 1683 TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries); 1684 break; 1685 } 1686 1687 case DIOCGETADDRS: { 1688 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 1689 1690 pp->nr = 0; 1691 s = splsoftnet(); 1692 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket, 1693 pp->r_action, pp->r_num, 0, 1, 0); 1694 if (pool == NULL) { 1695 error = EBUSY; 1696 splx(s); 1697 break; 1698 } 1699 TAILQ_FOREACH(pa, &pool->list, entries) 1700 pp->nr++; 1701 splx(s); 1702 break; 1703 } 1704 1705 case DIOCGETADDR: { 1706 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 1707 u_int32_t nr = 0; 1708 1709 s = splsoftnet(); 1710 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket, 1711 pp->r_action, pp->r_num, 0, 1, 1); 1712 if (pool == NULL) { 1713 error = EBUSY; 1714 splx(s); 1715 break; 1716 } 1717 pa = TAILQ_FIRST(&pool->list); 1718 while ((pa != NULL) && (nr < pp->nr)) { 1719 pa = TAILQ_NEXT(pa, entries); 1720 nr++; 1721 } 1722 if (pa == NULL) { 1723 error = EBUSY; 1724 splx(s); 1725 break; 1726 } 1727 bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr)); 1728 pf_dynaddr_copyout(&pp->addr.addr); 1729 pf_tbladdr_copyout(&pp->addr.addr); 1730 splx(s); 1731 break; 1732 } 1733 1734 case DIOCCHANGEADDR: { 1735 struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; 1736 struct pf_pooladdr *oldpa = NULL, *newpa = NULL; 1737 struct pf_ruleset *ruleset; 1738 1739 if (pca->action < PF_CHANGE_ADD_HEAD || 1740 pca->action > PF_CHANGE_REMOVE) { 1741 error = EINVAL; 1742 break; 1743 } 1744 if (pca->addr.addr.type != PF_ADDR_ADDRMASK && 1745 pca->addr.addr.type != PF_ADDR_DYNIFTL && 1746 pca->addr.addr.type != PF_ADDR_TABLE) { 1747 error = EINVAL; 1748 break; 1749 } 1750 1751 ruleset = pf_find_ruleset(pca->anchor, pca->ruleset); 1752 if (ruleset == NULL) { 1753 error = EBUSY; 1754 break; 1755 } 1756 pool = pf_get_pool(pca->anchor, pca->ruleset, pca->ticket, 1757 pca->r_action, pca->r_num, pca->r_last, 1, 1); 1758 if (pool == NULL) { 1759 error = EBUSY; 1760 break; 1761 } 1762 if (pca->action != PF_CHANGE_REMOVE) { 1763 newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT); 1764 if (newpa == NULL) { 1765 error = ENOMEM; 1766 break; 1767 } 1768 bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr)); 1769#ifndef INET 1770 if (pca->af == AF_INET) { 1771 pool_put(&pf_pooladdr_pl, newpa); 1772 error = EAFNOSUPPORT; 1773 break; 1774 } 1775#endif /* INET */ 1776#ifndef INET6 1777 if (pca->af == AF_INET6) { 1778 pool_put(&pf_pooladdr_pl, newpa); 1779 error = EAFNOSUPPORT; 1780 break; 1781 } 1782#endif /* INET6 */ 1783 if (newpa->ifname[0]) { 1784 newpa->ifp = ifunit(newpa->ifname); 1785 if (newpa->ifp == NULL) { 1786 pool_put(&pf_pooladdr_pl, newpa); 1787 error = EINVAL; 1788 break; 1789 } 1790 } else 1791 newpa->ifp = NULL; 1792 if (pf_dynaddr_setup(&newpa->addr, pca->af) || 1793 pf_tbladdr_setup(ruleset, &newpa->addr)) { 1794 pf_dynaddr_remove(&newpa->addr); 1795 pool_put(&pf_pooladdr_pl, newpa); 1796 error = EINVAL; 1797 break; 1798 } 1799 } 1800 1801 s = splsoftnet(); 1802 1803 if (pca->action == PF_CHANGE_ADD_HEAD) 1804 oldpa = TAILQ_FIRST(&pool->list); 1805 else if (pca->action == PF_CHANGE_ADD_TAIL) 1806 oldpa = TAILQ_LAST(&pool->list, pf_palist); 1807 else { 1808 int i = 0; 1809 1810 oldpa = TAILQ_FIRST(&pool->list); 1811 while ((oldpa != NULL) && (i < pca->nr)) { 1812 oldpa = TAILQ_NEXT(oldpa, entries); 1813 i++; 1814 } 1815 if (oldpa == NULL) { 1816 error = EINVAL; 1817 splx(s); 1818 break; 1819 } 1820 } 1821 1822 if (pca->action == PF_CHANGE_REMOVE) { 1823 TAILQ_REMOVE(&pool->list, oldpa, entries); 1824 pf_dynaddr_remove(&oldpa->addr); 1825 pf_tbladdr_remove(&oldpa->addr); 1826 pool_put(&pf_pooladdr_pl, oldpa); 1827 } else { 1828 if (oldpa == NULL) 1829 TAILQ_INSERT_TAIL(&pool->list, newpa, entries); 1830 else if (pca->action == PF_CHANGE_ADD_HEAD || 1831 pca->action == PF_CHANGE_ADD_BEFORE) 1832 TAILQ_INSERT_BEFORE(oldpa, newpa, entries); 1833 else 1834 TAILQ_INSERT_AFTER(&pool->list, oldpa, 1835 newpa, entries); 1836 } 1837 1838 pool->cur = TAILQ_FIRST(&pool->list); 1839 PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, 1840 pca->af); 1841 splx(s); 1842 break; 1843 } 1844 1845 case DIOCGETANCHORS: { 1846 struct pfioc_anchor *pa = (struct pfioc_anchor *)addr; 1847 struct pf_anchor *anchor; 1848 1849 pa->nr = 0; 1850 TAILQ_FOREACH(anchor, &pf_anchors, entries) 1851 pa->nr++; 1852 break; 1853 } 1854 1855 case DIOCGETANCHOR: { 1856 struct pfioc_anchor *pa = (struct pfioc_anchor *)addr; 1857 struct pf_anchor *anchor; 1858 u_int32_t nr = 0; 1859 1860 anchor = TAILQ_FIRST(&pf_anchors); 1861 while (anchor != NULL && nr < pa->nr) { 1862 anchor = TAILQ_NEXT(anchor, entries); 1863 nr++; 1864 } 1865 if (anchor == NULL) 1866 error = EBUSY; 1867 else 1868 bcopy(anchor->name, pa->name, sizeof(pa->name)); 1869 break; 1870 } 1871 1872 case DIOCGETRULESETS: { 1873 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; 1874 struct pf_anchor *anchor; 1875 struct pf_ruleset *ruleset; 1876 1877 pr->anchor[PF_ANCHOR_NAME_SIZE-1] = 0; 1878 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) { 1879 error = EINVAL; 1880 break; 1881 } 1882 pr->nr = 0; 1883 TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) 1884 pr->nr++; 1885 break; 1886 } 1887 1888 case DIOCGETRULESET: { 1889 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; 1890 struct pf_anchor *anchor; 1891 struct pf_ruleset *ruleset; 1892 u_int32_t nr = 0; 1893 1894 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) { 1895 error = EINVAL; 1896 break; 1897 } 1898 ruleset = TAILQ_FIRST(&anchor->rulesets); 1899 while (ruleset != NULL && nr < pr->nr) { 1900 ruleset = TAILQ_NEXT(ruleset, entries); 1901 nr++; 1902 } 1903 if (ruleset == NULL) 1904 error = EBUSY; 1905 else 1906 bcopy(ruleset->name, pr->name, sizeof(pr->name)); 1907 break; 1908 } 1909 1910 case DIOCRCLRTABLES: { 1911 struct pfioc_table *io = (struct pfioc_table *)addr; 1912 1913 if (io->pfrio_esize != 0) { 1914 error = ENODEV; 1915 break; 1916 } 1917 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, 1918 io->pfrio_flags); 1919 break; 1920 } 1921 1922 case DIOCRADDTABLES: { 1923 struct pfioc_table *io = (struct pfioc_table *)addr; 1924 1925 if (io->pfrio_esize != sizeof(struct pfr_table)) { 1926 error = ENODEV; 1927 break; 1928 } 1929 error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size, 1930 &io->pfrio_nadd, io->pfrio_flags); 1931 break; 1932 } 1933 1934 case DIOCRDELTABLES: { 1935 struct pfioc_table *io = (struct pfioc_table *)addr; 1936 1937 if (io->pfrio_esize != sizeof(struct pfr_table)) { 1938 error = ENODEV; 1939 break; 1940 } 1941 error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size, 1942 &io->pfrio_ndel, io->pfrio_flags); 1943 break; 1944 } 1945 1946 case DIOCRGETTABLES: { 1947 struct pfioc_table *io = (struct pfioc_table *)addr; 1948 1949 if (io->pfrio_esize != sizeof(struct pfr_table)) { 1950 error = ENODEV; 1951 break; 1952 } 1953 error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer, 1954 &io->pfrio_size, io->pfrio_flags); 1955 break; 1956 } 1957 1958 case DIOCRGETTSTATS: { 1959 struct pfioc_table *io = (struct pfioc_table *)addr; 1960 1961 if (io->pfrio_esize != sizeof(struct pfr_tstats)) { 1962 error = ENODEV; 1963 break; 1964 } 1965 error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer, 1966 &io->pfrio_size, io->pfrio_flags); 1967 break; 1968 } 1969 1970 case DIOCRCLRTSTATS: { 1971 struct pfioc_table *io = (struct pfioc_table *)addr; 1972 1973 if (io->pfrio_esize != sizeof(struct pfr_table)) { 1974 error = ENODEV; 1975 break; 1976 } 1977 error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size, 1978 &io->pfrio_nzero, io->pfrio_flags); 1979 break; 1980 } 1981 1982 case DIOCRSETTFLAGS: { 1983 struct pfioc_table *io = (struct pfioc_table *)addr; 1984 1985 if (io->pfrio_esize != sizeof(struct pfr_table)) { 1986 error = ENODEV; 1987 break; 1988 } 1989 error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size, 1990 io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange, 1991 &io->pfrio_ndel, io->pfrio_flags); 1992 break; 1993 } 1994 1995 case DIOCRCLRADDRS: { 1996 struct pfioc_table *io = (struct pfioc_table *)addr; 1997 1998 if (io->pfrio_esize != 0) { 1999 error = ENODEV; 2000 break; 2001 } 2002 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel, 2003 io->pfrio_flags); 2004 break; 2005 } 2006 2007 case DIOCRADDADDRS: { 2008 struct pfioc_table *io = (struct pfioc_table *)addr; 2009 2010 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2011 error = ENODEV; 2012 break; 2013 } 2014 error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer, 2015 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags); 2016 break; 2017 } 2018 2019 case DIOCRDELADDRS: { 2020 struct pfioc_table *io = (struct pfioc_table *)addr; 2021 2022 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2023 error = ENODEV; 2024 break; 2025 } 2026 error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer, 2027 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags); 2028 break; 2029 } 2030 2031 case DIOCRSETADDRS: { 2032 struct pfioc_table *io = (struct pfioc_table *)addr; 2033 2034 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2035 error = ENODEV; 2036 break; 2037 } 2038 error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer, 2039 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd, 2040 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags); 2041 break; 2042 } 2043 2044 case DIOCRGETADDRS: { 2045 struct pfioc_table *io = (struct pfioc_table *)addr; 2046 2047 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2048 error = ENODEV; 2049 break; 2050 } 2051 error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer, 2052 &io->pfrio_size, io->pfrio_flags); 2053 break; 2054 } 2055 2056 case DIOCRGETASTATS: { 2057 struct pfioc_table *io = (struct pfioc_table *)addr; 2058 2059 if (io->pfrio_esize != sizeof(struct pfr_astats)) { 2060 error = ENODEV; 2061 break; 2062 } 2063 error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer, 2064 &io->pfrio_size, io->pfrio_flags); 2065 break; 2066 } 2067 2068 case DIOCRCLRASTATS: { 2069 struct pfioc_table *io = (struct pfioc_table *)addr; 2070 2071 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2072 error = ENODEV; 2073 break; 2074 } 2075 error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer, 2076 io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags); 2077 break; 2078 } 2079 2080 case DIOCRTSTADDRS: { 2081 struct pfioc_table *io = (struct pfioc_table *)addr; 2082 2083 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2084 error = ENODEV; 2085 break; 2086 } 2087 error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer, 2088 io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags); 2089 break; 2090 } 2091 2092 case DIOCRINABEGIN: { 2093 struct pfioc_table *io = (struct pfioc_table *)addr; 2094 2095 if (io->pfrio_esize != 0) { 2096 error = ENODEV; 2097 break; 2098 } 2099 error = pfr_ina_begin(&io->pfrio_table, &io->pfrio_ticket, 2100 &io->pfrio_ndel, io->pfrio_flags); 2101 break; 2102 } 2103 2104 case DIOCRINACOMMIT: { 2105 struct pfioc_table *io = (struct pfioc_table *)addr; 2106 2107 if (io->pfrio_esize != 0) { 2108 error = ENODEV; 2109 break; 2110 } 2111 error = pfr_ina_commit(&io->pfrio_table, io->pfrio_ticket, 2112 &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags); 2113 break; 2114 } 2115 2116 case DIOCRINADEFINE: { 2117 struct pfioc_table *io = (struct pfioc_table *)addr; 2118 2119 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2120 error = ENODEV; 2121 break; 2122 } 2123 error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer, 2124 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr, 2125 io->pfrio_ticket, io->pfrio_flags); 2126 break; 2127 } 2128 2129 case DIOCOSFPFLUSH: 2130 s = splsoftnet(); 2131 pf_osfp_flush(); 2132 splx(s); 2133 break; 2134 2135 case DIOCOSFPADD: { 2136 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; 2137 s = splsoftnet(); 2138 error = pf_osfp_add(io); 2139 splx(s); 2140 break; 2141 } 2142 2143 case DIOCOSFPGET: { 2144 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; 2145 s = splsoftnet(); 2146 error = pf_osfp_get(io); 2147 splx(s); 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 */ 2060 2061 case DIOCBEGINADDRS: { 2062 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 2063 2064 pf_empty_pool(&pf_pabuf); 2065 pp->ticket = ++ticket_pabuf; 2066 break; 2067 } 2068 2069 case DIOCADDADDR: { 2070 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 2071 2072#ifndef INET 2073 if (pp->af == AF_INET) { 2074 error = EAFNOSUPPORT; 2075 break; 2076 } 2077#endif /* INET */ 2078#ifndef INET6 2079 if (pp->af == AF_INET6) { 2080 error = EAFNOSUPPORT; 2081 break; 2082 } 2083#endif /* INET6 */ 2084 if (pp->addr.addr.type != PF_ADDR_ADDRMASK && 2085 pp->addr.addr.type != PF_ADDR_DYNIFTL && 2086 pp->addr.addr.type != PF_ADDR_TABLE) { 2087 error = EINVAL; 2088 break; 2089 } 2090 pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT); 2091 if (pa == NULL) { 2092 error = ENOMEM; 2093 break; 2094 } 2095 bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr)); 2096 if (pa->ifname[0]) { 2097 pa->ifp = ifunit(pa->ifname); 2098 if (pa->ifp == NULL) { 2099 pool_put(&pf_pooladdr_pl, pa); 2100 error = EINVAL; 2101 break; 2102 } 2103 } 2104 if (pf_dynaddr_setup(&pa->addr, pp->af)) { 2105 pf_dynaddr_remove(&pa->addr); 2106 pool_put(&pf_pooladdr_pl, pa); 2107 error = EINVAL; 2108 break; 2109 } 2110 TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries); 2111 break; 2112 } 2113 2114 case DIOCGETADDRS: { 2115 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 2116 2117 pp->nr = 0; 2118 s = splsoftnet(); 2119 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket, 2120 pp->r_action, pp->r_num, 0, 1, 0); 2121 if (pool == NULL) { 2122 error = EBUSY; 2123 splx(s); 2124 break; 2125 } 2126 TAILQ_FOREACH(pa, &pool->list, entries) 2127 pp->nr++; 2128 splx(s); 2129 break; 2130 } 2131 2132 case DIOCGETADDR: { 2133 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 2134 u_int32_t nr = 0; 2135 2136 s = splsoftnet(); 2137 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket, 2138 pp->r_action, pp->r_num, 0, 1, 1); 2139 if (pool == NULL) { 2140 error = EBUSY; 2141 splx(s); 2142 break; 2143 } 2144 pa = TAILQ_FIRST(&pool->list); 2145 while ((pa != NULL) && (nr < pp->nr)) { 2146 pa = TAILQ_NEXT(pa, entries); 2147 nr++; 2148 } 2149 if (pa == NULL) { 2150 error = EBUSY; 2151 splx(s); 2152 break; 2153 } 2154 bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr)); 2155 pf_dynaddr_copyout(&pp->addr.addr); 2156 pf_tbladdr_copyout(&pp->addr.addr); 2157 splx(s); 2158 break; 2159 } 2160 2161 case DIOCCHANGEADDR: { 2162 struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; 2163 struct pf_pooladdr *oldpa = NULL, *newpa = NULL; 2164 struct pf_ruleset *ruleset; 2165 2166 if (pca->action < PF_CHANGE_ADD_HEAD || 2167 pca->action > PF_CHANGE_REMOVE) { 2168 error = EINVAL; 2169 break; 2170 } 2171 if (pca->addr.addr.type != PF_ADDR_ADDRMASK && 2172 pca->addr.addr.type != PF_ADDR_DYNIFTL && 2173 pca->addr.addr.type != PF_ADDR_TABLE) { 2174 error = EINVAL; 2175 break; 2176 } 2177 2178 ruleset = pf_find_ruleset(pca->anchor, pca->ruleset); 2179 if (ruleset == NULL) { 2180 error = EBUSY; 2181 break; 2182 } 2183 pool = pf_get_pool(pca->anchor, pca->ruleset, pca->ticket, 2184 pca->r_action, pca->r_num, pca->r_last, 1, 1); 2185 if (pool == NULL) { 2186 error = EBUSY; 2187 break; 2188 } 2189 if (pca->action != PF_CHANGE_REMOVE) { 2190 newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT); 2191 if (newpa == NULL) { 2192 error = ENOMEM; 2193 break; 2194 } 2195 bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr)); 2196#ifndef INET 2197 if (pca->af == AF_INET) { 2198 pool_put(&pf_pooladdr_pl, newpa); 2199 error = EAFNOSUPPORT; 2200 break; 2201 } 2202#endif /* INET */ 2203#ifndef INET6 2204 if (pca->af == AF_INET6) { 2205 pool_put(&pf_pooladdr_pl, newpa); 2206 error = EAFNOSUPPORT; 2207 break; 2208 } 2209#endif /* INET6 */ 2210 if (newpa->ifname[0]) { 2211 newpa->ifp = ifunit(newpa->ifname); 2212 if (newpa->ifp == NULL) { 2213 pool_put(&pf_pooladdr_pl, newpa); 2214 error = EINVAL; 2215 break; 2216 } 2217 } else 2218 newpa->ifp = NULL; 2219 if (pf_dynaddr_setup(&newpa->addr, pca->af) || 2220 pf_tbladdr_setup(ruleset, &newpa->addr)) { 2221 pf_dynaddr_remove(&newpa->addr); 2222 pool_put(&pf_pooladdr_pl, newpa); 2223 error = EINVAL; 2224 break; 2225 } 2226 } 2227 2228 s = splsoftnet(); 2229 2230 if (pca->action == PF_CHANGE_ADD_HEAD) 2231 oldpa = TAILQ_FIRST(&pool->list); 2232 else if (pca->action == PF_CHANGE_ADD_TAIL) 2233 oldpa = TAILQ_LAST(&pool->list, pf_palist); 2234 else { 2235 int i = 0; 2236 2237 oldpa = TAILQ_FIRST(&pool->list); 2238 while ((oldpa != NULL) && (i < pca->nr)) { 2239 oldpa = TAILQ_NEXT(oldpa, entries); 2240 i++; 2241 } 2242 if (oldpa == NULL) { 2243 error = EINVAL; 2244 splx(s); 2245 break; 2246 } 2247 } 2248 2249 if (pca->action == PF_CHANGE_REMOVE) { 2250 TAILQ_REMOVE(&pool->list, oldpa, entries); 2251 pf_dynaddr_remove(&oldpa->addr); 2252 pf_tbladdr_remove(&oldpa->addr); 2253 pool_put(&pf_pooladdr_pl, oldpa); 2254 } else { 2255 if (oldpa == NULL) 2256 TAILQ_INSERT_TAIL(&pool->list, newpa, entries); 2257 else if (pca->action == PF_CHANGE_ADD_HEAD || 2258 pca->action == PF_CHANGE_ADD_BEFORE) 2259 TAILQ_INSERT_BEFORE(oldpa, newpa, entries); 2260 else 2261 TAILQ_INSERT_AFTER(&pool->list, oldpa, 2262 newpa, entries); 2263 } 2264 2265 pool->cur = TAILQ_FIRST(&pool->list); 2266 PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, 2267 pca->af); 2268 splx(s); 2269 break; 2270 } 2271 2272 case DIOCGETANCHORS: { 2273 struct pfioc_anchor *pa = (struct pfioc_anchor *)addr; 2274 struct pf_anchor *anchor; 2275 2276 pa->nr = 0; 2277 TAILQ_FOREACH(anchor, &pf_anchors, entries) 2278 pa->nr++; 2279 break; 2280 } 2281 2282 case DIOCGETANCHOR: { 2283 struct pfioc_anchor *pa = (struct pfioc_anchor *)addr; 2284 struct pf_anchor *anchor; 2285 u_int32_t nr = 0; 2286 2287 anchor = TAILQ_FIRST(&pf_anchors); 2288 while (anchor != NULL && nr < pa->nr) { 2289 anchor = TAILQ_NEXT(anchor, entries); 2290 nr++; 2291 } 2292 if (anchor == NULL) 2293 error = EBUSY; 2294 else 2295 bcopy(anchor->name, pa->name, sizeof(pa->name)); 2296 break; 2297 } 2298 2299 case DIOCGETRULESETS: { 2300 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; 2301 struct pf_anchor *anchor; 2302 struct pf_ruleset *ruleset; 2303 2304 pr->anchor[PF_ANCHOR_NAME_SIZE-1] = 0; 2305 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) { 2306 error = EINVAL; 2307 break; 2308 } 2309 pr->nr = 0; 2310 TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) 2311 pr->nr++; 2312 break; 2313 } 2314 2315 case DIOCGETRULESET: { 2316 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; 2317 struct pf_anchor *anchor; 2318 struct pf_ruleset *ruleset; 2319 u_int32_t nr = 0; 2320 2321 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) { 2322 error = EINVAL; 2323 break; 2324 } 2325 ruleset = TAILQ_FIRST(&anchor->rulesets); 2326 while (ruleset != NULL && nr < pr->nr) { 2327 ruleset = TAILQ_NEXT(ruleset, entries); 2328 nr++; 2329 } 2330 if (ruleset == NULL) 2331 error = EBUSY; 2332 else 2333 bcopy(ruleset->name, pr->name, sizeof(pr->name)); 2334 break; 2335 } 2336 2337 case DIOCRCLRTABLES: { 2338 struct pfioc_table *io = (struct pfioc_table *)addr; 2339 2340 if (io->pfrio_esize != 0) { 2341 error = ENODEV; 2342 break; 2343 } 2344 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, 2345 io->pfrio_flags); 2346 break; 2347 } 2348 2349 case DIOCRADDTABLES: { 2350 struct pfioc_table *io = (struct pfioc_table *)addr; 2351 2352 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2353 error = ENODEV; 2354 break; 2355 } 2356 error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size, 2357 &io->pfrio_nadd, io->pfrio_flags); 2358 break; 2359 } 2360 2361 case DIOCRDELTABLES: { 2362 struct pfioc_table *io = (struct pfioc_table *)addr; 2363 2364 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2365 error = ENODEV; 2366 break; 2367 } 2368 error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size, 2369 &io->pfrio_ndel, io->pfrio_flags); 2370 break; 2371 } 2372 2373 case DIOCRGETTABLES: { 2374 struct pfioc_table *io = (struct pfioc_table *)addr; 2375 2376 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2377 error = ENODEV; 2378 break; 2379 } 2380 error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer, 2381 &io->pfrio_size, io->pfrio_flags); 2382 break; 2383 } 2384 2385 case DIOCRGETTSTATS: { 2386 struct pfioc_table *io = (struct pfioc_table *)addr; 2387 2388 if (io->pfrio_esize != sizeof(struct pfr_tstats)) { 2389 error = ENODEV; 2390 break; 2391 } 2392 error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer, 2393 &io->pfrio_size, io->pfrio_flags); 2394 break; 2395 } 2396 2397 case DIOCRCLRTSTATS: { 2398 struct pfioc_table *io = (struct pfioc_table *)addr; 2399 2400 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2401 error = ENODEV; 2402 break; 2403 } 2404 error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size, 2405 &io->pfrio_nzero, io->pfrio_flags); 2406 break; 2407 } 2408 2409 case DIOCRSETTFLAGS: { 2410 struct pfioc_table *io = (struct pfioc_table *)addr; 2411 2412 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2413 error = ENODEV; 2414 break; 2415 } 2416 error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size, 2417 io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange, 2418 &io->pfrio_ndel, io->pfrio_flags); 2419 break; 2420 } 2421 2422 case DIOCRCLRADDRS: { 2423 struct pfioc_table *io = (struct pfioc_table *)addr; 2424 2425 if (io->pfrio_esize != 0) { 2426 error = ENODEV; 2427 break; 2428 } 2429 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel, 2430 io->pfrio_flags); 2431 break; 2432 } 2433 2434 case DIOCRADDADDRS: { 2435 struct pfioc_table *io = (struct pfioc_table *)addr; 2436 2437 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2438 error = ENODEV; 2439 break; 2440 } 2441 error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer, 2442 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags); 2443 break; 2444 } 2445 2446 case DIOCRDELADDRS: { 2447 struct pfioc_table *io = (struct pfioc_table *)addr; 2448 2449 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2450 error = ENODEV; 2451 break; 2452 } 2453 error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer, 2454 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags); 2455 break; 2456 } 2457 2458 case DIOCRSETADDRS: { 2459 struct pfioc_table *io = (struct pfioc_table *)addr; 2460 2461 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2462 error = ENODEV; 2463 break; 2464 } 2465 error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer, 2466 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd, 2467 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags); 2468 break; 2469 } 2470 2471 case DIOCRGETADDRS: { 2472 struct pfioc_table *io = (struct pfioc_table *)addr; 2473 2474 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2475 error = ENODEV; 2476 break; 2477 } 2478 error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer, 2479 &io->pfrio_size, io->pfrio_flags); 2480 break; 2481 } 2482 2483 case DIOCRGETASTATS: { 2484 struct pfioc_table *io = (struct pfioc_table *)addr; 2485 2486 if (io->pfrio_esize != sizeof(struct pfr_astats)) { 2487 error = ENODEV; 2488 break; 2489 } 2490 error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer, 2491 &io->pfrio_size, io->pfrio_flags); 2492 break; 2493 } 2494 2495 case DIOCRCLRASTATS: { 2496 struct pfioc_table *io = (struct pfioc_table *)addr; 2497 2498 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2499 error = ENODEV; 2500 break; 2501 } 2502 error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer, 2503 io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags); 2504 break; 2505 } 2506 2507 case DIOCRTSTADDRS: { 2508 struct pfioc_table *io = (struct pfioc_table *)addr; 2509 2510 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2511 error = ENODEV; 2512 break; 2513 } 2514 error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer, 2515 io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags); 2516 break; 2517 } 2518 2519 case DIOCRINABEGIN: { 2520 struct pfioc_table *io = (struct pfioc_table *)addr; 2521 2522 if (io->pfrio_esize != 0) { 2523 error = ENODEV; 2524 break; 2525 } 2526 error = pfr_ina_begin(&io->pfrio_table, &io->pfrio_ticket, 2527 &io->pfrio_ndel, io->pfrio_flags); 2528 break; 2529 } 2530 2531 case DIOCRINACOMMIT: { 2532 struct pfioc_table *io = (struct pfioc_table *)addr; 2533 2534 if (io->pfrio_esize != 0) { 2535 error = ENODEV; 2536 break; 2537 } 2538 error = pfr_ina_commit(&io->pfrio_table, io->pfrio_ticket, 2539 &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags); 2540 break; 2541 } 2542 2543 case DIOCRINADEFINE: { 2544 struct pfioc_table *io = (struct pfioc_table *)addr; 2545 2546 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2547 error = ENODEV; 2548 break; 2549 } 2550 error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer, 2551 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr, 2552 io->pfrio_ticket, io->pfrio_flags); 2553 break; 2554 } 2555 2556 case DIOCOSFPFLUSH: 2557 s = splsoftnet(); 2558 pf_osfp_flush(); 2559 splx(s); 2560 break; 2561 2562 case DIOCOSFPADD: { 2563 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; 2564 s = splsoftnet(); 2565 error = pf_osfp_add(io); 2566 splx(s); 2567 break; 2568 } 2569 2570 case DIOCOSFPGET: { 2571 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; 2572 s = splsoftnet(); 2573 error = pf_osfp_get(io); 2574 splx(s); 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__ */
|
| |