Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F95819076
D30359.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
48 KB
Referenced Files
None
Subscribers
None
D30359.diff
View Options
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -276,14 +276,6 @@
extern u_long pf_ioctl_maxcount;
-#define ERROUT_FUNCTION(target, x) \
- do { \
- error = (x); \
- SDT_PROBE3(pf, ioctl, function, error, __func__, error, \
- __LINE__); \
- goto target; \
- } while (0)
-
static void
pfattach_vnet(void)
{
@@ -1666,648 +1658,6 @@
rule->u_src_nodes = counter_u64_fetch(krule->src_nodes);
}
-static int
-pf_check_rule_addr(const struct pf_rule_addr *addr)
-{
-
- switch (addr->addr.type) {
- case PF_ADDR_ADDRMASK:
- case PF_ADDR_NOROUTE:
- case PF_ADDR_DYNIFTL:
- case PF_ADDR_TABLE:
- case PF_ADDR_URPFFAILED:
- case PF_ADDR_RANGE:
- break;
- default:
- return (EINVAL);
- }
-
- if (addr->addr.p.dyn != NULL) {
- return (EINVAL);
- }
-
- return (0);
-}
-
-static int
-pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *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
-pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
-{
- int error = 0;
-
- bzero(mape, sizeof(*mape));
- PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset));
- PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen));
- PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid));
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_mape_to_nvmape(const struct pf_mape_portset *mape)
-{
- nvlist_t *nvl;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_number(nvl, "offset", mape->offset);
- nvlist_add_number(nvl, "psidlen", mape->psidlen);
- nvlist_add_number(nvl, "psid", mape->psid);
-
- return (nvl);
-}
-
-static int
-pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
-{
- int error = 0;
-
- bzero(kpool, sizeof(*kpool));
-
- PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key)));
-
- if (nvlist_exists_nvlist(nvl, "counter")) {
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"),
- &kpool->counter));
- }
-
- PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx));
- PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2,
- NULL));
- PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts));
-
- if (nvlist_exists_nvlist(nvl, "mape")) {
- PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"),
- &kpool->mape));
- }
-
-errout:
- 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_destroy(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);
-
- tmp = pf_mape_to_nvmape(&pool->mape);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "mape", tmp);
- nvlist_destroy(tmp);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static int
-pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
-{
- int error = 0;
-
- bzero(addr, sizeof(*addr));
-
- PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type));
- PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags));
- if (addr->type == PF_ADDR_DYNIFTL)
- PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname,
- sizeof(addr->v.ifname)));
- if (addr->type == PF_ADDR_TABLE)
- PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname,
- sizeof(addr->v.tblname)));
-
- if (! nvlist_exists_nvlist(nvl, "addr"))
- return (EINVAL);
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"),
- &addr->v.a.addr));
-
- if (! nvlist_exists_nvlist(nvl, "mask"))
- return (EINVAL);
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"),
- &addr->v.a.mask));
-
- switch (addr->type) {
- case PF_ADDR_DYNIFTL:
- case PF_ADDR_TABLE:
- case PF_ADDR_RANGE:
- case PF_ADDR_ADDRMASK:
- case PF_ADDR_NOROUTE:
- case PF_ADDR_URPFFAILED:
- break;
- default:
- return (EINVAL);
- }
-
-errout:
- 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);
- if (addr->type == PF_ADDR_DYNIFTL)
- nvlist_add_string(nvl, "ifname", addr->v.ifname);
- if (addr->type == PF_ADDR_TABLE)
- 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);
- nvlist_destroy(tmp);
- tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "mask", tmp);
- nvlist_destroy(tmp);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static int
-pf_validate_op(uint8_t op)
-{
- switch (op) {
- case PF_OP_NONE:
- case PF_OP_IRG:
- case PF_OP_EQ:
- case PF_OP_NE:
- case PF_OP_LT:
- case PF_OP_LE:
- case PF_OP_GT:
- case PF_OP_GE:
- case PF_OP_XRG:
- case PF_OP_RRG:
- break;
- default:
- return (EINVAL);
- }
-
- return (0);
-}
-
-static int
-pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
-{
- int error = 0;
-
- if (! nvlist_exists_nvlist(nvl, "addr"))
- return (EINVAL);
-
- PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"),
- &addr->addr));
- PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL));
- PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg));
- PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op));
-
- PFNV_CHK(pf_validate_op(addr->port_op));
-
-errout:
- 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);
- nvlist_destroy(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
-pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
-{
- int error = 0;
-
- bzero(uid, sizeof(*uid));
-
- PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL));
- PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op));
-
- PFNV_CHK(pf_validate_op(uid->op));
-
-errout:
- 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
-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
- * the first field. */
- return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid));
-}
-
-static int
-pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule **prule)
-{
- struct pf_krule *rule;
- int error = 0;
-
-#define ERROUT(x) ERROUT_FUNCTION(errout, x)
-
- rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK | M_ZERO);
-
- PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr));
-
- if (! nvlist_exists_nvlist(nvl, "src"))
- ERROUT(EINVAL);
-
- error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
- &rule->src);
- if (error != 0)
- ERROUT(error);
-
- if (! nvlist_exists_nvlist(nvl, "dst"))
- ERROUT(EINVAL);
-
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
- &rule->dst));
-
- if (nvlist_exists_string(nvl, "label")) {
- PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0],
- sizeof(rule->label[0])));
- } else if (nvlist_exists_string_array(nvl, "labels")) {
- const char *const *strs;
- size_t items;
- int ret;
-
- strs = nvlist_get_string_array(nvl, "labels", &items);
- if (items > PF_RULE_MAX_LABEL_COUNT)
- ERROUT(E2BIG);
-
- for (size_t i = 0; i < items; i++) {
- ret = strlcpy(rule->label[i], strs[i],
- sizeof(rule->label[0]));
- if (ret >= sizeof(rule->label[0]))
- ERROUT(E2BIG);
- }
- }
-
- PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
- sizeof(rule->ifname)));
- PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
- PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname,
- sizeof(rule->pqname)));
- PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname,
- sizeof(rule->tagname)));
- PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname,
- sizeof(rule->match_tagname)));
- PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname,
- sizeof(rule->overload_tblname)));
-
- if (! nvlist_exists_nvlist(nvl, "rpool"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
- &rule->rpool));
-
- PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
-
- PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid));
- PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL));
- PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit",
- &rule->max_src_conn_rate.limit));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds",
- &rule->max_src_conn_rate.seconds));
- PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob));
- PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid));
- PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid));
-
- PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp));
- PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6));
-
- PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss));
- PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags));
-
- if (! nvlist_exists_nvlist(nvl, "uid"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"),
- &rule->uid));
-
- if (! nvlist_exists_nvlist(nvl, "gid"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"),
- &rule->gid));
-
- PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag));
- PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action));
- PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction));
- PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log));
- PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif));
- PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick));
- PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot));
- PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not));
- PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass));
-
- PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state));
- PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af));
- PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto));
- PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type));
- PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code));
- PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags));
- PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset));
- PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl));
- PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts));
- PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt));
- PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl));
- PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos));
- PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos));
- PFNV_CHK(pf_nvuint8(nvl, "anchor_relative", &rule->anchor_relative));
- PFNV_CHK(pf_nvuint8(nvl, "anchor_wildcard", &rule->anchor_wildcard));
-
- PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush));
- PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio));
-
- PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", &rule->prio, 2, NULL));
-
- if (nvlist_exists_nvlist(nvl, "divert")) {
- const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert");
-
- if (! nvlist_exists_nvlist(nvldivert, "addr"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"),
- &rule->divert.addr));
- PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port));
- }
-
- /* Validation */
-#ifndef INET
- if (rule->af == AF_INET)
- ERROUT(EAFNOSUPPORT);
-#endif /* INET */
-#ifndef INET6
- if (rule->af == AF_INET6)
- ERROUT(EAFNOSUPPORT);
-#endif /* INET6 */
-
- PFNV_CHK(pf_check_rule_addr(&rule->src));
- PFNV_CHK(pf_check_rule_addr(&rule->dst));
-
- *prule = rule;
-
- return (0);
-
-#undef ERROUT
-errout:
- pf_krule_free(rule);
- *prule = NULL;
-
- 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_destroy(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);
- nvlist_destroy(tmp);
- tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "dst", tmp);
- nvlist_destroy(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);
- }
-
- for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
- nvlist_append_string_array(nvl, "labels", rule->label[i]);
- }
- nvlist_add_string(nvl, "label", rule->label[0]);
- 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_destroy(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);
- nvlist_destroy(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_destroy(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);
- nvlist_destroy(tmp);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
static int
pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule)
{
@@ -2433,219 +1783,6 @@
return (0);
}
-static int
-pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
-{
- int error = 0;
-
- bzero(cmp, sizeof(*cmp));
-
- PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
- PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
- PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
-
-errout:
- return (error);
-}
-
-static int
-pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
- struct pf_kstate_kill *kill)
-{
- int error = 0;
-
- bzero(kill, sizeof(*kill));
-
- if (! nvlist_exists_nvlist(nvl, "cmp"))
- return (EINVAL);
-
- PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
- &kill->psk_pfcmp));
- PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
- PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
-
- if (! nvlist_exists_nvlist(nvl, "src"))
- return (EINVAL);
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
- &kill->psk_src));
- if (! nvlist_exists_nvlist(nvl, "dst"))
- return (EINVAL);
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
- &kill->psk_dst));
- if (nvlist_exists_nvlist(nvl, "rt_addr")) {
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(
- nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
- }
-
- PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
- sizeof(kill->psk_ifname)));
- PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
- sizeof(kill->psk_label)));
- if (nvlist_exists_bool(nvl, "kill_match"))
- kill->psk_kill_match = nvlist_get_bool(nvl, "kill_match");
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_state_key_to_nvstate_key(const struct pf_state_key *key)
-{
- nvlist_t *nvl, *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- for (int i = 0; i < 2; i++) {
- tmp = pf_addr_to_nvaddr(&key->addr[i]);
- if (tmp == NULL)
- goto errout;
- nvlist_append_nvlist_array(nvl, "addr", tmp);
- nvlist_append_number_array(nvl, "port", key->port[i]);
- }
- nvlist_add_number(nvl, "af", key->af);
- nvlist_add_number(nvl, "proto", key->proto);
-
- return (nvl);
-
-errout:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static nvlist_t *
-pf_state_scrub_to_nvstate_scrub(const struct pf_state_scrub *scrub)
-{
- nvlist_t *nvl;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_bool(nvl, "timestamp", scrub->pfss_flags & PFSS_TIMESTAMP);
- nvlist_add_number(nvl, "ttl", scrub->pfss_ttl);
- nvlist_add_number(nvl, "ts_mod", scrub->pfss_ts_mod);
-
- return (nvl);
-}
-
-static nvlist_t *
-pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
-{
- nvlist_t *nvl, *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- if (peer->scrub) {
- tmp = pf_state_scrub_to_nvstate_scrub(peer->scrub);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "scrub", tmp);
- nvlist_destroy(tmp);
- }
-
- nvlist_add_number(nvl, "seqlo", peer->seqlo);
- nvlist_add_number(nvl, "seqhi", peer->seqhi);
- nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
- nvlist_add_number(nvl, "max_win", peer->max_win);
- nvlist_add_number(nvl, "mss", peer->mss);
- nvlist_add_number(nvl, "state", peer->state);
- nvlist_add_number(nvl, "wscale", peer->wscale);
-
- return (nvl);
-
-errout:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-
-static nvlist_t *
-pf_state_to_nvstate(const struct pf_state *s)
-{
- nvlist_t *nvl, *tmp;
- uint32_t expire, flags = 0;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_number(nvl, "id", s->id);
- nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
- nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name);
-
- tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "stack_key", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "wire_key", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_state_peer_to_nvstate_peer(&s->src);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "src", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_state_peer_to_nvstate_peer(&s->dst);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "dst", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_addr_to_nvaddr(&s->rt_addr);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "rt_addr", tmp);
- nvlist_destroy(tmp);
-
- nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1);
- nvlist_add_number(nvl, "anchor",
- s->anchor.ptr ? s->anchor.ptr->nr : -1);
- nvlist_add_number(nvl, "nat_rule",
- s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1);
- nvlist_add_number(nvl, "creation", s->creation);
-
- expire = pf_state_expires(s);
- if (expire <= time_uptime)
- expire = 0;
- else
- expire = expire - time_uptime;
- nvlist_add_number(nvl, "expire", expire);
-
- for (int i = 0; i < 2; i++) {
- nvlist_append_number_array(nvl, "packets",
- counter_u64_fetch(s->packets[i]));
- nvlist_append_number_array(nvl, "bytes",
- counter_u64_fetch(s->bytes[i]));
- }
-
- nvlist_add_number(nvl, "creatorid", s->creatorid);
- nvlist_add_number(nvl, "direction", s->direction);
- nvlist_add_number(nvl, "log", s->log);
- nvlist_add_number(nvl, "state_flags", s->state_flags);
- nvlist_add_number(nvl, "timeout", s->timeout);
- if (s->src_node)
- flags |= PFSYNC_FLAG_SRCNODE;
- if (s->nat_src_node)
- flags |= PFSYNC_FLAG_NATSRCNODE;
- nvlist_add_number(nvl, "sync_flags", flags);
-
- return (nvl);
-
-errout:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
static int
pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
uint32_t pool_ticket, const char *anchor, const char *anchor_call,
@@ -3139,8 +2276,9 @@
if (! nvlist_exists_nvlist(nvl, "rule"))
ERROUT(EINVAL);
+ rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK | M_ZERO);
error = pf_nvrule_to_krule(nvlist_get_nvlist(nvl, "rule"),
- &rule);
+ rule);
if (error)
ERROUT(error);
diff --git a/sys/netpfil/pf/pf_nv.h b/sys/netpfil/pf/pf_nv.h
--- a/sys/netpfil/pf/pf_nv.h
+++ b/sys/netpfil/pf/pf_nv.h
@@ -28,8 +28,33 @@
#ifndef _PF_NV_H_
#define _PF_NV_H_
-#include <sys/types.h>
#include <sys/nv.h>
+#include <sys/sdt.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/pfvar.h>
+
+SDT_PROVIDER_DECLARE(pf);
+SDT_PROBE_DECLARE(pf, ioctl, function, error);
+SDT_PROBE_DECLARE(pf, ioctl, nvchk, error);
+
+#define ERROUT_FUNCTION(target, x) \
+ do { \
+ error = (x); \
+ SDT_PROBE3(pf, ioctl, function, error, __func__, error, \
+ __LINE__); \
+ goto target; \
+ } while (0)
+
+#define PFNV_CHK(x) do { \
+ error = (x); \
+ SDT_PROBE2(pf, ioctl, nvchk, error, error, __LINE__); \
+ if (error != 0) \
+ goto errout; \
+ } while (0)
int pf_nvbinary(const nvlist_t *, const char *, void *, size_t);
int pf_nvint(const nvlist_t *, const char *, int *);
@@ -56,11 +81,14 @@
int pf_nvstring(const nvlist_t *, const char *, char *, size_t);
-#define PFNV_CHK(x) do { \
- error = (x); \
- SDT_PROBE2(pf, ioctl, nvchk, error, error, __LINE__); \
- if (error != 0) \
- goto errout; \
- } while (0)
+/* Translation functions */
+
+int pf_check_rule_addr(const struct pf_rule_addr *);
+
+nvlist_t *pf_krule_to_nvrule(const struct pf_krule *);
+int pf_nvrule_to_krule(const nvlist_t *, struct pf_krule *);
+int pf_nvstate_kill_to_kstate_kill(const nvlist_t *,
+ struct pf_kstate_kill *);
+nvlist_t *pf_state_to_nvstate(const struct pf_state *);
#endif
diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -28,9 +28,13 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/limits.h>
+#include <sys/queue.h>
#include <sys/systm.h>
#include <netpfil/pf/pf_nv.h>
@@ -137,3 +141,850 @@
return (0);
}
+
+static int
+pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *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
+pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
+{
+ int error = 0;
+
+ bzero(mape, sizeof(*mape));
+ PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset));
+ PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen));
+ PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid));
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_mape_to_nvmape(const struct pf_mape_portset *mape)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_number(nvl, "offset", mape->offset);
+ nvlist_add_number(nvl, "psidlen", mape->psidlen);
+ nvlist_add_number(nvl, "psid", mape->psid);
+
+ return (nvl);
+}
+
+static int
+pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
+{
+ int error = 0;
+
+ bzero(kpool, sizeof(*kpool));
+
+ PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key)));
+
+ if (nvlist_exists_nvlist(nvl, "counter")) {
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"),
+ &kpool->counter));
+ }
+
+ PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx));
+ PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2,
+ NULL));
+ PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts));
+
+ if (nvlist_exists_nvlist(nvl, "mape")) {
+ PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"),
+ &kpool->mape));
+ }
+
+errout:
+ 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_destroy(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);
+
+ tmp = pf_mape_to_nvmape(&pool->mape);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "mape", tmp);
+ nvlist_destroy(tmp);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static int
+pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
+{
+ int error = 0;
+
+ bzero(addr, sizeof(*addr));
+
+ PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type));
+ PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags));
+ if (addr->type == PF_ADDR_DYNIFTL)
+ PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname,
+ sizeof(addr->v.ifname)));
+ if (addr->type == PF_ADDR_TABLE)
+ PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname,
+ sizeof(addr->v.tblname)));
+
+ if (! nvlist_exists_nvlist(nvl, "addr"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"),
+ &addr->v.a.addr));
+
+ if (! nvlist_exists_nvlist(nvl, "mask"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"),
+ &addr->v.a.mask));
+
+ switch (addr->type) {
+ case PF_ADDR_DYNIFTL:
+ case PF_ADDR_TABLE:
+ case PF_ADDR_RANGE:
+ case PF_ADDR_ADDRMASK:
+ case PF_ADDR_NOROUTE:
+ case PF_ADDR_URPFFAILED:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+errout:
+ 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);
+ if (addr->type == PF_ADDR_DYNIFTL)
+ nvlist_add_string(nvl, "ifname", addr->v.ifname);
+ if (addr->type == PF_ADDR_TABLE)
+ 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);
+ nvlist_destroy(tmp);
+ tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "mask", tmp);
+ nvlist_destroy(tmp);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static int
+pf_validate_op(uint8_t op)
+{
+ switch (op) {
+ case PF_OP_NONE:
+ case PF_OP_IRG:
+ case PF_OP_EQ:
+ case PF_OP_NE:
+ case PF_OP_LT:
+ case PF_OP_LE:
+ case PF_OP_GT:
+ case PF_OP_GE:
+ case PF_OP_XRG:
+ case PF_OP_RRG:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
+{
+ int error = 0;
+
+ if (! nvlist_exists_nvlist(nvl, "addr"))
+ return (EINVAL);
+
+ PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"),
+ &addr->addr));
+ PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL));
+ PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg));
+ PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op));
+
+ PFNV_CHK(pf_validate_op(addr->port_op));
+
+errout:
+ 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);
+ nvlist_destroy(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
+pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
+{
+ int error = 0;
+
+ bzero(uid, sizeof(*uid));
+
+ PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL));
+ PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op));
+
+ PFNV_CHK(pf_validate_op(uid->op));
+
+errout:
+ 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
+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
+ * the first field. */
+ return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid));
+}
+
+int
+pf_check_rule_addr(const struct pf_rule_addr *addr)
+{
+
+ switch (addr->addr.type) {
+ case PF_ADDR_ADDRMASK:
+ case PF_ADDR_NOROUTE:
+ case PF_ADDR_DYNIFTL:
+ case PF_ADDR_TABLE:
+ case PF_ADDR_URPFFAILED:
+ case PF_ADDR_RANGE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ if (addr->addr.p.dyn != NULL) {
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+
+int
+pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule)
+{
+ int error = 0;
+
+#define ERROUT(x) ERROUT_FUNCTION(errout, x)
+
+ PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr));
+
+ if (! nvlist_exists_nvlist(nvl, "src"))
+ ERROUT(EINVAL);
+
+ error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
+ &rule->src);
+ if (error != 0)
+ ERROUT(error);
+
+ if (! nvlist_exists_nvlist(nvl, "dst"))
+ ERROUT(EINVAL);
+
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
+ &rule->dst));
+
+ if (nvlist_exists_string(nvl, "label")) {
+ PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0],
+ sizeof(rule->label[0])));
+ } else if (nvlist_exists_string_array(nvl, "labels")) {
+ const char *const *strs;
+ size_t items;
+ int ret;
+
+ strs = nvlist_get_string_array(nvl, "labels", &items);
+ if (items > PF_RULE_MAX_LABEL_COUNT)
+ ERROUT(E2BIG);
+
+ for (size_t i = 0; i < items; i++) {
+ ret = strlcpy(rule->label[i], strs[i],
+ sizeof(rule->label[0]));
+ if (ret >= sizeof(rule->label[0]))
+ ERROUT(E2BIG);
+ }
+ }
+
+ PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
+ sizeof(rule->ifname)));
+ PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
+ PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname,
+ sizeof(rule->pqname)));
+ PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname,
+ sizeof(rule->tagname)));
+ PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname,
+ sizeof(rule->match_tagname)));
+ PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname,
+ sizeof(rule->overload_tblname)));
+
+ if (! nvlist_exists_nvlist(nvl, "rpool"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
+ &rule->rpool));
+
+ PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
+
+ PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid));
+ PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL));
+ PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit",
+ &rule->max_src_conn_rate.limit));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds",
+ &rule->max_src_conn_rate.seconds));
+ PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob));
+ PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid));
+ PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid));
+
+ PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp));
+ PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6));
+
+ PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss));
+ PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags));
+
+ if (! nvlist_exists_nvlist(nvl, "uid"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"),
+ &rule->uid));
+
+ if (! nvlist_exists_nvlist(nvl, "gid"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"),
+ &rule->gid));
+
+ PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag));
+ PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action));
+ PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction));
+ PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log));
+ PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif));
+ PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick));
+ PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot));
+ PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not));
+ PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass));
+
+ PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state));
+ PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af));
+ PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto));
+ PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type));
+ PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code));
+ PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags));
+ PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset));
+ PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl));
+ PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts));
+ PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt));
+ PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl));
+ PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos));
+ PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos));
+ PFNV_CHK(pf_nvuint8(nvl, "anchor_relative", &rule->anchor_relative));
+ PFNV_CHK(pf_nvuint8(nvl, "anchor_wildcard", &rule->anchor_wildcard));
+
+ PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush));
+ PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio));
+
+ PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", &rule->prio, 2, NULL));
+
+ if (nvlist_exists_nvlist(nvl, "divert")) {
+ const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert");
+
+ if (! nvlist_exists_nvlist(nvldivert, "addr"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"),
+ &rule->divert.addr));
+ PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port));
+ }
+
+ /* Validation */
+#ifndef INET
+ if (rule->af == AF_INET)
+ ERROUT(EAFNOSUPPORT);
+#endif /* INET */
+#ifndef INET6
+ if (rule->af == AF_INET6)
+ ERROUT(EAFNOSUPPORT);
+#endif /* INET6 */
+
+ PFNV_CHK(pf_check_rule_addr(&rule->src));
+ PFNV_CHK(pf_check_rule_addr(&rule->dst));
+
+ return (0);
+
+#undef ERROUT
+errout:
+ 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_destroy(tmp);
+ nvlist_add_number(nvl, "port", rule->divert.port);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+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);
+ nvlist_destroy(tmp);
+ tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "dst", tmp);
+ nvlist_destroy(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);
+ }
+
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
+ nvlist_append_string_array(nvl, "labels", rule->label[i]);
+ }
+ nvlist_add_string(nvl, "label", rule->label[0]);
+ 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_destroy(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);
+ nvlist_destroy(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_destroy(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);
+ nvlist_destroy(tmp);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static int
+pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
+{
+ int error = 0;
+
+ bzero(cmp, sizeof(*cmp));
+
+ PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
+ PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
+ PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
+
+errout:
+ return (error);
+}
+
+int
+pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
+ struct pf_kstate_kill *kill)
+{
+ int error = 0;
+
+ bzero(kill, sizeof(*kill));
+
+ if (! nvlist_exists_nvlist(nvl, "cmp"))
+ return (EINVAL);
+
+ PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
+ &kill->psk_pfcmp));
+ PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
+ PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
+
+ if (! nvlist_exists_nvlist(nvl, "src"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
+ &kill->psk_src));
+ if (! nvlist_exists_nvlist(nvl, "dst"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
+ &kill->psk_dst));
+ if (nvlist_exists_nvlist(nvl, "rt_addr")) {
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(
+ nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
+ }
+
+ PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
+ sizeof(kill->psk_ifname)));
+ PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
+ sizeof(kill->psk_label)));
+ if (nvlist_exists_bool(nvl, "kill_match"))
+ kill->psk_kill_match = nvlist_get_bool(nvl, "kill_match");
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_state_key_to_nvstate_key(const struct pf_state_key *key)
+{
+ nvlist_t *nvl, *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ for (int i = 0; i < 2; i++) {
+ tmp = pf_addr_to_nvaddr(&key->addr[i]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_append_nvlist_array(nvl, "addr", tmp);
+ nvlist_append_number_array(nvl, "port", key->port[i]);
+ }
+ nvlist_add_number(nvl, "af", key->af);
+ nvlist_add_number(nvl, "proto", key->proto);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static nvlist_t *
+pf_state_scrub_to_nvstate_scrub(const struct pf_state_scrub *scrub)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_bool(nvl, "timestamp", scrub->pfss_flags & PFSS_TIMESTAMP);
+ nvlist_add_number(nvl, "ttl", scrub->pfss_ttl);
+ nvlist_add_number(nvl, "ts_mod", scrub->pfss_ts_mod);
+
+ return (nvl);
+}
+
+static nvlist_t *
+pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
+{
+ nvlist_t *nvl, *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ if (peer->scrub) {
+ tmp = pf_state_scrub_to_nvstate_scrub(peer->scrub);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "scrub", tmp);
+ nvlist_destroy(tmp);
+ }
+
+ nvlist_add_number(nvl, "seqlo", peer->seqlo);
+ nvlist_add_number(nvl, "seqhi", peer->seqhi);
+ nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
+ nvlist_add_number(nvl, "max_win", peer->max_win);
+ nvlist_add_number(nvl, "mss", peer->mss);
+ nvlist_add_number(nvl, "state", peer->state);
+ nvlist_add_number(nvl, "wscale", peer->wscale);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+nvlist_t *
+pf_state_to_nvstate(const struct pf_state *s)
+{
+ nvlist_t *nvl, *tmp;
+ uint32_t expire, flags = 0;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_number(nvl, "id", s->id);
+ nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
+ nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name);
+
+ tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "stack_key", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "wire_key", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_state_peer_to_nvstate_peer(&s->src);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "src", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_state_peer_to_nvstate_peer(&s->dst);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "dst", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_addr_to_nvaddr(&s->rt_addr);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "rt_addr", tmp);
+ nvlist_destroy(tmp);
+
+ nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1);
+ nvlist_add_number(nvl, "anchor",
+ s->anchor.ptr ? s->anchor.ptr->nr : -1);
+ nvlist_add_number(nvl, "nat_rule",
+ s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1);
+ nvlist_add_number(nvl, "creation", s->creation);
+
+ expire = pf_state_expires(s);
+ if (expire <= time_uptime)
+ expire = 0;
+ else
+ expire = expire - time_uptime;
+ nvlist_add_number(nvl, "expire", expire);
+
+ for (int i = 0; i < 2; i++) {
+ nvlist_append_number_array(nvl, "packets",
+ counter_u64_fetch(s->packets[i]));
+ nvlist_append_number_array(nvl, "bytes",
+ counter_u64_fetch(s->bytes[i]));
+ }
+
+ nvlist_add_number(nvl, "creatorid", s->creatorid);
+ nvlist_add_number(nvl, "direction", s->direction);
+ nvlist_add_number(nvl, "log", s->log);
+ nvlist_add_number(nvl, "state_flags", s->state_flags);
+ nvlist_add_number(nvl, "timeout", s->timeout);
+ if (s->src_node)
+ flags |= PFSYNC_FLAG_SRCNODE;
+ if (s->nat_src_node)
+ flags |= PFSYNC_FLAG_NATSRCNODE;
+ nvlist_add_number(nvl, "sync_flags", flags);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Sep 23, 6:45 PM (10 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12569085
Default Alt Text
D30359.diff (48 KB)
Attached To
Mode
D30359: pf: Move nvlist conversion functions to pf_nv
Attached
Detach File
Event Timeline
Log In to Comment