From owner-svn-src-vendor@FreeBSD.ORG Wed Dec 10 21:21:10 2008 Return-Path: Delivered-To: svn-src-vendor@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 81A2A1065678; Wed, 10 Dec 2008 21:21:10 +0000 (UTC) (envelope-from mlaier@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6C5948FC1C; Wed, 10 Dec 2008 21:21:10 +0000 (UTC) (envelope-from mlaier@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mBALLA28043151; Wed, 10 Dec 2008 21:21:10 GMT (envelope-from mlaier@svn.freebsd.org) Received: (from mlaier@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mBALLATn043146; Wed, 10 Dec 2008 21:21:10 GMT (envelope-from mlaier@svn.freebsd.org) Message-Id: <200812102121.mBALLATn043146@svn.freebsd.org> From: Max Laier Date: Wed, 10 Dec 2008 21:21:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org X-SVN-Group: vendor-sys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r185884 - vendor-sys/pf/dist/net X-BeenThere: svn-src-vendor@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the vendor work area tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Dec 2008 21:21:10 -0000 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@tla.org), * Angelos D. Keromytis (kermit@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 ***