The branch main has been updated by kp:

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

commit 7d381d0a5b50539638a2460c9ae2213af5c3fad8
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2024-09-05 15:38:20 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2024-09-19 20:20:14 +0000

    pf: exclude link local address from the dynamic interface address pool
    
    so that rules like "pass out on vr1 inet6 nat-to (vr1)" won't map
    to the non routable ipv6 link local address; with suggestions and
    ok claudio, henning
    
    Reviewed by:    zlei
    Obtained from:  OpenBSD, mikeb <mi...@openbsd.org>, e41548933f
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D46594
---
 sys/net/pfvar.h           |  4 +++-
 sys/netpfil/pf/pf_lb.c    | 17 +++++++++++++----
 sys/netpfil/pf/pf_table.c |  9 ++++++++-
 3 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 8335fbfaedb8..a5a0ed257ef3 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1228,6 +1228,7 @@ typedef void              
pfsync_clear_states_t(u_int32_t, const char *);
 typedef int            pfsync_defer_t(struct pf_kstate *, struct mbuf *);
 typedef void           pfsync_detach_ifnet_t(struct ifnet *);
 typedef void           pflow_export_state_t(const struct pf_kstate *);
+typedef bool           pf_addr_filter_func_t(const sa_family_t, const struct 
pf_addr *);
 
 VNET_DECLARE(pfsync_state_import_t *, pfsync_state_import_ptr);
 #define V_pfsync_state_import_ptr      VNET(pfsync_state_import_ptr)
@@ -2429,7 +2430,8 @@ void      pfr_cleanup(void);
 int    pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
 void   pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
            u_int64_t, int, int, int);
-int    pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t);
+int    pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t,
+           pf_addr_filter_func_t);
 void   pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
 struct pfr_ktable *
        pfr_attach_table(struct pf_kruleset *, char *);
diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
index 6541a42aa236..b322bd65cfd3 100644
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -71,6 +71,7 @@ static int pf_get_sport(sa_family_t, uint8_t, struct pf_krule 
*,
     struct pf_addr *, uint16_t, struct pf_addr *, uint16_t, struct pf_addr *,
     uint16_t *, uint16_t, uint16_t, struct pf_ksrc_node **,
     struct pf_udp_mapping **);
+static bool             pf_islinklocal(const sa_family_t, const struct pf_addr 
*);
 
 #define mix(a,b,c) \
        do {                                    \
@@ -401,6 +402,14 @@ failed:
        return (1);                                     /* none available */
 }
 
+static bool
+pf_islinklocal(const sa_family_t af, const struct pf_addr *addr)
+{
+       if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&addr->v6))
+               return (true);
+       return (false);
+}
+
 static int
 pf_get_mape_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
     struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
@@ -585,11 +594,11 @@ 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))
+                           &rpool->tblidx, &rpool->counter, af, NULL))
                                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))
+                           &rpool->tblidx, &rpool->counter, af, 
pf_islinklocal))
                                goto get_addr;
                } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
                        goto get_addr;
@@ -602,7 +611,7 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                if (rpool->cur->addr.type == PF_ADDR_TABLE) {
                        rpool->tblidx = -1;
                        if (pfr_pool_get(rpool->cur->addr.p.tbl,
-                           &rpool->tblidx, &rpool->counter, af)) {
+                           &rpool->tblidx, &rpool->counter, af, NULL)) {
                                /* table contains no address of type 'af' */
                                if (rpool->cur != acur)
                                        goto try_next;
@@ -612,7 +621,7 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
                        rpool->tblidx = -1;
                        if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
-                           &rpool->tblidx, &rpool->counter, af)) {
+                           &rpool->tblidx, &rpool->counter, af, 
pf_islinklocal)) {
                                /* table contains no address of type 'af' */
                                if (rpool->cur != acur)
                                        goto try_next;
diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c
index 4d248e40443d..690cb6d9ab90 100644
--- a/sys/netpfil/pf/pf_table.c
+++ b/sys/netpfil/pf/pf_table.c
@@ -2240,7 +2240,7 @@ pfr_detach_table(struct pfr_ktable *kt)
 
 int
 pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
-    sa_family_t af)
+    sa_family_t af, pf_addr_filter_func_t filter)
 {
        struct pf_addr           addr, cur, mask, umask_addr;
        union sockaddr_union     uaddr, umask;
@@ -2299,6 +2299,10 @@ _next_block:
 
        if (!KENTRY_NETWORK(ke)) {
                /* this is a single IP address - no possible nested block */
+               if (filter && filter(af, &addr)) {
+                       idx++;
+                       goto _next_block;
+               }
                PF_ACPY(counter, &addr, af);
                *pidx = idx;
                pfr_kstate_counter_add(&kt->pfrkt_match, 1);
@@ -2319,12 +2323,15 @@ _next_block:
                /* no need to check KENTRY_RNF_ROOT() here */
                if (ke2 == ke) {
                        /* lookup return the same block - perfect */
+                       if (filter && filter(af, &addr))
+                               goto _next_entry;
                        PF_ACPY(counter, &addr, af);
                        *pidx = idx;
                        pfr_kstate_counter_add(&kt->pfrkt_match, 1);
                        return (0);
                }
 
+_next_entry:
                /* we need to increase the counter past the nested block */
                pfr_prepare_network(&umask, AF_INET, ke2->pfrke_net);
                pfr_sockaddr_to_pf_addr(&umask, &umask_addr);

Reply via email to