Changeset View
Changeset View
Standalone View
Standalone View
sbin/pfctl/pfctl.c
| Show First 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | |||||
| int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); | int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); | ||||
| int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); | int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); | ||||
| int pfctl_load_debug(struct pfctl *, unsigned int); | int pfctl_load_debug(struct pfctl *, unsigned int); | ||||
| int pfctl_load_logif(struct pfctl *, char *); | int pfctl_load_logif(struct pfctl *, char *); | ||||
| int pfctl_load_hostid(struct pfctl *, u_int32_t); | int pfctl_load_hostid(struct pfctl *, u_int32_t); | ||||
| int pfctl_load_syncookies(struct pfctl *, u_int8_t); | int pfctl_load_syncookies(struct pfctl *, u_int8_t); | ||||
| int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, | int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, | ||||
| char *); | char *); | ||||
| void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int); | |||||
| void pfctl_print_rule_counters(struct pfctl_rule *, int); | void pfctl_print_rule_counters(struct pfctl_rule *, int); | ||||
| int pfctl_show_eth_rules(int, int); | |||||
| int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); | int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); | ||||
| int pfctl_show_nat(int, int, char *); | int pfctl_show_nat(int, int, char *); | ||||
| int pfctl_show_src_nodes(int, int); | int pfctl_show_src_nodes(int, int); | ||||
| int pfctl_show_states(int, const char *, int); | int pfctl_show_states(int, const char *, int); | ||||
| int pfctl_show_status(int, int); | int pfctl_show_status(int, int); | ||||
| int pfctl_show_running(int); | int pfctl_show_running(int); | ||||
| int pfctl_show_timeouts(int, int); | int pfctl_show_timeouts(int, int); | ||||
| int pfctl_show_limits(int, int); | int pfctl_show_limits(int, int); | ||||
| void pfctl_debug(int, u_int32_t, int); | void pfctl_debug(int, u_int32_t, int); | ||||
| int pfctl_test_altqsupport(int, int); | int pfctl_test_altqsupport(int, int); | ||||
| int pfctl_show_anchors(int, int, char *); | int pfctl_show_anchors(int, int, char *); | ||||
| int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *); | int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *); | ||||
| int pfctl_load_eth_ruleset(struct pfctl *); | |||||
| int pfctl_load_ruleset(struct pfctl *, char *, | int pfctl_load_ruleset(struct pfctl *, char *, | ||||
| struct pfctl_ruleset *, int, int); | struct pfctl_ruleset *, int, int); | ||||
| int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); | int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); | ||||
| const char *pfctl_lookup_option(char *, const char * const *); | const char *pfctl_lookup_option(char *, const char * const *); | ||||
| static struct pfctl_anchor_global pf_anchors; | static struct pfctl_anchor_global pf_anchors; | ||||
| static struct pfctl_anchor pf_main_anchor; | static struct pfctl_anchor pf_main_anchor; | ||||
| static struct pfr_buffer skip_b; | static struct pfr_buffer skip_b; | ||||
| ▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
| }; | }; | ||||
| static const char * const clearopt_list[] = { | static const char * const clearopt_list[] = { | ||||
| "nat", "queue", "rules", "Sources", | "nat", "queue", "rules", "Sources", | ||||
| "states", "info", "Tables", "osfp", "all", NULL | "states", "info", "Tables", "osfp", "all", NULL | ||||
| }; | }; | ||||
| static const char * const showopt_list[] = { | static const char * const showopt_list[] = { | ||||
| "nat", "queue", "rules", "Anchors", "Sources", "states", "info", | "ether", "nat", "queue", "rules", "Anchors", "Sources", "states", | ||||
| "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", | "info", "Interfaces", "labels", "timeouts", "memory", "Tables", | ||||
| "Running", "all", NULL | "osfp", "Running", "all", NULL | ||||
| }; | }; | ||||
| static const char * const tblcmdopt_list[] = { | static const char * const tblcmdopt_list[] = { | ||||
| "kill", "flush", "add", "delete", "load", "replace", "show", | "kill", "flush", "add", "delete", "load", "replace", "show", | ||||
| "test", "zero", "expire", NULL | "test", "zero", "expire", NULL | ||||
| }; | }; | ||||
| static const char * const debugopt_list[] = { | static const char * const debugopt_list[] = { | ||||
| ▲ Show 20 Lines • Show All 746 Lines • ▼ Show 20 Lines | pfctl_clear_pool(struct pfctl_pool *pool) | ||||
| while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { | while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { | ||||
| TAILQ_REMOVE(&pool->list, pa, entries); | TAILQ_REMOVE(&pool->list, pa, entries); | ||||
| free(pa); | free(pa); | ||||
| } | } | ||||
| } | } | ||||
| void | void | ||||
| pfctl_print_eth_rule_counters(struct pfctl_eth_rule *rule, int opts) | |||||
| { | |||||
| if (opts & PF_OPT_VERBOSE) { | |||||
| printf(" [ Evaluations: %-8llu Packets: %-8llu " | |||||
| "Bytes: %-10llu]\n", | |||||
| (unsigned long long)rule->evaluations, | |||||
| (unsigned long long)(rule->packets[0] + | |||||
| rule->packets[1]), | |||||
| (unsigned long long)(rule->bytes[0] + | |||||
| rule->bytes[1])); | |||||
| } | |||||
| } | |||||
| void | |||||
| pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) | pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) | ||||
| { | { | ||||
| if (opts & PF_OPT_DEBUG) { | if (opts & PF_OPT_DEBUG) { | ||||
| const char *t[PF_SKIP_COUNT] = { "i", "d", "f", | const char *t[PF_SKIP_COUNT] = { "i", "d", "f", | ||||
| "p", "sa", "sp", "da", "dp" }; | "p", "sa", "sp", "da", "dp" }; | ||||
| int i; | int i; | ||||
| printf(" [ Skip steps: "); | printf(" [ Skip steps: "); | ||||
| Show All 32 Lines | |||||
| { | { | ||||
| if (!first_title) | if (!first_title) | ||||
| printf("\n"); | printf("\n"); | ||||
| first_title = 0; | first_title = 0; | ||||
| printf("%s\n", title); | printf("%s\n", title); | ||||
| } | } | ||||
| int | int | ||||
| pfctl_show_eth_rules(int dev, int opts) | |||||
| { | |||||
| struct pfctl_eth_rules_info info; | |||||
| struct pfctl_eth_rule rule; | |||||
| int dotitle = opts & PF_OPT_SHOWALL; | |||||
| if (pfctl_get_eth_rules_info(dev, &info)) { | |||||
| warn("DIOCGETETHRULES"); | |||||
| return (-1); | |||||
| } | |||||
| for (int nr = 0; nr < info.nr; nr++) { | |||||
| if (pfctl_get_eth_rule(dev, nr, info.ticket, &rule, false) | |||||
| != 0) { | |||||
| warn("DIOCGETETHRULE"); | |||||
| return (-1); | |||||
| } | |||||
| if (dotitle) { | |||||
| pfctl_print_title("ETH RULES:"); | |||||
| dotitle = 0; | |||||
| } | |||||
| print_eth_rule(&rule, opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); | |||||
| printf("\n"); | |||||
| pfctl_print_eth_rule_counters(&rule, opts); | |||||
| } | |||||
| return (0); | |||||
| } | |||||
| int | |||||
| pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, | pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, | ||||
| char *anchorname, int depth) | char *anchorname, int depth) | ||||
| { | { | ||||
| struct pfioc_rule pr; | struct pfioc_rule pr; | ||||
| struct pfctl_rule rule; | struct pfctl_rule rule; | ||||
| u_int32_t nr, mnr, header = 0; | u_int32_t nr, mnr, header = 0; | ||||
| int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); | int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); | ||||
| int numeric = opts & PF_OPT_NUMERIC; | int numeric = opts & PF_OPT_NUMERIC; | ||||
| ▲ Show 20 Lines • Show All 415 Lines • ▼ Show 20 Lines | pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r, | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| int | int | ||||
| pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a) | pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a) | ||||
| { | { | ||||
| int osize = pf->trans->pfrb_size; | int osize = pf->trans->pfrb_size; | ||||
| if ((pf->loadopt & PFCTL_FLAG_ETH) != 0) { | |||||
| if (! path[0]) { | |||||
| if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) | |||||
| return (1); | |||||
| } | |||||
| } | |||||
| if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { | if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { | ||||
| if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || | if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || | ||||
| pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || | pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || | ||||
| pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) | pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) | ||||
| return (1); | return (1); | ||||
| } | } | ||||
| if (a == pf->astack[0] && ((altqsupport && | if (a == pf->astack[0] && ((altqsupport && | ||||
| (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { | (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { | ||||
| Show All 10 Lines | if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) | ||||
| return (4); | return (4); | ||||
| if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) | if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) | ||||
| return (5); | return (5); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| int | int | ||||
| pfctl_load_eth_ruleset(struct pfctl *pf) | |||||
| { | |||||
| struct pfctl_eth_rule *r; | |||||
| int error; | |||||
| while ((r = TAILQ_FIRST(&pf->eth_rules)) != NULL) { | |||||
| TAILQ_REMOVE(&pf->eth_rules, r, entries); | |||||
| if ((pf->opts & PF_OPT_NOACTION) == 0) { | |||||
| error = pfctl_add_eth_rule(pf->dev, r, pf->eth_ticket); | |||||
| if (error) | |||||
| return (error); | |||||
| } | |||||
| free(r); | |||||
| } | |||||
| return (0); | |||||
| } | |||||
| int | |||||
| pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, | pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, | ||||
| int rs_num, int depth) | int rs_num, int depth) | ||||
| { | { | ||||
| struct pfctl_rule *r; | struct pfctl_rule *r; | ||||
| int error, len = strlen(path); | int error, len = strlen(path); | ||||
| int brace = 0; | int brace = 0; | ||||
| pf->anchor = rs->anchor; | pf->anchor = rs->anchor; | ||||
| ▲ Show 20 Lines • Show All 161 Lines • ▼ Show 20 Lines | if ((path = calloc(1, MAXPATHLEN)) == NULL) | ||||
| ERRX("pfctl_rules: calloc"); | ERRX("pfctl_rules: calloc"); | ||||
| if (strlcpy(trs.pfrt_anchor, anchorname, | if (strlcpy(trs.pfrt_anchor, anchorname, | ||||
| sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) | sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) | ||||
| ERRX("pfctl_rules: strlcpy"); | ERRX("pfctl_rules: strlcpy"); | ||||
| pf.dev = dev; | pf.dev = dev; | ||||
| pf.opts = opts; | pf.opts = opts; | ||||
| pf.optimize = optimize; | pf.optimize = optimize; | ||||
| pf.loadopt = loadopt; | pf.loadopt = loadopt; | ||||
| TAILQ_INIT(&pf.eth_rules); | |||||
| /* non-brace anchor, create without resolving the path */ | /* non-brace anchor, create without resolving the path */ | ||||
| if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) | if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) | ||||
| ERRX("pfctl_rules: calloc"); | ERRX("pfctl_rules: calloc"); | ||||
| rs = &pf.anchor->ruleset; | rs = &pf.anchor->ruleset; | ||||
| pf_init_ruleset(rs); | pf_init_ruleset(rs); | ||||
| rs->anchor = pf.anchor; | rs->anchor = pf.anchor; | ||||
| if (strlcpy(pf.anchor->path, anchorname, | if (strlcpy(pf.anchor->path, anchorname, | ||||
| Show All 15 Lines | #define ERRX(x) do { warnx(x); goto _error; } while(0) | ||||
| if ((opts & PF_OPT_NOACTION) == 0) { | if ((opts & PF_OPT_NOACTION) == 0) { | ||||
| /* | /* | ||||
| * XXX For the time being we need to open transactions for | * XXX For the time being we need to open transactions for | ||||
| * the main ruleset before parsing, because tables are still | * the main ruleset before parsing, because tables are still | ||||
| * loaded at parse time. | * loaded at parse time. | ||||
| */ | */ | ||||
| if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) | if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) | ||||
| ERRX("pfctl_rules"); | ERRX("pfctl_rules"); | ||||
| if (pf.loadopt & PFCTL_FLAG_ETH) | |||||
| pf.eth_ticket = pfctl_get_ticket(t, PF_RULESET_ETH, anchorname); | |||||
| if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) | if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) | ||||
| pa.ticket = | pa.ticket = | ||||
| pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); | pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); | ||||
| if (pf.loadopt & PFCTL_FLAG_TABLE) | if (pf.loadopt & PFCTL_FLAG_TABLE) | ||||
| pf.astack[0]->ruleset.tticket = | pf.astack[0]->ruleset.tticket = | ||||
| pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); | pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); | ||||
| } | } | ||||
| if (parse_config(filename, &pf) < 0) { | if (parse_config(filename, &pf) < 0) { | ||||
| if ((opts & PF_OPT_NOACTION) == 0) | if ((opts & PF_OPT_NOACTION) == 0) | ||||
| ERRX("Syntax error in config file: " | ERRX("Syntax error in config file: " | ||||
| "pf rules not loaded"); | "pf rules not loaded"); | ||||
| else | else | ||||
| goto _error; | goto _error; | ||||
| } | } | ||||
| if (loadopt & PFCTL_FLAG_OPTION) | if (loadopt & PFCTL_FLAG_OPTION) | ||||
| pfctl_adjust_skip_ifaces(&pf); | pfctl_adjust_skip_ifaces(&pf); | ||||
| if ((pf.loadopt & PFCTL_FLAG_FILTER && | if ((pf.loadopt & PFCTL_FLAG_FILTER && | ||||
| (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || | (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || | ||||
| (pf.loadopt & PFCTL_FLAG_ETH && | |||||
| (pfctl_load_eth_ruleset(&pf))) || | |||||
| (pf.loadopt & PFCTL_FLAG_NAT && | (pf.loadopt & PFCTL_FLAG_NAT && | ||||
| (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || | (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || | ||||
| pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || | pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || | ||||
| pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || | pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || | ||||
| (pf.loadopt & PFCTL_FLAG_FILTER && | (pf.loadopt & PFCTL_FLAG_FILTER && | ||||
| pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { | pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { | ||||
| if ((opts & PF_OPT_NOACTION) == 0) | if ((opts & PF_OPT_NOACTION) == 0) | ||||
| ERRX("Unable to load rules into kernel"); | ERRX("Unable to load rules into kernel"); | ||||
| ▲ Show 20 Lines • Show All 825 Lines • ▼ Show 20 Lines | case 'R': | ||||
| error = pfctl_show_running(dev); | error = pfctl_show_running(dev); | ||||
| break; | break; | ||||
| case 't': | case 't': | ||||
| pfctl_show_timeouts(dev, opts); | pfctl_show_timeouts(dev, opts); | ||||
| break; | break; | ||||
| case 'm': | case 'm': | ||||
| pfctl_show_limits(dev, opts); | pfctl_show_limits(dev, opts); | ||||
| break; | break; | ||||
| case 'e': | |||||
| pfctl_show_eth_rules(dev, opts); | |||||
| break; | |||||
| case 'a': | case 'a': | ||||
| opts |= PF_OPT_SHOWALL; | opts |= PF_OPT_SHOWALL; | ||||
| pfctl_load_fingerprints(dev, opts); | pfctl_load_fingerprints(dev, opts); | ||||
| pfctl_show_eth_rules(dev, opts); | |||||
| pfctl_show_nat(dev, opts, anchorname); | pfctl_show_nat(dev, opts, anchorname); | ||||
| pfctl_show_rules(dev, path, opts, 0, anchorname, 0); | pfctl_show_rules(dev, path, opts, 0, anchorname, 0); | ||||
| pfctl_show_altq(dev, ifaceopt, opts, 0); | pfctl_show_altq(dev, ifaceopt, opts, 0); | ||||
| pfctl_show_states(dev, ifaceopt, opts); | pfctl_show_states(dev, ifaceopt, opts); | ||||
| pfctl_show_src_nodes(dev, opts); | pfctl_show_src_nodes(dev, opts); | ||||
| pfctl_show_status(dev, opts); | pfctl_show_status(dev, opts); | ||||
| pfctl_show_rules(dev, path, opts, 1, anchorname, 0); | pfctl_show_rules(dev, path, opts, 1, anchorname, 0); | ||||
| ▲ Show 20 Lines • Show All 146 Lines • Show Last 20 Lines | |||||