On Tue, Jun 21, 2016 at 05:12:39PM +0200, Mike Belopuhov wrote:
> On Tue, Jun 21, 2016 at 16:08 +0200, Alexander Bluhm wrote:
> > On Tue, Jun 21, 2016 at 02:45:42PM +0200, Mike Belopuhov wrote:
> > > Unless I'm wrong, I have to retract my OK and ask you to fix
> > > the sport bit instead.
> >
> > Yes, fixing it in pf_get_sport() is more correct. I will try
> > to make a diff.
> >
>
> Cool.
I have found an issue with pf_get_sport(), it only works for out
rules. In my use case I have an in rule that does nat and diverts
to a socket. Collisions with existing states were not found.
This diff fixes it, now I can trigger such a log message:
Jun 21 11:18:14 q70 /bsd: pf: pf: NAT proxy port allocation (10000-10001) failed
Unfortunately it does not solve my orignal state key reuse problem.
But I suggest fixing things step by step.
ok?
bluhm
Index: net/pf_lb.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_lb.c,v
retrieving revision 1.53
diff -u -p -r1.53 pf_lb.c
--- net/pf_lb.c 15 Jun 2016 11:36:06 -0000 1.53
+++ net/pf_lb.c 22 Jun 2016 17:08:06 -0000
@@ -155,6 +155,7 @@ pf_get_sport(struct pf_pdesc *pd, struct
struct pf_state_key_cmp key;
struct pf_addr init_addr;
u_int16_t cut;
+ int dir = (pd->dir == PF_IN) ? PF_OUT : PF_IN;
bzero(&init_addr, sizeof(init_addr));
if (pf_map_addr(pd->naf, r, &pd->nsaddr, naddr, &init_addr, sn, &r->nat,
@@ -182,9 +183,9 @@ pf_get_sport(struct pf_pdesc *pd, struct
key.af = pd->naf;
key.proto = pd->proto;
key.rdomain = pd->rdomain;
- PF_ACPY(&key.addr[0], &pd->ndaddr, key.af);
- PF_ACPY(&key.addr[1], naddr, key.af);
- key.port[0] = pd->ndport;
+ PF_ACPY(&key.addr[pd->didx], &pd->ndaddr, key.af);
+ PF_ACPY(&key.addr[pd->sidx], naddr, key.af);
+ key.port[pd->didx] = pd->ndport;
/*
* port search; start random, step;
@@ -194,20 +195,20 @@ pf_get_sport(struct pf_pdesc *pd, struct
pd->proto == IPPROTO_ICMP || pd->proto == IPPROTO_ICMPV6)) {
/* XXX bug: icmp states dont use the id on both
* XXX sides (traceroute -I through nat) */
- key.port[1] = pd->nsport;
- if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
+ key.port[pd->sidx] = pd->nsport;
+ if (pf_find_state_all(&key, dir, NULL) == NULL) {
*nport = pd->nsport;
return (0);
}
} else if (low == 0 && high == 0) {
- key.port[1] = pd->nsport;
- if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
+ key.port[pd->sidx] = pd->nsport;
+ if (pf_find_state_all(&key, dir, NULL) == NULL) {
*nport = pd->nsport;
return (0);
}
} else if (low == high) {
- key.port[1] = htons(low);
- if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
+ key.port[pd->sidx] = htons(low);
+ if (pf_find_state_all(&key, dir, NULL) == NULL) {
*nport = htons(low);
return (0);
}
@@ -223,16 +224,16 @@ pf_get_sport(struct pf_pdesc *pd, struct
cut = arc4random_uniform(1 + high - low) + low;
/* low <= cut <= high */
for (tmp = cut; tmp <= high; ++(tmp)) {
- key.port[1] = htons(tmp);
- if (pf_find_state_all(&key, PF_IN, NULL) ==
+ key.port[pd->sidx] = htons(tmp);
+ if (pf_find_state_all(&key, dir, NULL) ==
NULL && !in_baddynamic(tmp, pd->proto)) {
*nport = htons(tmp);
return (0);
}
}
for (tmp = cut - 1; tmp >= low; --(tmp)) {
- key.port[1] = htons(tmp);
- if (pf_find_state_all(&key, PF_IN, NULL) ==
+ key.port[pd->sidx] = htons(tmp);
+ if (pf_find_state_all(&key, dir, NULL) ==
NULL && !in_baddynamic(tmp, pd->proto)) {
*nport = htons(tmp);
return (0);