diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2003-01-02 01:56:57 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2003-01-02 01:56:57 +0000 |
commit | ad022e1cd0b62f8cefdc435e8b0a5244bd80c84e (patch) | |
tree | 5130771c5c839156d2224ceab65806881337716f /sys | |
parent | 0511f69accaf7f834afb09236139c83680f471e3 (diff) |
When route-to/reply-to is used in combination with address translation,
pf_test() may be called twice for the same packet. In this case, make
sure the translation is only applied in the second call. This solves
the problem with state insert failures where the second pf_test() call
tried to insert another state entry after the first call's translation.
ok henning@, mcbride@, thanks to Joe Nall for additional testing.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/pf.c | 76 |
1 files changed, 27 insertions, 49 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index 338cb22f1cc..c1aec3ffd8f 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.293 2003/01/01 16:09:29 henning Exp $ */ +/* $OpenBSD: pf.c,v 1.294 2003/01/02 01:56:56 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -235,6 +235,24 @@ int pf_socket_lookup(uid_t *, gid_t *, int, sa_family_t, struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } }; +#define STATE_LOOKUP() \ + do { \ + if (direction == PF_IN) \ + *state = pf_find_state(&tree_ext_gwy, &key); \ + else \ + *state = pf_find_state(&tree_lan_ext, &key); \ + if (*state == NULL) \ + return (PF_DROP); \ + if ((*state)->rule.ptr != NULL && \ + (((*state)->rule.ptr->rt == PF_ROUTETO && \ + (*state)->rule.ptr->direction == direction) || \ + ((*state)->rule.ptr->rt == PF_REPLYTO && \ + (*state)->rule.ptr->direction != direction)) && \ + (*state)->rt_ifp != NULL && \ + (*state)->rt_ifp != ifp) \ + return (PF_PASS); \ + } while (0) + #define STATE_TRANSLATE(s) \ (s)->lan.addr.addr32[0] != (s)->gwy.addr.addr32[0] || \ ((s)->af == AF_INET6 && \ @@ -2768,12 +2786,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, key.port[0] = th->th_sport; key.port[1] = th->th_dport; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); if (direction == (*state)->direction) { src = &(*state)->src; @@ -3053,12 +3066,7 @@ pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp, key.port[0] = pd->hdr.udp->uh_sport; key.port[1] = pd->hdr.udp->uh_dport; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); if (direction == (*state)->direction) { src = &(*state)->src; @@ -3163,12 +3171,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, key.port[0] = icmpid; key.port[1] = icmpid; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); (*state)->packets++; (*state)->bytes += pd->tot_len; @@ -3347,12 +3350,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, PF_ACPY(&key.addr[1], pd2.src, pd2.af); key.port[1] = th.th_sport; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); if (direction == (*state)->direction) { src = &(*state)->dst; @@ -3437,12 +3435,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, PF_ACPY(&key.addr[1], pd2.src, pd2.af); key.port[1] = uh.uh_sport; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); if (STATE_TRANSLATE(*state)) { if (direction == PF_IN) { @@ -3503,12 +3496,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, PF_ACPY(&key.addr[1], pd2.src, pd2.af); key.port[1] = iih.icmp_id; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); if (STATE_TRANSLATE(*state)) { if (direction == PF_IN) { @@ -3556,12 +3544,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, PF_ACPY(&key.addr[1], pd2.src, pd2.af); key.port[1] = iih.icmp6_id; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); if (STATE_TRANSLATE(*state)) { if (direction == PF_IN) { @@ -3612,12 +3595,7 @@ pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp, key.port[0] = 0; key.port[1] = 0; - if (direction == PF_IN) - *state = pf_find_state(&tree_ext_gwy, &key); - else - *state = pf_find_state(&tree_lan_ext, &key); - if (*state == NULL) - return (PF_DROP); + STATE_LOOKUP(); if (direction == (*state)->direction) { src = &(*state)->src; |