The branch main has been updated by ks:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d2761422eb0a811976390743921b3f15e9d8331a

commit d2761422eb0a811976390743921b3f15e9d8331a
Author:     Kajetan Staszkiewicz <k...@freebsd.org>
AuthorDate: 2025-07-31 14:28:30 +0000
Commit:     Kajetan Staszkiewicz <k...@freebsd.org>
CommitDate: 2025-08-01 10:11:30 +0000

    pf: Use different address family for source and redirection address
    
    The function pf_map_addr() and source tracking operate on a single
    address family. This made sense before introducing address family
    translation. When combining af-to with route-to or with sticky-address,
    the next-hop or the NAT address are of different address family than
    the source address. For example in NAT64 scenaro an IPv6 source address
    is translated to an IPv4 address and routed over IPv4 gateway.
    
    Make source nodes dual-AF, that is have a separate source AF and
    redirection AF. Store route AF in struct pf_kstate, export it to pfctl.
    When loading rules with redirection pools with pfctl store address
    family of each address. When printing states don't deduce next-hop's
    address family from af-to, use the one stored in state.
    
    Reviewed by:    kp
    Approved by:    kp
    Sponsored by:   InnoGames GmbH
    Differential Revision:  https://reviews.freebsd.org/D51659
---
 lib/libpfctl/libpfctl.c           |   3 +-
 lib/libpfctl/libpfctl.h           |  16 ++++-
 sbin/pfctl/parse.y                |  14 ++--
 sbin/pfctl/pf_print_state.c       |  13 ++--
 sbin/pfctl/pfctl.c                |  25 +++----
 sbin/pfctl/pfctl_parser.c         |  28 +++-----
 sbin/pfctl/pfctl_parser.h         |   4 +-
 sys/net/pfvar.h                   |  15 ++--
 sys/netpfil/pf/if_pfsync.c        |  12 ++++
 sys/netpfil/pf/pf.c               |  21 +++---
 sys/netpfil/pf/pf_ioctl.c         |   2 +
 sys/netpfil/pf/pf_lb.c            | 139 +++++++++++++++++++++++---------------
 sys/netpfil/pf/pf_nl.c            |   5 +-
 sys/netpfil/pf/pf_nl.h            |   3 +-
 tests/sys/netpfil/pf/nat64.sh     |   9 +++
 tests/sys/netpfil/pf/src_track.sh |  61 +++++++++++++++++
 16 files changed, 252 insertions(+), 118 deletions(-)

diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index d8e60075e103..104777352d8b 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -1940,6 +1940,7 @@ static struct snl_attr_parser ap_state[] = {
        { .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 @@ static struct snl_attr_parser ap_srcnode[] = {
        { .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/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index 98a80758ca74..116f9243fda9 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -143,9 +143,18 @@ struct pfctl_eth_anchor {
        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 @@ struct pfctl_state {
        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 @@ struct pfctl_src_node {
        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/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index ddb0f5dc6565..00c36b218055 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -4852,7 +4852,7 @@ binatrule : no BINAT natpasslog interface af proto FROM 
ipspec toipspec tag
                    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 @@ binatrule       : no BINAT natpasslog interface af 
proto FROM ipspec toipspec tag
                                        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 @@ int
 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 @@ apply_redirspec(struct pfctl_pool *rpool, struct 
redirspec *rs)
                    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 @@ int
 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 @@ add_binat_rdr_rule(
 
        /*
         * 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
index 5abdc2de419d..417ff70de975 100644
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -113,10 +113,11 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int 
verbose)
        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 @@ print_state(struct pfctl_state *s, int opts)
        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 @@ print_state(struct pfctl_state *s, int opts)
        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 @@ print_state(struct pfctl_state *s, int opts)
                                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
index 2015e0a09549..9aa50a73ba04 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1038,7 +1038,7 @@ pfctl_get_pool(int dev, struct pfctl_pool *pool, 
u_int32_t nr,
     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 @@ pfctl_get_pool(int dev, struct pfctl_pool *pool, 
u_int32_t nr,
                        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 @@ pfctl_get_pool(int dev, struct pfctl_pool *pool, 
u_int32_t nr,
 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 @@ pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool 
*dst)
 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 @@ pfctl_show_creators(int opts)
 
 /* 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 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct 
pfctl_rule *r, int depth)
                                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.c b/sbin/pfctl/pfctl_parser.c
index f2eb75135609..18b78a150c28 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -429,10 +429,9 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, 
struct pf_rule_addr *dst,
 }
 
 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 @@ print_pool(struct pfctl_pool *pool, u_int16_t p1, 
u_int16_t p2,
                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_src_node(struct pfctl_src_node *sn, int opts)
        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 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, 
int verbose, int numer
                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 @@ print_rule(struct pfctl_rule *r, const char 
*anchor_call, int verbose, int numer
        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 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, 
int verbose, int numer
                                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/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 7a3c0c2a523f..721950967661 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -286,7 +286,7 @@ int pfctl_append_rule(struct pfctl *, struct pfctl_rule *, 
const char *);
 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_config(char *, struct pfctl *);
 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/sys/net/pfvar.h b/sys/net/pfvar.h
index d55afe750869..8dae95c2cc2e 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -629,6 +629,7 @@ struct pf_kpooladdr {
        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 @@ struct pf_rule_actions {
        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 @@ struct pf_ksrc_node {
        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 @@ int                      
pf_step_out_of_keth_anchor(struct pf_keth_anchor_stackframe *,
                            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
index ee10a997c977..e34c08c8c4db 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -529,6 +529,7 @@ pfsync_state_import(union pfsync_state_union *sp, int 
flags, int msg_version)
        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 @@ pfsync_state_import(union pfsync_state_union *sp, int 
flags, int msg_version)
                        }
                        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 @@ pfsync_state_import(union pfsync_state_union *sp, int 
flags, int msg_version)
                                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 @@ pfsync_state_import(union pfsync_state_union *sp, int 
flags, int msg_version)
 
        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
index 79c298c18b46..f6ee02626624 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -401,7 +401,7 @@ static void          pf_overload_task(void *v, int pending);
 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 @@ static u_short
 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 @@ pf_insert_src_node(struct pf_ksrc_node *sns[PF_SN_MAX],
                (*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 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
                 * 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 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx 
*ctx,
        /* 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 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx 
*ctx,
        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 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx 
*ctx,
                    (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
index 9abc07c36788..178ee01649c6 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2661,6 +2661,7 @@ pf_ioctl_add_addr(struct pf_nl_pooladdr *pp)
                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 @@ pf_ioctl_get_addr(struct pf_nl_pooladdr *pp)
                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
index ea0d6facf695..bc9e1dc72902 100644
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -345,8 +345,8 @@ pf_get_sport(struct pf_pdesc *pd, struct pf_krule *r, 
struct pf_addr *naddr,
                }
        }
 
-       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 @@ pf_get_sport(struct pf_pdesc *pd, struct pf_krule *r, 
struct pf_addr *naddr,
                         * 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 @@ pf_islinklocal(const sa_family_t af, const struct pf_addr 
*addr)
 
 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 @@ pf_get_mape_sport(struct pf_pdesc *pd, struct pf_krule *r,
 }
 
 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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                        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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
        } 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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                                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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                                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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                                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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
 
                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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                        }
                } 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 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                } 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 @@ done_pool_mtx:
 }
 
 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 @@ pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
         */
        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 @@ pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
         * 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 @@ pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
        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 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule 
*r,
                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 @@ pf_get_transaddr_af(struct pf_krule *r, struct pf_pdesc 
*pd)
 
        /* 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.c b/sys/netpfil/pf/pf_nl.c
index 73933c022ca2..c5de1e84a287 100644
--- a/sys/netpfil/pf/pf_nl.c
+++ b/sys/netpfil/pf/pf_nl.c
@@ -178,7 +178,7 @@ dump_state(struct nlpcb *nlp, const struct nlmsghdr *hdr, 
struct pf_kstate *s,
 
        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 @@ dump_state(struct nlpcb *nlp, const struct nlmsghdr *hdr, 
struct pf_kstate *s,
        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 @@ pf_handle_get_srcnodes(struct nlmsghdr *hdr, struct 
nl_pstate *npt)
                        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/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h
index 929c20e4c582..d263a0b22deb 100644
--- a/sys/netpfil/pf/pf_nl.h
+++ b/sys/netpfil/pf/pf_nl.h
@@ -135,6 +135,7 @@ enum pfstate_type_t {
        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 @@ enum pf_srcnodes_types_t {
        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 */
*** 99 LINES SKIPPED ***

Reply via email to