); } +static int +pf_handle_add_table(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + struct pfioc_table attrs = { 0 }; + struct nl_writer *nw = npt->nw; + struct genlmsghdr *ghdr_new; + int error; + + error = nl_parse_nlmsg(hdr, &table_parser, npt, &attrs); + if (error != 0) + return (error); + + PF_RULES_WLOCK(); + error = pfr_add_tables(&attrs.pfrio_table, 1, &attrs.pfrio_nadd, + attrs.pfrio_flags | PFR_FLAG_USERIOCTL); + PF_RULES_WUNLOCK(); + if (error != 0) + return (error); + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + return (ENOMEM); + + ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = PFNL_CMD_ADD_TABLE; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + nlattr_add_u32(nw, PF_T_NBR_ADDED, attrs.pfrio_nadd); + + if (!nlmsg_end(nw)) { + nlmsg_abort(nw); + return (ENOMEM); + } + + return (0); +} + static const struct nlhdr_parser *all_parsers[] = { &state_parser, &addrule_parser, @@ -2043,6 +2080,13 @@ static const struct genl_cmd pf_cmds[] = { .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, }, + { + .cmd_num = PFNL_CMD_ADD_TABLE, + .cmd_name = "ADD_TABLE", + .cmd_cb = pf_handle_add_table, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, + .cmd_priv = PRIV_NETINET_PF, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index d749ef3ab99e..38a44c2c4395 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -62,6 +62,7 @@ enum { PFNL_CMD_GET_RULESET = 24, PFNL_CMD_GET_SRCNODES = 25, PFNL_CMD_CLEAR_TABLES = 26, + PFNL_CMD_ADD_TABLE = 27, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) @@ -431,6 +432,7 @@ enum pf_tables_t { PF_T_TABLE_FLAGS = 3, /* u32 */ PF_T_FLAGS = 4, /* u32 */ PF_T_NBR_DELETED = 5, /* u32 */ + PF_T_NBR_ADDED = 6, /* u32 */ }; #ifdef _KERNEL