aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libpfctl/libpfctl.c282
-rw-r--r--lib/libpfctl/libpfctl.h3
2 files changed, 284 insertions, 1 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index 2db3f0ede99f..cb9b377f7b6c 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -1229,7 +1229,287 @@ pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor,
anchor_call, false));
}
-int pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket,
+#define _OUT(_field) offsetof(struct pf_addr_wrap, _field)
+static const struct snl_attr_parser ap_addr_wrap[] = {
+ { .type = PF_AT_ADDR, .off = _OUT(v.a.addr), .cb = snl_attr_get_in6_addr },
+ { .type = PF_AT_MASK, .off = _OUT(v.a.mask), .cb = snl_attr_get_in6_addr },
+ { .type = PF_AT_IFNAME, .off = _OUT(v.ifname), .arg = (void *)IFNAMSIZ,.cb = snl_attr_copy_string },
+ { .type = PF_AT_TABLENAME, .off = _OUT(v.tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string },
+ { .type = PF_AT_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 },
+ { .type = PF_AT_IFLAGS, .off = _OUT(iflags), .cb = snl_attr_get_uint8 },
+ { .type = PF_AT_TBLCNT, .off = _OUT(p.tblcnt), .cb = snl_attr_get_uint32 },
+ { .type = PF_AT_DYNCNT, .off = _OUT(p.dyncnt), .cb = snl_attr_get_uint32 },
+};
+SNL_DECLARE_ATTR_PARSER(addr_wrap_parser, ap_addr_wrap);
+#undef _OUT
+
+#define _OUT(_field) offsetof(struct pf_rule_addr, _field)
+static struct snl_attr_parser ap_rule_addr[] = {
+ { .type = PF_RAT_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = snl_attr_get_nested },
+ { .type = PF_RAT_SRC_PORT, .off = _OUT(port[0]), .cb = snl_attr_get_uint16 },
+ { .type = PF_RAT_DST_PORT, .off = _OUT(port[1]), .cb = snl_attr_get_uint16 },
+ { .type = PF_RAT_NEG, .off = _OUT(neg), .cb = snl_attr_get_uint8 },
+ { .type = PF_RAT_OP, .off = _OUT(port_op), .cb = snl_attr_get_uint8 },
+};
+#undef _OUT
+SNL_DECLARE_ATTR_PARSER(rule_addr_parser, ap_rule_addr);
+
+struct snl_parsed_labels
+{
+ char labels[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
+ uint32_t i;
+};
+
+static bool
+snl_attr_get_pf_rule_labels(struct snl_state *ss, struct nlattr *nla,
+ const void *arg __unused, void *target)
+{
+ struct snl_parsed_labels *l = (struct snl_parsed_labels *)target;
+ bool ret;
+
+ if (l->i >= PF_RULE_MAX_LABEL_COUNT)
+ return (E2BIG);
+
+ ret = snl_attr_copy_string(ss, nla, (void *)PF_RULE_LABEL_SIZE,
+ l->labels[l->i]);
+ if (ret)
+ l->i++;
+
+ return (ret);
+}
+
+#define _OUT(_field) offsetof(struct nl_parsed_labels, _field)
+static const struct snl_attr_parser ap_labels[] = {
+ { .type = PF_LT_LABEL, .off = 0, .cb = snl_attr_get_pf_rule_labels },
+};
+SNL_DECLARE_ATTR_PARSER(rule_labels_parser, ap_labels);
+#undef _OUT
+
+static bool
+snl_attr_get_nested_pf_rule_labels(struct snl_state *ss, struct nlattr *nla,
+ const void *arg __unused, void *target)
+{
+ struct snl_parsed_labels parsed_labels = { };
+ bool error;
+
+ /* Assumes target points to the beginning of the structure */
+ error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &rule_labels_parser, &parsed_labels);
+ if (! error)
+ return (error);
+
+ memcpy(target, parsed_labels.labels, sizeof(parsed_labels));
+
+ return (true);
+}
+
+#define _OUT(_field) offsetof(struct pf_mape_portset, _field)
+static const struct snl_attr_parser ap_mape_portset[] = {
+ { .type = PF_MET_OFFSET, .off = _OUT(offset), .cb = snl_attr_get_uint8 },
+ { .type = PF_MET_PSID_LEN, .off = _OUT(psidlen), .cb = snl_attr_get_uint8 },
+ {. type = PF_MET_PSID, .off = _OUT(psid), .cb = snl_attr_get_uint16 },
+};
+SNL_DECLARE_ATTR_PARSER(mape_portset_parser, ap_mape_portset);
+#undef _OUT
+
+#define _OUT(_field) offsetof(struct pfctl_pool, _field)
+static const struct snl_attr_parser ap_pool[] = {
+ { .type = PF_PT_KEY, .off = _OUT(key), .arg = (void *)sizeof(struct pf_poolhashkey), .cb = snl_attr_get_bytes },
+ { .type = PF_PT_COUNTER, .off = _OUT(counter), .cb = snl_attr_get_in6_addr },
+ { .type = PF_PT_TBLIDX, .off = _OUT(tblidx), .cb = snl_attr_get_uint32 },
+ { .type = PF_PT_PROXY_SRC_PORT, .off = _OUT(proxy_port[0]), .cb = snl_attr_get_uint16 },
+ { .type = PF_PT_PROXY_DST_PORT, .off = _OUT(proxy_port[1]), .cb = snl_attr_get_uint16 },
+ { .type = PF_PT_OPTS, .off = _OUT(opts), .cb = snl_attr_get_uint8 },
+ { .type = PF_PT_MAPE, .off = _OUT(mape), .arg = &mape_portset_parser, .cb = snl_attr_get_nested },
+};
+SNL_DECLARE_ATTR_PARSER(pool_parser, ap_pool);
+#undef _OUT
+
+struct nl_parsed_timeouts
+{
+ uint32_t timeouts[PFTM_MAX];
+ uint32_t i;
+};
+
+static bool
+snl_attr_get_pf_timeout(struct snl_state *ss, struct nlattr *nla,
+ const void *arg __unused, void *target)
+{
+ struct nl_parsed_timeouts *t = (struct nl_parsed_timeouts *)target;
+ bool ret;
+
+ if (t->i >= PFTM_MAX)
+ return (E2BIG);
+
+ ret = snl_attr_get_uint32(ss, nla, NULL, &t->timeouts[t->i]);
+ if (ret)
+ t->i++;
+
+ return (ret);
+}
+
+#define _OUT(_field) offsetof(struct nl_parsed_timeout, _field)
+static const struct snl_attr_parser ap_timeouts[] = {
+ { .type = PF_TT_TIMEOUT, .off = 0, .cb = snl_attr_get_pf_timeout },
+};
+SNL_DECLARE_ATTR_PARSER(timeout_parser, ap_timeouts);
+#undef _OUT
+
+static bool
+snl_attr_get_nested_timeouts(struct snl_state *ss, struct nlattr *nla,
+ const void *arg __unused, void *target)
+{
+ struct nl_parsed_timeouts parsed_timeouts = { };
+ bool error;
+
+ /* Assumes target points to the beginning of the structure */
+ error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &timeout_parser, &parsed_timeouts);
+ if (! error)
+ return (error);
+
+ memcpy(target, parsed_timeouts.timeouts, sizeof(parsed_timeouts.timeouts));
+
+ return (true);
+}
+
+#define _OUT(_field) offsetof(struct pf_rule_uid, _field)
+static const struct snl_attr_parser ap_rule_uid[] = {
+ { .type = PF_RUT_UID_LOW, .off = _OUT(uid[0]), .cb = snl_attr_get_uint32 },
+ { .type = PF_RUT_UID_HIGH, .off = _OUT(uid[1]), .cb = snl_attr_get_uint32 },
+ { .type = PF_RUT_OP, .off = _OUT(op), .cb = snl_attr_get_uint8 },
+};
+SNL_DECLARE_ATTR_PARSER(rule_uid_parser, ap_rule_uid);
+#undef _OUT
+
+struct pfctl_nl_get_rule {
+ struct pfctl_rule r;
+ char anchor_call[MAXPATHLEN];
+};
+#define _OUT(_field) offsetof(struct pfctl_nl_get_rule, _field)
+static struct snl_attr_parser ap_getrule[] = {
+ { .type = PF_RT_SRC, .off = _OUT(r.src), .arg = &rule_addr_parser,.cb = snl_attr_get_nested },
+ { .type = PF_RT_DST, .off = _OUT(r.dst), .arg = &rule_addr_parser,.cb = snl_attr_get_nested },
+ { .type = PF_RT_RIDENTIFIER, .off = _OUT(r.ridentifier), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_LABELS, .off = _OUT(r.label), .arg = &rule_labels_parser,.cb = snl_attr_get_nested_pf_rule_labels },
+ { .type = PF_RT_IFNAME, .off = _OUT(r.ifname), .arg = (void *)IFNAMSIZ, .cb = snl_attr_copy_string },
+ { .type = PF_RT_QNAME, .off = _OUT(r.qname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string },
+ { .type = PF_RT_PQNAME, .off = _OUT(r.pqname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string },
+ { .type = PF_RT_TAGNAME, .off = _OUT(r.tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string },
+ { .type = PF_RT_MATCH_TAGNAME, .off = _OUT(r.match_tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string },
+ { .type = PF_RT_OVERLOAD_TBLNAME, .off = _OUT(r.overload_tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string },
+ { .type = PF_RT_RPOOL, .off = _OUT(r.rpool), .arg = &pool_parser, .cb = snl_attr_get_nested },
+ { .type = PF_RT_OS_FINGERPRINT, .off = _OUT(r.os_fingerprint), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_RTABLEID, .off = _OUT(r.rtableid), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_TIMEOUT, .off = _OUT(r.timeout), .arg = &timeout_parser, .cb = snl_attr_get_nested_timeouts },
+ { .type = PF_RT_MAX_STATES, .off = _OUT(r.max_states), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_MAX_SRC_NODES, .off = _OUT(r.max_src_nodes), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_MAX_SRC_STATES, .off = _OUT(r.max_src_states), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_MAX_SRC_CONN_RATE_LIMIT, .off = _OUT(r.max_src_conn_rate.limit), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_MAX_SRC_CONN_RATE_SECS, .off = _OUT(r.max_src_conn_rate.seconds), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_DNPIPE, .off = _OUT(r.dnpipe), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_DNRPIPE, .off = _OUT(r.dnrpipe), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_DNFLAGS, .off = _OUT(r.free_flags), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_NR, .off = _OUT(r.nr), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_PROB, .off = _OUT(r.prob), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_CUID, .off = _OUT(r.cuid), .cb = snl_attr_get_uint32 },
+ {. type = PF_RT_CPID, .off = _OUT(r.cpid), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_RETURN_ICMP, .off = _OUT(r.return_icmp), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_RETURN_ICMP6, .off = _OUT(r.return_icmp6), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_MAX_MSS, .off = _OUT(r.max_mss), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_SCRUB_FLAGS, .off = _OUT(r.scrub_flags), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_UID, .off = _OUT(r.uid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested },
+ { .type = PF_RT_GID, .off = _OUT(r.gid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested },
+ { .type = PF_RT_RULE_FLAG, .off = _OUT(r.rule_flag), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_ACTION, .off = _OUT(r.action), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_DIRECTION, .off = _OUT(r.direction), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_LOG, .off = _OUT(r.log), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_LOGIF, .off = _OUT(r.logif), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_QUICK, .off = _OUT(r.quick), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_IF_NOT, .off = _OUT(r.ifnot), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_MATCH_TAG_NOT, .off = _OUT(r.match_tag_not), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_NATPASS, .off = _OUT(r.natpass), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_KEEP_STATE, .off = _OUT(r.keep_state), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_AF, .off = _OUT(r.af), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_PROTO, .off = _OUT(r.proto), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_TYPE, .off = _OUT(r.type), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_CODE, .off = _OUT(r.code), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_FLAGS, .off = _OUT(r.flags), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_FLAGSET, .off = _OUT(r.flagset), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_MIN_TTL, .off = _OUT(r.min_ttl), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_ALLOW_OPTS, .off = _OUT(r.allow_opts), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_RT, .off = _OUT(r.rt), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_RETURN_TTL, .off = _OUT(r.return_ttl), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_TOS, .off = _OUT(r.tos), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_SET_TOS, .off = _OUT(r.set_tos), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_ANCHOR_RELATIVE, .off = _OUT(r.anchor_relative), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_ANCHOR_WILDCARD, .off = _OUT(r.anchor_wildcard), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_FLUSH, .off = _OUT(r.flush), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_PRIO, .off = _OUT(r.prio), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_SET_PRIO, .off = _OUT(r.set_prio[0]), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_SET_PRIO_REPLY, .off = _OUT(r.set_prio[1]), .cb = snl_attr_get_uint8 },
+ { .type = PF_RT_DIVERT_ADDRESS, .off = _OUT(r.divert.addr), .cb = snl_attr_get_in6_addr },
+ { .type = PF_RT_DIVERT_PORT, .off = _OUT(r.divert.port), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_PACKETS_IN, .off = _OUT(r.packets[0]), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_PACKETS_OUT, .off = _OUT(r.packets[1]), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_BYTES_IN, .off = _OUT(r.bytes[0]), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_BYTES_OUT, .off = _OUT(r.bytes[1]), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_EVALUATIONS, .off = _OUT(r.evaluations), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_TIMESTAMP, .off = _OUT(r.last_active_timestamp), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_STATES_CUR, .off = _OUT(r.states_cur), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_STATES_TOTAL, .off = _OUT(r.states_tot), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_SRC_NODES, .off = _OUT(r.src_nodes), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_ANCHOR_CALL, .off = _OUT(anchor_call), .arg = (void*)MAXPATHLEN, .cb = snl_attr_copy_string },
+};
+static struct snl_field_parser fp_getrule[] = {};
+#undef _OUT
+SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, fp_getrule, ap_getrule);
+
+int
+pfctl_get_clear_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket,
+ const char *anchor, uint32_t ruleset, struct pfctl_rule *rule,
+ char *anchor_call, bool clear)
+{
+ struct pfctl_nl_get_rule attrs = {};
+ struct snl_errmsg_data e = {};
+ struct nlmsghdr *hdr;
+ struct snl_writer nw;
+ uint32_t seq_id;
+ int family_id;
+
+ family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
+ if (family_id == 0)
+ return (ENOTSUP);
+
+ snl_init_writer(&h->ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULE);
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+
+ snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, anchor);
+ snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset);
+ snl_add_msg_attr_u32(&nw, PF_GR_NR, nr);
+ snl_add_msg_attr_u32(&nw, PF_GR_TICKET, ticket);
+ snl_add_msg_attr_u8(&nw, PF_GR_CLEAR, clear);
+
+ hdr = snl_finalize_msg(&nw);
+ if (hdr == NULL)
+ return (ENOMEM);
+
+ seq_id = hdr->nlmsg_seq;
+ if (! snl_send_message(&h->ss, hdr))
+ return (ENXIO);
+
+ while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
+ if (! snl_parse_nlmsg(&h->ss, hdr, &getrule_parser, &attrs))
+ continue;
+ }
+
+ memcpy(rule, &attrs.r, sizeof(attrs.r));
+ strlcpy(anchor_call, attrs.anchor_call, MAXPATHLEN);
+
+ return (e.error);
+}
+
+int
+pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket,
const char *anchor, uint32_t ruleset, struct pfctl_rule *rule,
char *anchor_call, bool clear)
{
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index cd72d04d6715..f05044a9a985 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -418,6 +418,9 @@ int pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket,
int pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket,
const char *anchor, uint32_t ruleset, struct pfctl_rule *rule,
char *anchor_call, bool clear);
+int pfctl_get_clear_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket,
+ const char *anchor, uint32_t ruleset, struct pfctl_rule *rule,
+ char *anchor_call, bool clear);
int pfctl_add_rule(int dev, const struct pfctl_rule *r,
const char *anchor, const char *anchor_call, uint32_t ticket,
uint32_t pool_ticket);