svn commit: r185884 - vendor-sys/pf/dist/net

Max Laier mlaier at FreeBSD.org
Wed Dec 10 13:21:10 PST 2008


Author: mlaier
Date: Wed Dec 10 21:21:09 2008
New Revision: 185884
URL: http://svn.freebsd.org/changeset/base/185884

Log:
  Import OPENBSD_4_2_BASE

Modified:
  vendor-sys/pf/dist/net/if_pflog.c
  vendor-sys/pf/dist/net/if_pfsync.c
  vendor-sys/pf/dist/net/if_pfsync.h
  vendor-sys/pf/dist/net/pf.c
  vendor-sys/pf/dist/net/pf_if.c
  vendor-sys/pf/dist/net/pf_ioctl.c
  vendor-sys/pf/dist/net/pf_norm.c
  vendor-sys/pf/dist/net/pf_table.c
  vendor-sys/pf/dist/net/pfvar.h

Modified: vendor-sys/pf/dist/net/if_pflog.c
==============================================================================
--- vendor-sys/pf/dist/net/if_pflog.c	Wed Dec 10 21:09:09 2008	(r185883)
+++ vendor-sys/pf/dist/net/if_pflog.c	Wed Dec 10 21:21:09 2008	(r185884)
@@ -1,4 +1,4 @@
-/*	$OpenBSD: if_pflog.c,v 1.22 2006/12/15 09:31:20 otto Exp $	*/
+/*	$OpenBSD: if_pflog.c,v 1.24 2007/05/26 17:13:30 jason Exp $	*/
 /*
  * The authors of this code are John Ioannidis (ji at tla.org),
  * Angelos D. Keromytis (kermit at csd.uch.gr) and 
@@ -87,8 +87,6 @@ struct if_clone	pflog_cloner =
 
 struct ifnet	*pflogifs[PFLOGIFS_MAX];	/* for fast access */
 
-extern int ifqmaxlen;
-
 void
 pflogattach(int npflog)
 {
@@ -96,7 +94,6 @@ pflogattach(int npflog)
 	LIST_INIT(&pflogif_list);
 	for (i = 0; i < PFLOGIFS_MAX; i++)
 		pflogifs[i] = NULL;
-	(void) pflog_clone_create(&pflog_cloner, 0);
 	if_clone_attach(&pflog_cloner);
 }
 

Modified: vendor-sys/pf/dist/net/if_pfsync.c
==============================================================================
--- vendor-sys/pf/dist/net/if_pfsync.c	Wed Dec 10 21:09:09 2008	(r185883)
+++ vendor-sys/pf/dist/net/if_pfsync.c	Wed Dec 10 21:21:09 2008	(r185884)
@@ -1,4 +1,4 @@
-/*	$OpenBSD: if_pfsync.c,v 1.73 2006/11/16 13:13:38 henning Exp $	*/
+/*	$OpenBSD: if_pfsync.c,v 1.83 2007/06/26 14:44:12 mcbride Exp $	*/
 
 /*
  * Copyright (c) 2002 Michael Shalayeff
@@ -106,7 +106,6 @@ void	pfsync_bulk_update(void *);
 void	pfsync_bulkfail(void *);
 
 int	pfsync_sync_ok;
-extern int ifqmaxlen;
 
 struct if_clone	pfsync_cloner =
     IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create, pfsync_clone_destroy);
@@ -221,6 +220,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_rule *r = NULL;
 	struct pfi_kif	*kif;
 
@@ -243,7 +243,9 @@ pfsync_insert_net_state(struct pfsync_st
 	 * If the ruleset checksums match, it's safe to associate the state
 	 * with the rule of that number.
 	 */
-	if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && chksum_flag)
+	if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && chksum_flag &&
+	    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
@@ -257,6 +259,12 @@ pfsync_insert_net_state(struct pfsync_st
 	}
 	bzero(st, sizeof(*st));
 
+	if ((sk = pf_alloc_state_key(st)) == NULL) {
+		pool_put(&pf_state_pl, st);
+		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+		return (ENOMEM);
+	}
+
 	/* allocate memory for scrub info */
 	if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
 	    pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) {
@@ -264,6 +272,7 @@ pfsync_insert_net_state(struct pfsync_st
 		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);
 		return (ENOMEM);
 	}
 
@@ -274,9 +283,9 @@ pfsync_insert_net_state(struct pfsync_st
 	r->states++;
 
 	/* fill in the rest of the state entry */
-	pf_state_host_ntoh(&sp->lan, &st->lan);
-	pf_state_host_ntoh(&sp->gwy, &st->gwy);
-	pf_state_host_ntoh(&sp->ext, &st->ext);
+	pf_state_host_ntoh(&sp->lan, &sk->lan);
+	pf_state_host_ntoh(&sp->gwy, &sk->gwy);
+	pf_state_host_ntoh(&sp->ext, &sk->ext);
 
 	pf_state_peer_ntoh(&sp->src, &st->src);
 	pf_state_peer_ntoh(&sp->dst, &st->dst);
@@ -285,9 +294,9 @@ pfsync_insert_net_state(struct pfsync_st
 	st->creation = time_second - ntohl(sp->creation);
 	st->expire = ntohl(sp->expire) + time_second;
 
-	st->af = sp->af;
-	st->proto = sp->proto;
-	st->direction = sp->direction;
+	sk->af = sp->af;
+	sk->proto = sp->proto;
+	sk->direction = sp->direction;
 	st->log = sp->log;
 	st->timeout = sp->timeout;
 	st->allow_opts = sp->allow_opts;
@@ -318,14 +327,17 @@ pfsync_input(struct mbuf *m, ...)
 	struct pfsync_header *ph;
 	struct pfsync_softc *sc = pfsyncif;
 	struct pf_state *st;
-	struct pf_state_cmp key;
+	struct pf_state_key *sk;
+	struct pf_state_cmp id_key;
 	struct pfsync_state *sp;
 	struct pfsync_state_upd *up;
 	struct pfsync_state_del *dp;
 	struct pfsync_state_clr *cp;
 	struct pfsync_state_upd_req *rup;
 	struct pfsync_state_bus *bus;
+#ifdef IPSEC
 	struct pfsync_tdb *pt;
+#endif
 	struct in_addr src;
 	struct mbuf *mp;
 	int iplen, action, error, i, s, count, offp, sfail, stale = 0;
@@ -389,7 +401,8 @@ pfsync_input(struct mbuf *m, ...)
 	switch (action) {
 	case PFSYNC_ACT_CLR: {
 		struct pf_state *nexts;
-		struct pfi_kif	*kif;
+		struct pf_state_key *nextsk;
+		struct pfi_kif *kif;
 		u_int32_t creatorid;
 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
 		    sizeof(*cp), &offp)) == NULL) {
@@ -414,13 +427,16 @@ pfsync_input(struct mbuf *m, ...)
 				splx(s);
 				return;
 			}
-			for (st = RB_MIN(pf_state_tree_lan_ext,
-			    &kif->pfik_lan_ext); st; st = nexts) {
-				nexts = RB_NEXT(pf_state_tree_lan_ext,
-				    &kif->pfik_lan_ext, st);
-				if (st->creatorid == creatorid) {
-					st->sync_flags |= PFSTATE_FROMSYNC;
-					pf_unlink_state(st);
+			for (sk = RB_MIN(pf_state_tree_lan_ext,
+			    &pf_statetbl_lan_ext); sk; sk = nextsk) {
+				nextsk = RB_NEXT(pf_state_tree_lan_ext,
+				    &pf_statetbl_lan_ext, sk);
+				TAILQ_FOREACH(st, &sk->states, next) {
+					if (st->creatorid == creatorid) {
+						st->sync_flags |=
+						    PFSTATE_FROMSYNC;
+						pf_unlink_state(st);
+					}
 				}
 			}
 		}
@@ -485,18 +501,19 @@ pfsync_input(struct mbuf *m, ...)
 				continue;
 			}
 
-			bcopy(sp->id, &key.id, sizeof(key.id));
-			key.creatorid = sp->creatorid;
+			bcopy(sp->id, &id_key.id, sizeof(id_key.id));
+			id_key.creatorid = sp->creatorid;
 
-			st = pf_find_state_byid(&key);
+			st = pf_find_state_byid(&id_key);
 			if (st == NULL) {
 				/* insert the update */
 				if (pfsync_insert_net_state(sp, chksum_flag))
 					pfsyncstats.pfsyncs_badstate++;
 				continue;
 			}
+			sk = st->state_key;
 			sfail = 0;
-			if (st->proto == IPPROTO_TCP) {
+			if (sk->proto == IPPROTO_TCP) {
 				/*
 				 * The state should never go backwards except
 				 * for syn-proxy states.  Neither should the
@@ -579,10 +596,10 @@ pfsync_input(struct mbuf *m, ...)
 		s = splsoftnet();
 		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
 		    i < count; i++, sp++) {
-			bcopy(sp->id, &key.id, sizeof(key.id));
-			key.creatorid = sp->creatorid;
+			bcopy(sp->id, &id_key.id, sizeof(id_key.id));
+			id_key.creatorid = sp->creatorid;
 
-			st = pf_find_state_byid(&key);
+			st = pf_find_state_byid(&id_key);
 			if (st == NULL) {
 				pfsyncstats.pfsyncs_badstate++;
 				continue;
@@ -616,10 +633,10 @@ pfsync_input(struct mbuf *m, ...)
 				continue;
 			}
 
-			bcopy(up->id, &key.id, sizeof(key.id));
-			key.creatorid = up->creatorid;
+			bcopy(up->id, &id_key.id, sizeof(id_key.id));
+			id_key.creatorid = up->creatorid;
 
-			st = pf_find_state_byid(&key);
+			st = pf_find_state_byid(&id_key);
 			if (st == NULL) {
 				/* We don't have this state. Ask for it. */
 				error = pfsync_request_update(up, &src);
@@ -631,8 +648,9 @@ pfsync_input(struct mbuf *m, ...)
 				pfsyncstats.pfsyncs_badstate++;
 				continue;
 			}
+			sk = st->state_key;
 			sfail = 0;
-			if (st->proto == IPPROTO_TCP) {
+			if (sk->proto == IPPROTO_TCP) {
 				/*
 				 * The state should never go backwards except
 				 * for syn-proxy states.  Neither should the
@@ -702,10 +720,10 @@ pfsync_input(struct mbuf *m, ...)
 		s = splsoftnet();
 		for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
 		    i < count; i++, dp++) {
-			bcopy(dp->id, &key.id, sizeof(key.id));
-			key.creatorid = dp->creatorid;
+			bcopy(dp->id, &id_key.id, sizeof(id_key.id));
+			id_key.creatorid = dp->creatorid;
 
-			st = pf_find_state_byid(&key);
+			st = pf_find_state_byid(&id_key);
 			if (st == NULL) {
 				pfsyncstats.pfsyncs_badstate++;
 				continue;
@@ -732,10 +750,10 @@ pfsync_input(struct mbuf *m, ...)
 		for (i = 0,
 		    rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
 		    i < count; i++, rup++) {
-			bcopy(rup->id, &key.id, sizeof(key.id));
-			key.creatorid = rup->creatorid;
+			bcopy(rup->id, &id_key.id, sizeof(id_key.id));
+			id_key.creatorid = rup->creatorid;
 
-			if (key.id == 0 && key.creatorid == 0) {
+			if (id_key.id == 0 && id_key.creatorid == 0) {
 				sc->sc_ureq_received = time_uptime;
 				if (sc->sc_bulk_send_next == NULL)
 					sc->sc_bulk_send_next =
@@ -747,7 +765,7 @@ pfsync_input(struct mbuf *m, ...)
 				pfsync_send_bus(sc, PFSYNC_BUS_START);
 				timeout_add(&sc->sc_bulk_tmo, 1 * hz);
 			} else {
-				st = pf_find_state_byid(&key);
+				st = pf_find_state_byid(&id_key);
 				if (st == NULL) {
 					pfsyncstats.pfsyncs_badstate++;
 					continue;
@@ -804,6 +822,7 @@ pfsync_input(struct mbuf *m, ...)
 			break;
 		}
 		break;
+#ifdef IPSEC
 	case PFSYNC_ACT_TDB_UPD:
 		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
 		    count * sizeof(*pt), &offp)) == NULL) {
@@ -816,6 +835,7 @@ pfsync_input(struct mbuf *m, ...)
 			pfsync_update_net_tdb(pt);
 		splx(s);
 		break;
+#endif
 	}
 
 done:
@@ -1080,6 +1100,7 @@ pfsync_pack_state(u_int8_t action, struc
 	struct pfsync_state *sp = NULL;
 	struct pfsync_state_upd *up = NULL;
 	struct pfsync_state_del *dp = NULL;
+	struct pf_state_key *sk = st->state_key;
 	struct pf_rule *r;
 	u_long secs;
 	int s, ret = 0;
@@ -1164,10 +1185,10 @@ pfsync_pack_state(u_int8_t action, struc
 		bcopy(&st->id, sp->id, sizeof(sp->id));
 		sp->creatorid = st->creatorid;
 
-		strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
-		pf_state_host_hton(&st->lan, &sp->lan);
-		pf_state_host_hton(&st->gwy, &sp->gwy);
-		pf_state_host_hton(&st->ext, &sp->ext);
+		strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
+		pf_state_host_hton(&sk->lan, &sp->lan);
+		pf_state_host_hton(&sk->gwy, &sp->gwy);
+		pf_state_host_hton(&sk->ext, &sp->ext);
 
 		bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
 
@@ -1184,9 +1205,9 @@ pfsync_pack_state(u_int8_t action, struc
 			sp->anchor = htonl(-1);
 		else
 			sp->anchor = htonl(r->nr);
-		sp->af = st->af;
-		sp->proto = st->proto;
-		sp->direction = st->direction;
+		sp->af = sk->af;
+		sp->proto = sk->proto;
+		sp->direction = sk->direction;
 		sp->log = st->log;
 		sp->allow_opts = st->allow_opts;
 		sp->timeout = st->timeout;
@@ -1418,7 +1439,7 @@ pfsync_bulk_update(void *v)
 			}
 
 			/* figure next state to send */
-			state = TAILQ_NEXT(state, u.s.entry_list);
+			state = TAILQ_NEXT(state, entry_list);
 
 			/* wrap to start of list if we hit the end */
 			if (!state)
@@ -1577,6 +1598,7 @@ pfsync_sendout_mbuf(struct pfsync_softc 
 	return (0);
 }
 
+#ifdef IPSEC
 /* Update an in-kernel tdb. Silently fail if no tdb is found. */
 void
 pfsync_update_net_tdb(struct pfsync_tdb *pt)
@@ -1727,3 +1749,4 @@ pfsync_update_tdb(struct tdb *tdb, int o
 	splx(s);
 	return (ret);
 }
+#endif

Modified: vendor-sys/pf/dist/net/if_pfsync.h
==============================================================================
--- vendor-sys/pf/dist/net/if_pfsync.h	Wed Dec 10 21:09:09 2008	(r185883)
+++ vendor-sys/pf/dist/net/if_pfsync.h	Wed Dec 10 21:21:09 2008	(r185884)
@@ -1,4 +1,4 @@
-/*	$OpenBSD: if_pfsync.h,v 1.30 2006/10/31 14:49:01 henning Exp $	*/
+/*	$OpenBSD: if_pfsync.h,v 1.31 2007/05/31 04:11:42 mcbride Exp $	*/
 
 /*
  * Copyright (c) 2001 Michael Shalayeff
@@ -32,62 +32,6 @@
 
 #define PFSYNC_ID_LEN	sizeof(u_int64_t)
 
-struct pfsync_state_scrub {
-	u_int16_t	pfss_flags;
-	u_int8_t	pfss_ttl;	/* stashed TTL		*/
-#define PFSYNC_SCRUB_FLAG_VALID 	0x01
-	u_int8_t	scrub_flag;
-	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	*/
-	u_int32_t	seqhi;		/* Max the other end ACKd + win	*/
-	u_int32_t	seqdiff;	/* Sequence number modulator	*/
-	u_int16_t	max_win;	/* largest window (pre scaling)	*/
-	u_int16_t	mss;		/* Maximum segment size option	*/
-	u_int8_t	state;		/* active state level		*/
-	u_int8_t	wscale;		/* window scaling factor	*/
-	u_int8_t	pad[6];
-} __packed;
-
-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_peer src;
-	struct pfsync_state_peer dst;
-	struct pf_addr	 rt_addr;
-	u_int32_t	 rule;
-	u_int32_t	 anchor;
-	u_int32_t	 nat_rule;
-	u_int32_t	 creation;
-	u_int32_t	 expire;
-	u_int32_t	 packets[2][2];
-	u_int32_t	 bytes[2][2];
-	u_int32_t	 creatorid;
-	sa_family_t	 af;
-	u_int8_t	 proto;
-	u_int8_t	 direction;
-	u_int8_t	 log;
-	u_int8_t	 allow_opts;
-	u_int8_t	 timeout;
-	u_int8_t	 sync_flags;
-	u_int8_t	 updates;
-} __packed;
-
-#define PFSYNC_FLAG_COMPRESS 	0x01
-#define PFSYNC_FLAG_STALE	0x02
-
 struct pfsync_tdb {
 	u_int32_t	spi;
 	union sockaddr_union dst;
@@ -251,6 +195,7 @@ struct pfsyncreq {
 };
 
 
+/* for copies to/from network */
 #define pf_state_peer_hton(s,d) do {		\
 	(d)->seqlo = htonl((s)->seqlo);		\
 	(d)->seqhi = htonl((s)->seqhi);		\
@@ -312,7 +257,7 @@ int pfsync_clear_states(u_int32_t, char 
 int pfsync_pack_state(u_int8_t, struct pf_state *, int);
 #define pfsync_insert_state(st)	do {				\
 	if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) ||	\
-	    (st->proto == IPPROTO_PFSYNC))			\
+	    (st->state_key->proto == IPPROTO_PFSYNC))			\
 		st->sync_flags |= PFSTATE_NOSYNC;		\
 	else if (!st->sync_flags)				\
 		pfsync_pack_state(PFSYNC_ACT_INS, (st), 	\

Modified: vendor-sys/pf/dist/net/pf.c
==============================================================================
--- vendor-sys/pf/dist/net/pf.c	Wed Dec 10 21:09:09 2008	(r185883)
+++ vendor-sys/pf/dist/net/pf.c	Wed Dec 10 21:21:09 2008	(r185884)
@@ -1,5 +1,4 @@
-/*	$OpenBSD: pf.c,v 1.527 2007/02/22 15:23:23 pyr Exp $ */
-/* add:	$OpenBSD: pf.c,v 1.559 2007/09/18 18:45:59 markus Exp $ */
+/*	$OpenBSD: pf.c,v 1.552 2007/08/21 15:57:27 dhartmei Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -96,6 +95,10 @@
  * Global variables
  */
 
+/* state tables */
+struct pf_state_tree_lan_ext	 pf_statetbl_lan_ext;
+struct pf_state_tree_ext_gwy	 pf_statetbl_ext_gwy;
+
 struct pf_altqqueue	 pf_altqs[2];
 struct pf_palist	 pf_pabuf;
 struct pf_altqqueue	*pf_altqs_active;
@@ -114,8 +117,9 @@ struct pf_anchor_stackframe {
 	struct pf_anchor			*child;
 } pf_anchor_stack[64];
 
-struct pool		 pf_src_tree_pl, pf_rule_pl;
-struct pool		 pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+struct pool		 pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl;
+struct pool		 pf_state_pl, pf_state_key_pl;
+struct pool		 pf_altq_pl;
 
 void			 pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
 
@@ -153,22 +157,13 @@ struct pf_rule		*pf_get_translation(stru
 			    struct pf_addr *, u_int16_t,
 			    struct pf_addr *, u_int16_t,
 			    struct pf_addr *, u_int16_t *);
-int			 pf_test_tcp(struct pf_rule **, struct pf_state **,
-			    int, struct pfi_kif *, struct mbuf *, int,
-			    void *, struct pf_pdesc *, struct pf_rule **,
-			    struct pf_ruleset **, struct ifqueue *);
-int			 pf_test_udp(struct pf_rule **, struct pf_state **,
+void			 pf_attach_state(struct pf_state_key *,
+			    struct pf_state *, int);
+void			 pf_detach_state(struct pf_state *, int);
+int			 pf_test_rule(struct pf_rule **, struct pf_state **,
 			    int, struct pfi_kif *, struct mbuf *, int,
 			    void *, struct pf_pdesc *, struct pf_rule **,
 			    struct pf_ruleset **, struct ifqueue *);
-int			 pf_test_icmp(struct pf_rule **, struct pf_state **,
-			    int, struct pfi_kif *, struct mbuf *, int,
-			    void *, struct pf_pdesc *, struct pf_rule **,
-			    struct pf_ruleset **, struct ifqueue *);
-int			 pf_test_other(struct pf_rule **, struct pf_state **,
-			    int, struct pfi_kif *, struct mbuf *, int, void *,
-			    struct pf_pdesc *, struct pf_rule **,
-			    struct pf_ruleset **, struct ifqueue *);
 int			 pf_test_fragment(struct pf_rule **, int,
 			    struct pfi_kif *, struct mbuf *, void *,
 			    struct pf_pdesc *, struct pf_rule **,
@@ -184,8 +179,9 @@ int			 pf_test_state_icmp(struct pf_stat
 			    void *, struct pf_pdesc *, u_short *);
 int			 pf_test_state_other(struct pf_state **, int,
 			    struct pfi_kif *, struct pf_pdesc *);
-int			 pf_match_tag(struct mbuf *, struct pf_rule *,
-			     struct pf_mtag *, int *);
+int			 pf_match_tag(struct mbuf *, struct pf_rule *, int *);
+void			 pf_step_into_anchor(int *, struct pf_ruleset **, int,
+			    struct pf_rule **, struct pf_rule **,  int *);
 int			 pf_step_out_of_anchor(int *, struct pf_ruleset **,
 			     int, struct pf_rule **, struct pf_rule **,
 			     int *);
@@ -217,9 +213,11 @@ int			 pf_check_proto_cksum(struct mbuf 
 			    u_int8_t, sa_family_t);
 int			 pf_addr_wrap_neq(struct pf_addr_wrap *,
 			    struct pf_addr_wrap *);
-struct pf_state		*pf_find_state_recurse(struct pfi_kif *,
-			    struct pf_state_cmp *, u_int8_t);
+struct pf_state		*pf_find_state(struct pfi_kif *,
+			    struct pf_state_key_cmp *, u_int8_t);
 int			 pf_src_connlimit(struct pf_state **);
+void			 pf_stateins_err(const char *, struct pf_state *,
+			    struct pfi_kif *);
 int			 pf_check_congestion(struct ifqueue *);
 
 extern struct pool pfr_ktable_pl;
@@ -236,11 +234,9 @@ struct pf_pool_limit pf_pool_limits[PF_L
 #define STATE_LOOKUP()							\
 	do {								\
 		if (direction == PF_IN)					\
-			*state = pf_find_state_recurse(			\
-			    kif, &key, PF_EXT_GWY);			\
+			*state = pf_find_state(kif, &key, PF_EXT_GWY);	\
 		else							\
-			*state = pf_find_state_recurse(			\
-			    kif, &key, PF_LAN_EXT);			\
+			*state = pf_find_state(kif, &key, PF_LAN_EXT);	\
 		if (*state == NULL || (*state)->timeout == PFTM_PURGE)	\
 			return (PF_DROP);				\
 		if (direction == PF_OUT &&				\
@@ -253,13 +249,13 @@ struct pf_pool_limit pf_pool_limits[PF_L
 			return (PF_PASS);				\
 	} while (0)
 
-#define	STATE_TRANSLATE(s) \
-	(s)->lan.addr.addr32[0] != (s)->gwy.addr.addr32[0] || \
-	((s)->af == AF_INET6 && \
-	((s)->lan.addr.addr32[1] != (s)->gwy.addr.addr32[1] || \
-	(s)->lan.addr.addr32[2] != (s)->gwy.addr.addr32[2] || \
-	(s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \
-	(s)->lan.port != (s)->gwy.port
+#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
@@ -283,10 +279,10 @@ struct pf_pool_limit pf_pool_limits[PF_L
 	} while (0)
 
 static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
-static __inline int pf_state_compare_lan_ext(struct pf_state *,
-	struct pf_state *);
-static __inline int pf_state_compare_ext_gwy(struct pf_state *,
-	struct pf_state *);
+static __inline int pf_state_compare_lan_ext(struct pf_state_key *,
+	struct pf_state_key *);
+static __inline int pf_state_compare_ext_gwy(struct pf_state_key *,
+	struct pf_state_key *);
 static __inline int pf_state_compare_id(struct pf_state *,
 	struct pf_state *);
 
@@ -296,12 +292,15 @@ struct pf_state_tree_id tree_id;
 struct pf_state_queue state_list;
 
 RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
-RB_GENERATE(pf_state_tree_lan_ext, pf_state,
-    u.s.entry_lan_ext, pf_state_compare_lan_ext);
-RB_GENERATE(pf_state_tree_ext_gwy, pf_state,
-    u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
+RB_GENERATE(pf_state_tree_lan_ext, pf_state_key,
+    entry_lan_ext, pf_state_compare_lan_ext);
+RB_GENERATE(pf_state_tree_ext_gwy, pf_state_key,
+    entry_ext_gwy, pf_state_compare_ext_gwy);
 RB_GENERATE(pf_state_tree_id, pf_state,
-    u.s.entry_id, pf_state_compare_id);
+    entry_id, pf_state_compare_id);
+
+#define	PF_DT_SKIP_LANEXT	0x01
+#define	PF_DT_SKIP_EXTGWY	0x02
 
 static __inline int
 pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
@@ -348,7 +347,7 @@ pf_src_compare(struct pf_src_node *a, st
 }
 
 static __inline int
-pf_state_compare_lan_ext(struct pf_state *a, struct pf_state *b)
+pf_state_compare_lan_ext(struct pf_state_key *a, struct pf_state_key *b)
 {
 	int	diff;
 
@@ -416,7 +415,7 @@ pf_state_compare_lan_ext(struct pf_state
 }
 
 static __inline int
-pf_state_compare_ext_gwy(struct pf_state *a, struct pf_state *b)
+pf_state_compare_ext_gwy(struct pf_state_key *a, struct pf_state_key *b)
 {
 	int	diff;
 
@@ -522,74 +521,71 @@ 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));
 }
 
 struct pf_state *
-pf_find_state_recurse(struct pfi_kif *kif, struct pf_state_cmp *key, u_int8_t tree)
+pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int8_t tree)
 {
-	struct pf_state *s;
+	struct pf_state_key	*sk;
+	struct pf_state		*s;
 
 	pf_status.fcounters[FCNT_STATE_SEARCH]++;
 
 	switch (tree) {
 	case PF_LAN_EXT:
-		if ((s = RB_FIND(pf_state_tree_lan_ext, &kif->pfik_lan_ext,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		if ((s = RB_FIND(pf_state_tree_lan_ext, &pfi_all->pfik_lan_ext,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		return (NULL);
+		sk = RB_FIND(pf_state_tree_lan_ext, &pf_statetbl_lan_ext,
+		    (struct pf_state_key *)key);
+		break;
 	case PF_EXT_GWY:
-		if ((s = RB_FIND(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		if ((s = RB_FIND(pf_state_tree_ext_gwy, &pfi_all->pfik_ext_gwy,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		return (NULL);
+		sk = RB_FIND(pf_state_tree_ext_gwy, &pf_statetbl_ext_gwy,
+		    (struct pf_state_key *)key);
+		break;
 	default:
-		panic("pf_find_state_recurse");
+		panic("pf_find_state");
 	}
+
+	/* list is sorted, if-bound states before floating ones */
+	if (sk != NULL)
+		TAILQ_FOREACH(s, &sk->states, next)
+			if (s->kif == pfi_all || s->kif == kif)
+				return (s);
+
+	return (NULL);
 }
 
 struct pf_state *
-pf_find_state_all(struct pf_state_cmp *key, u_int8_t tree, int *more)
+pf_find_state_all(struct pf_state_key_cmp *key, u_int8_t tree, int *more)
 {
-	struct pf_state *s, *ss = NULL;
-	struct pfi_kif	*kif;
+	struct pf_state_key	*sk;
+	struct pf_state		*s, *ret = NULL;
 
 	pf_status.fcounters[FCNT_STATE_SEARCH]++;
 
 	switch (tree) {
 	case PF_LAN_EXT:
-		TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
-			s = RB_FIND(pf_state_tree_lan_ext,
-			    &kif->pfik_lan_ext, (struct pf_state *)key);
-			if (s == NULL)
-				continue;
-			if (more == NULL)
-				return (s);
-			ss = s;
-			(*more)++;
-		}
-		return (ss);
+		sk = RB_FIND(pf_state_tree_lan_ext,
+		    &pf_statetbl_lan_ext, (struct pf_state_key *)key);
+		break;
 	case PF_EXT_GWY:
-		TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
-			s = RB_FIND(pf_state_tree_ext_gwy,
-			    &kif->pfik_ext_gwy, (struct pf_state *)key);
-			if (s == NULL)
-				continue;
-			if (more == NULL)
-				return (s);
-			ss = s;
-			(*more)++;
-		}
-		return (ss);
+		sk = RB_FIND(pf_state_tree_ext_gwy,
+		    &pf_statetbl_ext_gwy, (struct pf_state_key *)key);
+		break;
 	default:
 		panic("pf_find_state_all");
 	}
+
+	if (sk != NULL) {
+		ret = TAILQ_FIRST(&sk->states);
+		if (more == NULL)
+			return (ret);
+
+		TAILQ_FOREACH(s, &sk->states, next)
+			(*more)++;
+	}
+
+	return (ret);
 }
 
 void
@@ -625,7 +621,6 @@ pf_check_threshold(struct pf_threshold *
 int
 pf_src_connlimit(struct pf_state **state)
 {
-	struct pf_state	*s;
 	int bad = 0;
 
 	(*state)->src_node->conn++;
@@ -656,12 +651,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)->af);
+			    (*state)->state_key->af);
 		}
 
 		bzero(&p, sizeof(p));
-		p.pfra_af = (*state)->af;
-		switch ((*state)->af) {
+		p.pfra_af = (*state)->state_key->af;
+		switch ((*state)->state_key->af) {
 #ifdef INET
 		case AF_INET:
 			p.pfra_net = 32;
@@ -681,26 +676,31 @@ pf_src_connlimit(struct pf_state **state
 
 		/* kill existing states if that's required. */
 		if ((*state)->rule.ptr->flush) {
-			pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
+			struct pf_state_key *sk;
+			struct pf_state *st;
 
-			RB_FOREACH(s, pf_state_tree_id, &tree_id) {
+			pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
+			RB_FOREACH(st, pf_state_tree_id, &tree_id) {
+				sk = st->state_key;
 				/*
 				 * Kill states from this source.  (Only those
 				 * from the same rule if PF_FLUSH_GLOBAL is not
 				 * set)
 				 */
-				if (s->af == (*state)->af &&
-				    (((*state)->direction == PF_OUT &&
+				if (sk->af ==
+				    (*state)->state_key->af &&
+				    (((*state)->state_key->direction ==
+				        PF_OUT &&
 				    PF_AEQ(&(*state)->src_node->addr,
-				    &s->lan.addr, s->af)) ||
-				    ((*state)->direction == PF_IN &&
+				        &sk->lan.addr, sk->af)) ||
+				    ((*state)->state_key->direction == PF_IN &&
 				    PF_AEQ(&(*state)->src_node->addr,
-				    &s->ext.addr, s->af))) &&
+				        &sk->ext.addr, sk->af))) &&
 				    ((*state)->rule.ptr->flush &
 				    PF_FLUSH_GLOBAL ||
-				    (*state)->rule.ptr == s->rule.ptr)) {
-					s->timeout = PFTM_PURGE;
-					s->src.state = s->dst.state =
+				    (*state)->rule.ptr == st->rule.ptr)) {
+					st->timeout = PFTM_PURGE;
+					st->src.state = st->dst.state =
 					    TCPS_CLOSED;
 					killed++;
 				}
@@ -782,73 +782,80 @@ pf_insert_src_node(struct pf_src_node **
 	return (0);
 }
 
+void
+pf_stateins_err(const char *tree, struct pf_state *s, struct pfi_kif *kif)
+{
+	struct pf_state_key	*sk = s->state_key;
+
+	if (pf_status.debug >= PF_DEBUG_MISC) {
+		printf("pf: state insert failed: %s %s", tree, kif->pfik_name);
+		printf(" lan: ");
+		pf_print_host(&sk->lan.addr, sk->lan.port,
+		    sk->af);
+		printf(" gwy: ");
+		pf_print_host(&sk->gwy.addr, sk->gwy.port,
+		    sk->af);
+		printf(" ext: ");
+		pf_print_host(&sk->ext.addr, sk->ext.port,
+		    sk->af);
+		if (s->sync_flags & PFSTATE_FROMSYNC)
+			printf(" (from sync)");
+		printf("\n");
+	}
+}
+
 int
-pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
+pf_insert_state(struct pfi_kif *kif, struct pf_state *s)
 {
-	/* Thou MUST NOT insert multiple duplicate keys */
-	state->u.s.kif = kif;
-	if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) {
-		if (pf_status.debug >= PF_DEBUG_MISC) {
-			printf("pf: state insert failed: tree_lan_ext");
-			printf(" lan: ");
-			pf_print_host(&state->lan.addr, state->lan.port,
-			    state->af);
-			printf(" gwy: ");
-			pf_print_host(&state->gwy.addr, state->gwy.port,
-			    state->af);
-			printf(" ext: ");
-			pf_print_host(&state->ext.addr, state->ext.port,
-			    state->af);
-			if (state->sync_flags & PFSTATE_FROMSYNC)
-				printf(" (from sync)");
-			printf("\n");
-		}
-		return (-1);
+	struct pf_state_key	*cur;
+	struct pf_state		*sp;
+
+	KASSERT(s->state_key != NULL);
+	s->kif = kif;
+
+	if ((cur = RB_INSERT(pf_state_tree_lan_ext, &pf_statetbl_lan_ext,
+	    s->state_key)) != NULL) {
+		/* key exists. check for same kif, if none, add to key */
+		TAILQ_FOREACH(sp, &cur->states, next)
+			if (sp->kif == kif) {	/* collision! */
+				pf_stateins_err("tree_lan_ext", s, kif);
+				return (-1);
+			}
+		pf_detach_state(s, PF_DT_SKIP_LANEXT|PF_DT_SKIP_EXTGWY);
+		pf_attach_state(cur, s, kif == pfi_all ? 1 : 0);
 	}
 
-	if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) {
-		if (pf_status.debug >= PF_DEBUG_MISC) {
-			printf("pf: state insert failed: tree_ext_gwy");
-			printf(" lan: ");
-			pf_print_host(&state->lan.addr, state->lan.port,
-			    state->af);
-			printf(" gwy: ");
-			pf_print_host(&state->gwy.addr, state->gwy.port,
-			    state->af);
-			printf(" ext: ");
-			pf_print_host(&state->ext.addr, state->ext.port,
-			    state->af);
-			if (state->sync_flags & PFSTATE_FROMSYNC)
-				printf(" (from sync)");
-			printf("\n");
-		}
-		RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
+	/* if cur != NULL, we already found a state key and attached to it */
+	if (cur == NULL && (cur = RB_INSERT(pf_state_tree_ext_gwy,
+	    &pf_statetbl_ext_gwy, s->state_key)) != NULL) {
+		/* must not happen. we must have found the sk above! */
+		pf_stateins_err("tree_ext_gwy", s, kif);
+		pf_detach_state(s, PF_DT_SKIP_EXTGWY);
 		return (-1);
 	}
 
-	if (state->id == 0 && state->creatorid == 0) {
-		state->id = htobe64(pf_status.stateid++);
-		state->creatorid = pf_status.hostid;
+	if (s->id == 0 && s->creatorid == 0) {
+		s->id = htobe64(pf_status.stateid++);
+		s->creatorid = pf_status.hostid;
 	}
-	if (RB_INSERT(pf_state_tree_id, &tree_id, state) != NULL) {
+	if (RB_INSERT(pf_state_tree_id, &tree_id, s) != NULL) {
 		if (pf_status.debug >= PF_DEBUG_MISC) {
 			printf("pf: state insert failed: "
 			    "id: %016llx creatorid: %08x",
-			    betoh64(state->id), ntohl(state->creatorid));
-			if (state->sync_flags & PFSTATE_FROMSYNC)
+			    betoh64(s->id), ntohl(s->creatorid));
+			if (s->sync_flags & PFSTATE_FROMSYNC)
 				printf(" (from sync)");
 			printf("\n");
 		}
-		RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
-		RB_REMOVE(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state);
+		pf_detach_state(s, 0);
 		return (-1);
 	}
-	TAILQ_INSERT_TAIL(&state_list, state, u.s.entry_list);
+	TAILQ_INSERT_TAIL(&state_list, s, entry_list);
 	pf_status.fcounters[FCNT_STATE_INSERT]++;
 	pf_status.states++;
 	pfi_kif_ref(kif, PFI_KIF_REF_STATE);
 #if NPFSYNC
-	pfsync_insert_state(state);
+	pfsync_insert_state(s);
 #endif
 	return (0);
 }
@@ -954,7 +961,7 @@ pf_src_tree_remove_state(struct pf_state
 	u_int32_t timeout;
 
 	if (s->src_node != NULL) {
-		if (s->proto == IPPROTO_TCP) {
+		if (s->state_key->proto == IPPROTO_TCP) {
 			if (s->src.tcp_est)
 				--s->src_node->conn;
 		}
@@ -983,16 +990,12 @@ void
 pf_unlink_state(struct pf_state *cur)
 {
 	if (cur->src.state == PF_TCPS_PROXY_DST) {
-		pf_send_tcp(cur->rule.ptr, cur->af,
-		    &cur->ext.addr, &cur->lan.addr,
-		    cur->ext.port, cur->lan.port,
+		pf_send_tcp(cur->rule.ptr, cur->state_key->af,
+		    &cur->state_key->ext.addr, &cur->state_key->lan.addr,
+		    cur->state_key->ext.port, cur->state_key->lan.port,
 		    cur->src.seqhi, cur->src.seqlo + 1,
 		    TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
 	}
-	RB_REMOVE(pf_state_tree_ext_gwy,
-	    &cur->u.s.kif->pfik_ext_gwy, cur);
-	RB_REMOVE(pf_state_tree_lan_ext,
-	    &cur->u.s.kif->pfik_lan_ext, cur);
 	RB_REMOVE(pf_state_tree_id, &tree_id, cur);
 #if NPFSYNC
 	if (cur->creatorid == pf_status.hostid)
@@ -1000,6 +1003,7 @@ pf_unlink_state(struct pf_state *cur)
 #endif
 	cur->timeout = PFTM_UNLINKED;
 	pf_src_tree_remove_state(cur);
+	pf_detach_state(cur, 0);
 }
 
 /* callers should be at splsoftnet and hold the
@@ -1025,8 +1029,8 @@ pf_free_state(struct pf_state *cur)
 		if (--cur->anchor.ptr->states <= 0)
 			pf_rm_rule(NULL, cur->anchor.ptr);
 	pf_normalize_tcp_cleanup(cur);
-	pfi_kif_unref(cur->u.s.kif, PFI_KIF_REF_STATE);
-	TAILQ_REMOVE(&state_list, cur, u.s.entry_list);
+	pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE);
+	TAILQ_REMOVE(&state_list, cur, entry_list);
 	if (cur->tag)
 		pf_tag_unref(cur->tag);
 	pool_put(&pf_state_pl, cur);
@@ -1050,7 +1054,7 @@ pf_purge_expired_states(u_int32_t maxche
 		}
 
 		/* get next state, as cur may get deleted */
-		next = TAILQ_NEXT(cur, u.s.entry_list);
+		next = TAILQ_NEXT(cur, entry_list);
 
 		if (cur->timeout == PFTM_UNLINKED) {
 			/* free unlinked state */
@@ -1175,7 +1179,8 @@ pf_print_host(struct pf_addr *addr, u_in
 void
 pf_print_state(struct pf_state *s)
 {
-	switch (s->proto) {
+	struct pf_state_key *sk = s->state_key;
+	switch (sk->proto) {
 	case IPPROTO_TCP:
 		printf("TCP ");
 		break;
@@ -1189,14 +1194,14 @@ pf_print_state(struct pf_state *s)
 		printf("ICMPV6 ");
 		break;
 	default:
-		printf("%u ", s->proto);
+		printf("%u ", sk->proto);
 		break;
 	}
-	pf_print_host(&s->lan.addr, s->lan.port, s->af);
+	pf_print_host(&sk->lan.addr, sk->lan.port, sk->af);
 	printf(" ");
-	pf_print_host(&s->gwy.addr, s->gwy.port, s->af);
+	pf_print_host(&sk->gwy.addr, sk->gwy.port, sk->af);
 	printf(" ");
-	pf_print_host(&s->ext.addr, s->ext.port, s->af);
+	pf_print_host(&sk->ext.addr, sk->ext.port, sk->af);
 	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)
@@ -1565,7 +1570,6 @@ pf_send_tcp(const struct pf_rule *r, sa_
 #endif /* INET6 */
 	struct tcphdr	*th;
 	char		*opt;
-	struct pf_mtag	*pf_mtag;
 
 	/* maximum segment size tcp option */
 	tlen = sizeof(struct tcphdr);
@@ -1589,24 +1593,18 @@ pf_send_tcp(const struct pf_rule *r, sa_
 	m = m_gethdr(M_DONTWAIT, MT_HEADER);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list