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 |