summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-08-12 16:41:26 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-08-12 16:41:26 +0000
commita75210033c0bbbcb37c382ddac12cb42b3a7d02f (patch)
tree3390efb6a0fceeb0bc7eddb15e335a1d8bcadf34
parent75c91e344185f9666bcb28aabe07eb95e4ce517c (diff)
Use state tree instead of separate (flat) list to find NAT proxy ports,
allows to use the same proxy port with different external peers. From Ryan McBride
-rw-r--r--sys/net/pf.c142
-rw-r--r--sys/net/pf_ioctl.c7
-rw-r--r--sys/net/pfvar.h12
3 files changed, 42 insertions, 119 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 922fd1f7a0b..4a000063ce6 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.241 2002/08/08 14:31:51 dhartmei Exp $ */
+/* $OpenBSD: pf.c,v 1.242 2002/08/12 16:41:25 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -105,8 +105,6 @@ u_int32_t ticket_binats_active;
u_int32_t ticket_binats_inactive;
u_int32_t ticket_rdrs_active;
u_int32_t ticket_rdrs_inactive;
-struct pf_port_list pf_tcp_ports;
-struct pf_port_list pf_udp_ports;
/* Timeouts */
int pftm_tcp_first_packet = 120; /* First TCP packet */
@@ -214,12 +212,9 @@ int pf_test_state_other(struct pf_state **, int,
void *pf_pull_hdr(struct mbuf *, int, void *, int,
u_short *, u_short *, int);
void pf_calc_skip_steps(struct pf_rulequeue *);
-
-int pf_get_sport(u_int8_t, u_int16_t, u_int16_t,
- u_int16_t *);
-void pf_put_sport(u_int8_t, u_int16_t);
-int pf_add_sport(struct pf_port_list *, u_int16_t);
-int pf_chk_sport(struct pf_port_list *, u_int16_t);
+int pf_get_sport(u_int8_t, u_int8_t,
+ struct pf_addr *, struct pf_addr *,
+ u_int16_t, u_int16_t *, u_int16_t, u_int16_t);
int pf_normalize_tcp(int, struct ifnet *, struct mbuf *,
int, int, void *, struct pf_pdesc *);
void pf_route(struct mbuf **, struct pf_rule *, int);
@@ -650,10 +645,6 @@ pf_purge_expired_states(void)
KASSERT(peer->state == cur->state);
RB_REMOVE(pf_state_tree, &tree_lan_ext, peer);
- /* release NAT resources */
- if (STATE_TRANSLATE(cur->state))
- pf_put_sport(cur->state->proto,
- htons(cur->state->gwy.port));
if (cur->state->rule.ptr != NULL)
cur->state->rule.ptr->states--;
pool_put(&pf_state_pl, cur->state);
@@ -834,6 +825,9 @@ pf_print_state(struct pf_state *s)
case IPPROTO_ICMP:
printf("ICMP ");
break;
+ case IPPROTO_ICMPV6:
+ printf("ICMPV6 ");
+ break;
default:
printf("%u ", s->proto);
break;
@@ -1354,62 +1348,17 @@ pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
}
int
-pf_chk_sport(struct pf_port_list *plist, u_int16_t port)
-{
- struct pf_port_node *pnode;
-
- LIST_FOREACH(pnode, plist, next) {
- if (pnode->port == port)
- return (1);
- }
-
- return (0);
-}
-
-int
-pf_add_sport(struct pf_port_list *plist, u_int16_t port)
+pf_get_sport(u_int8_t af, u_int8_t proto,
+ struct pf_addr *daddr, struct pf_addr *raddr,
+ u_int16_t dport, u_int16_t *port, u_int16_t low, u_int16_t high)
{
- struct pf_port_node *pnode;
-
- pnode = pool_get(&pf_sport_pl, PR_NOWAIT);
- if (pnode == NULL)
- return (ENOMEM);
-
- pnode->port = port;
- LIST_INSERT_HEAD(plist, pnode, next);
-
- return (0);
-}
-
-void
-pf_put_sport(u_int8_t proto, u_int16_t port)
-{
- struct pf_port_list *plist;
- struct pf_port_node *pnode;
-
- if (proto == IPPROTO_TCP)
- plist = &pf_tcp_ports;
- else if (proto == IPPROTO_UDP)
- plist = &pf_udp_ports;
- else
- return;
-
- LIST_FOREACH(pnode, plist, next) {
- if (pnode->port == port) {
- LIST_REMOVE(pnode, next);
- pool_put(&pf_sport_pl, pnode);
- break;
- }
- }
-}
+ struct pf_tree_node key;
-int
-pf_get_sport(u_int8_t proto, u_int16_t low, u_int16_t high, u_int16_t *port)
-{
- struct pf_port_list *plist;
int step;
u_int16_t cut;
+ if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP))
+ return (EINVAL);
if (low == 0 && high == 0) {
NTOHS(*port);
return (0);
@@ -1419,18 +1368,19 @@ pf_get_sport(u_int8_t proto, u_int16_t low, u_int16_t high, u_int16_t *port)
return (0);
}
- if (proto == IPPROTO_TCP)
- plist = &pf_tcp_ports;
- else if (proto == IPPROTO_UDP)
- plist = &pf_udp_ports;
- else
- return (EINVAL);
+ key.af = af;
+ key.proto = proto;
+ PF_ACPY(&key.addr[0], daddr, key.af);
+ PF_ACPY(&key.addr[1], raddr, key.af);
+ key.port[0] = dport;
/* port search; start random, step; similar 2 portloop in in_pcbbind */
if (low == high) {
- *port = low;
- if (!pf_chk_sport(plist, *port))
- goto found;
+ key.port[1] = htons(low);
+ if (pf_find_state(&tree_ext_gwy, &key) == NULL) {
+ *port = low;
+ return (0);
+ }
return (1);
} else if (low < high) {
step = 1;
@@ -1443,22 +1393,21 @@ pf_get_sport(u_int8_t proto, u_int16_t low, u_int16_t high, u_int16_t *port)
*port = cut - step;
do {
*port += step;
- if (!pf_chk_sport(plist, *port))
- goto found;
+ key.port[1] = htons(*port);
+ if (pf_find_state(&tree_ext_gwy, &key) == NULL)
+ return (0);
} while (*port != low && *port != high);
step = -step;
*port = cut;
do {
*port += step;
- if (!pf_chk_sport(plist, *port))
- goto found;
+ key.port[1] = htons(*port);
+ if (pf_find_state(&tree_ext_gwy, &key) == NULL)
+ return (0);
} while (*port != low && *port != high);
return (1); /* none available */
-
-found:
- return (pf_add_sport(plist, *port));
}
struct pf_nat *
@@ -1671,8 +1620,9 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if ((nat = pf_get_nat(ifp, IPPROTO_TCP,
saddr, th->th_sport, daddr, th->th_dport, af)) != NULL) {
bport = nport = th->th_sport;
- error = pf_get_sport(IPPROTO_TCP, nat->proxy_port[0],
- nat->proxy_port[1], &nport);
+ error = pf_get_sport(af, IPPROTO_TCP, daddr,
+ &nat->raddr.addr, th->th_dport, &nport,
+ nat->proxy_port[0], nat->proxy_port[1]);
if (error) {
DPFPRINTF(PF_DEBUG_MISC,
("pf: NAT proxy port allocation "
@@ -1801,11 +1751,8 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
(*rm)->return_icmp & 255, af);
}
- if ((*rm)->action == PF_DROP) {
- if (nport && nat != NULL)
- pf_put_sport(IPPROTO_TCP, nport);
+ if ((*rm)->action == PF_DROP)
return (PF_DROP);
- }
}
if (((*rm != NULL) && (*rm)->keep_state) || nat != NULL ||
@@ -1819,8 +1766,6 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
(*rm)->states < (*rm)->max_states)
s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL) {
- if (nport && nat != NULL)
- pf_put_sport(IPPROTO_TCP, nport);
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -1862,7 +1807,7 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
s->src.seqlo = ntohl(th->th_seq);
s->src.seqhi = s->src.seqlo + len + 1;
- if (th->th_flags & TH_SYN && !(th->th_flags & TH_ACK) &&
+ if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
*rm != NULL && (*rm)->keep_state == PF_STATE_MODULATE) {
/* Generate sequence number modulator */
while ((s->src.seqdiff = arc4random()) == 0)
@@ -1888,8 +1833,6 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
s->packets = 1;
s->bytes = pd->tot_len;
if (pf_insert_state(s)) {
- if (nport && nat != NULL)
- pf_put_sport(IPPROTO_TCP, nport);
REASON_SET(&reason, PFRES_MEMORY);
pool_put(&pf_state_pl, s);
return (PF_DROP);
@@ -1936,8 +1879,9 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if ((nat = pf_get_nat(ifp, IPPROTO_UDP,
saddr, uh->uh_sport, daddr, uh->uh_dport, af)) != NULL) {
bport = nport = uh->uh_sport;
- error = pf_get_sport(IPPROTO_UDP, nat->proxy_port[0],
- nat->proxy_port[1], &nport);
+ error = pf_get_sport(af, IPPROTO_UDP, daddr,
+ &nat->raddr.addr, uh->uh_dport, &nport,
+ nat->proxy_port[0], nat->proxy_port[1]);
if (error) {
DPFPRINTF(PF_DEBUG_MISC,
("pf: NAT proxy port allocation "
@@ -2061,11 +2005,8 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
(*rm)->return_icmp & 255, af);
}
- if ((*rm)->action == PF_DROP) {
- if (nport && nat != NULL)
- pf_put_sport(IPPROTO_UDP, nport);
+ if ((*rm)->action == PF_DROP)
return (PF_DROP);
- }
}
if ((*rm != NULL && (*rm)->keep_state) || nat != NULL ||
@@ -2076,11 +2017,8 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
if (*rm == NULL || !(*rm)->max_states ||
(*rm)->states < (*rm)->max_states)
s = pool_get(&pf_state_pl, PR_NOWAIT);
- if (s == NULL) {
- if (nport && nat != NULL)
- pf_put_sport(IPPROTO_UDP, nport);
+ if (s == NULL)
return (PF_DROP);
- }
if (*rm != NULL)
(*rm)->states++;
@@ -2130,8 +2068,6 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
s->packets = 1;
s->bytes = pd->tot_len;
if (pf_insert_state(s)) {
- if (nport && nat != NULL)
- pf_put_sport(IPPROTO_UDP, nport);
REASON_SET(&reason, PFRES_MEMORY);
pool_put(&pf_state_pl, s);
return (PF_DROP);
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index b1a5ebe08bb..4708ce3dbdb 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.7 2002/07/05 14:05:44 henning Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.8 2002/08/12 16:41:25 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -87,8 +87,6 @@ pfattach(int num)
&pool_allocator_nointr);
pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
NULL);
- pool_init(&pf_sport_pl, sizeof(struct pf_port_node), 0, 0, 0, "pfsport",
- NULL);
pool_init(&pf_addr_pl, sizeof(struct pf_addr_dyn), 0, 0, 0, "pfaddr",
NULL);
@@ -109,9 +107,6 @@ pfattach(int num)
pf_rdrs_active = &pf_rdrs[0];
pf_rdrs_inactive = &pf_rdrs[1];
- LIST_INIT(&pf_tcp_ports);
- LIST_INIT(&pf_udp_ports);
-
timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to);
timeout_add(&pf_expire_to, pftm_interval * hz);
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 821f7607f1f..afbb3f44a0d 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.88 2002/07/15 18:07:17 henning Exp $ */
+/* $OpenBSD: pfvar.h,v 1.89 2002/08/12 16:41:25 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -380,12 +380,6 @@ struct pf_rdr {
u_int8_t no;
};
-struct pf_port_node {
- LIST_ENTRY(pf_port_node) next;
- u_int16_t port;
-};
-LIST_HEAD(pf_port_list, pf_port_node);
-
TAILQ_HEAD(pf_rulequeue, pf_rule);
struct pf_pdesc {
@@ -679,14 +673,12 @@ extern struct pf_binatqueue *pf_binats_active;
extern struct pf_binatqueue *pf_binats_inactive;
extern struct pf_rdrqueue *pf_rdrs_active;
extern struct pf_rdrqueue *pf_rdrs_inactive;
-extern struct pf_port_list pf_tcp_ports;
-extern struct pf_port_list pf_udp_ports;
extern void pf_dynaddr_remove(struct pf_addr_wrap *);
extern int pf_dynaddr_setup(struct pf_addr_wrap *,
u_int8_t);
extern void pf_calc_skip_steps(struct pf_rulequeue *);
extern void pf_dynaddr_copyout(struct pf_addr_wrap *);
-extern struct pool pf_tree_pl, pf_rule_pl, pf_nat_pl, pf_sport_pl;
+extern struct pool pf_tree_pl, pf_rule_pl, pf_nat_pl;
extern struct pool pf_rdr_pl, pf_state_pl, pf_binat_pl,
pf_addr_pl;
extern void pf_purge_timeout(void *);