Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115684779
D47783.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
32 KB
Referenced Files
None
Subscribers
None
D47783.diff
View Options
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -174,7 +174,12 @@
char overload_tblname[PF_TABLE_NAME_SIZE];
TAILQ_ENTRY(pfctl_rule) entries;
- struct pfctl_pool rpool;
+ struct pfctl_pool nat;
+ union {
+ /* Alias old and new names. */
+ struct pfctl_pool rpool;
+ struct pfctl_pool rdr;
+ };
uint64_t evaluations;
uint64_t packets[2];
@@ -521,7 +526,7 @@
int pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit);
int pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit);
int pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket);
-int pfctl_add_addr(struct pfctl_handle *h, const struct pfioc_pooladdr *pa);
+int pfctl_add_addr(struct pfctl_handle *h, const struct pfioc_pooladdr *pa, int which);
int pfctl_get_addrs(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num,
uint8_t r_action, const char *anchor, uint32_t *nr);
int pfctl_get_addr(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num,
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -731,7 +731,7 @@
strlcpy(rule->overload_tblname, nvlist_get_string(nvl, "overload_tblname"),
PF_TABLE_NAME_SIZE);
- pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), &rule->rpool);
+ pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), &rule->rdr);
rule->evaluations = nvlist_get_number(nvl, "evaluations");
pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL);
@@ -1226,7 +1226,8 @@
snl_add_msg_attr_string(nw, PF_RT_TAGNAME, r->tagname);
snl_add_msg_attr_string(nw, PF_RT_MATCH_TAGNAME, r->match_tagname);
snl_add_msg_attr_string(nw, PF_RT_OVERLOAD_TBLNAME, r->overload_tblname);
- snl_add_msg_attr_rpool(nw, PF_RT_RPOOL, &r->rpool);
+ snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_RDR, &r->rdr);
+ snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_NAT, &r->nat);
snl_add_msg_attr_u32(nw, PF_RT_OS_FINGERPRINT, r->os_fingerprint);
snl_add_msg_attr_u32(nw, PF_RT_RTABLEID, r->rtableid);
snl_add_msg_attr_timeouts(nw, PF_RT_TIMEOUT, r->timeout);
@@ -1596,7 +1597,7 @@
{ .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_RPOOL_RDR, .off = _OUT(r.rdr), .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 },
@@ -1660,6 +1661,7 @@
{ .type = PF_RT_ANCHOR_CALL, .off = _OUT(anchor_call), .arg = (void*)MAXPATHLEN, .cb = snl_attr_copy_string },
{ .type = PF_RT_RCV_IFNAME, .off = _OUT(r.rcv_ifname), .arg = (void*)IFNAMSIZ, .cb = snl_attr_copy_string },
{ .type = PF_RT_MAX_SRC_CONN, .off = _OUT(r.max_src_conn), .cb = snl_attr_get_uint32 },
+ { .type = PF_RT_RPOOL_NAT, .off = _OUT(r.nat), .arg = &pool_parser, .cb = snl_attr_get_nested },
};
static struct snl_field_parser fp_getrule[] = {};
#undef _OUT
@@ -2771,7 +2773,7 @@
}
int
-pfctl_add_addr(struct pfctl_handle *h, const struct pfioc_pooladdr *pa)
+pfctl_add_addr(struct pfctl_handle *h, const struct pfioc_pooladdr *pa, int which __unused)
{
struct snl_writer nw;
struct snl_errmsg_data e = {};
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1687,7 +1687,7 @@
/* callbacks for rule/nat/rdr/addr */
int
-pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af)
+pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af, int which)
{
struct pf_pooladdr *pa;
int ret;
@@ -1701,7 +1701,7 @@
TAILQ_FOREACH(pa, &p->list, entries) {
memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if ((ret = pfctl_add_addr(pf->h, &pf->paddr)) != 0)
+ if ((ret = pfctl_add_addr(pf->h, &pf->paddr, which)) != 0)
errc(1, ret, "DIOCADDADDR");
}
}
@@ -2045,7 +2045,7 @@
was_present = false;
if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (pfctl_add_pool(pf, &r->rpool, r->af))
+ if (pfctl_add_pool(pf, &r->rpool, r->af, PF_RDR))
return (1);
error = pfctl_add_rule_h(pf->h, r, anchor, name, ticket,
pf->paddr.ticket);
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -281,7 +281,7 @@
int pfctl_append_eth_rule(struct pfctl *, struct pfctl_eth_rule *,
const char *);
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
-int pfctl_add_pool(struct pfctl *, struct pfctl_pool *, sa_family_t);
+int pfctl_add_pool(struct pfctl *, struct pfctl_pool *, sa_family_t, int);
void pfctl_move_pool(struct pfctl_pool *, struct pfctl_pool *);
void pfctl_clear_pool(struct pfctl_pool *);
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -785,7 +785,8 @@
char overload_tblname[PF_TABLE_NAME_SIZE];
TAILQ_ENTRY(pf_krule) entries;
- struct pf_kpool rpool;
+ struct pf_kpool nat;
+ struct pf_kpool rdr;
struct pf_counter_u64 evaluations;
struct pf_counter_u64 packets[2];
@@ -1604,8 +1605,10 @@
struct pf_addr *src; /* src address */
struct pf_addr *dst; /* dst address */
- u_int16_t *sport;
- u_int16_t *dport;
+ u_int16_t *sport;
+ u_int16_t *dport;
+ u_int16_t osport;
+ u_int16_t odport;
struct pf_mtag *pf_mtag;
struct pf_rule_actions act;
@@ -2192,7 +2195,7 @@
TAILQ_HEAD(pf_altqqueue, pf_altq);
VNET_DECLARE(struct pf_altqqueue, pf_altqs[4]);
#define V_pf_altqs VNET(pf_altqs)
-VNET_DECLARE(struct pf_kpalist, pf_pabuf);
+VNET_DECLARE(struct pf_kpalist, pf_pabuf[2]);
#define V_pf_pabuf VNET(pf_pabuf)
VNET_DECLARE(u_int32_t, ticket_altqs_active);
@@ -2527,6 +2530,20 @@
#endif /* _KERNEL */
#ifdef _KERNEL
+struct pf_nl_pooladdr {
+ u_int32_t action;
+ u_int32_t ticket;
+ u_int32_t nr;
+ u_int32_t r_num;
+ u_int8_t r_action;
+ u_int8_t r_last;
+ u_int8_t af;
+ char anchor[MAXPATHLEN];
+ struct pf_pooladdr addr;
+ /* Above this is identical to pfioc_pooladdr */
+ int which;
+};
+
VNET_DECLARE(struct pf_kanchor_global, pf_anchors);
#define V_pf_anchors VNET(pf_anchors)
VNET_DECLARE(struct pf_kanchor, pf_main_anchor);
@@ -2579,9 +2596,9 @@
int pf_ioctl_get_limit(int, unsigned int *);
int pf_ioctl_set_limit(int, unsigned int, unsigned int *);
int pf_ioctl_begin_addrs(uint32_t *);
-int pf_ioctl_add_addr(struct pfioc_pooladdr *);
-int pf_ioctl_get_addrs(struct pfioc_pooladdr *);
-int pf_ioctl_get_addr(struct pfioc_pooladdr *);
+int pf_ioctl_add_addr(struct pf_nl_pooladdr *);
+int pf_ioctl_get_addrs(struct pf_nl_pooladdr *);
+int pf_ioctl_get_addr(struct pf_nl_pooladdr *);
int pf_ioctl_get_rulesets(struct pfioc_ruleset *);
int pf_ioctl_get_ruleset(struct pfioc_ruleset *);
diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -582,7 +582,7 @@
* give up, as we can't be sure that we will pick the
* same one as the pfsync peer did.
*/
- rpool_first = TAILQ_FIRST(&(r->rpool.list));
+ rpool_first = TAILQ_FIRST(&(r->rdr.list));
if ((rpool_first == NULL) ||
(TAILQ_NEXT(rpool_first, entries) != NULL)) {
DPFPRINTF(PF_DEBUG_MISC,
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -157,7 +157,7 @@
/* state tables */
VNET_DEFINE(struct pf_altqqueue, pf_altqs[4]);
-VNET_DEFINE(struct pf_kpalist, pf_pabuf);
+VNET_DEFINE(struct pf_kpalist, pf_pabuf[2]);
VNET_DEFINE(struct pf_altqqueue *, pf_altqs_active);
VNET_DEFINE(struct pf_altqqueue *, pf_altq_ifs_active);
VNET_DEFINE(struct pf_altqqueue *, pf_altqs_inactive);
@@ -332,8 +332,7 @@
struct pf_kruleset **, struct inpcb *);
static int pf_create_state(struct pf_krule *, struct pf_krule *,
struct pf_krule *, struct pf_pdesc *,
- struct pf_state_key *, struct pf_state_key *,
- u_int16_t, u_int16_t, int *,
+ struct pf_state_key *, struct pf_state_key *, int *,
struct pf_kstate **, int, u_int16_t, u_int16_t,
struct pf_krule_slist *, struct pf_udp_mapping *);
static int pf_state_key_addr_setup(struct pf_pdesc *,
@@ -1027,7 +1026,7 @@
u_short reason = 0;
KASSERT((rule->rule_flag & PFRULE_SRCTRACK ||
- rule->rpool.opts & PF_POOL_STICKYADDR),
+ rule->rdr.opts & PF_POOL_STICKYADDR),
("%s for non-tracking rule %p", __func__, rule));
/*
@@ -1242,7 +1241,8 @@
TAILQ_INIT(&V_pf_altqs[1]);
TAILQ_INIT(&V_pf_altqs[2]);
TAILQ_INIT(&V_pf_altqs[3]);
- TAILQ_INIT(&V_pf_pabuf);
+ TAILQ_INIT(&V_pf_pabuf[0]);
+ TAILQ_INIT(&V_pf_pabuf[1]);
V_pf_altqs_active = &V_pf_altqs[0];
V_pf_altq_ifs_active = &V_pf_altqs[1];
V_pf_altqs_inactive = &V_pf_altqs[2];
@@ -4979,6 +4979,8 @@
sport = dport = 0;
break;
}
+ pd->osport = sport;
+ pd->odport = dport;
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
@@ -5327,7 +5329,7 @@
(pd->flags & PFDESC_TCP_NORM)))) {
int action;
action = pf_create_state(r, nr, a, pd, nk, sk,
- sport, dport, &rewrite, sm, tag, bproto_sum, bip_sum,
+ &rewrite, sm, tag, bproto_sum, bip_sum,
&match_rules, udp_mapping);
if (action != PF_PASS) {
pf_udp_mapping_release(udp_mapping);
@@ -5382,9 +5384,9 @@
static int
pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
struct pf_pdesc *pd, struct pf_state_key *nk, struct pf_state_key *sk,
- u_int16_t sport, u_int16_t dport, int *rewrite, struct pf_kstate **sm,
- int tag, u_int16_t bproto_sum, u_int16_t bip_sum,
- struct pf_krule_slist *match_rules, struct pf_udp_mapping *udp_mapping)
+ int *rewrite, struct pf_kstate **sm, int tag, u_int16_t bproto_sum,
+ u_int16_t bip_sum, struct pf_krule_slist *match_rules,
+ struct pf_udp_mapping *udp_mapping)
{
struct pf_kstate *s = NULL;
struct pf_ksrc_node *sn = NULL;
@@ -5405,14 +5407,14 @@
}
/* src node for filter rule */
if ((r->rule_flag & PFRULE_SRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR) &&
+ r->rdr.opts & PF_POOL_STICKYADDR) &&
(sn_reason = pf_insert_src_node(&sn, &snh, r, pd->src, pd->af,
&pd->act.rt_addr, pd->act.rt_kif)) != 0) {
REASON_SET(&reason, sn_reason);
goto csfailed;
}
/* src node for translation rule */
- if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
+ if (nr != NULL && (nr->rdr.opts & PF_POOL_STICKYADDR) &&
(sn_reason = pf_insert_src_node(&nsn, &nsnh, nr, &sk->addr[pd->sidx],
pd->af, &nk->addr[1], NULL)) != 0 ) {
REASON_SET(&reason, sn_reason);
@@ -5535,7 +5537,9 @@
if (nr == NULL) {
KASSERT((sk == NULL && nk == NULL), ("%s: nr %p sk %p, nk %p",
__func__, nr, sk, nk));
- sk = pf_state_key_setup(pd, pd->src, pd->dst, sport, dport);
+ MPASS(pd->sport == NULL || (pd->osport == *pd->sport));
+ MPASS(pd->dport == NULL || (pd->odport == *pd->dport));
+ sk = pf_state_key_setup(pd, pd->src, pd->dst, pd->osport, pd->odport);
if (sk == NULL)
goto csfailed;
nk = sk;
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
@@ -100,7 +100,7 @@
SDT_PROBE_DEFINE2(pf, ioctl, nvchk, error, "int", "int");
static struct pf_kpool *pf_get_kpool(const char *, u_int32_t, u_int8_t,
- u_int32_t, u_int8_t, u_int8_t, u_int8_t);
+ u_int32_t, u_int8_t, u_int8_t, u_int8_t, int);
static void pf_mv_kpool(struct pf_kpalist *, struct pf_kpalist *);
static void pf_empty_kpool(struct pf_kpalist *);
@@ -430,12 +430,14 @@
static struct pf_kpool *
pf_get_kpool(const char *anchor, u_int32_t ticket, u_int8_t rule_action,
u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
- u_int8_t check_ticket)
+ u_int8_t check_ticket, int which)
{
struct pf_kruleset *ruleset;
struct pf_krule *rule;
int rs_num;
+ MPASS(which == PF_RDR || which == PF_NAT);
+
ruleset = pf_find_kruleset(anchor);
if (ruleset == NULL)
return (NULL);
@@ -468,7 +470,10 @@
if (rule == NULL)
return (NULL);
- return (&rule->rpool);
+ if (which == PF_NAT)
+ return (&rule->nat);
+ else
+ return (&rule->rdr);
}
static void
@@ -605,7 +610,7 @@
if (rule->rcv_kif)
pfi_kkif_unref(rule->rcv_kif);
pf_kanchor_remove(rule);
- pf_empty_kpool(&rule->rpool.list);
+ pf_empty_kpool(&rule->rdr.list);
pf_krule_free(rule);
}
@@ -1824,7 +1829,8 @@
struct pf_krule *rule;
rule = malloc(sizeof(struct pf_krule), M_PFRULE, M_WAITOK | M_ZERO);
- mtx_init(&rule->rpool.mtx, "pf_krule_pool", NULL, MTX_DEF);
+ mtx_init(&rule->nat.mtx, "pf_krule_nat_pool", NULL, MTX_DEF);
+ mtx_init(&rule->rdr.mtx, "pf_krule_rdr_pool", NULL, MTX_DEF);
rule->timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
M_WAITOK | M_ZERO);
return (rule);
@@ -1862,7 +1868,8 @@
counter_u64_free(rule->src_nodes);
uma_zfree_pcpu(pf_timestamp_pcpu_zone, rule->timestamp);
- mtx_destroy(&rule->rpool.mtx);
+ mtx_destroy(&rule->nat.mtx);
+ mtx_destroy(&rule->rdr.mtx);
free(rule, M_PFRULE);
}
@@ -1966,7 +1973,7 @@
if (ret != 0)
return (ret);
- pf_pool_to_kpool(&rule->rpool, &krule->rpool);
+ pf_pool_to_kpool(&rule->rpool, &krule->rdr);
/* Don't allow userspace to set evaluations, packets or bytes. */
/* kif, anchor, overload_tbl are not copied over. */
@@ -2096,7 +2103,8 @@
rule->src_nodes = counter_u64_alloc(M_WAITOK);
rule->cuid = uid;
rule->cpid = pid;
- TAILQ_INIT(&rule->rpool.list);
+ TAILQ_INIT(&rule->rdr.list);
+ TAILQ_INIT(&rule->nat.list);
PF_CONFIG_LOCK();
PF_RULES_WLOCK();
@@ -2194,13 +2202,15 @@
(rule->set_prio[0] > PF_PRIO_MAX ||
rule->set_prio[1] > PF_PRIO_MAX))
error = EINVAL;
- TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
- if (pa->addr.type == PF_ADDR_TABLE) {
- pa->addr.p.tbl = pfr_attach_table(ruleset,
- pa->addr.v.tblname);
- if (pa->addr.p.tbl == NULL)
- error = ENOMEM;
- }
+ for (int i = 0; i < 2; i++) {
+ TAILQ_FOREACH(pa, &V_pf_pabuf[i], entries)
+ if (pa->addr.type == PF_ADDR_TABLE) {
+ pa->addr.p.tbl = pfr_attach_table(ruleset,
+ pa->addr.v.tblname);
+ if (pa->addr.p.tbl == NULL)
+ error = ENOMEM;
+ }
+ }
rule->overload_tbl = NULL;
if (rule->overload_tblname[0]) {
@@ -2212,14 +2222,15 @@
PFR_TFLAG_ACTIVE;
}
- pf_mv_kpool(&V_pf_pabuf, &rule->rpool.list);
+ pf_mv_kpool(&V_pf_pabuf[0], &rule->nat.list);
+ pf_mv_kpool(&V_pf_pabuf[1], &rule->rdr.list);
if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
(rule->action == PF_BINAT)) && rule->anchor == NULL) ||
(rule->rt > PF_NOPFROUTE)) &&
- (TAILQ_FIRST(&rule->rpool.list) == NULL))
+ (TAILQ_FIRST(&rule->rdr.list) == NULL))
error = EINVAL;
- if (rule->action == PF_PASS && rule->rpool.opts & PF_POOL_STICKYADDR &&
+ if (rule->action == PF_PASS && rule->rdr.opts & PF_POOL_STICKYADDR &&
!rule->keep_state) {
error = EINVAL;
}
@@ -2230,7 +2241,8 @@
ERROUT(error);
}
- rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
+ rule->nat.cur = TAILQ_FIRST(&rule->nat.list);
+ rule->rdr.cur = TAILQ_FIRST(&rule->rdr.list);
TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
rule, entries);
ruleset->rules[rs_num].inactive.rcount++;
@@ -2538,7 +2550,8 @@
pf_ioctl_begin_addrs(uint32_t *ticket)
{
PF_RULES_WLOCK();
- pf_empty_kpool(&V_pf_pabuf);
+ pf_empty_kpool(&V_pf_pabuf[0]);
+ pf_empty_kpool(&V_pf_pabuf[1]);
*ticket = ++V_ticket_pabuf;
PF_RULES_WUNLOCK();
@@ -2546,12 +2559,14 @@
}
int
-pf_ioctl_add_addr(struct pfioc_pooladdr *pp)
+pf_ioctl_add_addr(struct pf_nl_pooladdr *pp)
{
struct pf_kpooladdr *pa = NULL;
struct pfi_kkif *kif = NULL;
int error;
+ MPASS(pp->which == PF_RDR || pp->which == PF_NAT);
+
#ifndef INET
if (pp->af == AF_INET)
return (EAFNOSUPPORT);
@@ -2596,7 +2611,8 @@
PF_RULES_WUNLOCK();
goto out;
}
- TAILQ_INSERT_TAIL(&V_pf_pabuf, pa, entries);
+ TAILQ_INSERT_TAIL(&V_pf_pabuf[pp->which == PF_RDR ? 1 : 0],
+ pa, entries);
PF_RULES_WUNLOCK();
return (0);
@@ -2607,19 +2623,21 @@
}
int
-pf_ioctl_get_addrs(struct pfioc_pooladdr *pp)
+pf_ioctl_get_addrs(struct pf_nl_pooladdr *pp)
{
struct pf_kpool *pool;
struct pf_kpooladdr *pa;
PF_RULES_RLOCK_TRACKER;
+ MPASS(pp->which == PF_RDR || pp->which == PF_NAT);
+
pp->anchor[sizeof(pp->anchor) - 1] = 0;
pp->nr = 0;
PF_RULES_RLOCK();
pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
- pp->r_num, 0, 1, 0);
+ pp->r_num, 0, 1, 0, pp->which);
if (pool == NULL) {
PF_RULES_RUNLOCK();
return (EBUSY);
@@ -2632,19 +2650,21 @@
}
int
-pf_ioctl_get_addr(struct pfioc_pooladdr *pp)
+pf_ioctl_get_addr(struct pf_nl_pooladdr *pp)
{
struct pf_kpool *pool;
struct pf_kpooladdr *pa;
u_int32_t nr = 0;
+ MPASS(pp->which == PF_RDR || pp->which == PF_NAT);
+
PF_RULES_RLOCK_TRACKER;
pp->anchor[sizeof(pp->anchor) - 1] = 0;
PF_RULES_RLOCK();
pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
- pp->r_num, 0, 1, 1);
+ pp->r_num, 0, 1, 1, pp->which);
if (pool == NULL) {
PF_RULES_RUNLOCK();
return (EBUSY);
@@ -3626,7 +3646,8 @@
newrule->src_nodes = counter_u64_alloc(M_WAITOK);
newrule->cuid = td->td_ucred->cr_ruid;
newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
- TAILQ_INIT(&newrule->rpool.list);
+ TAILQ_INIT(&newrule->nat.list);
+ TAILQ_INIT(&newrule->rdr.list);
}
#define ERROUT(x) ERROUT_IOCTL(DIOCCHANGERULE_error, x)
@@ -3723,14 +3744,16 @@
error = ENOMEM;
if (pf_kanchor_setup(newrule, ruleset, pcr->anchor_call))
error = EINVAL;
- TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
- if (pa->addr.type == PF_ADDR_TABLE) {
- pa->addr.p.tbl =
- pfr_attach_table(ruleset,
- pa->addr.v.tblname);
- if (pa->addr.p.tbl == NULL)
- error = ENOMEM;
- }
+ for (int i = 0; i < 2; i++) {
+ TAILQ_FOREACH(pa, &V_pf_pabuf[i], entries)
+ if (pa->addr.type == PF_ADDR_TABLE) {
+ pa->addr.p.tbl =
+ pfr_attach_table(ruleset,
+ pa->addr.v.tblname);
+ if (pa->addr.p.tbl == NULL)
+ error = ENOMEM;
+ }
+ }
newrule->overload_tbl = NULL;
if (newrule->overload_tblname[0]) {
@@ -3743,13 +3766,14 @@
PFR_TFLAG_ACTIVE;
}
- pf_mv_kpool(&V_pf_pabuf, &newrule->rpool.list);
+ pf_mv_kpool(&V_pf_pabuf[0], &newrule->nat.list);
+ pf_mv_kpool(&V_pf_pabuf[1], &newrule->rdr.list);
if (((((newrule->action == PF_NAT) ||
(newrule->action == PF_RDR) ||
(newrule->action == PF_BINAT) ||
(newrule->rt > PF_NOPFROUTE)) &&
!newrule->anchor)) &&
- (TAILQ_FIRST(&newrule->rpool.list) == NULL))
+ (TAILQ_FIRST(&newrule->rdr.list) == NULL))
error = EINVAL;
if (error) {
@@ -3759,9 +3783,11 @@
break;
}
- newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
+ newrule->nat.cur = TAILQ_FIRST(&newrule->nat.list);
+ newrule->rdr.cur = TAILQ_FIRST(&newrule->rdr.list);
}
- pf_empty_kpool(&V_pf_pabuf);
+ pf_empty_kpool(&V_pf_pabuf[0]);
+ pf_empty_kpool(&V_pf_pabuf[1]);
if (pcr->action == PF_CHANGE_ADD_HEAD)
oldrule = TAILQ_FIRST(
@@ -4390,22 +4416,35 @@
case DIOCADDADDR: {
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+ struct pf_nl_pooladdr npp = {};
- error = pf_ioctl_add_addr(pp);
+ npp.which = PF_RDR;
+ memcpy(&npp, pp, sizeof(*pp));
+ error = pf_ioctl_add_addr(&npp);
break;
}
case DIOCGETADDRS: {
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+ struct pf_nl_pooladdr npp = {};
+
+ npp.which = PF_RDR;
+ memcpy(&npp, pp, sizeof(*pp));
+ error = pf_ioctl_get_addrs(&npp);
+ memcpy(pp, &npp, sizeof(*pp));
- error = pf_ioctl_get_addrs(pp);
break;
}
case DIOCGETADDR: {
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+ struct pf_nl_pooladdr npp = {};
+
+ npp.which = PF_RDR;
+ memcpy(&npp, pp, sizeof(*pp));
+ error = pf_ioctl_get_addr(&npp);
+ memcpy(pp, &npp, sizeof(*pp));
- error = pf_ioctl_get_addr(pp);
break;
}
@@ -4460,7 +4499,7 @@
ERROUT(EBUSY);
pool = pf_get_kpool(pca->anchor, pca->ticket, pca->r_action,
- pca->r_num, pca->r_last, 1, 1);
+ pca->r_num, pca->r_last, 1, 1, PF_RDR);
if (pool == NULL)
ERROUT(EBUSY);
diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -149,8 +149,8 @@
if (r->action == PF_BINAT && pd->dir == PF_IN) {
src = &r->dst;
- if (r->rpool.cur != NULL)
- xdst = &r->rpool.cur->addr;
+ if (r->rdr.cur != NULL)
+ xdst = &r->rdr.cur->addr;
} else {
src = &r->src;
dst = &r->dst;
@@ -240,7 +240,7 @@
* from the mapping. In this case we have to look up the src_node as
* pf_map_addr would.
*/
- if (proto == IPPROTO_UDP && (r->rpool.opts & PF_POOL_ENDPI)) {
+ if (proto == IPPROTO_UDP && (r->rdr.opts & PF_POOL_ENDPI)) {
struct pf_udp_endpoint_cmp udp_source;
bzero(&udp_source, sizeof(udp_source));
@@ -252,8 +252,8 @@
PF_ACPY(naddr, &(*udp_mapping)->endpoints[1].addr, af);
*nport = (*udp_mapping)->endpoints[1].port;
/* Try to find a src_node as per pf_map_addr(). */
- if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
- (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE)
+ if (*sn == NULL && r->rdr.opts & PF_POOL_STICKYADDR &&
+ (r->rdr.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE)
*sn = pf_find_src_node(saddr, r, af, sh, false);
if (*sn != NULL)
PF_SRC_NODE_UNLOCK(*sn);
@@ -363,7 +363,7 @@
tmp = cut;
for (tmp -= 1; tmp >= low && tmp <= 0xffff; --tmp) {
if (proto == IPPROTO_UDP &&
- (r->rpool.opts & PF_POOL_ENDPI)) {
+ (r->rdr.opts & PF_POOL_ENDPI)) {
(*udp_mapping)->endpoints[1].port = htons(tmp);
if (pf_udp_mapping_insert(*udp_mapping) == 0) {
*nport = htons(tmp);
@@ -379,7 +379,7 @@
}
}
- switch (r->rpool.opts & PF_POOL_TYPEMASK) {
+ switch (r->rdr.opts & PF_POOL_TYPEMASK) {
case PF_POOL_RANDOM:
case PF_POOL_ROUNDROBIN:
/*
@@ -423,13 +423,13 @@
uint16_t i, ahigh, cut;
int ashift, psidshift;
- ashift = 16 - r->rpool.mape.offset;
- psidshift = ashift - r->rpool.mape.psidlen;
- psmask = r->rpool.mape.psid & ((1U << r->rpool.mape.psidlen) - 1);
+ ashift = 16 - r->rdr.mape.offset;
+ psidshift = ashift - r->rdr.mape.psidlen;
+ psmask = r->rdr.mape.psid & ((1U << r->rdr.mape.psidlen) - 1);
psmask = psmask << psidshift;
highmask = (1U << psidshift) - 1;
- ahigh = (1U << r->rpool.mape.offset) - 1;
+ ahigh = (1U << r->rdr.mape.offset) - 1;
cut = arc4random() & ahigh;
if (cut == 0)
cut = 1;
@@ -454,7 +454,7 @@
struct pf_addr *naddr, struct pfi_kkif **nkif, struct pf_addr *init_addr)
{
u_short reason = PFRES_MATCH;
- struct pf_kpool *rpool = &r->rpool;
+ struct pf_kpool *rpool = &r->rdr;
struct pf_addr *raddr = NULL, *rmask = NULL;
mtx_lock(&rpool->mtx);
@@ -629,7 +629,7 @@
struct pf_ksrc_node **sn, struct pf_srchash **sh)
{
u_short reason = 0;
- struct pf_kpool *rpool = &r->rpool;
+ struct pf_kpool *rpool = &r->rdr;
KASSERT(*sn == NULL, ("*sn not NULL"));
@@ -638,8 +638,8 @@
* Request the sh to be unlocked if sn was not found, as we never
* insert a new sn when parsing the ruleset.
*/
- if (r->rpool.opts & PF_POOL_STICKYADDR &&
- (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE)
+ if (r->rdr.opts & PF_POOL_STICKYADDR &&
+ (r->rdr.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE)
*sn = pf_find_src_node(saddr, r, af, sh, false);
if (*sn != NULL) {
@@ -763,19 +763,19 @@
low = 1;
high = 65535;
} else {
- low = r->rpool.proxy_port[0];
- high = r->rpool.proxy_port[1];
+ low = r->rdr.proxy_port[0];
+ high = r->rdr.proxy_port[1];
}
- if (r->rpool.mape.offset > 0) {
+ if (r->rdr.mape.offset > 0) {
if (pf_get_mape_sport(pd->af, pd->proto, r, saddr,
sport, daddr, dport, naddr, nportp, &sn, &sh,
udp_mapping)) {
DPFPRINTF(PF_DEBUG_MISC,
("pf: MAP-E port allocation (%u/%u/%u)"
" failed\n",
- r->rpool.mape.offset,
- r->rpool.mape.psidlen,
- r->rpool.mape.psid));
+ r->rdr.mape.offset,
+ r->rdr.mape.psidlen,
+ r->rdr.mape.psid));
reason = PFRES_MAPFAILED;
goto notrans;
}
@@ -784,7 +784,7 @@
udp_mapping)) {
DPFPRINTF(PF_DEBUG_MISC,
("pf: NAT proxy port allocation (%u-%u) failed\n",
- r->rpool.proxy_port[0], r->rpool.proxy_port[1]));
+ r->rdr.proxy_port[0], r->rdr.proxy_port[1]));
reason = PFRES_MAPFAILED;
goto notrans;
}
@@ -792,41 +792,41 @@
case PF_BINAT:
switch (pd->dir) {
case PF_OUT:
- if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
+ if (r->rdr.cur->addr.type == PF_ADDR_DYNIFTL){
switch (pd->af) {
#ifdef INET
case AF_INET:
- if (r->rpool.cur->addr.p.dyn->
+ if (r->rdr.cur->addr.p.dyn->
pfid_acnt4 < 1) {
reason = PFRES_MAPFAILED;
goto notrans;
}
PF_POOLMASK(naddr,
- &r->rpool.cur->addr.p.dyn->
+ &r->rdr.cur->addr.p.dyn->
pfid_addr4,
- &r->rpool.cur->addr.p.dyn->
+ &r->rdr.cur->addr.p.dyn->
pfid_mask4, saddr, AF_INET);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- if (r->rpool.cur->addr.p.dyn->
+ if (r->rdr.cur->addr.p.dyn->
pfid_acnt6 < 1) {
reason = PFRES_MAPFAILED;
goto notrans;
}
PF_POOLMASK(naddr,
- &r->rpool.cur->addr.p.dyn->
+ &r->rdr.cur->addr.p.dyn->
pfid_addr6,
- &r->rpool.cur->addr.p.dyn->
+ &r->rdr.cur->addr.p.dyn->
pfid_mask6, saddr, AF_INET6);
break;
#endif /* INET6 */
}
} else
PF_POOLMASK(naddr,
- &r->rpool.cur->addr.v.a.addr,
- &r->rpool.cur->addr.v.a.mask, saddr,
+ &r->rdr.cur->addr.v.a.addr,
+ &r->rdr.cur->addr.v.a.mask, saddr,
pd->af);
break;
case PF_IN:
@@ -871,27 +871,27 @@
reason = pf_map_addr_sn(pd->af, r, saddr, naddr, NULL, NULL, &sn, &sh);
if (reason != 0)
goto notrans;
- if ((r->rpool.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
- PF_POOLMASK(naddr, naddr, &r->rpool.cur->addr.v.a.mask,
+ if ((r->rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
+ PF_POOLMASK(naddr, naddr, &r->rdr.cur->addr.v.a.mask,
daddr, pd->af);
/* Do not change SCTP ports. */
if (pd->proto == IPPROTO_SCTP)
break;
- if (r->rpool.proxy_port[1]) {
+ if (r->rdr.proxy_port[1]) {
uint32_t tmp_nport;
tmp_nport = ((ntohs(dport) - ntohs(r->dst.port[0])) %
- (r->rpool.proxy_port[1] - r->rpool.proxy_port[0] +
- 1)) + r->rpool.proxy_port[0];
+ (r->rdr.proxy_port[1] - r->rdr.proxy_port[0] +
+ 1)) + r->rdr.proxy_port[0];
/* Wrap around if necessary. */
if (tmp_nport > 65535)
tmp_nport -= 65535;
nport = htons((uint16_t)tmp_nport);
- } else if (r->rpool.proxy_port[0])
- nport = htons(r->rpool.proxy_port[0]);
+ } else if (r->rdr.proxy_port[0])
+ nport = htons(r->rdr.proxy_port[0]);
else
nport = dport;
diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h
--- a/sys/netpfil/pf/pf_nl.h
+++ b/sys/netpfil/pf/pf_nl.h
@@ -198,7 +198,7 @@
PF_RT_TAGNAME = 8, /* string */
PF_RT_MATCH_TAGNAME = 9, /* string */
PF_RT_OVERLOAD_TBLNAME = 10, /* string */
- PF_RT_RPOOL = 11, /* nested, pf_rpool_type_t */
+ PF_RT_RPOOL_RDR = 11, /* nested, pf_rpool_type_t */
PF_RT_OS_FINGERPRINT = 12, /* u32 */
PF_RT_RTABLEID = 13, /* u32 */
PF_RT_TIMEOUT = 14, /* nested, pf_timeout_type_t */
@@ -262,6 +262,7 @@
PF_RT_ANCHOR_CALL = 72, /* string */
PF_RT_RCV_IFNAME = 73, /* string */
PF_RT_MAX_SRC_CONN = 74, /* u32 */
+ PF_RT_RPOOL_NAT = 75, /* nested, pf_rpool_type_t */
};
enum pf_addrule_type_t {
@@ -381,6 +382,7 @@
PF_AA_AF = 7, /* u8 */
PF_AA_ANCHOR = 8, /* string */
PF_AA_ADDR = 9, /* nested, pf_pooladdr */
+ PF_AA_WHICH = 10, /* u32 */
};
enum pf_get_rulesets_types_t {
diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c
--- a/sys/netpfil/pf/pf_nl.c
+++ b/sys/netpfil/pf/pf_nl.c
@@ -678,7 +678,7 @@
{ .type = PF_RT_TAGNAME, .off = _OUT(tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = nlattr_get_chara },
{ .type = PF_RT_MATCH_TAGNAME, .off = _OUT(match_tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = nlattr_get_chara },
{ .type = PF_RT_OVERLOAD_TBLNAME, .off = _OUT(overload_tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = nlattr_get_chara },
- { .type = PF_RT_RPOOL, .off = _OUT(rpool), .arg = &pool_parser, .cb = nlattr_get_nested },
+ { .type = PF_RT_RPOOL_RDR, .off = _OUT(rdr), .arg = &pool_parser, .cb = nlattr_get_nested },
{ .type = PF_RT_OS_FINGERPRINT, .off = _OUT(os_fingerprint), .cb = nlattr_get_uint32 },
{ .type = PF_RT_RTABLEID, .off = _OUT(rtableid), .cb = nlattr_get_uint32 },
{ .type = PF_RT_TIMEOUT, .off = _OUT(timeout), .arg = &timeout_parser, .cb = nlattr_get_nested_timeouts },
@@ -732,6 +732,7 @@
{ .type = PF_RT_DIVERT_PORT, .off = _OUT(divert.port), .cb = nlattr_get_uint16 },
{ .type = PF_RT_RCV_IFNAME, .off = _OUT(rcv_ifname), .arg = (void *)IFNAMSIZ, .cb = nlattr_get_chara },
{ .type = PF_RT_MAX_SRC_CONN, .off = _OUT(max_src_conn), .cb = nlattr_get_uint32 },
+ { .type = PF_RT_RPOOL_NAT, .off = _OUT(nat), .arg = &pool_parser, .cb = nlattr_get_nested },
};
NL_DECLARE_ATTR_PARSER(rule_parser, nla_p_rule);
#undef _OUT
@@ -915,7 +916,8 @@
nlattr_add_string(nw, PF_RT_TAGNAME, rule->tagname);
nlattr_add_string(nw, PF_RT_MATCH_TAGNAME, rule->match_tagname);
nlattr_add_string(nw, PF_RT_OVERLOAD_TBLNAME, rule->overload_tblname);
- nlattr_add_pool(nw, PF_RT_RPOOL, &rule->rpool);
+ nlattr_add_pool(nw, PF_RT_RPOOL_RDR, &rule->rdr);
+ nlattr_add_pool(nw, PF_RT_RPOOL_NAT, &rule->nat);
nlattr_add_u32(nw, PF_RT_OS_FINGERPRINT, rule->os_fingerprint);
nlattr_add_u32(nw, PF_RT_RTABLEID, rule->rtableid);
nlattr_add_timeout(nw, PF_RT_TIMEOUT, rule->timeout);
@@ -1528,7 +1530,7 @@
NL_DECLARE_ATTR_PARSER(pool_addr_parser, nla_p_pool_addr);
#undef _OUT
-#define _OUT(_field) offsetof(struct pfioc_pooladdr, _field)
+#define _OUT(_field) offsetof(struct pf_nl_pooladdr, _field)
static const struct nlattr_parser nla_p_add_addr[] = {
{ .type = PF_AA_ACTION, .off = _OUT(action), .cb = nlattr_get_uint32 },
{ .type = PF_AA_TICKET, .off = _OUT(ticket), .cb = nlattr_get_uint32 },
@@ -1539,6 +1541,7 @@
{ .type = PF_AA_AF, .off = _OUT(af), .cb = nlattr_get_uint8 },
{ .type = PF_AA_ANCHOR, .off = _OUT(anchor), .arg = (void *)MAXPATHLEN, .cb = nlattr_get_chara },
{ .type = PF_AA_ADDR, .off = _OUT(addr), .arg = &pool_addr_parser, .cb = nlattr_get_nested },
+ { .type = PF_AA_WHICH, .off = _OUT(which), .cb = nlattr_get_uint32 },
};
static const struct nlfield_parser nlf_p_add_addr[] = {};
#undef _OUT
@@ -1547,13 +1550,16 @@
static int
pf_handle_add_addr(struct nlmsghdr *hdr, struct nl_pstate *npt)
{
- struct pfioc_pooladdr attrs = { 0 };
+ struct pf_nl_pooladdr attrs = { 0 };
int error;
error = nl_parse_nlmsg(hdr, &add_addr_parser, npt, &attrs);
if (error != 0)
return (error);
+ if (attrs.which == 0)
+ attrs.which = PF_RDR;
+
error = pf_ioctl_add_addr(&attrs);
return (error);
@@ -1562,7 +1568,7 @@
static int
pf_handle_get_addrs(struct nlmsghdr *hdr, struct nl_pstate *npt)
{
- struct pfioc_pooladdr attrs = { 0 };
+ struct pf_nl_pooladdr attrs = { 0 };
struct nl_writer *nw = npt->nw;
struct genlmsghdr *ghdr_new;
int error;
@@ -1571,6 +1577,9 @@
if (error != 0)
return (error);
+ if (attrs.which == 0)
+ attrs.which = PF_RDR;
+
error = pf_ioctl_get_addrs(&attrs);
if (error != 0)
return (error);
@@ -1596,7 +1605,7 @@
static int
pf_handle_get_addr(struct nlmsghdr *hdr, struct nl_pstate *npt)
{
- struct pfioc_pooladdr attrs = { 0 };
+ struct pf_nl_pooladdr attrs = { 0 };
struct nl_writer *nw = npt->nw;
struct genlmsghdr *ghdr_new;
int error;
@@ -1605,6 +1614,9 @@
if (error != 0)
return (error);
+ if (attrs.which == 0)
+ attrs.which = PF_RDR;
+
error = pf_ioctl_get_addr(&attrs);
if (error != 0)
return (error);
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
@@ -563,7 +563,7 @@
if (! nvlist_exists_nvlist(nvl, "rpool"))
ERROUT(EINVAL);
PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
- &rule->rpool));
+ &rule->rdr));
PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
@@ -721,7 +721,7 @@
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);
+ tmp = pf_pool_to_nvpool(&rule->rdr);
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "rpool", tmp);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 28, 2:54 AM (10 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17824821
Default Alt Text
D47783.diff (32 KB)
Attached To
Mode
D47783: pf: partially import OpenBSD's NAT rewrite
Attached
Detach File
Event Timeline
Log In to Comment