summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
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);