diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2020-06-04 04:27:52 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2020-06-04 04:27:52 +0000 |
commit | b212416942e2f3a1215ec9f47edab7ca780b9e01 (patch) | |
tree | aae9935b22c0615645268bedb5dc8276360d9aaa /sys/net/pf_table.c | |
parent | 74eb90b709658f99ff6d83b8db67ac1634e28ef4 (diff) |
Fix pfr_kentry_byaddr() to be used for a rule in an anchor. It
couldn't find an entry if its table is attached a table on the root.
This fixes the problem "route-to <TABLE> least-states" doesn't work.
The problem is found by IIJ.
OK sashan
Diffstat (limited to 'sys/net/pf_table.c')
-rw-r--r-- | sys/net/pf_table.c | 64 |
1 files changed, 23 insertions, 41 deletions
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c index aa91b250d50..487207dcd0e 100644 --- a/sys/net/pf_table.c +++ b/sys/net/pf_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_table.c,v 1.131 2019/07/08 17:49:57 mpi Exp $ */ +/* $OpenBSD: pf_table.c,v 1.132 2020/06/04 04:27:51 yasuoka Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -2085,11 +2085,28 @@ int pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) { struct pfr_kentry *ke = NULL; + int match; + + ke = pfr_kentry_byaddr(kt, a, af, 0); + + match = (ke && !(ke->pfrke_flags & PFRKE_FLAG_NOT)); + if (match) + kt->pfrkt_match++; + else + kt->pfrkt_nomatch++; + + return (match); +} + +struct pfr_kentry * +pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, + int exact) +{ + struct pfr_kentry *ke = NULL; struct sockaddr_in tmp4; #ifdef INET6 struct sockaddr_in6 tmp6; #endif /* INET6 */ - int match; if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) kt = kt->pfrkt_root; @@ -2116,12 +2133,10 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) default: unhandled_af(af); } - match = (ke && !(ke->pfrke_flags & PFRKE_FLAG_NOT)); - if (match) - kt->pfrkt_match++; - else - kt->pfrkt_nomatch++; - return (match); + if (exact && ke && KENTRY_NETWORK(ke)) + ke = NULL; + + return (ke); } void @@ -2499,39 +2514,6 @@ pfr_states_decrease(struct pfr_ktable *kt, struct pf_addr *addr, int af) return ke->pfrke_counters->states; } -/* - * Added for load balancing to find a kentry outside of the table. - * We need to create a custom pfr_addr struct. - */ -struct pfr_kentry * -pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *addr, sa_family_t af, - int exact) -{ - struct pfr_kentry *ke; - struct pfr_addr p; - - bzero(&p, sizeof(p)); - p.pfra_af = af; - switch (af) { - case AF_INET: - p.pfra_net = 32; - p.pfra_ip4addr = addr->v4; - break; -#ifdef INET6 - case AF_INET6: - p.pfra_net = 128; - p.pfra_ip6addr = addr->v6; - break; -#endif /* INET6 */ - default: - unhandled_af(af); - } - - ke = pfr_lookup_addr(kt, &p, exact); - - return ke; -} - void pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn) { |