Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf_ioctl.c
| Show First 20 Lines • Show All 1,624 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| static int | static int | ||||
| pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr) | pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr) | ||||
| { | { | ||||
| return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr))); | return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr))); | ||||
| } | } | ||||
| static nvlist_t * | |||||
| pf_addr_to_nvaddr(const struct pf_addr *paddr) | |||||
| { | |||||
| nvlist_t *nvl; | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) | |||||
| return (NULL); | |||||
| nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr)); | |||||
| return (nvl); | |||||
| } | |||||
| static int | static int | ||||
| pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool) | pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool) | ||||
| { | { | ||||
| int error = 0; | int error = 0; | ||||
| bzero(kpool, sizeof(*kpool)); | bzero(kpool, sizeof(*kpool)); | ||||
| PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key))); | PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key))); | ||||
| if (nvlist_exists_nvlist(nvl, "counter")) { | if (nvlist_exists_nvlist(nvl, "counter")) { | ||||
| PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), | PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), | ||||
| &kpool->counter)); | &kpool->counter)); | ||||
| } | } | ||||
| PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx)); | PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx)); | ||||
| PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2, | PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2, | ||||
| NULL)); | NULL)); | ||||
| PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts)); | PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts)); | ||||
| errout: | errout: | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static nvlist_t * | |||||
| pf_pool_to_nvpool(const struct pf_kpool *pool) | |||||
| { | |||||
| nvlist_t *nvl; | |||||
| nvlist_t *tmp; | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) | |||||
| return (NULL); | |||||
| nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key)); | |||||
| tmp = pf_addr_to_nvaddr(&pool->counter); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "counter", tmp); | |||||
| nvlist_add_number(nvl, "tblidx", pool->tblidx); | |||||
| pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2); | |||||
| nvlist_add_number(nvl, "opts", pool->opts); | |||||
| return (nvl); | |||||
| error: | |||||
| nvlist_destroy(nvl); | |||||
| return (NULL); | |||||
| } | |||||
| static int | static int | ||||
| pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) | pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) | ||||
| { | { | ||||
| int error = 0; | int error = 0; | ||||
| bzero(addr, sizeof(*addr)); | bzero(addr, sizeof(*addr)); | ||||
| PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type)); | PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type)); | ||||
| Show All 24 Lines | pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) | ||||
| default: | default: | ||||
| return (EINVAL); | return (EINVAL); | ||||
| } | } | ||||
| errout: | errout: | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static nvlist_t * | |||||
| pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr) | |||||
| { | |||||
| nvlist_t *nvl; | |||||
| nvlist_t *tmp; | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) | |||||
| return (NULL); | |||||
| nvlist_add_number(nvl, "type", addr->type); | |||||
| nvlist_add_number(nvl, "iflags", addr->iflags); | |||||
| nvlist_add_string(nvl, "ifname", addr->v.ifname); | |||||
| nvlist_add_string(nvl, "tblname", addr->v.tblname); | |||||
| tmp = pf_addr_to_nvaddr(&addr->v.a.addr); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "addr", tmp); | |||||
| tmp = pf_addr_to_nvaddr(&addr->v.a.mask); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "mask", tmp); | |||||
| return (nvl); | |||||
| error: | |||||
| nvlist_destroy(nvl); | |||||
| return (NULL); | |||||
| } | |||||
| static int | static int | ||||
| pf_validate_op(uint8_t op) | pf_validate_op(uint8_t op) | ||||
| { | { | ||||
| switch (op) { | switch (op) { | ||||
| case PF_OP_NONE: | case PF_OP_NONE: | ||||
| case PF_OP_IRG: | case PF_OP_IRG: | ||||
| case PF_OP_EQ: | case PF_OP_EQ: | ||||
| case PF_OP_NE: | case PF_OP_NE: | ||||
| Show All 26 Lines | pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) | ||||
| PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op)); | PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op)); | ||||
| PFNV_CHK(pf_validate_op(addr->port_op)); | PFNV_CHK(pf_validate_op(addr->port_op)); | ||||
| errout: | errout: | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static nvlist_t * | |||||
| pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr) | |||||
| { | |||||
| nvlist_t *nvl; | |||||
| nvlist_t *tmp; | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) | |||||
| return (NULL); | |||||
| tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "addr", tmp); | |||||
| pf_uint16_array_nv(nvl, "port", addr->port, 2); | |||||
| nvlist_add_number(nvl, "neg", addr->neg); | |||||
| nvlist_add_number(nvl, "port_op", addr->port_op); | |||||
| return (nvl); | |||||
| error: | |||||
| nvlist_destroy(nvl); | |||||
| return (NULL); | |||||
| } | |||||
| static int | static int | ||||
| pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) | pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) | ||||
| { | { | ||||
| int error = 0; | int error = 0; | ||||
| bzero(uid, sizeof(*uid)); | bzero(uid, sizeof(*uid)); | ||||
| PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL)); | PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL)); | ||||
| PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op)); | PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op)); | ||||
| PFNV_CHK(pf_validate_op(uid->op)); | PFNV_CHK(pf_validate_op(uid->op)); | ||||
| errout: | errout: | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static nvlist_t * | |||||
| pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid) | |||||
| { | |||||
| nvlist_t *nvl; | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) | |||||
| return (NULL); | |||||
| pf_uint32_array_nv(nvl, "uid", uid->uid, 2); | |||||
| nvlist_add_number(nvl, "op", uid->op); | |||||
| return (nvl); | |||||
| } | |||||
| static int | static int | ||||
| pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid) | pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid) | ||||
| { | { | ||||
| /* Cheat a little. These stucts are the same, other than the name of | /* Cheat a little. These stucts are the same, other than the name of | ||||
| * the first field. */ | * the first field. */ | ||||
| return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid)); | return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid)); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | |||||
| errout: | errout: | ||||
| pf_krule_free(rule); | pf_krule_free(rule); | ||||
| *prule = NULL; | *prule = NULL; | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static nvlist_t * | |||||
| pf_divert_to_nvdivert(const struct pf_krule *rule) | |||||
| { | |||||
| nvlist_t *nvl; | |||||
| nvlist_t *tmp; | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) | |||||
| return (NULL); | |||||
| tmp = pf_addr_to_nvaddr(&rule->divert.addr); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "addr", tmp); | |||||
| nvlist_add_number(nvl, "port", rule->divert.port); | |||||
| return (nvl); | |||||
| error: | |||||
| nvlist_destroy(nvl); | |||||
| return (NULL); | |||||
| } | |||||
| static nvlist_t * | |||||
| pf_krule_to_nvrule(const struct pf_krule *rule) | |||||
| { | |||||
| nvlist_t *nvl, *tmp; | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) | |||||
| return (nvl); | |||||
| nvlist_add_number(nvl, "nr", rule->nr); | |||||
| tmp = pf_rule_addr_to_nvrule_addr(&rule->src); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "src", tmp); | |||||
| tmp = pf_rule_addr_to_nvrule_addr(&rule->dst); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "dst", tmp); | |||||
| for (int i = 0; i < PF_SKIP_COUNT; i++) { | |||||
| nvlist_append_number_array(nvl, "skip", | |||||
| rule->skip[i].ptr ? rule->skip[i].ptr->nr : -1); | |||||
| } | |||||
| nvlist_add_string(nvl, "label", rule->label); | |||||
| nvlist_add_string(nvl, "ifname", rule->ifname); | |||||
| nvlist_add_string(nvl, "qname", rule->qname); | |||||
| nvlist_add_string(nvl, "pqname", rule->pqname); | |||||
| nvlist_add_string(nvl, "tagname", rule->tagname); | |||||
| nvlist_add_string(nvl, "match_tagname", rule->match_tagname); | |||||
| nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname); | |||||
| tmp = pf_pool_to_nvpool(&rule->rpool); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "rpool", tmp); | |||||
| nvlist_add_number(nvl, "evaluations", | |||||
| counter_u64_fetch(rule->evaluations)); | |||||
| for (int i = 0; i < 2; i++) { | |||||
| nvlist_append_number_array(nvl, "packets", | |||||
| counter_u64_fetch(rule->packets[i])); | |||||
| nvlist_append_number_array(nvl, "bytes", | |||||
| counter_u64_fetch(rule->bytes[i])); | |||||
| } | |||||
| nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint); | |||||
| nvlist_add_number(nvl, "rtableid", rule->rtableid); | |||||
| pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX); | |||||
| nvlist_add_number(nvl, "max_states", rule->max_states); | |||||
| nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes); | |||||
| nvlist_add_number(nvl, "max_src_states", rule->max_src_states); | |||||
| nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn); | |||||
| nvlist_add_number(nvl, "max_src_conn_rate.limit", | |||||
| rule->max_src_conn_rate.limit); | |||||
| nvlist_add_number(nvl, "max_src_conn_rate.seconds", | |||||
| rule->max_src_conn_rate.seconds); | |||||
| nvlist_add_number(nvl, "qid", rule->qid); | |||||
| nvlist_add_number(nvl, "pqid", rule->pqid); | |||||
| nvlist_add_number(nvl, "prob", rule->prob); | |||||
| nvlist_add_number(nvl, "cuid", rule->cuid); | |||||
| nvlist_add_number(nvl, "cpid", rule->cpid); | |||||
| nvlist_add_number(nvl, "states_cur", | |||||
| counter_u64_fetch(rule->states_cur)); | |||||
| nvlist_add_number(nvl, "states_tot", | |||||
| counter_u64_fetch(rule->states_tot)); | |||||
| nvlist_add_number(nvl, "src_nodes", | |||||
| counter_u64_fetch(rule->src_nodes)); | |||||
| nvlist_add_number(nvl, "return_icmp", rule->return_icmp); | |||||
| nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6); | |||||
| nvlist_add_number(nvl, "max_mss", rule->max_mss); | |||||
| nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags); | |||||
| tmp = pf_rule_uid_to_nvrule_uid(&rule->uid); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "uid", tmp); | |||||
| tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "gid", tmp); | |||||
| nvlist_add_number(nvl, "rule_flag", rule->rule_flag); | |||||
| nvlist_add_number(nvl, "action", rule->action); | |||||
| nvlist_add_number(nvl, "direction", rule->direction); | |||||
| nvlist_add_number(nvl, "log", rule->log); | |||||
| nvlist_add_number(nvl, "logif", rule->logif); | |||||
| nvlist_add_number(nvl, "quick", rule->quick); | |||||
| nvlist_add_number(nvl, "ifnot", rule->ifnot); | |||||
| nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not); | |||||
| nvlist_add_number(nvl, "natpass", rule->natpass); | |||||
| nvlist_add_number(nvl, "keep_state", rule->keep_state); | |||||
| nvlist_add_number(nvl, "af", rule->af); | |||||
| nvlist_add_number(nvl, "proto", rule->proto); | |||||
| nvlist_add_number(nvl, "type", rule->type); | |||||
| nvlist_add_number(nvl, "code", rule->code); | |||||
| nvlist_add_number(nvl, "flags", rule->flags); | |||||
| nvlist_add_number(nvl, "flagset", rule->flagset); | |||||
| nvlist_add_number(nvl, "min_ttl", rule->min_ttl); | |||||
| nvlist_add_number(nvl, "allow_opts", rule->allow_opts); | |||||
| nvlist_add_number(nvl, "rt", rule->rt); | |||||
| nvlist_add_number(nvl, "return_ttl", rule->return_ttl); | |||||
| nvlist_add_number(nvl, "tos", rule->tos); | |||||
| nvlist_add_number(nvl, "set_tos", rule->set_tos); | |||||
| nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative); | |||||
| nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard); | |||||
| nvlist_add_number(nvl, "flush", rule->flush); | |||||
| nvlist_add_number(nvl, "prio", rule->prio); | |||||
| pf_uint8_array_nv(nvl, "set_prio", &rule->prio, 2); | |||||
| tmp = pf_divert_to_nvdivert(rule); | |||||
| if (tmp == NULL) | |||||
| goto error; | |||||
| nvlist_add_nvlist(nvl, "divert", tmp); | |||||
| return (nvl); | |||||
| error: | |||||
| nvlist_destroy(nvl); | |||||
| return (NULL); | |||||
| } | |||||
| static int | static int | ||||
| pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule) | pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule) | ||||
| { | { | ||||
| int ret; | int ret; | ||||
| #ifndef INET | #ifndef INET | ||||
| if (rule->af == AF_INET) { | if (rule->af == AF_INET) { | ||||
| return (EAFNOSUPPORT); | return (EAFNOSUPPORT); | ||||
| ▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | 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)) | ||||
| switch (cmd) { | switch (cmd) { | ||||
| case DIOCGETRULES: | case DIOCGETRULES: | ||||
| case DIOCGETRULE: | case DIOCGETRULE: | ||||
| case DIOCGETRULENV: | |||||
| case DIOCGETADDRS: | case DIOCGETADDRS: | ||||
| case DIOCGETADDR: | case DIOCGETADDR: | ||||
| case DIOCGETSTATE: | case DIOCGETSTATE: | ||||
| case DIOCSETSTATUSIF: | case DIOCSETSTATUSIF: | ||||
| case DIOCGETSTATUS: | case DIOCGETSTATUS: | ||||
| case DIOCCLRSTATUS: | case DIOCCLRSTATUS: | ||||
| case DIOCNATLOOK: | case DIOCNATLOOK: | ||||
| case DIOCSETDEBUG: | case DIOCSETDEBUG: | ||||
| ▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | if (!(flags & FWRITE)) | ||||
| case DIOCRGETADDRS: | case DIOCRGETADDRS: | ||||
| case DIOCRGETASTATS: | case DIOCRGETASTATS: | ||||
| case DIOCRTSTADDRS: | case DIOCRTSTADDRS: | ||||
| case DIOCOSFPGET: | case DIOCOSFPGET: | ||||
| case DIOCGETSRCNODES: | case DIOCGETSRCNODES: | ||||
| case DIOCIGETIFACES: | case DIOCIGETIFACES: | ||||
| case DIOCGIFSPEEDV1: | case DIOCGIFSPEEDV1: | ||||
| case DIOCGIFSPEEDV0: | case DIOCGIFSPEEDV0: | ||||
| case DIOCGETRULENV: | |||||
| break; | break; | ||||
| case DIOCRCLRTABLES: | case DIOCRCLRTABLES: | ||||
| case DIOCRADDTABLES: | case DIOCRADDTABLES: | ||||
| case DIOCRDELTABLES: | case DIOCRDELTABLES: | ||||
| case DIOCRCLRTSTATS: | case DIOCRCLRTSTATS: | ||||
| case DIOCRCLRADDRS: | case DIOCRCLRADDRS: | ||||
| case DIOCRADDADDRS: | case DIOCRADDADDRS: | ||||
| case DIOCRDELADDRS: | case DIOCRDELADDRS: | ||||
| ▲ Show 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | if (pr->action == PF_GET_CLR_CNTR) { | ||||
| counter_u64_zero(rule->evaluations); | counter_u64_zero(rule->evaluations); | ||||
| for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
| counter_u64_zero(rule->packets[i]); | counter_u64_zero(rule->packets[i]); | ||||
| counter_u64_zero(rule->bytes[i]); | counter_u64_zero(rule->bytes[i]); | ||||
| } | } | ||||
| counter_u64_zero(rule->states_tot); | counter_u64_zero(rule->states_tot); | ||||
| } | } | ||||
| PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
| break; | |||||
| } | |||||
| case DIOCGETRULENV: { | |||||
| struct pfioc_nv *nv = (struct pfioc_nv *)addr; | |||||
| nvlist_t *nvrule = NULL; | |||||
| nvlist_t *nvl = NULL; | |||||
| struct pf_kruleset *ruleset; | |||||
| struct pf_krule *rule; | |||||
| void *nvlpacked = NULL; | |||||
| int rs_num, nr; | |||||
| bool clear_counter = false; | |||||
| #define ERROUT(x) do { error = (x); goto DIOCGETRULENV_error; } while (0) | |||||
| /* Copy the request in */ | |||||
| nvlpacked = malloc(nv->len, M_TEMP, M_WAITOK); | |||||
| if (nvlpacked == NULL) | |||||
| ERROUT(ENOMEM); | |||||
| error = copyin(nv->data, nvlpacked, nv->len); | |||||
| if (error) | |||||
| ERROUT(ENOMEM); | |||||
| nvl = nvlist_unpack(nvlpacked, nv->len, 0); | |||||
| if (nvl == NULL) | |||||
| ERROUT(EBADMSG); | |||||
| if (! nvlist_exists_string(nvl, "anchor")) | |||||
| ERROUT(EBADMSG); | |||||
| if (! nvlist_exists_number(nvl, "ruleset")) | |||||
| ERROUT(EBADMSG); | |||||
| if (! nvlist_exists_number(nvl, "ticket")) | |||||
| ERROUT(EBADMSG); | |||||
| if (! nvlist_exists_number(nvl, "nr")) | |||||
| ERROUT(EBADMSG); | |||||
| if (nvlist_exists_bool(nvl, "clear_counter")) | |||||
| clear_counter = nvlist_get_bool(nvl, "clear_counter"); | |||||
| if (clear_counter && !(flags & FWRITE)) | |||||
| ERROUT(EACCES); | |||||
| nr = nvlist_get_number(nvl, "nr"); | |||||
| PF_RULES_WLOCK(); | |||||
| ruleset = pf_find_kruleset(nvlist_get_string(nvl, "anchor")); | |||||
| if (ruleset == NULL) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(ENOENT); | |||||
| } | |||||
| rs_num = pf_get_ruleset_number(nvlist_get_number(nvl, "ruleset")); | |||||
| if (rs_num >= PF_RULESET_MAX) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(EINVAL); | |||||
| } | |||||
| if (nvlist_get_number(nvl, "ticket") != | |||||
| ruleset->rules[rs_num].active.ticket) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(EBUSY); | |||||
| break; | |||||
| } | |||||
| if ((error = nvlist_error(nvl))) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(error); | |||||
| } | |||||
| rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); | |||||
| while ((rule != NULL) && (rule->nr != nr)) | |||||
| rule = TAILQ_NEXT(rule, entries); | |||||
| if (rule == NULL) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(EBUSY); | |||||
| break; | |||||
| } | |||||
| nvrule = pf_krule_to_nvrule(rule); | |||||
| nvlist_destroy(nvl); | |||||
| nvl = nvlist_create(0); | |||||
| if (nvl == NULL) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(ENOMEM); | |||||
| } | |||||
| nvlist_add_number(nvl, "nr", nr); | |||||
| nvlist_add_nvlist(nvl, "rule", nvrule); | |||||
| nvrule = NULL; | |||||
| if (pf_kanchor_nvcopyout(ruleset, rule, nvl)) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(EBUSY); | |||||
| } | |||||
| free(nvlpacked, M_TEMP); | |||||
| nvlpacked = nvlist_pack(nvl, &nv->len); | |||||
| if (nvlpacked == NULL) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(ENOMEM); | |||||
| } | |||||
| if (nv->size == 0) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(0); | |||||
| } | |||||
| else if (nv->size < nv->len) { | |||||
| PF_RULES_WUNLOCK(); | |||||
| ERROUT(ENOSPC); | |||||
| } | |||||
| error = copyout(nvlpacked, nv->data, nv->len); | |||||
| if (clear_counter) { | |||||
| counter_u64_zero(rule->evaluations); | |||||
| for (int i = 0; i < 2; i++) { | |||||
| counter_u64_zero(rule->packets[i]); | |||||
| counter_u64_zero(rule->bytes[i]); | |||||
| } | |||||
| counter_u64_zero(rule->states_tot); | |||||
| } | |||||
| PF_RULES_WUNLOCK(); | |||||
| #undef ERROUT | |||||
| DIOCGETRULENV_error: | |||||
| free(nvlpacked, M_TEMP); | |||||
| nvlist_destroy(nvrule); | |||||
| nvlist_destroy(nvl); | |||||
| break; | break; | ||||
| } | } | ||||
| case DIOCCHANGERULE: { | case DIOCCHANGERULE: { | ||||
| struct pfioc_rule *pcr = (struct pfioc_rule *)addr; | struct pfioc_rule *pcr = (struct pfioc_rule *)addr; | ||||
| struct pf_kruleset *ruleset; | struct pf_kruleset *ruleset; | ||||
| struct pf_krule *oldrule = NULL, *newrule = NULL; | struct pf_krule *oldrule = NULL, *newrule = NULL; | ||||
| struct pfi_kkif *kif = NULL; | struct pfi_kkif *kif = NULL; | ||||
| ▲ Show 20 Lines • Show All 2,696 Lines • Show Last 20 Lines | |||||