Skip to content

Commit

Permalink
MFC r341998:
Browse files Browse the repository at this point in the history
pf: Fix endless loop on NAT exhaustion with sticky-address

When we try to find a source port in pf_get_sport() it's possible that
all available source ports will be in use. In that case we call
pf_map_addr() to try to find a new source IP to try from. If there are
no more available source IPs pf_map_addr() will return 1 and we stop
trying.

However, if sticky-address is set we'll always return the same IP
address, even if we've already tried that one.
We need to check the supplied address, because if that's the one we'd
set it means pf_get_sport() has already tried it, and we should error
out rather than keep trying.

PR:		233867
  • Loading branch information
kprovost committed Dec 26, 2018
1 parent 21de50b commit 8df6e4a
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 0 deletions.
4 changes: 4 additions & 0 deletions sys/netpfil/pf/pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5513,6 +5513,8 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
dst.sin_len = sizeof(dst);
dst.sin_addr = ip->ip_dst;

bzero(&naddr, sizeof(naddr));

if (TAILQ_EMPTY(&r->rpool.list)) {
DPFPRINTF(PF_DEBUG_URGENT,
("%s: TAILQ_EMPTY(&r->rpool.list)\n", __func__));
Expand Down Expand Up @@ -5672,6 +5674,8 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
dst.sin6_len = sizeof(dst);
dst.sin6_addr = ip6->ip6_dst;

bzero(&naddr, sizeof(naddr));

if (TAILQ_EMPTY(&r->rpool.list)) {
DPFPRINTF(PF_DEBUG_URGENT,
("%s: TAILQ_EMPTY(&r->rpool.list)\n", __func__));
Expand Down
6 changes: 6 additions & 0 deletions sys/netpfil/pf/pf_lb.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,12 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
src node was created just a moment ago in pf_create_state and it
needs to be filled in with routing decision calculated here. */
if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
/* 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))
return (1);

PF_ACPY(naddr, &(*sn)->raddr, af);
if (V_pf_status.debug >= PF_DEBUG_MISC) {
printf("pf_map_addr: src tracking maps ");
Expand Down

0 comments on commit 8df6e4a

Please sign in to comment.