Page MenuHomeFreeBSD

D51659.diff
No OneTemporary

D51659.diff

diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -143,9 +143,18 @@
int match; /* XXX: used for pfctl black magic */
};
+struct pfctl_pooladdr {
+ struct pf_addr_wrap addr;
+ TAILQ_ENTRY(pfctl_pooladdr) entries;
+ char ifname[IFNAMSIZ];
+ sa_family_t af;
+};
+
+TAILQ_HEAD(pfctl_palist, pfctl_pooladdr);
+
struct pfctl_pool {
- struct pf_palist list;
- struct pf_pooladdr *cur;
+ struct pfctl_palist list;
+ struct pfctl_pooladdr *cur;
struct pf_poolhashkey key;
struct pf_addr counter;
struct pf_mape_portset mape;
@@ -383,6 +392,7 @@
uint8_t set_prio[2];
uint8_t rt;
char rt_ifname[IFNAMSIZ];
+ sa_family_t rt_af;
uint8_t src_node_flags;
};
@@ -414,7 +424,7 @@
uint32_t states;
uint32_t conn;
sa_family_t af;
- sa_family_t naf;
+ sa_family_t raf;
uint8_t ruletype;
uint64_t creation;
uint64_t expire;
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -1940,6 +1940,7 @@
{ .type = PF_ST_RT, .off = _OUT(rt), .cb = snl_attr_get_uint8 },
{ .type = PF_ST_RT_IFNAME, .off = _OUT(rt_ifname), .cb = snl_attr_store_ifname },
{ .type = PF_ST_SRC_NODE_FLAGS, .off = _OUT(src_node_flags), .cb = snl_attr_get_uint8 },
+ { .type = PF_ST_RT_AF, .off = _OUT(rt_af), .cb = snl_attr_get_uint8 },
};
#undef _IN
#undef _OUT
@@ -3043,7 +3044,7 @@
{ .type = PF_SN_CREATION, .off = _OUT(creation), .cb = snl_attr_get_uint64 },
{ .type = PF_SN_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint64 },
{ .type = PF_SN_CONNECTION_RATE, .off = _OUT(conn_rate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested },
- { .type = PF_SN_NAF, .off = _OUT(naf), .cb = snl_attr_get_uint8 },
+ { .type = PF_SN_RAF, .off = _OUT(raf), .cb = snl_attr_get_uint8 },
{ .type = PF_SN_NODE_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 },
};
#undef _OUT
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -4852,7 +4852,7 @@
tagged rtable binat_redirspec
{
struct pfctl_rule binat;
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
if (check_rulestate(PFCTL_STATE_NAT))
YYERROR;
@@ -5011,11 +5011,12 @@
YYERROR;
}
- pa = calloc(1, sizeof(struct pf_pooladdr));
+ pa = calloc(1, sizeof(struct pfctl_pooladdr));
if (pa == NULL)
err(1, "binat: calloc");
pa->addr = $13->host->addr;
pa->ifname[0] = 0;
+ pa->af = $13->host->af;
TAILQ_INSERT_TAIL(&binat.rdr.list,
pa, entries);
@@ -6115,7 +6116,7 @@
apply_redirspec(struct pfctl_pool *rpool, struct redirspec *rs)
{
struct node_host *h;
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
if (rs == NULL)
return 0;
@@ -6155,10 +6156,11 @@
sizeof(struct pf_poolhashkey));
for (h = rs->host; h != NULL; h = h->next) {
- pa = calloc(1, sizeof(struct pf_pooladdr));
+ pa = calloc(1, sizeof(struct pfctl_pooladdr));
if (pa == NULL)
err(1, "%s: calloc", __func__);
pa->addr = h->addr;
+ pa->af = h->af;
if (h->ifname != NULL) {
if (strlcpy(pa->ifname, h->ifname,
sizeof(pa->ifname)) >= sizeof(pa->ifname))
@@ -6175,7 +6177,7 @@
check_binat_redirspec(struct node_host *src_host, struct pfctl_rule *r,
sa_family_t af)
{
- struct pf_pooladdr *nat_pool = TAILQ_FIRST(&(r->nat.list));
+ struct pfctl_pooladdr *nat_pool = TAILQ_FIRST(&(r->nat.list));
int error = 0;
/* XXX: FreeBSD allows syntax like "{ host1 host2 }" for redirection
@@ -6248,7 +6250,7 @@
/*
* We're copying the whole rule, but we must re-init redir pools.
- * FreeBSD uses lists of pf_pooladdr, we can't just overwrite them.
+ * FreeBSD uses lists of pfctl_pooladdr, we can't just overwrite them.
*/
bcopy(binat_rule, rdr_rule, sizeof(struct pfctl_rule));
TAILQ_INIT(&(rdr_rule->rdr.list));
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -113,10 +113,11 @@
if (addr->type != PF_ADDR_RANGE &&
!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
PF_AZERO(&addr->v.a.mask, AF_INET6))) {
- int bits = unmask(&addr->v.a.mask);
-
- if (bits < (af == AF_INET ? 32 : 128))
- printf("/%d", bits);
+ if (af == AF_INET || af == AF_INET6) {
+ int bits = unmask(&addr->v.a.mask);
+ if (bits < (af == AF_INET ? 32 : 128))
+ printf("/%d", bits);
+ }
}
}
@@ -228,7 +229,6 @@
struct pfctl_state_key *key, *sk, *nk;
const char *protoname;
int min, sec;
- sa_family_t af;
uint8_t proto;
int afto = (s->key[PF_SK_STACK].af != s->key[PF_SK_WIRE].af);
int idx;
@@ -242,7 +242,6 @@
key = s->key;
#endif
- af = s->key[PF_SK_WIRE].af;
proto = s->key[PF_SK_WIRE].proto;
if (s->direction == PF_OUT) {
@@ -430,7 +429,7 @@
default:
printf(" gateway: ");
}
- print_host(&s->rt_addr, 0, af, opts);
+ print_host(&s->rt_addr, 0, s->rt_af, opts);
if (s->rt_ifname[0])
printf("@%s", s->rt_ifname);
}
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1038,7 +1038,7 @@
u_int32_t ticket, int r_action, const char *anchorname, int which)
{
struct pfioc_pooladdr pp;
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
u_int32_t pnr, mpnr;
int ret;
@@ -1054,10 +1054,11 @@
warnc(ret, "DIOCGETADDR");
return (-1);
}
- pa = calloc(1, sizeof(struct pf_pooladdr));
+ pa = calloc(1, sizeof(struct pfctl_pooladdr));
if (pa == NULL)
err(1, "calloc");
- bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr));
+ bcopy(&pp.addr, pa, sizeof(struct pfctl_pooladdr));
+ pa->af = pp.af;
TAILQ_INSERT_TAIL(&pool->list, pa, entries);
}
@@ -1067,7 +1068,7 @@
void
pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst)
{
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
while ((pa = TAILQ_FIRST(&src->list)) != NULL) {
TAILQ_REMOVE(&src->list, pa, entries);
@@ -1078,7 +1079,7 @@
void
pfctl_clear_pool(struct pfctl_pool *pool)
{
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
TAILQ_REMOVE(&pool->list, pa, entries);
@@ -1794,14 +1795,14 @@
/* callbacks for rule/nat/rdr/addr */
int
-pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af, int which)
+pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, int which)
{
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
int ret;
- pf->paddr.af = af;
TAILQ_FOREACH(pa, &p->list, entries) {
- memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
+ memcpy(&pf->paddr.addr, pa, sizeof(struct pfctl_pooladdr));
+ pf->paddr.af = pa->af;
if ((pf->opts & PF_OPT_NOACTION) == 0) {
if ((ret = pfctl_add_addr(pf->h, &pf->paddr, which)) != 0)
errc(1, ret, "DIOCADDADDR");
@@ -2165,11 +2166,11 @@
errc(1, error, "DIOCBEGINADDRS");
}
- if (pfctl_add_pool(pf, &r->rdr, r->af, PF_RDR))
+ if (pfctl_add_pool(pf, &r->rdr, PF_RDR))
return (1);
- if (pfctl_add_pool(pf, &r->nat, r->naf ? r->naf : r->af, PF_NAT))
+ if (pfctl_add_pool(pf, &r->nat, PF_NAT))
return (1);
- if (pfctl_add_pool(pf, &r->route, r->af, PF_RT))
+ if (pfctl_add_pool(pf, &r->route, PF_RT))
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
@@ -286,7 +286,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);
+int pfctl_add_pool(struct pfctl *, struct pfctl_pool *, int);
void pfctl_move_pool(struct pfctl_pool *, struct pfctl_pool *);
void pfctl_clear_pool(struct pfctl_pool *);
@@ -304,7 +304,7 @@
int parse_flags(char *);
int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *);
-void print_pool(struct pfctl_pool *, u_int16_t, u_int16_t, sa_family_t, int);
+void print_pool(struct pfctl_pool *, u_int16_t, u_int16_t, int);
void print_src_node(struct pfctl_src_node *, int);
void print_eth_rule(struct pfctl_eth_rule *, const char *, int);
void print_rule(struct pfctl_rule *, const char *, int, int);
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -429,10 +429,9 @@
}
void
-print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2,
- sa_family_t af, int id)
+print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2, int id)
{
- struct pf_pooladdr *pooladdr;
+ struct pfctl_pooladdr *pooladdr;
if ((TAILQ_FIRST(&pool->list) != NULL) &&
TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
@@ -442,15 +441,15 @@
case PF_NAT:
case PF_RDR:
case PF_BINAT:
- print_addr(&pooladdr->addr, af, 0);
+ print_addr(&pooladdr->addr, pooladdr->af, 0);
break;
case PF_PASS:
case PF_MATCH:
- if (PF_AZERO(&pooladdr->addr.v.a.addr, af))
+ if (PF_AZERO(&pooladdr->addr.v.a.addr, pooladdr->af))
printf("%s", pooladdr->ifname);
else {
printf("(%s ", pooladdr->ifname);
- print_addr(&pooladdr->addr, af, 0);
+ print_addr(&pooladdr->addr, pooladdr->af, 0);
printf(")");
}
break;
@@ -674,7 +673,7 @@
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
printf(" -> ");
aw.v.a.addr = sn->raddr;
- print_addr(&aw, sn->naf ? sn->naf : sn->af, opts & PF_OPT_VERBOSE2);
+ print_addr(&aw, sn->raf, opts & PF_OPT_VERBOSE2);
printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states,
sn->conn, sn->conn_rate.count / 1000,
(sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds);
@@ -952,10 +951,7 @@
else if (r->rt == PF_DUPTO)
printf(" dup-to");
printf(" ");
- print_pool(&r->rdr, 0, 0, r->af, PF_PASS);
- print_pool(&r->route, 0, 0,
- r->rule_flag & PFRULE_AFTO && r->rt != PF_REPLYTO ? r->naf : r->af,
- PF_PASS);
+ print_pool(&r->route, 0, 0, PF_PASS);
}
if (r->af) {
if (r->af == AF_INET)
@@ -1252,17 +1248,16 @@
if (r->action == PF_NAT || r->action == PF_BINAT || r->action == PF_RDR) {
printf(" -> ");
print_pool(&r->rdr, r->rdr.proxy_port[0],
- r->rdr.proxy_port[1], r->af, r->action);
+ r->rdr.proxy_port[1], r->action);
} else {
if (!TAILQ_EMPTY(&r->nat.list)) {
if (r->rule_flag & PFRULE_AFTO) {
- printf(" af-to %s from ", r->naf == AF_INET ? "inet" : "inet6");
+ printf(" af-to %s from ", r->naf == AF_INET ? "inet" : (r->naf == AF_INET6 ? "inet6" : "? "));
} else {
printf(" nat-to ");
}
print_pool(&r->nat, r->nat.proxy_port[0],
- r->nat.proxy_port[1], r->naf ? r->naf : r->af,
- PF_NAT);
+ r->nat.proxy_port[1], PF_NAT);
}
if (!TAILQ_EMPTY(&r->rdr.list)) {
if (r->rule_flag & PFRULE_AFTO) {
@@ -1271,8 +1266,7 @@
printf(" rdr-to ");
}
print_pool(&r->rdr, r->rdr.proxy_port[0],
- r->rdr.proxy_port[1], r->naf ? r->naf : r->af,
- PF_RDR);
+ r->rdr.proxy_port[1], PF_RDR);
}
}
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -629,6 +629,7 @@
struct pf_addr_wrap addr;
TAILQ_ENTRY(pf_kpooladdr) entries;
char ifname[IFNAMSIZ];
+ sa_family_t af;
struct pfi_kkif *kif;
};
@@ -656,6 +657,7 @@
uint16_t max_mss;
uint16_t dnpipe;
uint16_t dnrpipe; /* Reverse direction pipe */
+ sa_family_t rt_af;
uint8_t log;
uint8_t set_tos;
uint8_t min_ttl;
@@ -911,7 +913,7 @@
u_int32_t creation;
u_int32_t expire;
sa_family_t af;
- sa_family_t naf;
+ sa_family_t raf;
u_int8_t ruletype;
pf_sn_types_t type;
struct mtx *lock;
@@ -2717,14 +2719,15 @@
struct pf_keth_rule **, struct pf_keth_rule **,
int *);
-u_short pf_map_addr(u_int8_t, struct pf_krule *,
+u_short pf_map_addr(sa_family_t, struct pf_krule *,
struct pf_addr *, struct pf_addr *,
- struct pfi_kkif **nkif, struct pf_addr *,
- struct pf_kpool *);
+ struct pfi_kkif **nkif, sa_family_t *,
+ struct pf_addr *, struct pf_kpool *);
u_short pf_map_addr_sn(u_int8_t, struct pf_krule *,
struct pf_addr *, struct pf_addr *,
- struct pfi_kkif **nkif, struct pf_addr *,
- struct pf_kpool *, pf_sn_types_t);
+ sa_family_t *, struct pfi_kkif **nkif,
+ struct pf_addr *, struct pf_kpool *,
+ pf_sn_types_t);
int pf_get_transaddr_af(struct pf_krule *,
struct pf_pdesc *);
u_short pf_get_translation(struct pf_test_ctx *);
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
@@ -529,6 +529,7 @@
struct pfi_kkif *rt_kif = NULL;
struct pf_kpooladdr *rpool_first;
int error;
+ sa_family_t rt_af = 0;
uint8_t rt = 0;
int n = 0;
@@ -602,6 +603,11 @@
}
rt = r->rt;
rt_kif = rpool_first->kif;
+ /*
+ * Guess the AF of the route address, FreeBSD 13 does
+ * not support af-to so it should be safe.
+ */
+ rt_af = r->af;
} else if (!PF_AZERO(&sp->pfs_1301.rt_addr, sp->pfs_1301.af)) {
/*
* Ruleset different, routing *supposedly* requested,
@@ -627,6 +633,11 @@
return ((flags & PFSYNC_SI_IOCTL) ? EINVAL : 0);
}
rt = sp->pfs_1400.rt;
+ /*
+ * Guess the AF of the route address, FreeBSD 13 does
+ * not support af-to so it should be safe.
+ */
+ rt_af = sp->pfs_1400.af;
}
break;
}
@@ -706,6 +717,7 @@
st->act.rt = rt;
st->act.rt_kif = rt_kif;
+ st->act.rt_af = rt_af;
switch (msg_version) {
case PFSYNC_MSG_VERSION_1301:
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
@@ -401,7 +401,7 @@
static u_short pf_insert_src_node(struct pf_ksrc_node *[PF_SN_MAX],
struct pf_srchash *[PF_SN_MAX], struct pf_krule *,
struct pf_addr *, sa_family_t, struct pf_addr *,
- struct pfi_kkif *, pf_sn_types_t);
+ struct pfi_kkif *, sa_family_t, pf_sn_types_t);
static u_int pf_purge_expired_states(u_int, int);
static void pf_purge_unlinked_rules(void);
static int pf_mtag_uminit(void *, int, int);
@@ -1017,7 +1017,7 @@
pf_insert_src_node(struct pf_ksrc_node *sns[PF_SN_MAX],
struct pf_srchash *snhs[PF_SN_MAX], struct pf_krule *rule,
struct pf_addr *src, sa_family_t af, struct pf_addr *raddr,
- struct pfi_kkif *rkif, pf_sn_types_t sn_type)
+ struct pfi_kkif *rkif, sa_family_t raf, pf_sn_types_t sn_type)
{
u_short reason = 0;
struct pf_krule *r_track = rule;
@@ -1089,8 +1089,9 @@
(*sn)->rule = r_track;
pf_addrcpy(&(*sn)->addr, src, af);
if (raddr != NULL)
- pf_addrcpy(&(*sn)->raddr, raddr, af);
+ pf_addrcpy(&(*sn)->raddr, raddr, raf);
(*sn)->rkif = rkif;
+ (*sn)->raf = raf;
LIST_INSERT_HEAD(&(*sh)->nodes, *sn, entry);
(*sn)->creation = time_uptime;
(*sn)->ruletype = rule->action;
@@ -5907,9 +5908,13 @@
* it is applied only from the last pass rule.
*/
pd->act.rt = r->rt;
+ if (r->rt == PF_REPLYTO)
+ pd->act.rt_af = pd->af;
+ else
+ pd->act.rt_af = pd->naf;
if ((transerror = pf_map_addr_sn(pd->af, r, pd->src,
- &pd->act.rt_addr, &pd->act.rt_kif, NULL, &(r->route),
- PF_SN_ROUTE)) != PFRES_MATCH) {
+ &pd->act.rt_addr, &pd->act.rt_af, &pd->act.rt_kif, NULL,
+ &(r->route), PF_SN_ROUTE)) != PFRES_MATCH) {
REASON_SET(&ctx.reason, transerror);
goto cleanup;
}
@@ -6039,7 +6044,7 @@
/* src node for limits */
if ((r->rule_flag & PFRULE_SRCTRACK) &&
(sn_reason = pf_insert_src_node(sns, snhs, r, pd->src, pd->af,
- NULL, NULL, PF_SN_LIMIT)) != 0) {
+ NULL, NULL, pd->af, PF_SN_LIMIT)) != 0) {
REASON_SET(&ctx->reason, sn_reason);
goto csfailed;
}
@@ -6047,7 +6052,7 @@
if (r->rt) {
if ((r->route.opts & PF_POOL_STICKYADDR) &&
(sn_reason = pf_insert_src_node(sns, snhs, r, pd->src,
- pd->af, &pd->act.rt_addr, pd->act.rt_kif,
+ pd->af, &pd->act.rt_addr, pd->act.rt_kif, pd->act.rt_af,
PF_SN_ROUTE)) != 0) {
REASON_SET(&ctx->reason, sn_reason);
goto csfailed;
@@ -6066,7 +6071,7 @@
(sn_reason = pf_insert_src_node(sns, snhs, ctx->nr,
ctx->sk ? &(ctx->sk->addr[pd->sidx]) : pd->src, pd->af,
ctx->nk ? &(ctx->nk->addr[1]) : &(pd->nsaddr), NULL,
- PF_SN_NAT)) != 0 ) {
+ pd->naf, PF_SN_NAT)) != 0 ) {
REASON_SET(&ctx->reason, sn_reason);
goto csfailed;
}
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
@@ -2661,6 +2661,7 @@
PF_RULES_WUNLOCK();
goto out;
}
+ pa->af = pp->af;
switch (pp->which) {
case PF_NAT:
TAILQ_INSERT_TAIL(&V_pf_pabuf[0], pa, entries);
@@ -2742,6 +2743,7 @@
return (EBUSY);
}
pf_kpooladdr_to_pooladdr(pa, &pp->addr);
+ pp->af = pa->af;
pf_addr_copyout(&pp->addr.addr);
PF_RULES_RUNLOCK();
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
@@ -345,8 +345,8 @@
}
}
- if (pf_map_addr_sn(pd->naf, r, &pd->nsaddr, naddr, NULL, &init_addr,
- rpool, sn_type))
+ if (pf_map_addr_sn(pd->naf, r, &pd->nsaddr, naddr, &(pd->naf), NULL,
+ &init_addr, rpool, sn_type))
goto failed;
if (pd->proto == IPPROTO_ICMP) {
@@ -470,8 +470,8 @@
* pick a different source address since we're out
* of free port choices for the current one.
*/
- if (pf_map_addr_sn(pd->naf, r, &pd->nsaddr, naddr, NULL,
- &init_addr, rpool, sn_type))
+ if (pf_map_addr_sn(pd->naf, r, &pd->nsaddr, naddr,
+ &(pd->naf), NULL, &init_addr, rpool, sn_type))
return (1);
break;
case PF_POOL_NONE:
@@ -501,8 +501,8 @@
static int
pf_get_mape_sport(struct pf_pdesc *pd, struct pf_krule *r,
- struct pf_addr *naddr, uint16_t *nport,
- struct pf_udp_mapping **udp_mapping, struct pf_kpool *rpool)
+ struct pf_addr *naddr, uint16_t *nport, struct pf_udp_mapping **udp_mapping,
+ struct pf_kpool *rpool)
{
uint16_t psmask, low, highmask;
uint16_t i, ahigh, cut;
@@ -535,15 +535,22 @@
}
u_short
-pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
- struct pf_addr *naddr, struct pfi_kkif **nkif, struct pf_addr *init_addr,
- struct pf_kpool *rpool)
+pf_map_addr(sa_family_t saf, struct pf_krule *r, struct pf_addr *saddr,
+ struct pf_addr *naddr, struct pfi_kkif **nkif, sa_family_t *naf,
+ struct pf_addr *init_addr, struct pf_kpool *rpool)
{
u_short reason = PFRES_MATCH;
struct pf_addr *raddr = NULL, *rmask = NULL;
struct pfr_ktable *kt;
uint64_t hashidx;
int cnt;
+ sa_family_t wanted_af;
+
+ KASSERT(saf != 0, ("%s: saf == 0", __func__));
+ KASSERT(naf != NULL, ("%s: naf = NULL", __func__));
+ KASSERT((*naf) != 0, ("%s: *naf = 0", __func__));
+
+ wanted_af = (*naf);
mtx_lock(&rpool->mtx);
/* Find the route using chosen algorithm. Store the found route
@@ -553,7 +560,7 @@
goto done_pool_mtx;
}
if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
- switch (af) {
+ switch (wanted_af) {
#ifdef INET
case AF_INET:
if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
@@ -577,7 +584,7 @@
break;
#endif /* INET6 */
default:
- unhandled_af(af);
+ unhandled_af(wanted_af);
}
} else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
if (!PF_POOL_DYNTYPE(rpool->opts)) {
@@ -587,14 +594,24 @@
} else {
raddr = &rpool->cur->addr.v.a.addr;
rmask = &rpool->cur->addr.v.a.mask;
+ /*
+ * For single addresses check their address family. Unless they
+ * have none, which happens when addresses are added with
+ * the old ioctl mechanism. In such case trust that the address
+ * has the proper AF.
+ */
+ if (rpool->cur->af && rpool->cur->af != wanted_af) {
+ reason = PFRES_MAPFAILED;
+ goto done_pool_mtx;
+ }
}
switch (rpool->opts & PF_POOL_TYPEMASK) {
case PF_POOL_NONE:
- pf_addrcpy(naddr, raddr, af);
+ pf_addrcpy(naddr, raddr, wanted_af);
break;
case PF_POOL_BITMASK:
- pf_poolmask(naddr, raddr, rmask, saddr, af);
+ pf_poolmask(naddr, raddr, rmask, saddr, wanted_af);
break;
case PF_POOL_RANDOM:
if (rpool->cur->addr.type == PF_ADDR_TABLE ||
@@ -615,13 +632,14 @@
rpool->tblidx = (int)arc4random_uniform(cnt);
memset(&rpool->counter, 0, sizeof(rpool->counter));
if (pfr_pool_get(kt, &rpool->tblidx, &rpool->counter,
- af, pf_islinklocal, false)) {
+ wanted_af, pf_islinklocal, false)) {
reason = PFRES_MAPFAILED;
goto done_pool_mtx; /* unsupported */
}
- pf_addrcpy(naddr, &rpool->counter, af);
- } else if (init_addr != NULL && PF_AZERO(init_addr, af)) {
- switch (af) {
+ pf_addrcpy(naddr, &rpool->counter, wanted_af);
+ } else if (init_addr != NULL && PF_AZERO(init_addr,
+ wanted_af)) {
+ switch (wanted_af) {
#ifdef INET
case AF_INET:
rpool->counter.addr32[0] = arc4random();
@@ -650,12 +668,14 @@
break;
#endif /* INET6 */
}
- pf_poolmask(naddr, raddr, rmask, &rpool->counter, af);
- pf_addrcpy(init_addr, naddr, af);
+ pf_poolmask(naddr, raddr, rmask, &rpool->counter,
+ wanted_af);
+ pf_addrcpy(init_addr, naddr, wanted_af);
} else {
- pf_addr_inc(&rpool->counter, af);
- pf_poolmask(naddr, raddr, rmask, &rpool->counter, af);
+ pf_addr_inc(&rpool->counter, wanted_af);
+ pf_poolmask(naddr, raddr, rmask, &rpool->counter,
+ wanted_af);
}
break;
case PF_POOL_SRCHASH:
@@ -663,7 +683,8 @@
unsigned char hash[16];
hashidx =
- pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
+ pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key,
+ wanted_af);
if (rpool->cur->addr.type == PF_ADDR_TABLE ||
rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
if (rpool->cur->addr.type == PF_ADDR_TABLE)
@@ -682,14 +703,14 @@
rpool->tblidx = (int)(hashidx % cnt);
memset(&rpool->counter, 0, sizeof(rpool->counter));
if (pfr_pool_get(kt, &rpool->tblidx, &rpool->counter,
- af, pf_islinklocal, false)) {
+ wanted_af, pf_islinklocal, false)) {
reason = PFRES_MAPFAILED;
goto done_pool_mtx; /* unsupported */
}
- pf_addrcpy(naddr, &rpool->counter, af);
+ pf_addrcpy(naddr, &rpool->counter, wanted_af);
} else {
pf_poolmask(naddr, raddr, rmask,
- (struct pf_addr *)&hash, af);
+ (struct pf_addr *)&hash, wanted_af);
}
break;
}
@@ -699,14 +720,16 @@
if (rpool->cur->addr.type == PF_ADDR_TABLE) {
if (!pfr_pool_get(rpool->cur->addr.p.tbl,
- &rpool->tblidx, &rpool->counter, af, NULL, true))
+ &rpool->tblidx, &rpool->counter, wanted_af,
+ NULL, true))
goto get_addr;
} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
- &rpool->tblidx, &rpool->counter, af, pf_islinklocal,
- true))
+ &rpool->tblidx, &rpool->counter, wanted_af,
+ pf_islinklocal, true))
goto get_addr;
- } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
+ } else if (pf_match_addr(0, raddr, rmask, &rpool->counter,
+ wanted_af))
goto get_addr;
try_next:
@@ -717,8 +740,9 @@
rpool->tblidx = -1;
if (rpool->cur->addr.type == PF_ADDR_TABLE) {
if (pfr_pool_get(rpool->cur->addr.p.tbl,
- &rpool->tblidx, &rpool->counter, af, NULL, true)) {
- /* table contains no address of type 'af' */
+ &rpool->tblidx, &rpool->counter, wanted_af, NULL,
+ true)) {
+ /* table contains no address of type 'wanted_af' */
if (rpool->cur != acur)
goto try_next;
reason = PFRES_MAPFAILED;
@@ -726,9 +750,9 @@
}
} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
- &rpool->tblidx, &rpool->counter, af, pf_islinklocal,
- true)) {
- /* table contains no address of type 'af' */
+ &rpool->tblidx, &rpool->counter, wanted_af,
+ pf_islinklocal, true)) {
+ /* interface has no address of type 'wanted_af' */
if (rpool->cur != acur)
goto try_next;
reason = PFRES_MAPFAILED;
@@ -737,14 +761,18 @@
} else {
raddr = &rpool->cur->addr.v.a.addr;
rmask = &rpool->cur->addr.v.a.mask;
- pf_addrcpy(&rpool->counter, raddr, af);
+ if (rpool->cur->af && rpool->cur->af != wanted_af) {
+ reason = PFRES_MAPFAILED;
+ goto done_pool_mtx;
+ }
+ pf_addrcpy(&rpool->counter, raddr, wanted_af);
}
get_addr:
- pf_addrcpy(naddr, &rpool->counter, af);
- if (init_addr != NULL && PF_AZERO(init_addr, af))
- pf_addrcpy(init_addr, naddr, af);
- pf_addr_inc(&rpool->counter, af);
+ pf_addrcpy(naddr, &rpool->counter, wanted_af);
+ if (init_addr != NULL && PF_AZERO(init_addr, wanted_af))
+ pf_addrcpy(init_addr, naddr, wanted_af);
+ pf_addr_inc(&rpool->counter, wanted_af);
break;
}
}
@@ -759,9 +787,9 @@
}
u_short
-pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
- struct pf_addr *naddr, struct pfi_kkif **nkif, struct pf_addr *init_addr,
- struct pf_kpool *rpool, pf_sn_types_t sn_type)
+pf_map_addr_sn(sa_family_t saf, struct pf_krule *r, struct pf_addr *saddr,
+ struct pf_addr *naddr, sa_family_t *naf, struct pfi_kkif **nkif,
+ struct pf_addr *init_addr, struct pf_kpool *rpool, pf_sn_types_t sn_type)
{
struct pf_ksrc_node *sn = NULL;
struct pf_srchash *sh = NULL;
@@ -772,27 +800,31 @@
*/
if (rpool->opts & PF_POOL_STICKYADDR &&
(rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE)
- sn = pf_find_src_node(saddr, r, af, &sh, sn_type, false);
+ sn = pf_find_src_node(saddr, r, saf, &sh, sn_type, false);
if (sn != NULL) {
PF_SRC_NODE_LOCK_ASSERT(sn);
+ (*naf) = sn->raf;
/* If the supplied address is the same as the current one we've
* been asked before, so tell the caller that there's no other
* address to be had. */
- if (PF_AEQ(naddr, &(sn->raddr), af)) {
+
+ if (PF_AEQ(naddr, &(sn->raddr), *naf)) {
+ printf("%s: no more addresses\n", __func__);
reason = PFRES_MAPFAILED;
goto done;
}
- pf_addrcpy(naddr, &(sn->raddr), af);
+ pf_addrcpy(naddr, &(sn->raddr), *naf);
+
if (nkif)
*nkif = sn->rkif;
if (V_pf_status.debug >= PF_DEBUG_NOISY) {
printf("%s: src tracking maps ", __func__);
- pf_print_host(saddr, 0, af);
+ pf_print_host(saddr, 0, saf);
printf(" to ");
- pf_print_host(naddr, 0, af);
+ pf_print_host(naddr, 0, *naf);
if (nkif)
printf("@%s", (*nkif)->pfik_name);
printf("\n");
@@ -804,7 +836,7 @@
* Source node has not been found. Find a new address and store it
* in variables given by the caller.
*/
- if ((reason = pf_map_addr(af, r, saddr, naddr, nkif, init_addr,
+ if ((reason = pf_map_addr(saf, r, saddr, naddr, nkif, naf, init_addr,
rpool)) != 0) {
if (V_pf_status.debug >= PF_DEBUG_MISC)
printf("%s: pf_map_addr has failed\n", __func__);
@@ -814,7 +846,7 @@
if (V_pf_status.debug >= PF_DEBUG_NOISY &&
(rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
printf("%s: selected address ", __func__);
- pf_print_host(naddr, 0, af);
+ pf_print_host(naddr, 0, *naf);
if (nkif)
printf("@%s", (*nkif)->pfik_name);
printf("\n");
@@ -996,8 +1028,9 @@
int tries;
uint16_t cut, low, high, nport;
- reason = pf_map_addr_sn(pd->af, r, &pd->nsaddr, naddr, NULL,
- NULL, rpool, PF_SN_NAT);
+ reason = pf_map_addr_sn(pd->af, r, &pd->nsaddr, naddr,
+ &(pd->naf), NULL, NULL, rpool, PF_SN_NAT);
+
if (reason != 0)
goto notrans;
if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
@@ -1161,8 +1194,8 @@
/* get the destination address and port */
if (! TAILQ_EMPTY(&r->rdr.list)) {
- if (pf_map_addr_sn(pd->naf, r, &nsaddr, &naddr, NULL, NULL,
- &r->rdr, PF_SN_NAT))
+ if (pf_map_addr_sn(pd->naf, r, &nsaddr, &naddr, &(pd->naf),
+ NULL, NULL, &r->rdr, PF_SN_NAT))
return (-1);
if (r->rdr.proxy_port[0])
pd->ndport = htons(r->rdr.proxy_port[0]);
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
@@ -135,6 +135,7 @@
PF_ST_RT = 36, /* u8 */
PF_ST_RT_IFNAME = 37, /* string */
PF_ST_SRC_NODE_FLAGS = 38, /* u8 */
+ PF_ST_RT_AF = 39, /* u8 */
};
enum pf_addr_type_t {
@@ -433,7 +434,7 @@
PF_SN_CREATION = 12, /* u64 */
PF_SN_EXPIRE = 13, /* u64 */
PF_SN_CONNECTION_RATE = 14, /* nested, pf_threshold */
- PF_SN_NAF = 15, /* u8 */
+ PF_SN_RAF = 15, /* u8 */
PF_SN_NODE_TYPE = 16, /* u8 */
};
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
@@ -178,7 +178,7 @@
nlattr_add_string(nw, PF_ST_IFNAME, s->kif->pfik_name);
nlattr_add_string(nw, PF_ST_ORIG_IFNAME, s->orig_kif->pfik_name);
- dump_addr(nw, PF_ST_RT_ADDR, &s->act.rt_addr, af);
+ dump_addr(nw, PF_ST_RT_ADDR, &s->act.rt_addr, s->act.rt_af);
nlattr_add_u32(nw, PF_ST_CREATION, time_uptime - (s->creation / 1000));
uint32_t expire = pf_state_expires(s);
if (expire > time_uptime)
@@ -224,6 +224,7 @@
if (s->sns[PF_SN_ROUTE] != NULL)
src_node_flags |= PFSTATE_SRC_NODE_ROUTE;
nlattr_add_u8(nw, PF_ST_SRC_NODE_FLAGS, src_node_flags);
+ nlattr_add_u8(nw, PF_ST_RT_AF, s->act.rt_af);
if (!dump_state_peer(nw, PF_ST_PEER_SRC, &s->src))
goto enomem;
@@ -1761,7 +1762,7 @@
nlattr_add_u32(nw, PF_SN_STATES, n->states);
nlattr_add_u32(nw, PF_SN_CONNECTIONS, n->conn);
nlattr_add_u8(nw, PF_SN_AF, n->af);
- nlattr_add_u8(nw, PF_SN_NAF, n->naf);
+ nlattr_add_u8(nw, PF_SN_RAF, n->raf);
nlattr_add_u8(nw, PF_SN_RULE_TYPE, n->ruletype);
nlattr_add_u64(nw, PF_SN_CREATION, secs - n->creation);
diff --git a/tests/sys/netpfil/pf/nat64.sh b/tests/sys/netpfil/pf/nat64.sh
--- a/tests/sys/netpfil/pf/nat64.sh
+++ b/tests/sys/netpfil/pf/nat64.sh
@@ -916,6 +916,15 @@
atf_check -s exit:0 -o ignore \
ping6 -c 3 64:ff9b::192.0.2.2
+
+ states=$(mktemp) || exit 1
+ jexec rtr pfctl -qvvss | normalize_pfctl_s > $states
+
+ for state_regexp in \
+ "${epair}b ipv6-icmp 192.0.2.1:.* \(2001:db8::2\[[0-9]+\]\) -> 192.0.2.2:8 \(64:ff9b::c000:202\[[0-9]+\]\).*4:2 pkts.*route-to: 192.0.2.2@${epair_link}a" \
+ ; do
+ grep -qE "${state_regexp}" $states || atf_fail "State not found for '${state_regexp}'"
+ done
}
route_to_cleanup()
diff --git a/tests/sys/netpfil/pf/src_track.sh b/tests/sys/netpfil/pf/src_track.sh
--- a/tests/sys/netpfil/pf/src_track.sh
+++ b/tests/sys/netpfil/pf/src_track.sh
@@ -503,6 +503,66 @@
pft_cleanup
}
+atf_test_case "mixed_af" "cleanup"
+mixed_af_head()
+{
+ atf_set descr 'Test mixed address family source tracking'
+ atf_set require.user root
+}
+
+mixed_af_body()
+{
+ setup_router_server_nat64
+
+ # Clients will connect from another network behind the router.
+ # This allows for using multiple source addresses.
+ jexec router route add -6 ${net_clients_6}::/${net_clients_6_mask} ${net_tester_6_host_tester}
+
+ jexec router pfctl -e
+ pft_set_rules router \
+ "set reassemble yes" \
+ "set state-policy if-bound" \
+ "pass in on ${epair_tester}b \
+ route-to { (${epair_server1}a ${net_server1_4_host_server}) \
+ } sticky-address \
+ inet6 proto tcp from any to 64:ff9b::/96 \
+ af-to inet from ${net_clients_4}.0/${net_clients_4_mask} round-robin sticky-address"
+
+ atf_check -s exit:0 ${common_dir}/pft_ping.py \
+ --sendif ${epair_tester}a \
+ --replyif ${epair_tester}a \
+ --fromaddr 2001:db8:44::1 \
+ --to 64:ff9b::192.0.2.100 \
+ --ping-type=tcp3way \
+ --send-sport=4201
+
+ states=$(mktemp) || exit 1
+ jexec router pfctl -qvvss | normalize_pfctl_s > $states
+ nodes=$(mktemp) || exit 1
+ jexec router pfctl -qvvsS | normalize_pfctl_s > $nodes
+
+ # States are checked for proper route-to information.
+ # The route-to gateway is IPv4.
+ for state_regexp in \
+ "${epair_tester}b tcp 203.0.113.0:4201 \(2001:db8:44::1\[4201\]\) -> 192.0.2.100:9 \(64:ff9b::c000:264\[9\]\) .* route-to: 198.51.100.18@${epair_server1}a" \
+ ; do
+ grep -qE "${state_regexp}" $states || atf_fail "State not found for '${state_regexp}'"
+ done
+
+ # Source nodes map IPv6 source address onto IPv4 gateway and IPv4 SNAT address.
+ for node_regexp in \
+ '2001:db8:44::1 -> 203.0.113.0 .* states 1, .* NAT/RDR sticky-address' \
+ '2001:db8:44::1 -> 198.51.100.18 .* states 1, .* route sticky-address' \
+ ; do
+ grep -qE "${node_regexp}" $nodes || atf_fail "Source node not found for '${node_regexp}'"
+ done
+}
+
+mixed_af_cleanup()
+{
+ pft_cleanup
+}
+
atf_init_test_cases()
{
atf_add_test_case "source_track"
@@ -512,4 +572,5 @@
atf_add_test_case "max_src_states_global"
atf_add_test_case "sn_types_compat"
atf_add_test_case "sn_types_pass"
+ atf_add_test_case "mixed_af"
}

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 12, 4:00 PM (8 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26901687
Default Alt Text
D51659.diff (32 KB)

Event Timeline