From 4af3c109dbc5ac062f35413421ffda1f8c61514e Mon Sep 17 00:00:00 2001 From: bluhm Date: Fri, 24 Jun 2016 13:55:57 +0000 Subject: [PATCH] The function pf_get_sport() did work for out rules only. Make it aware of the direction of the packet. Now nat-to can be used by in rules and together with divert-to. Collisions with existing states are found and produce a "NAT proxy port allocation failed" message. OK henning@ mikeb@ --- sys/net/pf_lb.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/sys/net/pf_lb.c b/sys/net/pf_lb.c index 6ac74760a7c..163977962d1 100644 --- a/sys/net/pf_lb.c +++ b/sys/net/pf_lb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_lb.c,v 1.53 2016/06/15 11:36:06 mikeb Exp $ */ +/* $OpenBSD: pf_lb.c,v 1.54 2016/06/24 13:55:57 bluhm Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -155,6 +155,9 @@ pf_get_sport(struct pf_pdesc *pd, struct pf_rule *r, 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; + int sidx = pd->sidx; + int didx = pd->didx; bzero(&init_addr, sizeof(init_addr)); if (pf_map_addr(pd->naf, r, &pd->nsaddr, naddr, &init_addr, sn, &r->nat, @@ -182,9 +185,9 @@ pf_get_sport(struct pf_pdesc *pd, struct pf_rule *r, 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[didx], &pd->ndaddr, key.af); + PF_ACPY(&key.addr[sidx], naddr, key.af); + key.port[didx] = pd->ndport; /* * port search; start random, step; @@ -194,20 +197,20 @@ pf_get_sport(struct pf_pdesc *pd, struct pf_rule *r, 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[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[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[sidx] = htons(low); + if (pf_find_state_all(&key, dir, NULL) == NULL) { *nport = htons(low); return (0); } @@ -223,16 +226,16 @@ pf_get_sport(struct pf_pdesc *pd, struct pf_rule *r, 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[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[sidx] = htons(tmp); + if (pf_find_state_all(&key, dir, NULL) == NULL && !in_baddynamic(tmp, pd->proto)) { *nport = htons(tmp); return (0); -- 2.20.1