pfctl_optimize.c (145840) | pfctl_optimize.c (171172) |
---|---|
1/* $OpenBSD: pfctl_optimize.c,v 1.5 2005/01/03 15:18:10 frantzen Exp $ */ | 1/* $OpenBSD: pfctl_optimize.c,v 1.13 2006/10/31 14:17:45 mcbride Exp $ */ |
2 3/* 4 * Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/cdefs.h> | 2 3/* 4 * Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/cdefs.h> |
20__FBSDID("$FreeBSD: head/contrib/pf/pfctl/pfctl_optimize.c 145840 2005-05-03 16:55:20Z mlaier $"); | 20__FBSDID("$FreeBSD: head/contrib/pf/pfctl/pfctl_optimize.c 171172 2007-07-03 12:30:03Z mlaier $"); |
21 22#include <sys/types.h> 23#include <sys/ioctl.h> 24#include <sys/socket.h> 25 26#include <net/if.h> 27#include <net/pfvar.h> 28 --- 78 unchanged lines hidden (view full) --- 107 * The presence of these fields in a rule put the rule in it's own 108 * superblock. Thus it will not be optimized. It also prevents the 109 * rule from being re-ordered at all. 110 */ 111 PF_RULE_FIELD(label, BARRIER), 112 PF_RULE_FIELD(prob, BARRIER), 113 PF_RULE_FIELD(max_states, BARRIER), 114 PF_RULE_FIELD(max_src_nodes, BARRIER), | 21 22#include <sys/types.h> 23#include <sys/ioctl.h> 24#include <sys/socket.h> 25 26#include <net/if.h> 27#include <net/pfvar.h> 28 --- 78 unchanged lines hidden (view full) --- 107 * The presence of these fields in a rule put the rule in it's own 108 * superblock. Thus it will not be optimized. It also prevents the 109 * rule from being re-ordered at all. 110 */ 111 PF_RULE_FIELD(label, BARRIER), 112 PF_RULE_FIELD(prob, BARRIER), 113 PF_RULE_FIELD(max_states, BARRIER), 114 PF_RULE_FIELD(max_src_nodes, BARRIER), |
115 PF_RULE_FIELD(max_src_states, BARRIER), 116 PF_RULE_FIELD(max_src_conn, BARRIER), 117 PF_RULE_FIELD(max_src_conn_rate, BARRIER), 118 PF_RULE_FIELD(anchor, BARRIER), /* for now */ |
|
115 116 /* 117 * These fields must be the same between all rules in the same superblock. 118 * These rules are allowed to be re-ordered but only among like rules. 119 * For instance we can re-order all 'tag "foo"' rules because they have the 120 * same tag. But we can not re-order between a 'tag "foo"' and a 121 * 'tag "bar"' since that would change the meaning of the ruleset. 122 */ 123 PF_RULE_FIELD(tagname, BREAK), 124 PF_RULE_FIELD(keep_state, BREAK), 125 PF_RULE_FIELD(qname, BREAK), | 119 120 /* 121 * These fields must be the same between all rules in the same superblock. 122 * These rules are allowed to be re-ordered but only among like rules. 123 * For instance we can re-order all 'tag "foo"' rules because they have the 124 * same tag. But we can not re-order between a 'tag "foo"' and a 125 * 'tag "bar"' since that would change the meaning of the ruleset. 126 */ 127 PF_RULE_FIELD(tagname, BREAK), 128 PF_RULE_FIELD(keep_state, BREAK), 129 PF_RULE_FIELD(qname, BREAK), |
130 PF_RULE_FIELD(pqname, BREAK), |
|
126 PF_RULE_FIELD(rt, BREAK), 127 PF_RULE_FIELD(allow_opts, BREAK), 128 PF_RULE_FIELD(rule_flag, BREAK), 129 PF_RULE_FIELD(action, BREAK), | 131 PF_RULE_FIELD(rt, BREAK), 132 PF_RULE_FIELD(allow_opts, BREAK), 133 PF_RULE_FIELD(rule_flag, BREAK), 134 PF_RULE_FIELD(action, BREAK), |
135 PF_RULE_FIELD(log, BREAK), 136 PF_RULE_FIELD(quick, BREAK), 137 PF_RULE_FIELD(return_ttl, BREAK), 138 PF_RULE_FIELD(overload_tblname, BREAK), 139 PF_RULE_FIELD(flush, BREAK), 140 PF_RULE_FIELD(rpool, BREAK), 141 PF_RULE_FIELD(logif, BREAK), |
|
130 131 /* 132 * Any fields not listed in this structure act as BREAK fields 133 */ 134 135 136 /* 137 * These fields must not differ when we merge two rules together but 138 * their difference isn't enough to put the rules in different superblocks. 139 * There are no problems re-ordering any rules with these fields. 140 */ 141 PF_RULE_FIELD(af, NOMERGE), 142 PF_RULE_FIELD(ifnot, NOMERGE), | 142 143 /* 144 * Any fields not listed in this structure act as BREAK fields 145 */ 146 147 148 /* 149 * These fields must not differ when we merge two rules together but 150 * their difference isn't enough to put the rules in different superblocks. 151 * There are no problems re-ordering any rules with these fields. 152 */ 153 PF_RULE_FIELD(af, NOMERGE), 154 PF_RULE_FIELD(ifnot, NOMERGE), |
143 PF_RULE_FIELD(ifname, NOMERGE), | 155 PF_RULE_FIELD(ifname, NOMERGE), /* hack for IF groups */ |
144 PF_RULE_FIELD(match_tag_not, NOMERGE), 145 PF_RULE_FIELD(match_tagname, NOMERGE), 146 PF_RULE_FIELD(os_fingerprint, NOMERGE), 147 PF_RULE_FIELD(timeout, NOMERGE), 148 PF_RULE_FIELD(return_icmp, NOMERGE), 149 PF_RULE_FIELD(return_icmp6, NOMERGE), 150 PF_RULE_FIELD(uid, NOMERGE), 151 PF_RULE_FIELD(gid, NOMERGE), --- 16 unchanged lines hidden (view full) --- 168 PF_RULE_FIELD(dst.addr, COMBINED), 169 170 /* We just don't care about these fields. They're set by the kernel */ 171 PF_RULE_FIELD(skip, DC), 172 PF_RULE_FIELD(evaluations, DC), 173 PF_RULE_FIELD(packets, DC), 174 PF_RULE_FIELD(bytes, DC), 175 PF_RULE_FIELD(kif, DC), | 156 PF_RULE_FIELD(match_tag_not, NOMERGE), 157 PF_RULE_FIELD(match_tagname, NOMERGE), 158 PF_RULE_FIELD(os_fingerprint, NOMERGE), 159 PF_RULE_FIELD(timeout, NOMERGE), 160 PF_RULE_FIELD(return_icmp, NOMERGE), 161 PF_RULE_FIELD(return_icmp6, NOMERGE), 162 PF_RULE_FIELD(uid, NOMERGE), 163 PF_RULE_FIELD(gid, NOMERGE), --- 16 unchanged lines hidden (view full) --- 180 PF_RULE_FIELD(dst.addr, COMBINED), 181 182 /* We just don't care about these fields. They're set by the kernel */ 183 PF_RULE_FIELD(skip, DC), 184 PF_RULE_FIELD(evaluations, DC), 185 PF_RULE_FIELD(packets, DC), 186 PF_RULE_FIELD(bytes, DC), 187 PF_RULE_FIELD(kif, DC), |
176 PF_RULE_FIELD(anchor, DC), | |
177 PF_RULE_FIELD(states, DC), 178 PF_RULE_FIELD(src_nodes, DC), 179 PF_RULE_FIELD(nr, DC), 180 PF_RULE_FIELD(entries, DC), 181 PF_RULE_FIELD(qid, DC), 182 PF_RULE_FIELD(pqid, DC), 183 PF_RULE_FIELD(anchor_relative, DC), 184 PF_RULE_FIELD(anchor_wildcard, DC), | 188 PF_RULE_FIELD(states, DC), 189 PF_RULE_FIELD(src_nodes, DC), 190 PF_RULE_FIELD(nr, DC), 191 PF_RULE_FIELD(entries, DC), 192 PF_RULE_FIELD(qid, DC), 193 PF_RULE_FIELD(pqid, DC), 194 PF_RULE_FIELD(anchor_relative, DC), 195 PF_RULE_FIELD(anchor_wildcard, DC), |
196 PF_RULE_FIELD(tag, DC), 197 PF_RULE_FIELD(match_tag, DC), 198 PF_RULE_FIELD(overload_tbl, DC), |
|
185 186 /* These fields should never be set in a PASS/BLOCK rule */ 187 PF_RULE_FIELD(natpass, NEVER), 188 PF_RULE_FIELD(max_mss, NEVER), 189 PF_RULE_FIELD(min_ttl, NEVER), 190}; 191 192 193 194int add_opt_table(struct pfctl *, struct pf_opt_tbl **, sa_family_t, 195 struct pf_rule_addr *); 196int addrs_combineable(struct pf_rule_addr *, struct pf_rule_addr *); 197int addrs_equal(struct pf_rule_addr *, struct pf_rule_addr *); 198int block_feedback(struct pfctl *, struct superblock *); 199int combine_rules(struct pfctl *, struct superblock *); 200void comparable_rule(struct pf_rule *, const struct pf_rule *, int); 201int construct_superblocks(struct pfctl *, struct pf_opt_queue *, 202 struct superblocks *); 203void exclude_supersets(struct pf_rule *, struct pf_rule *); | 199 200 /* These fields should never be set in a PASS/BLOCK rule */ 201 PF_RULE_FIELD(natpass, NEVER), 202 PF_RULE_FIELD(max_mss, NEVER), 203 PF_RULE_FIELD(min_ttl, NEVER), 204}; 205 206 207 208int add_opt_table(struct pfctl *, struct pf_opt_tbl **, sa_family_t, 209 struct pf_rule_addr *); 210int addrs_combineable(struct pf_rule_addr *, struct pf_rule_addr *); 211int addrs_equal(struct pf_rule_addr *, struct pf_rule_addr *); 212int block_feedback(struct pfctl *, struct superblock *); 213int combine_rules(struct pfctl *, struct superblock *); 214void comparable_rule(struct pf_rule *, const struct pf_rule *, int); 215int construct_superblocks(struct pfctl *, struct pf_opt_queue *, 216 struct superblocks *); 217void exclude_supersets(struct pf_rule *, struct pf_rule *); |
218int interface_group(const char *); |
|
204int load_feedback_profile(struct pfctl *, struct superblocks *); 205int optimize_superblock(struct pfctl *, struct superblock *); 206int pf_opt_create_table(struct pfctl *, struct pf_opt_tbl *); 207void remove_from_skipsteps(struct skiplist *, struct superblock *, 208 struct pf_opt_rule *, struct pf_skip_step *); 209int remove_identical_rules(struct pfctl *, struct superblock *); 210int reorder_rules(struct pfctl *, struct superblock *, int); 211int rules_combineable(struct pf_rule *, struct pf_rule *); --- 26 unchanged lines hidden (view full) --- 238 { "dport", PF_SKIP_DST_PORT, skip_cmp_dst_port } \ 239} 240 241struct pfr_buffer table_buffer; 242int table_identifier; 243 244 245int | 219int load_feedback_profile(struct pfctl *, struct superblocks *); 220int optimize_superblock(struct pfctl *, struct superblock *); 221int pf_opt_create_table(struct pfctl *, struct pf_opt_tbl *); 222void remove_from_skipsteps(struct skiplist *, struct superblock *, 223 struct pf_opt_rule *, struct pf_skip_step *); 224int remove_identical_rules(struct pfctl *, struct superblock *); 225int reorder_rules(struct pfctl *, struct superblock *, int); 226int rules_combineable(struct pf_rule *, struct pf_rule *); --- 26 unchanged lines hidden (view full) --- 253 { "dport", PF_SKIP_DST_PORT, skip_cmp_dst_port } \ 254} 255 256struct pfr_buffer table_buffer; 257int table_identifier; 258 259 260int |
246pfctl_optimize_rules(struct pfctl *pf) | 261pfctl_optimize_ruleset(struct pfctl *pf, struct pf_ruleset *rs) |
247{ 248 struct superblocks superblocks; | 262{ 263 struct superblocks superblocks; |
264 struct pf_opt_queue opt_queue; |
|
249 struct superblock *block; 250 struct pf_opt_rule *por; | 265 struct superblock *block; 266 struct pf_opt_rule *por; |
251 int nr; | 267 struct pf_rule *r; 268 struct pf_rulequeue *old_rules; |
252 253 DEBUG("optimizing ruleset"); 254 memset(&table_buffer, 0, sizeof(table_buffer)); 255 skip_init(); | 269 270 DEBUG("optimizing ruleset"); 271 memset(&table_buffer, 0, sizeof(table_buffer)); 272 skip_init(); |
273 TAILQ_INIT(&opt_queue); |
|
256 | 274 |
257 if (TAILQ_FIRST(&pf->opt_queue)) 258 nr = TAILQ_FIRST(&pf->opt_queue)->por_rule.nr; | 275 old_rules = rs->rules[PF_RULESET_FILTER].active.ptr; 276 rs->rules[PF_RULESET_FILTER].active.ptr = 277 rs->rules[PF_RULESET_FILTER].inactive.ptr; 278 rs->rules[PF_RULESET_FILTER].inactive.ptr = old_rules; |
259 | 279 |
280 /* 281 * XXX expanding the pf_opt_rule format throughout pfctl might allow 282 * us to avoid all this copying. 283 */ 284 while ((r = TAILQ_FIRST(rs->rules[PF_RULESET_FILTER].inactive.ptr)) 285 != NULL) { 286 TAILQ_REMOVE(rs->rules[PF_RULESET_FILTER].inactive.ptr, r, 287 entries); 288 if ((por = calloc(1, sizeof(*por))) == NULL) 289 err(1, "calloc"); 290 memcpy(&por->por_rule, r, sizeof(*r)); 291 if (TAILQ_FIRST(&r->rpool.list) != NULL) { 292 TAILQ_INIT(&por->por_rule.rpool.list); 293 pfctl_move_pool(&r->rpool, &por->por_rule.rpool); 294 } else 295 bzero(&por->por_rule.rpool, 296 sizeof(por->por_rule.rpool)); 297 298 299 TAILQ_INSERT_TAIL(&opt_queue, por, por_entry); 300 } 301 |
|
260 TAILQ_INIT(&superblocks); | 302 TAILQ_INIT(&superblocks); |
261 if (construct_superblocks(pf, &pf->opt_queue, &superblocks)) | 303 if (construct_superblocks(pf, &opt_queue, &superblocks)) |
262 goto error; 263 | 304 goto error; 305 |
264 if (pf->opts & PF_OPT_OPTIMIZE_PROFILE) { | 306 if (pf->optimize & PF_OPTIMIZE_PROFILE) { |
265 if (load_feedback_profile(pf, &superblocks)) 266 goto error; 267 } 268 269 TAILQ_FOREACH(block, &superblocks, sb_entry) { 270 if (optimize_superblock(pf, block)) 271 goto error; 272 } 273 | 307 if (load_feedback_profile(pf, &superblocks)) 308 goto error; 309 } 310 311 TAILQ_FOREACH(block, &superblocks, sb_entry) { 312 if (optimize_superblock(pf, block)) 313 goto error; 314 } 315 |
274 275 /* 276 * Optimizations are done so we turn off the optimization flag and 277 * put the rules right back into the regular codepath. 278 */ 279 pf->opts &= ~PF_OPT_OPTIMIZE; 280 | 316 rs->anchor->refcnt = 0; |
281 while ((block = TAILQ_FIRST(&superblocks))) { 282 TAILQ_REMOVE(&superblocks, block, sb_entry); 283 284 while ((por = TAILQ_FIRST(&block->sb_rules))) { 285 TAILQ_REMOVE(&block->sb_rules, por, por_entry); | 317 while ((block = TAILQ_FIRST(&superblocks))) { 318 TAILQ_REMOVE(&superblocks, block, sb_entry); 319 320 while ((por = TAILQ_FIRST(&block->sb_rules))) { 321 TAILQ_REMOVE(&block->sb_rules, por, por_entry); |
286 por->por_rule.nr = nr++; 287 if (pfctl_add_rule(pf, &por->por_rule, 288 por->por_anchor)) { 289 free(por); 290 goto error; 291 } | 322 por->por_rule.nr = rs->anchor->refcnt++; 323 if ((r = calloc(1, sizeof(*r))) == NULL) 324 err(1, "calloc"); 325 memcpy(r, &por->por_rule, sizeof(*r)); 326 TAILQ_INIT(&r->rpool.list); 327 pfctl_move_pool(&por->por_rule.rpool, &r->rpool); 328 TAILQ_INSERT_TAIL( 329 rs->rules[PF_RULESET_FILTER].active.ptr, 330 r, entries); |
292 free(por); 293 } 294 free(block); 295 } 296 297 return (0); 298 299error: | 331 free(por); 332 } 333 free(block); 334 } 335 336 return (0); 337 338error: |
300 while ((por = TAILQ_FIRST(&pf->opt_queue))) { 301 TAILQ_REMOVE(&pf->opt_queue, por, por_entry); | 339 while ((por = TAILQ_FIRST(&opt_queue))) { 340 TAILQ_REMOVE(&opt_queue, por, por_entry); |
302 if (por->por_src_tbl) { 303 pfr_buf_clear(por->por_src_tbl->pt_buf); 304 free(por->por_src_tbl->pt_buf); 305 free(por->por_src_tbl); 306 } 307 if (por->por_dst_tbl) { 308 pfr_buf_clear(por->por_dst_tbl->pt_buf); 309 free(por->por_dst_tbl->pt_buf); --- 52 unchanged lines hidden (view full) --- 362 /* shortcut. there will be alot of 1-rule superblocks */ 363 if (!TAILQ_NEXT(TAILQ_FIRST(&block->sb_rules), por_entry)) 364 return (0); 365 366#ifdef OPT_DEBUG 367 printf("--- Superblock ---\n"); 368 TAILQ_FOREACH(por, &block->sb_rules, por_entry) { 369 printf(" "); | 341 if (por->por_src_tbl) { 342 pfr_buf_clear(por->por_src_tbl->pt_buf); 343 free(por->por_src_tbl->pt_buf); 344 free(por->por_src_tbl); 345 } 346 if (por->por_dst_tbl) { 347 pfr_buf_clear(por->por_dst_tbl->pt_buf); 348 free(por->por_dst_tbl->pt_buf); --- 52 unchanged lines hidden (view full) --- 401 /* shortcut. there will be alot of 1-rule superblocks */ 402 if (!TAILQ_NEXT(TAILQ_FIRST(&block->sb_rules), por_entry)) 403 return (0); 404 405#ifdef OPT_DEBUG 406 printf("--- Superblock ---\n"); 407 TAILQ_FOREACH(por, &block->sb_rules, por_entry) { 408 printf(" "); |
370 print_rule(&por->por_rule, por->por_anchor, 1); | 409 print_rule(&por->por_rule, por->por_rule.anchor ? 410 por->por_rule.anchor->name : "", 1); |
371 } 372#endif /* OPT_DEBUG */ 373 374 375 if (remove_identical_rules(pf, block)) 376 return (1); 377 if (combine_rules(pf, block)) 378 return (1); | 411 } 412#endif /* OPT_DEBUG */ 413 414 415 if (remove_identical_rules(pf, block)) 416 return (1); 417 if (combine_rules(pf, block)) 418 return (1); |
379 if ((pf->opts & PF_OPT_OPTIMIZE_PROFILE) && | 419 if ((pf->optimize & PF_OPTIMIZE_PROFILE) && |
380 TAILQ_FIRST(&block->sb_rules)->por_rule.quick && 381 block->sb_profiled_block) { 382 if (block_feedback(pf, block)) 383 return (1); 384 } else if (reorder_rules(pf, block, 0)) { 385 return (1); 386 } 387 --- 390 unchanged lines hidden (view full) --- 778 779 780 /* 781 * Walk through all of the profiled superblock's rules and copy 782 * the counters onto our rules. 783 */ 784 TAILQ_FOREACH(por1, &block->sb_profiled_block->sb_rules, por_entry) { 785 comparable_rule(&a, &por1->por_rule, DC); | 420 TAILQ_FIRST(&block->sb_rules)->por_rule.quick && 421 block->sb_profiled_block) { 422 if (block_feedback(pf, block)) 423 return (1); 424 } else if (reorder_rules(pf, block, 0)) { 425 return (1); 426 } 427 --- 390 unchanged lines hidden (view full) --- 818 819 820 /* 821 * Walk through all of the profiled superblock's rules and copy 822 * the counters onto our rules. 823 */ 824 TAILQ_FOREACH(por1, &block->sb_profiled_block->sb_rules, por_entry) { 825 comparable_rule(&a, &por1->por_rule, DC); |
786 total_count += por1->por_rule.packets; | 826 total_count += por1->por_rule.packets[0] + 827 por1->por_rule.packets[1]; |
787 TAILQ_FOREACH(por2, &block->sb_rules, por_entry) { 788 if (por2->por_profile_count) 789 continue; 790 comparable_rule(&b, &por2->por_rule, DC); 791 if (memcmp(&a, &b, sizeof(a)) == 0) { 792 por2->por_profile_count = | 828 TAILQ_FOREACH(por2, &block->sb_rules, por_entry) { 829 if (por2->por_profile_count) 830 continue; 831 comparable_rule(&b, &por2->por_rule, DC); 832 if (memcmp(&a, &b, sizeof(a)) == 0) { 833 por2->por_profile_count = |
793 por1->por_rule.packets; | 834 por1->por_rule.packets[0] + 835 por1->por_rule.packets[1]; |
794 break; 795 } 796 } 797 } 798 superblock_free(pf, block->sb_profiled_block); 799 block->sb_profiled_block = NULL; 800 801 /* --- 51 unchanged lines hidden (view full) --- 853 if (ioctl(pf->dev, DIOCGETRULES, &pr)) { 854 warn("DIOCGETRULES"); 855 return (1); 856 } 857 mnr = pr.nr; 858 859 DEBUG("Loading %d active rules for a feedback profile", mnr); 860 for (nr = 0; nr < mnr; ++nr) { | 836 break; 837 } 838 } 839 } 840 superblock_free(pf, block->sb_profiled_block); 841 block->sb_profiled_block = NULL; 842 843 /* --- 51 unchanged lines hidden (view full) --- 895 if (ioctl(pf->dev, DIOCGETRULES, &pr)) { 896 warn("DIOCGETRULES"); 897 return (1); 898 } 899 mnr = pr.nr; 900 901 DEBUG("Loading %d active rules for a feedback profile", mnr); 902 for (nr = 0; nr < mnr; ++nr) { |
903 struct pf_ruleset *rs; |
|
861 if ((por = calloc(1, sizeof(*por))) == NULL) { 862 warn("calloc"); 863 return (1); 864 } 865 pr.nr = nr; 866 if (ioctl(pf->dev, DIOCGETRULE, &pr)) { 867 warn("DIOCGETRULES"); 868 return (1); 869 } 870 memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule)); | 904 if ((por = calloc(1, sizeof(*por))) == NULL) { 905 warn("calloc"); 906 return (1); 907 } 908 pr.nr = nr; 909 if (ioctl(pf->dev, DIOCGETRULE, &pr)) { 910 warn("DIOCGETRULES"); 911 return (1); 912 } 913 memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule)); |
871 strlcpy(por->por_anchor, pr.anchor_call, 872 sizeof(por->por_anchor)); | 914 rs = pf_find_or_create_ruleset(pr.anchor_call); 915 por->por_rule.anchor = rs->anchor; |
873 if (TAILQ_EMPTY(&por->por_rule.rpool.list)) 874 memset(&por->por_rule.rpool, 0, 875 sizeof(por->por_rule.rpool)); 876 TAILQ_INSERT_TAIL(&queue, por, por_entry); 877 878 /* XXX pfctl_get_pool(pf->dev, &pr.rule.rpool, nr, pr.ticket, 879 * PF_PASS, pf->anchor) ??? 880 * ... pfctl_clear_pool(&pr.rule.rpool) --- 166 unchanged lines hidden (view full) --- 1047 case PF_ADDR_DYNIFTL: 1048 if (strcmp(a->dst.addr.v.ifname, b->dst.addr.v.ifname) != 0 || 1049 a->dst.addr.iflags != a->dst.addr.iflags || 1050 memcmp(&a->dst.addr.v.a.mask, &b->dst.addr.v.a.mask, 1051 sizeof(a->dst.addr.v.a.mask))) 1052 return (1); 1053 return (0); 1054 case PF_ADDR_NOROUTE: | 916 if (TAILQ_EMPTY(&por->por_rule.rpool.list)) 917 memset(&por->por_rule.rpool, 0, 918 sizeof(por->por_rule.rpool)); 919 TAILQ_INSERT_TAIL(&queue, por, por_entry); 920 921 /* XXX pfctl_get_pool(pf->dev, &pr.rule.rpool, nr, pr.ticket, 922 * PF_PASS, pf->anchor) ??? 923 * ... pfctl_clear_pool(&pr.rule.rpool) --- 166 unchanged lines hidden (view full) --- 1090 case PF_ADDR_DYNIFTL: 1091 if (strcmp(a->dst.addr.v.ifname, b->dst.addr.v.ifname) != 0 || 1092 a->dst.addr.iflags != a->dst.addr.iflags || 1093 memcmp(&a->dst.addr.v.a.mask, &b->dst.addr.v.a.mask, 1094 sizeof(a->dst.addr.v.a.mask))) 1095 return (1); 1096 return (0); 1097 case PF_ADDR_NOROUTE: |
1098 case PF_ADDR_URPFFAILED: |
|
1055 return (0); 1056 case PF_ADDR_TABLE: 1057 return (strcmp(a->dst.addr.v.tblname, b->dst.addr.v.tblname)); 1058 } 1059 return (1); 1060} 1061 1062/* Compare two rules DST port field for skiplist construction */ --- 55 unchanged lines hidden (view full) --- 1118 case PF_ADDR_DYNIFTL: 1119 if (strcmp(a->src.addr.v.ifname, b->src.addr.v.ifname) != 0 || 1120 a->src.addr.iflags != a->src.addr.iflags || 1121 memcmp(&a->src.addr.v.a.mask, &b->src.addr.v.a.mask, 1122 sizeof(a->src.addr.v.a.mask))) 1123 return (1); 1124 return (0); 1125 case PF_ADDR_NOROUTE: | 1099 return (0); 1100 case PF_ADDR_TABLE: 1101 return (strcmp(a->dst.addr.v.tblname, b->dst.addr.v.tblname)); 1102 } 1103 return (1); 1104} 1105 1106/* Compare two rules DST port field for skiplist construction */ --- 55 unchanged lines hidden (view full) --- 1162 case PF_ADDR_DYNIFTL: 1163 if (strcmp(a->src.addr.v.ifname, b->src.addr.v.ifname) != 0 || 1164 a->src.addr.iflags != a->src.addr.iflags || 1165 memcmp(&a->src.addr.v.a.mask, &b->src.addr.v.a.mask, 1166 sizeof(a->src.addr.v.a.mask))) 1167 return (1); 1168 return (0); 1169 case PF_ADDR_NOROUTE: |
1170 case PF_ADDR_URPFFAILED: |
|
1126 return (0); 1127 case PF_ADDR_TABLE: 1128 return (strcmp(a->src.addr.v.tblname, b->src.addr.v.tblname)); 1129 } 1130 return (1); 1131} 1132 1133/* Compare two rules SRC port field for skiplist construction */ --- 135 unchanged lines hidden (view full) --- 1269 tbl->pt_name); 1270 table_identifier = arc4random(); 1271 goto again; 1272 } 1273 } 1274 tablenum++; 1275 1276 | 1171 return (0); 1172 case PF_ADDR_TABLE: 1173 return (strcmp(a->src.addr.v.tblname, b->src.addr.v.tblname)); 1174 } 1175 return (1); 1176} 1177 1178/* Compare two rules SRC port field for skiplist construction */ --- 135 unchanged lines hidden (view full) --- 1314 tbl->pt_name); 1315 table_identifier = arc4random(); 1316 goto again; 1317 } 1318 } 1319 tablenum++; 1320 1321 |
1277 if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1, pf->anchor, 1278 tbl->pt_buf, pf->tticket)) { | 1322 if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1, 1323 pf->anchor->name, tbl->pt_buf, pf->anchor->ruleset.tticket)) { |
1279 warn("failed to create table %s", tbl->pt_name); 1280 return (1); 1281 } 1282 return (0); 1283} 1284 1285/* 1286 * Partition the flat ruleset into a list of distinct superblocks --- 82 unchanged lines hidden (view full) --- 1369 if (pf_rule_desc[i].prf_type == BARRIER) { 1370 for (j = 0; j < pf_rule_desc[i].prf_size; j++) 1371 if (((char *)&por->por_rule)[j + 1372 pf_rule_desc[i].prf_offset] != 0) 1373 return (0); 1374 } 1375 } 1376 | 1324 warn("failed to create table %s", tbl->pt_name); 1325 return (1); 1326 } 1327 return (0); 1328} 1329 1330/* 1331 * Partition the flat ruleset into a list of distinct superblocks --- 82 unchanged lines hidden (view full) --- 1414 if (pf_rule_desc[i].prf_type == BARRIER) { 1415 for (j = 0; j < pf_rule_desc[i].prf_size; j++) 1416 if (((char *)&por->por_rule)[j + 1417 pf_rule_desc[i].prf_offset] != 0) 1418 return (0); 1419 } 1420 } 1421 |
1377 /* 'anchor' heads and per-rule src-track are also hard breaks */ 1378 if (por->por_anchor[0] != '\0' || 1379 (por->por_rule.rule_flag & PFRULE_RULESRCTRACK)) | 1422 /* per-rule src-track is also a hard break */ 1423 if (por->por_rule.rule_flag & PFRULE_RULESRCTRACK) |
1380 return (0); 1381 | 1424 return (0); 1425 |
1426 /* 1427 * Have to handle interface groups seperately. Consider the following 1428 * rules: 1429 * block on EXTIFS to any port 22 1430 * pass on em0 to any port 22 1431 * (where EXTIFS is an arbitrary interface group) 1432 * The optimizer may decide to re-order the pass rule in front of the 1433 * block rule. But what if EXTIFS includes em0??? Such a reordering 1434 * would change the meaning of the ruleset. 1435 * We can't just lookup the EXTIFS group and check if em0 is a member 1436 * because the user is allowed to add interfaces to a group during 1437 * runtime. 1438 * Ergo interface groups become a defacto superblock break :-( 1439 */ 1440 if (interface_group(por->por_rule.ifname) || 1441 interface_group(TAILQ_FIRST(&block->sb_rules)->por_rule.ifname)) { 1442 if (strcasecmp(por->por_rule.ifname, 1443 TAILQ_FIRST(&block->sb_rules)->por_rule.ifname) != 0) 1444 return (0); 1445 } 1446 |
|
1382 comparable_rule(&a, &TAILQ_FIRST(&block->sb_rules)->por_rule, NOMERGE); 1383 comparable_rule(&b, &por->por_rule, NOMERGE); | 1447 comparable_rule(&a, &TAILQ_FIRST(&block->sb_rules)->por_rule, NOMERGE); 1448 comparable_rule(&b, &por->por_rule, NOMERGE); |
1384 if (strcmp(TAILQ_FIRST(&block->sb_rules)->por_anchor, 1385 por->por_anchor) == 0 && memcmp(&a, &b, sizeof(a)) == 0) | 1449 if (memcmp(&a, &b, sizeof(a)) == 0) |
1386 return (1); 1387 1388#ifdef OPT_DEBUG 1389 for (i = 0; i < sizeof(por->por_rule); i++) { 1390 int closest = -1; 1391 if (((u_int8_t *)&a)[i] != ((u_int8_t *)&b)[i]) { 1392 for (j = 0; j < sizeof(pf_rule_desc) / 1393 sizeof(*pf_rule_desc); j++) { --- 27 unchanged lines hidden (view full) --- 1421 } 1422#endif /* OPT_DEBUG */ 1423 1424 return (0); 1425} 1426 1427 1428/* | 1450 return (1); 1451 1452#ifdef OPT_DEBUG 1453 for (i = 0; i < sizeof(por->por_rule); i++) { 1454 int closest = -1; 1455 if (((u_int8_t *)&a)[i] != ((u_int8_t *)&b)[i]) { 1456 for (j = 0; j < sizeof(pf_rule_desc) / 1457 sizeof(*pf_rule_desc); j++) { --- 27 unchanged lines hidden (view full) --- 1485 } 1486#endif /* OPT_DEBUG */ 1487 1488 return (0); 1489} 1490 1491 1492/* |
1493 * Figure out if an interface name is an actual interface or actually a 1494 * group of interfaces. 1495 */ 1496int 1497interface_group(const char *ifname) 1498{ 1499 if (ifname == NULL || !ifname[0]) 1500 return (0); 1501 1502 /* Real interfaces must end in a number, interface groups do not */ 1503 if (isdigit(ifname[strlen(ifname) - 1])) 1504 return (0); 1505 else 1506 return (1); 1507} 1508 1509 1510/* |
|
1429 * Make a rule that can directly compared by memcmp() 1430 */ 1431void 1432comparable_rule(struct pf_rule *dst, const struct pf_rule *src, int type) 1433{ 1434 int i; 1435 /* 1436 * To simplify the comparison, we just zero out the fields that are --- 134 unchanged lines hidden --- | 1511 * Make a rule that can directly compared by memcmp() 1512 */ 1513void 1514comparable_rule(struct pf_rule *dst, const struct pf_rule *src, int type) 1515{ 1516 int i; 1517 /* 1518 * To simplify the comparison, we just zero out the fields that are --- 134 unchanged lines hidden --- |