summaryrefslogtreecommitdiffstats
path: root/sys/net/pf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c1442
1 files changed, 733 insertions, 709 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index a332e304845..2e6176a8447 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.576 2008/05/29 00:28:07 henning Exp $ */
+/* $OpenBSD: pf.c,v 1.577 2008/05/29 01:00:53 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -160,10 +160,18 @@ struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
u_int16_t, int);
struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
int, int, struct pfi_kif *, struct pf_src_node **,
- struct pf_addr *, u_int16_t,
- struct pf_addr *, u_int16_t,
- struct pf_addr *, u_int16_t *);
+ struct pf_state_key **, struct pf_state_key **,
+ struct pf_state_key **, struct pf_state_key **,
+ struct pf_addr *, struct pf_addr *,
+ u_int16_t, u_int16_t);
void pf_detach_state(struct pf_state *, int);
+struct pf_state_key *pf_state_key_insert(struct pf_state_key *,
+ struct pf_state *);
+int pf_state_key_setup(struct pf_pdesc *, struct pf_rule *,
+ struct pf_state_key **, struct pf_state_key **,
+ struct pf_state_key **, struct pf_state_key **,
+ struct pf_addr *, struct pf_addr *,
+ u_int16_t, u_int16_t);
void pf_state_key_detach(struct pf_state_key *,
struct pf_state *, int);
u_int32_t pf_tcp_iss(struct pf_pdesc *);
@@ -218,13 +226,15 @@ void pf_set_rt_ifp(struct pf_state *,
int pf_check_proto_cksum(struct mbuf *, int, int,
u_int8_t, sa_family_t);
struct pf_divert *pf_get_divert(struct mbuf *);
+void pf_print_state_parts(struct pf_state *,
+ struct pf_state_key *, struct pf_state_key *);
int pf_addr_wrap_neq(struct pf_addr_wrap *,
struct pf_addr_wrap *);
struct pf_state *pf_find_state(struct pfi_kif *,
struct pf_state_key_cmp *, u_int);
int pf_src_connlimit(struct pf_state **);
-void pf_stateins_err(struct pf_state_key *,
- struct pfi_kif *);
+void pf_keyins_err(struct pf_state *, struct pf_state_key *,
+ struct pf_state_key *, char *, u_int8_t);
int pf_check_congestion(struct ifqueue *);
extern struct pool pfr_ktable_pl;
@@ -238,29 +248,21 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
{ &pfr_kentry_pl, PFR_KENTRY_HIWAT }
};
-#define STATE_LOOKUP() \
+#define STATE_LOOKUP(i, k, d, s) \
do { \
- *state = pf_find_state(kif, &key, direction); \
- if (*state == NULL || (*state)->timeout == PFTM_PURGE) \
+ s = pf_find_state(i, k, d); \
+ if (s == NULL || (s)->timeout == PFTM_PURGE) \
return (PF_DROP); \
- if (direction == PF_OUT && \
- (((*state)->rule.ptr->rt == PF_ROUTETO && \
- (*state)->rule.ptr->direction == PF_OUT) || \
- ((*state)->rule.ptr->rt == PF_REPLYTO && \
- (*state)->rule.ptr->direction == PF_IN)) && \
- (*state)->rt_kif != NULL && \
- (*state)->rt_kif != kif) \
+ if (d == PF_OUT && \
+ (((s)->rule.ptr->rt == PF_ROUTETO && \
+ (s)->rule.ptr->direction == PF_OUT) || \
+ ((s)->rule.ptr->rt == PF_REPLYTO && \
+ (s)->rule.ptr->direction == PF_IN)) && \
+ (s)->rt_kif != NULL && \
+ (s)->rt_kif != i) \
return (PF_PASS); \
} while (0)
-#define STATE_TRANSLATE(sk) \
- (sk)->lan.addr.addr32[0] != (sk)->gwy.addr.addr32[0] || \
- ((sk)->af == AF_INET6 && \
- ((sk)->lan.addr.addr32[1] != (sk)->gwy.addr.addr32[1] || \
- (sk)->lan.addr.addr32[2] != (sk)->gwy.addr.addr32[2] || \
- (sk)->lan.addr.addr32[3] != (sk)->gwy.addr.addr32[3])) || \
- (sk)->lan.port != (sk)->gwy.port
-
#define BOUND_IFACE(r, k) \
((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
@@ -432,12 +434,12 @@ pf_src_connlimit(struct pf_state **state)
if (pf_status.debug >= PF_DEBUG_MISC) {
printf("pf_src_connlimit: blocking address ");
pf_print_host(&(*state)->src_node->addr, 0,
- (*state)->key_wire->af);
+ (*state)->key[PF_SK_WIRE]->af);
}
bzero(&p, sizeof(p));
- p.pfra_af = (*state)->key_wire->af;
- switch ((*state)->key_wire->af) {
+ p.pfra_af = (*state)->key[PF_SK_WIRE]->af;
+ switch ((*state)->key[PF_SK_WIRE]->af) {
#ifdef INET
case AF_INET:
p.pfra_net = 32;
@@ -462,21 +464,20 @@ pf_src_connlimit(struct pf_state **state)
pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
RB_FOREACH(st, pf_state_tree_id, &tree_id) {
- sk = st->key_wire;
+ sk = st->key[PF_SK_WIRE];
/*
* Kill states from this source. (Only those
* from the same rule if PF_FLUSH_GLOBAL is not
* set)
*/
if (sk->af ==
- (*state)->key_wire->af &&
- (((*state)->direction ==
- PF_OUT &&
+ (*state)->key[PF_SK_WIRE]->af &&
+ (((*state)->direction == PF_OUT &&
PF_AEQ(&(*state)->src_node->addr,
- &sk->addr1, sk->af)) ||
+ &sk->addr[0], sk->af)) ||
((*state)->direction == PF_IN &&
PF_AEQ(&(*state)->src_node->addr,
- &sk->addr2, sk->af))) &&
+ &sk->addr[1], sk->af))) &&
((*state)->rule.ptr->flush &
PF_FLUSH_GLOBAL ||
(*state)->rule.ptr == st->rule.ptr)) {
@@ -564,16 +565,12 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
}
void
-pf_stateins_err(struct pf_state_key *sk, struct pfi_kif *kif)
+pf_keyins_err(struct pf_state *s, struct pf_state_key *skw,
+ struct pf_state_key *sks, char *side, u_int8_t direction)
{
if (pf_status.debug >= PF_DEBUG_MISC) {
- printf("pf: state insert failed: %s", kif->pfik_name);
- printf(" addr1: ");
- pf_print_host(&sk->addr1, sk->port1,
- sk->af);
- printf(" addr2: ");
- pf_print_host(&sk->addr2, sk->port2,
- sk->af);
+ printf("pf: %s key insert failed: ", side, s->kif->pfik_name);
+ pf_print_state_parts(s, skw, sks);
printf("\n");
}
}
@@ -592,57 +589,57 @@ pf_state_compare_key(struct pf_state_key *a, struct pf_state_key *b)
switch (a->af) {
#ifdef INET
case AF_INET:
- if (a->addr1.addr32[0] > b->addr1.addr32[0])
+ if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
return (1);
- if (a->addr1.addr32[0] < b->addr1.addr32[0])
+ if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
return (-1);
- if (a->addr2.addr32[0] > b->addr2.addr32[0])
+ if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
return (1);
- if (a->addr2.addr32[0] < b->addr2.addr32[0])
+ if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
return (-1);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- if (a->addr1.addr32[3] > b->addr1.addr32[3])
+ if (a->addr[0].addr32[3] > b->addr[0].addr32[3])
return (1);
- if (a->addr1.addr32[3] < b->addr1.addr32[3])
+ if (a->addr[0].addr32[3] < b->addr[0].addr32[3])
return (-1);
- if (a->addr2.addr32[3] > b->addr2.addr32[3])
+ if (a->addr[1].addr32[3] > b->addr[1].addr32[3])
return (1);
- if (a->addr2.addr32[3] < b->addr2.addr32[3])
+ if (a->addr[1].addr32[3] < b->addr[1].addr32[3])
return (-1);
- if (a->addr1.addr32[2] > b->addr1.addr32[2])
+ if (a->addr[0].addr32[2] > b->addr[0].addr32[2])
return (1);
- if (a->addr1.addr32[2] < b->addr1.addr32[2])
+ if (a->addr[0].addr32[2] < b->addr[0].addr32[2])
return (-1);
- if (a->addr2.addr32[2] > b->addr2.addr32[2])
+ if (a->addr[1].addr32[2] > b->addr[1].addr32[2])
return (1);
- if (a->addr2.addr32[2] < b->addr2.addr32[2])
+ if (a->addr[1].addr32[2] < b->addr[1].addr32[2])
return (-1);
- if (a->addr1.addr32[1] > b->addr1.addr32[1])
+ if (a->addr[0].addr32[1] > b->addr[0].addr32[1])
return (1);
- if (a->addr1.addr32[1] < b->addr1.addr32[1])
+ if (a->addr[0].addr32[1] < b->addr[0].addr32[1])
return (-1);
- if (a->addr2.addr32[1] > b->addr2.addr32[1])
+ if (a->addr[1].addr32[1] > b->addr[1].addr32[1])
return (1);
- if (a->addr2.addr32[1] < b->addr2.addr32[1])
+ if (a->addr[1].addr32[1] < b->addr[1].addr32[1])
return (-1);
- if (a->addr1.addr32[0] > b->addr1.addr32[0])
+ if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
return (1);
- if (a->addr1.addr32[0] < b->addr1.addr32[0])
+ if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
return (-1);
- if (a->addr2.addr32[0] > b->addr2.addr32[0])
+ if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
return (1);
- if (a->addr2.addr32[0] < b->addr2.addr32[0])
+ if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
return (-1);
break;
#endif /* INET6 */
}
- if ((diff = a->port1 - b->port1) != 0)
+ if ((diff = a->port[0] - b->port[0]) != 0)
return (diff);
- if ((diff = a->port2 - b->port2) != 0)
+ if ((diff = a->port[1] - b->port[1]) != 0)
return (diff);
return (0);
@@ -670,9 +667,9 @@ pf_attach_state(struct pf_state_key *sk, struct pf_state *s, int tail,
struct pf_state_item *si;
if (where == PF_SK_WIRE || where == PF_SK_BOTH)
- s->key_wire = sk;
- if (where == PF_SK_STACK || where == PF_SK_BOTH)
- s->key_stack = sk;
+ s->key[PF_SK_WIRE] = sk;
+ if (where == PF_SK_STACK || where == PF_SK_BOTH)
+ s->key[PF_SK_STACK] = sk;
si = pool_get(&pf_state_item_pl, PR_NOWAIT);
si->s = s;
@@ -687,13 +684,17 @@ pf_attach_state(struct pf_state_key *sk, struct pf_state *s, int tail,
void
pf_detach_state(struct pf_state *s, int flags)
{
- if (s->key_wire == s->key_stack) {
- pf_state_key_detach(s->key_wire, s, flags);
- s->key_wire = s->key_stack = NULL;
- } else {
- pf_state_key_detach(s->key_stack, s, flags);
- pf_state_key_detach(s->key_wire, s, flags);
- s->key_wire = s->key_stack = NULL;
+ if (s->key[PF_SK_WIRE] == s->key[PF_SK_STACK])
+ s->key[PF_SK_WIRE] = NULL;
+
+ if (s->key[PF_SK_STACK] != NULL) {
+ pf_state_key_detach(s->key[PF_SK_STACK], s, flags);
+ s->key[PF_SK_STACK] = NULL;
+ }
+
+ if (s->key[PF_SK_WIRE] != NULL) {
+ pf_state_key_detach(s->key[PF_SK_WIRE], s, flags);
+ s->key[PF_SK_WIRE] = NULL;
}
}
@@ -730,28 +731,97 @@ pf_alloc_state_key(void)
return (sk);
}
-int
-pf_state_insert(struct pfi_kif *kif, struct pf_state_key *sk,
- struct pf_state *s)
+struct pf_state_key *
+pf_state_key_insert(struct pf_state_key *sk, struct pf_state *s)
{
struct pf_state_key *cur;
struct pf_state_item *si;
- s->kif = kif;
-
- if ((cur = RB_INSERT(pf_state_tree, &pf_statetbl, sk)) != NULL) {
+ if (sk && (cur = RB_INSERT(pf_state_tree, &pf_statetbl, sk)) != NULL) {
/* key exists. check for same kif, if none, add to key */
TAILQ_FOREACH(si, &cur->states, entry)
- if (si->s->kif == kif &&
- si->s->direction == s->direction) {
+ if (si->s->kif == s->kif &&
+ si->s->direction == s->direction) {
/* collision! */
- pf_stateins_err(sk, kif);
pf_detach_state(s, PF_DT_SKIP_STATETREE);
- return (-1);
+ return (NULL);
}
pf_detach_state(s, PF_DT_SKIP_STATETREE);
- /* RYAN PF_SK_BOTH not gut for nat shitz */
- pf_attach_state(cur, s, kif == pfi_all ? 1 : 0, PF_SK_BOTH);
+ return (cur);
+ }
+ return (sk);
+}
+
+
+int
+pf_state_key_setup(struct pf_pdesc *pd, struct pf_rule *nr,
+ struct pf_state_key **skw, struct pf_state_key **sks,
+ struct pf_state_key **skp, struct pf_state_key **nkp,
+ struct pf_addr *saddr, struct pf_addr *daddr,
+ u_int16_t sport, u_int16_t dport)
+{
+ KASSERT((*skp == NULL && *nkp == NULL));
+
+ if ((*skp = pf_alloc_state_key()) == NULL)
+ return (ENOMEM);
+
+ PF_ACPY(&(*skp)->addr[pd->sidx], saddr, pd->af);
+ PF_ACPY(&(*skp)->addr[pd->didx], daddr, pd->af);
+ (*skp)->port[pd->sidx] = sport;
+ (*skp)->port[pd->didx] = dport;
+ (*skp)->proto = pd->proto;
+ (*skp)->af = pd->af;
+
+ if (nr != NULL) {
+ if ((*nkp = pf_alloc_state_key()) == NULL)
+ return (ENOMEM); /* cleanup handled in pf_test_rule() */
+
+ /* XXX maybe just bcopy and TAILQ_INIT(&(*nkp)->states) */
+ PF_ACPY(&(*nkp)->addr[0], &(*skp)->addr[0], pd->af);
+ PF_ACPY(&(*nkp)->addr[1], &(*skp)->addr[1], pd->af);
+ (*nkp)->port[0] = (*skp)->port[0];
+ (*nkp)->port[1] = (*skp)->port[1];
+ (*nkp)->proto = pd->proto;
+ (*nkp)->af = pd->af;
+ } else
+ *nkp = *skp;
+
+ if (pd->dir == PF_IN) {
+ *skw = *skp;
+ *sks = *nkp;
+ } else {
+ *sks = *skp;
+ *skw = *nkp;
+ }
+ return (0);
+}
+
+
+int
+pf_state_insert(struct pfi_kif *kif, struct pf_state_key *skw,
+ struct pf_state_key *sks, struct pf_state *s)
+{
+ struct pf_state_key *nskw, *nsks;
+
+ s->kif = kif;
+
+ KASSERT((sks != NULL));
+ KASSERT((skw != NULL));
+
+ if ((nskw = pf_state_key_insert(skw, s)) == NULL) {
+ pf_keyins_err(s, skw, sks, "wire", s->direction);
+ return (-1);
+ }
+
+ if (skw == sks) {
+ pf_attach_state(nskw, s, kif == pfi_all ? 1 : 0, PF_SK_BOTH);
+ } else {
+ if ((nsks = pf_state_key_insert(sks, s)) == NULL) {
+ pf_keyins_err(s, skw, sks, "stack", s->direction);
+ return (-1);
+ }
+ pf_attach_state(nskw, s, kif == pfi_all ? 1 : 0, PF_SK_WIRE);
+ pf_attach_state(nsks, s, kif == pfi_all ? 1 : 0, PF_SK_STACK);
}
if (s->id == 0 && s->creatorid == 0) {
@@ -775,10 +845,8 @@ pf_state_insert(struct pfi_kif *kif, struct pf_state_key *sk,
pf_status.states++;
pfi_kif_ref(kif, PFI_KIF_REF_STATE);
#if NPFSYNC
-#ifdef XXX_PFSYNC_FIXED
pfsync_insert_state(s);
#endif
-#endif
return (0);
}
@@ -786,7 +854,7 @@ struct pf_state *
pf_find_state_byid(struct pf_state_cmp *key)
{
pf_status.fcounters[FCNT_STATE_SEARCH]++;
-
+
return (RB_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key));
}
@@ -805,9 +873,10 @@ pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir)
/* list is sorted, if-bound states before floating ones */
TAILQ_FOREACH(si, &sk->states, entry)
if ((si->s->kif == pfi_all || si->s->kif == kif) &&
- ((dir == si->s->direction && si->s->key_wire == sk) ||
- (dir != si->s->direction && si->s->key_stack == sk)))
+ sk == (dir == PF_IN ? si->s->key[PF_SK_WIRE] :
+ si->s->key[PF_SK_STACK]))
return (si->s);
+
return (NULL);
}
@@ -822,12 +891,19 @@ pf_find_state_all(struct pf_state_key_cmp *key, u_int dir, int *more)
sk = RB_FIND(pf_state_tree, &pf_statetbl, (struct pf_state_key *)key);
if (sk != NULL) {
- ret = TAILQ_FIRST(&sk->states);
- if (more != NULL)
- TAILQ_FOREACH(si, &sk->states, entry)
- (*more)++;
+ TAILQ_FOREACH(si, &sk->states, entry)
+ if (dir == PF_INOUT ||
+ (sk == (dir == PF_IN ? si->s->key[PF_SK_WIRE] :
+ si->s->key[PF_SK_STACK]))) {
+ if (more == NULL)
+ return (si->s);
+
+ if (ret)
+ (*more)++;
+ else
+ ret = si;
+ }
}
-
return (ret ? ret->s : NULL);
}
@@ -963,9 +1039,11 @@ pf_unlink_state(struct pf_state *cur)
{
if (cur->src.state == PF_TCPS_PROXY_DST) {
/* XXX wire key the right one? */
- pf_send_tcp(cur->rule.ptr, cur->key_wire->af,
- &cur->key_wire->addr2, &cur->key_wire->addr1,
- cur->key_wire->port2, cur->key_wire->port1,
+ pf_send_tcp(cur->rule.ptr, cur->key[PF_SK_WIRE]->af,
+ &cur->key[PF_SK_WIRE]->addr[1],
+ &cur->key[PF_SK_WIRE]->addr[0],
+ cur->key[PF_SK_WIRE]->port[1],
+ cur->key[PF_SK_WIRE]->port[0],
cur->src.seqhi, cur->src.seqlo + 1,
TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
}
@@ -1152,42 +1230,81 @@ pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
void
pf_print_state(struct pf_state *s)
{
- struct pf_state_key *sk = s->key_wire;
- switch (sk->proto) {
+ pf_print_state_parts(s, NULL, NULL);
+}
+
+void
+pf_print_state_parts(struct pf_state *s,
+ struct pf_state_key *skwp, struct pf_state_key *sksp)
+{
+ struct pf_state_key *skw, *sks;
+ u_int8_t proto, dir;
+
+ /* Do our best to fill these, but they're skipped if NULL */
+ skw = skwp ? skwp : (s ? s->key[PF_SK_WIRE] : NULL);
+ sks = sksp ? sksp : (s ? s->key[PF_SK_STACK] : NULL);
+ proto = skw ? skw->proto : (sks ? sks->proto : 0);
+ dir = s ? s->direction : 0;
+
+ switch (proto) {
case IPPROTO_TCP:
- printf("TCP ");
+ printf("TCP");
break;
case IPPROTO_UDP:
- printf("UDP ");
+ printf("UDP");
break;
case IPPROTO_ICMP:
- printf("ICMP ");
+ printf("ICMP");
break;
case IPPROTO_ICMPV6:
- printf("ICMPV6 ");
+ printf("ICMPV6");
break;
default:
- printf("%u ", sk->proto);
+ printf("%u", skw->proto);
break;
}
- pf_print_host(&sk->addr1, sk->port1, sk->af);
- printf(" ");
- pf_print_host(&sk->addr2, sk->port2, sk->af);
-#ifdef RYAN_NAT
- printf(" ");
- pf_print_host(&sk->addr2, sk->ext.port, sk->af);
-#endif
- printf(" [lo=%u high=%u win=%u modulator=%u", s->src.seqlo,
- s->src.seqhi, s->src.max_win, s->src.seqdiff);
- if (s->src.wscale && s->dst.wscale)
- printf(" wscale=%u", s->src.wscale & PF_WSCALE_MASK);
- printf("]");
- printf(" [lo=%u high=%u win=%u modulator=%u", s->dst.seqlo,
- s->dst.seqhi, s->dst.max_win, s->dst.seqdiff);
- if (s->src.wscale && s->dst.wscale)
- printf(" wscale=%u", s->dst.wscale & PF_WSCALE_MASK);
- printf("]");
- printf(" %u:%u", s->src.state, s->dst.state);
+ switch (dir) {
+ case PF_IN:
+ printf(" in");
+ break;
+ case PF_OUT:
+ printf(" out");
+ break;
+ }
+ if (skw) {
+ printf(" wire: ");
+ pf_print_host(&skw->addr[0], skw->port[0], skw->af);
+ printf(" ");
+ pf_print_host(&skw->addr[1], skw->port[1], skw->af);
+ }
+ if (sks) {
+ printf(" stack: ");
+ if (sks != skw) {
+ pf_print_host(&sks->addr[0], sks->port[0], sks->af);
+ printf(" ");
+ pf_print_host(&sks->addr[1], sks->port[1], sks->af);
+ } else
+ printf("-");
+ }
+ if (s) {
+ if (proto == IPPROTO_TCP) {
+ printf(" [lo=%u high=%u win=%u modulator=%u",
+ s->src.seqlo, s->src.seqhi,
+ s->src.max_win, s->src.seqdiff);
+ if (s->src.wscale && s->dst.wscale)
+ printf(" wscale=%u",
+ s->src.wscale & PF_WSCALE_MASK);
+ printf("]");
+ printf(" [lo=%u high=%u win=%u modulator=%u",
+ s->dst.seqlo, s->dst.seqhi,
+ s->dst.max_win, s->dst.seqdiff);
+ if (s->src.wscale && s->dst.wscale)
+ printf(" wscale=%u",
+ s->dst.wscale & PF_WSCALE_MASK);
+ printf("]");
+ }
+ printf(" %u:%u", s->src.state, s->dst.state);
+ }
}
void
@@ -1394,7 +1511,8 @@ pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
struct pf_addr oia, ooa;
PF_ACPY(&oia, ia, af);
- PF_ACPY(&ooa, oa, af);
+ if (oa)
+ PF_ACPY(&ooa, oa, af);
/* Change inner protocol port, fix inner protocol checksum. */
if (ip != NULL) {
@@ -1443,31 +1561,33 @@ pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
break;
#endif /* INET6 */
}
- /* Change outer ip address, fix outer ip or icmpv6 checksum. */
- PF_ACPY(oa, na, af);
- switch (af) {
+ /* Outer ip address, fix outer ip or icmpv6 checksum, if necessary. */
+ if (oa) {
+ PF_ACPY(oa, na, af);
+ switch (af) {
#ifdef INET
- case AF_INET:
- *hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
- ooa.addr16[0], oa->addr16[0], 0),
- ooa.addr16[1], oa->addr16[1], 0);
- break;
+ case AF_INET:
+ *hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
+ ooa.addr16[0], oa->addr16[0], 0),
+ ooa.addr16[1], oa->addr16[1], 0);
+ break;
#endif /* INET */
#ifdef INET6
- case AF_INET6:
- *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(*ic,
- ooa.addr16[0], oa->addr16[0], u),
- ooa.addr16[1], oa->addr16[1], u),
- ooa.addr16[2], oa->addr16[2], u),
- ooa.addr16[3], oa->addr16[3], u),
- ooa.addr16[4], oa->addr16[4], u),
- ooa.addr16[5], oa->addr16[5], u),
- ooa.addr16[6], oa->addr16[6], u),
- ooa.addr16[7], oa->addr16[7], u);
- break;
+ case AF_INET6:
+ *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(*ic,
+ ooa.addr16[0], oa->addr16[0], u),
+ ooa.addr16[1], oa->addr16[1], u),
+ ooa.addr16[2], oa->addr16[2], u),
+ ooa.addr16[3], oa->addr16[3], u),
+ ooa.addr16[4], oa->addr16[4], u),
+ ooa.addr16[5], oa->addr16[5], u),
+ ooa.addr16[6], oa->addr16[6], u),
+ ooa.addr16[7], oa->addr16[7], u);
+ break;
#endif /* INET6 */
+ }
}
}
@@ -2254,7 +2374,6 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
struct pf_src_node **sn)
{
-#ifdef RYAN_NAT
struct pf_state_key_cmp key;
struct pf_addr init_addr;
u_int16_t cut;
@@ -2271,9 +2390,9 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
do {
key.af = af;
key.proto = proto;
- PF_ACPY(&key.addr2, daddr, key.af);
- PF_ACPY(&key.addr1, naddr, key.af);
- key.port2 = dport;
+ PF_ACPY(&key.addr[1], daddr, key.af);
+ PF_ACPY(&key.addr[0], naddr, key.af);
+ key.port[1] = dport;
/*
* port search; start random, step;
@@ -2281,15 +2400,15 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
*/
if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
proto == IPPROTO_ICMP)) {
- key.gwy.port = dport;
+ key.port[0] = dport;
if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
return (0);
} else if (low == 0 && high == 0) {
- key.gwy.port = *nport;
+ key.port[0] = *nport;
if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
return (0);
} else if (low == high) {
- key.gwy.port = htons(low);
+ key.port[0] = htons(low);
if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
*nport = htons(low);
return (0);
@@ -2306,7 +2425,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
cut = htonl(arc4random()) % (1 + high - low) + low;
/* low <= cut <= high */
for (tmp = cut; tmp <= high; ++(tmp)) {
- key.gwy.port = htons(tmp);
+ key.port[0] = htons(tmp);
if (pf_find_state_all(&key, PF_IN, NULL) ==
NULL) {
*nport = htons(tmp);
@@ -2314,7 +2433,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
}
}
for (tmp = cut - 1; tmp >= low; --(tmp)) {
- key.gwy.port = htons(tmp);
+ key.port[0] = htons(tmp);
if (pf_find_state_all(&key, PF_IN, NULL) ==
NULL) {
*nport = htons(tmp);
@@ -2336,7 +2455,6 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
return (1);
}
} while (! PF_AEQ(&init_addr, naddr, af) );
-#endif
return (1); /* none available */
}
@@ -2424,12 +2542,14 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
struct pf_rule *
pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
struct pfi_kif *kif, struct pf_src_node **sn,
- struct pf_addr *saddr, u_int16_t sport,
- struct pf_addr *daddr, u_int16_t dport,
- struct pf_addr *naddr, u_int16_t *nport)
+ struct pf_state_key **skw, struct pf_state_key **sks,
+ struct pf_state_key **skp, struct pf_state_key **nkp,
+ struct pf_addr *saddr, struct pf_addr *daddr,
+ u_int16_t sport, u_int16_t dport)
{
struct pf_rule *r = NULL;
+
if (direction == PF_OUT) {
r = pf_match_translation(pd, m, off, direction, kif, saddr,
sport, daddr, dport, PF_RULESET_BINAT);
@@ -2445,6 +2565,17 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
}
if (r != NULL) {
+ struct pf_addr *naddr;
+ u_int16_t *nport;
+
+ if (pf_state_key_setup(pd, r, skw, sks, skp, nkp,
+ saddr, daddr, sport, dport))
+ return r;
+
+ /* XXX We only modify one side for now. */
+ naddr = &(*nkp)->addr[1];
+ nport = &(*nkp)->port[1];
+
switch (r->action) {
case PF_NONAT:
case PF_NOBINAT:
@@ -2787,7 +2918,7 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
s->rt_kif = NULL;
if (!r->rt || r->rt == PF_FASTROUTE)
return;
- switch (s->key_wire->af) {
+ switch (s->key[PF_SK_WIRE]->af) {
#ifdef INET
case AF_INET:
pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL,
@@ -2841,12 +2972,13 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
{
struct pf_rule *nr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
- u_int16_t bport, nport = 0;
sa_family_t af = pd->af;
struct pf_rule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL;
struct pf_src_node *nsn = NULL;
struct tcphdr *th = pd->hdr.tcp;
+ struct pf_state_key *skw = NULL, *sks = NULL;
+ struct pf_state_key *sk = NULL, *nk = NULL;
u_short reason;
int rewrite = 0, hdrlen = 0;
int tag = -1, rtableid = -1;
@@ -2855,15 +2987,16 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
int state_icmp = 0;
u_int16_t mss = tcp_mssdflt;
u_int16_t sport, dport;
+ u_int16_t nport = 0, bport = 0;
+ u_int16_t bproto_sum = 0, bip_sum;
u_int8_t icmptype = 0, icmpcode = 0;
+
if (direction == PF_IN && pf_check_congestion(ifq)) {
REASON_SET(&reason, PFRES_CONGEST);
return (PF_DROP);
}
- sport = dport = hdrlen = 0;
-
switch (pd->proto) {
case IPPROTO_TCP:
sport = th->th_sport;
@@ -2880,6 +3013,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
if (pd->af != AF_INET)
break;
sport = dport = pd->hdr.icmp->icmp_id;
+ hdrlen = sizeof(*pd->hdr.icmp);
icmptype = pd->hdr.icmp->icmp_type;
icmpcode = pd->hdr.icmp->icmp_code;
@@ -2893,7 +3027,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
#endif /* INET */
#ifdef INET6
case IPPROTO_ICMPV6:
- if (pd->af != AF_INET6)
+ if (af != AF_INET6)
break;
sport = dport = pd->hdr.icmp6->icmp6_id;
hdrlen = sizeof(*pd->hdr.icmp6);
@@ -2907,122 +3041,141 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
state_icmp++;
break;
#endif /* INET6 */
+ default:
+ sport = dport = hdrlen = 0;
+ break;
}
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
- if (direction == PF_OUT) {
- bport = nport = sport;
- /* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
- saddr, sport, daddr, dport, &pd->naddr, &nport)) != NULL) {
- PF_ACPY(&pd->baddr, saddr, af);
- switch (pd->proto) {
- case IPPROTO_TCP:
+ bport = nport = sport;
+ /* check packet for BINAT/NAT/RDR */
+ if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn,
+ &skw, &sks, &sk, &nk, saddr, daddr, sport, dport)) != NULL) {
+ if (nk == NULL || sk == NULL) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ goto cleanup;
+ }
+
+ bip_sum = *pd->ip_sum;
+
+ switch (pd->proto) {
+ case IPPROTO_TCP:
+ bproto_sum = th->th_sum;
+ pd->proto_sum = &th->th_sum;
+
+ if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
+ nk->port[pd->sidx] != sport) {
pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
- &th->th_sum, &pd->naddr, nport, 0, af);
+ &th->th_sum, &nk->addr[pd->sidx],
+ nk->port[pd->sidx], 0, af);
+ pd->sport = &th->th_sport;
sport = th->th_sport;
- rewrite++;
- break;
- case IPPROTO_UDP:
+ }
+
+ if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
+ nk->port[pd->didx] != dport) {
+ pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
+ &th->th_sum, &nk->addr[pd->didx],
+ nk->port[pd->didx], 0, af);
+ dport = th->th_dport;
+ pd->dport = &th->th_dport;
+ }
+ rewrite++;
+ break;
+ case IPPROTO_UDP:
+ bproto_sum = pd->hdr.udp->uh_sum;
+ pd->proto_sum = &pd->hdr.udp->uh_sum;
+
+ if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
+ nk->port[pd->sidx] != sport) {
pf_change_ap(saddr, &pd->hdr.udp->uh_sport,
pd->ip_sum, &pd->hdr.udp->uh_sum,
- &pd->naddr, nport, 1, af);
+ &nk->addr[pd->sidx],
+ nk->port[pd->sidx], 1, af);
sport = pd->hdr.udp->uh_sport;
- rewrite++;
- break;
-#ifdef INET
- case IPPROTO_ICMP:
- pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
- pd->naddr.v4.s_addr, 0);
- pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
- pd->hdr.icmp->icmp_cksum, sport, nport, 0);
- pd->hdr.icmp->icmp_id = nport;
- m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
- break;
-#endif /* INET */
-#ifdef INET6
- case IPPROTO_ICMPV6:
- pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
- &pd->naddr, 0);
- rewrite++;
- break;
-#endif /* INET */
- default:
- switch (af) {
-#ifdef INET
- case AF_INET:
- pf_change_a(&saddr->v4.s_addr,
- pd->ip_sum, pd->naddr.v4.s_addr, 0);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- PF_ACPY(saddr, &pd->naddr, af);
- break;
-#endif /* INET */
- }
- break;
+ pd->sport = &pd->hdr.udp->uh_sport;
}
- if (nr->natpass)
- r = NULL;
- pd->nat_rule = nr;
- }
- } else {
- bport = nport = dport;
- /* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
- saddr, sport, daddr, dport, &pd->naddr, &nport)) != NULL) {
- PF_ACPY(&pd->baddr, daddr, af);
- switch (pd->proto) {
- case IPPROTO_TCP:
- pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
- &th->th_sum, &pd->naddr, nport, 0, af);
- dport = th->th_dport;
- rewrite++;
- break;
- case IPPROTO_UDP:
+ if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
+ nk->port[pd->didx] != dport) {
pf_change_ap(daddr, &pd->hdr.udp->uh_dport,
pd->ip_sum, &pd->hdr.udp->uh_sum,
- &pd->naddr, nport, 1, af);
+ &nk->addr[pd->didx],
+ nk->port[pd->didx], 1, af);
dport = pd->hdr.udp->uh_dport;
- rewrite++;
- break;
+ pd->dport = &pd->hdr.udp->uh_dport;
+ }
+ rewrite++;
+ break;
#ifdef INET
- case IPPROTO_ICMP:
+ case IPPROTO_ICMP:
+ nk->port[0] = nk->port[1];
+ if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET))
+ pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
+ nk->addr[pd->sidx].v4.s_addr, 0);
+
+ if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET))
pf_change_a(&daddr->v4.s_addr, pd->ip_sum,
- pd->naddr.v4.s_addr, 0);
- break;
+ nk->addr[pd->didx].v4.s_addr, 0);
+
+ if (nk->port[1] != pd->hdr.icmp->icmp_id) {
+ pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum, sport,
+ nk->port[1], 0);
+ pd->hdr.icmp->icmp_id = nk->port[1];
+ pd->sport = &pd->hdr.icmp->icmp_id;
+ }
+ m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
+ break;
#endif /* INET */
#ifdef INET6
- case IPPROTO_ICMPV6:
+ case IPPROTO_ICMPV6:
+ nk->port[0] = nk->port[1];
+ if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET6))
+ pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
+ &nk->addr[pd->sidx], 0);
+
+ if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET6))
pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
- &pd->naddr, 0);
- rewrite++;
- break;
-#endif /* INET6 */
- default:
- switch (af) {
+ &nk->addr[pd->didx], 0);
+ rewrite++;
+ break;
+#endif /* INET */
+ default:
+ switch (af) {
#ifdef INET
- case AF_INET:
+ case AF_INET:
+ if (PF_ANEQ(saddr,
+ &nk->addr[pd->sidx], AF_INET))
+ pf_change_a(&saddr->v4.s_addr,
+ pd->ip_sum,
+ nk->addr[pd->didx].v4.s_addr, 0);
+
+ if (PF_ANEQ(daddr,
+ &nk->addr[pd->didx], AF_INET))
pf_change_a(&daddr->v4.s_addr,
- pd->ip_sum, pd->naddr.v4.s_addr, 0);
- break;
+ pd->ip_sum,
+ nk->addr[pd->didx].v4.s_addr, 0);
+ break;
#endif /* INET */
#ifdef INET6
- case AF_INET6:
- PF_ACPY(daddr, &pd->naddr, af);
- break;
-#endif /* INET */
- }
+ case AF_INET6:
+ if (PF_ANEQ(saddr,
+ &nk->addr[pd->sidx], AF_INET6))
+ PF_ACPY(saddr, &nk->addr[pd->sidx], af);
+
+ if (PF_ANEQ(daddr,
+ &nk->addr[pd->didx], AF_INET6))
+ PF_ACPY(saddr, &nk->addr[pd->didx], af);
break;
+#endif /* INET */
}
-
- if (nr->natpass)
- r = NULL;
- pd->nat_rule = nr;
+ break;
}
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
}
while (r != NULL) {
@@ -3124,77 +3277,17 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
(r->rule_flag & PFRULE_RETURN))) {
/* undo NAT changes, if they have taken place */
if (nr != NULL) {
- if (direction == PF_OUT) {
- switch (pd->proto) {
- case IPPROTO_TCP:
- pf_change_ap(saddr, &th->th_sport,
- pd->ip_sum, &th->th_sum,
- &pd->baddr, bport, 0, af);
- sport = th->th_sport;
- rewrite++;
- break;
- case IPPROTO_UDP:
- pf_change_ap(saddr,
- &pd->hdr.udp->uh_sport, pd->ip_sum,
- &pd->hdr.udp->uh_sum, &pd->baddr,
- bport, 1, af);
- sport = pd->hdr.udp->uh_sport;
- rewrite++;
- break;
- case IPPROTO_ICMP:
-#ifdef INET6
- case IPPROTO_ICMPV6:
-#endif
- /* nothing! */
- break;
- default:
- switch (af) {
- case AF_INET:
- pf_change_a(&saddr->v4.s_addr,
- pd->ip_sum,
- pd->baddr.v4.s_addr, 0);
- break;
- case AF_INET6:
- PF_ACPY(saddr, &pd->baddr, af);
- break;
- }
- }
- } else {
- switch (pd->proto) {
- case IPPROTO_TCP:
- pf_change_ap(daddr, &th->th_dport,
- pd->ip_sum, &th->th_sum,
- &pd->baddr, bport, 0, af);
- dport = th->th_dport;
- rewrite++;
- break;
- case IPPROTO_UDP:
- pf_change_ap(daddr,
- &pd->hdr.udp->uh_dport, pd->ip_sum,
- &pd->hdr.udp->uh_sum, &pd->baddr,
- bport, 1, af);
- dport = pd->hdr.udp->uh_dport;
- rewrite++;
- break;
- case IPPROTO_ICMP:
-#ifdef INET6
- case IPPROTO_ICMPV6:
-#endif
- /* nothing! */
- break;
- default:
- switch (af) {
- case AF_INET:
- pf_change_a(&daddr->v4.s_addr,
- pd->ip_sum,
- pd->baddr.v4.s_addr, 0);
- break;
- case AF_INET6:
- PF_ACPY(daddr, &pd->baddr, af);
- break;
- }
- }
- }
+ PF_ACPY(saddr, &sk->addr[pd->sidx], af);
+ PF_ACPY(daddr, &sk->addr[pd->didx], af);
+ if (pd->sport)
+ *pd->sport = sk->port[pd->sidx];
+ if (pd->dport)
+ *pd->dport = sk->port[pd->didx];
+ if (pd->proto_sum)
+ *pd->proto_sum = bproto_sum;
+ if (pd->ip_sum)
+ *pd->ip_sum = bip_sum;
+ m_copyback(m, off, hdrlen, pd->hdr.any);
}
if (pd->proto == IPPROTO_TCP &&
((r->rule_flag & PFRULE_RETURNRST) ||
@@ -3251,7 +3344,6 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
(pd->flags & PFDESC_TCP_NORM))) {
/* create new state */
struct pf_state *s = NULL;
- struct pf_state_key *sk = NULL;
struct pf_src_node *sn = NULL;
/* check maximums */
@@ -3270,8 +3362,9 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
/* src node for translation rule */
if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
((direction == PF_OUT &&
- pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
- (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
+ pf_insert_src_node(&nsn, nr, &sks->addr[0], af) != 0) ||
+ (direction == PF_IN &&
+ pf_insert_src_node(&nsn, nr, &skw->addr[0], af) != 0))) {
REASON_SET(&reason, PFRES_SRCLIMIT);
goto cleanup;
}
@@ -3292,9 +3385,10 @@ cleanup:
pf_status.src_nodes--;
pool_put(&pf_src_tree_pl, nsn);
}
- if (sk != NULL) {
+ if (sk != NULL)
pool_put(&pf_state_key_pl, sk);
- }
+ if (nk != NULL)
+ pool_put(&pf_state_key_pl, nk);
return (PF_DROP);
}
bzero(s, sizeof(*s));
@@ -3367,7 +3461,10 @@ cleanup:
s->src_node->states++;
}
if (nsn != NULL) {
- PF_ACPY(&nsn->raddr, &pd->naddr, af);
+ if (direction == PF_IN)
+ PF_ACPY(&nsn->raddr, &nk->addr[0], af);
+ else
+ PF_ACPY(&nsn->raddr, &nk->addr[1], af);
s->nat_src_node = nsn;
s->nat_src_node->states++;
}
@@ -3397,54 +3494,11 @@ cleanup:
}
s->direction = direction;
- if ((sk = pf_alloc_state_key()) == NULL) {
- REASON_SET(&reason, PFRES_MEMORY);
+ if (sk == NULL && pf_state_key_setup(pd, nr,
+ &skw, &sks, &sk, &nk, saddr, daddr, sport, dport))
goto cleanup;
- }
- sk->proto = pd->proto;
- sk->af = af;
- if (direction == PF_IN) {
- PF_ACPY(&sk->addr1, saddr, af);
- PF_ACPY(&sk->addr2, daddr, af);
- switch (pd->proto) {
- case IPPROTO_ICMP:
-#ifdef INET6
- case IPPROTO_ICMPV6:
-#endif
- sk->port1 = nport;
- sk->port2 = 0;
- break;
- default:
- sk->port1 = sport;
- sk->port2 = dport;
- }
- if (nr != NULL) {
-/* RYAN NAT */
- }
- } else {
- PF_ACPY(&sk->addr2, saddr, af);
- PF_ACPY(&sk->addr1, daddr, af);
- switch (pd->proto) {
- case IPPROTO_ICMP:
-#ifdef INET6
- case IPPROTO_ICMPV6:
-#endif
- sk->port2 = nport;
- sk->port1 = 0;
- break;
- default:
- sk->port2 = sport;
- sk->port1 = dport;
- }
- if (nr != NULL) {
-/* RYAN NAT */
- }
- }
-
- pf_attach_state(sk, s, 0, PF_SK_BOTH);
- pf_set_rt_ifp(s, saddr); /* needs s->state_key set */
- if (pf_state_insert(BOUND_IFACE(r, kif), sk, s)) {
+ if (pf_state_insert(BOUND_IFACE(r, kif), skw, sks, s)) {
if (pd->proto == IPPROTO_TCP)
pf_normalize_tcp_cleanup(s);
REASON_SET(&reason, PFRES_STATEINS);
@@ -3454,6 +3508,9 @@ cleanup:
return (PF_DROP);
} else
*sm = s;
+
+ pf_set_rt_ifp(s, saddr); /* needs s->state_key set */
+
if (tag > 0) {
pf_tag_ref(tag);
s->tag = tag;
@@ -3463,17 +3520,20 @@ cleanup:
r->keep_state == PF_STATE_SYNPROXY) {
s->src.state = PF_TCPS_PROXY_SRC;
if (nr != NULL) {
- if (direction == PF_OUT) {
- pf_change_ap(saddr, &th->th_sport,
- pd->ip_sum, &th->th_sum, &pd->baddr,
- bport, 0, af);
- sport = th->th_sport;
- } else {
- pf_change_ap(daddr, &th->th_dport,
- pd->ip_sum, &th->th_sum, &pd->baddr,
- bport, 0, af);
- sport = th->th_dport;
- }
+ if (PF_ANEQ(pd->src, &nk->addr[0], pd->af) ||
+ nk->port[0] != th->th_sport)
+ pf_change_ap(pd->src, &th->th_sport,
+ pd->ip_sum, &th->th_sum,
+ &nk->addr[0], nk->port[0],
+ 0, pd->af);
+ if (PF_ANEQ(pd->dst, &nk->addr[1], pd->af) ||
+ nk->port[1] != th->th_dport)
+ pf_change_ap(pd->dst, &th->th_dport,
+ pd->ip_sum, &th->th_sum,
+ &nk->addr[1], nk->port[1],
+ 0, pd->af);
+ sport = th->th_sport;
+ dport = th->th_dport;
}
s->src.seqhi = htonl(arc4random());
/* Find mss option */
@@ -3600,18 +3660,18 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd->af;
key.proto = IPPROTO_TCP;
if (direction == PF_IN) { /* wire side, straight */
- PF_ACPY(&key.addr1, pd->src, key.af);
- PF_ACPY(&key.addr2, pd->dst, key.af);
- key.port1 = th->th_sport;
- key.port2 = th->th_dport;
+ PF_ACPY(&key.addr[0], pd->src, key.af);
+ PF_ACPY(&key.addr[1], pd->dst, key.af);
+ key.port[0] = th->th_sport;
+ key.port[1] = th->th_dport;
} else { /* stack side, reverse */
- PF_ACPY(&key.addr2, pd->src, key.af);
- PF_ACPY(&key.addr1, pd->dst, key.af);
- key.port2 = th->th_sport;
- key.port1 = th->th_dport;
+ PF_ACPY(&key.addr[1], pd->src, key.af);
+ PF_ACPY(&key.addr[0], pd->dst, key.af);
+ key.port[1] = th->th_sport;
+ key.port[0] = th->th_dport;
}
- STATE_LOOKUP();
+ STATE_LOOKUP(kif, &key, direction, *state);
if (direction == (*state)->direction) {
src = &(*state)->src;
@@ -3661,8 +3721,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
(*state)->src.max_win = MAX(ntohs(th->th_win), 1);
if ((*state)->dst.seqhi == 1)
(*state)->dst.seqhi = htonl(arc4random());
- pf_send_tcp((*state)->rule.ptr, pd->af, &key.addr1,
- &key.addr2, key.port1, key.port2,
+ pf_send_tcp((*state)->rule.ptr, pd->af, &key.addr[0],
+ &key.addr[1], key.port[0], key.port[1],
(*state)->dst.seqhi, 0, TH_SYN, 0,
(*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
REASON_SET(reason, PFRES_SYNPROXY);
@@ -3680,8 +3740,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
ntohl(th->th_ack), ntohl(th->th_seq) + 1,
TH_ACK, (*state)->src.max_win, 0, 0, 0,
(*state)->tag, NULL, NULL);
- pf_send_tcp((*state)->rule.ptr, pd->af, &key.addr1,
- &key.addr2, key.port1, key.port2,
+ pf_send_tcp((*state)->rule.ptr, pd->af, &key.addr[0],
+ &key.addr[1], key.port[0], key.port[1],
(*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
TH_ACK, (*state)->dst.max_win, 0, 0, 1,
0, NULL, NULL);
@@ -4036,20 +4096,23 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
/* Any packets which have gotten here are to be passed */
-#ifdef RYAN_NAT
/* translate source/destination address, if necessary */
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_OUT)
+ if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk = (*state)->key[pd->didx];
+
+ if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
+ nk->port[pd->sidx] != th->th_sport)
pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
- &th->th_sum, &(*state)->state_key->gwy.addr,
- (*state)->state_key->gwy.port, 0, pd->af);
- else
+ &th->th_sum, &nk->addr[pd->sidx],
+ nk->port[pd->sidx], 0, pd->af);
+
+ if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
+ nk->port[pd->didx] != th->th_dport)
pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
- &th->th_sum, &(*state)->state_key->addr1,
- (*state)->state_key->lan.port, 0, pd->af);
+ &th->th_sum, &nk->addr[pd->didx],
+ nk->port[pd->didx], 0, pd->af);
copyback = 1;
}
-#endif
/* Copyback sequence modulation or stateful scrub changes if needed */
if (copyback)
@@ -4069,18 +4132,18 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd->af;
key.proto = IPPROTO_UDP;
if (direction == PF_IN) { /* wire side, straight */
- PF_ACPY(&key.addr1, pd->src, key.af);
- PF_ACPY(&key.addr2, pd->dst, key.af);
- key.port1 = uh->uh_sport;
- key.port2 = uh->uh_dport;
+ PF_ACPY(&key.addr[0], pd->src, key.af);
+ PF_ACPY(&key.addr[1], pd->dst, key.af);
+ key.port[0] = uh->uh_sport;
+ key.port[1] = uh->uh_dport;
} else { /* stack side, reverse */
- PF_ACPY(&key.addr2, pd->src, key.af);
- PF_ACPY(&key.addr1, pd->dst, key.af);
- key.port2 = uh->uh_sport;
- key.port1 = uh->uh_dport;
+ PF_ACPY(&key.addr[1], pd->src, key.af);
+ PF_ACPY(&key.addr[0], pd->dst, key.af);
+ key.port[1] = uh->uh_sport;
+ key.port[0] = uh->uh_dport;
}
- STATE_LOOKUP();
+ STATE_LOOKUP(kif, &key, direction, *state);
if (direction == (*state)->direction) {
src = &(*state)->src;
@@ -4103,20 +4166,23 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
else
(*state)->timeout = PFTM_UDP_SINGLE;
-#ifdef RYAN_NAT
/* translate source/destination address, if necessary */
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_OUT)
+ if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk = (*state)->key[pd->didx];
+
+ if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
+ nk->port[pd->sidx] != uh->uh_sport)
pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
- &uh->uh_sum, &(*state)->state_key->gwy.addr,
- (*state)->state_key->gwy.port, 1, pd->af);
- else
+ &uh->uh_sum, &nk->addr[pd->sidx],
+ nk->port[pd->sidx], 1, pd->af);
+
+ if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
+ nk->port[pd->didx] != uh->uh_dport)
pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
- &uh->uh_sum, &(*state)->state_key->addr1,
- (*state)->state_key->lan.port, 1, pd->af);
+ &uh->uh_sum, &nk->addr[pd->didx],
+ nk->port[pd->didx], 1, pd->af);
m_copyback(m, off, sizeof(*uh), uh);
}
-#endif
return (PF_PASS);
}
@@ -4125,6 +4191,7 @@ int
pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason)
{
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst;
u_int16_t icmpid, *icmpsum;
u_int8_t icmptype;
int state_icmp = 0;
@@ -4168,85 +4235,74 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
*/
key.af = pd->af;
key.proto = pd->proto;
+ key.port[0] = key.port[1] = icmpid;
if (direction == PF_IN) { /* wire side, straight */
- PF_ACPY(&key.addr1, pd->src, key.af);
- PF_ACPY(&key.addr2, pd->dst, key.af);
- key.port1 = icmpid;
- key.port2 = 0;
+ PF_ACPY(&key.addr[0], pd->src, key.af);
+ PF_ACPY(&key.addr[1], pd->dst, key.af);
} else { /* stack side, reverse */
- PF_ACPY(&key.addr2, pd->src, key.af);
- PF_ACPY(&key.addr1, pd->dst, key.af);
- key.port2 = 0;
- key.port1 = icmpid;
+ PF_ACPY(&key.addr[1], pd->src, key.af);
+ PF_ACPY(&key.addr[0], pd->dst, key.af);
}
- STATE_LOOKUP();
+ STATE_LOOKUP(kif, &key, direction, *state);
(*state)->expire = time_second;
(*state)->timeout = PFTM_ICMP_ERROR_REPLY;
-#ifdef RYAN_NAT
/* translate source/destination address, if necessary */
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_OUT) {
- switch (pd->af) {
+ if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk = (*state)->key[pd->didx];
+
+ switch (pd->af) {
#ifdef INET
- case AF_INET:
+ case AF_INET:
+ if (PF_ANEQ(pd->src,
+ &nk->addr[pd->sidx], AF_INET))
pf_change_a(&saddr->v4.s_addr,
pd->ip_sum,
- (*state)->state_key->gwy.addr.v4.s_addr, 0);
- pd->hdr.icmp->icmp_cksum =
- pf_cksum_fixup(
- pd->hdr.icmp->icmp_cksum, icmpid,
- (*state)->state_key->gwy.port, 0);
- pd->hdr.icmp->icmp_id =
- (*state)->state_key->gwy.port;
- m_copyback(m, off, ICMP_MINLEN,
- pd->hdr.icmp);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- pf_change_a6(saddr,
- &pd->hdr.icmp6->icmp6_cksum,
- &(*state)->state_key->gwy.addr, 0);
- m_copyback(m, off,
- sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
- break;
-#endif /* INET6 */
- }
- } else {
- switch (pd->af) {
-#ifdef INET
- case AF_INET:
+ nk->addr[pd->sidx].v4.s_addr, 0);
+
+ if (PF_ANEQ(pd->dst, &nk->addr[pd->didx],
+ AF_INET))
pf_change_a(&daddr->v4.s_addr,
pd->ip_sum,
- (*state)->state_key->addr1.v4.s_addr, 0);
+ nk->addr[pd->didx].v4.s_addr, 0);
+
+ if (nk->port[0] !=
+ pd->hdr.icmp->icmp_id) {
pd->hdr.icmp->icmp_cksum =
pf_cksum_fixup(
pd->hdr.icmp->icmp_cksum, icmpid,
- (*state)->state_key->lan.port, 0);
+ nk->port[pd->sidx], 0);
pd->hdr.icmp->icmp_id =
- (*state)->state_key->lan.port;
- m_copyback(m, off, ICMP_MINLEN,
- pd->hdr.icmp);
- break;
+ nk->port[pd->sidx];
+ }
+
+ m_copyback(m, off, ICMP_MINLEN,
+ pd->hdr.icmp);
+ break;
#endif /* INET */
#ifdef INET6
- case AF_INET6:
+ case AF_INET6:
+ if (PF_ANEQ(pd->src,
+ &nk->addr[pd->sidx], AF_INET6))
+ pf_change_a6(saddr,
+ &pd->hdr.icmp6->icmp6_cksum,
+ &nk->addr[pd->sidx], 0);
+
+ if (PF_ANEQ(pd->dst,
+ &nk->addr[pd->didx], AF_INET6))
pf_change_a6(daddr,
&pd->hdr.icmp6->icmp6_cksum,
- &(*state)->state_key->addr1, 0);
- m_copyback(m, off,
- sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
- break;
+ &nk->addr[pd->didx], 0);
+
+ m_copyback(m, off,
+ sizeof(struct icmp6_hdr),
+ pd->hdr.icmp6);
+ break;
#endif /* INET6 */
- }
}
}
-#endif /* RYAN_NAT */
return (PF_PASS);
} else {
@@ -4267,6 +4323,9 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
int off2;
pd2.af = pd->af;
+ /* Payload packet is from the opposite direction. */
+ pd2.sidx = (direction == PF_IN) ? 1 : 0;
+ pd2.didx = (direction == PF_IN) ? 0 : 1;
switch (pd->af) {
#ifdef INET
case AF_INET:
@@ -4377,19 +4436,12 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd2.af;
key.proto = IPPROTO_TCP;
- if (direction == PF_IN) { /* wire, straight */
- PF_ACPY(&key.addr1, pd2.src, key.af);
- PF_ACPY(&key.addr2, pd2.dst, key.af);
- key.port1 = th.th_sport;
- key.port2 = th.th_dport;
- } else { /* stack, reverse */
- PF_ACPY(&key.addr2, pd2.src, key.af);
- PF_ACPY(&key.addr1, pd2.dst, key.af);
- key.port2 = th.th_sport;
- key.port1 = th.th_dport;
- }
+ PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+ PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+ key.port[pd2.sidx] = th.th_sport;
+ key.port[pd2.didx] = th.th_dport;
- STATE_LOOKUP();
+ STATE_LOOKUP(kif, &key, direction, *state);
if (direction == (*state)->direction) {
src = &(*state)->dst;
@@ -4426,26 +4478,46 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
}
REASON_SET(reason, PFRES_BADSTATE);
return (PF_DROP);
+ } else {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: OK ICMP %d:%d ",
+ icmptype, pd->hdr.icmp->icmp_code);
+ pf_print_host(pd->src, 0, pd->af);
+ printf(" -> ");
+ pf_print_host(pd->dst, 0, pd->af);
+ printf(" state: ");
+ pf_print_state(*state);
+ printf(" seq=%u\n", seq);
+ }
}
-#ifdef RYAN_NAT
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_IN) {
+ /* translate source/destination address, if necessary */
+ if ((*state)->key[PF_SK_WIRE] !=
+ (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk =
+ (*state)->key[pd->didx];
+
+ if (PF_ANEQ(pd2.src,
+ &nk->addr[pd2.sidx], pd2.af) ||
+ nk->port[pd2.sidx] != th.th_sport)
pf_change_icmp(pd2.src, &th.th_sport,
- daddr, &(*state)->state_key->addr1,
- (*state)->state_key->lan.port, NULL,
+ daddr, &nk->addr[pd2.sidx],
+ nk->port[pd2.sidx], NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, pd2.af);
- } else {
+
+ if (PF_ANEQ(pd2.dst,
+ &nk->addr[pd2.didx], pd2.af) ||
+ nk->port[pd2.didx] != th.th_dport)
pf_change_icmp(pd2.dst, &th.th_dport,
- saddr, &(*state)->state_key->gwy.addr,
- (*state)->state_key->gwy.port, NULL,
+ NULL, /* XXX Inbound NAT? */
+ &nk->addr[pd2.didx],
+ nk->port[pd2.didx], NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, pd2.af);
- }
copyback = 1;
}
-#endif
+
if (copyback) {
switch (pd2.af) {
#ifdef INET
@@ -4485,37 +4557,38 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd2.af;
key.proto = IPPROTO_UDP;
- if (direction == PF_IN) { /* wire, straight */
- PF_ACPY(&key.addr1, pd2.src, key.af);
- PF_ACPY(&key.addr2, pd2.dst, key.af);
- key.port1 = uh.uh_sport;
- key.port2 = uh.uh_dport;
- } else { /* stack, reverse */
- PF_ACPY(&key.addr2, pd2.src, key.af);
- PF_ACPY(&key.addr1, pd2.dst, key.af);
- key.port2 = uh.uh_sport;
- key.port1 = uh.uh_dport;
- }
-
- STATE_LOOKUP();
-#ifdef RYAN_NAT
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_IN) {
+ PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+ PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+ key.port[pd2.sidx] = uh.uh_sport;
+ key.port[pd2.didx] = uh.uh_dport;
+
+ STATE_LOOKUP(kif, &key, direction, *state);
+
+ /* translate source/destination address, if necessary */
+ if ((*state)->key[PF_SK_WIRE] !=
+ (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk =
+ (*state)->key[pd->didx];
+
+ if (PF_ANEQ(pd2.src,
+ &nk->addr[pd2.sidx], pd2.af) ||
+ nk->port[pd2.sidx] != uh.uh_sport)
pf_change_icmp(pd2.src, &uh.uh_sport,
- daddr,
- &(*state)->state_key->addr1,
- (*state)->state_key->lan.port,
- &uh.uh_sum,
+ daddr, &nk->addr[pd2.sidx],
+ nk->port[pd2.sidx], &uh.uh_sum,
pd2.ip_sum, icmpsum,
pd->ip_sum, 1, pd2.af);
- } else {
+
+ if (PF_ANEQ(pd2.dst,
+ &nk->addr[pd2.didx], pd2.af) ||
+ nk->port[pd2.didx] != uh.uh_dport)
pf_change_icmp(pd2.dst, &uh.uh_dport,
- saddr,
- &(*state)->state_key->gwy.addr,
- (*state)->state_key->gwy.port, &uh.uh_sum,
+ NULL, /* XXX Inbound NAT? */
+ &nk->addr[pd2.didx],
+ nk->port[pd2.didx], &uh.uh_sum,
pd2.ip_sum, icmpsum,
pd->ip_sum, 1, pd2.af);
- }
+
switch (pd2.af) {
#ifdef INET
case AF_INET:
@@ -4536,7 +4609,6 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
}
m_copyback(m, off2, sizeof(uh), &uh);
}
-#endif
return (PF_PASS);
break;
}
@@ -4554,48 +4626,41 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd2.af;
key.proto = IPPROTO_ICMP;
- if (direction == PF_IN) { /* wire, straight */
- PF_ACPY(&key.addr1, pd2.src, key.af);
- PF_ACPY(&key.addr2, pd2.dst, key.af);
- key.port1 = 0;
- key.port2 = iih.icmp_id;
- } else { /* stack, reverse */
- PF_ACPY(&key.addr2, pd2.src, key.af);
- PF_ACPY(&key.addr1, pd2.dst, key.af);
- key.port2 = 0;
- key.port1 = iih.icmp_id;
- }
+ PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+ PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+ key.port[0] = key.port[1] = iih.icmp_id;
+
+ STATE_LOOKUP(kif, &key, direction, *state);
-printf("pf: state search icmp repl: %s", kif->pfik_name);
-printf(" addr1: ");
-pf_print_host(&key.addr1, key.port1, pd->af);
-printf(" addr2: ");
-pf_print_host(&key.addr2, key.port2, pd->af);
-printf("\n");
- STATE_LOOKUP();
-
-#ifdef RYAN_NAT
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_IN) {
+ /* translate source/destination address, if necessary */
+ if ((*state)->key[PF_SK_WIRE] !=
+ (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk =
+ (*state)->key[pd->didx];
+
+ if (PF_ANEQ(pd2.src,
+ &nk->addr[pd2.sidx], pd2.af) ||
+ nk->port[pd2.sidx] != iih.icmp_id)
pf_change_icmp(pd2.src, &iih.icmp_id,
- daddr,
- &(*state)->state_key->addr1,
- (*state)->state_key->lan.port, NULL,
+ daddr, &nk->addr[pd2.sidx],
+ nk->port[pd2.sidx], NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, AF_INET);
- } else {
+
+ if (PF_ANEQ(pd2.dst,
+ &nk->addr[pd2.didx], pd2.af) ||
+ nk->port[pd2.didx] != iih.icmp_id)
pf_change_icmp(pd2.dst, &iih.icmp_id,
- saddr,
- &(*state)->state_key->gwy.addr,
- (*state)->state_key->gwy.port, NULL,
+ NULL, /* XXX Inbound NAT? */
+ &nk->addr[pd2.didx],
+ nk->port[pd2.didx], NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, AF_INET);
- }
+
m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
m_copyback(m, ipoff2, sizeof(h2), &h2);
m_copyback(m, off2, ICMP_MINLEN, &iih);
}
-#endif
return (PF_PASS);
break;
}
@@ -4614,43 +4679,43 @@ printf("\n");
key.af = pd2.af;
key.proto = IPPROTO_ICMPV6;
- if (direction == PF_IN) {
- PF_ACPY(&key.addr1, pd2.dst, key.af);
- PF_ACPY(&key.addr2, pd2.src, key.af);
- key.port1 = 0;
- key.port2 = iih.icmp6_id;
- } else {
- PF_ACPY(&key.addr2, pd2.src, key.af);
- PF_ACPY(&key.addr1, pd2.dst, key.af);
- key.port2 = 0;
- key.port1 = iih.icmp6_id;
- }
+ PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+ PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+ key.port[0] = key.port[1] = iih.icmp6_id;
+
+ STATE_LOOKUP(kif, &key, direction, *state);
- STATE_LOOKUP();
+ /* translate source/destination address, if necessary */
+ if ((*state)->key[PF_SK_WIRE] !=
+ (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk =
+ (*state)->key[pd->didx];
-#ifdef RYAN_NAT
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_IN) {
+ if (PF_ANEQ(pd2.src,
+ &nk->addr[pd2.sidx], pd2.af) ||
+ nk->port[pd2.sidx] != iih.icmp6_id)
pf_change_icmp(pd2.src, &iih.icmp6_id,
- daddr,
- &(*state)->state_key->addr1,
- (*state)->state_key->lan.port, NULL,
+ daddr, &nk->addr[pd2.sidx],
+ nk->port[pd2.sidx], NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, AF_INET6);
- } else {
+
+ if (PF_ANEQ(pd2.dst,
+ &nk->addr[pd2.didx], pd2.af) ||
+ nk->port[pd2.didx] != iih.icmp6_id)
pf_change_icmp(pd2.dst, &iih.icmp6_id,
- saddr, &(*state)->state_key->gwy.addr,
- (*state)->state_key->gwy.port, NULL,
+ NULL, /* XXX Inbound NAT? */
+ &nk->addr[pd2.didx],
+ nk->port[pd2.didx], NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, AF_INET6);
- }
+
m_copyback(m, off, sizeof(struct icmp6_hdr),
pd->hdr.icmp6);
m_copyback(m, ipoff2, sizeof(h2_6), &h2_6);
m_copyback(m, off2, sizeof(struct icmp6_hdr),
&iih);
}
-#endif
return (PF_PASS);
break;
}
@@ -4658,37 +4723,33 @@ printf("\n");
default: {
key.af = pd2.af;
key.proto = pd2.proto;
- if (direction == PF_IN) {
- PF_ACPY(&key.addr1, pd2.src, key.af);
- PF_ACPY(&key.addr2, pd2.dst, key.af);
- key.port1 = 0;
- key.port2 = 0;
- } else {
- PF_ACPY(&key.addr2, pd2.src, key.af);
- PF_ACPY(&key.addr1, pd2.dst, key.af);
- key.port2 = 0;
- key.port1 = 0;
- }
-
- STATE_LOOKUP();
-
-#ifdef RYAN_NAT
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_IN) {
- pf_change_icmp(pd2.src, NULL,
- daddr,
- &(*state)->state_key->addr1,
- 0, NULL,
+ PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+ PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+ key.port[0] = key.port[1] = 0;
+
+ STATE_LOOKUP(kif, &key, direction, *state);
+
+ /* translate source/destination address, if necessary */
+ if ((*state)->key[PF_SK_WIRE] !=
+ (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk =
+ (*state)->key[pd->didx];
+
+ if (PF_ANEQ(pd2.src,
+ &nk->addr[pd2.sidx], pd2.af))
+ pf_change_icmp(pd2.src, NULL, daddr,
+ &nk->addr[pd2.sidx], 0, NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, pd2.af);
- } else {
- pf_change_icmp(pd2.dst, NULL,
- saddr,
- &(*state)->state_key->gwy.addr,
- 0, NULL,
+
+ if (PF_ANEQ(pd2.dst,
+ &nk->addr[pd2.didx], pd2.af))
+ pf_change_icmp(pd2.src, NULL,
+ NULL, /* XXX Inbound NAT? */
+ &nk->addr[pd2.didx], 0, NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, pd2.af);
- }
+
switch (pd2.af) {
#ifdef INET
case AF_INET:
@@ -4708,7 +4769,6 @@ printf("\n");
#endif /* INET6 */
}
}
-#endif
return (PF_PASS);
break;
}
@@ -4726,18 +4786,16 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd->af;
key.proto = pd->proto;
if (direction == PF_IN) {
- PF_ACPY(&key.addr1, pd->src, key.af);
- PF_ACPY(&key.addr2, pd->dst, key.af);
- key.port1 = 0;
- key.port2 = 0;
+ PF_ACPY(&key.addr[0], pd->src, key.af);
+ PF_ACPY(&key.addr[1], pd->dst, key.af);
+ key.port[0] = key.port[1] = 0;
} else {
- PF_ACPY(&key.addr2, pd->src, key.af);
- PF_ACPY(&key.addr1, pd->dst, key.af);
- key.port2 = 0;
- key.port1 = 0;
+ PF_ACPY(&key.addr[1], pd->src, key.af);
+ PF_ACPY(&key.addr[0], pd->dst, key.af);
+ key.port[1] = key.port[0] = 0;
}
- STATE_LOOKUP();
+ STATE_LOOKUP(kif, &key, direction, *state);
if (direction == (*state)->direction) {
src = &(*state)->src;
@@ -4760,45 +4818,38 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
else
(*state)->timeout = PFTM_OTHER_SINGLE;
-#ifdef RYAN_NAT
/* translate source/destination address, if necessary */
- if (STATE_TRANSLATE((*state)->state_key)) {
- if (direction == PF_OUT)
- switch (pd->af) {
+ if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+ struct pf_state_key *nk = (*state)->key[pd->didx];
+
+ switch (pd->af) {
#ifdef INET
- case AF_INET:
+ case AF_INET:
+ if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET))
pf_change_a(&pd->src->v4.s_addr,
pd->ip_sum,
- (*state)->state_key->gwy.addr.v4.s_addr,
+ nk->addr[pd->sidx].v4.s_addr,
0);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- PF_ACPY(pd->src,
- &(*state)->state_key->gwy.addr, pd->af);
- break;
-#endif /* INET6 */
- }
- else
- switch (pd->af) {
-#ifdef INET
- case AF_INET:
+
+
+ if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET))
pf_change_a(&pd->dst->v4.s_addr,
pd->ip_sum,
- (*state)->state_key->addr1.v4.s_addr,
+ nk->addr[pd->didx].v4.s_addr,
0);
+
break;
#endif /* INET */
#ifdef INET6
- case AF_INET6:
- PF_ACPY(pd->dst,
- &(*state)->state_key->addr1, pd->af);
- break;
+ case AF_INET6:
+ if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET))
+ PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af);
+
+ if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET))
+ PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af);
#endif /* INET6 */
- }
+ }
}
-#endif
return (PF_PASS);
}
@@ -5472,9 +5523,13 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
pd.src = (struct pf_addr *)&h->ip_src;
pd.dst = (struct pf_addr *)&h->ip_dst;
- PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
+ pd.sport = pd.dport = NULL;
pd.ip_sum = &h->ip_sum;
+ pd.proto_sum = NULL;
pd.proto = h->ip_p;
+ pd.dir = dir;
+ pd.sidx = (dir == PF_IN) ? 0 : 1;
+ pd.didx = (dir == PF_IN) ? 1 : 0;
pd.af = AF_INET;
pd.tos = h->ip_tos;
pd.tot_len = ntohs(h->ip_len);
@@ -5676,39 +5731,22 @@ done:
}
tr = r;
nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
- if (nr != NULL) {
- struct pf_addr *x;
- /*
- * XXX: we need to make sure that the addresses
- * passed to pfr_update_stats() are the same than
- * the addresses used during matching (pfr_match)
- */
- if (r == &pf_default_rule) {
- tr = nr;
- x = (s == NULL || s->direction == dir) ?
- &pd.baddr : &pd.naddr;
- } else
- x = (s == NULL || s->direction == dir) ?
- &pd.naddr : &pd.baddr;
- if (x == &pd.baddr || s == NULL) {
- /* we need to change the address */
- if (dir == PF_OUT)
- pd.src = x;
- else
- pd.dst = x;
- }
- }
+ if (nr != NULL && r == &pf_default_rule)
+ tr = nr;
if (tr->src.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
- s->direction == dir) ?
- pd.src : pd.dst, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->src.neg);
+ pfr_update_stats(tr->src.addr.p.tbl,
+ (s == NULL) ? pd.src :
+ &s->key[(s->direction == PF_IN)]->
+ addr[(s->direction == PF_OUT)],
+ pd.af, pd.tot_len, dir == PF_OUT,
+ r->action == PF_PASS, tr->src.neg);
if (tr->dst.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
- s->direction == dir) ? pd.dst : pd.src, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->dst.neg);
+ pfr_update_stats(tr->dst.addr.p.tbl,
+ (s == NULL) ? pd.dst :
+ &s->key[(s->direction == PF_IN)]->
+ addr[(s->direction == PF_IN)],
+ pd.af, pd.tot_len, dir == PF_OUT,
+ r->action == PF_PASS, tr->dst.neg);
}
@@ -5793,8 +5831,12 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
pd.src = (struct pf_addr *)&h->ip6_src;
pd.dst = (struct pf_addr *)&h->ip6_dst;
- PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
+ pd.sport = pd.dport = NULL;
pd.ip_sum = NULL;
+ pd.proto_sum = NULL;
+ pd.dir = dir;
+ pd.sidx = (dir == PF_IN) ? 0 : 1;
+ pd.didx = (dir == PF_IN) ? 1 : 0;
pd.af = AF_INET6;
pd.tos = 0;
pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
@@ -6060,38 +6102,20 @@ done:
}
tr = r;
nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
- if (nr != NULL) {
- struct pf_addr *x;
- /*
- * XXX: we need to make sure that the addresses
- * passed to pfr_update_stats() are the same than
- * the addresses used during matching (pfr_match)
- */
- if (r == &pf_default_rule) {
- tr = nr;
- x = (s == NULL || s->direction == dir) ?
- &pd.baddr : &pd.naddr;
- } else {
- x = (s == NULL || s->direction == dir) ?
- &pd.naddr : &pd.baddr;
- }
- if (x == &pd.baddr || s == NULL) {
- if (dir == PF_OUT)
- pd.src = x;
- else
- pd.dst = x;
- }
- }
+ if (nr != NULL && r == &pf_default_rule)
+ tr = nr;
if (tr->src.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
- s->direction == dir) ? pd.src : pd.dst, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->src.neg);
+ pfr_update_stats(tr->src.addr.p.tbl,
+ (s == NULL) ? pd.src :
+ &s->key[(s->direction == PF_IN)]->addr[0],
+ pd.af, pd.tot_len, dir == PF_OUT,
+ r->action == PF_PASS, tr->src.neg);
if (tr->dst.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
- s->direction == dir) ? pd.dst : pd.src, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->dst.neg);
+ pfr_update_stats(tr->dst.addr.p.tbl,
+ (s == NULL) ? pd.dst :
+ &s->key[(s->direction == PF_IN)]->addr[1],
+ pd.af, pd.tot_len, dir == PF_OUT,
+ r->action == PF_PASS, tr->dst.neg);
}