diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2008-05-29 00:28:09 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2008-05-29 00:28:09 +0000 |
commit | b4ce6f58e6b8cf560109ecf401d63df14e2f9431 (patch) | |
tree | cdfcac7fba5c3083114d62c12a0f0ace3517bfcf /sys/net | |
parent | 8427b98770267f5b66e06365860340e78970d0bc (diff) |
rewrite the state table logic.
complete the split off of the layer 3/4 adressing information from the extra
information in the actual state. a state key holds a list of states, and a
state points to two state keys - they're only different in the NAT case.
More specificially, it deprecates the (often difficult to understand)
concept of lan, ext, and gwy addresses, replacing them with WIRE and
STACK side address tuples. (af, proto, saddr, daddr, sport, dport).
Concept first brought up some years ago on a ferry ride in bc by ryan and
me, I spent some time over the last year getting closer, and finally
got it completed in japan with ryan. dlg also took part, helped a lot,
and saved us 8 bytes.
This commit removes support for any kind of NAT as well as pfsync.
It also paves the road for some code simplification and some very cool
future stuff.
ok ryan beck, tested by many
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_pfsync.c | 41 | ||||
-rw-r--r-- | sys/net/pf.c | 948 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 97 | ||||
-rw-r--r-- | sys/net/pfvar.h | 70 |
4 files changed, 544 insertions, 612 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c index 8c70ab56079..518181e8322 100644 --- a/sys/net/if_pfsync.c +++ b/sys/net/if_pfsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.91 2008/05/18 11:54:04 mcbride Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.92 2008/05/29 00:28:07 henning Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -276,7 +276,7 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag) } bzero(st, sizeof(*st)); - if ((sk = pf_alloc_state_key(st)) == NULL) { + if ((sk = pf_alloc_state_key()) == NULL) { pool_put(&pf_state_pl, st); pfi_kif_unref(kif, PFI_KIF_REF_NONE); return (ENOMEM); @@ -293,6 +293,7 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag) return (ENOMEM); } + pf_attach_state(sk, st, 0, PF_SK_BOTH); /* XXX RYAN NAT */ st->rule.ptr = r; /* XXX get pointers to nat_rule and anchor */ @@ -300,11 +301,12 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag) r->states_cur++; r->states_tot++; +#ifdef XXX_HENNING_RYAN_FIXED_PFSYNC /* fill in the rest of the state entry */ pf_state_host_ntoh(&sp->lan, &sk->lan); pf_state_host_ntoh(&sp->gwy, &sk->gwy); pf_state_host_ntoh(&sp->ext, &sk->ext); - +#endif pf_state_peer_ntoh(&sp->src, &st->src); pf_state_peer_ntoh(&sp->dst, &st->dst); @@ -314,7 +316,7 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag) sk->af = sp->af; sk->proto = sp->proto; - sk->direction = sp->direction; + st->direction = sp->direction; st->log = sp->log; st->timeout = sp->timeout; st->allow_opts = sp->allow_opts; @@ -323,7 +325,7 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag) st->creatorid = sp->creatorid; st->sync_flags = PFSTATE_FROMSYNC; - if (pf_insert_state(kif, st)) { + if (pf_state_insert(kif, sk, st)) { pfi_kif_unref(kif, PFI_KIF_REF_NONE); /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */ r->states_cur--; @@ -346,6 +348,7 @@ pfsync_input(struct mbuf *m, ...) struct pfsync_softc *sc = pfsyncif; struct pf_state *st; struct pf_state_key *sk; + struct pf_state_item *si; struct pf_state_cmp id_key; struct pfsync_state *sp; struct pfsync_state_upd *up; @@ -445,15 +448,16 @@ pfsync_input(struct mbuf *m, ...) splx(s); return; } - 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 |= + /* XXX correct? */ + for (sk = RB_MIN(pf_state_tree, + &pf_statetbl); sk; sk = nextsk) { + nextsk = RB_NEXT(pf_state_tree, + &pf_statetbl, sk); + TAILQ_FOREACH(si, &sk->states, entry) { + if (si->s->creatorid == creatorid) { + si->s->sync_flags |= PFSTATE_FROMSYNC; - pf_unlink_state(st); + pf_unlink_state(si->s); } } } @@ -529,7 +533,7 @@ pfsync_input(struct mbuf *m, ...) pfsyncstats.pfsyncs_badstate++; continue; } - sk = st->state_key; + sk = st->key_wire; /* XXX right one? */ sfail = 0; if (sk->proto == IPPROTO_TCP) { /* @@ -666,7 +670,7 @@ pfsync_input(struct mbuf *m, ...) pfsyncstats.pfsyncs_badstate++; continue; } - sk = st->state_key; + sk = st->key_wire; /* XXX right one? */ sfail = 0; if (sk->proto == IPPROTO_TCP) { /* @@ -1118,7 +1122,7 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags) struct pfsync_state *sp = NULL; struct pfsync_state_upd *up = NULL; struct pfsync_state_del *dp = NULL; - struct pf_state_key *sk = st->state_key; + struct pf_state_key *sk = st->key_wire; struct pf_rule *r; u_long secs; int s, ret = 0; @@ -1204,10 +1208,11 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags) sp->creatorid = st->creatorid; strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname)); +#ifdef XXX_HENNING_RYAN_FIXED_PFSYNC pf_state_host_hton(&sk->lan, &sp->lan); pf_state_host_hton(&sk->gwy, &sp->gwy); pf_state_host_hton(&sk->ext, &sp->ext); - +#endif bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); sp->creation = htonl(secs - st->creation); @@ -1225,7 +1230,7 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags) sp->anchor = htonl(r->nr); sp->af = sk->af; sp->proto = sk->proto; - sp->direction = sk->direction; + sp->direction = st->direction; sp->log = st->log; sp->allow_opts = st->allow_opts; sp->timeout = st->timeout; diff --git a/sys/net/pf.c b/sys/net/pf.c index b204c420630..a332e304845 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,8 +1,8 @@ -/* $OpenBSD: pf.c,v 1.575 2008/05/18 11:54:04 mcbride Exp $ */ +/* $OpenBSD: pf.c,v 1.576 2008/05/29 00:28:07 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier - * Copyright (c) 2002,2003 Henning Brauer + * Copyright (c) 2002 - 2008 Henning Brauer * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,8 +98,7 @@ */ /* state tables */ -struct pf_state_tree_lan_ext pf_statetbl_lan_ext; -struct pf_state_tree_ext_gwy pf_statetbl_ext_gwy; +struct pf_state_tree pf_statetbl; struct pf_altqqueue pf_altqs[2]; struct pf_palist pf_pabuf; @@ -125,7 +124,7 @@ struct pf_anchor_stackframe { } pf_anchor_stack[64]; struct pool pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl; -struct pool pf_state_pl, pf_state_key_pl; +struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl; struct pool pf_altq_pl; void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t); @@ -164,9 +163,9 @@ struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *, struct pf_addr *, u_int16_t, struct pf_addr *, u_int16_t, struct pf_addr *, u_int16_t *); -void pf_attach_state(struct pf_state_key *, - struct pf_state *, int); void pf_detach_state(struct pf_state *, int); +void pf_state_key_detach(struct pf_state_key *, + 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, @@ -224,7 +223,7 @@ 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); int pf_src_connlimit(struct pf_state **); -void pf_stateins_err(const char *, struct pf_state *, +void pf_stateins_err(struct pf_state_key *, struct pfi_kif *); int pf_check_congestion(struct ifqueue *); @@ -289,9 +288,7 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = { } 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_key *, - struct pf_state_key *); -static __inline int pf_state_compare_ext_gwy(struct pf_state_key *, +static __inline int pf_state_compare_key(struct pf_state_key *, struct pf_state_key *); static __inline int pf_state_compare_id(struct pf_state *, struct pf_state *); @@ -302,15 +299,11 @@ 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_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, pf_state_key, entry, pf_state_compare_key); RB_GENERATE(pf_state_tree_id, pf_state, entry_id, pf_state_compare_id); -#define PF_DT_SKIP_LANEXT 0x01 -#define PF_DT_SKIP_EXTGWY 0x02 +#define PF_DT_SKIP_STATETREE 0x01 static __inline int pf_src_compare(struct pf_src_node *a, struct pf_src_node *b) @@ -356,157 +349,6 @@ pf_src_compare(struct pf_src_node *a, struct pf_src_node *b) return (0); } -static __inline int -pf_state_compare_lan_ext(struct pf_state_key *a, struct pf_state_key *b) -{ - int diff; - - if ((diff = a->proto - b->proto) != 0) - return (diff); - if ((diff = a->af - b->af) != 0) - return (diff); - switch (a->af) { -#ifdef INET - case AF_INET: - if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0]) - return (1); - if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0]) - return (-1); - if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0]) - return (1); - if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0]) - return (-1); - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - if (a->lan.addr.addr32[3] > b->lan.addr.addr32[3]) - return (1); - if (a->lan.addr.addr32[3] < b->lan.addr.addr32[3]) - return (-1); - if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3]) - return (1); - if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3]) - return (-1); - if (a->lan.addr.addr32[2] > b->lan.addr.addr32[2]) - return (1); - if (a->lan.addr.addr32[2] < b->lan.addr.addr32[2]) - return (-1); - if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2]) - return (1); - if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2]) - return (-1); - if (a->lan.addr.addr32[1] > b->lan.addr.addr32[1]) - return (1); - if (a->lan.addr.addr32[1] < b->lan.addr.addr32[1]) - return (-1); - if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1]) - return (1); - if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1]) - return (-1); - if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0]) - return (1); - if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0]) - return (-1); - if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0]) - return (1); - if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0]) - return (-1); - break; -#endif /* INET6 */ - } - - if ((diff = a->lan.port - b->lan.port) != 0) - return (diff); - if ((diff = a->ext.port - b->ext.port) != 0) - return (diff); - - return (0); -} - -static __inline int -pf_state_compare_ext_gwy(struct pf_state_key *a, struct pf_state_key *b) -{ - int diff; - - if ((diff = a->proto - b->proto) != 0) - return (diff); - if ((diff = a->af - b->af) != 0) - return (diff); - switch (a->af) { -#ifdef INET - case AF_INET: - if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0]) - return (1); - if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0]) - return (-1); - if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0]) - return (1); - if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0]) - return (-1); - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3]) - return (1); - if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3]) - return (-1); - if (a->gwy.addr.addr32[3] > b->gwy.addr.addr32[3]) - return (1); - if (a->gwy.addr.addr32[3] < b->gwy.addr.addr32[3]) - return (-1); - if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2]) - return (1); - if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2]) - return (-1); - if (a->gwy.addr.addr32[2] > b->gwy.addr.addr32[2]) - return (1); - if (a->gwy.addr.addr32[2] < b->gwy.addr.addr32[2]) - return (-1); - if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1]) - return (1); - if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1]) - return (-1); - if (a->gwy.addr.addr32[1] > b->gwy.addr.addr32[1]) - return (1); - if (a->gwy.addr.addr32[1] < b->gwy.addr.addr32[1]) - return (-1); - if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0]) - return (1); - if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0]) - return (-1); - if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0]) - return (1); - if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0]) - return (-1); - break; -#endif /* INET6 */ - } - - if ((diff = a->ext.port - b->ext.port) != 0) - return (diff); - if ((diff = a->gwy.port - b->gwy.port) != 0) - return (diff); - - return (0); -} - -static __inline int -pf_state_compare_id(struct pf_state *a, struct pf_state *b) -{ - if (a->id > b->id) - return (1); - if (a->id < b->id) - return (-1); - if (a->creatorid > b->creatorid) - return (1); - if (a->creatorid < b->creatorid) - return (-1); - - return (0); -} - #ifdef INET6 void pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af) @@ -527,77 +369,6 @@ pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af) } #endif /* INET6 */ -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(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir) -{ - struct pf_state_key *sk; - struct pf_state *s; - - pf_status.fcounters[FCNT_STATE_SEARCH]++; - - switch (dir) { - case PF_OUT: - sk = RB_FIND(pf_state_tree_lan_ext, &pf_statetbl_lan_ext, - (struct pf_state_key *)key); - break; - case PF_IN: - sk = RB_FIND(pf_state_tree_ext_gwy, &pf_statetbl_ext_gwy, - (struct pf_state_key *)key); - break; - default: - 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_key_cmp *key, u_int dir, int *more) -{ - struct pf_state_key *sk; - struct pf_state *s, *ret = NULL; - - pf_status.fcounters[FCNT_STATE_SEARCH]++; - - switch (dir) { - case PF_OUT: - sk = RB_FIND(pf_state_tree_lan_ext, - &pf_statetbl_lan_ext, (struct pf_state_key *)key); - break; - case PF_IN: - 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 pf_init_threshold(struct pf_threshold *threshold, u_int32_t limit, u_int32_t seconds) @@ -661,12 +432,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)->state_key->af); + (*state)->key_wire->af); } bzero(&p, sizeof(p)); - p.pfra_af = (*state)->state_key->af; - switch ((*state)->state_key->af) { + p.pfra_af = (*state)->key_wire->af; + switch ((*state)->key_wire->af) { #ifdef INET case AF_INET: p.pfra_net = 32; @@ -691,21 +462,21 @@ pf_src_connlimit(struct pf_state **state) pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++; RB_FOREACH(st, pf_state_tree_id, &tree_id) { - sk = st->state_key; + sk = st->key_wire; /* * Kill states from this source. (Only those * from the same rule if PF_FLUSH_GLOBAL is not * set) */ if (sk->af == - (*state)->state_key->af && - (((*state)->state_key->direction == - PF_OUT && + (*state)->key_wire->af && + (((*state)->direction == + PF_OUT && PF_AEQ(&(*state)->src_node->addr, - &sk->lan.addr, sk->af)) || - ((*state)->state_key->direction == PF_IN && + &sk->addr1, sk->af)) || + ((*state)->direction == PF_IN && PF_AEQ(&(*state)->src_node->addr, - &sk->ext.addr, sk->af))) && + &sk->addr2, sk->af))) && ((*state)->rule.ptr->flush & PF_FLUSH_GLOBAL || (*state)->rule.ptr == st->rule.ptr)) { @@ -793,57 +564,194 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule, } void -pf_stateins_err(const char *tree, struct pf_state *s, struct pfi_kif *kif) +pf_stateins_err(struct pf_state_key *sk, 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, + printf("pf: state insert failed: %s", kif->pfik_name); + printf(" addr1: "); + pf_print_host(&sk->addr1, sk->port1, sk->af); - printf(" gwy: "); - pf_print_host(&sk->gwy.addr, sk->gwy.port, + printf(" addr2: "); + pf_print_host(&sk->addr2, sk->port2, 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"); } } +/* state table stuff */ + +static __inline int +pf_state_compare_key(struct pf_state_key *a, struct pf_state_key *b) +{ + int diff; + + if ((diff = a->proto - b->proto) != 0) + return (diff); + if ((diff = a->af - b->af) != 0) + return (diff); + switch (a->af) { +#ifdef INET + case AF_INET: + if (a->addr1.addr32[0] > b->addr1.addr32[0]) + return (1); + if (a->addr1.addr32[0] < b->addr1.addr32[0]) + return (-1); + if (a->addr2.addr32[0] > b->addr2.addr32[0]) + return (1); + if (a->addr2.addr32[0] < b->addr2.addr32[0]) + return (-1); + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + if (a->addr1.addr32[3] > b->addr1.addr32[3]) + return (1); + if (a->addr1.addr32[3] < b->addr1.addr32[3]) + return (-1); + if (a->addr2.addr32[3] > b->addr2.addr32[3]) + return (1); + if (a->addr2.addr32[3] < b->addr2.addr32[3]) + return (-1); + if (a->addr1.addr32[2] > b->addr1.addr32[2]) + return (1); + if (a->addr1.addr32[2] < b->addr1.addr32[2]) + return (-1); + if (a->addr2.addr32[2] > b->addr2.addr32[2]) + return (1); + if (a->addr2.addr32[2] < b->addr2.addr32[2]) + return (-1); + if (a->addr1.addr32[1] > b->addr1.addr32[1]) + return (1); + if (a->addr1.addr32[1] < b->addr1.addr32[1]) + return (-1); + if (a->addr2.addr32[1] > b->addr2.addr32[1]) + return (1); + if (a->addr2.addr32[1] < b->addr2.addr32[1]) + return (-1); + if (a->addr1.addr32[0] > b->addr1.addr32[0]) + return (1); + if (a->addr1.addr32[0] < b->addr1.addr32[0]) + return (-1); + if (a->addr2.addr32[0] > b->addr2.addr32[0]) + return (1); + if (a->addr2.addr32[0] < b->addr2.addr32[0]) + return (-1); + break; +#endif /* INET6 */ + } + + if ((diff = a->port1 - b->port1) != 0) + return (diff); + if ((diff = a->port2 - b->port2) != 0) + return (diff); + + return (0); +} + +static __inline int +pf_state_compare_id(struct pf_state *a, struct pf_state *b) +{ + if (a->id > b->id) + return (1); + if (a->id < b->id) + return (-1); + if (a->creatorid > b->creatorid) + return (1); + if (a->creatorid < b->creatorid) + return (-1); + + return (0); +} + +void +pf_attach_state(struct pf_state_key *sk, struct pf_state *s, int tail, + int where) +{ + struct pf_state_item *si; + + if (where == PF_SK_WIRE || where == PF_SK_BOTH) + s->key_wire = sk; + if (where == PF_SK_STACK || where == PF_SK_BOTH) + s->key_stack = sk; + + si = pool_get(&pf_state_item_pl, PR_NOWAIT); + si->s = s; + + /* list is sorted, if-bound states before floating */ + if (tail) + TAILQ_INSERT_TAIL(&sk->states, si, entry); + else + TAILQ_INSERT_HEAD(&sk->states, si, entry); +} + +void +pf_detach_state(struct pf_state *s, int flags) +{ + if (s->key_wire == s->key_stack) { + pf_state_key_detach(s->key_wire, s, flags); + s->key_wire = s->key_stack = NULL; + } else { + pf_state_key_detach(s->key_stack, s, flags); + pf_state_key_detach(s->key_wire, s, flags); + s->key_wire = s->key_stack = NULL; + } +} + +void +pf_state_key_detach(struct pf_state_key *sk, struct pf_state *s, int flags) +{ + struct pf_state_item *si; + + for (si = TAILQ_FIRST(&sk->states); si->s != s; + si = TAILQ_NEXT(si, entry)); + +/* XXX DEBUG */ if (!si) { printf("pf_state_key_detach, si NULL\n"); } + + TAILQ_REMOVE(&sk->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); + pool_put(&pf_state_key_pl, sk); + } +} + +struct pf_state_key * +pf_alloc_state_key(void) +{ + struct pf_state_key *sk; + + if ((sk = pool_get(&pf_state_key_pl, PR_NOWAIT)) == NULL) + return (NULL); + bzero(sk, sizeof(*sk)); + TAILQ_INIT(&sk->states); + + return (sk); +} + int -pf_insert_state(struct pfi_kif *kif, struct pf_state *s) +pf_state_insert(struct pfi_kif *kif, struct pf_state_key *sk, + struct pf_state *s) { struct pf_state_key *cur; - struct pf_state *sp; + struct pf_state_item *si; - 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) { + if ((cur = RB_INSERT(pf_state_tree, &pf_statetbl, sk)) != 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); - pf_detach_state(s, - PF_DT_SKIP_LANEXT|PF_DT_SKIP_EXTGWY); + TAILQ_FOREACH(si, &cur->states, entry) + if (si->s->kif == kif && + si->s->direction == s->direction) { + /* collision! */ + pf_stateins_err(sk, kif); + pf_detach_state(s, PF_DT_SKIP_STATETREE); 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 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); + pf_detach_state(s, PF_DT_SKIP_STATETREE); + /* RYAN PF_SK_BOTH not gut for nat shitz */ + pf_attach_state(cur, s, kif == pfi_all ? 1 : 0, PF_SK_BOTH); } if (s->id == 0 && s->creatorid == 0) { @@ -867,11 +775,65 @@ pf_insert_state(struct pfi_kif *kif, struct pf_state *s) pf_status.states++; pfi_kif_ref(kif, PFI_KIF_REF_STATE); #if NPFSYNC +#ifdef XXX_PFSYNC_FIXED pfsync_insert_state(s); #endif +#endif return (0); } +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(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir) +{ + struct pf_state_key *sk; + struct pf_state_item *si; + + pf_status.fcounters[FCNT_STATE_SEARCH]++; + + if ((sk = RB_FIND(pf_state_tree, &pf_statetbl, + (struct pf_state_key *)key)) == NULL) + return (NULL); + + /* list is sorted, if-bound states before floating ones */ + TAILQ_FOREACH(si, &sk->states, entry) + if ((si->s->kif == pfi_all || si->s->kif == kif) && + ((dir == si->s->direction && si->s->key_wire == sk) || + (dir != si->s->direction && si->s->key_stack == sk))) + return (si->s); + return (NULL); +} + +struct pf_state * +pf_find_state_all(struct pf_state_key_cmp *key, u_int dir, int *more) +{ + struct pf_state_key *sk; + struct pf_state_item *si, *ret = NULL; + + pf_status.fcounters[FCNT_STATE_SEARCH]++; + + sk = RB_FIND(pf_state_tree, &pf_statetbl, (struct pf_state_key *)key); + + if (sk != NULL) { + ret = TAILQ_FIRST(&sk->states); + if (more != NULL) + TAILQ_FOREACH(si, &sk->states, entry) + (*more)++; + } + + return (ret ? ret->s : NULL); +} + +/* END state table stuff */ + + void pf_purge_thread(void *v) { @@ -1000,9 +962,10 @@ void pf_unlink_state(struct pf_state *cur) { if (cur->src.state == PF_TCPS_PROXY_DST) { - 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, + /* XXX wire key the right one? */ + pf_send_tcp(cur->rule.ptr, cur->key_wire->af, + &cur->key_wire->addr2, &cur->key_wire->addr1, + cur->key_wire->port2, cur->key_wire->port1, cur->src.seqhi, cur->src.seqlo + 1, TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL); } @@ -1189,7 +1152,7 @@ pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af) void pf_print_state(struct pf_state *s) { - struct pf_state_key *sk = s->state_key; + struct pf_state_key *sk = s->key_wire; switch (sk->proto) { case IPPROTO_TCP: printf("TCP "); @@ -1207,11 +1170,13 @@ pf_print_state(struct pf_state *s) printf("%u ", sk->proto); break; } - pf_print_host(&sk->lan.addr, sk->lan.port, sk->af); + pf_print_host(&sk->addr1, sk->port1, sk->af); printf(" "); - pf_print_host(&sk->gwy.addr, sk->gwy.port, sk->af); + pf_print_host(&sk->addr2, sk->port2, sk->af); +#ifdef RYAN_NAT printf(" "); - pf_print_host(&sk->ext.addr, sk->ext.port, sk->af); + pf_print_host(&sk->addr2, sk->ext.port, sk->af); +#endif printf(" [lo=%u high=%u win=%u modulator=%u", s->src.seqlo, s->src.seqhi, s->src.max_win, s->src.seqdiff); if (s->src.wscale && s->dst.wscale) @@ -2289,6 +2254,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high, struct pf_src_node **sn) { +#ifdef RYAN_NAT struct pf_state_key_cmp key; struct pf_addr init_addr; u_int16_t cut; @@ -2305,9 +2271,9 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, do { key.af = af; key.proto = proto; - PF_ACPY(&key.ext.addr, daddr, key.af); - PF_ACPY(&key.gwy.addr, naddr, key.af); - key.ext.port = dport; + PF_ACPY(&key.addr2, daddr, key.af); + PF_ACPY(&key.addr1, naddr, key.af); + key.port2 = dport; /* * port search; start random, step; @@ -2370,7 +2336,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, return (1); } } while (! PF_AEQ(&init_addr, naddr, af) ); - +#endif return (1); /* none available */ } @@ -2821,7 +2787,7 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr) s->rt_kif = NULL; if (!r->rt || r->rt == PF_FASTROUTE) return; - switch (s->state_key->af) { + switch (s->key_wire->af) { #ifdef INET case AF_INET: pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, @@ -2839,53 +2805,6 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr) } } -void -pf_attach_state(struct pf_state_key *sk, struct pf_state *s, int tail) -{ - s->state_key = sk; - - /* list is sorted, if-bound states before floating */ - if (tail) - TAILQ_INSERT_TAIL(&sk->states, s, next); - else - TAILQ_INSERT_HEAD(&sk->states, s, next); -} - -void -pf_detach_state(struct pf_state *s, int flags) -{ - struct pf_state_key *sk = s->state_key; - - if (sk == NULL) - return; - - s->state_key = NULL; - TAILQ_REMOVE(&sk->states, s, next); - if (TAILQ_EMPTY(&sk->states)) { - if (!(flags & PF_DT_SKIP_EXTGWY)) - RB_REMOVE(pf_state_tree_ext_gwy, - &pf_statetbl_ext_gwy, sk); - if (!(flags & PF_DT_SKIP_LANEXT)) - RB_REMOVE(pf_state_tree_lan_ext, - &pf_statetbl_lan_ext, sk); - pool_put(&pf_state_key_pl, sk); - } -} - -struct pf_state_key * -pf_alloc_state_key(struct pf_state *s) -{ - struct pf_state_key *sk; - - if ((sk = pool_get(&pf_state_key_pl, PR_NOWAIT)) == NULL) - return (NULL); - bzero(sk, sizeof(*sk)); - TAILQ_INIT(&sk->states); - pf_attach_state(sk, s, 0); - - return (sk); -} - u_int32_t pf_tcp_iss(struct pf_pdesc *pd) { @@ -3327,6 +3246,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, return (PF_DROP); } +/* XXX state creation should be really factored out */ if (!state_icmp && (r->keep_state || nr != NULL || (pd->flags & PFDESC_TCP_NORM))) { /* create new state */ @@ -3475,64 +3395,56 @@ cleanup: return (PF_DROP); } } + s->direction = direction; - if ((sk = pf_alloc_state_key(s)) == NULL) { + if ((sk = pf_alloc_state_key()) == NULL) { REASON_SET(&reason, PFRES_MEMORY); goto cleanup; } - sk->proto = pd->proto; - sk->direction = direction; sk->af = af; - if (direction == PF_OUT) { - PF_ACPY(&sk->gwy.addr, saddr, af); - PF_ACPY(&sk->ext.addr, daddr, af); + if (direction == PF_IN) { + PF_ACPY(&sk->addr1, saddr, af); + PF_ACPY(&sk->addr2, daddr, af); switch (pd->proto) { case IPPROTO_ICMP: #ifdef INET6 case IPPROTO_ICMPV6: #endif - sk->gwy.port = nport; - sk->ext.port = 0; + sk->port1 = nport; + sk->port2 = 0; break; default: - sk->gwy.port = sport; - sk->ext.port = dport; + sk->port1 = sport; + sk->port2 = dport; } if (nr != NULL) { - PF_ACPY(&sk->lan.addr, &pd->baddr, af); - sk->lan.port = bport; - } else { - PF_ACPY(&sk->lan.addr, &sk->gwy.addr, af); - sk->lan.port = sk->gwy.port; +/* RYAN NAT */ } } else { - PF_ACPY(&sk->lan.addr, daddr, af); - PF_ACPY(&sk->ext.addr, saddr, af); + PF_ACPY(&sk->addr2, saddr, af); + PF_ACPY(&sk->addr1, daddr, af); switch (pd->proto) { case IPPROTO_ICMP: #ifdef INET6 case IPPROTO_ICMPV6: #endif - sk->lan.port = nport; - sk->ext.port = 0; + sk->port2 = nport; + sk->port1 = 0; break; default: - sk->lan.port = dport; - sk->ext.port = sport; + sk->port2 = sport; + sk->port1 = dport; } if (nr != NULL) { - PF_ACPY(&sk->gwy.addr, &pd->baddr, af); - sk->gwy.port = bport; - } else { - PF_ACPY(&sk->gwy.addr, &sk->lan.addr, af); - sk->gwy.port = sk->lan.port; +/* RYAN NAT */ } } + pf_attach_state(sk, s, 0, PF_SK_BOTH); pf_set_rt_ifp(s, saddr); /* needs s->state_key set */ - if (pf_insert_state(BOUND_IFACE(r, kif), s)) { + if (pf_state_insert(BOUND_IFACE(r, kif), sk, s)) { if (pd->proto == IPPROTO_TCP) pf_normalize_tcp_cleanup(s); REASON_SET(&reason, PFRES_STATEINS); @@ -3687,21 +3599,21 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd->af; key.proto = IPPROTO_TCP; - if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd->src, key.af); - PF_ACPY(&key.gwy.addr, pd->dst, key.af); - key.ext.port = th->th_sport; - key.gwy.port = th->th_dport; - } else { - PF_ACPY(&key.lan.addr, pd->src, key.af); - PF_ACPY(&key.ext.addr, pd->dst, key.af); - key.lan.port = th->th_sport; - key.ext.port = th->th_dport; + if (direction == PF_IN) { /* wire side, straight */ + PF_ACPY(&key.addr1, pd->src, key.af); + PF_ACPY(&key.addr2, pd->dst, key.af); + key.port1 = th->th_sport; + key.port2 = th->th_dport; + } else { /* stack side, reverse */ + PF_ACPY(&key.addr2, pd->src, key.af); + PF_ACPY(&key.addr1, pd->dst, key.af); + key.port2 = th->th_sport; + key.port1 = th->th_dport; } STATE_LOOKUP(); - if (direction == (*state)->state_key->direction) { + if (direction == (*state)->direction) { src = &(*state)->src; dst = &(*state)->dst; } else { @@ -3710,7 +3622,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, } if ((*state)->src.state == PF_TCPS_PROXY_SRC) { - if (direction != (*state)->state_key->direction) { + if (direction != (*state)->direction) { REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } @@ -3739,16 +3651,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, (*state)->src.state = PF_TCPS_PROXY_DST; } if ((*state)->src.state == PF_TCPS_PROXY_DST) { - struct pf_state_host *src, *dst; - - if (direction == PF_OUT) { - src = &(*state)->state_key->gwy; - dst = &(*state)->state_key->ext; - } else { - src = &(*state)->state_key->ext; - dst = &(*state)->state_key->lan; - } - if (direction == (*state)->state_key->direction) { + if (direction == (*state)->direction) { if (((th->th_flags & (TH_SYN|TH_ACK)) != TH_ACK) || (ntohl(th->th_ack) != (*state)->src.seqhi + 1) || (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) { @@ -3758,8 +3661,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, (*state)->src.max_win = MAX(ntohs(th->th_win), 1); if ((*state)->dst.seqhi == 1) (*state)->dst.seqhi = htonl(arc4random()); - pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr, - &dst->addr, src->port, dst->port, + pf_send_tcp((*state)->rule.ptr, pd->af, &key.addr1, + &key.addr2, key.port1, key.port2, (*state)->dst.seqhi, 0, TH_SYN, 0, (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL); REASON_SET(reason, PFRES_SYNPROXY); @@ -3777,8 +3680,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, ntohl(th->th_ack), ntohl(th->th_seq) + 1, TH_ACK, (*state)->src.max_win, 0, 0, 0, (*state)->tag, NULL, NULL); - pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr, - &dst->addr, src->port, dst->port, + pf_send_tcp((*state)->rule.ptr, pd->af, &key.addr1, + &key.addr2, key.port1, key.port2, (*state)->src.seqhi + 1, (*state)->src.seqlo + 1, TH_ACK, (*state)->dst.max_win, 0, 0, 1, 0, NULL, NULL); @@ -4059,7 +3962,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, pd->p_len, ackskew, (*state)->packets[0], (*state)->packets[1], direction == PF_IN ? "in" : "out", - direction == (*state)->state_key->direction ? + direction == (*state)->direction ? "fwd" : "rev"); } @@ -4115,7 +4018,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, seq, orig_seq, ack, pd->p_len, ackskew, (*state)->packets[0], (*state)->packets[1], direction == PF_IN ? "in" : "out", - direction == (*state)->state_key->direction ? + direction == (*state)->direction ? "fwd" : "rev"); printf("pf: State failure on: %c %c %c %c | %c %c\n", SEQ_GEQ(src->seqhi, end) ? ' ' : '1', @@ -4132,6 +4035,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, /* Any packets which have gotten here are to be passed */ + +#ifdef RYAN_NAT /* translate source/destination address, if necessary */ if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_OUT) @@ -4140,13 +4045,15 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, (*state)->state_key->gwy.port, 0, pd->af); else pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum, - &th->th_sum, &(*state)->state_key->lan.addr, + &th->th_sum, &(*state)->state_key->addr1, (*state)->state_key->lan.port, 0, pd->af); - m_copyback(m, off, sizeof(*th), th); - } else if (copyback) { - /* Copyback sequence modulation or stateful scrub changes */ - m_copyback(m, off, sizeof(*th), th); + copyback = 1; } +#endif + + /* Copyback sequence modulation or stateful scrub changes if needed */ + if (copyback) + m_copyback(m, off, sizeof(*th), th); return (PF_PASS); } @@ -4161,21 +4068,21 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd->af; key.proto = IPPROTO_UDP; - if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd->src, key.af); - PF_ACPY(&key.gwy.addr, pd->dst, key.af); - key.ext.port = uh->uh_sport; - key.gwy.port = uh->uh_dport; - } else { - PF_ACPY(&key.lan.addr, pd->src, key.af); - PF_ACPY(&key.ext.addr, pd->dst, key.af); - key.lan.port = uh->uh_sport; - key.ext.port = uh->uh_dport; + if (direction == PF_IN) { /* wire side, straight */ + PF_ACPY(&key.addr1, pd->src, key.af); + PF_ACPY(&key.addr2, pd->dst, key.af); + key.port1 = uh->uh_sport; + key.port2 = uh->uh_dport; + } else { /* stack side, reverse */ + PF_ACPY(&key.addr2, pd->src, key.af); + PF_ACPY(&key.addr1, pd->dst, key.af); + key.port2 = uh->uh_sport; + key.port1 = uh->uh_dport; } STATE_LOOKUP(); - if (direction == (*state)->state_key->direction) { + if (direction == (*state)->direction) { src = &(*state)->src; dst = &(*state)->dst; } else { @@ -4196,6 +4103,7 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif, else (*state)->timeout = PFTM_UDP_SINGLE; +#ifdef RYAN_NAT /* translate source/destination address, if necessary */ if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_OUT) @@ -4204,10 +4112,11 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif, (*state)->state_key->gwy.port, 1, pd->af); else pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum, - &uh->uh_sum, &(*state)->state_key->lan.addr, + &uh->uh_sum, &(*state)->state_key->addr1, (*state)->state_key->lan.port, 1, pd->af); m_copyback(m, off, sizeof(*uh), uh); } +#endif return (PF_PASS); } @@ -4216,7 +4125,6 @@ int pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason) { - struct pf_addr *saddr = pd->src, *daddr = pd->dst; u_int16_t icmpid, *icmpsum; u_int8_t icmptype; int state_icmp = 0; @@ -4260,16 +4168,16 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, */ key.af = pd->af; key.proto = pd->proto; - if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd->src, key.af); - PF_ACPY(&key.gwy.addr, pd->dst, key.af); - key.ext.port = 0; - key.gwy.port = icmpid; - } else { - PF_ACPY(&key.lan.addr, pd->src, key.af); - PF_ACPY(&key.ext.addr, pd->dst, key.af); - key.lan.port = icmpid; - key.ext.port = 0; + if (direction == PF_IN) { /* wire side, straight */ + PF_ACPY(&key.addr1, pd->src, key.af); + PF_ACPY(&key.addr2, pd->dst, key.af); + key.port1 = icmpid; + key.port2 = 0; + } else { /* stack side, reverse */ + PF_ACPY(&key.addr2, pd->src, key.af); + PF_ACPY(&key.addr1, pd->dst, key.af); + key.port2 = 0; + key.port1 = icmpid; } STATE_LOOKUP(); @@ -4277,6 +4185,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, (*state)->expire = time_second; (*state)->timeout = PFTM_ICMP_ERROR_REPLY; +#ifdef RYAN_NAT /* translate source/destination address, if necessary */ if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_OUT) { @@ -4313,7 +4222,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, case AF_INET: pf_change_a(&daddr->v4.s_addr, pd->ip_sum, - (*state)->state_key->lan.addr.v4.s_addr, 0); + (*state)->state_key->addr1.v4.s_addr, 0); pd->hdr.icmp->icmp_cksum = pf_cksum_fixup( pd->hdr.icmp->icmp_cksum, icmpid, @@ -4328,7 +4237,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, case AF_INET6: pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum, - &(*state)->state_key->lan.addr, 0); + &(*state)->state_key->addr1, 0); m_copyback(m, off, sizeof(struct icmp6_hdr), pd->hdr.icmp6); @@ -4337,7 +4246,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, } } } - +#endif /* RYAN_NAT */ return (PF_PASS); } else { @@ -4468,21 +4377,21 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd2.af; key.proto = IPPROTO_TCP; - if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd2.dst, key.af); - PF_ACPY(&key.gwy.addr, pd2.src, key.af); - key.ext.port = th.th_dport; - key.gwy.port = th.th_sport; - } else { - PF_ACPY(&key.lan.addr, pd2.dst, key.af); - PF_ACPY(&key.ext.addr, pd2.src, key.af); - key.lan.port = th.th_dport; - key.ext.port = th.th_sport; + if (direction == PF_IN) { /* wire, straight */ + PF_ACPY(&key.addr1, pd2.src, key.af); + PF_ACPY(&key.addr2, pd2.dst, key.af); + key.port1 = th.th_sport; + key.port2 = th.th_dport; + } else { /* stack, reverse */ + PF_ACPY(&key.addr2, pd2.src, key.af); + PF_ACPY(&key.addr1, pd2.dst, key.af); + key.port2 = th.th_sport; + key.port1 = th.th_dport; } STATE_LOOKUP(); - if (direction == (*state)->state_key->direction) { + if (direction == (*state)->direction) { src = &(*state)->dst; dst = &(*state)->src; } else { @@ -4519,10 +4428,11 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, return (PF_DROP); } +#ifdef RYAN_NAT if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_IN) { pf_change_icmp(pd2.src, &th.th_sport, - daddr, &(*state)->state_key->lan.addr, + daddr, &(*state)->state_key->addr1, (*state)->state_key->lan.port, NULL, pd2.ip_sum, icmpsum, pd->ip_sum, 0, pd2.af); @@ -4535,7 +4445,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, } copyback = 1; } - +#endif if (copyback) { switch (pd2.af) { #ifdef INET @@ -4575,25 +4485,25 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd2.af; key.proto = IPPROTO_UDP; - if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd2.dst, key.af); - PF_ACPY(&key.gwy.addr, pd2.src, key.af); - key.ext.port = uh.uh_dport; - key.gwy.port = uh.uh_sport; - } else { - PF_ACPY(&key.lan.addr, pd2.dst, key.af); - PF_ACPY(&key.ext.addr, pd2.src, key.af); - key.lan.port = uh.uh_dport; - key.ext.port = uh.uh_sport; + if (direction == PF_IN) { /* wire, straight */ + PF_ACPY(&key.addr1, pd2.src, key.af); + PF_ACPY(&key.addr2, pd2.dst, key.af); + key.port1 = uh.uh_sport; + key.port2 = uh.uh_dport; + } else { /* stack, reverse */ + PF_ACPY(&key.addr2, pd2.src, key.af); + PF_ACPY(&key.addr1, pd2.dst, key.af); + key.port2 = uh.uh_sport; + key.port1 = uh.uh_dport; } STATE_LOOKUP(); - +#ifdef RYAN_NAT if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_IN) { pf_change_icmp(pd2.src, &uh.uh_sport, daddr, - &(*state)->state_key->lan.addr, + &(*state)->state_key->addr1, (*state)->state_key->lan.port, &uh.uh_sum, pd2.ip_sum, icmpsum, @@ -4626,7 +4536,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, } m_copyback(m, off2, sizeof(uh), &uh); } - +#endif return (PF_PASS); break; } @@ -4644,25 +4554,32 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd2.af; key.proto = IPPROTO_ICMP; - if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd2.dst, key.af); - PF_ACPY(&key.gwy.addr, pd2.src, key.af); - key.ext.port = 0; - key.gwy.port = iih.icmp_id; - } else { - PF_ACPY(&key.lan.addr, pd2.dst, key.af); - PF_ACPY(&key.ext.addr, pd2.src, key.af); - key.lan.port = iih.icmp_id; - key.ext.port = 0; + if (direction == PF_IN) { /* wire, straight */ + PF_ACPY(&key.addr1, pd2.src, key.af); + PF_ACPY(&key.addr2, pd2.dst, key.af); + key.port1 = 0; + key.port2 = iih.icmp_id; + } else { /* stack, reverse */ + PF_ACPY(&key.addr2, pd2.src, key.af); + PF_ACPY(&key.addr1, pd2.dst, key.af); + key.port2 = 0; + key.port1 = iih.icmp_id; } +printf("pf: state search icmp repl: %s", kif->pfik_name); +printf(" addr1: "); +pf_print_host(&key.addr1, key.port1, pd->af); +printf(" addr2: "); +pf_print_host(&key.addr2, key.port2, pd->af); +printf("\n"); STATE_LOOKUP(); +#ifdef RYAN_NAT if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_IN) { pf_change_icmp(pd2.src, &iih.icmp_id, daddr, - &(*state)->state_key->lan.addr, + &(*state)->state_key->addr1, (*state)->state_key->lan.port, NULL, pd2.ip_sum, icmpsum, pd->ip_sum, 0, AF_INET); @@ -4678,7 +4595,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, m_copyback(m, ipoff2, sizeof(h2), &h2); m_copyback(m, off2, ICMP_MINLEN, &iih); } - +#endif return (PF_PASS); break; } @@ -4698,24 +4615,25 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd2.af; key.proto = IPPROTO_ICMPV6; if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd2.dst, key.af); - PF_ACPY(&key.gwy.addr, pd2.src, key.af); - key.ext.port = 0; - key.gwy.port = iih.icmp6_id; + PF_ACPY(&key.addr1, pd2.dst, key.af); + PF_ACPY(&key.addr2, pd2.src, key.af); + key.port1 = 0; + key.port2 = iih.icmp6_id; } else { - PF_ACPY(&key.lan.addr, pd2.dst, key.af); - PF_ACPY(&key.ext.addr, pd2.src, key.af); - key.lan.port = iih.icmp6_id; - key.ext.port = 0; + PF_ACPY(&key.addr2, pd2.src, key.af); + PF_ACPY(&key.addr1, pd2.dst, key.af); + key.port2 = 0; + key.port1 = iih.icmp6_id; } STATE_LOOKUP(); +#ifdef RYAN_NAT if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_IN) { pf_change_icmp(pd2.src, &iih.icmp6_id, daddr, - &(*state)->state_key->lan.addr, + &(*state)->state_key->addr1, (*state)->state_key->lan.port, NULL, pd2.ip_sum, icmpsum, pd->ip_sum, 0, AF_INET6); @@ -4732,7 +4650,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, m_copyback(m, off2, sizeof(struct icmp6_hdr), &iih); } - +#endif return (PF_PASS); break; } @@ -4741,24 +4659,25 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd2.af; key.proto = pd2.proto; if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd2.dst, key.af); - PF_ACPY(&key.gwy.addr, pd2.src, key.af); - key.ext.port = 0; - key.gwy.port = 0; + PF_ACPY(&key.addr1, pd2.src, key.af); + PF_ACPY(&key.addr2, pd2.dst, key.af); + key.port1 = 0; + key.port2 = 0; } else { - PF_ACPY(&key.lan.addr, pd2.dst, key.af); - PF_ACPY(&key.ext.addr, pd2.src, key.af); - key.lan.port = 0; - key.ext.port = 0; + PF_ACPY(&key.addr2, pd2.src, key.af); + PF_ACPY(&key.addr1, pd2.dst, key.af); + key.port2 = 0; + key.port1 = 0; } STATE_LOOKUP(); +#ifdef RYAN_NAT if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_IN) { pf_change_icmp(pd2.src, NULL, daddr, - &(*state)->state_key->lan.addr, + &(*state)->state_key->addr1, 0, NULL, pd2.ip_sum, icmpsum, pd->ip_sum, 0, pd2.af); @@ -4789,7 +4708,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, #endif /* INET6 */ } } - +#endif return (PF_PASS); break; } @@ -4807,20 +4726,20 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif, key.af = pd->af; key.proto = pd->proto; if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, pd->src, key.af); - PF_ACPY(&key.gwy.addr, pd->dst, key.af); - key.ext.port = 0; - key.gwy.port = 0; + PF_ACPY(&key.addr1, pd->src, key.af); + PF_ACPY(&key.addr2, pd->dst, key.af); + key.port1 = 0; + key.port2 = 0; } else { - PF_ACPY(&key.lan.addr, pd->src, key.af); - PF_ACPY(&key.ext.addr, pd->dst, key.af); - key.lan.port = 0; - key.ext.port = 0; + PF_ACPY(&key.addr2, pd->src, key.af); + PF_ACPY(&key.addr1, pd->dst, key.af); + key.port2 = 0; + key.port1 = 0; } STATE_LOOKUP(); - if (direction == (*state)->state_key->direction) { + if (direction == (*state)->direction) { src = &(*state)->src; dst = &(*state)->dst; } else { @@ -4841,6 +4760,7 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif, else (*state)->timeout = PFTM_OTHER_SINGLE; +#ifdef RYAN_NAT /* translate source/destination address, if necessary */ if (STATE_TRANSLATE((*state)->state_key)) { if (direction == PF_OUT) @@ -4866,19 +4786,19 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif, case AF_INET: pf_change_a(&pd->dst->v4.s_addr, pd->ip_sum, - (*state)->state_key->lan.addr.v4.s_addr, + (*state)->state_key->addr1.v4.s_addr, 0); break; #endif /* INET */ #ifdef INET6 case AF_INET6: PF_ACPY(pd->dst, - &(*state)->state_key->lan.addr, pd->af); + &(*state)->state_key->addr1, pd->af); break; #endif /* INET6 */ } } - +#endif return (PF_PASS); } @@ -5498,7 +5418,6 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct ip *h; struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr; struct pf_state *s = NULL; - struct pf_state_key *sk = NULL; struct pf_ruleset *ruleset = NULL; struct pf_pdesc pd; int off, dirndx, pqid = 0; @@ -5739,7 +5658,6 @@ done: a->bytes[dirndx] += pd.tot_len; } if (s != NULL) { - sk = s->state_key; if (s->nat_rule.ptr != NULL) { s->nat_rule.ptr->packets[dirndx]++; s->nat_rule.ptr->bytes[dirndx] += pd.tot_len; @@ -5752,7 +5670,7 @@ done: s->nat_src_node->packets[dirndx]++; s->nat_src_node->bytes[dirndx] += pd.tot_len; } - dirndx = (dir == sk->direction) ? 0 : 1; + dirndx = (dir == s->direction) ? 0 : 1; s->packets[dirndx]++; s->bytes[dirndx] += pd.tot_len; } @@ -5767,10 +5685,10 @@ done: */ if (r == &pf_default_rule) { tr = nr; - x = (sk == NULL || sk->direction == dir) ? + x = (s == NULL || s->direction == dir) ? &pd.baddr : &pd.naddr; } else - x = (sk == NULL || sk->direction == dir) ? + x = (s == NULL || s->direction == dir) ? &pd.naddr : &pd.baddr; if (x == &pd.baddr || s == NULL) { /* we need to change the address */ @@ -5781,14 +5699,14 @@ done: } } if (tr->src.addr.type == PF_ADDR_TABLE) - pfr_update_stats(tr->src.addr.p.tbl, (sk == NULL || - sk->direction == dir) ? + pfr_update_stats(tr->src.addr.p.tbl, (s == NULL || + s->direction == dir) ? pd.src : pd.dst, pd.af, pd.tot_len, dir == PF_OUT, r->action == PF_PASS, tr->src.neg); if (tr->dst.addr.type == PF_ADDR_TABLE) - pfr_update_stats(tr->dst.addr.p.tbl, (sk == NULL || - sk->direction == dir) ? pd.dst : pd.src, pd.af, + pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL || + s->direction == dir) ? pd.dst : pd.src, pd.af, pd.tot_len, dir == PF_OUT, r->action == PF_PASS, tr->dst.neg); } @@ -5817,7 +5735,6 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct ip6_hdr *h; struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr; struct pf_state *s = NULL; - struct pf_state_key *sk = NULL; struct pf_ruleset *ruleset = NULL; struct pf_pdesc pd; int off, terminal = 0, dirndx, rh_cnt = 0; @@ -6125,7 +6042,6 @@ done: a->bytes[dirndx] += pd.tot_len; } if (s != NULL) { - sk = s->state_key; if (s->nat_rule.ptr != NULL) { s->nat_rule.ptr->packets[dirndx]++; s->nat_rule.ptr->bytes[dirndx] += pd.tot_len; @@ -6138,7 +6054,7 @@ done: s->nat_src_node->packets[dirndx]++; s->nat_src_node->bytes[dirndx] += pd.tot_len; } - dirndx = (dir == sk->direction) ? 0 : 1; + dirndx = (dir == s->direction) ? 0 : 1; s->packets[dirndx]++; s->bytes[dirndx] += pd.tot_len; } @@ -6153,10 +6069,10 @@ done: */ if (r == &pf_default_rule) { tr = nr; - x = (s == NULL || sk->direction == dir) ? + x = (s == NULL || s->direction == dir) ? &pd.baddr : &pd.naddr; } else { - x = (s == NULL || sk->direction == dir) ? + x = (s == NULL || s->direction == dir) ? &pd.naddr : &pd.baddr; } if (x == &pd.baddr || s == NULL) { @@ -6167,13 +6083,13 @@ done: } } if (tr->src.addr.type == PF_ADDR_TABLE) - pfr_update_stats(tr->src.addr.p.tbl, (sk == NULL || - sk->direction == dir) ? pd.src : pd.dst, pd.af, + pfr_update_stats(tr->src.addr.p.tbl, (s == NULL || + s->direction == dir) ? pd.src : pd.dst, pd.af, pd.tot_len, dir == PF_OUT, r->action == PF_PASS, tr->src.neg); if (tr->dst.addr.type == PF_ADDR_TABLE) - pfr_update_stats(tr->dst.addr.p.tbl, (sk == NULL || - sk->direction == dir) ? pd.dst : pd.src, pd.af, + pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL || + s->direction == dir) ? pd.dst : pd.src, pd.af, pd.tot_len, dir == PF_OUT, r->action == PF_PASS, tr->dst.neg); } diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index 63065d66019..4b1469149a3 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.197 2008/05/18 11:54:04 mcbride Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.198 2008/05/29 00:28:08 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -110,7 +110,7 @@ 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_key *, struct pf_state *); + struct pf_state *); void pf_state_import(struct pfsync_state *, struct pf_state_key *, struct pf_state *); @@ -149,6 +149,8 @@ pfattach(int num) NULL); pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0, 0, 0, "pfstatekeypl", NULL); + pool_init(&pf_state_item_pl, sizeof(struct pf_state_item), 0, 0, 0, + "pfstateitempl", NULL); pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl", &pool_allocator_nointr); pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0, @@ -842,22 +844,22 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) } void -pf_state_export(struct pfsync_state *sp, struct pf_state_key *sk, - struct pf_state *s) +pf_state_export(struct pfsync_state *sp, struct pf_state *s) { int secs = time_second; bzero(sp, sizeof(struct pfsync_state)); +/* XXX_RYAN_NAT */ /* copy from state key */ - sp->lan.addr = sk->lan.addr; - sp->lan.port = sk->lan.port; - sp->gwy.addr = sk->gwy.addr; - sp->gwy.port = sk->gwy.port; - sp->ext.addr = sk->ext.addr; - sp->ext.port = sk->ext.port; - sp->proto = sk->proto; - sp->af = sk->af; - sp->direction = sk->direction; + sp->lan.addr = s->key_wire->addr2; + sp->lan.port = s->key_wire->port2; + sp->gwy.addr = s->key_wire->addr2; + sp->gwy.port = s->key_wire->port2; + sp->ext.addr = s->key_wire->addr1; + sp->ext.port = s->key_wire->port1; + sp->proto = s->key_wire->proto; + sp->af = s->key_wire->af; + sp->direction = s->direction; /* copy from state */ memcpy(&sp->id, &s->id, sizeof(sp->id)); @@ -897,22 +899,23 @@ pf_state_import(struct pfsync_state *sp, struct pf_state_key *sk, struct pf_state *s) { /* copy to state key */ +#ifdef XXX_RYAN_HENNING_PFSYNC_FIXED sk->lan.addr = sp->lan.addr; sk->lan.port = sp->lan.port; sk->gwy.addr = sp->gwy.addr; sk->gwy.port = sp->gwy.port; sk->ext.addr = sp->ext.addr; sk->ext.port = sp->ext.port; +#endif sk->proto = sp->proto; sk->af = sp->af; - sk->direction = sp->direction; - /* 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; @@ -1583,7 +1586,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) case DIOCKILLSTATES: { struct pf_state *s, *nexts; struct pf_state_key *sk; - struct pf_state_host *src, *dst; + struct pf_addr *srcaddr, *dstaddr; + u_int16_t srcport, dstport; struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; u_int killed = 0; @@ -1605,14 +1609,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) { nexts = RB_NEXT(pf_state_tree_id, &tree_id, s); - sk = s->state_key; + sk = s->key_wire; - if (sk->direction == PF_OUT) { - src = &sk->lan; - dst = &sk->ext; + if (s->direction == PF_OUT) { + srcaddr = &sk->addr2; + dstaddr = &sk->addr1; + srcport = sk->port2; + dstport = sk->port1; } else { - src = &sk->ext; - dst = &sk->lan; + srcaddr = &sk->addr1; + dstaddr = &sk->addr2; + srcport = sk->port2; + dstport = sk->port1; } if ((!psk->psk_af || sk->af == psk->psk_af) && (!psk->psk_proto || psk->psk_proto == @@ -1620,19 +1628,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) PF_MATCHA(psk->psk_src.neg, &psk->psk_src.addr.v.a.addr, &psk->psk_src.addr.v.a.mask, - &src->addr, sk->af) && + srcaddr, sk->af) && PF_MATCHA(psk->psk_dst.neg, &psk->psk_dst.addr.v.a.addr, &psk->psk_dst.addr.v.a.mask, - &dst->addr, sk->af) && + dstaddr, sk->af) && (psk->psk_src.port_op == 0 || pf_match_port(psk->psk_src.port_op, psk->psk_src.port[0], psk->psk_src.port[1], - src->port)) && + srcport)) && (psk->psk_dst.port_op == 0 || pf_match_port(psk->psk_dst.port_op, psk->psk_dst.port[0], psk->psk_dst.port[1], - dst->port)) && + dstport)) && (!psk->psk_label[0] || (s->rule.ptr->label[0] && !strcmp(psk->psk_label, s->rule.ptr->label))) && (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname, @@ -1668,12 +1676,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } bzero(s, sizeof(struct pf_state)); - if ((sk = pf_alloc_state_key(s)) == NULL) { + if ((sk = pf_alloc_state_key()) == NULL) { pool_put(&pf_state_pl, s); error = ENOMEM; break; } pf_state_import(sp, sk, s); +/* RYAN NAT */ pf_attach_state(sk, s, 0, PF_SK_BOTH); kif = pfi_kif_get(sp->ifname); if (kif == NULL) { pool_put(&pf_state_pl, s); @@ -1681,7 +1690,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENOENT; break; } - if (pf_insert_state(kif, s)) { + if (pf_state_insert(kif, sk, s)) { pfi_kif_unref(kif, PFI_KIF_REF_NONE); pool_put(&pf_state_pl, s); error = EEXIST; @@ -1705,7 +1714,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } - pf_state_export(&ps->state, s->state_key, s); + pf_state_export(&ps->state, s); break; } @@ -1730,9 +1739,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->state_key, state); + pf_state_export(pstore, state); error = copyout(pstore, p, sizeof(*p)); if (error) { free(pstore, M_TEMP); @@ -1803,33 +1810,33 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) * state tree. */ if (direction == PF_IN) { - PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af); - key.ext.port = pnl->dport; - PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af); - key.gwy.port = pnl->sport; + PF_ACPY(&key.addr1, &pnl->daddr, pnl->af); + key.port1 = pnl->dport; + PF_ACPY(&key.addr2, &pnl->saddr, pnl->af); + key.port2 = pnl->sport; state = pf_find_state_all(&key, PF_IN, &m); } else { - PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af); - key.lan.port = pnl->dport; - PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af); - key.ext.port = pnl->sport; + PF_ACPY(&key.addr2, &pnl->daddr, pnl->af); + key.port2 = pnl->dport; + PF_ACPY(&key.addr1, &pnl->saddr, pnl->af); + key.port1 = pnl->sport; state = pf_find_state_all(&key, PF_OUT, &m); } if (m > 1) error = E2BIG; /* more than one state */ else if (state != NULL) { - sk = state->state_key; + sk = state->key_wire; /* XXX which side? */ if (direction == PF_IN) { - PF_ACPY(&pnl->rsaddr, &sk->lan.addr, + PF_ACPY(&pnl->rsaddr, &sk->addr1, sk->af); - pnl->rsport = sk->lan.port; + pnl->rsport = sk->port1; PF_ACPY(&pnl->rdaddr, &pnl->daddr, pnl->af); pnl->rdport = pnl->dport; } else { - PF_ACPY(&pnl->rdaddr, &sk->gwy.addr, + PF_ACPY(&pnl->rdaddr, &sk->addr2, sk->af); - pnl->rdport = sk->gwy.port; + pnl->rdport = sk->port2; PF_ACPY(&pnl->rsaddr, &pnl->saddr, pnl->af); pnl->rsport = pnl->sport; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index eedbdcf8614..a3515a08a05 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.267 2008/05/18 11:54:04 mcbride Exp $ */ +/* $OpenBSD: pfvar.h,v 1.268 2008/05/29 00:28:08 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -69,6 +69,7 @@ enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL, PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER, PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET }; enum { PF_GET_NONE, PF_GET_CLR_CNTR }; +enum { PF_SK_NONE, PF_SK_WIRE, PF_SK_STACK, PF_SK_BOTH }; /* * Note about PFTM_*: real indices into pf_rule.timeout[] come before @@ -698,46 +699,50 @@ TAILQ_HEAD(pf_state_queue, pf_state); /* keep synced with struct pf_state_key, used in RB_FIND */ struct pf_state_key_cmp { - struct pf_state_host lan; - struct pf_state_host gwy; - struct pf_state_host ext; + struct pf_addr addr1; + struct pf_addr addr2; + u_int16_t port1; + u_int16_t port2; sa_family_t af; u_int8_t proto; - u_int8_t direction; - u_int8_t pad; + u_int8_t pad[2]; +}; + +struct pf_state_item { + TAILQ_ENTRY(pf_state_item) entry; + struct pf_state *s; }; -TAILQ_HEAD(pf_statelist, pf_state); +TAILQ_HEAD(pf_statelisthead, pf_state_item); struct pf_state_key { - struct pf_state_host lan; - struct pf_state_host gwy; - struct pf_state_host ext; + struct pf_addr addr1; + struct pf_addr addr2; + u_int16_t port1; + u_int16_t port2; sa_family_t af; u_int8_t proto; - u_int8_t direction; - u_int8_t pad; + u_int8_t pad[2]; - RB_ENTRY(pf_state_key) entry_lan_ext; - RB_ENTRY(pf_state_key) entry_ext_gwy; - struct pf_statelist states; + RB_ENTRY(pf_state_key) entry; + struct pf_statelisthead states; }; - /* keep synced with struct pf_state, used in RB_FIND */ struct pf_state_cmp { - u_int64_t id; - u_int32_t creatorid; - u_int32_t pad; + u_int64_t id; + u_int32_t creatorid; + u_int8_t direction; + u_int8_t pad[3]; }; struct pf_state { u_int64_t id; u_int32_t creatorid; - u_int32_t pad; + u_int8_t direction; + u_int8_t pad[3]; TAILQ_ENTRY(pf_state) entry_list; - TAILQ_ENTRY(pf_state) next; RB_ENTRY(pf_state) entry_id; struct pf_state_peer src; struct pf_state_peer dst; @@ -745,7 +750,8 @@ struct pf_state { union pf_rule_ptr anchor; union pf_rule_ptr nat_rule; struct pf_addr rt_addr; - struct pf_state_key *state_key; + struct pf_state_key *key_wire; /* addresses wire-side */ + struct pf_state_key *key_stack; /* addresses stack-side */ struct pfi_kif *kif; struct pfi_kif *rt_kif; struct pf_src_node *src_node; @@ -1013,9 +1019,8 @@ struct pfr_ktable { #define pfrkt_nomatch pfrkt_ts.pfrts_nomatch #define pfrkt_tzero pfrkt_ts.pfrts_tzero -RB_HEAD(pf_state_tree_lan_ext, pf_state_key); -RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state_key, - entry_lan_ext, pf_state_compare_lan_ext); +RB_HEAD(pf_state_tree, pf_state_key); +RB_PROTOTYPE(pf_state_tree, pf_state_key, entry, pf_state_compare_key); RB_HEAD(pf_state_tree_ext_gwy, pf_state_key); RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state_key, @@ -1024,8 +1029,7 @@ RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state_key, RB_HEAD(pfi_ifhead, pfi_kif); /* state tables */ -extern struct pf_state_tree_lan_ext pf_statetbl_lan_ext; -extern struct pf_state_tree_ext_gwy pf_statetbl_ext_gwy; +extern struct pf_state_tree pf_statetbl; /* keep synced with pfi_kif, used in RB_FIND */ struct pfi_kif_cmp { @@ -1579,16 +1583,16 @@ extern void pf_tbladdr_remove(struct pf_addr_wrap *); extern void pf_tbladdr_copyout(struct pf_addr_wrap *); extern void pf_calc_skip_steps(struct pf_rulequeue *); extern struct pool pf_src_tree_pl, pf_rule_pl; -extern struct pool pf_state_pl, pf_state_key_pl, pf_altq_pl, - pf_pooladdr_pl; +extern struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl, + pf_altq_pl, pf_pooladdr_pl; extern struct pool pf_state_scrub_pl; extern void pf_purge_thread(void *); extern void pf_purge_expired_src_nodes(int); extern void pf_purge_expired_states(u_int32_t); extern void pf_unlink_state(struct pf_state *); extern void pf_free_state(struct pf_state *); -extern int pf_insert_state(struct pfi_kif *, - struct pf_state *); +extern int pf_state_insert(struct pfi_kif *, + struct pf_state_key *, struct pf_state *); extern int pf_insert_src_node(struct pf_src_node **, struct pf_rule *, struct pf_addr *, sa_family_t); @@ -1654,8 +1658,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(struct pf_state *); +struct pf_state_key *pf_alloc_state_key(void); +void pf_attach_state(struct pf_state_key *, struct pf_state *, int, 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, |