summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_pfsync.c260
-rw-r--r--sys/net/if_pfsync.h64
-rw-r--r--sys/net/pf.c175
-rw-r--r--sys/net/pf_ioctl.c148
-rw-r--r--sys/net/pfvar.h57
5 files changed, 274 insertions, 430 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c
index 33e1063db14..68d3ac40877 100644
--- a/sys/net/if_pfsync.c
+++ b/sys/net/if_pfsync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pfsync.c,v 1.97 2008/06/19 04:53:21 mcbride Exp $ */
+/* $OpenBSD: if_pfsync.c,v 1.98 2008/06/29 08:42:15 mcbride Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff
@@ -89,7 +89,6 @@ int pfsync_clone_destroy(struct ifnet *);
void pfsync_setmtu(struct pfsync_softc *, int);
int pfsync_alloc_scrub_memory(struct pfsync_state_peer *,
struct pf_state_peer *);
-int pfsync_insert_net_state(struct pfsync_state *, u_int8_t);
void pfsync_update_net_tdb(struct pfsync_tdb *);
int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
@@ -232,92 +231,135 @@ pfsync_alloc_scrub_memory(struct pfsync_state_peer *s,
return (0);
}
+void
+pfsync_state_export(struct pfsync_state *sp, struct pf_state *st)
+{
+ bzero(sp, sizeof(struct pfsync_state));
+
+ /* copy from state key */
+ 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];
+ sp->proto = st->key[PF_SK_WIRE]->proto;
+ sp->af = st->key[PF_SK_WIRE]->af;
+
+ /* copy from state */
+ strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
+ bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
+ sp->creation = htonl(time_second - st->creation);
+ sp->expire = pf_state_expires(st);
+ if (sp->expire <= time_second)
+ sp->expire = htonl(0);
+ else
+ sp->expire = htonl(sp->expire - time_second);
+
+ sp->direction = st->direction;
+ sp->log = st->log;
+ sp->timeout = st->timeout;
+ sp->state_flags = st->state_flags;
+ if (st->src_node)
+ sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
+ if (st->nat_src_node)
+ sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
+
+ bcopy(&st->id, &sp->id, sizeof(sp->id));
+ sp->creatorid = st->creatorid;
+ pf_state_peer_hton(&st->src, &sp->src);
+ pf_state_peer_hton(&st->dst, &sp->dst);
+
+ if (st->rule.ptr == NULL)
+ sp->rule = htonl(-1);
+ else
+ sp->rule = htonl(st->rule.ptr->nr);
+ if (st->anchor.ptr == NULL)
+ sp->anchor = htonl(-1);
+ else
+ sp->anchor = htonl(st->anchor.ptr->nr);
+ if (st->nat_rule.ptr == NULL)
+ sp->nat_rule = htonl(-1);
+ else
+ sp->nat_rule = htonl(st->nat_rule.ptr->nr);
+
+ pf_state_counter_hton(st->packets[0], sp->packets[0]);
+ pf_state_counter_hton(st->packets[1], sp->packets[1]);
+ pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
+ pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
+
+}
+
int
-pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
+pfsync_state_import(struct pfsync_state *sp, u_int8_t flags)
{
struct pf_state *st = NULL;
struct pf_state_key *skw = NULL, *sks = NULL;
struct pf_rule *r = NULL;
struct pfi_kif *kif;
+ int pool_flags;
+ int error;
if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
- printf("pfsync_insert_net_state: invalid creator id:"
+ printf("pfsync_state_import: invalid creator id:"
" %08x\n", ntohl(sp->creatorid));
return (EINVAL);
}
- kif = pfi_kif_get(sp->ifname);
- if (kif == NULL) {
+ if ((kif = pfi_kif_get(sp->ifname)) == NULL) {
if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_insert_net_state: "
+ printf("pfsync_state_import: "
"unknown interface: %s\n", sp->ifname);
- /* skip this state */
- return (0);
+ if (flags & PFSYNC_SI_IOCTL)
+ return (EINVAL);
+ return (0); /* skip this state */
}
/*
- * If the ruleset checksums match, it's safe to associate the state
- * with the rule of that number.
+ * If the ruleset checksums match or the state is coming from the ioctl,
+ * it's safe to associate the state with the rule of that number.
*/
- if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && chksum_flag &&
- ntohl(sp->rule) <
+ if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) &&
+ (flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->rule) <
pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount)
r = pf_main_ruleset.rules[
PF_RULESET_FILTER].active.ptr_array[ntohl(sp->rule)];
else
r = &pf_default_rule;
- if (!r->max_states || r->states_cur < r->max_states)
- st = pool_get(&pf_state_pl, PR_NOWAIT | PR_ZERO);
- if (st == NULL) {
- pfi_kif_unref(kif, PFI_KIF_REF_NONE);
- return (ENOMEM);
- }
+ if ((r->max_states && r->states_cur >= r->max_states))
+ goto cleanup;
+
+ if (flags & PFSYNC_SI_IOCTL)
+ pool_flags = PR_WAITOK | PR_LIMITFAIL | PR_ZERO;
+ else
+ pool_flags = PR_LIMITFAIL | PR_ZERO;
+
+ if ((st = pool_get(&pf_state_pl, pool_flags)) == NULL)
+ goto cleanup;
+
+ if ((skw = pf_alloc_state_key(pool_flags)) == NULL)
+ goto cleanup;
- 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]) {
- if ((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);
- }
+ if ((sks = pf_alloc_state_key(pool_flags)) == NULL)
+ goto cleanup;
} else
sks = skw;
/* allocate memory for scrub info */
if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
- pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) {
- pfi_kif_unref(kif, PFI_KIF_REF_NONE);
- if (st->src.scrub)
- pool_put(&pf_state_scrub_pl, st->src.scrub);
- pool_put(&pf_state_pl, st);
- 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);
- }
-
- st->rule.ptr = r;
- /* XXX get pointers to nat_rule and anchor */
-
- /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
- r->states_cur++;
- r->states_tot++;
+ pfsync_alloc_scrub_memory(&sp->dst, &st->dst))
+ goto cleanup;
- /* fill in the rest of the state entry */
+ /* 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];
@@ -333,34 +375,66 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
sks->af = sp->af;
}
- pf_state_peer_ntoh(&sp->src, &st->src);
- pf_state_peer_ntoh(&sp->dst, &st->dst);
-
+ /* copy to state */
bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
st->creation = time_second - ntohl(sp->creation);
+ st->expire = time_second;
+ if (sp->expire) {
+ /* XXX No adaptive scaling. */
+ st->expire -= r->timeout[sp->timeout] - ntohl(sp->expire);
+ }
+
st->expire = ntohl(sp->expire) + time_second;
st->direction = sp->direction;
st->log = sp->log;
st->timeout = sp->timeout;
st->state_flags = sp->state_flags;
+ if (!(flags & PFSYNC_SI_IOCTL))
+ st->sync_flags = PFSTATE_FROMSYNC;
bcopy(sp->id, &st->id, sizeof(st->id));
st->creatorid = sp->creatorid;
- st->sync_flags = PFSTATE_FROMSYNC;
+ pf_state_peer_ntoh(&sp->src, &st->src);
+ pf_state_peer_ntoh(&sp->dst, &st->dst);
- if (pf_state_insert(kif, skw, sks, st)) {
- pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ st->rule.ptr = r;
+ st->nat_rule.ptr = NULL;
+ st->anchor.ptr = NULL;
+ st->rt_kif = NULL;
+
+ st->pfsync_time = 0;
+
+
+ /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
+ r->states_cur++;
+ r->states_tot++;
+
+ if ((error = pf_state_insert(kif, skw, sks, st)) != 0) {
/* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
r->states_cur--;
+ goto cleanup_state;
+ }
+
+ return (0);
+
+ cleanup:
+ error = ENOMEM;
+ 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);
+
+ cleanup_state: /* pf_state_insert frees the state keys */
+ if (st) {
if (st->dst.scrub)
pool_put(&pf_state_scrub_pl, st->dst.scrub);
if (st->src.scrub)
pool_put(&pf_state_scrub_pl, st->src.scrub);
pool_put(&pf_state_pl, st);
- return (EINVAL);
}
-
- return (0);
+ return (error);
}
void
@@ -385,7 +459,7 @@ pfsync_input(struct mbuf *m, ...)
struct in_addr src;
struct mbuf *mp;
int iplen, action, error, i, s, count, offp, sfail, stale = 0;
- u_int8_t chksum_flag = 0;
+ u_int8_t flags = 0;
pfsyncstats.pfsyncs_ipackets++;
@@ -440,7 +514,7 @@ pfsync_input(struct mbuf *m, ...)
src = ip->ip_src;
if (!bcmp(&ph->pf_chksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
- chksum_flag++;
+ flags |= PFSYNC_SI_CKSUM;
switch (action) {
case PFSYNC_ACT_CLR: {
@@ -512,8 +586,7 @@ pfsync_input(struct mbuf *m, ...)
continue;
}
- if ((error = pfsync_insert_net_state(sp,
- chksum_flag))) {
+ if ((error = pfsync_state_import(sp, flags))) {
if (error == ENOMEM) {
splx(s);
goto done;
@@ -552,7 +625,7 @@ pfsync_input(struct mbuf *m, ...)
st = pf_find_state_byid(&id_key);
if (st == NULL) {
/* insert the update */
- if (pfsync_insert_net_state(sp, chksum_flag))
+ if (pfsync_state_import(sp, flags))
pfsyncstats.pfsyncs_badstate++;
continue;
}
@@ -1145,9 +1218,6 @@ 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[PF_SK_WIRE];
- struct pf_rule *r;
- u_long secs;
int s, ret = 0;
u_int8_t i = 255, newaction = 0;
@@ -1214,8 +1284,6 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
}
}
- secs = time_second;
-
st->pfsync_time = time_uptime;
if (sp == NULL) {
@@ -1227,53 +1295,19 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
h->count++;
bzero(sp, sizeof(*sp));
- bcopy(&st->id, sp->id, sizeof(sp->id));
- sp->creatorid = st->creatorid;
-
- strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
-
- 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);
- pf_state_counter_hton(st->packets[0], sp->packets[0]);
- pf_state_counter_hton(st->packets[1], sp->packets[1]);
- pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
- pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
- if ((r = st->rule.ptr) == NULL)
- sp->rule = htonl(-1);
- else
- sp->rule = htonl(r->nr);
- if ((r = st->anchor.ptr) == NULL)
- sp->anchor = htonl(-1);
- else
- sp->anchor = htonl(r->nr);
- sp->af = sk->af;
- sp->proto = sk->proto;
- sp->direction = st->direction;
- sp->log = st->log;
- sp->state_flags = st->state_flags;
- sp->timeout = st->timeout;
+ pfsync_state_export(sp, st);
if (flags & PFSYNC_FLAG_STALE)
sp->sync_flags |= PFSTATE_STALE;
- }
-
- pf_state_peer_hton(&st->src, &sp->src);
- pf_state_peer_hton(&st->dst, &sp->dst);
+ } else {
+ pf_state_peer_hton(&st->src, &sp->src);
+ pf_state_peer_hton(&st->dst, &sp->dst);
- if (st->expire <= secs)
- sp->expire = htonl(0);
- else
- sp->expire = htonl(st->expire - secs);
+ if (st->expire <= time_second)
+ sp->expire = htonl(0);
+ else
+ sp->expire = htonl(st->expire - time_second);
+ }
/* do we need to build "compressed" actions for network transfer? */
if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h
index 4d28e845dc4..1fa562c9590 100644
--- a/sys/net/if_pfsync.h
+++ b/sys/net/if_pfsync.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pfsync.h,v 1.34 2008/06/17 05:03:29 mcbride Exp $ */
+/* $OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -205,58 +205,18 @@ struct pfsyncreq {
int pfsyncr_authlevel;
};
-
-/* for copies to/from network */
-#define pf_state_peer_hton(s,d) do { \
- (d)->seqlo = htonl((s)->seqlo); \
- (d)->seqhi = htonl((s)->seqhi); \
- (d)->seqdiff = htonl((s)->seqdiff); \
- (d)->max_win = htons((s)->max_win); \
- (d)->mss = htons((s)->mss); \
- (d)->state = (s)->state; \
- (d)->wscale = (s)->wscale; \
- if ((s)->scrub) { \
- (d)->scrub.pfss_flags = \
- htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \
- (d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \
- (d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\
- (d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \
- } \
-} while (0)
-
-#define pf_state_peer_ntoh(s,d) do { \
- (d)->seqlo = ntohl((s)->seqlo); \
- (d)->seqhi = ntohl((s)->seqhi); \
- (d)->seqdiff = ntohl((s)->seqdiff); \
- (d)->max_win = ntohs((s)->max_win); \
- (d)->mss = ntohs((s)->mss); \
- (d)->state = (s)->state; \
- (d)->wscale = (s)->wscale; \
- if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \
- (d)->scrub != NULL) { \
- (d)->scrub->pfss_flags = \
- ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \
- (d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \
- (d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\
- } \
-} while (0)
-
-#define pf_state_counter_hton(s,d) do { \
- d[0] = htonl((s>>32)&0xffffffff); \
- d[1] = htonl(s&0xffffffff); \
-} while (0)
-
-#define pf_state_counter_ntoh(s,d) do { \
- d = ntohl(s[0]); \
- d = d<<32; \
- d += ntohl(s[1]); \
-} while (0)
-
#ifdef _KERNEL
-void pfsync_input(struct mbuf *, ...);
-int pfsync_clear_states(u_int32_t, char *);
-int pfsync_pack_state(u_int8_t, struct pf_state *, int);
-int pfsync_sysctl(int *, u_int, void *, size_t *, void *, size_t);
+void pfsync_input(struct mbuf *, ...);
+int pfsync_clear_states(u_int32_t, char *);
+int pfsync_pack_state(u_int8_t, struct pf_state *, int);
+int pfsync_sysctl(int *, u_int, void *, size_t *,
+ void *, size_t);
+void pfsync_state_export(struct pfsync_state *,
+ struct pf_state *);
+
+#define PFSYNC_SI_IOCTL 0x01
+#define PFSYNC_SI_CKSUM 0x02
+int pfsync_state_import(struct pfsync_state *, u_int8_t);
#define pfsync_insert_state(st) do { \
if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 5fa4fac095d..4adff5d5b33 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.600 2008/06/26 03:56:20 mcbride Exp $ */
+/* $OpenBSD: pf.c,v 1.601 2008/06/29 08:42:15 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -164,7 +164,7 @@ struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
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);
+void pf_detach_state(struct pf_state *);
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 *,
@@ -172,8 +172,7 @@ int pf_state_key_setup(struct pf_pdesc *, struct pf_rule *,
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);
+void pf_state_key_detach(struct pf_state *, int);
u_int32_t pf_tcp_iss(struct pf_pdesc *);
int pf_test_rule(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
@@ -248,8 +247,6 @@ int pf_addr_wrap_neq(struct pf_addr_wrap *,
struct pf_state *pf_find_state(struct pfi_kif *,
struct pf_state_key_cmp *, u_int, struct mbuf *);
int pf_src_connlimit(struct pf_state **);
-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;
@@ -578,17 +575,6 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
return (0);
}
-void
-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: %s key insert failed: ", side, s->kif->pfik_name);
- pf_print_state_parts(s, skw, sks);
- printf("\n");
- }
-}
-
/* state table stuff */
static __inline int
@@ -674,98 +660,100 @@ pf_state_compare_id(struct pf_state *a, struct pf_state *b)
return (0);
}
-void
-pf_attach_state(struct pf_state_key *sk, struct pf_state *s, int tail,
- int where)
+int
+pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int idx)
{
struct pf_state_item *si;
+ struct pf_state_key *cur;
+
+ KASSERT(s->key[idx] == NULL); /* XXX handle this? */
- if (where == PF_SK_WIRE || where == PF_SK_BOTH)
- s->key[PF_SK_WIRE] = sk;
- if (where == PF_SK_STACK || where == PF_SK_BOTH)
- s->key[PF_SK_STACK] = sk;
+ if ((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 == s->kif &&
+ si->s->direction == s->direction) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf(
+ "pf: %s key attach failed on %s: ",
+ (idx == PF_SK_WIRE) ?
+ "wire" : "stack",
+ s->kif->pfik_name);
+ pf_print_state_parts(s,
+ (idx == PF_SK_WIRE) ? sk : NULL,
+ (idx == PF_SK_STACK) ? sk : NULL);
+ printf("\n");
+ }
+ pool_put(&pf_state_key_pl, sk);
+ return (-1); /* collision! */
+ }
+ pool_put(&pf_state_key_pl, sk);
+ s->key[idx] = cur;
+ }
+ s->key[idx] = sk;
- si = pool_get(&pf_state_item_pl, PR_NOWAIT);
+ if ((si = pool_get(&pf_state_item_pl, PR_NOWAIT)) == NULL) {
+ pf_state_key_detach(s, idx);
+ return (-1);
+ }
si->s = s;
/* list is sorted, if-bound states before floating */
- if (tail)
+ if (s->kif == pfi_all)
TAILQ_INSERT_TAIL(&sk->states, si, entry);
else
TAILQ_INSERT_HEAD(&sk->states, si, entry);
+ return (0);
}
void
-pf_detach_state(struct pf_state *s, int flags)
+pf_detach_state(struct pf_state *s)
{
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_STACK] != NULL)
+ pf_state_key_detach(s, PF_SK_STACK);
- if (s->key[PF_SK_WIRE] != NULL) {
- pf_state_key_detach(s->key[PF_SK_WIRE], s, flags);
- s->key[PF_SK_WIRE] = NULL;
- }
+ if (s->key[PF_SK_WIRE] != NULL)
+ pf_state_key_detach(s, PF_SK_WIRE);
}
void
-pf_state_key_detach(struct pf_state_key *sk, struct pf_state *s, int flags)
+pf_state_key_detach(struct pf_state *s, int idx)
{
struct pf_state_item *si;
- for (si = TAILQ_FIRST(&sk->states); si->s != s;
- si = TAILQ_NEXT(si, entry));
+ si = TAILQ_FIRST(&s->key[idx]->states);
+ while (si && si->s != s)
+ si = TAILQ_NEXT(si, entry);
- TAILQ_REMOVE(&sk->states, si, entry);
- pool_put(&pf_state_item_pl, si);
+ if (si) {
+ TAILQ_REMOVE(&s->key[idx]->states, si, entry);
+ pool_put(&pf_state_item_pl, si);
+ }
- if (TAILQ_EMPTY(&sk->states)) {
- if (!(flags & PF_DT_SKIP_STATETREE))
- RB_REMOVE(pf_state_tree, &pf_statetbl, sk);
- if (sk->reverse)
- sk->reverse->reverse = NULL;
- pool_put(&pf_state_key_pl, sk);
+ if (TAILQ_EMPTY(&s->key[idx]->states)) {
+ RB_REMOVE(pf_state_tree, &pf_statetbl, s->key[idx]);
+ if (s->key[idx]->reverse)
+ s->key[idx]->reverse->reverse = NULL;
+ pool_put(&pf_state_key_pl, s->key[idx]);
}
+ s->key[idx] = NULL;
}
struct pf_state_key *
-pf_alloc_state_key(void)
+pf_alloc_state_key(int pool_flags)
{
struct pf_state_key *sk;
- if ((sk = pool_get(&pf_state_key_pl, PR_NOWAIT | PR_ZERO)) == NULL)
+ if ((sk = pool_get(&pf_state_key_pl, pool_flags)) == NULL)
return (NULL);
TAILQ_INIT(&sk->states);
return (sk);
}
-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;
-
- 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 == s->kif &&
- si->s->direction == s->direction) {
- /* collision! */
- pf_detach_state(s, PF_DT_SKIP_STATETREE);
- return (NULL);
- }
- pf_detach_state(s, PF_DT_SKIP_STATETREE);
- 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,
@@ -775,7 +763,7 @@ pf_state_key_setup(struct pf_pdesc *pd, struct pf_rule *nr,
{
KASSERT((*skp == NULL && *nkp == NULL));
- if ((*skp = pf_alloc_state_key()) == NULL)
+ if ((*skp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
return (ENOMEM);
PF_ACPY(&(*skp)->addr[pd->sidx], saddr, pd->af);
@@ -786,8 +774,8 @@ pf_state_key_setup(struct pf_pdesc *pd, struct pf_rule *nr,
(*skp)->af = pd->af;
if (nr != NULL) {
- if ((*nkp = pf_alloc_state_key()) == NULL)
- return (ENOMEM); /* cleanup handled in pf_test_rule() */
+ if ((*nkp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
+ return (ENOMEM); /* caller must handle cleanup */
/* XXX maybe just bcopy and TAILQ_INIT(&(*nkp)->states) */
PF_ACPY(&(*nkp)->addr[0], &(*skp)->addr[0], pd->af);
@@ -814,27 +802,18 @@ 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);
+ if (pf_state_key_attach(skw, s, PF_SK_WIRE))
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);
+ if (skw == sks)
+ s->key[PF_SK_STACK] = s->key[PF_SK_WIRE];
+ else {
+ if (pf_state_key_attach(sks, s, PF_SK_STACK)) {
+ pf_state_key_detach(s, PF_SK_WIRE);
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) {
@@ -850,7 +829,7 @@ pf_state_insert(struct pfi_kif *kif, struct pf_state_key *skw,
printf(" (from sync)");
printf("\n");
}
- pf_detach_state(s, 0);
+ pf_detach_state(s);
return (-1);
}
TAILQ_INSERT_TAIL(&state_list, s, entry_list);
@@ -1081,7 +1060,7 @@ pf_unlink_state(struct pf_state *cur)
#endif
cur->timeout = PFTM_UNLINKED;
pf_src_tree_remove_state(cur);
- pf_detach_state(cur, 0);
+ pf_detach_state(cur);
}
/* callers should be at splsoftnet and hold the
@@ -3360,11 +3339,11 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
}
if (r->action == PF_DROP)
- return (PF_DROP);
+ goto cleanup;
if (pf_tag_packet(m, tag, rtableid)) {
REASON_SET(&reason, PFRES_MEMORY);
- return (PF_DROP);
+ goto cleanup;
}
if (!state_icmp && (r->keep_state || nr != NULL ||
@@ -3373,9 +3352,6 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
action = pf_create_state(r, nr, a, pd, nsn, skw, sks, nk, sk, m,
off, sport, dport, &rewrite, kif, sm, tag, bproto_sum,
bip_sum, hdrlen);
- if (action == PF_DROP)
- goto cleanup;
- if (action != PF_PASS)
return (action);
}
@@ -3585,6 +3561,11 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
return (PF_PASS);
csfailed:
+ if (sk != NULL)
+ pool_put(&pf_state_key_pl, sk);
+ if (nk != NULL)
+ pool_put(&pf_state_key_pl, nk);
+
if (sn != NULL && sn->states == 0 && sn->expire == 0) {
RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
@@ -4957,6 +4938,10 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
struct pf_state_key *nk = (*state)->key[pd->didx];
+ KASSERT(nk);
+ KASSERT(pd);
+ KASSERT(pd->src);
+ KASSERT(pd->dst);
switch (pd->af) {
#ifdef INET
case AF_INET:
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 733ce7ffde7..4c1e18c89d6 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.208 2008/06/22 13:01:33 mcbride Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.209 2008/06/29 08:42:15 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -110,11 +110,6 @@ int pf_setup_pfsync_matching(struct pf_ruleset *);
void pf_hash_rule(MD5_CTX *, struct pf_rule *);
void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
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 *);
int pf_addr_setup(struct pf_ruleset *,
struct pf_addr_wrap *, sa_family_t);
void pf_addr_copyout(struct pf_addr_wrap *);
@@ -848,97 +843,6 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
return (0);
}
-void
-pf_state_export(struct pfsync_state *sp, struct pf_state *s)
-{
- int secs = time_second;
- bzero(sp, sizeof(struct pfsync_state));
-
- /* copy from state key */
- 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 */
- memcpy(&sp->id, &s->id, sizeof(sp->id));
- sp->creatorid = s->creatorid;
- strlcpy(sp->ifname, s->kif->pfik_name, sizeof(sp->ifname));
- pf_state_peer_to_pfsync(&s->src, &sp->src);
- pf_state_peer_to_pfsync(&s->dst, &sp->dst);
-
- sp->rule = s->rule.ptr->nr;
- sp->nat_rule = (s->nat_rule.ptr == NULL) ? -1 : s->nat_rule.ptr->nr;
- sp->anchor = (s->anchor.ptr == NULL) ? -1 : s->anchor.ptr->nr;
-
- pf_state_counter_to_pfsync(s->bytes[0], sp->bytes[0]);
- pf_state_counter_to_pfsync(s->bytes[1], sp->bytes[1]);
- pf_state_counter_to_pfsync(s->packets[0], sp->packets[0]);
- pf_state_counter_to_pfsync(s->packets[1], sp->packets[1]);
- sp->creation = secs - s->creation;
- sp->expire = pf_state_expires(s);
- sp->log = s->log;
- sp->state_flags = s->state_flags;
- sp->timeout = s->timeout;
-
- if (s->src_node)
- sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
- if (s->nat_src_node)
- sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
-
- if (sp->expire > secs)
- sp->expire -= secs;
- else
- sp->expire = 0;
-
-}
-
-void
-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(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;
- pf_state_peer_from_pfsync(&sp->src, &s->src);
- pf_state_peer_from_pfsync(&sp->dst, &s->dst);
-
- s->direction = sp->direction;
- s->rule.ptr = &pf_default_rule;
- s->nat_rule.ptr = NULL;
- s->anchor.ptr = NULL;
- s->rt_kif = NULL;
- s->creation = time_second;
- s->expire = time_second;
- if (sp->expire > 0)
- s->expire -= pf_default_rule.timeout[sp->timeout] - sp->expire;
- s->pfsync_time = 0;
- s->packets[0] = s->packets[1] = 0;
- s->bytes[0] = s->bytes[1] = 0;
-}
-
int
pf_setup_pfsync_matching(struct pf_ruleset *rs)
{
@@ -1678,57 +1582,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCADDSTATE: {
struct pfioc_state *ps = (struct pfioc_state *)addr;
struct pfsync_state *sp = &ps->state;
- struct pf_state *s;
- struct pf_state_key *skw, *sks;
- struct pfi_kif *kif;
if (sp->timeout >= PFTM_MAX &&
sp->timeout != PFTM_UNTIL_PACKET) {
error = EINVAL;
break;
}
- s = pool_get(&pf_state_pl, PR_WAITOK | PR_LIMITFAIL | PR_ZERO);
- if (s == NULL) {
- error = ENOMEM;
- break;
- }
- if ((skw = pf_alloc_state_key()) == NULL) {
- pool_put(&pf_state_pl, s);
- error = ENOMEM;
- break;
- }
- 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, skw);
- if (skw != sks)
- pool_put(&pf_state_key_pl, sks);
- error = ENOENT;
- break;
- }
- if (pf_state_insert(kif, skw, sks, s)) {
- pfi_kif_unref(kif, PFI_KIF_REF_NONE);
- pool_put(&pf_state_pl, s);
- error = EEXIST;
- break;
- }
- pf_default_rule.states_cur++;
+ error = pfsync_state_import(sp, PFSYNC_SI_IOCTL);
break;
}
@@ -1746,7 +1606,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
- pf_state_export(&ps->state, s);
+ pfsync_state_export(&ps->state, s);
break;
}
@@ -1771,7 +1631,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (state->timeout != PFTM_UNLINKED) {
if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
break;
- pf_state_export(pstore, state);
+ pfsync_state_export(pstore, state);
error = copyout(pstore, p, sizeof(*p));
if (error) {
free(pstore, M_TEMP);
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index a2259d43119..627ee31e28f 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.274 2008/06/11 02:46:35 henning Exp $ */
+/* $OpenBSD: pfvar.h,v 1.275 2008/06/29 08:42:15 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -756,7 +756,7 @@ struct pf_state {
u_int64_t packets[2];
u_int64_t bytes[2];
u_int32_t creation;
- u_int32_t expire;
+ u_int32_t expire;
u_int32_t pfsync_time;
u_int16_t tag;
u_int8_t log;
@@ -829,50 +829,55 @@ struct pfsync_state {
#define PFSYNC_FLAG_SRCNODE 0x04
#define PFSYNC_FLAG_NATSRCNODE 0x08
-/* for copies to/from userland via pf_ioctl() */
-#define pf_state_peer_to_pfsync(s,d) do { \
- (d)->seqlo = (s)->seqlo; \
- (d)->seqhi = (s)->seqhi; \
- (d)->seqdiff = (s)->seqdiff; \
- (d)->max_win = (s)->max_win; \
- (d)->mss = (s)->mss; \
+/* for copies to/from network byte order */
+/* ioctl interface also uses network byte order */
+#define pf_state_peer_hton(s,d) do { \
+ (d)->seqlo = htonl((s)->seqlo); \
+ (d)->seqhi = htonl((s)->seqhi); \
+ (d)->seqdiff = htonl((s)->seqdiff); \
+ (d)->max_win = htons((s)->max_win); \
+ (d)->mss = htons((s)->mss); \
(d)->state = (s)->state; \
(d)->wscale = (s)->wscale; \
if ((s)->scrub) { \
- (d)->scrub.pfss_flags = \
- (s)->scrub->pfss_flags & PFSS_TIMESTAMP; \
+ (d)->scrub.pfss_flags = \
+ htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \
(d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \
- (d)->scrub.pfss_ts_mod = (s)->scrub->pfss_ts_mod; \
+ (d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\
(d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \
} \
} while (0)
-#define pf_state_peer_from_pfsync(s,d) do { \
- (d)->seqlo = (s)->seqlo; \
- (d)->seqhi = (s)->seqhi; \
- (d)->seqdiff = (s)->seqdiff; \
- (d)->max_win = (s)->max_win; \
+#define pf_state_peer_ntoh(s,d) do { \
+ (d)->seqlo = ntohl((s)->seqlo); \
+ (d)->seqhi = ntohl((s)->seqhi); \
+ (d)->seqdiff = ntohl((s)->seqdiff); \
+ (d)->max_win = ntohs((s)->max_win); \
(d)->mss = ntohs((s)->mss); \
(d)->state = (s)->state; \
(d)->wscale = (s)->wscale; \
- if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \
+ if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \
(d)->scrub != NULL) { \
(d)->scrub->pfss_flags = \
ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \
(d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \
- (d)->scrub->pfss_ts_mod = (s)->scrub.pfss_ts_mod; \
+ (d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\
} \
} while (0)
-#define pf_state_counter_to_pfsync(s,d) do { \
- d[0] = (s>>32)&0xffffffff; \
- d[1] = s&0xffffffff; \
+#define pf_state_counter_hton(s,d) do { \
+ d[0] = htonl((s>>32)&0xffffffff); \
+ d[1] = htonl(s&0xffffffff); \
} while (0)
-#define pf_state_counter_from_pfsync(s) \
+#define pf_state_counter_from_pfsync(s) \
(((u_int64_t)(s[0])<<32) | (u_int64_t)(s[1]))
-
+#define pf_state_counter_ntoh(s,d) do { \
+ d = ntohl(s[0]); \
+ d = d<<32; \
+ d += ntohl(s[1]); \
+} while (0)
TAILQ_HEAD(pf_rulequeue, pf_rule);
@@ -1678,8 +1683,8 @@ void pf_purge_expired_fragments(void);
int pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *);
int pf_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *);
int pf_socket_lookup(int, struct pf_pdesc *);
-struct pf_state_key *pf_alloc_state_key(void);
-void pf_attach_state(struct pf_state_key *, struct pf_state *, int, int);
+struct pf_state_key *pf_alloc_state_key(int);
+int pf_state_key_attach(struct pf_state_key *, struct pf_state *, int);
void pfr_initialize(void);
int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,