summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorRyan Thomas McBride <mcbride@cvs.openbsd.org>2008-05-29 01:00:54 +0000
committerRyan Thomas McBride <mcbride@cvs.openbsd.org>2008-05-29 01:00:54 +0000
commitc496441ad96ff1d247439f6f966240d5f8e657fd (patch)
tree5667310b4fbf5a6b6cab31c04126b2780c0795de /sys
parentb4ce6f58e6b8cf560109ecf401d63df14e2f9431 (diff)
Second half of PF state table rearrangement.
- Mechanical change: Use arrays for state key pointers in pf_state, and addr/port in pf_state_key, to allow the use of indexes. - Fix NAT, pfsync, pfctl, and tcpdump to handle the new state structures. In struct pfsync_state, both state keys are included even when identical. - Also fix some bugs discovered in the existing code during testing. (in particular, "block return" for TCP packets was not returning an RST) ok henning beck deraadt tested by otto dlg beck laurent Special thanks to users Manuel Pata and Emilio Perea who did enough testing to actually find some bugs.
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_pfsync.c73
-rw-r--r--sys/net/if_pfsync.h14
-rw-r--r--sys/net/pf.c1442
-rw-r--r--sys/net/pf_ioctl.c153
-rw-r--r--sys/net/pfvar.h65
5 files changed, 897 insertions, 850 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c
index 518181e8322..705cb16549f 100644
--- a/sys/net/if_pfsync.c
+++ b/sys/net/if_pfsync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pfsync.c,v 1.92 2008/05/29 00:28:07 henning Exp $ */
+/* $OpenBSD: if_pfsync.c,v 1.93 2008/05/29 01:00:53 mcbride Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff
@@ -237,7 +237,7 @@ int
pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
{
struct pf_state *st = NULL;
- struct pf_state_key *sk = NULL;
+ struct pf_state_key *skw = NULL, *sks = NULL;
struct pf_rule *r = NULL;
struct pfi_kif *kif;
@@ -276,11 +276,24 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
}
bzero(st, sizeof(*st));
- if ((sk = pf_alloc_state_key()) == NULL) {
+ if ((skw = pf_alloc_state_key()) == NULL) {
pool_put(&pf_state_pl, st);
pfi_kif_unref(kif, PFI_KIF_REF_NONE);
return (ENOMEM);
}
+ if ((PF_ANEQ(&sp->key[PF_SK_WIRE].addr[0],
+ &sp->key[PF_SK_STACK].addr[0], sp->af) ||
+ PF_ANEQ(&sp->key[PF_SK_WIRE].addr[1],
+ &sp->key[PF_SK_STACK].addr[1], sp->af) ||
+ sp->key[PF_SK_WIRE].port[0] != sp->key[PF_SK_STACK].port[0] ||
+ sp->key[PF_SK_WIRE].port[1] != sp->key[PF_SK_STACK].port[1]) &&
+ (sks = pf_alloc_state_key()) == NULL) {
+ pool_put(&pf_state_pl, st);
+ pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ pool_put(&pf_state_key_pl, skw);
+ return (ENOMEM);
+ } else
+ sks = skw;
/* allocate memory for scrub info */
if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
@@ -289,11 +302,15 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
if (st->src.scrub)
pool_put(&pf_state_scrub_pl, st->src.scrub);
pool_put(&pf_state_pl, st);
- pool_put(&pf_state_key_pl, sk);
+ if (skw == sks)
+ sks = NULL;
+ if (skw != NULL)
+ pool_put(&pf_state_key_pl, skw);
+ if (sks != NULL)
+ pool_put(&pf_state_key_pl, sks);
return (ENOMEM);
}
- pf_attach_state(sk, st, 0, PF_SK_BOTH); /* XXX RYAN NAT */
st->rule.ptr = r;
/* XXX get pointers to nat_rule and anchor */
@@ -301,21 +318,28 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
r->states_cur++;
r->states_tot++;
-#ifdef XXX_HENNING_RYAN_FIXED_PFSYNC
/* fill in the rest of the state entry */
- pf_state_host_ntoh(&sp->lan, &sk->lan);
- pf_state_host_ntoh(&sp->gwy, &sk->gwy);
- pf_state_host_ntoh(&sp->ext, &sk->ext);
-#endif
+ skw->addr[0] = sp->key[PF_SK_WIRE].addr[0];
+ skw->addr[1] = sp->key[PF_SK_WIRE].addr[1];
+ skw->port[0] = sp->key[PF_SK_WIRE].port[0];
+ skw->port[1] = sp->key[PF_SK_WIRE].port[1];
+ skw->proto = sp->proto;
+ skw->af = sp->af;
+ if (sks != skw) {
+ sks->addr[0] = sp->key[PF_SK_STACK].addr[0];
+ sks->addr[1] = sp->key[PF_SK_STACK].addr[1];
+ sks->port[0] = sp->key[PF_SK_STACK].port[0];
+ sks->port[1] = sp->key[PF_SK_STACK].port[1];
+ sks->proto = sp->proto;
+ sks->af = sp->af;
+ }
+
pf_state_peer_ntoh(&sp->src, &st->src);
pf_state_peer_ntoh(&sp->dst, &st->dst);
bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
st->creation = time_second - ntohl(sp->creation);
st->expire = ntohl(sp->expire) + time_second;
-
- sk->af = sp->af;
- sk->proto = sp->proto;
st->direction = sp->direction;
st->log = sp->log;
st->timeout = sp->timeout;
@@ -325,7 +349,7 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
st->creatorid = sp->creatorid;
st->sync_flags = PFSTATE_FROMSYNC;
- if (pf_state_insert(kif, sk, st)) {
+ if (pf_state_insert(kif, skw, sks, st)) {
pfi_kif_unref(kif, PFI_KIF_REF_NONE);
/* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
r->states_cur--;
@@ -533,7 +557,7 @@ pfsync_input(struct mbuf *m, ...)
pfsyncstats.pfsyncs_badstate++;
continue;
}
- sk = st->key_wire; /* XXX right one? */
+ sk = st->key[PF_SK_WIRE]; /* XXX right one? */
sfail = 0;
if (sk->proto == IPPROTO_TCP) {
/*
@@ -670,7 +694,7 @@ pfsync_input(struct mbuf *m, ...)
pfsyncstats.pfsyncs_badstate++;
continue;
}
- sk = st->key_wire; /* XXX right one? */
+ sk = st->key[PF_SK_WIRE]; /* XXX right one? */
sfail = 0;
if (sk->proto == IPPROTO_TCP) {
/*
@@ -1122,7 +1146,7 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
struct pfsync_state *sp = NULL;
struct pfsync_state_upd *up = NULL;
struct pfsync_state_del *dp = NULL;
- struct pf_state_key *sk = st->key_wire;
+ struct pf_state_key *sk = st->key[PF_SK_WIRE];
struct pf_rule *r;
u_long secs;
int s, ret = 0;
@@ -1208,11 +1232,16 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
sp->creatorid = st->creatorid;
strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
-#ifdef XXX_HENNING_RYAN_FIXED_PFSYNC
- pf_state_host_hton(&sk->lan, &sp->lan);
- pf_state_host_hton(&sk->gwy, &sp->gwy);
- pf_state_host_hton(&sk->ext, &sp->ext);
-#endif
+
+ sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
+ sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
+ sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
+ sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
+ sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
+ sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
+ sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
+ sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
+
bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
sp->creation = htonl(secs - st->creation);
diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h
index e94dad5fa46..0e7266a2535 100644
--- a/sys/net/if_pfsync.h
+++ b/sys/net/if_pfsync.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pfsync.h,v 1.32 2007/12/14 18:33:37 deraadt Exp $ */
+/* $OpenBSD: if_pfsync.h,v 1.33 2008/05/29 01:00:53 mcbride Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -241,16 +241,6 @@ struct pfsyncreq {
} \
} while (0)
-#define pf_state_host_hton(s,d) do { \
- bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
- (d)->port = (s)->port; \
-} while (0)
-
-#define pf_state_host_ntoh(s,d) do { \
- bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
- (d)->port = (s)->port; \
-} while (0)
-
#define pf_state_counter_hton(s,d) do { \
d[0] = htonl((s>>32)&0xffffffff); \
d[1] = htonl(s&0xffffffff); \
@@ -270,7 +260,7 @@ int pfsync_sysctl(int *, u_int, void *, size_t *, void *, size_t);
#define pfsync_insert_state(st) do { \
if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \
- (st->state_key->proto == IPPROTO_PFSYNC)) \
+ (st->key[PF_SK_WIRE]->proto == IPPROTO_PFSYNC)) \
st->sync_flags |= PFSTATE_NOSYNC; \
else if (!st->sync_flags) \
pfsync_pack_state(PFSYNC_ACT_INS, (st), \
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);
}
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 4b1469149a3..e4b6f11529b 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.198 2008/05/29 00:28:08 henning Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.199 2008/05/29 01:00:53 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -112,6 +112,7 @@ int pf_commit_rules(u_int32_t, int, char *);
void pf_state_export(struct pfsync_state *,
struct pf_state *);
void pf_state_import(struct pfsync_state *,
+ struct pf_state_key *,
struct pf_state_key *, struct pf_state *);
struct pf_rule pf_default_rule;
@@ -849,16 +850,17 @@ pf_state_export(struct pfsync_state *sp, struct pf_state *s)
int secs = time_second;
bzero(sp, sizeof(struct pfsync_state));
-/* XXX_RYAN_NAT */
/* copy from state key */
- sp->lan.addr = s->key_wire->addr2;
- sp->lan.port = s->key_wire->port2;
- sp->gwy.addr = s->key_wire->addr2;
- sp->gwy.port = s->key_wire->port2;
- sp->ext.addr = s->key_wire->addr1;
- sp->ext.port = s->key_wire->port1;
- sp->proto = s->key_wire->proto;
- sp->af = s->key_wire->af;
+ sp->key[PF_SK_WIRE].addr[0] = s->key[PF_SK_WIRE]->addr[0];
+ sp->key[PF_SK_WIRE].addr[1] = s->key[PF_SK_WIRE]->addr[1];
+ sp->key[PF_SK_WIRE].port[0] = s->key[PF_SK_WIRE]->port[0];
+ sp->key[PF_SK_WIRE].port[1] = s->key[PF_SK_WIRE]->port[1];
+ sp->key[PF_SK_STACK].addr[0] = s->key[PF_SK_STACK]->addr[0];
+ sp->key[PF_SK_STACK].addr[1] = s->key[PF_SK_STACK]->addr[1];
+ sp->key[PF_SK_STACK].port[0] = s->key[PF_SK_STACK]->port[0];
+ sp->key[PF_SK_STACK].port[1] = s->key[PF_SK_STACK]->port[1];
+ sp->proto = s->key[PF_SK_WIRE]->proto;
+ sp->af = s->key[PF_SK_WIRE]->af;
sp->direction = s->direction;
/* copy from state */
@@ -895,20 +897,24 @@ pf_state_export(struct pfsync_state *sp, struct pf_state *s)
}
void
-pf_state_import(struct pfsync_state *sp, struct pf_state_key *sk,
- struct pf_state *s)
+pf_state_import(struct pfsync_state *sp, struct pf_state_key *skw,
+ struct pf_state_key *sks, struct pf_state *s)
{
- /* copy to state key */
-#ifdef XXX_RYAN_HENNING_PFSYNC_FIXED
- sk->lan.addr = sp->lan.addr;
- sk->lan.port = sp->lan.port;
- sk->gwy.addr = sp->gwy.addr;
- sk->gwy.port = sp->gwy.port;
- sk->ext.addr = sp->ext.addr;
- sk->ext.port = sp->ext.port;
-#endif
- sk->proto = sp->proto;
- sk->af = sp->af;
+ /* copy to state key(s) */
+ skw->addr[0] = sp->key[PF_SK_WIRE].addr[0];
+ skw->addr[1] = sp->key[PF_SK_WIRE].addr[1];
+ skw->port[0] = sp->key[PF_SK_WIRE].port[0];
+ skw->port[1] = sp->key[PF_SK_WIRE].port[1];
+ skw->proto = sp->proto;
+ skw->af = sp->af;
+ if (sks != skw) {
+ sks->addr[0] = sp->key[PF_SK_STACK].addr[0];
+ sks->addr[1] = sp->key[PF_SK_STACK].addr[1];
+ sks->port[0] = sp->key[PF_SK_STACK].port[0];
+ sks->port[1] = sp->key[PF_SK_STACK].port[1];
+ sks->proto = sp->proto;
+ sks->af = sp->af;
+ }
/* copy to state */
memcpy(&s->id, &sp->id, sizeof(sp->id));
s->creatorid = sp->creatorid;
@@ -1609,18 +1615,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
for (s = RB_MIN(pf_state_tree_id, &tree_id); s;
s = nexts) {
nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
- sk = s->key_wire;
+ sk = s->key[PF_SK_WIRE];
if (s->direction == PF_OUT) {
- srcaddr = &sk->addr2;
- dstaddr = &sk->addr1;
- srcport = sk->port2;
- dstport = sk->port1;
+ srcaddr = &sk->addr[1];
+ dstaddr = &sk->addr[0];
+ srcport = sk->port[0];
+ dstport = sk->port[0];
} else {
- srcaddr = &sk->addr1;
- dstaddr = &sk->addr2;
- srcport = sk->port2;
- dstport = sk->port1;
+ srcaddr = &sk->addr[0];
+ dstaddr = &sk->addr[1];
+ srcport = sk->port[0];
+ dstport = sk->port[0];
}
if ((!psk->psk_af || sk->af == psk->psk_af)
&& (!psk->psk_proto || psk->psk_proto ==
@@ -1662,7 +1668,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pfioc_state *ps = (struct pfioc_state *)addr;
struct pfsync_state *sp = &ps->state;
struct pf_state *s;
- struct pf_state_key *sk;
+ struct pf_state_key *skw, *sks;
struct pfi_kif *kif;
if (sp->timeout >= PFTM_MAX &&
@@ -1676,21 +1682,37 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bzero(s, sizeof(struct pf_state));
- if ((sk = pf_alloc_state_key()) == NULL) {
+ if ((skw = pf_alloc_state_key()) == NULL) {
pool_put(&pf_state_pl, s);
error = ENOMEM;
break;
}
- pf_state_import(sp, sk, s);
-/* RYAN NAT */ pf_attach_state(sk, s, 0, PF_SK_BOTH);
+ if ((PF_ANEQ(&sp->key[PF_SK_WIRE].addr[0],
+ &sp->key[PF_SK_STACK].addr[0], sp->af) ||
+ PF_ANEQ(&sp->key[PF_SK_WIRE].addr[1],
+ &sp->key[PF_SK_STACK].addr[1], sp->af) ||
+ sp->key[PF_SK_WIRE].port[0] !=
+ sp->key[PF_SK_STACK].port[0] ||
+ sp->key[PF_SK_WIRE].port[1] !=
+ sp->key[PF_SK_STACK].port[1]) &&
+ (sks = pf_alloc_state_key()) == NULL) {
+ pool_put(&pf_state_pl, s);
+ pool_put(&pf_state_key_pl, skw);
+ error = ENOMEM;
+ break;
+ } else
+ sks = skw;
+ pf_state_import(sp, skw, sks, s);
kif = pfi_kif_get(sp->ifname);
if (kif == NULL) {
pool_put(&pf_state_pl, s);
- pool_put(&pf_state_key_pl, sk);
+ pool_put(&pf_state_key_pl, skw);
+ if (skw != sks)
+ pool_put(&pf_state_key_pl, sks);
error = ENOENT;
break;
}
- if (pf_state_insert(kif, sk, s)) {
+ if (pf_state_insert(kif, skw, sks, s)) {
pfi_kif_unref(kif, PFI_KIF_REF_NONE);
pool_put(&pf_state_pl, s);
error = EEXIST;
@@ -1791,9 +1813,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_state *state;
struct pf_state_key_cmp key;
int m = 0, direction = pnl->direction;
+ int sidx, didx;
- key.af = pnl->af;
- key.proto = pnl->proto;
+ /* NATLOOK src and dst are reversed, so reverse sidx/didx */
+ sidx = (direction == PF_IN) ? 1 : 0;
+ didx = (direction == PF_IN) ? 0 : 1;
if (!pnl->proto ||
PF_AZERO(&pnl->saddr, pnl->af) ||
@@ -1803,44 +1827,23 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
(!pnl->dport || !pnl->sport)))
error = EINVAL;
else {
- /*
- * userland gives us source and dest of connection,
- * reverse the lookup so we ask for what happens with
- * the return traffic, enabling us to find it in the
- * state tree.
- */
- if (direction == PF_IN) {
- PF_ACPY(&key.addr1, &pnl->daddr, pnl->af);
- key.port1 = pnl->dport;
- PF_ACPY(&key.addr2, &pnl->saddr, pnl->af);
- key.port2 = pnl->sport;
- state = pf_find_state_all(&key, PF_IN, &m);
- } else {
- PF_ACPY(&key.addr2, &pnl->daddr, pnl->af);
- key.port2 = pnl->dport;
- PF_ACPY(&key.addr1, &pnl->saddr, pnl->af);
- key.port1 = pnl->sport;
- state = pf_find_state_all(&key, PF_OUT, &m);
- }
+ key.af = pnl->af;
+ key.proto = pnl->proto;
+ PF_ACPY(&key.addr[sidx], &pnl->saddr, pnl->af);
+ key.port[sidx] = pnl->sport;
+ PF_ACPY(&key.addr[didx], &pnl->daddr, pnl->af);
+ key.port[didx] = pnl->dport;
+
+ state = pf_find_state_all(&key, direction, &m);
+
if (m > 1)
error = E2BIG; /* more than one state */
else if (state != NULL) {
- sk = state->key_wire; /* XXX which side? */
- if (direction == PF_IN) {
- PF_ACPY(&pnl->rsaddr, &sk->addr1,
- sk->af);
- pnl->rsport = sk->port1;
- PF_ACPY(&pnl->rdaddr, &pnl->daddr,
- pnl->af);
- pnl->rdport = pnl->dport;
- } else {
- PF_ACPY(&pnl->rdaddr, &sk->addr2,
- sk->af);
- pnl->rdport = sk->port2;
- PF_ACPY(&pnl->rsaddr, &pnl->saddr,
- pnl->af);
- pnl->rsport = pnl->sport;
- }
+ sk = state->key[sidx];
+ PF_ACPY(&pnl->rsaddr, &sk->addr[sidx], sk->af);
+ pnl->rsport = sk->port[sidx];
+ PF_ACPY(&pnl->rdaddr, &sk->addr[didx], sk->af);
+ pnl->rdport = sk->port[didx];
} else
error = ENOENT;
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index a3515a08a05..256307832a5 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.268 2008/05/29 00:28:08 henning Exp $ */
+/* $OpenBSD: pfvar.h,v 1.269 2008/05/29 01:00:53 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -69,7 +69,7 @@ enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL,
PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER,
PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET };
enum { PF_GET_NONE, PF_GET_CLR_CNTR };
-enum { PF_SK_NONE, PF_SK_WIRE, PF_SK_STACK, PF_SK_BOTH };
+enum { PF_SK_WIRE, PF_SK_STACK, PF_SK_BOTH };
/*
* Note about PFTM_*: real indices into pf_rule.timeout[] come before
@@ -699,10 +699,8 @@ TAILQ_HEAD(pf_state_queue, pf_state);
/* keep synced with struct pf_state_key, used in RB_FIND */
struct pf_state_key_cmp {
- struct pf_addr addr1;
- struct pf_addr addr2;
- u_int16_t port1;
- u_int16_t port2;
+ struct pf_addr addr[2];
+ u_int16_t port[2];
sa_family_t af;
u_int8_t proto;
u_int8_t pad[2];
@@ -716,10 +714,8 @@ struct pf_state_item {
TAILQ_HEAD(pf_statelisthead, pf_state_item);
struct pf_state_key {
- struct pf_addr addr1;
- struct pf_addr addr2;
- u_int16_t port1;
- u_int16_t port2;
+ struct pf_addr addr[2];
+ u_int16_t port[2];
sa_family_t af;
u_int8_t proto;
u_int8_t pad[2];
@@ -750,8 +746,7 @@ struct pf_state {
union pf_rule_ptr anchor;
union pf_rule_ptr nat_rule;
struct pf_addr rt_addr;
- struct pf_state_key *key_wire; /* addresses wire-side */
- struct pf_state_key *key_stack; /* addresses stack-side */
+ struct pf_state_key *key[2]; /* addresses stack and wire */
struct pfi_kif *kif;
struct pfi_kif *rt_kif;
struct pf_src_node *src_node;
@@ -783,12 +778,6 @@ struct pfsync_state_scrub {
u_int32_t pfss_ts_mod; /* timestamp modulation */
} __packed;
-struct pfsync_state_host {
- struct pf_addr addr;
- u_int16_t port;
- u_int16_t pad[3];
-} __packed;
-
struct pfsync_state_peer {
struct pfsync_state_scrub scrub; /* state is scrubbed */
u_int32_t seqlo; /* Max sequence number sent */
@@ -801,12 +790,15 @@ struct pfsync_state_peer {
u_int8_t pad[6];
} __packed;
+struct pfsync_state_key {
+ struct pf_addr addr[2];
+ u_int16_t port[2];
+};
+
struct pfsync_state {
u_int32_t id[2];
char ifname[IFNAMSIZ];
- struct pfsync_state_host lan;
- struct pfsync_state_host gwy;
- struct pfsync_state_host ext;
+ struct pfsync_state_key key[2];
struct pfsync_state_peer src;
struct pfsync_state_peer dst;
struct pf_addr rt_addr;
@@ -1076,15 +1068,19 @@ struct pf_pdesc {
#endif /* INET6 */
void *any;
} hdr;
- struct pf_addr baddr; /* address before translation */
- struct pf_addr naddr; /* address after translation */
+
struct pf_rule *nat_rule; /* nat/rdr rule applied to packet */
- struct pf_addr *src;
- struct pf_addr *dst;
- struct ether_header
+ struct ether_header
*eh;
- u_int16_t *ip_sum;
+ struct pf_addr *src; /* src address */
+ struct pf_addr *dst; /* dst address */
+ u_int16_t *sport;
+ u_int16_t *dport;
+
u_int32_t p_len; /* total length of payload */
+
+ u_int16_t *ip_sum;
+ u_int16_t *proto_sum;
u_int16_t flags; /* Let SCRUB trigger behavior in
* state code. Easier than tags */
#define PFDESC_TCP_NORM 0x0001 /* TCP shall be statefully scrubbed */
@@ -1092,6 +1088,9 @@ struct pf_pdesc {
sa_family_t af;
u_int8_t proto;
u_int8_t tos;
+ u_int8_t dir; /* direction */
+ u_int8_t sidx; /* key index for source */
+ u_int8_t didx; /* key index for destination */
};
/* flags for RDR options */
@@ -1295,10 +1294,10 @@ struct pf_tagname {
struct pf_divert {
union {
- struct in_addr ipv4;
- struct in6_addr ipv6;
- } addr;
- u_int16_t port;
+ struct in_addr ipv4;
+ struct in6_addr ipv6;
+ } addr;
+ u_int16_t port;
};
#define PFFRAG_FRENT_HIWAT 5000 /* Number of fragment entries */
@@ -1592,7 +1591,9 @@ extern void pf_purge_expired_states(u_int32_t);
extern void pf_unlink_state(struct pf_state *);
extern void pf_free_state(struct pf_state *);
extern int pf_state_insert(struct pfi_kif *,
- struct pf_state_key *, struct pf_state *);
+ struct pf_state_key *,
+ struct pf_state_key *,
+ struct pf_state *);
extern int pf_insert_src_node(struct pf_src_node **,
struct pf_rule *, struct pf_addr *,
sa_family_t);