Page MenuHomeFreeBSD

D46864.diff
No OneTemporary

D46864.diff

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1602,7 +1602,6 @@
char any[0];
} hdr;
- struct pf_krule *nat_rule; /* nat/rdr rule applied to packet */
struct pf_addr *src; /* src address */
struct pf_addr *dst; /* dst address */
u_int16_t *sport;
@@ -2632,7 +2631,8 @@
struct pf_addr *, struct pf_addr *,
uint16_t, uint16_t, struct pf_kanchor_stackframe *,
struct pf_krule **,
- struct pf_udp_mapping **udp_mapping);
+ struct pf_udp_mapping **udp_mapping,
+ struct pf_krule_slist *match_rules);
struct pf_state_key *pf_state_key_setup(struct pf_pdesc *, struct mbuf *, int,
struct pf_addr *, struct pf_addr *, u_int16_t, u_int16_t);
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
@@ -322,14 +322,16 @@
static int pf_test_rule(struct pf_krule **, struct pf_kstate **,
struct pfi_kkif *, struct mbuf *, int,
struct pf_pdesc *, struct pf_krule **,
- struct pf_kruleset **, struct inpcb *, int);
+ struct pf_kruleset **, struct inpcb *, int,
+ struct pf_krule_slist *);
static int pf_create_state(struct pf_krule *, struct pf_krule *,
struct pf_krule *, struct pf_pdesc *,
struct pf_ksrc_node *, struct pf_state_key *,
struct pf_state_key *, struct mbuf *, int,
u_int16_t, u_int16_t, int *, struct pfi_kkif *,
struct pf_kstate **, int, u_int16_t, u_int16_t,
- int, struct pf_krule_slist *, struct pf_udp_mapping *);
+ int, struct pf_udp_mapping *,
+ struct pf_krule_slist *);
static int pf_state_key_addr_setup(struct pf_pdesc *, struct mbuf *,
int, struct pf_state_key_cmp *, int, struct pf_addr *,
int, struct pf_addr *, int);
@@ -371,10 +373,9 @@
const struct pf_state_key_cmp *, u_int);
static int pf_src_connlimit(struct pf_kstate **);
static int pf_match_rcvif(struct mbuf *, struct pf_krule *);
-static void pf_counters_inc(int,
- struct pf_pdesc *, struct pfi_kkif *,
- struct pf_kstate *, struct pf_krule *,
- struct pf_krule *);
+static void pf_counters_inc(int, struct pf_pdesc *,
+ struct pfi_kkif *, struct pf_kstate *,
+ struct pf_krule_slist *match_rules);
static void pf_overload_task(void *v, int pending);
static u_short pf_insert_src_node(struct pf_ksrc_node **,
struct pf_krule *, struct pf_addr *, sa_family_t);
@@ -4885,7 +4886,8 @@
static int
pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, struct pfi_kkif *kif,
struct mbuf *m, int off, struct pf_pdesc *pd, struct pf_krule **am,
- struct pf_kruleset **rsm, struct inpcb *inp, int hdrlen)
+ struct pf_kruleset **rsm, struct inpcb *inp, int hdrlen,
+ struct pf_krule_slist *match_rules)
{
struct pf_krule *nr = NULL;
struct pf_addr * const saddr = pd->src;
@@ -4893,7 +4895,6 @@
sa_family_t af = pd->af;
struct pf_krule *r, *a = NULL;
struct pf_kruleset *ruleset = NULL;
- struct pf_krule_slist match_rules;
struct pf_krule_item *ri;
struct pf_ksrc_node *nsn = NULL;
struct tcphdr *th = &pd->hdr.tcp;
@@ -4912,8 +4913,6 @@
PF_RULES_RASSERT();
- SLIST_INIT(&match_rules);
-
if (inp != NULL) {
INP_LOCK_ASSERT(inp);
pd->lookup.uid = inp->inp_cred->cr_uid;
@@ -4976,7 +4975,8 @@
/* check packet for BINAT/NAT/RDR */
transerror = pf_get_translation(pd, m, off, kif, &nsn, &sk,
- &nk, saddr, daddr, sport, dport, anchor_stack, &nr, &udp_mapping);
+ &nk, saddr, daddr, sport, dport, anchor_stack, &nr, &udp_mapping,
+ match_rules);
switch (transerror) {
default:
/* A translation error occurred. */
@@ -5131,7 +5131,6 @@
}
if (nr->natpass)
r = NULL;
- pd->nat_rule = nr;
}
while (r != NULL) {
@@ -5228,21 +5227,20 @@
r->os_fingerprint)),
TAILQ_NEXT(r, entries));
/* FALLTHROUGH */
+
+ ri = malloc(sizeof(struct pf_krule_item), M_PF_RULE_ITEM, M_NOWAIT | M_ZERO);
+ if (ri == NULL) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ goto cleanup;
+ }
+ ri->r = r;
+ SLIST_INSERT_HEAD(match_rules, ri, entry);
+
+
if (r->tag)
tag = r->tag;
if (r->anchor == NULL) {
if (r->action == PF_MATCH) {
- ri = malloc(sizeof(struct pf_krule_item), M_PF_RULE_ITEM, M_NOWAIT | M_ZERO);
- if (ri == NULL) {
- REASON_SET(&reason, PFRES_MEMORY);
- goto cleanup;
- }
- ri->r = r;
- SLIST_INSERT_HEAD(&match_rules, ri, entry);
- pf_counter_u64_critical_enter();
- pf_counter_u64_add_protected(&r->packets[pd->dir == PF_OUT], 1);
- pf_counter_u64_add_protected(&r->bytes[pd->dir == PF_OUT], pd->tot_len);
- pf_counter_u64_critical_exit();
pf_rule_to_actions(r, &pd->act);
if (r->log || pd->act.log & PF_LOG_MATCHES)
PFLOG_PACKET(kif, m,
@@ -5310,7 +5308,7 @@
int action;
action = pf_create_state(r, nr, a, pd, nsn, nk, sk, m, off,
sport, dport, &rewrite, kif, sm, tag, bproto_sum, bip_sum,
- hdrlen, &match_rules, udp_mapping);
+ hdrlen, udp_mapping, match_rules);
if (action != PF_PASS) {
pf_udp_mapping_release(udp_mapping);
if (action == PF_DROP &&
@@ -5321,11 +5319,6 @@
return (action);
}
} else {
- while ((ri = SLIST_FIRST(&match_rules))) {
- SLIST_REMOVE_HEAD(&match_rules, entry);
- free(ri, M_PF_RULE_ITEM);
- }
-
uma_zfree(V_pf_state_key_z, sk);
uma_zfree(V_pf_state_key_z, nk);
pf_udp_mapping_release(udp_mapping);
@@ -5349,11 +5342,6 @@
return (PF_PASS);
cleanup:
- while ((ri = SLIST_FIRST(&match_rules))) {
- SLIST_REMOVE_HEAD(&match_rules, entry);
- free(ri, M_PF_RULE_ITEM);
- }
-
uma_zfree(V_pf_state_key_z, sk);
uma_zfree(V_pf_state_key_z, nk);
pf_udp_mapping_release(udp_mapping);
@@ -5367,14 +5355,13 @@
struct pf_state_key *sk, struct mbuf *m, int off, u_int16_t sport,
u_int16_t dport, int *rewrite, struct pfi_kkif *kif, struct pf_kstate **sm,
int tag, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen,
- struct pf_krule_slist *match_rules, struct pf_udp_mapping *udp_mapping)
+ struct pf_udp_mapping *udp_mapping, struct pf_krule_slist *match_rules)
{
struct pf_kstate *s = NULL;
struct pf_ksrc_node *sn = NULL;
struct tcphdr *th = &pd->hdr.tcp;
u_int16_t mss = V_tcp_mssdflt;
u_short reason, sn_reason;
- struct pf_krule_item *ri;
/* check maximums */
if (r->max_states &&
@@ -5589,11 +5576,6 @@
return (PF_PASS);
csfailed:
- while ((ri = SLIST_FIRST(match_rules))) {
- SLIST_REMOVE_HEAD(match_rules, entry);
- free(ri, M_PF_RULE_ITEM);
- }
-
uma_zfree(V_pf_state_key_z, sk);
uma_zfree(V_pf_state_key_z, nk);
@@ -6583,7 +6565,7 @@
*/
ret = pf_test_rule(&r, &sm, V_pfi_all,
j->m, off, &j->pd, &ra, &rs, NULL,
- sizeof(j->pd.hdr.sctp));
+ sizeof(j->pd.hdr.sctp), NULL);
PF_RULES_RUNLOCK();
SDT_PROBE4(pf, sctp, multihome, test, kif, r, j->m, ret);
if (ret != PF_DROP && sm != NULL) {
@@ -7709,6 +7691,7 @@
struct pfi_kkif *nkif = NULL;
struct ifnet *ifp = NULL;
struct pf_addr naddr;
+ struct pf_krule_item *ri;
int error = 0;
uint16_t ip_len, ip_off;
uint16_t tmp;
@@ -7900,10 +7883,17 @@
error = EMSGSIZE;
KMOD_IPSTAT_INC(ips_cantfrag);
if (r_rt != PF_DUPTO) {
- if (s && pd->nat_rule != NULL)
- PACKET_UNDO_NAT(m0, pd,
- (ip->ip_hl << 2) + (ip_off & IP_OFFMASK),
- s);
+ if (s) {
+ while ((ri = SLIST_FIRST(&(s->match_rules)))) {
+ if (ri->r->action == PF_NAT ||
+ ri->r->action == PF_RDR) {
+ PACKET_UNDO_NAT(m0, pd,
+ (ip->ip_hl << 2) +
+ (ip_off & IP_OFFMASK),
+ s);
+ }
+ }
+ }
icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
ifp->if_mtu);
@@ -7959,6 +7949,7 @@
struct ip6_hdr *ip6;
struct pfi_kkif *nkif = NULL;
struct ifnet *ifp = NULL;
+ struct pf_krule_item *ri;
struct pf_addr naddr;
int r_rt, r_dir;
@@ -8113,10 +8104,18 @@
else {
in6_ifstat_inc(ifp, ifs6_in_toobig);
if (r_rt != PF_DUPTO) {
- if (s && pd->nat_rule != NULL)
- PACKET_UNDO_NAT(m0, pd,
- ((caddr_t)ip6 - m0->m_data) +
- sizeof(struct ip6_hdr), s);
+ if (s) {
+ while ((ri = SLIST_FIRST(&(s->match_rules)))) {
+ if (ri->r->action == PF_NAT ||
+ ri->r->action == PF_RDR) {
+ PACKET_UNDO_NAT(m0, pd,
+ ((caddr_t)ip6 -
+ m0->m_data) +
+ sizeof(struct ip6_hdr),
+ s);
+ }
+ }
+ }
icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
} else
@@ -8466,17 +8465,16 @@
u_short *action, u_short *reason, struct pfi_kkif *kif, struct pf_krule **a,
struct pf_krule **r, struct pf_kstate **s, struct pf_kruleset **ruleset,
int *off, int *hdrlen, struct inpcb *inp,
- struct pf_rule_actions *default_actions)
+ struct pf_rule_actions *default_actions, struct pf_krule_slist *match_rules)
{
struct mbuf *m = *m0;
- memset(pd, 0, sizeof(*pd));
+ SLIST_INIT(match_rules);
pd->dir = dir;
TAILQ_INIT(&pd->sctp_multihome_jobs);
if (default_actions != NULL)
memcpy(&pd->act, default_actions, sizeof(pd->act));
- pd->pf_mtag = pf_find_mtag(m);
if (pd->pf_mtag && pd->pf_mtag->dnpipe) {
pd->act.dnpipe = pd->pf_mtag->dnpipe;
@@ -8539,7 +8537,7 @@
*action = PF_DROP;
else
*action = pf_test_rule(r, s, kif, m, *off,
- pd, a, ruleset, inp, *hdrlen);
+ pd, a, ruleset, inp, *hdrlen, match_rules);
if (*action != PF_PASS)
REASON_SET(reason, PFRES_FRAG);
return (-1);
@@ -8594,7 +8592,7 @@
else
*action = pf_test_rule(r, s, kif, m, *off,
pd, a, ruleset, inp,
- *hdrlen);
+ *hdrlen, match_rules);
if (*action == PF_DROP)
REASON_SET(reason, PFRES_FRAG);
return (-1);
@@ -8767,11 +8765,11 @@
}
static void
-pf_counters_inc(int action, struct pf_pdesc *pd,
- struct pfi_kkif *kif, struct pf_kstate *s,
- struct pf_krule *r, struct pf_krule *a)
+pf_counters_inc(int action, struct pf_pdesc *pd, struct pfi_kkif *kif,
+ struct pf_kstate *s, struct pf_krule_slist *match_rules)
{
- struct pf_krule *tr, *nr;
+ struct pf_krule_item *ri;
+ struct pf_addr *src, *dst;
int dir = pd->dir;
int dirndx;
@@ -8783,65 +8781,58 @@
&kif->pfik_packets[pd->af == AF_INET6][dir == PF_OUT][action != PF_PASS],
1);
- if (action == PF_PASS || r->action == PF_DROP) {
- dirndx = (dir == PF_OUT);
- pf_counter_u64_add_protected(&r->packets[dirndx], 1);
- pf_counter_u64_add_protected(&r->bytes[dirndx], pd->tot_len);
- pf_update_timestamp(r);
-
- if (a != NULL) {
- pf_counter_u64_add_protected(&a->packets[dirndx], 1);
- pf_counter_u64_add_protected(&a->bytes[dirndx], pd->tot_len);
- }
- if (s != NULL) {
- struct pf_krule_item *ri;
-
- if (s->nat_rule.ptr != NULL) {
- pf_counter_u64_add_protected(&s->nat_rule.ptr->packets[dirndx],
- 1);
- pf_counter_u64_add_protected(&s->nat_rule.ptr->bytes[dirndx],
- pd->tot_len);
- }
- if (s->src_node != NULL) {
- counter_u64_add(s->src_node->packets[dirndx],
- 1);
- counter_u64_add(s->src_node->bytes[dirndx],
- pd->tot_len);
- }
- if (s->nat_src_node != NULL) {
- counter_u64_add(s->nat_src_node->packets[dirndx],
- 1);
- counter_u64_add(s->nat_src_node->bytes[dirndx],
- pd->tot_len);
- }
- dirndx = (dir == s->direction) ? 0 : 1;
- s->packets[dirndx]++;
- s->bytes[dirndx] += pd->tot_len;
-
- SLIST_FOREACH(ri, &s->match_rules, entry) {
- pf_counter_u64_add_protected(&ri->r->packets[dirndx], 1);
- pf_counter_u64_add_protected(&ri->r->bytes[dirndx], pd->tot_len);
- }
- }
- tr = r;
- nr = (s != NULL) ? s->nat_rule.ptr : pd->nat_rule;
- if (nr != NULL && r == &V_pf_default_rule)
- tr = nr;
- if (tr->src.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->src.addr.p.tbl,
- (s == NULL) ? pd->src :
- &s->key[(s->direction == PF_IN)]->
- addr[(s->direction == PF_OUT)],
- pd->af, pd->tot_len, dir == PF_OUT,
- r->action == PF_PASS, tr->src.neg);
- if (tr->dst.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->dst.addr.p.tbl,
- (s == NULL) ? pd->dst :
- &s->key[(s->direction == PF_IN)]->
- addr[(s->direction == PF_IN)],
- pd->af, pd->tot_len, dir == PF_OUT,
- r->action == PF_PASS, tr->dst.neg);
+ if (s == NULL) {
+ src = pd->src;
+ dst = pd->dst;
+ } else {
+ src = &s->key[(s->direction == PF_IN)]->addr[(s->direction == PF_OUT)];
+ dst = &s->key[(s->direction == PF_IN)]->addr[(s->direction == PF_IN)];
}
+
+ dirndx = (dir == PF_OUT);
+
+ SLIST_FOREACH(ri, match_rules, entry) {
+ if (action == PF_PASS || ri->r->action == PF_DROP) {
+ pf_counter_u64_add_protected(&ri->r->packets[dirndx], 1);
+ pf_counter_u64_add_protected(&ri->r->bytes[dirndx], pd->tot_len);
+ pf_update_timestamp(ri->r);
+ }
+
+ if (ri->r->src.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(ri->r->src.addr.p.tbl,
+ src, pd->af, pd->tot_len, dirndx,
+ ri->r->action == PF_PASS, ri->r->src.neg);
+ if (ri->r->dst.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(ri->r->dst.addr.p.tbl,
+ dst, pd->af, pd->tot_len, dirndx,
+ ri->r->action == PF_PASS, ri->r->dst.neg);
+ }
+
+ if (s != NULL) {
+ if (s->src_node != NULL) {
+ counter_u64_add(s->src_node->packets[dirndx], 1);
+ counter_u64_add(s->src_node->bytes[dirndx], pd->tot_len);
+ }
+ if (s->nat_src_node != NULL) {
+ counter_u64_add(s->nat_src_node->packets[dirndx], 1);
+ counter_u64_add(s->nat_src_node->bytes[dirndx], pd->tot_len);
+ }
+ dirndx = (dir == s->direction) ? 0 : 1;
+ s->packets[dirndx]++;
+ s->bytes[dirndx] += pd->tot_len;
+
+ printf("Counters:");
+ printf(" 00: ");
+ pf_print_host(&s->key[0]->addr[0], 0, pd->af);
+ printf(" 01: ");
+ pf_print_host(&s->key[0]->addr[1], 0, pd->af);
+ printf(" 10: ");
+ pf_print_host(&s->key[1]->addr[0], 0, pd->af);
+ printf(" 11: ");
+ pf_print_host(&s->key[1]->addr[1], 0, pd->af);
+ printf("\n");
+ }
+
pf_counter_u64_critical_exit();
}
@@ -8850,6 +8841,8 @@
pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0,
struct inpcb *inp, struct pf_rule_actions *default_actions)
{
+ struct pf_krule_slist match_rules;
+ struct pf_krule_item *ri;
struct pfi_kkif *kif;
u_short action, reason = 0;
struct mbuf *m = *m0;
@@ -8913,30 +8906,8 @@
return (PF_DROP);
}
- if (pf_setup_pdesc(af, dir, &pd, m0, &action, &reason, kif, &a, &r,
- &s, &ruleset, &off, &hdrlen, inp, default_actions) == -1) {
- if (action != PF_PASS)
- pd.act.log |= PF_LOG_FORCE;
- goto done;
- }
- m = *m0;
-
- switch (af) {
-#ifdef INET
- case AF_INET:
- h = mtod(m, struct ip *);
- ttl = h->ip_ttl;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- h6 = mtod(m, struct ip6_hdr *);
- ttl = h6->ip6_hlim;
- break;
-#endif
- default:
- panic("Unknown af %d", af);
- }
+ memset(&pd, 0, sizeof(pd));
+ pd.pf_mtag = pf_find_mtag(*m0);
if (pd.pf_mtag != NULL && (pd.pf_mtag->flags & PF_MTAG_FLAG_ROUTE_TO)) {
pd.pf_mtag->flags &= ~PF_MTAG_FLAG_ROUTE_TO;
@@ -8969,6 +8940,15 @@
return (PF_PASS);
}
+ if (pf_setup_pdesc(af, dir, &pd, m0, &action, &reason, kif, &a, &r,
+ &s, &ruleset, &off, &hdrlen, inp, default_actions,
+ &match_rules) == -1) {
+ if (action != PF_PASS)
+ pd.act.log |= PF_LOG_FORCE;
+ goto done;
+ }
+ m = *m0;
+
if (__predict_false(ip_divert_ptr != NULL) &&
((mtag = m_tag_locate(m, MTAG_PF_DIVERT, 0, NULL)) != NULL)) {
struct pf_divert_mtag *dt = (struct pf_divert_mtag *)(mtag+1);
@@ -8992,6 +8972,23 @@
m_tag_delete(m, mtag);
}
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ h = mtod(m, struct ip *);
+ ttl = h->ip_ttl;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ h6 = mtod(m, struct ip6_hdr *);
+ ttl = h6->ip6_hlim;
+ break;
+#endif
+ default:
+ panic("Unknown af %d", af);
+ }
+
#ifdef INET6
/*
* we do not support jumbogram. if we keep going, zero ip6_plen
@@ -9060,7 +9057,7 @@
break;
} else {
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp, hdrlen);
+ &a, &ruleset, inp, hdrlen, &match_rules);
}
}
break;
@@ -9075,7 +9072,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp, hdrlen);
+ &a, &ruleset, inp, hdrlen, &match_rules);
break;
}
@@ -9092,7 +9089,7 @@
a = s->anchor.ptr;
} else if (s == NULL) {
action = pf_test_rule(&r, &s, kif, m, off,
- &pd, &a, &ruleset, inp, hdrlen);
+ &pd, &a, &ruleset, inp, hdrlen, &match_rules);
}
break;
}
@@ -9112,7 +9109,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp, hdrlen);
+ &a, &ruleset, inp, hdrlen, &match_rules);
break;
}
@@ -9131,7 +9128,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp, hdrlen);
+ &a, &ruleset, inp, hdrlen, &match_rules);
break;
}
@@ -9144,7 +9141,7 @@
a = s->anchor.ptr;
} else if (s == NULL)
action = pf_test_rule(&r, &s, kif, m, off, &pd,
- &a, &ruleset, inp, hdrlen);
+ &a, &ruleset, inp, hdrlen, &match_rules);
break;
}
@@ -9261,6 +9258,11 @@
ip_divert_ptr(*m0, dir == PF_IN);
*m0 = NULL;
+ while ((ri = SLIST_FIRST(&match_rules))) {
+ SLIST_REMOVE_HEAD(&match_rules, entry);
+ free(ri, M_PF_RULE_ITEM);
+ }
+
return (action);
} else {
/* XXX: ipfw has the same behaviour! */
@@ -9294,13 +9296,15 @@
ruleset, &pd, (s == NULL));
if (s) {
SLIST_FOREACH(ri, &s->match_rules, entry)
- if (ri->r->log & PF_LOG_ALL)
+ if (ri->r->action == PF_MATCH &&
+ ri->r->log & PF_LOG_ALL)
PFLOG_PACKET(kif, m, action,
reason, ri->r, a, ruleset, &pd, 0);
}
}
- pf_counters_inc(action, &pd, kif, s, r, a);
+ pf_counters_inc(action, &pd, kif, s,
+ (s != NULL) ? &(s->match_rules) : &match_rules);
switch (action) {
case PF_SYNPROXY_DROP:
@@ -9349,8 +9353,14 @@
s->if_index_out = ifp->if_index;
}
- if (s)
+ if (s) {
PF_STATE_UNLOCK(s);
+ } else {
+ while ((ri = SLIST_FIRST(&match_rules))) {
+ SLIST_REMOVE_HEAD(&match_rules, entry);
+ free(ri, M_PF_RULE_ITEM);
+ }
+ }
#ifdef INET6
/* If reassembled packet passed, create new fragments. */
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
@@ -64,9 +64,10 @@
static void pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
static struct pf_krule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
- int, struct pfi_kkif *,
- struct pf_addr *, u_int16_t, struct pf_addr *,
- uint16_t, int, struct pf_kanchor_stackframe *);
+ int, struct pfi_kkif *, struct pf_addr *, u_int16_t,
+ struct pf_addr *, uint16_t, int,
+ struct pf_kanchor_stackframe *,
+ struct pf_krule_slist *);
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 **,
@@ -134,10 +135,12 @@
pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
struct pfi_kkif *kif, struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, uint16_t dport, int rs_num,
- struct pf_kanchor_stackframe *anchor_stack)
+ struct pf_kanchor_stackframe *anchor_stack,
+ struct pf_krule_slist *match_rules)
{
struct pf_krule *r, *rm = NULL;
struct pf_kruleset *ruleset = NULL;
+ struct pf_krule_item *ri;
int tag = -1;
int rtableid = -1;
int asd = 0;
@@ -192,6 +195,15 @@
off, &pd->hdr.tcp), r->os_fingerprint)))
r = TAILQ_NEXT(r, entries);
else {
+ ri = malloc(sizeof(struct pf_krule_item), M_PF_RULE_ITEM, M_NOWAIT | M_ZERO);
+ /*
+ * XXX KS: There's no error handling for the NAT
+ * ruleset. It needs to be added before we can add
+ * malloc failure check.
+ */
+ ri->r = r;
+ SLIST_INSERT_HEAD(match_rules, ri, entry);
+
if (r->tag)
tag = r->tag;
if (r->rtableid >= 0)
@@ -697,12 +709,11 @@
u_short
pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
- struct pfi_kkif *kif, struct pf_ksrc_node **sn,
- struct pf_state_key **skp, struct pf_state_key **nkp,
- struct pf_addr *saddr, struct pf_addr *daddr,
+ struct pfi_kkif *kif, struct pf_ksrc_node **sn, struct pf_state_key **skp,
+ struct pf_state_key **nkp, struct pf_addr *saddr, struct pf_addr *daddr,
uint16_t sport, uint16_t dport, struct pf_kanchor_stackframe *anchor_stack,
- struct pf_krule **rp,
- struct pf_udp_mapping **udp_mapping)
+ struct pf_krule **rp, struct pf_udp_mapping **udp_mapping,
+ struct pf_krule_slist *match_rules)
{
struct pf_krule *r = NULL;
struct pf_addr *naddr;
@@ -717,19 +728,19 @@
*rp = NULL;
if (pd->dir == PF_OUT) {
- r = pf_match_translation(pd, m, off, kif, saddr,
- sport, daddr, dport, PF_RULESET_BINAT, anchor_stack);
+ r = pf_match_translation(pd, m, off, kif, saddr, sport, daddr,
+ dport, PF_RULESET_BINAT, anchor_stack, match_rules);
if (r == NULL)
- r = pf_match_translation(pd, m, off, kif,
- saddr, sport, daddr, dport, PF_RULESET_NAT,
- anchor_stack);
+ r = pf_match_translation(pd, m, off, kif, saddr, sport,
+ daddr, dport, PF_RULESET_NAT, anchor_stack,
+ match_rules);
} else {
- r = pf_match_translation(pd, m, off, kif, saddr,
- sport, daddr, dport, PF_RULESET_RDR, anchor_stack);
+ r = pf_match_translation(pd, m, off, kif, saddr, sport, daddr,
+ dport, PF_RULESET_RDR, anchor_stack, match_rules);
if (r == NULL)
- r = pf_match_translation(pd, m, off, kif,
- saddr, sport, daddr, dport, PF_RULESET_BINAT,
- anchor_stack);
+ r = pf_match_translation(pd, m, off, kif, saddr, sport,
+ daddr, dport, PF_RULESET_BINAT, anchor_stack,
+ match_rules);
}
if (r == NULL)
diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile
--- a/tests/sys/netpfil/pf/Makefile
+++ b/tests/sys/netpfil/pf/Makefile
@@ -6,6 +6,7 @@
ATF_TESTS_SH+= altq \
anchor \
+ counters \
debug \
divert-to \
dup \
diff --git a/tests/sys/netpfil/pf/counters.sh b/tests/sys/netpfil/pf/counters.sh
new file mode 100755
--- /dev/null
+++ b/tests/sys/netpfil/pf/counters.sh
@@ -0,0 +1,99 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 Kajetan Staszkiewicz <vegeta@tuxpowered.net>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+. $(atf_get_srcdir)/utils.subr
+
+atf_test_case "source_track" "cleanup"
+
+counters_head()
+{
+ atf_set descr 'Rule and table counters'
+ atf_set require.user root
+}
+
+counters_body()
+{
+ setup_router_server_ipv6
+
+ # Clients will connect from another network behind the router.
+ # This allows for using multiple source addresses and for tester jail
+ # to not respond with RST packets for SYN+ACKs.
+ jexec router route add -6 2001:db8:44::0/64 2001:db8:42::2
+ jexec server route add -6 2001:db8:44::0/64 2001:db8:43::1
+
+ pft_set_rules router \
+ "table <nat_sources> counters { 2001:db8:44::0/64 }" \
+ "table <anchor_sources> counters { 2001:db8:44::0/64 }" \
+ "table <match_sources> counters { 2001:db8:44::0/64 }" \
+ "table <state_sources> counters { 2001:db8:44::0/64 }" \
+ "nat on ${epair_server}a inet6 from <nat_sources> to any -> ${epair_server}a" \
+ "block" \
+ "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \
+ "anchor anchor1 in on ${epair_tester}b inet6 proto tcp from <anchor_sources> {"\
+ "match from <match_sources>" \
+ "pass from <state_sources> keep state" \
+ "}" \
+ "pass out on ${epair_server}a inet6 proto tcp keep state"
+
+ # Use the 3-way testing so that more than 1 packet is sent.
+ ping_server_check_reply exit:0 --ping-type=tcp3way --send-sport=4201 --fromaddr 2001:db8:44::1
+
+ nat_rules=$(mktemp) || exit 1
+ jexec router pfctl -qvvsn > ${nat_rules}
+ echo === NAT rules ===
+ cat $nat_rules
+
+ pass_rules=$(mktemp) || exit 1
+ jexec router pfctl -qvvsr -a '*' > ${pass_rules}
+ echo === pass_rules ===
+ cat $pass_rules
+
+ states=$(mktemp) || exit 1
+ jexec router pfctl -qvss > ${states}
+ echo === states ===
+ cat $states
+
+ nodes=$(mktemp) || exit 1
+ jexec router pfctl -qvsS > ${nodes}
+ echo === nodes ===
+ cat $nodes
+
+ tables=$(mktemp) || exit 1
+ jexec router pfctl -qvvsT > ${tables}
+ echo === tables ===
+ cat $tables
+}
+
+counters_cleanup()
+{
+ pft_cleanup
+}
+
+
+atf_init_test_cases()
+{
+ atf_add_test_case "counters"
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 3, 1:45 PM (19 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13457156
Default Alt Text
D46864.diff (25 KB)

Event Timeline