1/* $FreeBSD: head/sys/contrib/pf/net/pf_ioctl.c 126261 2004-02-26 02:34:12Z mlaier $ */ |
2/* $OpenBSD: pf_ioctl.c,v 1.81 2003/08/22 21:50:34 david Exp $ */ 3 4/* 5 * Copyright (c) 2001 Daniel Hartmeier 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions --- 20 unchanged lines hidden (view full) --- 30 * POSSIBILITY OF SUCH DAMAGE. 31 * 32 * Effort sponsored in part by the Defense Advanced Research Projects 33 * Agency (DARPA) and Air Force Research Laboratory, Air Force 34 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 35 * 36 */ 37 |
38#if defined(__FreeBSD__) 39#include "opt_inet.h" 40#include "opt_inet6.h" 41#endif 42 |
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 |
56#include <sys/timeout.h> 57#include <sys/pool.h> |
58#endif |
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 |
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 |
104void pfattach(int); 105int pfopen(dev_t, int, int, struct proc *); 106int pfclose(dev_t, int, int, struct proc *); |
107#endif |
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 |
117int pfioctl(dev_t, u_long, caddr_t, int, struct proc *); |
118#endif |
119 |
120#if defined(__FreeBSD__) 121extern struct callout pf_expire_to; 122#if __FreeBSD_version < 501108 123extern struct protosw inetsw[]; 124#endif 125#else |
126extern struct timeout pf_expire_to; |
127#endif |
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 |
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 |
375pfattach(int num) 376{ 377 u_int32_t *timeout = pf_default_rule.timeout; 378 379 pool_init(&pf_tree_pl, sizeof(struct pf_tree_node), 0, 0, 0, "pftrpl", 380 NULL); 381 pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl", 382 &pool_allocator_nointr); --- 23 unchanged lines hidden (view full) --- 406 407 /* default rule should never be garbage collected */ 408 pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next; 409 pf_default_rule.action = PF_PASS; 410 pf_default_rule.nr = -1; 411 412 /* initialize default timeouts */ 413 timeout[PFTM_TCP_FIRST_PACKET] = 120; /* First TCP packet */ |
414 timeout[PFTM_TCP_OPENING] = 30; /* No response yet */ |
415 timeout[PFTM_TCP_ESTABLISHED] = 24*60*60; /* Established */ 416 timeout[PFTM_TCP_CLOSING] = 15 * 60; /* Half closed */ 417 timeout[PFTM_TCP_FIN_WAIT] = 45; /* Got both FINs */ 418 timeout[PFTM_TCP_CLOSED] = 90; /* Got a RST */ 419 timeout[PFTM_UDP_FIRST_PACKET] = 60; /* First UDP packet */ 420 timeout[PFTM_UDP_SINGLE] = 30; /* Unidirectional */ 421 timeout[PFTM_UDP_MULTIPLE] = 60; /* Bidirectional */ 422 timeout[PFTM_ICMP_FIRST_PACKET] = 20; /* First ICMP packet */ --- 5 unchanged lines hidden (view full) --- 428 timeout[PFTM_INTERVAL] = 10; /* Expire interval */ 429 430 timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to); 431 timeout_add(&pf_expire_to, timeout[PFTM_INTERVAL] * hz); 432 433 pf_normalize_init(); 434 pf_status.debug = PF_DEBUG_URGENT; 435} |
436#endif /* __FreeBSD__ */ |
437 |
438#if !defined(__FreeBSD__) |
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 |
447 |
448#if !defined(__FreeBSD__) |
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 |
457 458struct pf_pool * 459pf_get_pool(char *anchorname, char *rulesetname, u_int32_t ticket, 460 u_int8_t rule_action, u_int8_t rule_number, u_int8_t r_last, 461 u_int8_t active, u_int8_t check_ticket) 462{ 463 struct pf_ruleset *ruleset; 464 struct pf_rule *rule; --- 166 unchanged lines hidden (view full) --- 631} 632 633void 634pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset) 635{ 636 struct pf_anchor *anchor; 637 int i; 638 |
639 if (ruleset == NULL || ruleset->anchor == NULL || ruleset->tables > 0 || 640 ruleset->topen) |
641 return; 642 for (i = 0; i < PF_RULESET_MAX; ++i) 643 if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) || 644 !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr)) 645 return; 646 647 anchor = ruleset->anchor; 648 TAILQ_REMOVE(&anchor->rulesets, ruleset, entries); --- 132 unchanged lines hidden (view full) --- 781 TAILQ_REMOVE(&pf_tags, p, entries); 782 free(p, M_TEMP); 783 } 784 break; 785 } 786 } 787} 788 |
789#if defined(__FreeBSD__) |
790int |
791pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td) 792#else 793int |
794pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) |
795#endif |
796{ 797 struct pf_pooladdr *pa = NULL; 798 struct pf_pool *pool = NULL; 799 int s; 800 int error = 0; 801 802 /* XXX keep in sync with switch() below */ 803 if (securelevel > 1) --- 26 unchanged lines hidden (view full) --- 830 case DIOCRADDADDRS: 831 case DIOCRDELADDRS: 832 case DIOCRSETADDRS: 833 case DIOCRGETADDRS: 834 case DIOCRGETASTATS: 835 case DIOCRCLRASTATS: 836 case DIOCRTSTADDRS: 837 case DIOCOSFPGET: |
838#if defined(__FreeBSD__) 839 case DIOCGIFSPEED: 840#endif |
841 break; 842 default: 843 return (EPERM); 844 } 845 846 if (!(flags & FWRITE)) 847 switch (cmd) { 848 case DIOCGETRULES: --- 13 unchanged lines hidden (view full) --- 862 case DIOCGETRULESETS: 863 case DIOCGETRULESET: 864 case DIOCRGETTABLES: 865 case DIOCRGETTSTATS: 866 case DIOCRGETADDRS: 867 case DIOCRGETASTATS: 868 case DIOCRTSTADDRS: 869 case DIOCOSFPGET: |
870#if defined(__FreeBSD__) 871 case DIOCGIFSPEED: 872#endif |
873 break; 874 default: 875 return (EACCES); 876 } 877 |
878#if defined(__FreeBSD__) 879 PF_LOCK(); 880#endif 881 |
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 |
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 |
905 pf_status.since = time.tv_sec; |
906#endif |
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 |
912 strlcpy(pf_status.ifname, 913 status_ifp->if_xname, IFNAMSIZ); |
914#endif |
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 |
934 DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); 935 } 936 break; 937 938 case DIOCBEGINRULES: { 939 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 940 struct pf_ruleset *ruleset; 941 struct pf_rule *rule; --- 493 unchanged lines hidden (view full) --- 1435 break; 1436 } 1437 s = splsoftnet(); 1438 bcopy(&ps->state, state, sizeof(struct pf_state)); 1439 state->rule.ptr = NULL; 1440 state->nat_rule.ptr = NULL; 1441 state->anchor.ptr = NULL; 1442 state->rt_ifp = NULL; |
1443#if defined(__FreeBSD__) 1444 state->creation = time_second; 1445#else |
1446 state->creation = time.tv_sec; |
1447#endif |
1448 state->packets[0] = state->packets[1] = 0; 1449 state->bytes[0] = state->bytes[1] = 0; 1450 if (pf_insert_state(state)) { 1451 pool_put(&pf_state_pl, state); 1452 error = ENOMEM; 1453 } 1454 splx(s); 1455 break; --- 19 unchanged lines hidden (view full) --- 1475 bcopy(n->state, &ps->state, sizeof(struct pf_state)); 1476 ps->state.rule.nr = n->state->rule.ptr->nr; 1477 ps->state.nat_rule.nr = (n->state->nat_rule.ptr == NULL) ? 1478 -1 : n->state->nat_rule.ptr->nr; 1479 ps->state.anchor.nr = (n->state->anchor.ptr == NULL) ? 1480 -1 : n->state->anchor.ptr->nr; 1481 splx(s); 1482 ps->state.expire = pf_state_expires(n->state); |
1483#if defined(__FreeBSD__) 1484 if (ps->state.expire > time_second) 1485 ps->state.expire -= time_second; 1486#else |
1487 if (ps->state.expire > time.tv_sec) 1488 ps->state.expire -= time.tv_sec; |
1489#endif |
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 |
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 |
1520 int secs = time.tv_sec; |
1521#endif |
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 |
1541 error = copyout(&pstore, p, sizeof(*p)); |
1542#endif |
1543 if (error) { 1544 splx(s); 1545 goto fail; 1546 } 1547 p++; 1548 nr++; 1549 } 1550 ps->ps_len = sizeof(struct pf_state) * nr; --- 32 unchanged lines hidden (view full) --- 1583 u_int32_t debug = pf_status.debug; 1584 1585 bzero(&pf_status, sizeof(struct pf_status)); 1586 pf_status.running = running; 1587 pf_status.states = states; 1588 pf_status.since = since; 1589 pf_status.debug = debug; 1590 if (status_ifp != NULL) |
1591#if defined(__FreeBSD__) && (__FreeBSD_version < 501113) 1592 snprintf(pf_status.ifname, IFNAMSIZ, "%s%d", 1593 status_ifp->if_name, status_ifp->if_unit); 1594#else |
1595 strlcpy(pf_status.ifname, 1596 status_ifp->if_xname, IFNAMSIZ); |
1597#endif |
1598 break; 1599 } 1600 1601 case DIOCNATLOOK: { 1602 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr; 1603 struct pf_state *st; 1604 struct pf_tree_node key; 1605 int direction = pnl->direction; --- 85 unchanged lines hidden (view full) --- 1691 case DIOCSETLIMIT: { 1692 struct pfioc_limit *pl = (struct pfioc_limit *)addr; 1693 int old_limit; 1694 1695 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) { 1696 error = EINVAL; 1697 goto fail; 1698 } |
1699#if defined(__FreeBSD__) 1700 uma_zone_set_max(pf_pool_limits[pl->index].pp, pl->limit); 1701#else |
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 |
1708 old_limit = pf_pool_limits[pl->index].limit; 1709 pf_pool_limits[pl->index].limit = pl->limit; 1710 pl->limit = old_limit; 1711 break; 1712 } 1713 1714 case DIOCSETDEBUG: { 1715 u_int32_t *level = (u_int32_t *)addr; --- 10 unchanged lines hidden (view full) --- 1726 TAILQ_FOREACH(rule, 1727 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) 1728 rule->evaluations = rule->packets = 1729 rule->bytes = 0; 1730 splx(s); 1731 break; 1732 } 1733 |
1734#if defined(__FreeBSD__) 1735 case DIOCGIFSPEED: { 1736 struct pf_ifspeed *psp = (struct pf_ifspeed *)addr; 1737 struct pf_ifspeed ps; 1738 struct ifnet *ifp; 1739 1740 if (psp->ifname[0] != 0) { 1741 /* Can we completely trust user-land? */ 1742 strlcpy(ps.ifname, psp->ifname, IFNAMSIZ); 1743 ifp = ifunit(ps.ifname); 1744 if (ifp ) 1745 psp->baudrate = ifp->if_baudrate; 1746 else 1747 error = EINVAL; 1748 } else 1749 error = EINVAL; 1750 break; 1751 } 1752#endif /* __FreeBSD__ */ 1753 |
1754#ifdef ALTQ 1755 case DIOCSTARTALTQ: { 1756 struct pf_altq *altq; 1757 struct ifnet *ifp; 1758 struct tb_profile tb; 1759 1760 /* enable all altq interfaces on active list */ 1761 s = splsoftnet(); --- 10 unchanged lines hidden (view full) --- 1772 /* set tokenbucket regulator */ 1773 tb.rate = altq->ifbandwidth; 1774 tb.depth = altq->tbrsize; 1775 error = tbr_set(&ifp->if_snd, &tb); 1776 if (error != 0) 1777 break; 1778 } 1779 } |
1780#if defined(__FreeBSD__) 1781 if (error == 0) { 1782 mtx_lock(&pf_altq_mtx); 1783 pfaltq_running = 1; 1784 mtx_unlock(&pf_altq_mtx); 1785 } 1786#else |
1787 if (error == 0) 1788 pfaltq_running = 1; |
1789#endif |
1790 splx(s); 1791 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n")); 1792 break; 1793 } 1794 1795 case DIOCSTOPALTQ: { 1796 struct pf_altq *altq; 1797 struct ifnet *ifp; --- 15 unchanged lines hidden (view full) --- 1813 } 1814 /* clear tokenbucket regulator */ 1815 tb.rate = 0; 1816 err = tbr_set(&ifp->if_snd, &tb); 1817 if (err != 0 && error == 0) 1818 error = err; 1819 } 1820 } |
1821#if defined(__FreeBSD__) 1822 if (error == 0) { 1823 mtx_lock(&pf_altq_mtx); 1824 pfaltq_running = 0; 1825 mtx_unlock(&pf_altq_mtx); 1826 } 1827#else |
1828 if (error == 0) 1829 pfaltq_running = 0; |
1830#endif |
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 |
1848 error = altq_remove(altq); |
1849#if defined(__FreeBSD__) 1850 PF_LOCK(); 1851#endif |
1852 } 1853 pool_put(&pf_altq_pl, altq); 1854 } 1855 *ticket = ++ticket_altqs_inactive; 1856 break; 1857 } 1858 1859 case DIOCADDALTQ: { --- 20 unchanged lines hidden (view full) --- 1880 if (strncmp(a->ifname, altq->ifname, 1881 IFNAMSIZ) == 0 && a->qname[0] == 0) { 1882 altq->altq_disc = a->altq_disc; 1883 break; 1884 } 1885 } 1886 } 1887 |
1888#if defined(__FreeBSD__) 1889 PF_UNLOCK(); 1890#endif |
1891 error = altq_add(altq); |
1892#if defined(__FreeBSD__) 1893 PF_LOCK(); 1894#endif |
1895 if (error) { 1896 pool_put(&pf_altq_pl, altq); 1897 break; 1898 } 1899 1900 TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries); 1901 bcopy(altq, &pa->altq, sizeof(struct pf_altq)); 1902 break; --- 18 unchanged lines hidden (view full) --- 1921 pf_altqs_active = pf_altqs_inactive; 1922 pf_altqs_inactive = old_altqs; 1923 ticket_altqs_active = ticket_altqs_inactive; 1924 1925 /* Attach new disciplines */ 1926 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 1927 if (altq->qname[0] == 0) { 1928 /* attach the discipline */ |
1929#if defined(__FreeBSD__) 1930 PF_UNLOCK(); 1931#endif |
1932 error = altq_pfattach(altq); |
1933#if defined(__FreeBSD__) 1934 PF_LOCK(); 1935#endif |
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 |
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 |
1960 } 1961 pool_put(&pf_altq_pl, altq); 1962 } 1963 splx(s); 1964 1965 /* update queue IDs */ 1966 pf_rule_set_qid( 1967 pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); --- 69 unchanged lines hidden (view full) --- 2037 altq = TAILQ_NEXT(altq, entries); 2038 nr++; 2039 } 2040 if (altq == NULL) { 2041 error = EBUSY; 2042 splx(s); 2043 break; 2044 } |
2045#if defined(__FreeBSD__) 2046 PF_UNLOCK(); 2047#endif |
2048 error = altq_getqstats(altq, pq->buf, &nbytes); |
2049#if defined(__FreeBSD__) 2050 PF_LOCK(); 2051#endif |
2052 splx(s); 2053 if (error == 0) { 2054 pq->scheduler = altq->scheduler; 2055 pq->nbytes = nbytes; 2056 } 2057 break; 2058 } 2059#endif /* ALTQ */ --- 515 unchanged lines hidden (view full) --- 2575 break; 2576 } 2577 2578 default: 2579 error = ENODEV; 2580 break; 2581 } 2582fail: |
2583#if defined(__FreeBSD__) 2584 PF_UNLOCK(); 2585#endif 2586 return (error); 2587} |
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 |
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__ */ |