Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf_ioctl.c
| Show First 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | |||||
| static int pf_commit_altq(u_int32_t); | static int pf_commit_altq(u_int32_t); | ||||
| static int pf_enable_altq(struct pf_altq *); | static int pf_enable_altq(struct pf_altq *); | ||||
| static int pf_disable_altq(struct pf_altq *); | static int pf_disable_altq(struct pf_altq *); | ||||
| static u_int32_t pf_qname2qid(char *); | static u_int32_t pf_qname2qid(char *); | ||||
| static void pf_qid_unref(u_int32_t); | static void pf_qid_unref(u_int32_t); | ||||
| #endif /* ALTQ */ | #endif /* ALTQ */ | ||||
| static int pf_begin_rules(u_int32_t *, int, const char *); | static int pf_begin_rules(u_int32_t *, int, const char *); | ||||
| static int pf_rollback_rules(u_int32_t, int, char *); | static int pf_rollback_rules(u_int32_t, int, char *); | ||||
| static int pf_setup_pfsync_matching(struct pf_ruleset *); | static int pf_setup_pfsync_matching(struct pf_kruleset *); | ||||
| static void pf_hash_rule(MD5_CTX *, struct pf_rule *); | static void pf_hash_rule(MD5_CTX *, struct pf_krule *); | ||||
| static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *); | static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *); | ||||
| static int pf_commit_rules(u_int32_t, int, char *); | static int pf_commit_rules(u_int32_t, int, char *); | ||||
| static int pf_addr_setup(struct pf_ruleset *, | static int pf_addr_setup(struct pf_kruleset *, | ||||
| struct pf_addr_wrap *, sa_family_t); | struct pf_addr_wrap *, sa_family_t); | ||||
| static void pf_addr_copyout(struct pf_addr_wrap *); | static void pf_addr_copyout(struct pf_addr_wrap *); | ||||
| static void pf_src_node_copy(const struct pf_ksrc_node *, | static void pf_src_node_copy(const struct pf_ksrc_node *, | ||||
| struct pf_src_node *); | struct pf_src_node *); | ||||
| #ifdef ALTQ | #ifdef ALTQ | ||||
| static int pf_export_kaltq(struct pf_altq *, | static int pf_export_kaltq(struct pf_altq *, | ||||
| struct pfioc_altq_v1 *, size_t); | struct pfioc_altq_v1 *, size_t); | ||||
| static int pf_import_kaltq(struct pfioc_altq_v1 *, | static int pf_import_kaltq(struct pfioc_altq_v1 *, | ||||
| struct pf_altq *, size_t); | struct pf_altq *, size_t); | ||||
| #endif /* ALTQ */ | #endif /* ALTQ */ | ||||
| VNET_DEFINE(struct pf_rule, pf_default_rule); | VNET_DEFINE(struct pf_krule, pf_default_rule); | ||||
| #ifdef ALTQ | #ifdef ALTQ | ||||
| VNET_DEFINE_STATIC(int, pf_altq_running); | VNET_DEFINE_STATIC(int, pf_altq_running); | ||||
| #define V_pf_altq_running VNET(pf_altq_running) | #define V_pf_altq_running VNET(pf_altq_running) | ||||
| #endif | #endif | ||||
| #define TAGID_MAX 50000 | #define TAGID_MAX 50000 | ||||
| struct pf_tagname { | struct pf_tagname { | ||||
| ▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | pfattach_vnet(void) | ||||
| pfr_initialize(); | pfr_initialize(); | ||||
| pfi_initialize_vnet(); | pfi_initialize_vnet(); | ||||
| pf_normalize_init(); | pf_normalize_init(); | ||||
| V_pf_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT; | V_pf_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT; | ||||
| V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT; | V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT; | ||||
| RB_INIT(&V_pf_anchors); | RB_INIT(&V_pf_anchors); | ||||
| pf_init_ruleset(&pf_main_ruleset); | pf_init_kruleset(&pf_main_ruleset); | ||||
| /* default rule should never be garbage collected */ | /* default rule should never be garbage collected */ | ||||
| V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next; | V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next; | ||||
| #ifdef PF_DEFAULT_TO_DROP | #ifdef PF_DEFAULT_TO_DROP | ||||
| V_pf_default_rule.action = PF_DROP; | V_pf_default_rule.action = PF_DROP; | ||||
| #else | #else | ||||
| V_pf_default_rule.action = PF_PASS; | V_pf_default_rule.action = PF_PASS; | ||||
| #endif | #endif | ||||
| ▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if (swi_add(NULL, "pf send", pf_intr, curvnet, SWI_NET, | ||||
| return; | return; | ||||
| } | } | ||||
| static struct pf_pool * | static struct pf_pool * | ||||
| pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action, | pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action, | ||||
| u_int32_t rule_number, u_int8_t r_last, u_int8_t active, | u_int32_t rule_number, u_int8_t r_last, u_int8_t active, | ||||
| u_int8_t check_ticket) | u_int8_t check_ticket) | ||||
| { | { | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_rule *rule; | struct pf_krule *rule; | ||||
| int rs_num; | int rs_num; | ||||
| ruleset = pf_find_ruleset(anchor); | ruleset = pf_find_kruleset(anchor); | ||||
| if (ruleset == NULL) | if (ruleset == NULL) | ||||
| return (NULL); | return (NULL); | ||||
| rs_num = pf_get_ruleset_number(rule_action); | rs_num = pf_get_ruleset_number(rule_action); | ||||
| if (rs_num >= PF_RULESET_MAX) | if (rs_num >= PF_RULESET_MAX) | ||||
| return (NULL); | return (NULL); | ||||
| if (active) { | if (active) { | ||||
| if (check_ticket && ticket != | if (check_ticket && ticket != | ||||
| ruleset->rules[rs_num].active.ticket) | ruleset->rules[rs_num].active.ticket) | ||||
| return (NULL); | return (NULL); | ||||
| if (r_last) | if (r_last) | ||||
| rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, | rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, | ||||
| pf_rulequeue); | pf_krulequeue); | ||||
| else | else | ||||
| rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); | rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); | ||||
| } else { | } else { | ||||
| if (check_ticket && ticket != | if (check_ticket && ticket != | ||||
| ruleset->rules[rs_num].inactive.ticket) | ruleset->rules[rs_num].inactive.ticket) | ||||
| return (NULL); | return (NULL); | ||||
| if (r_last) | if (r_last) | ||||
| rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, | rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, | ||||
| pf_rulequeue); | pf_krulequeue); | ||||
| else | else | ||||
| rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr); | rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr); | ||||
| } | } | ||||
| if (!r_last) { | if (!r_last) { | ||||
| while ((rule != NULL) && (rule->nr != rule_number)) | while ((rule != NULL) && (rule->nr != rule_number)) | ||||
| rule = TAILQ_NEXT(rule, entries); | rule = TAILQ_NEXT(rule, entries); | ||||
| } | } | ||||
| if (rule == NULL) | if (rule == NULL) | ||||
| Show All 32 Lines | while ((pa = TAILQ_FIRST(poola)) != NULL) { | ||||
| if (pa->kif) | if (pa->kif) | ||||
| pfi_kif_unref(pa->kif); | pfi_kif_unref(pa->kif); | ||||
| TAILQ_REMOVE(poola, pa, entries); | TAILQ_REMOVE(poola, pa, entries); | ||||
| free(pa, M_PFRULE); | free(pa, M_PFRULE); | ||||
| } | } | ||||
| } | } | ||||
| static void | static void | ||||
| pf_unlink_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) | pf_unlink_rule(struct pf_krulequeue *rulequeue, struct pf_krule *rule) | ||||
| { | { | ||||
| PF_RULES_WASSERT(); | PF_RULES_WASSERT(); | ||||
| TAILQ_REMOVE(rulequeue, rule, entries); | TAILQ_REMOVE(rulequeue, rule, entries); | ||||
| PF_UNLNKDRULES_LOCK(); | PF_UNLNKDRULES_LOCK(); | ||||
| rule->rule_flag |= PFRULE_REFS; | rule->rule_flag |= PFRULE_REFS; | ||||
| TAILQ_INSERT_TAIL(&V_pf_unlinked_rules, rule, entries); | TAILQ_INSERT_TAIL(&V_pf_unlinked_rules, rule, entries); | ||||
| PF_UNLNKDRULES_UNLOCK(); | PF_UNLNKDRULES_UNLOCK(); | ||||
| } | } | ||||
| void | void | ||||
| pf_free_rule(struct pf_rule *rule) | pf_free_rule(struct pf_krule *rule) | ||||
| { | { | ||||
| PF_RULES_WASSERT(); | PF_RULES_WASSERT(); | ||||
| if (rule->tag) | if (rule->tag) | ||||
| tag_unref(&V_pf_tags, rule->tag); | tag_unref(&V_pf_tags, rule->tag); | ||||
| if (rule->match_tag) | if (rule->match_tag) | ||||
| tag_unref(&V_pf_tags, rule->match_tag); | tag_unref(&V_pf_tags, rule->match_tag); | ||||
| Show All 17 Lines | #endif | ||||
| case PF_ADDR_TABLE: | case PF_ADDR_TABLE: | ||||
| pfr_detach_table(rule->dst.addr.p.tbl); | pfr_detach_table(rule->dst.addr.p.tbl); | ||||
| break; | break; | ||||
| } | } | ||||
| if (rule->overload_tbl) | if (rule->overload_tbl) | ||||
| pfr_detach_table(rule->overload_tbl); | pfr_detach_table(rule->overload_tbl); | ||||
| if (rule->kif) | if (rule->kif) | ||||
| pfi_kif_unref(rule->kif); | pfi_kif_unref(rule->kif); | ||||
| pf_anchor_remove(rule); | pf_kanchor_remove(rule); | ||||
| pf_empty_pool(&rule->rpool.list); | pf_empty_pool(&rule->rpool.list); | ||||
| counter_u64_free(rule->states_cur); | counter_u64_free(rule->states_cur); | ||||
| counter_u64_free(rule->states_tot); | counter_u64_free(rule->states_tot); | ||||
| counter_u64_free(rule->src_nodes); | counter_u64_free(rule->src_nodes); | ||||
| free(rule, M_PFRULE); | free(rule, M_PFRULE); | ||||
| } | } | ||||
| static void | static void | ||||
| ▲ Show 20 Lines • Show All 420 Lines • ▼ Show 20 Lines | out: | ||||
| else | else | ||||
| pf_commit_altq(ticket); | pf_commit_altq(ticket); | ||||
| } | } | ||||
| #endif /* ALTQ */ | #endif /* ALTQ */ | ||||
| static int | static int | ||||
| pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor) | pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor) | ||||
| { | { | ||||
| struct pf_ruleset *rs; | struct pf_kruleset *rs; | ||||
| struct pf_rule *rule; | struct pf_krule *rule; | ||||
| PF_RULES_WASSERT(); | PF_RULES_WASSERT(); | ||||
| if (rs_num < 0 || rs_num >= PF_RULESET_MAX) | if (rs_num < 0 || rs_num >= PF_RULESET_MAX) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| rs = pf_find_or_create_ruleset(anchor); | rs = pf_find_or_create_kruleset(anchor); | ||||
| if (rs == NULL) | if (rs == NULL) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) { | while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) { | ||||
| pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule); | pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule); | ||||
| rs->rules[rs_num].inactive.rcount--; | rs->rules[rs_num].inactive.rcount--; | ||||
| } | } | ||||
| *ticket = ++rs->rules[rs_num].inactive.ticket; | *ticket = ++rs->rules[rs_num].inactive.ticket; | ||||
| rs->rules[rs_num].inactive.open = 1; | rs->rules[rs_num].inactive.open = 1; | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor) | pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor) | ||||
| { | { | ||||
| struct pf_ruleset *rs; | struct pf_kruleset *rs; | ||||
| struct pf_rule *rule; | struct pf_krule *rule; | ||||
| PF_RULES_WASSERT(); | PF_RULES_WASSERT(); | ||||
| if (rs_num < 0 || rs_num >= PF_RULESET_MAX) | if (rs_num < 0 || rs_num >= PF_RULESET_MAX) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| rs = pf_find_ruleset(anchor); | rs = pf_find_kruleset(anchor); | ||||
| if (rs == NULL || !rs->rules[rs_num].inactive.open || | if (rs == NULL || !rs->rules[rs_num].inactive.open || | ||||
| rs->rules[rs_num].inactive.ticket != ticket) | rs->rules[rs_num].inactive.ticket != ticket) | ||||
| return (0); | return (0); | ||||
| while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) { | while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) { | ||||
| pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule); | pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule); | ||||
| rs->rules[rs_num].inactive.rcount--; | rs->rules[rs_num].inactive.rcount--; | ||||
| } | } | ||||
| rs->rules[rs_num].inactive.open = 0; | rs->rules[rs_num].inactive.open = 0; | ||||
| Show All 37 Lines | pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr) | ||||
| PF_MD5_UPD(pfr, port[0]); | PF_MD5_UPD(pfr, port[0]); | ||||
| PF_MD5_UPD(pfr, port[1]); | PF_MD5_UPD(pfr, port[1]); | ||||
| PF_MD5_UPD(pfr, neg); | PF_MD5_UPD(pfr, neg); | ||||
| PF_MD5_UPD(pfr, port_op); | PF_MD5_UPD(pfr, port_op); | ||||
| } | } | ||||
| static void | static void | ||||
| pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule) | pf_hash_rule(MD5_CTX *ctx, struct pf_krule *rule) | ||||
| { | { | ||||
| u_int16_t x; | u_int16_t x; | ||||
| u_int32_t y; | u_int32_t y; | ||||
| pf_hash_rule_addr(ctx, &rule->src); | pf_hash_rule_addr(ctx, &rule->src); | ||||
| pf_hash_rule_addr(ctx, &rule->dst); | pf_hash_rule_addr(ctx, &rule->dst); | ||||
| PF_MD5_UPD_STR(rule, label); | PF_MD5_UPD_STR(rule, label); | ||||
| PF_MD5_UPD_STR(rule, ifname); | PF_MD5_UPD_STR(rule, ifname); | ||||
| Show All 24 Lines | pf_hash_rule(MD5_CTX *ctx, struct pf_krule *rule) | ||||
| PF_MD5_UPD(rule, allow_opts); | PF_MD5_UPD(rule, allow_opts); | ||||
| PF_MD5_UPD(rule, rt); | PF_MD5_UPD(rule, rt); | ||||
| PF_MD5_UPD(rule, tos); | PF_MD5_UPD(rule, tos); | ||||
| } | } | ||||
| static int | static int | ||||
| pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) | pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) | ||||
| { | { | ||||
| struct pf_ruleset *rs; | struct pf_kruleset *rs; | ||||
| struct pf_rule *rule, **old_array; | struct pf_krule *rule, **old_array; | ||||
| struct pf_rulequeue *old_rules; | struct pf_krulequeue *old_rules; | ||||
| int error; | int error; | ||||
| u_int32_t old_rcount; | u_int32_t old_rcount; | ||||
| PF_RULES_WASSERT(); | PF_RULES_WASSERT(); | ||||
| if (rs_num < 0 || rs_num >= PF_RULESET_MAX) | if (rs_num < 0 || rs_num >= PF_RULESET_MAX) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| rs = pf_find_ruleset(anchor); | rs = pf_find_kruleset(anchor); | ||||
| if (rs == NULL || !rs->rules[rs_num].inactive.open || | if (rs == NULL || !rs->rules[rs_num].inactive.open || | ||||
| ticket != rs->rules[rs_num].inactive.ticket) | ticket != rs->rules[rs_num].inactive.ticket) | ||||
| return (EBUSY); | return (EBUSY); | ||||
| /* Calculate checksum for the main ruleset */ | /* Calculate checksum for the main ruleset */ | ||||
| if (rs == &pf_main_ruleset) { | if (rs == &pf_main_ruleset) { | ||||
| error = pf_setup_pfsync_matching(rs); | error = pf_setup_pfsync_matching(rs); | ||||
| if (error != 0) | if (error != 0) | ||||
| Show All 22 Lines | pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) | ||||
| /* Purge the old rule list. */ | /* Purge the old rule list. */ | ||||
| while ((rule = TAILQ_FIRST(old_rules)) != NULL) | while ((rule = TAILQ_FIRST(old_rules)) != NULL) | ||||
| pf_unlink_rule(old_rules, rule); | pf_unlink_rule(old_rules, rule); | ||||
| if (rs->rules[rs_num].inactive.ptr_array) | if (rs->rules[rs_num].inactive.ptr_array) | ||||
| free(rs->rules[rs_num].inactive.ptr_array, M_TEMP); | free(rs->rules[rs_num].inactive.ptr_array, M_TEMP); | ||||
| rs->rules[rs_num].inactive.ptr_array = NULL; | rs->rules[rs_num].inactive.ptr_array = NULL; | ||||
| rs->rules[rs_num].inactive.rcount = 0; | rs->rules[rs_num].inactive.rcount = 0; | ||||
| rs->rules[rs_num].inactive.open = 0; | rs->rules[rs_num].inactive.open = 0; | ||||
| pf_remove_if_empty_ruleset(rs); | pf_remove_if_empty_kruleset(rs); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| pf_setup_pfsync_matching(struct pf_ruleset *rs) | pf_setup_pfsync_matching(struct pf_kruleset *rs) | ||||
| { | { | ||||
| MD5_CTX ctx; | MD5_CTX ctx; | ||||
| struct pf_rule *rule; | struct pf_krule *rule; | ||||
| int rs_cnt; | int rs_cnt; | ||||
| u_int8_t digest[PF_MD5_DIGEST_LENGTH]; | u_int8_t digest[PF_MD5_DIGEST_LENGTH]; | ||||
| MD5Init(&ctx); | MD5Init(&ctx); | ||||
| for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) { | for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) { | ||||
| /* XXX PF_RULESET_SCRUB as well? */ | /* XXX PF_RULESET_SCRUB as well? */ | ||||
| if (rs_cnt == PF_RULESET_SCRUB) | if (rs_cnt == PF_RULESET_SCRUB) | ||||
| continue; | continue; | ||||
| Show All 20 Lines | pf_setup_pfsync_matching(struct pf_kruleset *rs) | ||||
| } | } | ||||
| MD5Final(digest, &ctx); | MD5Final(digest, &ctx); | ||||
| memcpy(V_pf_status.pf_chksum, digest, sizeof(V_pf_status.pf_chksum)); | memcpy(V_pf_status.pf_chksum, digest, sizeof(V_pf_status.pf_chksum)); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr, | pf_addr_setup(struct pf_kruleset *ruleset, struct pf_addr_wrap *addr, | ||||
| sa_family_t af) | sa_family_t af) | ||||
| { | { | ||||
| int error = 0; | int error = 0; | ||||
| switch (addr->type) { | switch (addr->type) { | ||||
| case PF_ADDR_TABLE: | case PF_ADDR_TABLE: | ||||
| addr->p.tbl = pfr_attach_table(ruleset, addr->v.tblname); | addr->p.tbl = pfr_attach_table(ruleset, addr->v.tblname); | ||||
| if (addr->p.tbl == NULL) | if (addr->p.tbl == NULL) | ||||
| ▲ Show 20 Lines • Show All 293 Lines • ▼ Show 20 Lines | if (nr == n) | ||||
| return (altq); | return (altq); | ||||
| nr++; | nr++; | ||||
| } | } | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| #endif /* ALTQ */ | #endif /* ALTQ */ | ||||
| static void | |||||
| pf_krule_to_rule(const struct pf_krule *krule, struct pf_rule *rule) | |||||
| { | |||||
| bzero(rule, sizeof(*rule)); | |||||
| bcopy(&krule->src, &rule->src, sizeof(rule->src)); | |||||
| bcopy(&krule->dst, &rule->dst, sizeof(rule->dst)); | |||||
| for (int i = 0; i < PF_SKIP_COUNT; ++i) { | |||||
| if (rule->skip[i].ptr == NULL) | |||||
| rule->skip[i].nr = -1; | |||||
| else | |||||
| rule->skip[i].nr = krule->skip[i].ptr->nr; | |||||
| } | |||||
| strlcpy(rule->label, krule->label, sizeof(rule->label)); | |||||
| strlcpy(rule->ifname, krule->ifname, sizeof(rule->ifname)); | |||||
| strlcpy(rule->qname, krule->qname, sizeof(rule->qname)); | |||||
| strlcpy(rule->pqname, krule->pqname, sizeof(rule->pqname)); | |||||
| strlcpy(rule->tagname, krule->tagname, sizeof(rule->tagname)); | |||||
| strlcpy(rule->match_tagname, krule->match_tagname, | |||||
| sizeof(rule->match_tagname)); | |||||
| strlcpy(rule->overload_tblname, krule->overload_tblname, | |||||
| sizeof(rule->overload_tblname)); | |||||
| bcopy(&krule->rpool, &rule->rpool, sizeof(krule->rpool)); | |||||
| rule->evaluations = krule->evaluations; | |||||
| for (int i = 0; i < 2; i++) { | |||||
| rule->packets[i] = krule->packets[i]; | |||||
| rule->bytes[i] = krule->bytes[i]; | |||||
| } | |||||
| /* kif, anchor, overload_tbl are not copied over. */ | |||||
| rule->os_fingerprint = krule->os_fingerprint; | |||||
| rule->rtableid = krule->rtableid; | |||||
| bcopy(krule->timeout, rule->timeout, sizeof(krule->timeout)); | |||||
| rule->max_states = krule->max_states; | |||||
| rule->max_src_nodes = krule->max_src_nodes; | |||||
| rule->max_src_states = krule->max_src_states; | |||||
| rule->max_src_conn = krule->max_src_conn; | |||||
| rule->max_src_conn_rate.limit = krule->max_src_conn_rate.limit; | |||||
| rule->max_src_conn_rate.seconds = krule->max_src_conn_rate.seconds; | |||||
| rule->qid = krule->qid; | |||||
| rule->pqid = krule->pqid; | |||||
| rule->rt_listid = krule->rt_listid; | |||||
| rule->nr = krule->nr; | |||||
| rule->prob = krule->prob; | |||||
| rule->cuid = krule->cuid; | |||||
| rule->cpid = krule->cpid; | |||||
| rule->return_icmp = krule->return_icmp; | |||||
| rule->return_icmp6 = krule->return_icmp6; | |||||
| rule->max_mss = krule->max_mss; | |||||
| rule->tag = krule->tag; | |||||
| rule->match_tag = krule->match_tag; | |||||
| rule->scrub_flags = krule->scrub_flags; | |||||
| bcopy(&krule->uid, &rule->uid, sizeof(krule->uid)); | |||||
| bcopy(&krule->gid, &rule->gid, sizeof(krule->gid)); | |||||
| rule->rule_flag = krule->rule_flag; | |||||
| rule->action = krule->action; | |||||
| rule->direction = krule->direction; | |||||
| rule->log = krule->log; | |||||
| rule->logif = krule->logif; | |||||
| rule->quick = krule->quick; | |||||
| rule->ifnot = krule->ifnot; | |||||
| rule->match_tag_not = krule->match_tag_not; | |||||
| rule->natpass = krule->natpass; | |||||
| rule->keep_state = krule->keep_state; | |||||
| rule->af = krule->af; | |||||
| rule->proto = krule->proto; | |||||
| rule->type = krule->type; | |||||
| rule->code = krule->code; | |||||
| rule->flags = krule->flags; | |||||
| rule->flagset = krule->flagset; | |||||
| rule->min_ttl = krule->min_ttl; | |||||
| rule->allow_opts = krule->allow_opts; | |||||
| rule->rt = krule->rt; | |||||
| rule->return_ttl = krule->return_ttl; | |||||
| rule->tos = krule->tos; | |||||
| rule->set_tos = krule->set_tos; | |||||
| rule->anchor_relative = krule->anchor_relative; | |||||
| rule->anchor_wildcard = krule->anchor_wildcard; | |||||
| rule->flush = krule->flush; | |||||
| rule->prio = krule->prio; | |||||
| rule->set_prio[0] = krule->set_prio[0]; | |||||
| rule->set_prio[1] = krule->set_prio[1]; | |||||
| bcopy(&krule->divert, &rule->divert, sizeof(krule->divert)); | |||||
| rule->u_states_cur = counter_u64_fetch(krule->states_cur); | |||||
| rule->u_states_tot = counter_u64_fetch(krule->states_tot); | |||||
| rule->u_src_nodes = counter_u64_fetch(krule->src_nodes); | |||||
| } | |||||
| static void | |||||
| pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule) | |||||
| { | |||||
| bzero(krule, sizeof(*krule)); | |||||
| bcopy(&rule->src, &krule->src, sizeof(rule->src)); | |||||
| bcopy(&rule->dst, &krule->dst, sizeof(rule->dst)); | |||||
| strlcpy(krule->label, rule->label, sizeof(rule->label)); | |||||
| strlcpy(krule->ifname, rule->ifname, sizeof(rule->ifname)); | |||||
| strlcpy(krule->qname, rule->qname, sizeof(rule->qname)); | |||||
| strlcpy(krule->pqname, rule->pqname, sizeof(rule->pqname)); | |||||
| strlcpy(krule->tagname, rule->tagname, sizeof(rule->tagname)); | |||||
| strlcpy(krule->match_tagname, rule->match_tagname, | |||||
| sizeof(rule->match_tagname)); | |||||
| strlcpy(krule->overload_tblname, rule->overload_tblname, | |||||
| sizeof(rule->overload_tblname)); | |||||
| bcopy(&rule->rpool, &krule->rpool, sizeof(krule->rpool)); | |||||
| /* Don't allow userspace to set evaulations, packets or bytes. */ | |||||
| /* kif, anchor, overload_tbl are not copied over. */ | |||||
| krule->os_fingerprint = krule->os_fingerprint; | |||||
| krule->rtableid = rule->rtableid; | |||||
| bcopy(rule->timeout, krule->timeout, sizeof(krule->timeout)); | |||||
| krule->max_states = rule->max_states; | |||||
| krule->max_src_nodes = rule->max_src_nodes; | |||||
| krule->max_src_states = rule->max_src_states; | |||||
| krule->max_src_conn = rule->max_src_conn; | |||||
| krule->max_src_conn_rate.limit = rule->max_src_conn_rate.limit; | |||||
| krule->max_src_conn_rate.seconds = rule->max_src_conn_rate.seconds; | |||||
| krule->qid = rule->qid; | |||||
| krule->pqid = rule->pqid; | |||||
| krule->rt_listid = rule->rt_listid; | |||||
| krule->nr = rule->nr; | |||||
| krule->prob = rule->prob; | |||||
| krule->cuid = rule->cuid; | |||||
| krule->cpid = rule->cpid; | |||||
| krule->return_icmp = rule->return_icmp; | |||||
| krule->return_icmp6 = rule->return_icmp6; | |||||
| krule->max_mss = rule->max_mss; | |||||
| krule->tag = rule->tag; | |||||
| krule->match_tag = rule->match_tag; | |||||
| krule->scrub_flags = rule->scrub_flags; | |||||
| bcopy(&rule->uid, &krule->uid, sizeof(krule->uid)); | |||||
| bcopy(&rule->gid, &krule->gid, sizeof(krule->gid)); | |||||
| krule->rule_flag = rule->rule_flag; | |||||
| krule->action = rule->action; | |||||
| krule->direction = rule->direction; | |||||
| krule->log = rule->log; | |||||
| krule->logif = rule->logif; | |||||
| krule->quick = rule->quick; | |||||
| krule->ifnot = rule->ifnot; | |||||
| krule->match_tag_not = rule->match_tag_not; | |||||
| krule->natpass = rule->natpass; | |||||
| krule->keep_state = rule->keep_state; | |||||
| krule->af = rule->af; | |||||
| krule->proto = rule->proto; | |||||
| krule->type = rule->type; | |||||
| krule->code = rule->code; | |||||
| krule->flags = rule->flags; | |||||
| krule->flagset = rule->flagset; | |||||
| krule->min_ttl = rule->min_ttl; | |||||
| krule->allow_opts = rule->allow_opts; | |||||
| krule->rt = rule->rt; | |||||
| krule->return_ttl = rule->return_ttl; | |||||
| krule->tos = rule->tos; | |||||
| krule->set_tos = rule->set_tos; | |||||
| krule->anchor_relative = rule->anchor_relative; | |||||
| krule->anchor_wildcard = rule->anchor_wildcard; | |||||
| krule->flush = rule->flush; | |||||
| krule->prio = rule->prio; | |||||
| krule->set_prio[0] = rule->set_prio[0]; | |||||
| krule->set_prio[1] = rule->set_prio[1]; | |||||
| bcopy(&rule->divert, &krule->divert, sizeof(krule->divert)); | |||||
| } | |||||
| static int | static int | ||||
| pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) | pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) | ||||
| { | { | ||||
| int error = 0; | int error = 0; | ||||
| PF_RULES_RLOCK_TRACKER; | PF_RULES_RLOCK_TRACKER; | ||||
| /* XXX keep in sync with switch() below */ | /* XXX keep in sync with switch() below */ | ||||
| if (securelevel_gt(td->td_ucred, 2)) | if (securelevel_gt(td->td_ucred, 2)) | ||||
| ▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | else { | ||||
| } | } | ||||
| V_pf_status.since = time_second; | V_pf_status.since = time_second; | ||||
| DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); | DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); | ||||
| } | } | ||||
| break; | break; | ||||
| case DIOCADDRULE: { | case DIOCADDRULE: { | ||||
| struct pfioc_rule *pr = (struct pfioc_rule *)addr; | struct pfioc_rule *pr = (struct pfioc_rule *)addr; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_rule *rule, *tail; | struct pf_krule *rule, *tail; | ||||
| struct pf_pooladdr *pa; | struct pf_pooladdr *pa; | ||||
| struct pfi_kif *kif = NULL; | struct pfi_kif *kif = NULL; | ||||
| int rs_num; | int rs_num; | ||||
| if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { | if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| } | } | ||||
| Show All 11 Lines | |||||
| #ifndef INET6 | #ifndef INET6 | ||||
| if (pr->rule.af == AF_INET6) { | if (pr->rule.af == AF_INET6) { | ||||
| error = EAFNOSUPPORT; | error = EAFNOSUPPORT; | ||||
| break; | break; | ||||
| } | } | ||||
| #endif /* INET6 */ | #endif /* INET6 */ | ||||
| rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK); | rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK); | ||||
| bcopy(&pr->rule, rule, sizeof(struct pf_rule)); | pf_rule_to_krule(&pr->rule, rule); | ||||
| if (rule->ifname[0]) | if (rule->ifname[0]) | ||||
| kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | ||||
| rule->states_cur = counter_u64_alloc(M_WAITOK); | rule->states_cur = counter_u64_alloc(M_WAITOK); | ||||
| rule->states_tot = counter_u64_alloc(M_WAITOK); | rule->states_tot = counter_u64_alloc(M_WAITOK); | ||||
| rule->src_nodes = counter_u64_alloc(M_WAITOK); | rule->src_nodes = counter_u64_alloc(M_WAITOK); | ||||
| rule->cuid = td->td_ucred->cr_ruid; | rule->cuid = td->td_ucred->cr_ruid; | ||||
| rule->cpid = td->td_proc ? td->td_proc->p_pid : 0; | rule->cpid = td->td_proc ? td->td_proc->p_pid : 0; | ||||
| TAILQ_INIT(&rule->rpool.list); | TAILQ_INIT(&rule->rpool.list); | ||||
| #define ERROUT(x) { error = (x); goto DIOCADDRULE_error; } | #define ERROUT(x) { error = (x); goto DIOCADDRULE_error; } | ||||
| PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
| pr->anchor[sizeof(pr->anchor) - 1] = 0; | pr->anchor[sizeof(pr->anchor) - 1] = 0; | ||||
| ruleset = pf_find_ruleset(pr->anchor); | ruleset = pf_find_kruleset(pr->anchor); | ||||
| if (ruleset == NULL) | if (ruleset == NULL) | ||||
| ERROUT(EINVAL); | ERROUT(EINVAL); | ||||
| rs_num = pf_get_ruleset_number(pr->rule.action); | rs_num = pf_get_ruleset_number(pr->rule.action); | ||||
| if (rs_num >= PF_RULESET_MAX) | if (rs_num >= PF_RULESET_MAX) | ||||
| ERROUT(EINVAL); | ERROUT(EINVAL); | ||||
| if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { | if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { | ||||
| DPFPRINTF(PF_DEBUG_MISC, | DPFPRINTF(PF_DEBUG_MISC, | ||||
| ("ticket: %d != [%d]%d\n", pr->ticket, rs_num, | ("ticket: %d != [%d]%d\n", pr->ticket, rs_num, | ||||
| ruleset->rules[rs_num].inactive.ticket)); | ruleset->rules[rs_num].inactive.ticket)); | ||||
| ERROUT(EBUSY); | ERROUT(EBUSY); | ||||
| } | } | ||||
| if (pr->pool_ticket != V_ticket_pabuf) { | if (pr->pool_ticket != V_ticket_pabuf) { | ||||
| DPFPRINTF(PF_DEBUG_MISC, | DPFPRINTF(PF_DEBUG_MISC, | ||||
| ("pool_ticket: %d != %d\n", pr->pool_ticket, | ("pool_ticket: %d != %d\n", pr->pool_ticket, | ||||
| V_ticket_pabuf)); | V_ticket_pabuf)); | ||||
| ERROUT(EBUSY); | ERROUT(EBUSY); | ||||
| } | } | ||||
| tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, | tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, | ||||
| pf_rulequeue); | pf_krulequeue); | ||||
| if (tail) | if (tail) | ||||
| rule->nr = tail->nr + 1; | rule->nr = tail->nr + 1; | ||||
| else | else | ||||
| rule->nr = 0; | rule->nr = 0; | ||||
| if (rule->ifname[0]) { | if (rule->ifname[0]) { | ||||
| rule->kif = pfi_kif_attach(kif, rule->ifname); | rule->kif = pfi_kif_attach(kif, rule->ifname); | ||||
| pfi_kif_ref(rule->kif); | pfi_kif_ref(rule->kif); | ||||
| } else | } else | ||||
| Show All 27 Lines | #endif | ||||
| if (!rule->log) | if (!rule->log) | ||||
| rule->logif = 0; | rule->logif = 0; | ||||
| if (rule->logif >= PFLOGIFS_MAX) | if (rule->logif >= PFLOGIFS_MAX) | ||||
| error = EINVAL; | error = EINVAL; | ||||
| if (pf_addr_setup(ruleset, &rule->src.addr, rule->af)) | if (pf_addr_setup(ruleset, &rule->src.addr, rule->af)) | ||||
| error = ENOMEM; | error = ENOMEM; | ||||
| if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af)) | if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af)) | ||||
| error = ENOMEM; | error = ENOMEM; | ||||
| if (pf_anchor_setup(rule, ruleset, pr->anchor_call)) | if (pf_kanchor_setup(rule, ruleset, pr->anchor_call)) | ||||
| error = EINVAL; | error = EINVAL; | ||||
| if (rule->scrub_flags & PFSTATE_SETPRIO && | if (rule->scrub_flags & PFSTATE_SETPRIO && | ||||
| (rule->set_prio[0] > PF_PRIO_MAX || | (rule->set_prio[0] > PF_PRIO_MAX || | ||||
| rule->set_prio[1] > PF_PRIO_MAX)) | rule->set_prio[1] > PF_PRIO_MAX)) | ||||
| error = EINVAL; | error = EINVAL; | ||||
| TAILQ_FOREACH(pa, &V_pf_pabuf, entries) | TAILQ_FOREACH(pa, &V_pf_pabuf, entries) | ||||
| if (pa->addr.type == PF_ADDR_TABLE) { | if (pa->addr.type == PF_ADDR_TABLE) { | ||||
| pa->addr.p.tbl = pfr_attach_table(ruleset, | pa->addr.p.tbl = pfr_attach_table(ruleset, | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | DIOCADDRULE_error: | ||||
| free(rule, M_PFRULE); | free(rule, M_PFRULE); | ||||
| if (kif) | if (kif) | ||||
| free(kif, PFI_MTYPE); | free(kif, PFI_MTYPE); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCGETRULES: { | case DIOCGETRULES: { | ||||
| struct pfioc_rule *pr = (struct pfioc_rule *)addr; | struct pfioc_rule *pr = (struct pfioc_rule *)addr; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_rule *tail; | struct pf_krule *tail; | ||||
| int rs_num; | int rs_num; | ||||
| PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
| pr->anchor[sizeof(pr->anchor) - 1] = 0; | pr->anchor[sizeof(pr->anchor) - 1] = 0; | ||||
| ruleset = pf_find_ruleset(pr->anchor); | ruleset = pf_find_kruleset(pr->anchor); | ||||
| if (ruleset == NULL) { | if (ruleset == NULL) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| } | } | ||||
| rs_num = pf_get_ruleset_number(pr->rule.action); | rs_num = pf_get_ruleset_number(pr->rule.action); | ||||
| if (rs_num >= PF_RULESET_MAX) { | if (rs_num >= PF_RULESET_MAX) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| } | } | ||||
| tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, | tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, | ||||
| pf_rulequeue); | pf_krulequeue); | ||||
| if (tail) | if (tail) | ||||
| pr->nr = tail->nr + 1; | pr->nr = tail->nr + 1; | ||||
| else | else | ||||
| pr->nr = 0; | pr->nr = 0; | ||||
| pr->ticket = ruleset->rules[rs_num].active.ticket; | pr->ticket = ruleset->rules[rs_num].active.ticket; | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCGETRULE: { | case DIOCGETRULE: { | ||||
| struct pfioc_rule *pr = (struct pfioc_rule *)addr; | struct pfioc_rule *pr = (struct pfioc_rule *)addr; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_rule *rule; | struct pf_krule *rule; | ||||
| int rs_num, i; | int rs_num; | ||||
| PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
| pr->anchor[sizeof(pr->anchor) - 1] = 0; | pr->anchor[sizeof(pr->anchor) - 1] = 0; | ||||
| ruleset = pf_find_ruleset(pr->anchor); | ruleset = pf_find_kruleset(pr->anchor); | ||||
| if (ruleset == NULL) { | if (ruleset == NULL) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| } | } | ||||
| rs_num = pf_get_ruleset_number(pr->rule.action); | rs_num = pf_get_ruleset_number(pr->rule.action); | ||||
| if (rs_num >= PF_RULESET_MAX) { | if (rs_num >= PF_RULESET_MAX) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| } | } | ||||
| if (pr->ticket != ruleset->rules[rs_num].active.ticket) { | if (pr->ticket != ruleset->rules[rs_num].active.ticket) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| error = EBUSY; | error = EBUSY; | ||||
| break; | break; | ||||
| } | } | ||||
| rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); | rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); | ||||
| while ((rule != NULL) && (rule->nr != pr->nr)) | while ((rule != NULL) && (rule->nr != pr->nr)) | ||||
| rule = TAILQ_NEXT(rule, entries); | rule = TAILQ_NEXT(rule, entries); | ||||
| if (rule == NULL) { | if (rule == NULL) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| error = EBUSY; | error = EBUSY; | ||||
| break; | break; | ||||
| } | } | ||||
| bcopy(rule, &pr->rule, sizeof(struct pf_rule)); | |||||
| pr->rule.u_states_cur = counter_u64_fetch(rule->states_cur); | pf_krule_to_rule(rule, &pr->rule); | ||||
| pr->rule.u_states_tot = counter_u64_fetch(rule->states_tot); | |||||
| pr->rule.u_src_nodes = counter_u64_fetch(rule->src_nodes); | if (pf_kanchor_copyout(ruleset, rule, pr)) { | ||||
| if (pf_anchor_copyout(ruleset, rule, pr)) { | |||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| error = EBUSY; | error = EBUSY; | ||||
| break; | break; | ||||
| } | } | ||||
| pf_addr_copyout(&pr->rule.src.addr); | pf_addr_copyout(&pr->rule.src.addr); | ||||
| pf_addr_copyout(&pr->rule.dst.addr); | pf_addr_copyout(&pr->rule.dst.addr); | ||||
| for (i = 0; i < PF_SKIP_COUNT; ++i) | |||||
| if (rule->skip[i].ptr == NULL) | |||||
| pr->rule.skip[i].nr = -1; | |||||
| else | |||||
| pr->rule.skip[i].nr = | |||||
| rule->skip[i].ptr->nr; | |||||
| if (pr->action == PF_GET_CLR_CNTR) { | if (pr->action == PF_GET_CLR_CNTR) { | ||||
| rule->evaluations = 0; | rule->evaluations = 0; | ||||
| rule->packets[0] = rule->packets[1] = 0; | rule->packets[0] = rule->packets[1] = 0; | ||||
| rule->bytes[0] = rule->bytes[1] = 0; | rule->bytes[0] = rule->bytes[1] = 0; | ||||
| counter_u64_zero(rule->states_tot); | counter_u64_zero(rule->states_tot); | ||||
| } | } | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCCHANGERULE: { | case DIOCCHANGERULE: { | ||||
| struct pfioc_rule *pcr = (struct pfioc_rule *)addr; | struct pfioc_rule *pcr = (struct pfioc_rule *)addr; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_rule *oldrule = NULL, *newrule = NULL; | struct pf_krule *oldrule = NULL, *newrule = NULL; | ||||
| struct pfi_kif *kif = NULL; | struct pfi_kif *kif = NULL; | ||||
| struct pf_pooladdr *pa; | struct pf_pooladdr *pa; | ||||
| u_int32_t nr = 0; | u_int32_t nr = 0; | ||||
| int rs_num; | int rs_num; | ||||
| if (pcr->action < PF_CHANGE_ADD_HEAD || | if (pcr->action < PF_CHANGE_ADD_HEAD || | ||||
| pcr->action > PF_CHANGE_GET_TICKET) { | pcr->action > PF_CHANGE_GET_TICKET) { | ||||
| error = EINVAL; | error = EINVAL; | ||||
| Show All 13 Lines | |||||
| #endif /* INET */ | #endif /* INET */ | ||||
| #ifndef INET6 | #ifndef INET6 | ||||
| if (pcr->rule.af == AF_INET6) { | if (pcr->rule.af == AF_INET6) { | ||||
| error = EAFNOSUPPORT; | error = EAFNOSUPPORT; | ||||
| break; | break; | ||||
| } | } | ||||
| #endif /* INET6 */ | #endif /* INET6 */ | ||||
| newrule = malloc(sizeof(*newrule), M_PFRULE, M_WAITOK); | newrule = malloc(sizeof(*newrule), M_PFRULE, M_WAITOK); | ||||
| bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); | pf_rule_to_krule(&pcr->rule, newrule); | ||||
| if (newrule->ifname[0]) | if (newrule->ifname[0]) | ||||
| kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | ||||
| newrule->states_cur = counter_u64_alloc(M_WAITOK); | newrule->states_cur = counter_u64_alloc(M_WAITOK); | ||||
| newrule->states_tot = counter_u64_alloc(M_WAITOK); | newrule->states_tot = counter_u64_alloc(M_WAITOK); | ||||
| newrule->src_nodes = counter_u64_alloc(M_WAITOK); | newrule->src_nodes = counter_u64_alloc(M_WAITOK); | ||||
| newrule->cuid = td->td_ucred->cr_ruid; | newrule->cuid = td->td_ucred->cr_ruid; | ||||
| newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0; | newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0; | ||||
| TAILQ_INIT(&newrule->rpool.list); | TAILQ_INIT(&newrule->rpool.list); | ||||
| } | } | ||||
| #define ERROUT(x) { error = (x); goto DIOCCHANGERULE_error; } | #define ERROUT(x) { error = (x); goto DIOCCHANGERULE_error; } | ||||
| PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
| if (!(pcr->action == PF_CHANGE_REMOVE || | if (!(pcr->action == PF_CHANGE_REMOVE || | ||||
| pcr->action == PF_CHANGE_GET_TICKET) && | pcr->action == PF_CHANGE_GET_TICKET) && | ||||
| pcr->pool_ticket != V_ticket_pabuf) | pcr->pool_ticket != V_ticket_pabuf) | ||||
| ERROUT(EBUSY); | ERROUT(EBUSY); | ||||
| ruleset = pf_find_ruleset(pcr->anchor); | ruleset = pf_find_kruleset(pcr->anchor); | ||||
| if (ruleset == NULL) | if (ruleset == NULL) | ||||
| ERROUT(EINVAL); | ERROUT(EINVAL); | ||||
| rs_num = pf_get_ruleset_number(pcr->rule.action); | rs_num = pf_get_ruleset_number(pcr->rule.action); | ||||
| if (rs_num >= PF_RULESET_MAX) | if (rs_num >= PF_RULESET_MAX) | ||||
| ERROUT(EINVAL); | ERROUT(EINVAL); | ||||
| if (pcr->action == PF_CHANGE_GET_TICKET) { | if (pcr->action == PF_CHANGE_GET_TICKET) { | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | #endif /* ALTQ */ | ||||
| if (!newrule->log) | if (!newrule->log) | ||||
| newrule->logif = 0; | newrule->logif = 0; | ||||
| if (newrule->logif >= PFLOGIFS_MAX) | if (newrule->logif >= PFLOGIFS_MAX) | ||||
| error = EINVAL; | error = EINVAL; | ||||
| if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af)) | if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af)) | ||||
| error = ENOMEM; | error = ENOMEM; | ||||
| if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af)) | if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af)) | ||||
| error = ENOMEM; | error = ENOMEM; | ||||
| if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call)) | if (pf_kanchor_setup(newrule, ruleset, pcr->anchor_call)) | ||||
| error = EINVAL; | error = EINVAL; | ||||
| TAILQ_FOREACH(pa, &V_pf_pabuf, entries) | TAILQ_FOREACH(pa, &V_pf_pabuf, entries) | ||||
| if (pa->addr.type == PF_ADDR_TABLE) { | if (pa->addr.type == PF_ADDR_TABLE) { | ||||
| pa->addr.p.tbl = | pa->addr.p.tbl = | ||||
| pfr_attach_table(ruleset, | pfr_attach_table(ruleset, | ||||
| pa->addr.v.tblname); | pa->addr.v.tblname); | ||||
| if (pa->addr.p.tbl == NULL) | if (pa->addr.p.tbl == NULL) | ||||
| error = ENOMEM; | error = ENOMEM; | ||||
| Show All 32 Lines | #endif /* ALTQ */ | ||||
| } | } | ||||
| pf_empty_pool(&V_pf_pabuf); | pf_empty_pool(&V_pf_pabuf); | ||||
| if (pcr->action == PF_CHANGE_ADD_HEAD) | if (pcr->action == PF_CHANGE_ADD_HEAD) | ||||
| oldrule = TAILQ_FIRST( | oldrule = TAILQ_FIRST( | ||||
| ruleset->rules[rs_num].active.ptr); | ruleset->rules[rs_num].active.ptr); | ||||
| else if (pcr->action == PF_CHANGE_ADD_TAIL) | else if (pcr->action == PF_CHANGE_ADD_TAIL) | ||||
| oldrule = TAILQ_LAST( | oldrule = TAILQ_LAST( | ||||
| ruleset->rules[rs_num].active.ptr, pf_rulequeue); | ruleset->rules[rs_num].active.ptr, pf_krulequeue); | ||||
| else { | else { | ||||
| oldrule = TAILQ_FIRST( | oldrule = TAILQ_FIRST( | ||||
| ruleset->rules[rs_num].active.ptr); | ruleset->rules[rs_num].active.ptr); | ||||
| while ((oldrule != NULL) && (oldrule->nr != pcr->nr)) | while ((oldrule != NULL) && (oldrule->nr != pcr->nr)) | ||||
| oldrule = TAILQ_NEXT(oldrule, entries); | oldrule = TAILQ_NEXT(oldrule, entries); | ||||
| if (oldrule == NULL) { | if (oldrule == NULL) { | ||||
| if (newrule != NULL) | if (newrule != NULL) | ||||
| pf_free_rule(newrule); | pf_free_rule(newrule); | ||||
| Show All 25 Lines | #endif /* ALTQ */ | ||||
| nr = 0; | nr = 0; | ||||
| TAILQ_FOREACH(oldrule, | TAILQ_FOREACH(oldrule, | ||||
| ruleset->rules[rs_num].active.ptr, entries) | ruleset->rules[rs_num].active.ptr, entries) | ||||
| oldrule->nr = nr++; | oldrule->nr = nr++; | ||||
| ruleset->rules[rs_num].active.ticket++; | ruleset->rules[rs_num].active.ticket++; | ||||
| pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); | pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); | ||||
| pf_remove_if_empty_ruleset(ruleset); | pf_remove_if_empty_kruleset(ruleset); | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| break; | break; | ||||
| #undef ERROUT | #undef ERROUT | ||||
| DIOCCHANGERULE_error: | DIOCCHANGERULE_error: | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| if (newrule != NULL) { | if (newrule != NULL) { | ||||
| ▲ Show 20 Lines • Show All 371 Lines • ▼ Show 20 Lines | case DIOCSETDEBUG: { | ||||
| PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
| V_pf_status.debug = *level; | V_pf_status.debug = *level; | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCCLRRULECTRS: { | case DIOCCLRRULECTRS: { | ||||
| /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */ | /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */ | ||||
| struct pf_ruleset *ruleset = &pf_main_ruleset; | struct pf_kruleset *ruleset = &pf_main_ruleset; | ||||
| struct pf_rule *rule; | struct pf_krule *rule; | ||||
| PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
| TAILQ_FOREACH(rule, | TAILQ_FOREACH(rule, | ||||
| ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) { | ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) { | ||||
| rule->evaluations = 0; | rule->evaluations = 0; | ||||
| rule->packets[0] = rule->packets[1] = 0; | rule->packets[0] = rule->packets[1] = 0; | ||||
| rule->bytes[0] = rule->bytes[1] = 0; | rule->bytes[0] = rule->bytes[1] = 0; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 325 Lines • ▼ Show 20 Lines | case DIOCGETADDR: { | ||||
| PF_RULES_RUNLOCK(); | PF_RULES_RUNLOCK(); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCCHANGEADDR: { | case DIOCCHANGEADDR: { | ||||
| struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; | struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; | ||||
| struct pf_pool *pool; | struct pf_pool *pool; | ||||
| struct pf_pooladdr *oldpa = NULL, *newpa = NULL; | struct pf_pooladdr *oldpa = NULL, *newpa = NULL; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pfi_kif *kif = NULL; | struct pfi_kif *kif = NULL; | ||||
| if (pca->action < PF_CHANGE_ADD_HEAD || | if (pca->action < PF_CHANGE_ADD_HEAD || | ||||
| pca->action > PF_CHANGE_REMOVE) { | pca->action > PF_CHANGE_REMOVE) { | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| } | } | ||||
| if (pca->addr.addr.type != PF_ADDR_ADDRMASK && | if (pca->addr.addr.type != PF_ADDR_ADDRMASK && | ||||
| Show All 23 Lines | #endif /* INET6 */ | ||||
| newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK); | newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK); | ||||
| bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr)); | bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr)); | ||||
| if (newpa->ifname[0]) | if (newpa->ifname[0]) | ||||
| kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | ||||
| newpa->kif = NULL; | newpa->kif = NULL; | ||||
| } | } | ||||
| #define ERROUT(x) { error = (x); goto DIOCCHANGEADDR_error; } | #define ERROUT(x) { error = (x); goto DIOCCHANGEADDR_error; } | ||||
| PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
| ruleset = pf_find_ruleset(pca->anchor); | ruleset = pf_find_kruleset(pca->anchor); | ||||
| if (ruleset == NULL) | if (ruleset == NULL) | ||||
| ERROUT(EBUSY); | ERROUT(EBUSY); | ||||
| pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action, | pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action, | ||||
| pca->r_num, pca->r_last, 1, 1); | pca->r_num, pca->r_last, 1, 1); | ||||
| if (pool == NULL) | if (pool == NULL) | ||||
| ERROUT(EBUSY); | ERROUT(EBUSY); | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | DIOCCHANGEADDR_error: | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| if (kif != NULL) | if (kif != NULL) | ||||
| free(kif, PFI_MTYPE); | free(kif, PFI_MTYPE); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCGETRULESETS: { | case DIOCGETRULESETS: { | ||||
| struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; | struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_anchor *anchor; | struct pf_kanchor *anchor; | ||||
| PF_RULES_RLOCK(); | PF_RULES_RLOCK(); | ||||
| pr->path[sizeof(pr->path) - 1] = 0; | pr->path[sizeof(pr->path) - 1] = 0; | ||||
| if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { | if ((ruleset = pf_find_kruleset(pr->path)) == NULL) { | ||||
| PF_RULES_RUNLOCK(); | PF_RULES_RUNLOCK(); | ||||
| error = ENOENT; | error = ENOENT; | ||||
| break; | break; | ||||
| } | } | ||||
| pr->nr = 0; | pr->nr = 0; | ||||
| if (ruleset->anchor == NULL) { | if (ruleset->anchor == NULL) { | ||||
| /* XXX kludge for pf_main_ruleset */ | /* XXX kludge for pf_main_ruleset */ | ||||
| RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors) | RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors) | ||||
| if (anchor->parent == NULL) | if (anchor->parent == NULL) | ||||
| pr->nr++; | pr->nr++; | ||||
| } else { | } else { | ||||
| RB_FOREACH(anchor, pf_anchor_node, | RB_FOREACH(anchor, pf_kanchor_node, | ||||
| &ruleset->anchor->children) | &ruleset->anchor->children) | ||||
| pr->nr++; | pr->nr++; | ||||
| } | } | ||||
| PF_RULES_RUNLOCK(); | PF_RULES_RUNLOCK(); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCGETRULESET: { | case DIOCGETRULESET: { | ||||
| struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; | struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; | ||||
| struct pf_ruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_anchor *anchor; | struct pf_kanchor *anchor; | ||||
| u_int32_t nr = 0; | u_int32_t nr = 0; | ||||
| PF_RULES_RLOCK(); | PF_RULES_RLOCK(); | ||||
| pr->path[sizeof(pr->path) - 1] = 0; | pr->path[sizeof(pr->path) - 1] = 0; | ||||
| if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { | if ((ruleset = pf_find_kruleset(pr->path)) == NULL) { | ||||
| PF_RULES_RUNLOCK(); | PF_RULES_RUNLOCK(); | ||||
| error = ENOENT; | error = ENOENT; | ||||
| break; | break; | ||||
| } | } | ||||
| pr->name[0] = 0; | pr->name[0] = 0; | ||||
| if (ruleset->anchor == NULL) { | if (ruleset->anchor == NULL) { | ||||
| /* XXX kludge for pf_main_ruleset */ | /* XXX kludge for pf_main_ruleset */ | ||||
| RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors) | RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors) | ||||
| if (anchor->parent == NULL && nr++ == pr->nr) { | if (anchor->parent == NULL && nr++ == pr->nr) { | ||||
| strlcpy(pr->name, anchor->name, | strlcpy(pr->name, anchor->name, | ||||
| sizeof(pr->name)); | sizeof(pr->name)); | ||||
| break; | break; | ||||
| } | } | ||||
| } else { | } else { | ||||
| RB_FOREACH(anchor, pf_anchor_node, | RB_FOREACH(anchor, pf_kanchor_node, | ||||
| &ruleset->anchor->children) | &ruleset->anchor->children) | ||||
| if (nr++ == pr->nr) { | if (nr++ == pr->nr) { | ||||
| strlcpy(pr->name, anchor->name, | strlcpy(pr->name, anchor->name, | ||||
| sizeof(pr->name)); | sizeof(pr->name)); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (!pr->name[0]) | if (!pr->name[0]) | ||||
| ▲ Show 20 Lines • Show All 709 Lines • ▼ Show 20 Lines | #endif /* ALTQ */ | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| free(ioes, M_TEMP); | free(ioes, M_TEMP); | ||||
| break; | break; | ||||
| } | } | ||||
| case DIOCXCOMMIT: { | case DIOCXCOMMIT: { | ||||
| struct pfioc_trans *io = (struct pfioc_trans *)addr; | struct pfioc_trans *io = (struct pfioc_trans *)addr; | ||||
| struct pfioc_trans_e *ioe, *ioes; | struct pfioc_trans_e *ioe, *ioes; | ||||
| struct pf_ruleset *rs; | struct pf_kruleset *rs; | ||||
| size_t totlen; | size_t totlen; | ||||
| int i; | int i; | ||||
| if (io->esize != sizeof(*ioe)) { | if (io->esize != sizeof(*ioe)) { | ||||
| error = ENODEV; | error = ENODEV; | ||||
| break; | break; | ||||
| } | } | ||||
| Show All 33 Lines | #ifdef ALTQ | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| free(ioes, M_TEMP); | free(ioes, M_TEMP); | ||||
| error = EBUSY; | error = EBUSY; | ||||
| goto fail; | goto fail; | ||||
| } | } | ||||
| break; | break; | ||||
| #endif /* ALTQ */ | #endif /* ALTQ */ | ||||
| case PF_RULESET_TABLE: | case PF_RULESET_TABLE: | ||||
| rs = pf_find_ruleset(ioe->anchor); | rs = pf_find_kruleset(ioe->anchor); | ||||
| if (rs == NULL || !rs->topen || ioe->ticket != | if (rs == NULL || !rs->topen || ioe->ticket != | ||||
| rs->tticket) { | rs->tticket) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| free(ioes, M_TEMP); | free(ioes, M_TEMP); | ||||
| error = EBUSY; | error = EBUSY; | ||||
| goto fail; | goto fail; | ||||
| } | } | ||||
| break; | break; | ||||
| default: | default: | ||||
| if (ioe->rs_num < 0 || ioe->rs_num >= | if (ioe->rs_num < 0 || ioe->rs_num >= | ||||
| PF_RULESET_MAX) { | PF_RULESET_MAX) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| free(ioes, M_TEMP); | free(ioes, M_TEMP); | ||||
| error = EINVAL; | error = EINVAL; | ||||
| goto fail; | goto fail; | ||||
| } | } | ||||
| rs = pf_find_ruleset(ioe->anchor); | rs = pf_find_kruleset(ioe->anchor); | ||||
| if (rs == NULL || | if (rs == NULL || | ||||
| !rs->rules[ioe->rs_num].inactive.open || | !rs->rules[ioe->rs_num].inactive.open || | ||||
| rs->rules[ioe->rs_num].inactive.ticket != | rs->rules[ioe->rs_num].inactive.ticket != | ||||
| ioe->ticket) { | ioe->ticket) { | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| free(ioes, M_TEMP); | free(ioes, M_TEMP); | ||||
| error = EBUSY; | error = EBUSY; | ||||
| goto fail; | goto fail; | ||||
| ▲ Show 20 Lines • Show All 794 Lines • Show Last 20 Lines | |||||