mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-01 14:14:56 +00:00
pf: convert DIOCGETTIMEOUT/DIOCSETTIMEOUT to netlink
This commit is contained in:
parent
2c10bacdf4
commit
30bad751e8
|
@ -2522,3 +2522,87 @@ pfctl_set_debug(struct pfctl_handle *h, uint32_t level)
|
|||
|
||||
return (e.error);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds)
|
||||
{
|
||||
struct snl_writer nw;
|
||||
struct snl_errmsg_data e = {};
|
||||
struct nlmsghdr *hdr;
|
||||
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_SET_TIMEOUT);
|
||||
|
||||
snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout);
|
||||
snl_add_msg_attr_u32(&nw, PF_TO_SECONDS, seconds);
|
||||
|
||||
if ((hdr = snl_finalize_msg(&nw)) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
return (e.error);
|
||||
}
|
||||
|
||||
struct pfctl_nl_timeout {
|
||||
uint32_t seconds;
|
||||
};
|
||||
#define _OUT(_field) offsetof(struct pfctl_nl_timeout, _field)
|
||||
static struct snl_attr_parser ap_get_timeout[] = {
|
||||
{ .type = PF_TO_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 },
|
||||
};
|
||||
static struct snl_field_parser fp_get_timeout[] = {};
|
||||
#undef _OUT
|
||||
SNL_DECLARE_PARSER(get_timeout_parser, struct genlmsghdr, fp_get_timeout, ap_get_timeout);
|
||||
|
||||
int
|
||||
pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds)
|
||||
{
|
||||
struct snl_writer nw;
|
||||
struct pfctl_nl_timeout to = {};
|
||||
struct snl_errmsg_data e = {};
|
||||
struct nlmsghdr *hdr;
|
||||
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_GET_TIMEOUT);
|
||||
hdr->nlmsg_flags |= NLM_F_DUMP;
|
||||
|
||||
snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout);
|
||||
|
||||
if ((hdr = snl_finalize_msg(&nw)) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
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, &get_timeout_parser, &to))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seconds != NULL)
|
||||
*seconds = to.seconds;
|
||||
|
||||
return (e.error);
|
||||
}
|
||||
|
||||
|
|
|
@ -493,5 +493,7 @@ struct pfctl_natlook {
|
|||
int pfctl_natlook(struct pfctl_handle *h,
|
||||
const struct pfctl_natlook_key *k, struct pfctl_natlook *r);
|
||||
int pfctl_set_debug(struct pfctl_handle *h, uint32_t level);
|
||||
int pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds);
|
||||
int pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5165,7 +5165,7 @@ timeout_spec : STRING NUMBER
|
|||
yyerror("only positive values permitted");
|
||||
YYERROR;
|
||||
}
|
||||
if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
|
||||
if (pfctl_apply_timeout(pf, $1, $2, 0) != 0) {
|
||||
yyerror("unknown timeout %s", $1);
|
||||
free($1);
|
||||
YYERROR;
|
||||
|
@ -5179,7 +5179,7 @@ timeout_spec : STRING NUMBER
|
|||
yyerror("only positive values permitted");
|
||||
YYERROR;
|
||||
}
|
||||
if (pfctl_set_timeout(pf, "interval", $2, 0) != 0)
|
||||
if (pfctl_apply_timeout(pf, "interval", $2, 0) != 0)
|
||||
YYERROR;
|
||||
}
|
||||
;
|
||||
|
|
|
@ -1656,17 +1656,15 @@ pfctl_show_running(int dev)
|
|||
int
|
||||
pfctl_show_timeouts(int dev, int opts)
|
||||
{
|
||||
struct pfioc_tm pt;
|
||||
uint32_t seconds;
|
||||
int i;
|
||||
|
||||
if (opts & PF_OPT_SHOWALL)
|
||||
pfctl_print_title("TIMEOUTS:");
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
for (i = 0; pf_timeouts[i].name; i++) {
|
||||
pt.timeout = pf_timeouts[i].timeout;
|
||||
if (ioctl(dev, DIOCGETTIMEOUT, &pt))
|
||||
if (pfctl_get_timeout(pfh, pf_timeouts[i].timeout, &seconds))
|
||||
err(1, "DIOCGETTIMEOUT");
|
||||
printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
|
||||
printf("%-20s %10d", pf_timeouts[i].name, seconds);
|
||||
if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
|
||||
pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
|
||||
printf(" states");
|
||||
|
@ -2469,7 +2467,7 @@ pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
|
|||
}
|
||||
|
||||
int
|
||||
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
||||
pfctl_apply_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -2499,12 +2497,7 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
|
|||
int
|
||||
pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
|
||||
{
|
||||
struct pfioc_tm pt;
|
||||
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
pt.timeout = timeout;
|
||||
pt.seconds = seconds;
|
||||
if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) {
|
||||
if (pfctl_set_timeout(pf->h, timeout, seconds)) {
|
||||
warnx("DIOCSETTIMEOUT");
|
||||
return (1);
|
||||
}
|
||||
|
@ -2553,7 +2546,7 @@ pfctl_set_optimization(struct pfctl *pf, const char *opt)
|
|||
}
|
||||
|
||||
for (i = 0; hint[i].name; i++)
|
||||
if ((r = pfctl_set_timeout(pf, hint[i].name,
|
||||
if ((r = pfctl_apply_timeout(pf, hint[i].name,
|
||||
hint[i].timeout, 1)))
|
||||
return (r);
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ int pfctl_add_pool(struct pfctl *, struct pfctl_pool *, sa_family_t);
|
|||
void pfctl_move_pool(struct pfctl_pool *, struct pfctl_pool *);
|
||||
void pfctl_clear_pool(struct pfctl_pool *);
|
||||
|
||||
int pfctl_set_timeout(struct pfctl *, const char *, int, int);
|
||||
int pfctl_apply_timeout(struct pfctl *, const char *, int, int);
|
||||
int pfctl_set_reassembly(struct pfctl *, int, int);
|
||||
int pfctl_set_optimization(struct pfctl *, const char *);
|
||||
int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
||||
|
|
|
@ -2503,6 +2503,8 @@ int pf_ioctl_addrule(struct pf_krule *, uint32_t,
|
|||
uint32_t, const char *, const char *, uid_t uid,
|
||||
pid_t);
|
||||
void pf_ioctl_clear_status(void);
|
||||
int pf_ioctl_get_timeout(int, int *);
|
||||
int pf_ioctl_set_timeout(int, int, int *);
|
||||
|
||||
void pf_krule_free(struct pf_krule *);
|
||||
void pf_krule_clear_counters(struct pf_krule *);
|
||||
|
|
|
@ -2443,6 +2443,46 @@ pf_ioctl_clear_status(void)
|
|||
PF_RULES_WUNLOCK();
|
||||
}
|
||||
|
||||
int
|
||||
pf_ioctl_set_timeout(int timeout, int seconds, int *prev_seconds)
|
||||
{
|
||||
uint32_t old;
|
||||
|
||||
if (timeout < 0 || timeout >= PFTM_MAX ||
|
||||
seconds < 0)
|
||||
return (EINVAL);
|
||||
|
||||
PF_RULES_WLOCK();
|
||||
old = V_pf_default_rule.timeout[timeout];
|
||||
if (timeout == PFTM_INTERVAL && seconds == 0)
|
||||
seconds = 1;
|
||||
V_pf_default_rule.timeout[timeout] = seconds;
|
||||
if (timeout == PFTM_INTERVAL && seconds < old)
|
||||
wakeup(pf_purge_thread);
|
||||
|
||||
if (prev_seconds != NULL)
|
||||
*prev_seconds = old;
|
||||
|
||||
PF_RULES_WUNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pf_ioctl_get_timeout(int timeout, int *seconds)
|
||||
{
|
||||
PF_RULES_RLOCK_TRACKER;
|
||||
|
||||
if (timeout < 0 || timeout >= PFTM_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
PF_RULES_RLOCK();
|
||||
*seconds = V_pf_default_rule.timeout[timeout];
|
||||
PF_RULES_RUNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
|
||||
{
|
||||
|
@ -3838,35 +3878,16 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||
|
||||
case DIOCSETTIMEOUT: {
|
||||
struct pfioc_tm *pt = (struct pfioc_tm *)addr;
|
||||
int old;
|
||||
|
||||
if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
|
||||
pt->seconds < 0) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
PF_RULES_WLOCK();
|
||||
old = V_pf_default_rule.timeout[pt->timeout];
|
||||
if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
|
||||
pt->seconds = 1;
|
||||
V_pf_default_rule.timeout[pt->timeout] = pt->seconds;
|
||||
if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
|
||||
wakeup(pf_purge_thread);
|
||||
pt->seconds = old;
|
||||
PF_RULES_WUNLOCK();
|
||||
error = pf_ioctl_set_timeout(pt->timeout, pt->seconds,
|
||||
&pt->seconds);
|
||||
break;
|
||||
}
|
||||
|
||||
case DIOCGETTIMEOUT: {
|
||||
struct pfioc_tm *pt = (struct pfioc_tm *)addr;
|
||||
|
||||
if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
PF_RULES_RLOCK();
|
||||
pt->seconds = V_pf_default_rule.timeout[pt->timeout];
|
||||
PF_RULES_RUNLOCK();
|
||||
error = pf_ioctl_get_timeout(pt->timeout, &pt->seconds);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1349,6 +1349,67 @@ pf_handle_set_debug(struct nlmsghdr *hdr, struct nl_pstate *npt)
|
|||
return (0);
|
||||
}
|
||||
|
||||
struct pf_nl_set_timeout
|
||||
{
|
||||
uint32_t timeout;
|
||||
uint32_t seconds;
|
||||
};
|
||||
#define _OUT(_field) offsetof(struct pf_nl_set_timeout, _field)
|
||||
static const struct nlattr_parser nla_p_set_timeout[] = {
|
||||
{ .type = PF_TO_TIMEOUT, .off = _OUT(timeout), .cb = nlattr_get_uint32 },
|
||||
{ .type = PF_TO_SECONDS, .off = _OUT(seconds), .cb = nlattr_get_uint32 },
|
||||
};
|
||||
static const struct nlfield_parser nlf_p_set_timeout[] = {};
|
||||
#undef _OUT
|
||||
NL_DECLARE_PARSER(set_timeout_parser, struct genlmsghdr, nlf_p_set_timeout, nla_p_set_timeout);
|
||||
|
||||
static int
|
||||
pf_handle_set_timeout(struct nlmsghdr *hdr, struct nl_pstate *npt)
|
||||
{
|
||||
struct pf_nl_set_timeout attrs = {};
|
||||
int error;
|
||||
|
||||
error = nl_parse_nlmsg(hdr, &set_timeout_parser, npt, &attrs);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
return (pf_ioctl_set_timeout(attrs.timeout, attrs.seconds, NULL));
|
||||
}
|
||||
|
||||
static int
|
||||
pf_handle_get_timeout(struct nlmsghdr *hdr, struct nl_pstate *npt)
|
||||
{
|
||||
struct pf_nl_set_timeout attrs = {};
|
||||
struct nl_writer *nw = npt->nw;
|
||||
struct genlmsghdr *ghdr_new;
|
||||
int error;
|
||||
|
||||
error = nl_parse_nlmsg(hdr, &set_timeout_parser, npt, &attrs);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = pf_ioctl_get_timeout(attrs.timeout, &attrs.seconds);
|
||||
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_GET_TIMEOUT;
|
||||
ghdr_new->version = 0;
|
||||
ghdr_new->reserved = 0;
|
||||
|
||||
nlattr_add_u32(nw, PF_TO_SECONDS, attrs.seconds);
|
||||
|
||||
if (!nlmsg_end(nw)) {
|
||||
nlmsg_abort(nw);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const struct nlhdr_parser *all_parsers[] = {
|
||||
&state_parser,
|
||||
&addrule_parser,
|
||||
|
@ -1357,6 +1418,7 @@ static const struct nlhdr_parser *all_parsers[] = {
|
|||
&set_statusif_parser,
|
||||
&natlook_parser,
|
||||
&set_debug_parser,
|
||||
&set_timeout_parser,
|
||||
};
|
||||
|
||||
static int family_id;
|
||||
|
@ -1460,6 +1522,20 @@ 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_SET_TIMEOUT,
|
||||
.cmd_name = "SET_TIMEOUT",
|
||||
.cmd_cb = pf_handle_set_timeout,
|
||||
.cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL,
|
||||
.cmd_priv = PRIV_NETINET_PF,
|
||||
},
|
||||
{
|
||||
.cmd_num = PFNL_CMD_GET_TIMEOUT,
|
||||
.cmd_name = "GET_TIMEOUT",
|
||||
.cmd_cb = pf_handle_get_timeout,
|
||||
.cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL,
|
||||
.cmd_priv = PRIV_NETINET_PF,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
@ -50,6 +50,8 @@ enum {
|
|||
PFNL_CMD_CLEAR_STATUS = 12,
|
||||
PFNL_CMD_NATLOOK = 13,
|
||||
PFNL_CMD_SET_DEBUG = 14,
|
||||
PFNL_CMD_SET_TIMEOUT = 15,
|
||||
PFNL_CMD_GET_TIMEOUT = 16,
|
||||
__PFNL_CMD_MAX,
|
||||
};
|
||||
#define PFNL_CMD_MAX (__PFNL_CMD_MAX -1)
|
||||
|
@ -334,6 +336,12 @@ enum pf_set_debug_types_t {
|
|||
PF_SD_LEVEL = 1, /* u32 */
|
||||
};
|
||||
|
||||
enum pf_timeout_types_t {
|
||||
PF_TO_UNSPEC,
|
||||
PF_TO_TIMEOUT = 1, /* u32 */
|
||||
PF_TO_SECONDS = 2, /* u32 */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
void pf_nl_register(void);
|
||||
|
|
Loading…
Reference in a new issue