1,2c1,2
< /* $FreeBSD: head/sys/contrib/pf/net/pf.c 130397 2004-06-13 01:36:31Z mlaier $ */
< /* $OpenBSD: pf.c,v 1.389.2.4 2004/04/30 23:27:57 brad Exp $ */
---
> /* $FreeBSD: head/sys/contrib/pf/net/pf.c 130613 2004-06-16 23:24:02Z mlaier $ */
> /* $OpenBSD: pf.c,v 1.433 2004/03/26 22:20:57 dhartmei Exp $ */
5a6
> * Copyright (c) 2002,2003 Henning Brauer
64a66
> #include <sys/endian.h>
93a96,97
>
> #if NPFSYNC > 0
94a99
> #endif /* NPFSYNC > 0 */
107,110d111
< #ifdef ALTQ
< #include <altq/if_altq.h>
< #endif
<
113d113
< #if (__FreeBSD_version >= 500112)
115,117d114
< #else
< #include <machine/limits.h>
< #endif
119d115
< #endif
121d116
< #ifdef __FreeBSD__
123,125d117
< #if (__FreeBSD_version < 501105)
< int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
< u_long if_hwassist_flags, int sw_csum);
127d118
< #endif
130d120
< struct pf_state_tree;
143d132
< struct ifnet *status_ifp;
146a136
> int altqs_inactive_open;
157c147
< uma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl;
---
> uma_zone_t pf_src_tree_pl, pf_rule_pl;
160c150
< struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl;
---
> struct pool pf_src_tree_pl, pf_rule_pl;
164,167d153
< void pf_dynaddr_update(void *);
< #ifdef __FreeBSD__
< void pf_dynaddr_update_event(void *arg, struct ifnet *ifp);
< #endif
192c178
< int, int, struct ifnet *,
---
> int, int, struct pfi_kif *,
196c182
< int, int, struct ifnet *,
---
> int, int, struct pfi_kif *, struct pf_src_node **,
201c187
< int, struct ifnet *, struct mbuf *, int, int,
---
> int, struct pfi_kif *, struct mbuf *, int,
205c191
< int, struct ifnet *, struct mbuf *, int, int,
---
> int, struct pfi_kif *, struct mbuf *, int,
209c195
< int, struct ifnet *, struct mbuf *, int, int,
---
> int, struct pfi_kif *, struct mbuf *, int,
213c199
< int, struct ifnet *, struct mbuf *, int, void *,
---
> int, struct pfi_kif *, struct mbuf *, int, void *,
217c203
< struct ifnet *, struct mbuf *, void *,
---
> struct pfi_kif *, struct mbuf *, void *,
221c207
< struct ifnet *, struct mbuf *, int, int,
---
> struct pfi_kif *, struct mbuf *, int,
224c210
< struct ifnet *, struct mbuf *, int, int,
---
> struct pfi_kif *, struct mbuf *, int,
227c213
< struct ifnet *, struct mbuf *, int, int,
---
> struct pfi_kif *, struct mbuf *, int,
230c216
< struct ifnet *, struct pf_pdesc *);
---
> struct pfi_kif *, struct pf_pdesc *);
233,234c219
< struct pf_rule *, struct pf_rule *,
< struct pf_tag *, int *);
---
> struct pf_rule *, struct pf_tag *, int *);
237c222
< int pf_map_addr(u_int8_t, struct pf_pool *,
---
> int pf_map_addr(u_int8_t, struct pf_rule *,
239,240c224,225
< struct pf_addr *);
< int pf_get_sport(sa_family_t, u_int8_t, struct pf_pool *,
---
> struct pf_addr *, struct pf_src_node **);
> int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
242c227,228
< struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t);
---
> struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
> struct pf_src_node **);
247c233
< int pf_socket_lookup(uid_t *, gid_t *, int, sa_family_t,
---
> int pf_socket_lookup(uid_t *, gid_t *,
260a247,249
> static int pf_add_mbuf_tag(struct mbuf *, u_int);
> struct pf_state *pf_find_state_recurse(struct pfi_kif *,
> struct pf_state *, u_int8_t);
267,268c256,260
< struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
< { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
---
> struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
> { &pf_state_pl, PFSTATE_HIWAT },
> { &pf_src_tree_pl, PFSNODE_HIWAT },
> { &pf_frent_pl, PFFRAG_FRENT_HIWAT }
> };
274c266,267
< *state = pf_find_state(&tree_ext_gwy, &key); \
---
> *state = pf_find_state_recurse( \
> kif, &key, PF_EXT_GWY); \
276c269,270
< *state = pf_find_state(&tree_lan_ext, &key); \
---
> *state = pf_find_state_recurse( \
> kif, &key, PF_LAN_EXT); \
284,285c278,279
< (*state)->rt_ifp != NULL && \
< (*state)->rt_ifp != ifp) \
---
> (*state)->rt_kif != NULL && \
> (*state)->rt_kif != kif) \
297,298c291,293
< static __inline int pf_state_compare(struct pf_tree_node *,
< struct pf_tree_node *);
---
> #define BOUND_IFACE(r, k) (((r)->rule_flag & PFRULE_IFBOUND) ? (k) : \
> ((r)->rule_flag & PFRULE_GRBOUND) ? (k)->pfik_parent : \
> (k)->pfik_parent->pfik_parent)
300,301c295,301
< struct pf_state_tree tree_lan_ext, tree_ext_gwy;
< RB_GENERATE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
---
> 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_id(struct pf_state *,
> struct pf_state *);
302a303,315
> struct pf_src_tree tree_src_tracking;
>
> struct pf_state_tree_id tree_id;
> struct pf_state_queue state_updates;
>
> 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_id, pf_state,
> u.s.entry_id, pf_state_compare_id);
>
308c321
< pf_state_compare(struct pf_tree_node *a, struct pf_tree_node *b)
---
> pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
311a325,372
> if (a->rule.ptr > b->rule.ptr)
> return (1);
> if (a->rule.ptr < b->rule.ptr)
> return (-1);
> if ((diff = a->af - b->af) != 0)
> return (diff);
> switch (a->af) {
> #ifdef INET
> case AF_INET:
> if (a->addr.addr32[0] > b->addr.addr32[0])
> return (1);
> if (a->addr.addr32[0] < b->addr.addr32[0])
> return (-1);
> break;
> #endif /* INET */
> #ifdef INET6
> case AF_INET6:
> if (a->addr.addr32[3] > b->addr.addr32[3])
> return (1);
> if (a->addr.addr32[3] < b->addr.addr32[3])
> return (-1);
> if (a->addr.addr32[2] > b->addr.addr32[2])
> return (1);
> if (a->addr.addr32[2] < b->addr.addr32[2])
> return (-1);
> if (a->addr.addr32[1] > b->addr.addr32[1])
> return (1);
> if (a->addr.addr32[1] < b->addr.addr32[1])
> return (-1);
> if (a->addr.addr32[0] > b->addr.addr32[0])
> return (1);
> if (a->addr.addr32[0] < b->addr.addr32[0])
> return (-1);
> break;
> #endif /* INET6 */
> }
> return (0);
> }
>
> #ifdef __FreeBSD__
> static int
> #else
> static __inline int
> #endif
> pf_state_compare_lan_ext(struct pf_state *a, struct pf_state *b)
> {
> int diff;
>
319c380
< if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
321c382
< if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
323c384
< if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
325c386
< if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
331c392
< if (a->addr[0].addr32[3] > b->addr[0].addr32[3])
---
> if (a->lan.addr.addr32[3] > b->lan.addr.addr32[3])
333c394
< if (a->addr[0].addr32[3] < b->addr[0].addr32[3])
---
> if (a->lan.addr.addr32[3] < b->lan.addr.addr32[3])
335c396
< if (a->addr[1].addr32[3] > b->addr[1].addr32[3])
---
> if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
337c398
< if (a->addr[1].addr32[3] < b->addr[1].addr32[3])
---
> if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
339c400
< if (a->addr[0].addr32[2] > b->addr[0].addr32[2])
---
> if (a->lan.addr.addr32[2] > b->lan.addr.addr32[2])
341c402
< if (a->addr[0].addr32[2] < b->addr[0].addr32[2])
---
> if (a->lan.addr.addr32[2] < b->lan.addr.addr32[2])
343c404
< if (a->addr[1].addr32[2] > b->addr[1].addr32[2])
---
> if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
345c406
< if (a->addr[1].addr32[2] < b->addr[1].addr32[2])
---
> if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
347c408
< if (a->addr[0].addr32[1] > b->addr[0].addr32[1])
---
> if (a->lan.addr.addr32[1] > b->lan.addr.addr32[1])
349c410
< if (a->addr[0].addr32[1] < b->addr[0].addr32[1])
---
> if (a->lan.addr.addr32[1] < b->lan.addr.addr32[1])
351c412
< if (a->addr[1].addr32[1] > b->addr[1].addr32[1])
---
> if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
353c414
< if (a->addr[1].addr32[1] < b->addr[1].addr32[1])
---
> if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
355c416
< if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
357c418
< if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
359c420
< if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
361c422
< if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
367c428
< if ((diff = a->port[0] - b->port[0]) != 0)
---
> if ((diff = a->lan.port - b->lan.port) != 0)
369c430
< if ((diff = a->port[1] - b->port[1]) != 0)
---
> if ((diff = a->ext.port - b->ext.port) != 0)
374a436,461
> #ifdef __FreeBSD__
> static int
> #else
> static __inline int
> #endif
> pf_state_compare_ext_gwy(struct pf_state *a, struct pf_state *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 */
375a463,527
> 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);
> }
>
> #ifdef __FreeBSD__
> static int
> #else
> static __inline int
> #endif
> 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
396c548
< pf_find_state(struct pf_state_tree *tree, struct pf_tree_node *key)
---
> pf_find_state_byid(struct pf_state *key)
398c550,552
< struct pf_tree_node *k;
---
> pf_status.fcounters[FCNT_STATE_SEARCH]++;
> return (RB_FIND(pf_state_tree_id, &tree_id, key));
> }
399a554,558
> struct pf_state *
> pf_find_state_recurse(struct pfi_kif *kif, struct pf_state *key, u_int8_t tree)
> {
> struct pf_state *s;
>
401,404c560,568
< k = RB_FIND(pf_state_tree, tree, key);
< if (k)
< return (k->state);
< else
---
>
> switch (tree) {
> case PF_LAN_EXT:
> for (; kif != NULL; kif = kif->pfik_parent) {
> s = RB_FIND(pf_state_tree_lan_ext,
> &kif->pfik_lan_ext, key);
> if (s != NULL)
> return (s);
> }
405a570,580
> case PF_EXT_GWY:
> for (; kif != NULL; kif = kif->pfik_parent) {
> s = RB_FIND(pf_state_tree_ext_gwy,
> &kif->pfik_ext_gwy, key);
> if (s != NULL)
> return (s);
> }
> return (NULL);
> default:
> panic("pf_find_state_recurse");
> }
407a583,620
> struct pf_state *
> pf_find_state_all(struct pf_state *key, u_int8_t tree, int *more)
> {
> struct pf_state *s, *ss = NULL;
> struct pfi_kif *kif;
>
> 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, key);
> if (s == NULL)
> continue;
> if (more == NULL)
> return (s);
> ss = s;
> (*more)++;
> }
> return (ss);
> case PF_EXT_GWY:
> TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
> s = RB_FIND(pf_state_tree_ext_gwy,
> &kif->pfik_ext_gwy, key);
> if (s == NULL)
> continue;
> if (more == NULL)
> return (s);
> ss = s;
> (*more)++;
> }
> return (ss);
> default:
> panic("pf_find_state_all");
> }
> }
>
409c622,623
< pf_insert_state(struct pf_state *state)
---
> pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
> struct pf_addr *src, sa_family_t af)
411c625
< struct pf_tree_node *keya, *keyb;
---
> struct pf_src_node k;
413,422c627,678
< keya = pool_get(&pf_tree_pl, PR_NOWAIT);
< if (keya == NULL)
< return (-1);
< keya->state = state;
< keya->proto = state->proto;
< keya->af = state->af;
< PF_ACPY(&keya->addr[0], &state->lan.addr, state->af);
< keya->port[0] = state->lan.port;
< PF_ACPY(&keya->addr[1], &state->ext.addr, state->af);
< keya->port[1] = state->ext.port;
---
> if (*sn == NULL) {
> k.af = af;
> PF_ACPY(&k.addr, src, af);
> if (rule->rule_flag & PFRULE_RULESRCTRACK ||
> rule->rpool.opts & PF_POOL_STICKYADDR)
> k.rule.ptr = rule;
> else
> k.rule.ptr = NULL;
> pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
> *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
> }
> if (*sn == NULL) {
> if (!rule->max_src_nodes ||
> rule->src_nodes < rule->max_src_nodes)
> (*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT);
> if ((*sn) == NULL)
> return (-1);
> bzero(*sn, sizeof(struct pf_src_node));
> (*sn)->af = af;
> if (rule->rule_flag & PFRULE_RULESRCTRACK ||
> rule->rpool.opts & PF_POOL_STICKYADDR)
> (*sn)->rule.ptr = rule;
> else
> (*sn)->rule.ptr = NULL;
> PF_ACPY(&(*sn)->addr, src, af);
> if (RB_INSERT(pf_src_tree,
> &tree_src_tracking, *sn) != NULL) {
> if (pf_status.debug >= PF_DEBUG_MISC) {
> printf("pf: src_tree insert failed: ");
> pf_print_host(&(*sn)->addr, 0, af);
> printf("\n");
> }
> pool_put(&pf_src_tree_pl, *sn);
> return (-1);
> }
> #ifdef __FreeBSD__
> (*sn)->creation = time_second;
> #else
> (*sn)->creation = time.tv_sec;
> #endif
> (*sn)->ruletype = rule->action;
> if ((*sn)->rule.ptr != NULL)
> (*sn)->rule.ptr->src_nodes++;
> pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
> pf_status.src_nodes++;
> } else {
> if (rule->max_src_states &&
> (*sn)->states >= rule->max_src_states)
> return (-1);
> }
> return (0);
> }
423a680,682
> int
> pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
> {
425c684,685
< if (RB_INSERT(pf_state_tree, &tree_lan_ext, keya) != NULL) {
---
> state->u.s.kif = kif;
> if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) {
436a697,698
> if (state->sync_flags & PFSTATE_FROMSYNC)
> printf(" (from sync)");
439d700
< pool_put(&pf_tree_pl, keya);
443,458c704
< keyb = pool_get(&pf_tree_pl, PR_NOWAIT);
< if (keyb == NULL) {
< /* Need to pull out the other state */
< RB_REMOVE(pf_state_tree, &tree_lan_ext, keya);
< pool_put(&pf_tree_pl, keya);
< return (-1);
< }
< keyb->state = state;
< keyb->proto = state->proto;
< keyb->af = state->af;
< PF_ACPY(&keyb->addr[0], &state->ext.addr, state->af);
< keyb->port[0] = state->ext.port;
< PF_ACPY(&keyb->addr[1], &state->gwy.addr, state->af);
< keyb->port[1] = state->gwy.port;
<
< if (RB_INSERT(pf_state_tree, &tree_ext_gwy, keyb) != NULL) {
---
> if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) {
469a716,717
> if (state->sync_flags & PFSTATE_FROMSYNC)
> printf(" (from sync)");
472,474c720
< RB_REMOVE(pf_state_tree, &tree_lan_ext, keya);
< pool_put(&pf_tree_pl, keya);
< pool_put(&pf_tree_pl, keyb);
---
> RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
477a724,749
> if (state->id == 0 && state->creatorid == 0) {
> state->id = htobe64(pf_status.stateid++);
> state->creatorid = pf_status.hostid;
> }
> if (RB_INSERT(pf_state_tree_id, &tree_id, state) != NULL) {
> if (pf_status.debug >= PF_DEBUG_MISC) {
> #ifdef __FreeBSD__
> printf("pf: state insert failed: "
> "id: %016llx creatorid: %08x",
> (long long)be64toh(state->id),
> ntohl(state->creatorid));
> #else
> printf("pf: state insert failed: "
> "id: %016llx creatorid: %08x",
> betoh64(state->id), ntohl(state->creatorid));
> #endif
> if (state->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);
> return (-1);
> }
> TAILQ_INSERT_HEAD(&state_updates, state, u.s.entry_updates);
>
479a752
> pfi_attach_state(kif);
501a775
> pf_purge_expired_src_nodes();
565c839
< pf_purge_expired_states(void)
---
> pf_purge_expired_src_nodes(void)
567,568c841
< struct pf_tree_node *cur, *peer, *next;
< struct pf_tree_node key;
---
> struct pf_src_node *cur, *next;
570,571c843,844
< for (cur = RB_MIN(pf_state_tree, &tree_ext_gwy); cur; cur = next) {
< next = RB_NEXT(pf_state_tree, &tree_ext_gwy, cur);
---
> for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
> next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
574c847
< if (pf_state_expires(cur->state) <= (u_int32_t)time_second) {
---
> if (cur->states <= 0 && cur->expire <= time_second) {
576c849
< if (pf_state_expires(cur->state) <= time.tv_sec) {
---
> if (cur->states <= 0 && cur->expire <= time.tv_sec) {
578,589c851,863
< if (cur->state->src.state == PF_TCPS_PROXY_DST)
< pf_send_tcp(cur->state->rule.ptr,
< cur->state->af,
< &cur->state->ext.addr,
< &cur->state->lan.addr,
< cur->state->ext.port,
< cur->state->lan.port,
< cur->state->src.seqhi,
< cur->state->src.seqlo + 1,
< 0,
< TH_RST|TH_ACK, 0, 0);
< RB_REMOVE(pf_state_tree, &tree_ext_gwy, cur);
---
> if (cur->rule.ptr != NULL) {
> cur->rule.ptr->src_nodes--;
> if (cur->rule.ptr->states <= 0 &&
> cur->rule.ptr->max_src_nodes <= 0)
> pf_rm_rule(NULL, cur->rule.ptr);
> }
> RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, cur);
> }
> }
> }
591,600c865,868
< /* Need this key's peer (in the other tree) */
< key.state = cur->state;
< key.proto = cur->state->proto;
< key.af = cur->state->af;
< PF_ACPY(&key.addr[0], &cur->state->lan.addr,
< cur->state->af);
< key.port[0] = cur->state->lan.port;
< PF_ACPY(&key.addr[1], &cur->state->ext.addr,
< cur->state->af);
< key.port[1] = cur->state->ext.port;
---
> void
> pf_src_tree_remove_state(struct pf_state *s)
> {
> u_int32_t timeout;
602c870,875
< peer = RB_FIND(pf_state_tree, &tree_lan_ext, &key);
---
> if (s->src_node != NULL) {
> if (--s->src_node->states <= 0) {
> timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
> if (!timeout)
> timeout =
> pf_default_rule.timeout[PFTM_SRC_NODE];
604,606c877
< KASSERT((peer), ("peer null :%s", __FUNCTION__));
< KASSERT((peer->state == cur->state),
< ("peer->state != cur->state: %s", __FUNCTION__));
---
> s->src_node->expire = time_second + timeout;
608,609c879
< KASSERT(peer);
< KASSERT(peer->state == cur->state);
---
> s->src_node->expire = time.tv_sec + timeout;
611c881,897
< RB_REMOVE(pf_state_tree, &tree_lan_ext, peer);
---
> }
> }
> if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
> if (--s->nat_src_node->states <= 0) {
> timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
> if (!timeout)
> timeout =
> pf_default_rule.timeout[PFTM_SRC_NODE];
> #ifdef __FreeBSD__
> s->nat_src_node->expire = time_second + timeout;
> #else
> s->nat_src_node->expire = time.tv_sec + timeout;
> #endif
> }
> }
> s->src_node = s->nat_src_node = NULL;
> }
612a899,923
> void
> pf_purge_expired_states(void)
> {
> struct pf_state *cur, *next;
>
> for (cur = RB_MIN(pf_state_tree_id, &tree_id);
> cur; cur = next) {
> next = RB_NEXT(pf_state_tree_id, &tree_id, cur);
>
> #ifdef __FreeBSD__
> if (pf_state_expires(cur) <= time_second) {
> #else
> if (pf_state_expires(cur) <= time.tv_sec) {
> #endif
> 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,
> cur->src.seqhi, cur->src.seqlo + 1, 0,
> TH_RST|TH_ACK, 0, 0);
> 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);
614c925
< pfsync_delete_state(cur->state);
---
> pfsync_delete_state(cur);
616,629c927,941
< if (--cur->state->rule.ptr->states <= 0)
< pf_rm_rule(NULL, cur->state->rule.ptr);
< if (cur->state->nat_rule.ptr != NULL)
< if (--cur->state->nat_rule.ptr->states <= 0)
< pf_rm_rule(NULL,
< cur->state->nat_rule.ptr);
< if (cur->state->anchor.ptr != NULL)
< if (--cur->state->anchor.ptr->states <= 0)
< pf_rm_rule(NULL,
< cur->state->anchor.ptr);
< pf_normalize_tcp_cleanup(cur->state);
< pool_put(&pf_state_pl, cur->state);
< pool_put(&pf_tree_pl, cur);
< pool_put(&pf_tree_pl, peer);
---
> pf_src_tree_remove_state(cur);
> if (--cur->rule.ptr->states <= 0 &&
> cur->rule.ptr->src_nodes <= 0)
> pf_rm_rule(NULL, cur->rule.ptr);
> if (cur->nat_rule.ptr != NULL)
> if (--cur->nat_rule.ptr->states <= 0 &&
> cur->nat_rule.ptr->src_nodes <= 0)
> pf_rm_rule(NULL, cur->nat_rule.ptr);
> if (cur->anchor.ptr != NULL)
> if (--cur->anchor.ptr->states <= 0)
> pf_rm_rule(NULL, cur->anchor.ptr);
> pf_normalize_tcp_cleanup(cur);
> pfi_detach_state(cur->u.s.kif);
> TAILQ_REMOVE(&state_updates, cur, u.s.entry_updates);
> pool_put(&pf_state_pl, cur);
669,711d980
< int
< pf_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
< {
< if (aw->type != PF_ADDR_DYNIFTL)
< return (0);
< aw->p.dyn = pool_get(&pf_addr_pl, PR_NOWAIT);
< if (aw->p.dyn == NULL)
< return (1);
< bcopy(aw->v.ifname, aw->p.dyn->ifname, sizeof(aw->p.dyn->ifname));
< aw->p.dyn->ifp = ifunit(aw->p.dyn->ifname);
< if (aw->p.dyn->ifp == NULL) {
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< return (1);
< }
< aw->p.dyn->addr = &aw->v.a.addr;
< aw->p.dyn->af = af;
< aw->p.dyn->undefined = 1;
< #ifndef __FreeBSD__
< aw->p.dyn->hook_cookie = hook_establish(
< aw->p.dyn->ifp->if_addrhooks, 1,
< pf_dynaddr_update, aw->p.dyn);
< if (aw->p.dyn->hook_cookie == NULL) {
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< return (1);
< }
< #else
< PF_UNLOCK();
< aw->p.dyn->hook_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
< pf_dynaddr_update_event, aw->p.dyn, EVENTHANDLER_PRI_ANY);
< PF_LOCK();
< if (aw->p.dyn->hook_cookie == NULL) {
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< return (1);
< }
< #endif
< pf_dynaddr_update(aw->p.dyn);
< return (0);
< }
<
< #ifdef __FreeBSD__
713,792d981
< pf_dynaddr_update_event(void *arg, struct ifnet *ifp)
< {
< PF_LOCK();
< pf_dynaddr_update(arg);
< PF_UNLOCK();
< }
< #endif
<
< void
< pf_dynaddr_update(void *p)
< {
< struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p;
< struct ifaddr *ia;
< int s, changed = 0;
<
< if (ad == NULL || ad->ifp == NULL)
< panic("pf_dynaddr_update");
< s = splsoftnet();
< TAILQ_FOREACH(ia, &ad->ifp->if_addrlist, ifa_list)
< if (ia->ifa_addr != NULL &&
< ia->ifa_addr->sa_family == ad->af) {
< if (ad->af == AF_INET) {
< struct in_addr *a, *b;
<
< a = &ad->addr->v4;
< b = &((struct sockaddr_in *)ia->ifa_addr)
< ->sin_addr;
< if (ad->undefined ||
< memcmp(a, b, sizeof(*a))) {
< bcopy(b, a, sizeof(*a));
< changed = 1;
< }
< } else if (ad->af == AF_INET6) {
< struct in6_addr *a, *b;
<
< a = &ad->addr->v6;
< b = &((struct sockaddr_in6 *)ia->ifa_addr)
< ->sin6_addr;
< if (ad->undefined ||
< memcmp(a, b, sizeof(*a))) {
< bcopy(b, a, sizeof(*a));
< changed = 1;
< }
< }
< if (changed)
< ad->undefined = 0;
< break;
< }
< if (ia == NULL)
< ad->undefined = 1;
< splx(s);
< }
<
< void
< pf_dynaddr_remove(struct pf_addr_wrap *aw)
< {
< if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
< return;
< #ifndef __FreeBSD__
< hook_disestablish(aw->p.dyn->ifp->if_addrhooks,
< aw->p.dyn->hook_cookie);
< #else
< PF_UNLOCK();
< EVENTHANDLER_DEREGISTER(ifaddr_event, aw->p.dyn->hook_cookie);
< PF_LOCK();
< #endif
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< }
<
< void
< pf_dynaddr_copyout(struct pf_addr_wrap *aw)
< {
< if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
< return;
< bcopy(aw->p.dyn->ifname, aw->v.ifname, sizeof(aw->v.ifname));
< aw->p.dyn = (struct pf_addr_dyn *)1;
< }
<
< void
937c1126
< if (cur->ifp != prev->ifp || cur->ifnot != prev->ifnot)
---
> if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
980,984c1169
< if (aw1->p.dyn->ifp != aw2->p.dyn->ifp)
< return (1);
< if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
< return (1);
< return (0);
---
> return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt);
996,1022d1180
< pf_rule_set_qid(struct pf_rulequeue *rules)
< {
< struct pf_rule *rule;
<
< TAILQ_FOREACH(rule, rules, entries)
< if (rule->qname[0] != 0) {
< rule->qid = pf_qname_to_qid(rule->qname);
< if (rule->pqname[0] != 0)
< rule->pqid = pf_qname_to_qid(rule->pqname);
< else
< rule->pqid = rule->qid;
< }
< }
<
< u_int32_t
< pf_qname_to_qid(char *qname)
< {
< struct pf_altq *altq;
<
< TAILQ_FOREACH(altq, pf_altqs_active, entries)
< if (!strcmp(altq->qname, qname))
< return (altq->qid);
<
< return (0);
< }
<
< void
1235,1236d1392
< #if (__FreeBSD_version < 501114)
< struct route ro;
1238d1393
< #endif
1345c1500,1501
< h->ip_off = htons(path_mtu_discovery ? IP_DF : 0);
---
> h->ip_off = path_mtu_discovery ? IP_DF : 0;
> h->ip_len = len;
1348d1503
< #endif
1349a1505
> #endif
1354,1364d1509
< /*
< * XXX
< * OpenBSD changed ip_len/ip_off byte ordering!
< * Because FreeBSD assumes host byte ordering we need to
< * change here.
< */
< NTOHS(ip->ip_len);
< NTOHS(ip->ip_off);
< #if (__FreeBSD_version < 501114)
< bzero(&ro, sizeof(ro));
< ip_rtaddr(ip->ip_dst, &ro);
1366,1373d1510
< ip_output(m, (void *)NULL, &ro, 0, (void *)NULL,
< (void *)NULL);
< PF_LOCK();
< if(ro.ro_rt) {
< RTFREE(ro.ro_rt);
< }
< #else /* __FreeBSD_version >= 501114 */
< PF_UNLOCK();
1377d1513
< #endif
1455c1591
< icmp_error(m0, type, code, 0, NULL);
---
> icmp_error(m0, type, code, 0, (void *)NULL);
1584,1585c1720,1721
< pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat,
< struct pf_rule *rdr, struct pf_tag *pftag, int *tag)
---
> pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat_rule,
> struct pf_tag *pftag, int *tag)
1593,1596c1729,1730
< if (nat != NULL && nat->tag)
< *tag = nat->tag;
< if (rdr != NULL && rdr->tag)
< *tag = rdr->tag;
---
> if (nat_rule != NULL && nat_rule->tag)
> *tag = nat_rule->tag;
1680c1814
< pf_addr_inc(struct pf_addr *addr, u_int8_t af)
---
> pf_addr_inc(struct pf_addr *addr, sa_family_t af)
1769,1770c1903,1904
< pf_map_addr(u_int8_t af, struct pf_pool *rpool, struct pf_addr *saddr,
< struct pf_addr *naddr, struct pf_addr *init_addr)
---
> pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
> struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
1773,1774c1907,1909
< struct pf_addr *raddr;
< struct pf_addr *rmask;
---
> struct pf_pool *rpool = &r->rpool;
> struct pf_addr *raddr = &rpool->cur->addr.v.a.addr;
> struct pf_addr *rmask = &rpool->cur->addr.v.a.mask;
1775a1911
> struct pf_src_node k;
1776a1913,1936
> if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
> (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
> k.af = af;
> PF_ACPY(&k.addr, saddr, af);
> if (r->rule_flag & PFRULE_RULESRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR)
> k.rule.ptr = r;
> else
> k.rule.ptr = NULL;
> pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
> *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
> if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
> PF_ACPY(naddr, &(*sn)->raddr, af);
> if (pf_status.debug >= PF_DEBUG_MISC) {
> printf("pf_map_addr: src tracking maps ");
> pf_print_host(&k.addr, 0, af);
> printf(" to ");
> pf_print_host(naddr, 0, af);
> printf("\n");
> }
> return (0);
> }
> }
>
1779,1782c1939,1955
< if (rpool->cur->addr.type == PF_ADDR_DYNIFTL &&
< rpool->cur->addr.p.dyn->undefined)
< return (1);
< if (rpool->cur->addr.type == PF_ADDR_TABLE) {
---
> if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
> if (af == AF_INET) {
> if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
> (rpool->opts & PF_POOL_TYPEMASK) !=
> PF_POOL_ROUNDROBIN)
> return (1);
> raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
> rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
> } else {
> if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
> (rpool->opts & PF_POOL_TYPEMASK) !=
> PF_POOL_ROUNDROBIN)
> return (1);
> raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
> rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
> }
> } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
1841a2015,2019
> } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
> if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
> &rpool->tblidx, &rpool->counter,
> &raddr, &rmask, af))
> goto get_addr;
1853c2031
< /* table contain no address of type 'af' */
---
> /* table contains no address of type 'af' */
1857a2036,2045
> } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
> rpool->tblidx = -1;
> if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
> &rpool->tblidx, &rpool->counter,
> &raddr, &rmask, af)) {
> /* table contains no address of type 'af' */
> if (rpool->cur != acur)
> goto try_next;
> return (1);
> }
1868a2057,2058
> if (*sn != NULL)
> PF_ACPY(&(*sn)->raddr, naddr, af);
1872c2062
< printf("pf_map_addr: selected address: ");
---
> printf("pf_map_addr: selected address ");
1881c2071
< pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_pool *rpool,
---
> pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
1883c2073,2074
< struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high)
---
> struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
> struct pf_src_node **sn)
1885c2076
< struct pf_tree_node key;
---
> struct pf_state key;
1890c2081
< if (pf_map_addr(af, rpool, saddr, naddr, &init_addr))
---
> if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
1896,1898c2087,2089
< PF_ACPY(&key.addr[0], daddr, key.af);
< PF_ACPY(&key.addr[1], naddr, key.af);
< key.port[0] = dport;
---
> PF_ACPY(&key.ext.addr, daddr, key.af);
> PF_ACPY(&key.gwy.addr, naddr, key.af);
> key.ext.port = dport;
1905,1906c2096,2097
< key.port[1] = 0;
< if (pf_find_state(&tree_ext_gwy, &key) == NULL)
---
> key.gwy.port = 0;
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
1909,1910c2100,2101
< key.port[1] = *nport;
< if (pf_find_state(&tree_ext_gwy, &key) == NULL) {
---
> key.gwy.port = *nport;
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
1912d2102
< }
1914,1915c2104,2105
< key.port[1] = htons(low);
< if (pf_find_state(&tree_ext_gwy, &key) == NULL) {
---
> key.gwy.port = htons(low);
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) {
1931,1932c2121,2122
< key.port[1] = htons(tmp);
< if (pf_find_state(&tree_ext_gwy, &key) ==
---
> key.gwy.port = htons(tmp);
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
1939,1940c2129,2130
< key.port[1] = htons(tmp);
< if (pf_find_state(&tree_ext_gwy, &key) ==
---
> key.gwy.port = htons(tmp);
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
1948c2138
< switch (rpool->opts & PF_POOL_TYPEMASK) {
---
> switch (r->rpool.opts & PF_POOL_TYPEMASK) {
1951c2141
< if (pf_map_addr(af, rpool, saddr, naddr, &init_addr))
---
> if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
1959d2148
< break;
1968c2157
< int direction, struct ifnet *ifp, struct pf_addr *saddr, u_int16_t sport,
---
> int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
1989,1990c2178,2179
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
2036c2225
< struct ifnet *ifp,
---
> struct pfi_kif *kif, struct pf_src_node **sn,
2044c2233
< r = pf_match_translation(pd, m, off, direction, ifp, saddr,
---
> r = pf_match_translation(pd, m, off, direction, kif, saddr,
2047c2236
< r = pf_match_translation(pd, m, off, direction, ifp,
---
> r = pf_match_translation(pd, m, off, direction, kif,
2050c2239
< r = pf_match_translation(pd, m, off, direction, ifp, saddr,
---
> r = pf_match_translation(pd, m, off, direction, kif, saddr,
2053c2242
< r = pf_match_translation(pd, m, off, direction, ifp,
---
> r = pf_match_translation(pd, m, off, direction, kif,
2063d2251
< break;
2065c2253
< if (pf_get_sport(pd->af, pd->proto, &r->rpool, saddr,
---
> if (pf_get_sport(pd->af, pd->proto, r, saddr,
2067c2255
< r->rpool.proxy_port[1])) {
---
> r->rpool.proxy_port[1], sn)) {
2079,2083c2267,2289
< if (r->rpool.cur->addr.type ==
< PF_ADDR_DYNIFTL &&
< r->rpool.cur->addr.p.dyn->undefined)
< return (NULL);
< else
---
> if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
> if (pd->af == AF_INET) {
> if (r->rpool.cur->addr.p.dyn->
> pfid_acnt4 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->rpool.cur->addr.p.dyn->
> pfid_addr4,
> &r->rpool.cur->addr.p.dyn->
> pfid_mask4,
> saddr, AF_INET);
> } else {
> if (r->rpool.cur->addr.p.dyn->
> pfid_acnt6 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->rpool.cur->addr.p.dyn->
> pfid_addr6,
> &r->rpool.cur->addr.p.dyn->
> pfid_mask6,
> saddr, AF_INET6);
> }
> } else
2090,2093c2296,2318
< if (r->src.addr.type == PF_ADDR_DYNIFTL &&
< r->src.addr.p.dyn->undefined)
< return (NULL);
< else
---
> if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
> if (pd->af == AF_INET) {
> if (r->src.addr.p.dyn->
> pfid_acnt4 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->src.addr.p.dyn->
> pfid_addr4,
> &r->src.addr.p.dyn->
> pfid_mask4,
> daddr, AF_INET);
> } else {
> if (r->src.addr.p.dyn->
> pfid_acnt6 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->src.addr.p.dyn->
> pfid_addr6,
> &r->src.addr.p.dyn->
> pfid_mask6,
> daddr, AF_INET6);
> }
> } else
2102c2327
< if (pf_map_addr(r->af, &r->rpool, saddr, naddr, NULL))
---
> if (pf_map_addr(r->af, r, saddr, naddr, NULL, sn))
2124d2348
< break;
2132,2133c2356
< pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, sa_family_t af,
< int proto, struct pf_pdesc *pd)
---
> pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
2146c2369
< switch (proto) {
---
> switch (pd->proto) {
2180c2403
< switch(af) {
---
> switch (pd->af) {
2183d2405
< #if (__FreeBSD_version >= 500043)
2185d2406
< #endif
2192d2412
< #if (__FreeBSD_version >= 500043)
2194d2413
< #endif
2201,2202c2420
< inp = in_pcblookup(tb, &saddr->v4, sport, &daddr->v4,
< dport, INPLOOKUP_WILDCARD);
---
> inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
2211d2428
< #if (__FreeBSD_version >= 500043)
2213d2429
< #endif
2220d2435
< #if (__FreeBSD_version >= 500043)
2222d2436
< #endif
2230,2231c2444
< inp = in_pcblookup(tb, &saddr->v6, sport, &daddr->v6,
< dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
---
> inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0);
2243d2455
< #if (__FreeBSD_version >= 500043)
2245d2456
< #endif
2248d2458
< #if (__FreeBSD_version >= 500043)
2251d2460
< #endif
2286c2495
< /* fallthrough */
---
> /* FALLTHROUGH */
2292a2502
> break;
2322c2532
< /* fallthrough */
---
> /* FALLTHROUGH */
2328a2539
> break;
2408c2619
< s->rt_ifp = NULL;
---
> s->rt_kif = NULL;
2414,2416c2625,2627
< pf_map_addr(AF_INET, &r->rpool, saddr,
< &s->rt_addr, NULL);
< s->rt_ifp = r->rpool.cur->ifp;
---
> pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL,
> &s->nat_src_node);
> s->rt_kif = r->rpool.cur->kif;
2421,2423c2632,2634
< pf_map_addr(AF_INET6, &r->rpool, saddr,
< &s->rt_addr, NULL);
< s->rt_ifp = r->rpool.cur->ifp;
---
> pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL,
> &s->nat_src_node);
> s->rt_kif = r->rpool.cur->kif;
2431c2642
< struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h,
2434c2645
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
2436d2646
< struct pf_addr baddr, naddr;
2444a2655
> struct pf_src_node *nsn = NULL;
2456c2667
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp,
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
2458,2459c2669,2670
< &naddr, &nport)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> &pd->naddr, &nport)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
2461c2672
< &th->th_sum, &naddr, nport, 0, af);
---
> &th->th_sum, &pd->naddr, nport, 0, af);
2463c2674
< if (nat->natpass)
---
> if (nr->natpass)
2464a2676
> pd->nat_rule = nr;
2469,2472c2681,2684
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr,
< th->th_sport, daddr, th->th_dport,
< &naddr, &nport)) != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, th->th_sport, daddr, th->th_dport,
> &pd->naddr, &nport)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
2474c2686
< &th->th_sum, &naddr, nport, 0, af);
---
> &th->th_sum, &pd->naddr, nport, 0, af);
2476c2688
< if (rdr->natpass)
---
> if (nr->natpass)
2477a2690
> pd->nat_rule = nr;
2483,2484c2696,2697
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
2509,2510c2722
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2515,2516c2727
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2520,2521c2731
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
2550,2555d2759
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
2561c2765
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
2569,2576c2773,2782
< if (nat != NULL) {
< pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
< &th->th_sum, &baddr, bport, 0, af);
< rewrite++;
< } else if (rdr != NULL) {
< pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
< &th->th_sum, &baddr, bport, 0, af);
< rewrite++;
---
> if (nr != NULL) {
> if (direction == PF_OUT) {
> pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
> &th->th_sum, &pd->baddr, bport, 0, af);
> rewrite++;
> } else {
> pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
> &th->th_sum, &pd->baddr, bport, 0, af);
> rewrite++;
> }
2607c2813
< if (r->keep_state || nat != NULL || rdr != NULL ||
---
> if (r->keep_state || nr != NULL ||
2611a2818
> struct pf_src_node *sn = NULL;
2614,2615c2821,2836
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
>
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
2616a2838,2851
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
2625,2628c2860
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
2642,2643c2874,2875
< if (nat != NULL) {
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
2654,2655c2886,2887
< if (rdr != NULL) {
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
2689d2920
< s->dst.seqlo = 0; /* Haven't seen these yet */
2692d2922
< s->dst.seqdiff = 0; /* Defer random generation */
2703,2704d2932
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
2706c2934,2942
<
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
2709a2946
> pf_src_tree_remove_state(s);
2716a2954
> pf_src_tree_remove_state(s);
2720c2958
< if (pf_insert_state(s)) {
---
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
2722a2961
> pf_src_tree_remove_state(s);
2730,2737c2969,2979
< if (nat != NULL)
< pf_change_ap(saddr, &th->th_sport,
< pd->ip_sum, &th->th_sum, &baddr,
< bport, 0, af);
< else if (rdr != NULL)
< pf_change_ap(daddr, &th->th_dport,
< pd->ip_sum, &th->th_sum, &baddr,
< bport, 0, af);
---
> if (nr != NULL) {
> if (direction == PF_OUT) {
> pf_change_ap(saddr, &th->th_sport,
> pd->ip_sum, &th->th_sum, &pd->baddr,
> bport, 0, af);
> } else {
> pf_change_ap(daddr, &th->th_dport,
> pd->ip_sum, &th->th_sum, &pd->baddr,
> bport, 0, af);
> }
> }
2745,2746c2987,2988
< th->th_sport, s->src.seqhi,
< ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0);
---
> th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
> TH_SYN|TH_ACK, 0, s->src.mss, 0);
2760c3002
< struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h,
2763c3005
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
2765d3006
< struct pf_addr baddr, naddr;
2773a3015
> struct pf_src_node *nsn = NULL;
2784c3026
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp,
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
2786,2787c3028,3029
< &naddr, &nport)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> &pd->naddr, &nport)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
2789c3031
< &uh->uh_sum, &naddr, nport, 1, af);
---
> &uh->uh_sum, &pd->naddr, nport, 1, af);
2791c3033
< if (nat->natpass)
---
> if (nr->natpass)
2792a3035
> pd->nat_rule = nr;
2797,2800c3040,3043
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr,
< uh->uh_sport, daddr, uh->uh_dport, &naddr, &nport))
< != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, uh->uh_sport, daddr, uh->uh_dport, &pd->naddr,
> &nport)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
2802c3045
< &uh->uh_sum, &naddr, nport, 1, af);
---
> &uh->uh_sum, &pd->naddr, nport, 1, af);
2804c3047
< if (rdr->natpass)
---
> if (nr->natpass)
2805a3049
> pd->nat_rule = nr;
2811,2812c3055,3056
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
2835,2836c3079
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2841,2842c3084
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2846,2847c3088
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
2875,2880d3115
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
2886c3121
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
2893,2900c3128,3137
< if (nat != NULL) {
< pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
< &uh->uh_sum, &baddr, bport, 1, af);
< rewrite++;
< } else if (rdr != NULL) {
< pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
< &uh->uh_sum, &baddr, bport, 1, af);
< rewrite++;
---
> if (nr != NULL) {
> if (direction == PF_OUT) {
> pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
> &uh->uh_sum, &pd->baddr, bport, 1, af);
> rewrite++;
> } else {
> pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
> &uh->uh_sum, &pd->baddr, bport, 1, af);
> rewrite++;
> }
2918c3155
< if (r->keep_state || nat != NULL || rdr != NULL) {
---
> if (r->keep_state || nr != NULL) {
2920a3158
> struct pf_src_node *sn = NULL;
2922,2923c3160,3174
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
2924a3176,3189
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
2933,2936c3198
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
2950,2951c3212,3213
< if (nat != NULL) {
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
2962,2963c3224,3225
< if (rdr != NULL) {
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
2970,2973d3231
< s->src.seqlo = 0;
< s->src.seqhi = 0;
< s->src.seqdiff = 0;
< s->src.max_win = 0;
2975,2978d3232
< s->dst.seqlo = 0;
< s->dst.seqhi = 0;
< s->dst.seqdiff = 0;
< s->dst.max_win = 0;
2988,2989d3241
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
2991c3243,3252
< if (pf_insert_state(s)) {
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
2992a3254
> pf_src_tree_remove_state(s);
3008c3270
< struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h,
3011c3273
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
3013d3274
< struct pf_addr baddr, naddr;
3015a3277
> struct pf_src_node *nsn = NULL;
3062,3064c3324,3326
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
3069c3331
< naddr.v4.s_addr, 0);
---
> pd->naddr.v4.s_addr, 0);
3075c3337
< &naddr, 0);
---
> &pd->naddr, 0);
3080c3342
< if (nat->natpass)
---
> if (nr->natpass)
3081a3344
> pd->nat_rule = nr;
3085,3087c3348,3350
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
3092c3355
< pd->ip_sum, naddr.v4.s_addr, 0);
---
> pd->ip_sum, pd->naddr.v4.s_addr, 0);
3098c3361
< &naddr, 0);
---
> &pd->naddr, 0);
3103c3366
< if (rdr->natpass)
---
> if (nr->natpass)
3104a3368
> pd->nat_rule = nr;
3110,3111c3374,3375
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
3131,3132c3395
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
3160,3165d3422
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
3174c3431
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
3185,3186c3442
< if (!state_icmp && (r->keep_state ||
< nat != NULL || rdr != NULL)) {
---
> if (!state_icmp && (r->keep_state || nr != NULL)) {
3188a3445
> struct pf_src_node *sn = NULL;
3190,3191c3447,3461
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
3192a3463,3476
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
3201,3204c3485
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
3218,3219c3499,3500
< if (nat != NULL)
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
3228,3229c3509,3510
< if (rdr != NULL)
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
3234,3244d3514
<
< s->src.seqlo = 0;
< s->src.seqhi = 0;
< s->src.seqdiff = 0;
< s->src.max_win = 0;
< s->src.state = 0;
< s->dst.seqlo = 0;
< s->dst.seqhi = 0;
< s->dst.seqdiff = 0;
< s->dst.max_win = 0;
< s->dst.state = 0;
3253,3254d3522
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
3256c3524,3533
< if (pf_insert_state(s)) {
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
3257a3535
> pf_src_tree_remove_state(s);
3276c3554
< struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
3279c3557
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
3281a3560
> struct pf_src_node *nsn = NULL;
3283d3561
< struct pf_addr baddr, naddr;
3293,3295c3571,3573
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
3300c3578
< naddr.v4.s_addr, 0);
---
> pd->naddr.v4.s_addr, 0);
3305c3583
< PF_ACPY(saddr, &naddr, af);
---
> PF_ACPY(saddr, &pd->naddr, af);
3309c3587
< if (nat->natpass)
---
> if (nr->natpass)
3310a3589
> pd->nat_rule = nr;
3314,3316c3593,3595
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
3321c3600
< pd->ip_sum, naddr.v4.s_addr, 0);
---
> pd->ip_sum, pd->naddr.v4.s_addr, 0);
3326c3605
< PF_ACPY(daddr, &naddr, af);
---
> PF_ACPY(daddr, &pd->naddr, af);
3330c3609
< if (rdr->natpass)
---
> if (nr->natpass)
3331a3611
> pd->nat_rule = nr;
3337,3338c3617,3618
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
3354,3355c3634
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
3383,3388d3661
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
3389a3663
>
3391c3665
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
3398,3401c3672,3677
< if (nat != NULL)
< a = saddr;
< else if (rdr != NULL)
< a = daddr;
---
> if (nr != NULL) {
> if (direction == PF_OUT)
> a = saddr;
> else
> a = daddr;
> }
3407c3683
< baddr.v4.s_addr, 0);
---
> pd->baddr.v4.s_addr, 0);
3412c3688
< PF_ACPY(a, &baddr, af);
---
> PF_ACPY(a, &pd->baddr, af);
3433c3709
< if (r->keep_state || nat != NULL || rdr != NULL) {
---
> if (r->keep_state || nr != NULL) {
3435a3712
> struct pf_src_node *sn = NULL;
3437,3438c3714,3728
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
3439a3730,3743
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
3448,3451c3752
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
3462d3762
< s->gwy.port = 0;
3464,3466c3764,3765
< s->ext.port = 0;
< if (nat != NULL)
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
3469d3767
< s->lan.port = 0;
3472d3769
< s->lan.port = 0;
3474,3476c3771,3772
< s->ext.port = 0;
< if (rdr != NULL)
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
3479d3774
< s->gwy.port = 0;
3481,3484d3775
< s->src.seqlo = 0;
< s->src.seqhi = 0;
< s->src.seqdiff = 0;
< s->src.max_win = 0;
3486,3489d3776
< s->dst.seqlo = 0;
< s->dst.seqhi = 0;
< s->dst.seqdiff = 0;
< s->dst.max_win = 0;
3499,3500d3785
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
3502c3787,3796
< if (pf_insert_state(s)) {
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
3504,3506c3798
< if (r->log)
< PFLOG_PACKET(ifp, h, m, af, direction, reason,
< r, a, ruleset);
---
> pf_src_tree_remove_state(s);
3517c3809
< pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
---
> pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
3531,3532c3823,3824
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
3550,3551c3842
< else if (r->match_tag &&
< !pf_match_tag(m, r, NULL, NULL, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, NULL, pftag, &tag))
3575,3580d3865
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
3581a3867
>
3583c3869
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
3597,3598c3883,3884
< pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp,
< struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd,
---
> pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
> struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
3601c3887
< struct pf_tree_node key;
---
> struct pf_state key;
3606c3892
< int ackskew, dirndx;
---
> int ackskew;
3612,3615c3898,3908
< PF_ACPY(&key.addr[0], pd->src, key.af);
< PF_ACPY(&key.addr[1], pd->dst, key.af);
< key.port[0] = th->th_sport;
< key.port[1] = th->th_dport;
---
> 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;
> }
3622d3914
< dirndx = 0;
3626d3917
< dirndx = 1;
3667c3958,3959
< (*state)->dst.seqhi, 0, TH_SYN, 0, (*state)->src.mss, 0);
---
> (*state)->dst.seqhi, 0, TH_SYN, 0,
> (*state)->src.mss, 0);
3824,3826d4115
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
3915,3917d4203
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
3983,3984c4269,4270
< if (pf_normalize_tcp_stateful(m, off, pd, reason, th, src, dst,
< ©back))
---
> if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
> src, dst, ©back))
4006,4015d4291
< (*state)->rule.ptr->packets++;
< (*state)->rule.ptr->bytes += pd->tot_len;
< if ((*state)->nat_rule.ptr != NULL) {
< (*state)->nat_rule.ptr->packets++;
< (*state)->nat_rule.ptr->bytes += pd->tot_len;
< }
< if ((*state)->anchor.ptr != NULL) {
< (*state)->anchor.ptr->packets++;
< (*state)->anchor.ptr->bytes += pd->tot_len;
< }
4020,4021c4296,4297
< pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp,
< struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd)
---
> pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
> struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
4024c4300
< struct pf_tree_node key;
---
> struct pf_state key;
4026d4301
< int dirndx;
4030,4033c4305,4315
< PF_ACPY(&key.addr[0], pd->src, key.af);
< PF_ACPY(&key.addr[1], pd->dst, key.af);
< key.port[0] = uh->uh_sport;
< key.port[1] = uh->uh_dport;
---
> 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;
> }
4040d4321
< dirndx = 0;
4044d4324
< dirndx = 1;
4047,4049d4326
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
4080,4089d4356
< (*state)->rule.ptr->packets++;
< (*state)->rule.ptr->bytes += pd->tot_len;
< if ((*state)->nat_rule.ptr != NULL) {
< (*state)->nat_rule.ptr->packets++;
< (*state)->nat_rule.ptr->bytes += pd->tot_len;
< }
< if ((*state)->anchor.ptr != NULL) {
< (*state)->anchor.ptr->packets++;
< (*state)->anchor.ptr->bytes += pd->tot_len;
< }
4094,4095c4361,4362
< pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
< struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd)
---
> 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)
4101c4368
< int state_icmp = 0, dirndx;
---
> int state_icmp = 0;
4139c4406
< struct pf_tree_node key;
---
> struct pf_state key;
4143,4146c4410,4420
< PF_ACPY(&key.addr[0], saddr, key.af);
< PF_ACPY(&key.addr[1], daddr, key.af);
< key.port[0] = icmpid;
< key.port[1] = icmpid;
---
> 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 = icmpid;
> 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 = icmpid;
> }
4150,4152d4423
< dirndx = (direction == (*state)->direction) ? 0 : 1;
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
4312c4583
< struct pf_tree_node key;
---
> struct pf_state key;
4331,4334c4602,4612
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = th.th_dport;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = th.th_sport;
---
> 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;
> }
4346c4624,4625
< if (src->wscale && dst->wscale && !(th.th_flags & TH_SYN))
---
> if (src->wscale && dst->wscale &&
> !(th.th_flags & TH_SYN))
4419c4698
< struct pf_tree_node key;
---
> struct pf_state key;
4431,4434c4710,4720
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = uh.uh_dport;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = uh.uh_sport;
---
> 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;
> }
4481c4767
< struct pf_tree_node key;
---
> struct pf_state key;
4493,4496c4779,4789
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = iih.icmp_id;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = iih.icmp_id;
---
> 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 = iih.icmp_id;
> 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 = iih.icmp_id;
> }
4529c4822
< struct pf_tree_node key;
---
> struct pf_state key;
4541,4544c4834,4844
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = iih.icmp6_id;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = iih.icmp6_id;
---
> 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 = iih.icmp6_id;
> key.gwy.port = 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 = iih.icmp6_id;
> }
4575c4875
< struct pf_tree_node key;
---
> struct pf_state key;
4579,4582c4879,4889
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = 0;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = 0;
---
> 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;
> } 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;
> }
4629c4936
< pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp,
---
> pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
4633,4634c4940
< struct pf_tree_node key;
< int dirndx;
---
> struct pf_state key;
4638,4641c4944,4954
< PF_ACPY(&key.addr[0], pd->src, key.af);
< PF_ACPY(&key.addr[1], pd->dst, key.af);
< key.port[0] = 0;
< key.port[1] = 0;
---
> 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;
> } 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;
> }
4648d4960
< dirndx = 0;
4652d4963
< dirndx = 1;
4655,4657d4965
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
4709,4718d5016
< (*state)->rule.ptr->packets++;
< (*state)->rule.ptr->bytes += pd->tot_len;
< if ((*state)->nat_rule.ptr != NULL) {
< (*state)->nat_rule.ptr->packets++;
< (*state)->nat_rule.ptr->bytes += pd->tot_len;
< }
< if ((*state)->anchor.ptr != NULL) {
< (*state)->anchor.ptr->packets++;
< (*state)->anchor.ptr->bytes += pd->tot_len;
< }
4745c5043,5044
< if (m->m_pkthdr.len < off + len || ntohs(h->ip_len) < off + len) {
---
> if (m->m_pkthdr.len < off + len ||
> ntohs(h->ip_len) < off + len) {
4804,4964d5102
< #if defined(__FreeBSD__) && (__FreeBSD_version < 501105)
< int
< ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
< u_long if_hwassist_flags, int sw_csum)
< {
< int error = 0;
< int hlen = ip->ip_hl << 2;
< int len = (mtu - hlen) & ~7; /* size of payload in each fragment */
< int off;
< struct mbuf *m0 = *m_frag; /* the original packet */
< int firstlen;
< struct mbuf **mnext;
< int nfrags;
<
< if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */
< ipstat.ips_cantfrag++;
< return EMSGSIZE;
< }
<
< /*
< * Must be able to put at least 8 bytes per fragment.
< */
< if (len < 8)
< return EMSGSIZE;
<
< /*
< * If the interface will not calculate checksums on
< * fragmented packets, then do it here.
< */
< if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA &&
< (if_hwassist_flags & CSUM_IP_FRAGS) == 0) {
< in_delayed_cksum(m0);
< m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
< }
<
< if (len > PAGE_SIZE) {
< /*
< * Fragment large datagrams such that each segment
< * contains a multiple of PAGE_SIZE amount of data,
< * plus headers. This enables a receiver to perform
< * page-flipping zero-copy optimizations.
< *
< * XXX When does this help given that sender and receiver
< * could have different page sizes, and also mtu could
< * be less than the receiver's page size ?
< */
< int newlen;
< struct mbuf *m;
<
< for (m = m0, off = 0; m && (off+m->m_len) <= mtu; m = m->m_next)
< off += m->m_len;
<
< /*
< * firstlen (off - hlen) must be aligned on an
< * 8-byte boundary
< */
< if (off < hlen)
< goto smart_frag_failure;
< off = ((off - hlen) & ~7) + hlen;
< newlen = (~PAGE_MASK) & mtu;
< if ((newlen + sizeof (struct ip)) > mtu) {
< /* we failed, go back the default */
< smart_frag_failure:
< newlen = len;
< off = hlen + len;
< }
< len = newlen;
<
< } else {
< off = hlen + len;
< }
<
< firstlen = off - hlen;
< mnext = &m0->m_nextpkt; /* pointer to next packet */
<
< /*
< * Loop through length of segment after first fragment,
< * make new header and copy data of each part and link onto chain.
< * Here, m0 is the original packet, m is the fragment being created.
< * The fragments are linked off the m_nextpkt of the original
< * packet, which after processing serves as the first fragment.
< */
< for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) {
< struct ip *mhip; /* ip header on the fragment */
< struct mbuf *m;
< int mhlen = sizeof (struct ip);
<
< MGETHDR(m, M_DONTWAIT, MT_HEADER);
< if (m == 0) {
< error = ENOBUFS;
< ipstat.ips_odropped++;
< goto done;
< }
< m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG;
< /*
< * In the first mbuf, leave room for the link header, then
< * copy the original IP header including options. The payload
< * goes into an additional mbuf chain returned by m_copy().
< */
< m->m_data += max_linkhdr;
< mhip = mtod(m, struct ip *);
< *mhip = *ip;
< if (hlen > sizeof (struct ip)) {
< mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
< mhip->ip_v = IPVERSION;
< mhip->ip_hl = mhlen >> 2;
< }
< m->m_len = mhlen;
< /* XXX do we need to add ip->ip_off below ? */
< mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off;
< if (off + len >= ip->ip_len) { /* last fragment */
< len = ip->ip_len - off;
< m->m_flags |= M_LASTFRAG;
< } else
< mhip->ip_off |= IP_MF;
< mhip->ip_len = htons((u_short)(len + mhlen));
< m->m_next = m_copy(m0, off, len);
< if (m->m_next == 0) { /* copy failed */
< m_free(m);
< error = ENOBUFS; /* ??? */
< ipstat.ips_odropped++;
< goto done;
< }
< m->m_pkthdr.len = mhlen + len;
< m->m_pkthdr.rcvif = (struct ifnet *)0;
< #ifdef MAC
< mac_create_fragment(m0, m);
< #endif
< m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags;
< mhip->ip_off = htons(mhip->ip_off);
< mhip->ip_sum = 0;
< if (sw_csum & CSUM_DELAY_IP)
< mhip->ip_sum = in_cksum(m, mhlen);
< *mnext = m;
< mnext = &m->m_nextpkt;
< }
< ipstat.ips_ofragments += nfrags;
<
< /* set first marker for fragment chain */
< m0->m_flags |= M_FIRSTFRAG | M_FRAG;
< m0->m_pkthdr.csum_data = nfrags;
<
< /*
< * Update first fragment by trimming what's been copied out
< * and updating header.
< */
< m_adj(m0, hlen + firstlen - ip->ip_len);
< m0->m_pkthdr.len = hlen + firstlen;
< ip->ip_len = htons((u_short)m0->m_pkthdr.len);
< ip->ip_off |= IP_MF;
< ip->ip_off = htons(ip->ip_off);
< ip->ip_sum = 0;
< if (sw_csum & CSUM_DELAY_IP)
< ip->ip_sum = in_cksum(m0, hlen);
<
< done:
< *m_frag = m0;
< return error;
< }
< #endif /* __FreeBSD__ && __FreeBSD_version > 501105 */
<
4976a5115
> struct pf_src_node *sn = NULL;
5035,5037c5174,5175
< pf_map_addr(AF_INET, &r->rpool,
< (struct pf_addr *)&ip->ip_src,
< &naddr, NULL);
---
> pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
> &naddr, NULL, &sn);
5040c5178,5179
< ifp = r->rpool.cur->ifp;
---
> ifp = r->rpool.cur->kif ?
> r->rpool.cur->kif->pfik_ifp : NULL;
5045c5184
< ifp = s->rt_ifp;
---
> ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
5052,5057c5191,5193
< if (m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL) != NULL)
< goto bad;
< mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
< if (mtag == NULL)
< goto bad;
< m_tag_prepend(m0, mtag);
---
> mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
> if (mtag == NULL) {
> struct m_tag *mtag;
5059c5195,5201
< if (oifp != ifp) {
---
> mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
> if (mtag == NULL)
> goto bad;
> m_tag_prepend(m0, mtag);
> }
>
> if (oifp != ifp && mtag == NULL) {
5122a5265,5292
> #ifdef IPSEC
> /*
> * If deferred crypto processing is needed, check that the
> * interface supports it.
> */
> if ((mtag = m_tag_find(m0, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL))
> != NULL && (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
> /* Notify IPsec to do its own crypto. */
> ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
> goto bad;
> }
> #endif /* IPSEC */
>
> /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
> if (m0->m_pkthdr.csum & M_TCPV4_CSUM_OUT) {
> if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
> ifp->if_bridge != NULL) {
> in_delayed_cksum(m0);
> m0->m_pkthdr.csum &= ~M_TCPV4_CSUM_OUT; /* Clear */
> }
> } else if (m0->m_pkthdr.csum & M_UDPV4_CSUM_OUT) {
> if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
> ifp->if_bridge != NULL) {
> in_delayed_cksum(m0);
> m0->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */
> }
> }
>
5229a5400
> struct pf_src_node *sn = NULL;
5288,5289c5459,5460
< pf_map_addr(AF_INET6, &r->rpool,
< (struct pf_addr *)&ip6->ip6_src, &naddr, NULL);
---
> pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
> &naddr, NULL, &sn);
5293c5464
< ifp = r->rpool.cur->ifp;
---
> ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
5298c5469
< ifp = s->rt_ifp;
---
> ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
5508c5679,5680
< pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
---
> pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
> sa_family_t af)
5589a5762,5775
> static int
> pf_add_mbuf_tag(struct mbuf *m, u_int tag)
> {
> struct m_tag *mtag;
>
> if (m_tag_find(m, tag, NULL) != NULL)
> return (0);
> mtag = m_tag_get(tag, 0, M_NOWAIT);
> if (mtag == NULL)
> return (1);
> m_tag_prepend(m, mtag);
> return (0);
> }
>
5594,5602c5780,5788
< u_short action, reason = 0, log = 0;
< struct mbuf *m = *m0;
< struct ip *h = NULL; /* XXX: was uninitialized */
< struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
< struct pf_state *s = NULL;
< struct pf_ruleset *ruleset = NULL;
< struct pf_pdesc pd;
< int off;
< int pqid = 0;
---
> struct pfi_kif *kif;
> u_short action, reason = 0, log = 0;
> struct mbuf *m = *m0;
> struct ip *h = NULL; /* make the compiler happy */
> struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
> struct pf_state *s = NULL;
> struct pf_ruleset *ruleset = NULL;
> struct pf_pdesc pd;
> int off, dirndx, pqid = 0;
5615c5801,5809
< #if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
---
> kif = pfi_index2kif[ifp->if_index];
> if (kif == NULL) {
> #ifdef __FreeBSD__
> PF_UNLOCK();
> #endif
> return (PF_DROP);
> }
>
> #ifdef __FreeBSD__
5623a5818
> memset(&pd, 0, sizeof(pd));
5632c5827
< if (pf_normalize_ip(m0, dir, ifp, &reason) != PF_PASS) {
---
> if (pf_normalize_ip(m0, dir, kif, &reason) != PF_PASS) {
5647d5841
< memset(&pd, 0, sizeof(pd));
5649a5844
> PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
5658c5853
< action = pf_test_fragment(&r, dir, ifp, m, h,
---
> action = pf_test_fragment(&r, dir, kif, m, h,
5682c5877
< action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
---
> action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
5684,5685c5879,5880
< break;
< action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd,
---
> goto done;
> action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
5687a5883,5885
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5688a5887
> a = s->anchor.ptr;
5691,5692c5890,5891
< action = pf_test_tcp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_tcp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5710c5909,5915
< action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd);
---
> if (uh.uh_dport == 0 ||
> ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
> ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
> action = PF_DROP;
> goto done;
> }
> action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
5711a5917,5919
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5716,5717c5924,5925
< action = pf_test_udp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_udp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5735c5943
< action = pf_test_state_icmp(&s, dir, ifp, m, 0, off, h, &pd);
---
> action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd);
5736a5945,5947
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5738,5739d5948
< r->packets++;
< r->bytes += ntohs(h->ip_len);
5741,5744d5949
< if (a != NULL) {
< a->packets++;
< a->bytes += ntohs(h->ip_len);
< }
5747,5748c5952,5953
< action = pf_test_icmp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_icmp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5753c5958
< action = pf_test_state_other(&s, dir, ifp, &pd);
---
> action = pf_test_state_other(&s, dir, kif, &pd);
5754a5960,5962
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5759c5967
< action = pf_test_other(&r, &s, dir, ifp, m, off, h,
---
> action = pf_test_other(&r, &s, dir, kif, m, off, h,
5764,5768d5971
< if (ifp == status_ifp) {
< pf_status.bcounters[0][dir == PF_OUT] += pd.tot_len;
< pf_status.pcounters[0][dir == PF_OUT][action != PF_PASS]++;
< }
<
5770,5783d5972
< tr = r;
< if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL)
< tr = s->nat_rule.ptr;
< if (tr->src.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->src.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->src.not);
< if (tr->dst.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->dst.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->dst.not);
<
5812a6002,6016
> /*
> * connections redirected to loopback should not match sockets
> * bound specifically to loopback due to security implications,
> * see tcp_input() and in_pcblookup_listen().
> */
> if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
> pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
> (s->nat_rule.ptr->action == PF_RDR ||
> s->nat_rule.ptr->action == PF_BINAT) &&
> (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET &&
> pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
> action = PF_DROP;
> REASON_SET(&reason, PFRES_MEMORY);
> }
>
5814c6018
< PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, a, ruleset);
5815a6020,6083
> kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
> kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
>
> if (action == PF_PASS || r->action == PF_DROP) {
> r->packets++;
> r->bytes += pd.tot_len;
> if (a != NULL) {
> a->packets++;
> a->bytes += pd.tot_len;
> }
> if (s != NULL) {
> dirndx = (dir == s->direction) ? 0 : 1;
> s->packets[dirndx]++;
> s->bytes[dirndx] += pd.tot_len;
> if (s->nat_rule.ptr != NULL) {
> s->nat_rule.ptr->packets++;
> s->nat_rule.ptr->bytes += pd.tot_len;
> }
> if (s->src_node != NULL) {
> s->src_node->packets++;
> s->src_node->bytes += pd.tot_len;
> }
> if (s->nat_src_node != NULL) {
> s->nat_src_node->packets++;
> s->nat_src_node->bytes += pd.tot_len;
> }
> }
> tr = r;
> nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
> if (nr != NULL) {
> struct pf_addr *x;
> /*
> * XXX: we need to make sure that the addresses
> * passed to pfr_update_stats() are the same than
> * the addresses used during matching (pfr_match)
> */
> if (r == &pf_default_rule) {
> tr = nr;
> x = (s == NULL || s->direction == dir) ?
> &pd.baddr : &pd.naddr;
> } else
> x = (s == NULL || s->direction == dir) ?
> &pd.naddr : &pd.baddr;
> if (x == &pd.baddr || s == NULL) {
> /* we need to change the address */
> if (dir == PF_OUT)
> pd.src = x;
> else
> pd.dst = x;
> }
> }
> if (tr->src.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.src : pd.dst, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->src.not);
> if (tr->dst.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.dst : pd.src, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->dst.not);
> }
>
>
5836,5843c6104,6112
< u_short action, reason = 0, log = 0;
< struct mbuf *m = *m0;
< struct ip6_hdr *h = NULL; /* make the compiler happy */
< struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
< struct pf_state *s = NULL;
< struct pf_ruleset *ruleset = NULL;
< struct pf_pdesc pd;
< int off, terminal = 0;
---
> struct pfi_kif *kif;
> u_short action, reason = 0, log = 0;
> struct mbuf *m = *m0;
> struct ip6_hdr *h = NULL; /* make the compiler happy */
> struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
> struct pf_state *s = NULL;
> struct pf_ruleset *ruleset = NULL;
> struct pf_pdesc pd;
> int off, terminal = 0, dirndx;
5857c6126,6134
< #if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
---
> kif = pfi_index2kif[ifp->if_index];
> if (kif == NULL) {
> #ifdef __FreeBSD__
> PF_UNLOCK();
> #endif
> return (PF_DROP);
> }
>
> #ifdef __FreeBSD__
5865a6143
> memset(&pd, 0, sizeof(pd));
5874c6152
< if (pf_normalize_ip6(m0, dir, ifp, &reason) != PF_PASS) {
---
> if (pf_normalize_ip6(m0, dir, kif, &reason) != PF_PASS) {
5881d6158
< memset(&pd, 0, sizeof(pd));
5883a6161
> PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
5894c6172
< action = pf_test_fragment(&r, dir, ifp, m, h,
---
> action = pf_test_fragment(&r, dir, kif, m, h,
5946c6224
< action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
---
> action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
5948,5949c6226,6227
< break;
< action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd,
---
> goto done;
> action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
5951a6230,6232
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5952a6234
> a = s->anchor.ptr;
5955,5956c6237,6238
< action = pf_test_tcp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_tcp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5974c6256,6262
< action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd);
---
> if (uh.uh_dport == 0 ||
> ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
> ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
> action = PF_DROP;
> goto done;
> }
> action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
5975a6264,6266
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5976a6268
> a = s->anchor.ptr;
5979,5980c6271,6272
< action = pf_test_udp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_udp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5998,5999c6290,6291
< action = pf_test_state_icmp(&s, dir, ifp,
< m, 0, off, h, &pd);
---
> action = pf_test_state_icmp(&s, dir, kif,
> m, off, h, &pd);
6000a6293,6295
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
6002,6003c6297
< r->packets++;
< r->bytes += h->ip6_plen;
---
> a = s->anchor.ptr;
6006,6007c6300,6301
< action = pf_test_icmp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_icmp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
6012,6013c6306,6313
< action = pf_test_other(&r, &s, dir, ifp, m, off, h,
< &pd, &a, &ruleset);
---
> action = pf_test_state_other(&s, dir, kif, &pd);
> if (action == PF_PASS) {
> r = s->rule.ptr;
> a = s->anchor.ptr;
> log = s->log;
> } else if (s == NULL)
> action = pf_test_other(&r, &s, dir, kif, m, off, h,
> &pd, &a, &ruleset);
6017,6021d6316
< if (ifp == status_ifp) {
< pf_status.bcounters[1][dir == PF_OUT] += pd.tot_len;
< pf_status.pcounters[1][dir == PF_OUT][action != PF_PASS]++;
< }
<
6023,6036d6317
< tr = r;
< if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL)
< tr = s->nat_rule.ptr;
< if (tr->src.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->src.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->src.not);
< if (tr->dst.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->dst.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->dst.not);
<
6058a6340,6349
> if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
> pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
> (s->nat_rule.ptr->action == PF_RDR ||
> s->nat_rule.ptr->action == PF_BINAT) &&
> IN6_IS_ADDR_LOOPBACK(&pd.dst->v6) &&
> pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
> action = PF_DROP;
> REASON_SET(&reason, PFRES_MEMORY);
> }
>
6060c6351
< PFLOG_PACKET(ifp, h, m, AF_INET6, dir, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, r, a, ruleset);
6061a6353,6416
> kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
> kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
>
> if (action == PF_PASS || r->action == PF_DROP) {
> r->packets++;
> r->bytes += pd.tot_len;
> if (a != NULL) {
> a->packets++;
> a->bytes += pd.tot_len;
> }
> if (s != NULL) {
> dirndx = (dir == s->direction) ? 0 : 1;
> s->packets[dirndx]++;
> s->bytes[dirndx] += pd.tot_len;
> if (s->nat_rule.ptr != NULL) {
> s->nat_rule.ptr->packets++;
> s->nat_rule.ptr->bytes += pd.tot_len;
> }
> if (s->src_node != NULL) {
> s->src_node->packets++;
> s->src_node->bytes += pd.tot_len;
> }
> if (s->nat_src_node != NULL) {
> s->nat_src_node->packets++;
> s->nat_src_node->bytes += pd.tot_len;
> }
> }
> tr = r;
> nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
> if (nr != NULL) {
> struct pf_addr *x;
> /*
> * XXX: we need to make sure that the addresses
> * passed to pfr_update_stats() are the same than
> * the addresses used during matching (pfr_match)
> */
> if (r == &pf_default_rule) {
> tr = nr;
> x = (s == NULL || s->direction == dir) ?
> &pd.baddr : &pd.naddr;
> } else {
> x = (s == NULL || s->direction == dir) ?
> &pd.naddr : &pd.baddr;
> }
> if (x == &pd.baddr || s == NULL) {
> if (dir == PF_OUT)
> pd.src = x;
> else
> pd.dst = x;
> }
> }
> if (tr->src.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.src : pd.dst, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->src.not);
> if (tr->dst.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.dst : pd.src, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->dst.not);
> }
>
>
< /* $FreeBSD: head/sys/contrib/pf/net/pf.c 130397 2004-06-13 01:36:31Z mlaier $ */
< /* $OpenBSD: pf.c,v 1.389.2.4 2004/04/30 23:27:57 brad Exp $ */
---
> /* $FreeBSD: head/sys/contrib/pf/net/pf.c 130613 2004-06-16 23:24:02Z mlaier $ */
> /* $OpenBSD: pf.c,v 1.433 2004/03/26 22:20:57 dhartmei Exp $ */
5a6
> * Copyright (c) 2002,2003 Henning Brauer
64a66
> #include <sys/endian.h>
93a96,97
>
> #if NPFSYNC > 0
94a99
> #endif /* NPFSYNC > 0 */
107,110d111
< #ifdef ALTQ
< #include <altq/if_altq.h>
< #endif
<
113d113
< #if (__FreeBSD_version >= 500112)
115,117d114
< #else
< #include <machine/limits.h>
< #endif
119d115
< #endif
121d116
< #ifdef __FreeBSD__
123,125d117
< #if (__FreeBSD_version < 501105)
< int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
< u_long if_hwassist_flags, int sw_csum);
127d118
< #endif
130d120
< struct pf_state_tree;
143d132
< struct ifnet *status_ifp;
146a136
> int altqs_inactive_open;
157c147
< uma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl;
---
> uma_zone_t pf_src_tree_pl, pf_rule_pl;
160c150
< struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl;
---
> struct pool pf_src_tree_pl, pf_rule_pl;
164,167d153
< void pf_dynaddr_update(void *);
< #ifdef __FreeBSD__
< void pf_dynaddr_update_event(void *arg, struct ifnet *ifp);
< #endif
192c178
< int, int, struct ifnet *,
---
> int, int, struct pfi_kif *,
196c182
< int, int, struct ifnet *,
---
> int, int, struct pfi_kif *, struct pf_src_node **,
201c187
< int, struct ifnet *, struct mbuf *, int, int,
---
> int, struct pfi_kif *, struct mbuf *, int,
205c191
< int, struct ifnet *, struct mbuf *, int, int,
---
> int, struct pfi_kif *, struct mbuf *, int,
209c195
< int, struct ifnet *, struct mbuf *, int, int,
---
> int, struct pfi_kif *, struct mbuf *, int,
213c199
< int, struct ifnet *, struct mbuf *, int, void *,
---
> int, struct pfi_kif *, struct mbuf *, int, void *,
217c203
< struct ifnet *, struct mbuf *, void *,
---
> struct pfi_kif *, struct mbuf *, void *,
221c207
< struct ifnet *, struct mbuf *, int, int,
---
> struct pfi_kif *, struct mbuf *, int,
224c210
< struct ifnet *, struct mbuf *, int, int,
---
> struct pfi_kif *, struct mbuf *, int,
227c213
< struct ifnet *, struct mbuf *, int, int,
---
> struct pfi_kif *, struct mbuf *, int,
230c216
< struct ifnet *, struct pf_pdesc *);
---
> struct pfi_kif *, struct pf_pdesc *);
233,234c219
< struct pf_rule *, struct pf_rule *,
< struct pf_tag *, int *);
---
> struct pf_rule *, struct pf_tag *, int *);
237c222
< int pf_map_addr(u_int8_t, struct pf_pool *,
---
> int pf_map_addr(u_int8_t, struct pf_rule *,
239,240c224,225
< struct pf_addr *);
< int pf_get_sport(sa_family_t, u_int8_t, struct pf_pool *,
---
> struct pf_addr *, struct pf_src_node **);
> int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
242c227,228
< struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t);
---
> struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
> struct pf_src_node **);
247c233
< int pf_socket_lookup(uid_t *, gid_t *, int, sa_family_t,
---
> int pf_socket_lookup(uid_t *, gid_t *,
260a247,249
> static int pf_add_mbuf_tag(struct mbuf *, u_int);
> struct pf_state *pf_find_state_recurse(struct pfi_kif *,
> struct pf_state *, u_int8_t);
267,268c256,260
< struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
< { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
---
> struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
> { &pf_state_pl, PFSTATE_HIWAT },
> { &pf_src_tree_pl, PFSNODE_HIWAT },
> { &pf_frent_pl, PFFRAG_FRENT_HIWAT }
> };
274c266,267
< *state = pf_find_state(&tree_ext_gwy, &key); \
---
> *state = pf_find_state_recurse( \
> kif, &key, PF_EXT_GWY); \
276c269,270
< *state = pf_find_state(&tree_lan_ext, &key); \
---
> *state = pf_find_state_recurse( \
> kif, &key, PF_LAN_EXT); \
284,285c278,279
< (*state)->rt_ifp != NULL && \
< (*state)->rt_ifp != ifp) \
---
> (*state)->rt_kif != NULL && \
> (*state)->rt_kif != kif) \
297,298c291,293
< static __inline int pf_state_compare(struct pf_tree_node *,
< struct pf_tree_node *);
---
> #define BOUND_IFACE(r, k) (((r)->rule_flag & PFRULE_IFBOUND) ? (k) : \
> ((r)->rule_flag & PFRULE_GRBOUND) ? (k)->pfik_parent : \
> (k)->pfik_parent->pfik_parent)
300,301c295,301
< struct pf_state_tree tree_lan_ext, tree_ext_gwy;
< RB_GENERATE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
---
> 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_id(struct pf_state *,
> struct pf_state *);
302a303,315
> struct pf_src_tree tree_src_tracking;
>
> struct pf_state_tree_id tree_id;
> struct pf_state_queue state_updates;
>
> 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_id, pf_state,
> u.s.entry_id, pf_state_compare_id);
>
308c321
< pf_state_compare(struct pf_tree_node *a, struct pf_tree_node *b)
---
> pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
311a325,372
> if (a->rule.ptr > b->rule.ptr)
> return (1);
> if (a->rule.ptr < b->rule.ptr)
> return (-1);
> if ((diff = a->af - b->af) != 0)
> return (diff);
> switch (a->af) {
> #ifdef INET
> case AF_INET:
> if (a->addr.addr32[0] > b->addr.addr32[0])
> return (1);
> if (a->addr.addr32[0] < b->addr.addr32[0])
> return (-1);
> break;
> #endif /* INET */
> #ifdef INET6
> case AF_INET6:
> if (a->addr.addr32[3] > b->addr.addr32[3])
> return (1);
> if (a->addr.addr32[3] < b->addr.addr32[3])
> return (-1);
> if (a->addr.addr32[2] > b->addr.addr32[2])
> return (1);
> if (a->addr.addr32[2] < b->addr.addr32[2])
> return (-1);
> if (a->addr.addr32[1] > b->addr.addr32[1])
> return (1);
> if (a->addr.addr32[1] < b->addr.addr32[1])
> return (-1);
> if (a->addr.addr32[0] > b->addr.addr32[0])
> return (1);
> if (a->addr.addr32[0] < b->addr.addr32[0])
> return (-1);
> break;
> #endif /* INET6 */
> }
> return (0);
> }
>
> #ifdef __FreeBSD__
> static int
> #else
> static __inline int
> #endif
> pf_state_compare_lan_ext(struct pf_state *a, struct pf_state *b)
> {
> int diff;
>
319c380
< if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
321c382
< if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
323c384
< if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
325c386
< if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
331c392
< if (a->addr[0].addr32[3] > b->addr[0].addr32[3])
---
> if (a->lan.addr.addr32[3] > b->lan.addr.addr32[3])
333c394
< if (a->addr[0].addr32[3] < b->addr[0].addr32[3])
---
> if (a->lan.addr.addr32[3] < b->lan.addr.addr32[3])
335c396
< if (a->addr[1].addr32[3] > b->addr[1].addr32[3])
---
> if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
337c398
< if (a->addr[1].addr32[3] < b->addr[1].addr32[3])
---
> if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
339c400
< if (a->addr[0].addr32[2] > b->addr[0].addr32[2])
---
> if (a->lan.addr.addr32[2] > b->lan.addr.addr32[2])
341c402
< if (a->addr[0].addr32[2] < b->addr[0].addr32[2])
---
> if (a->lan.addr.addr32[2] < b->lan.addr.addr32[2])
343c404
< if (a->addr[1].addr32[2] > b->addr[1].addr32[2])
---
> if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
345c406
< if (a->addr[1].addr32[2] < b->addr[1].addr32[2])
---
> if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
347c408
< if (a->addr[0].addr32[1] > b->addr[0].addr32[1])
---
> if (a->lan.addr.addr32[1] > b->lan.addr.addr32[1])
349c410
< if (a->addr[0].addr32[1] < b->addr[0].addr32[1])
---
> if (a->lan.addr.addr32[1] < b->lan.addr.addr32[1])
351c412
< if (a->addr[1].addr32[1] > b->addr[1].addr32[1])
---
> if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
353c414
< if (a->addr[1].addr32[1] < b->addr[1].addr32[1])
---
> if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
355c416
< if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
357c418
< if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
---
> if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
359c420
< if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
361c422
< if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
---
> if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
367c428
< if ((diff = a->port[0] - b->port[0]) != 0)
---
> if ((diff = a->lan.port - b->lan.port) != 0)
369c430
< if ((diff = a->port[1] - b->port[1]) != 0)
---
> if ((diff = a->ext.port - b->ext.port) != 0)
374a436,461
> #ifdef __FreeBSD__
> static int
> #else
> static __inline int
> #endif
> pf_state_compare_ext_gwy(struct pf_state *a, struct pf_state *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 */
375a463,527
> 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);
> }
>
> #ifdef __FreeBSD__
> static int
> #else
> static __inline int
> #endif
> 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
396c548
< pf_find_state(struct pf_state_tree *tree, struct pf_tree_node *key)
---
> pf_find_state_byid(struct pf_state *key)
398c550,552
< struct pf_tree_node *k;
---
> pf_status.fcounters[FCNT_STATE_SEARCH]++;
> return (RB_FIND(pf_state_tree_id, &tree_id, key));
> }
399a554,558
> struct pf_state *
> pf_find_state_recurse(struct pfi_kif *kif, struct pf_state *key, u_int8_t tree)
> {
> struct pf_state *s;
>
401,404c560,568
< k = RB_FIND(pf_state_tree, tree, key);
< if (k)
< return (k->state);
< else
---
>
> switch (tree) {
> case PF_LAN_EXT:
> for (; kif != NULL; kif = kif->pfik_parent) {
> s = RB_FIND(pf_state_tree_lan_ext,
> &kif->pfik_lan_ext, key);
> if (s != NULL)
> return (s);
> }
405a570,580
> case PF_EXT_GWY:
> for (; kif != NULL; kif = kif->pfik_parent) {
> s = RB_FIND(pf_state_tree_ext_gwy,
> &kif->pfik_ext_gwy, key);
> if (s != NULL)
> return (s);
> }
> return (NULL);
> default:
> panic("pf_find_state_recurse");
> }
407a583,620
> struct pf_state *
> pf_find_state_all(struct pf_state *key, u_int8_t tree, int *more)
> {
> struct pf_state *s, *ss = NULL;
> struct pfi_kif *kif;
>
> 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, key);
> if (s == NULL)
> continue;
> if (more == NULL)
> return (s);
> ss = s;
> (*more)++;
> }
> return (ss);
> case PF_EXT_GWY:
> TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
> s = RB_FIND(pf_state_tree_ext_gwy,
> &kif->pfik_ext_gwy, key);
> if (s == NULL)
> continue;
> if (more == NULL)
> return (s);
> ss = s;
> (*more)++;
> }
> return (ss);
> default:
> panic("pf_find_state_all");
> }
> }
>
409c622,623
< pf_insert_state(struct pf_state *state)
---
> pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
> struct pf_addr *src, sa_family_t af)
411c625
< struct pf_tree_node *keya, *keyb;
---
> struct pf_src_node k;
413,422c627,678
< keya = pool_get(&pf_tree_pl, PR_NOWAIT);
< if (keya == NULL)
< return (-1);
< keya->state = state;
< keya->proto = state->proto;
< keya->af = state->af;
< PF_ACPY(&keya->addr[0], &state->lan.addr, state->af);
< keya->port[0] = state->lan.port;
< PF_ACPY(&keya->addr[1], &state->ext.addr, state->af);
< keya->port[1] = state->ext.port;
---
> if (*sn == NULL) {
> k.af = af;
> PF_ACPY(&k.addr, src, af);
> if (rule->rule_flag & PFRULE_RULESRCTRACK ||
> rule->rpool.opts & PF_POOL_STICKYADDR)
> k.rule.ptr = rule;
> else
> k.rule.ptr = NULL;
> pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
> *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
> }
> if (*sn == NULL) {
> if (!rule->max_src_nodes ||
> rule->src_nodes < rule->max_src_nodes)
> (*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT);
> if ((*sn) == NULL)
> return (-1);
> bzero(*sn, sizeof(struct pf_src_node));
> (*sn)->af = af;
> if (rule->rule_flag & PFRULE_RULESRCTRACK ||
> rule->rpool.opts & PF_POOL_STICKYADDR)
> (*sn)->rule.ptr = rule;
> else
> (*sn)->rule.ptr = NULL;
> PF_ACPY(&(*sn)->addr, src, af);
> if (RB_INSERT(pf_src_tree,
> &tree_src_tracking, *sn) != NULL) {
> if (pf_status.debug >= PF_DEBUG_MISC) {
> printf("pf: src_tree insert failed: ");
> pf_print_host(&(*sn)->addr, 0, af);
> printf("\n");
> }
> pool_put(&pf_src_tree_pl, *sn);
> return (-1);
> }
> #ifdef __FreeBSD__
> (*sn)->creation = time_second;
> #else
> (*sn)->creation = time.tv_sec;
> #endif
> (*sn)->ruletype = rule->action;
> if ((*sn)->rule.ptr != NULL)
> (*sn)->rule.ptr->src_nodes++;
> pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
> pf_status.src_nodes++;
> } else {
> if (rule->max_src_states &&
> (*sn)->states >= rule->max_src_states)
> return (-1);
> }
> return (0);
> }
423a680,682
> int
> pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
> {
425c684,685
< if (RB_INSERT(pf_state_tree, &tree_lan_ext, keya) != NULL) {
---
> state->u.s.kif = kif;
> if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) {
436a697,698
> if (state->sync_flags & PFSTATE_FROMSYNC)
> printf(" (from sync)");
439d700
< pool_put(&pf_tree_pl, keya);
443,458c704
< keyb = pool_get(&pf_tree_pl, PR_NOWAIT);
< if (keyb == NULL) {
< /* Need to pull out the other state */
< RB_REMOVE(pf_state_tree, &tree_lan_ext, keya);
< pool_put(&pf_tree_pl, keya);
< return (-1);
< }
< keyb->state = state;
< keyb->proto = state->proto;
< keyb->af = state->af;
< PF_ACPY(&keyb->addr[0], &state->ext.addr, state->af);
< keyb->port[0] = state->ext.port;
< PF_ACPY(&keyb->addr[1], &state->gwy.addr, state->af);
< keyb->port[1] = state->gwy.port;
<
< if (RB_INSERT(pf_state_tree, &tree_ext_gwy, keyb) != NULL) {
---
> if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) {
469a716,717
> if (state->sync_flags & PFSTATE_FROMSYNC)
> printf(" (from sync)");
472,474c720
< RB_REMOVE(pf_state_tree, &tree_lan_ext, keya);
< pool_put(&pf_tree_pl, keya);
< pool_put(&pf_tree_pl, keyb);
---
> RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
477a724,749
> if (state->id == 0 && state->creatorid == 0) {
> state->id = htobe64(pf_status.stateid++);
> state->creatorid = pf_status.hostid;
> }
> if (RB_INSERT(pf_state_tree_id, &tree_id, state) != NULL) {
> if (pf_status.debug >= PF_DEBUG_MISC) {
> #ifdef __FreeBSD__
> printf("pf: state insert failed: "
> "id: %016llx creatorid: %08x",
> (long long)be64toh(state->id),
> ntohl(state->creatorid));
> #else
> printf("pf: state insert failed: "
> "id: %016llx creatorid: %08x",
> betoh64(state->id), ntohl(state->creatorid));
> #endif
> if (state->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);
> return (-1);
> }
> TAILQ_INSERT_HEAD(&state_updates, state, u.s.entry_updates);
>
479a752
> pfi_attach_state(kif);
501a775
> pf_purge_expired_src_nodes();
565c839
< pf_purge_expired_states(void)
---
> pf_purge_expired_src_nodes(void)
567,568c841
< struct pf_tree_node *cur, *peer, *next;
< struct pf_tree_node key;
---
> struct pf_src_node *cur, *next;
570,571c843,844
< for (cur = RB_MIN(pf_state_tree, &tree_ext_gwy); cur; cur = next) {
< next = RB_NEXT(pf_state_tree, &tree_ext_gwy, cur);
---
> for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
> next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
574c847
< if (pf_state_expires(cur->state) <= (u_int32_t)time_second) {
---
> if (cur->states <= 0 && cur->expire <= time_second) {
576c849
< if (pf_state_expires(cur->state) <= time.tv_sec) {
---
> if (cur->states <= 0 && cur->expire <= time.tv_sec) {
578,589c851,863
< if (cur->state->src.state == PF_TCPS_PROXY_DST)
< pf_send_tcp(cur->state->rule.ptr,
< cur->state->af,
< &cur->state->ext.addr,
< &cur->state->lan.addr,
< cur->state->ext.port,
< cur->state->lan.port,
< cur->state->src.seqhi,
< cur->state->src.seqlo + 1,
< 0,
< TH_RST|TH_ACK, 0, 0);
< RB_REMOVE(pf_state_tree, &tree_ext_gwy, cur);
---
> if (cur->rule.ptr != NULL) {
> cur->rule.ptr->src_nodes--;
> if (cur->rule.ptr->states <= 0 &&
> cur->rule.ptr->max_src_nodes <= 0)
> pf_rm_rule(NULL, cur->rule.ptr);
> }
> RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, cur);
> }
> }
> }
591,600c865,868
< /* Need this key's peer (in the other tree) */
< key.state = cur->state;
< key.proto = cur->state->proto;
< key.af = cur->state->af;
< PF_ACPY(&key.addr[0], &cur->state->lan.addr,
< cur->state->af);
< key.port[0] = cur->state->lan.port;
< PF_ACPY(&key.addr[1], &cur->state->ext.addr,
< cur->state->af);
< key.port[1] = cur->state->ext.port;
---
> void
> pf_src_tree_remove_state(struct pf_state *s)
> {
> u_int32_t timeout;
602c870,875
< peer = RB_FIND(pf_state_tree, &tree_lan_ext, &key);
---
> if (s->src_node != NULL) {
> if (--s->src_node->states <= 0) {
> timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
> if (!timeout)
> timeout =
> pf_default_rule.timeout[PFTM_SRC_NODE];
604,606c877
< KASSERT((peer), ("peer null :%s", __FUNCTION__));
< KASSERT((peer->state == cur->state),
< ("peer->state != cur->state: %s", __FUNCTION__));
---
> s->src_node->expire = time_second + timeout;
608,609c879
< KASSERT(peer);
< KASSERT(peer->state == cur->state);
---
> s->src_node->expire = time.tv_sec + timeout;
611c881,897
< RB_REMOVE(pf_state_tree, &tree_lan_ext, peer);
---
> }
> }
> if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
> if (--s->nat_src_node->states <= 0) {
> timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
> if (!timeout)
> timeout =
> pf_default_rule.timeout[PFTM_SRC_NODE];
> #ifdef __FreeBSD__
> s->nat_src_node->expire = time_second + timeout;
> #else
> s->nat_src_node->expire = time.tv_sec + timeout;
> #endif
> }
> }
> s->src_node = s->nat_src_node = NULL;
> }
612a899,923
> void
> pf_purge_expired_states(void)
> {
> struct pf_state *cur, *next;
>
> for (cur = RB_MIN(pf_state_tree_id, &tree_id);
> cur; cur = next) {
> next = RB_NEXT(pf_state_tree_id, &tree_id, cur);
>
> #ifdef __FreeBSD__
> if (pf_state_expires(cur) <= time_second) {
> #else
> if (pf_state_expires(cur) <= time.tv_sec) {
> #endif
> 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,
> cur->src.seqhi, cur->src.seqlo + 1, 0,
> TH_RST|TH_ACK, 0, 0);
> 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);
614c925
< pfsync_delete_state(cur->state);
---
> pfsync_delete_state(cur);
616,629c927,941
< if (--cur->state->rule.ptr->states <= 0)
< pf_rm_rule(NULL, cur->state->rule.ptr);
< if (cur->state->nat_rule.ptr != NULL)
< if (--cur->state->nat_rule.ptr->states <= 0)
< pf_rm_rule(NULL,
< cur->state->nat_rule.ptr);
< if (cur->state->anchor.ptr != NULL)
< if (--cur->state->anchor.ptr->states <= 0)
< pf_rm_rule(NULL,
< cur->state->anchor.ptr);
< pf_normalize_tcp_cleanup(cur->state);
< pool_put(&pf_state_pl, cur->state);
< pool_put(&pf_tree_pl, cur);
< pool_put(&pf_tree_pl, peer);
---
> pf_src_tree_remove_state(cur);
> if (--cur->rule.ptr->states <= 0 &&
> cur->rule.ptr->src_nodes <= 0)
> pf_rm_rule(NULL, cur->rule.ptr);
> if (cur->nat_rule.ptr != NULL)
> if (--cur->nat_rule.ptr->states <= 0 &&
> cur->nat_rule.ptr->src_nodes <= 0)
> pf_rm_rule(NULL, cur->nat_rule.ptr);
> if (cur->anchor.ptr != NULL)
> if (--cur->anchor.ptr->states <= 0)
> pf_rm_rule(NULL, cur->anchor.ptr);
> pf_normalize_tcp_cleanup(cur);
> pfi_detach_state(cur->u.s.kif);
> TAILQ_REMOVE(&state_updates, cur, u.s.entry_updates);
> pool_put(&pf_state_pl, cur);
669,711d980
< int
< pf_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
< {
< if (aw->type != PF_ADDR_DYNIFTL)
< return (0);
< aw->p.dyn = pool_get(&pf_addr_pl, PR_NOWAIT);
< if (aw->p.dyn == NULL)
< return (1);
< bcopy(aw->v.ifname, aw->p.dyn->ifname, sizeof(aw->p.dyn->ifname));
< aw->p.dyn->ifp = ifunit(aw->p.dyn->ifname);
< if (aw->p.dyn->ifp == NULL) {
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< return (1);
< }
< aw->p.dyn->addr = &aw->v.a.addr;
< aw->p.dyn->af = af;
< aw->p.dyn->undefined = 1;
< #ifndef __FreeBSD__
< aw->p.dyn->hook_cookie = hook_establish(
< aw->p.dyn->ifp->if_addrhooks, 1,
< pf_dynaddr_update, aw->p.dyn);
< if (aw->p.dyn->hook_cookie == NULL) {
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< return (1);
< }
< #else
< PF_UNLOCK();
< aw->p.dyn->hook_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
< pf_dynaddr_update_event, aw->p.dyn, EVENTHANDLER_PRI_ANY);
< PF_LOCK();
< if (aw->p.dyn->hook_cookie == NULL) {
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< return (1);
< }
< #endif
< pf_dynaddr_update(aw->p.dyn);
< return (0);
< }
<
< #ifdef __FreeBSD__
713,792d981
< pf_dynaddr_update_event(void *arg, struct ifnet *ifp)
< {
< PF_LOCK();
< pf_dynaddr_update(arg);
< PF_UNLOCK();
< }
< #endif
<
< void
< pf_dynaddr_update(void *p)
< {
< struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p;
< struct ifaddr *ia;
< int s, changed = 0;
<
< if (ad == NULL || ad->ifp == NULL)
< panic("pf_dynaddr_update");
< s = splsoftnet();
< TAILQ_FOREACH(ia, &ad->ifp->if_addrlist, ifa_list)
< if (ia->ifa_addr != NULL &&
< ia->ifa_addr->sa_family == ad->af) {
< if (ad->af == AF_INET) {
< struct in_addr *a, *b;
<
< a = &ad->addr->v4;
< b = &((struct sockaddr_in *)ia->ifa_addr)
< ->sin_addr;
< if (ad->undefined ||
< memcmp(a, b, sizeof(*a))) {
< bcopy(b, a, sizeof(*a));
< changed = 1;
< }
< } else if (ad->af == AF_INET6) {
< struct in6_addr *a, *b;
<
< a = &ad->addr->v6;
< b = &((struct sockaddr_in6 *)ia->ifa_addr)
< ->sin6_addr;
< if (ad->undefined ||
< memcmp(a, b, sizeof(*a))) {
< bcopy(b, a, sizeof(*a));
< changed = 1;
< }
< }
< if (changed)
< ad->undefined = 0;
< break;
< }
< if (ia == NULL)
< ad->undefined = 1;
< splx(s);
< }
<
< void
< pf_dynaddr_remove(struct pf_addr_wrap *aw)
< {
< if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
< return;
< #ifndef __FreeBSD__
< hook_disestablish(aw->p.dyn->ifp->if_addrhooks,
< aw->p.dyn->hook_cookie);
< #else
< PF_UNLOCK();
< EVENTHANDLER_DEREGISTER(ifaddr_event, aw->p.dyn->hook_cookie);
< PF_LOCK();
< #endif
< pool_put(&pf_addr_pl, aw->p.dyn);
< aw->p.dyn = NULL;
< }
<
< void
< pf_dynaddr_copyout(struct pf_addr_wrap *aw)
< {
< if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
< return;
< bcopy(aw->p.dyn->ifname, aw->v.ifname, sizeof(aw->v.ifname));
< aw->p.dyn = (struct pf_addr_dyn *)1;
< }
<
< void
937c1126
< if (cur->ifp != prev->ifp || cur->ifnot != prev->ifnot)
---
> if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
980,984c1169
< if (aw1->p.dyn->ifp != aw2->p.dyn->ifp)
< return (1);
< if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
< return (1);
< return (0);
---
> return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt);
996,1022d1180
< pf_rule_set_qid(struct pf_rulequeue *rules)
< {
< struct pf_rule *rule;
<
< TAILQ_FOREACH(rule, rules, entries)
< if (rule->qname[0] != 0) {
< rule->qid = pf_qname_to_qid(rule->qname);
< if (rule->pqname[0] != 0)
< rule->pqid = pf_qname_to_qid(rule->pqname);
< else
< rule->pqid = rule->qid;
< }
< }
<
< u_int32_t
< pf_qname_to_qid(char *qname)
< {
< struct pf_altq *altq;
<
< TAILQ_FOREACH(altq, pf_altqs_active, entries)
< if (!strcmp(altq->qname, qname))
< return (altq->qid);
<
< return (0);
< }
<
< void
1235,1236d1392
< #if (__FreeBSD_version < 501114)
< struct route ro;
1238d1393
< #endif
1345c1500,1501
< h->ip_off = htons(path_mtu_discovery ? IP_DF : 0);
---
> h->ip_off = path_mtu_discovery ? IP_DF : 0;
> h->ip_len = len;
1348d1503
< #endif
1349a1505
> #endif
1354,1364d1509
< /*
< * XXX
< * OpenBSD changed ip_len/ip_off byte ordering!
< * Because FreeBSD assumes host byte ordering we need to
< * change here.
< */
< NTOHS(ip->ip_len);
< NTOHS(ip->ip_off);
< #if (__FreeBSD_version < 501114)
< bzero(&ro, sizeof(ro));
< ip_rtaddr(ip->ip_dst, &ro);
1366,1373d1510
< ip_output(m, (void *)NULL, &ro, 0, (void *)NULL,
< (void *)NULL);
< PF_LOCK();
< if(ro.ro_rt) {
< RTFREE(ro.ro_rt);
< }
< #else /* __FreeBSD_version >= 501114 */
< PF_UNLOCK();
1377d1513
< #endif
1455c1591
< icmp_error(m0, type, code, 0, NULL);
---
> icmp_error(m0, type, code, 0, (void *)NULL);
1584,1585c1720,1721
< pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat,
< struct pf_rule *rdr, struct pf_tag *pftag, int *tag)
---
> pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat_rule,
> struct pf_tag *pftag, int *tag)
1593,1596c1729,1730
< if (nat != NULL && nat->tag)
< *tag = nat->tag;
< if (rdr != NULL && rdr->tag)
< *tag = rdr->tag;
---
> if (nat_rule != NULL && nat_rule->tag)
> *tag = nat_rule->tag;
1680c1814
< pf_addr_inc(struct pf_addr *addr, u_int8_t af)
---
> pf_addr_inc(struct pf_addr *addr, sa_family_t af)
1769,1770c1903,1904
< pf_map_addr(u_int8_t af, struct pf_pool *rpool, struct pf_addr *saddr,
< struct pf_addr *naddr, struct pf_addr *init_addr)
---
> pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
> struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
1773,1774c1907,1909
< struct pf_addr *raddr;
< struct pf_addr *rmask;
---
> struct pf_pool *rpool = &r->rpool;
> struct pf_addr *raddr = &rpool->cur->addr.v.a.addr;
> struct pf_addr *rmask = &rpool->cur->addr.v.a.mask;
1775a1911
> struct pf_src_node k;
1776a1913,1936
> if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
> (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
> k.af = af;
> PF_ACPY(&k.addr, saddr, af);
> if (r->rule_flag & PFRULE_RULESRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR)
> k.rule.ptr = r;
> else
> k.rule.ptr = NULL;
> pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
> *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
> if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
> PF_ACPY(naddr, &(*sn)->raddr, af);
> if (pf_status.debug >= PF_DEBUG_MISC) {
> printf("pf_map_addr: src tracking maps ");
> pf_print_host(&k.addr, 0, af);
> printf(" to ");
> pf_print_host(naddr, 0, af);
> printf("\n");
> }
> return (0);
> }
> }
>
1779,1782c1939,1955
< if (rpool->cur->addr.type == PF_ADDR_DYNIFTL &&
< rpool->cur->addr.p.dyn->undefined)
< return (1);
< if (rpool->cur->addr.type == PF_ADDR_TABLE) {
---
> if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
> if (af == AF_INET) {
> if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
> (rpool->opts & PF_POOL_TYPEMASK) !=
> PF_POOL_ROUNDROBIN)
> return (1);
> raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
> rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
> } else {
> if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
> (rpool->opts & PF_POOL_TYPEMASK) !=
> PF_POOL_ROUNDROBIN)
> return (1);
> raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
> rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
> }
> } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
1841a2015,2019
> } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
> if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
> &rpool->tblidx, &rpool->counter,
> &raddr, &rmask, af))
> goto get_addr;
1853c2031
< /* table contain no address of type 'af' */
---
> /* table contains no address of type 'af' */
1857a2036,2045
> } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
> rpool->tblidx = -1;
> if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
> &rpool->tblidx, &rpool->counter,
> &raddr, &rmask, af)) {
> /* table contains no address of type 'af' */
> if (rpool->cur != acur)
> goto try_next;
> return (1);
> }
1868a2057,2058
> if (*sn != NULL)
> PF_ACPY(&(*sn)->raddr, naddr, af);
1872c2062
< printf("pf_map_addr: selected address: ");
---
> printf("pf_map_addr: selected address ");
1881c2071
< pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_pool *rpool,
---
> pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
1883c2073,2074
< struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high)
---
> struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
> struct pf_src_node **sn)
1885c2076
< struct pf_tree_node key;
---
> struct pf_state key;
1890c2081
< if (pf_map_addr(af, rpool, saddr, naddr, &init_addr))
---
> if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
1896,1898c2087,2089
< PF_ACPY(&key.addr[0], daddr, key.af);
< PF_ACPY(&key.addr[1], naddr, key.af);
< key.port[0] = dport;
---
> PF_ACPY(&key.ext.addr, daddr, key.af);
> PF_ACPY(&key.gwy.addr, naddr, key.af);
> key.ext.port = dport;
1905,1906c2096,2097
< key.port[1] = 0;
< if (pf_find_state(&tree_ext_gwy, &key) == NULL)
---
> key.gwy.port = 0;
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
1909,1910c2100,2101
< key.port[1] = *nport;
< if (pf_find_state(&tree_ext_gwy, &key) == NULL) {
---
> key.gwy.port = *nport;
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
1912d2102
< }
1914,1915c2104,2105
< key.port[1] = htons(low);
< if (pf_find_state(&tree_ext_gwy, &key) == NULL) {
---
> key.gwy.port = htons(low);
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) {
1931,1932c2121,2122
< key.port[1] = htons(tmp);
< if (pf_find_state(&tree_ext_gwy, &key) ==
---
> key.gwy.port = htons(tmp);
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
1939,1940c2129,2130
< key.port[1] = htons(tmp);
< if (pf_find_state(&tree_ext_gwy, &key) ==
---
> key.gwy.port = htons(tmp);
> if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
1948c2138
< switch (rpool->opts & PF_POOL_TYPEMASK) {
---
> switch (r->rpool.opts & PF_POOL_TYPEMASK) {
1951c2141
< if (pf_map_addr(af, rpool, saddr, naddr, &init_addr))
---
> if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
1959d2148
< break;
1968c2157
< int direction, struct ifnet *ifp, struct pf_addr *saddr, u_int16_t sport,
---
> int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
1989,1990c2178,2179
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
2036c2225
< struct ifnet *ifp,
---
> struct pfi_kif *kif, struct pf_src_node **sn,
2044c2233
< r = pf_match_translation(pd, m, off, direction, ifp, saddr,
---
> r = pf_match_translation(pd, m, off, direction, kif, saddr,
2047c2236
< r = pf_match_translation(pd, m, off, direction, ifp,
---
> r = pf_match_translation(pd, m, off, direction, kif,
2050c2239
< r = pf_match_translation(pd, m, off, direction, ifp, saddr,
---
> r = pf_match_translation(pd, m, off, direction, kif, saddr,
2053c2242
< r = pf_match_translation(pd, m, off, direction, ifp,
---
> r = pf_match_translation(pd, m, off, direction, kif,
2063d2251
< break;
2065c2253
< if (pf_get_sport(pd->af, pd->proto, &r->rpool, saddr,
---
> if (pf_get_sport(pd->af, pd->proto, r, saddr,
2067c2255
< r->rpool.proxy_port[1])) {
---
> r->rpool.proxy_port[1], sn)) {
2079,2083c2267,2289
< if (r->rpool.cur->addr.type ==
< PF_ADDR_DYNIFTL &&
< r->rpool.cur->addr.p.dyn->undefined)
< return (NULL);
< else
---
> if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
> if (pd->af == AF_INET) {
> if (r->rpool.cur->addr.p.dyn->
> pfid_acnt4 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->rpool.cur->addr.p.dyn->
> pfid_addr4,
> &r->rpool.cur->addr.p.dyn->
> pfid_mask4,
> saddr, AF_INET);
> } else {
> if (r->rpool.cur->addr.p.dyn->
> pfid_acnt6 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->rpool.cur->addr.p.dyn->
> pfid_addr6,
> &r->rpool.cur->addr.p.dyn->
> pfid_mask6,
> saddr, AF_INET6);
> }
> } else
2090,2093c2296,2318
< if (r->src.addr.type == PF_ADDR_DYNIFTL &&
< r->src.addr.p.dyn->undefined)
< return (NULL);
< else
---
> if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
> if (pd->af == AF_INET) {
> if (r->src.addr.p.dyn->
> pfid_acnt4 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->src.addr.p.dyn->
> pfid_addr4,
> &r->src.addr.p.dyn->
> pfid_mask4,
> daddr, AF_INET);
> } else {
> if (r->src.addr.p.dyn->
> pfid_acnt6 < 1)
> return (NULL);
> PF_POOLMASK(naddr,
> &r->src.addr.p.dyn->
> pfid_addr6,
> &r->src.addr.p.dyn->
> pfid_mask6,
> daddr, AF_INET6);
> }
> } else
2102c2327
< if (pf_map_addr(r->af, &r->rpool, saddr, naddr, NULL))
---
> if (pf_map_addr(r->af, r, saddr, naddr, NULL, sn))
2124d2348
< break;
2132,2133c2356
< pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, sa_family_t af,
< int proto, struct pf_pdesc *pd)
---
> pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
2146c2369
< switch (proto) {
---
> switch (pd->proto) {
2180c2403
< switch(af) {
---
> switch (pd->af) {
2183d2405
< #if (__FreeBSD_version >= 500043)
2185d2406
< #endif
2192d2412
< #if (__FreeBSD_version >= 500043)
2194d2413
< #endif
2201,2202c2420
< inp = in_pcblookup(tb, &saddr->v4, sport, &daddr->v4,
< dport, INPLOOKUP_WILDCARD);
---
> inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
2211d2428
< #if (__FreeBSD_version >= 500043)
2213d2429
< #endif
2220d2435
< #if (__FreeBSD_version >= 500043)
2222d2436
< #endif
2230,2231c2444
< inp = in_pcblookup(tb, &saddr->v6, sport, &daddr->v6,
< dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
---
> inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0);
2243d2455
< #if (__FreeBSD_version >= 500043)
2245d2456
< #endif
2248d2458
< #if (__FreeBSD_version >= 500043)
2251d2460
< #endif
2286c2495
< /* fallthrough */
---
> /* FALLTHROUGH */
2292a2502
> break;
2322c2532
< /* fallthrough */
---
> /* FALLTHROUGH */
2328a2539
> break;
2408c2619
< s->rt_ifp = NULL;
---
> s->rt_kif = NULL;
2414,2416c2625,2627
< pf_map_addr(AF_INET, &r->rpool, saddr,
< &s->rt_addr, NULL);
< s->rt_ifp = r->rpool.cur->ifp;
---
> pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL,
> &s->nat_src_node);
> s->rt_kif = r->rpool.cur->kif;
2421,2423c2632,2634
< pf_map_addr(AF_INET6, &r->rpool, saddr,
< &s->rt_addr, NULL);
< s->rt_ifp = r->rpool.cur->ifp;
---
> pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL,
> &s->nat_src_node);
> s->rt_kif = r->rpool.cur->kif;
2431c2642
< struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h,
2434c2645
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
2436d2646
< struct pf_addr baddr, naddr;
2444a2655
> struct pf_src_node *nsn = NULL;
2456c2667
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp,
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
2458,2459c2669,2670
< &naddr, &nport)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> &pd->naddr, &nport)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
2461c2672
< &th->th_sum, &naddr, nport, 0, af);
---
> &th->th_sum, &pd->naddr, nport, 0, af);
2463c2674
< if (nat->natpass)
---
> if (nr->natpass)
2464a2676
> pd->nat_rule = nr;
2469,2472c2681,2684
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr,
< th->th_sport, daddr, th->th_dport,
< &naddr, &nport)) != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, th->th_sport, daddr, th->th_dport,
> &pd->naddr, &nport)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
2474c2686
< &th->th_sum, &naddr, nport, 0, af);
---
> &th->th_sum, &pd->naddr, nport, 0, af);
2476c2688
< if (rdr->natpass)
---
> if (nr->natpass)
2477a2690
> pd->nat_rule = nr;
2483,2484c2696,2697
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
2509,2510c2722
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2515,2516c2727
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2520,2521c2731
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
2550,2555d2759
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
2561c2765
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
2569,2576c2773,2782
< if (nat != NULL) {
< pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
< &th->th_sum, &baddr, bport, 0, af);
< rewrite++;
< } else if (rdr != NULL) {
< pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
< &th->th_sum, &baddr, bport, 0, af);
< rewrite++;
---
> if (nr != NULL) {
> if (direction == PF_OUT) {
> pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
> &th->th_sum, &pd->baddr, bport, 0, af);
> rewrite++;
> } else {
> pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
> &th->th_sum, &pd->baddr, bport, 0, af);
> rewrite++;
> }
2607c2813
< if (r->keep_state || nat != NULL || rdr != NULL ||
---
> if (r->keep_state || nr != NULL ||
2611a2818
> struct pf_src_node *sn = NULL;
2614,2615c2821,2836
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
>
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
2616a2838,2851
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
2625,2628c2860
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
2642,2643c2874,2875
< if (nat != NULL) {
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
2654,2655c2886,2887
< if (rdr != NULL) {
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
2689d2920
< s->dst.seqlo = 0; /* Haven't seen these yet */
2692d2922
< s->dst.seqdiff = 0; /* Defer random generation */
2703,2704d2932
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
2706c2934,2942
<
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
2709a2946
> pf_src_tree_remove_state(s);
2716a2954
> pf_src_tree_remove_state(s);
2720c2958
< if (pf_insert_state(s)) {
---
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
2722a2961
> pf_src_tree_remove_state(s);
2730,2737c2969,2979
< if (nat != NULL)
< pf_change_ap(saddr, &th->th_sport,
< pd->ip_sum, &th->th_sum, &baddr,
< bport, 0, af);
< else if (rdr != NULL)
< pf_change_ap(daddr, &th->th_dport,
< pd->ip_sum, &th->th_sum, &baddr,
< bport, 0, af);
---
> if (nr != NULL) {
> if (direction == PF_OUT) {
> pf_change_ap(saddr, &th->th_sport,
> pd->ip_sum, &th->th_sum, &pd->baddr,
> bport, 0, af);
> } else {
> pf_change_ap(daddr, &th->th_dport,
> pd->ip_sum, &th->th_sum, &pd->baddr,
> bport, 0, af);
> }
> }
2745,2746c2987,2988
< th->th_sport, s->src.seqhi,
< ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0);
---
> th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
> TH_SYN|TH_ACK, 0, s->src.mss, 0);
2760c3002
< struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h,
2763c3005
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
2765d3006
< struct pf_addr baddr, naddr;
2773a3015
> struct pf_src_node *nsn = NULL;
2784c3026
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp,
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
2786,2787c3028,3029
< &naddr, &nport)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> &pd->naddr, &nport)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
2789c3031
< &uh->uh_sum, &naddr, nport, 1, af);
---
> &uh->uh_sum, &pd->naddr, nport, 1, af);
2791c3033
< if (nat->natpass)
---
> if (nr->natpass)
2792a3035
> pd->nat_rule = nr;
2797,2800c3040,3043
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr,
< uh->uh_sport, daddr, uh->uh_dport, &naddr, &nport))
< != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, uh->uh_sport, daddr, uh->uh_dport, &pd->naddr,
> &nport)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
2802c3045
< &uh->uh_sum, &naddr, nport, 1, af);
---
> &uh->uh_sum, &pd->naddr, nport, 1, af);
2804c3047
< if (rdr->natpass)
---
> if (nr->natpass)
2805a3049
> pd->nat_rule = nr;
2811,2812c3055,3056
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
2835,2836c3079
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2841,2842c3084
< pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
< pd), 1)) &&
---
> pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
2846,2847c3088
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
2875,2880d3115
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
2886c3121
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
2893,2900c3128,3137
< if (nat != NULL) {
< pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
< &uh->uh_sum, &baddr, bport, 1, af);
< rewrite++;
< } else if (rdr != NULL) {
< pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
< &uh->uh_sum, &baddr, bport, 1, af);
< rewrite++;
---
> if (nr != NULL) {
> if (direction == PF_OUT) {
> pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
> &uh->uh_sum, &pd->baddr, bport, 1, af);
> rewrite++;
> } else {
> pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
> &uh->uh_sum, &pd->baddr, bport, 1, af);
> rewrite++;
> }
2918c3155
< if (r->keep_state || nat != NULL || rdr != NULL) {
---
> if (r->keep_state || nr != NULL) {
2920a3158
> struct pf_src_node *sn = NULL;
2922,2923c3160,3174
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
2924a3176,3189
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
2933,2936c3198
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
2950,2951c3212,3213
< if (nat != NULL) {
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
2962,2963c3224,3225
< if (rdr != NULL) {
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL) {
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
2970,2973d3231
< s->src.seqlo = 0;
< s->src.seqhi = 0;
< s->src.seqdiff = 0;
< s->src.max_win = 0;
2975,2978d3232
< s->dst.seqlo = 0;
< s->dst.seqhi = 0;
< s->dst.seqdiff = 0;
< s->dst.max_win = 0;
2988,2989d3241
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
2991c3243,3252
< if (pf_insert_state(s)) {
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
2992a3254
> pf_src_tree_remove_state(s);
3008c3270
< struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h,
3011c3273
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
3013d3274
< struct pf_addr baddr, naddr;
3015a3277
> struct pf_src_node *nsn = NULL;
3062,3064c3324,3326
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
3069c3331
< naddr.v4.s_addr, 0);
---
> pd->naddr.v4.s_addr, 0);
3075c3337
< &naddr, 0);
---
> &pd->naddr, 0);
3080c3342
< if (nat->natpass)
---
> if (nr->natpass)
3081a3344
> pd->nat_rule = nr;
3085,3087c3348,3350
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
3092c3355
< pd->ip_sum, naddr.v4.s_addr, 0);
---
> pd->ip_sum, pd->naddr.v4.s_addr, 0);
3098c3361
< &naddr, 0);
---
> &pd->naddr, 0);
3103c3366
< if (rdr->natpass)
---
> if (nr->natpass)
3104a3368
> pd->nat_rule = nr;
3110,3111c3374,3375
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
3131,3132c3395
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
3160,3165d3422
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
3174c3431
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
3185,3186c3442
< if (!state_icmp && (r->keep_state ||
< nat != NULL || rdr != NULL)) {
---
> if (!state_icmp && (r->keep_state || nr != NULL)) {
3188a3445
> struct pf_src_node *sn = NULL;
3190,3191c3447,3461
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
3192a3463,3476
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
3201,3204c3485
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
3218,3219c3499,3500
< if (nat != NULL)
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
3228,3229c3509,3510
< if (rdr != NULL)
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
3234,3244d3514
<
< s->src.seqlo = 0;
< s->src.seqhi = 0;
< s->src.seqdiff = 0;
< s->src.max_win = 0;
< s->src.state = 0;
< s->dst.seqlo = 0;
< s->dst.seqhi = 0;
< s->dst.seqdiff = 0;
< s->dst.max_win = 0;
< s->dst.state = 0;
3253,3254d3522
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
3256c3524,3533
< if (pf_insert_state(s)) {
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
3257a3535
> pf_src_tree_remove_state(s);
3276c3554
< struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
---
> struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
3279c3557
< struct pf_rule *nat = NULL, *rdr = NULL;
---
> struct pf_rule *nr = NULL;
3281a3560
> struct pf_src_node *nsn = NULL;
3283d3561
< struct pf_addr baddr, naddr;
3293,3295c3571,3573
< if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, saddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, saddr, af);
3300c3578
< naddr.v4.s_addr, 0);
---
> pd->naddr.v4.s_addr, 0);
3305c3583
< PF_ACPY(saddr, &naddr, af);
---
> PF_ACPY(saddr, &pd->naddr, af);
3309c3587
< if (nat->natpass)
---
> if (nr->natpass)
3310a3589
> pd->nat_rule = nr;
3314,3316c3593,3595
< if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0,
< daddr, 0, &naddr, NULL)) != NULL) {
< PF_ACPY(&baddr, daddr, af);
---
> if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
> saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
> PF_ACPY(&pd->baddr, daddr, af);
3321c3600
< pd->ip_sum, naddr.v4.s_addr, 0);
---
> pd->ip_sum, pd->naddr.v4.s_addr, 0);
3326c3605
< PF_ACPY(daddr, &naddr, af);
---
> PF_ACPY(daddr, &pd->naddr, af);
3330c3609
< if (rdr->natpass)
---
> if (nr->natpass)
3331a3611
> pd->nat_rule = nr;
3337,3338c3617,3618
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
3354,3355c3634
< else if (r->match_tag &&
< !pf_match_tag(m, r, nat, rdr, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
3383,3388d3661
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
3389a3663
>
3391c3665
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
3398,3401c3672,3677
< if (nat != NULL)
< a = saddr;
< else if (rdr != NULL)
< a = daddr;
---
> if (nr != NULL) {
> if (direction == PF_OUT)
> a = saddr;
> else
> a = daddr;
> }
3407c3683
< baddr.v4.s_addr, 0);
---
> pd->baddr.v4.s_addr, 0);
3412c3688
< PF_ACPY(a, &baddr, af);
---
> PF_ACPY(a, &pd->baddr, af);
3433c3709
< if (r->keep_state || nat != NULL || rdr != NULL) {
---
> if (r->keep_state || nr != NULL) {
3435a3712
> struct pf_src_node *sn = NULL;
3437,3438c3714,3728
< if (!r->max_states || r->states < r->max_states)
< s = pool_get(&pf_state_pl, PR_NOWAIT);
---
> /* check maximums */
> if (r->max_states && (r->states >= r->max_states))
> goto cleanup;
> /* src node for flter rule */
> if ((r->rule_flag & PFRULE_SRCTRACK ||
> r->rpool.opts & PF_POOL_STICKYADDR) &&
> pf_insert_src_node(&sn, r, saddr, af) != 0)
> goto cleanup;
> /* src node for translation rule */
> if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
> ((direction == PF_OUT &&
> pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
> (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
> goto cleanup;
> s = pool_get(&pf_state_pl, PR_NOWAIT);
3439a3730,3743
> cleanup:
> if (sn != NULL && sn->states == 0 && sn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, sn);
> }
> if (nsn != sn && nsn != NULL && nsn->states == 0 &&
> nsn->expire == 0) {
> RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
> pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
> pf_status.src_nodes--;
> pool_put(&pf_src_tree_pl, nsn);
> }
3448,3451c3752
< if (nat != NULL)
< s->nat_rule.ptr = nat;
< else
< s->nat_rule.ptr = rdr;
---
> s->nat_rule.ptr = nr;
3462d3762
< s->gwy.port = 0;
3464,3466c3764,3765
< s->ext.port = 0;
< if (nat != NULL)
< PF_ACPY(&s->lan.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->lan.addr, &pd->baddr, af);
3469d3767
< s->lan.port = 0;
3472d3769
< s->lan.port = 0;
3474,3476c3771,3772
< s->ext.port = 0;
< if (rdr != NULL)
< PF_ACPY(&s->gwy.addr, &baddr, af);
---
> if (nr != NULL)
> PF_ACPY(&s->gwy.addr, &pd->baddr, af);
3479d3774
< s->gwy.port = 0;
3481,3484d3775
< s->src.seqlo = 0;
< s->src.seqhi = 0;
< s->src.seqdiff = 0;
< s->src.max_win = 0;
3486,3489d3776
< s->dst.seqlo = 0;
< s->dst.seqhi = 0;
< s->dst.seqdiff = 0;
< s->dst.max_win = 0;
3499,3500d3785
< s->packets[0] = 1;
< s->bytes[0] = pd->tot_len;
3502c3787,3796
< if (pf_insert_state(s)) {
---
> if (sn != NULL) {
> s->src_node = sn;
> s->src_node->states++;
> }
> if (nsn != NULL) {
> PF_ACPY(&nsn->raddr, &pd->naddr, af);
> s->nat_src_node = nsn;
> s->nat_src_node->states++;
> }
> if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
3504,3506c3798
< if (r->log)
< PFLOG_PACKET(ifp, h, m, af, direction, reason,
< r, a, ruleset);
---
> pf_src_tree_remove_state(s);
3517c3809
< pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
---
> pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
3531,3532c3823,3824
< if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
< (r->ifp == ifp && r->ifnot)))
---
> if (r->kif != NULL &&
> (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
3550,3551c3842
< else if (r->match_tag &&
< !pf_match_tag(m, r, NULL, NULL, pftag, &tag))
---
> else if (r->match_tag && !pf_match_tag(m, r, NULL, pftag, &tag))
3575,3580d3865
< r->packets++;
< r->bytes += pd->tot_len;
< if (a != NULL) {
< a->packets++;
< a->bytes += pd->tot_len;
< }
3581a3867
>
3583c3869
< PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
3597,3598c3883,3884
< pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp,
< struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd,
---
> pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
> struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
3601c3887
< struct pf_tree_node key;
---
> struct pf_state key;
3606c3892
< int ackskew, dirndx;
---
> int ackskew;
3612,3615c3898,3908
< PF_ACPY(&key.addr[0], pd->src, key.af);
< PF_ACPY(&key.addr[1], pd->dst, key.af);
< key.port[0] = th->th_sport;
< key.port[1] = th->th_dport;
---
> 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;
> }
3622d3914
< dirndx = 0;
3626d3917
< dirndx = 1;
3667c3958,3959
< (*state)->dst.seqhi, 0, TH_SYN, 0, (*state)->src.mss, 0);
---
> (*state)->dst.seqhi, 0, TH_SYN, 0,
> (*state)->src.mss, 0);
3824,3826d4115
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
3915,3917d4203
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
3983,3984c4269,4270
< if (pf_normalize_tcp_stateful(m, off, pd, reason, th, src, dst,
< ©back))
---
> if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
> src, dst, ©back))
4006,4015d4291
< (*state)->rule.ptr->packets++;
< (*state)->rule.ptr->bytes += pd->tot_len;
< if ((*state)->nat_rule.ptr != NULL) {
< (*state)->nat_rule.ptr->packets++;
< (*state)->nat_rule.ptr->bytes += pd->tot_len;
< }
< if ((*state)->anchor.ptr != NULL) {
< (*state)->anchor.ptr->packets++;
< (*state)->anchor.ptr->bytes += pd->tot_len;
< }
4020,4021c4296,4297
< pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp,
< struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd)
---
> pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
> struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
4024c4300
< struct pf_tree_node key;
---
> struct pf_state key;
4026d4301
< int dirndx;
4030,4033c4305,4315
< PF_ACPY(&key.addr[0], pd->src, key.af);
< PF_ACPY(&key.addr[1], pd->dst, key.af);
< key.port[0] = uh->uh_sport;
< key.port[1] = uh->uh_dport;
---
> 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;
> }
4040d4321
< dirndx = 0;
4044d4324
< dirndx = 1;
4047,4049d4326
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
4080,4089d4356
< (*state)->rule.ptr->packets++;
< (*state)->rule.ptr->bytes += pd->tot_len;
< if ((*state)->nat_rule.ptr != NULL) {
< (*state)->nat_rule.ptr->packets++;
< (*state)->nat_rule.ptr->bytes += pd->tot_len;
< }
< if ((*state)->anchor.ptr != NULL) {
< (*state)->anchor.ptr->packets++;
< (*state)->anchor.ptr->bytes += pd->tot_len;
< }
4094,4095c4361,4362
< pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
< struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd)
---
> 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)
4101c4368
< int state_icmp = 0, dirndx;
---
> int state_icmp = 0;
4139c4406
< struct pf_tree_node key;
---
> struct pf_state key;
4143,4146c4410,4420
< PF_ACPY(&key.addr[0], saddr, key.af);
< PF_ACPY(&key.addr[1], daddr, key.af);
< key.port[0] = icmpid;
< key.port[1] = icmpid;
---
> 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 = icmpid;
> 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 = icmpid;
> }
4150,4152d4423
< dirndx = (direction == (*state)->direction) ? 0 : 1;
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
4312c4583
< struct pf_tree_node key;
---
> struct pf_state key;
4331,4334c4602,4612
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = th.th_dport;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = th.th_sport;
---
> 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;
> }
4346c4624,4625
< if (src->wscale && dst->wscale && !(th.th_flags & TH_SYN))
---
> if (src->wscale && dst->wscale &&
> !(th.th_flags & TH_SYN))
4419c4698
< struct pf_tree_node key;
---
> struct pf_state key;
4431,4434c4710,4720
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = uh.uh_dport;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = uh.uh_sport;
---
> 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;
> }
4481c4767
< struct pf_tree_node key;
---
> struct pf_state key;
4493,4496c4779,4789
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = iih.icmp_id;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = iih.icmp_id;
---
> 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 = iih.icmp_id;
> 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 = iih.icmp_id;
> }
4529c4822
< struct pf_tree_node key;
---
> struct pf_state key;
4541,4544c4834,4844
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = iih.icmp6_id;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = iih.icmp6_id;
---
> 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 = iih.icmp6_id;
> key.gwy.port = 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 = iih.icmp6_id;
> }
4575c4875
< struct pf_tree_node key;
---
> struct pf_state key;
4579,4582c4879,4889
< PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
< key.port[0] = 0;
< PF_ACPY(&key.addr[1], pd2.src, pd2.af);
< key.port[1] = 0;
---
> 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;
> } 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;
> }
4629c4936
< pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp,
---
> pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
4633,4634c4940
< struct pf_tree_node key;
< int dirndx;
---
> struct pf_state key;
4638,4641c4944,4954
< PF_ACPY(&key.addr[0], pd->src, key.af);
< PF_ACPY(&key.addr[1], pd->dst, key.af);
< key.port[0] = 0;
< key.port[1] = 0;
---
> 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;
> } 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;
> }
4648d4960
< dirndx = 0;
4652d4963
< dirndx = 1;
4655,4657d4965
< (*state)->packets[dirndx]++;
< (*state)->bytes[dirndx] += pd->tot_len;
<
4709,4718d5016
< (*state)->rule.ptr->packets++;
< (*state)->rule.ptr->bytes += pd->tot_len;
< if ((*state)->nat_rule.ptr != NULL) {
< (*state)->nat_rule.ptr->packets++;
< (*state)->nat_rule.ptr->bytes += pd->tot_len;
< }
< if ((*state)->anchor.ptr != NULL) {
< (*state)->anchor.ptr->packets++;
< (*state)->anchor.ptr->bytes += pd->tot_len;
< }
4745c5043,5044
< if (m->m_pkthdr.len < off + len || ntohs(h->ip_len) < off + len) {
---
> if (m->m_pkthdr.len < off + len ||
> ntohs(h->ip_len) < off + len) {
4804,4964d5102
< #if defined(__FreeBSD__) && (__FreeBSD_version < 501105)
< int
< ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
< u_long if_hwassist_flags, int sw_csum)
< {
< int error = 0;
< int hlen = ip->ip_hl << 2;
< int len = (mtu - hlen) & ~7; /* size of payload in each fragment */
< int off;
< struct mbuf *m0 = *m_frag; /* the original packet */
< int firstlen;
< struct mbuf **mnext;
< int nfrags;
<
< if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */
< ipstat.ips_cantfrag++;
< return EMSGSIZE;
< }
<
< /*
< * Must be able to put at least 8 bytes per fragment.
< */
< if (len < 8)
< return EMSGSIZE;
<
< /*
< * If the interface will not calculate checksums on
< * fragmented packets, then do it here.
< */
< if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA &&
< (if_hwassist_flags & CSUM_IP_FRAGS) == 0) {
< in_delayed_cksum(m0);
< m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
< }
<
< if (len > PAGE_SIZE) {
< /*
< * Fragment large datagrams such that each segment
< * contains a multiple of PAGE_SIZE amount of data,
< * plus headers. This enables a receiver to perform
< * page-flipping zero-copy optimizations.
< *
< * XXX When does this help given that sender and receiver
< * could have different page sizes, and also mtu could
< * be less than the receiver's page size ?
< */
< int newlen;
< struct mbuf *m;
<
< for (m = m0, off = 0; m && (off+m->m_len) <= mtu; m = m->m_next)
< off += m->m_len;
<
< /*
< * firstlen (off - hlen) must be aligned on an
< * 8-byte boundary
< */
< if (off < hlen)
< goto smart_frag_failure;
< off = ((off - hlen) & ~7) + hlen;
< newlen = (~PAGE_MASK) & mtu;
< if ((newlen + sizeof (struct ip)) > mtu) {
< /* we failed, go back the default */
< smart_frag_failure:
< newlen = len;
< off = hlen + len;
< }
< len = newlen;
<
< } else {
< off = hlen + len;
< }
<
< firstlen = off - hlen;
< mnext = &m0->m_nextpkt; /* pointer to next packet */
<
< /*
< * Loop through length of segment after first fragment,
< * make new header and copy data of each part and link onto chain.
< * Here, m0 is the original packet, m is the fragment being created.
< * The fragments are linked off the m_nextpkt of the original
< * packet, which after processing serves as the first fragment.
< */
< for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) {
< struct ip *mhip; /* ip header on the fragment */
< struct mbuf *m;
< int mhlen = sizeof (struct ip);
<
< MGETHDR(m, M_DONTWAIT, MT_HEADER);
< if (m == 0) {
< error = ENOBUFS;
< ipstat.ips_odropped++;
< goto done;
< }
< m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG;
< /*
< * In the first mbuf, leave room for the link header, then
< * copy the original IP header including options. The payload
< * goes into an additional mbuf chain returned by m_copy().
< */
< m->m_data += max_linkhdr;
< mhip = mtod(m, struct ip *);
< *mhip = *ip;
< if (hlen > sizeof (struct ip)) {
< mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
< mhip->ip_v = IPVERSION;
< mhip->ip_hl = mhlen >> 2;
< }
< m->m_len = mhlen;
< /* XXX do we need to add ip->ip_off below ? */
< mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off;
< if (off + len >= ip->ip_len) { /* last fragment */
< len = ip->ip_len - off;
< m->m_flags |= M_LASTFRAG;
< } else
< mhip->ip_off |= IP_MF;
< mhip->ip_len = htons((u_short)(len + mhlen));
< m->m_next = m_copy(m0, off, len);
< if (m->m_next == 0) { /* copy failed */
< m_free(m);
< error = ENOBUFS; /* ??? */
< ipstat.ips_odropped++;
< goto done;
< }
< m->m_pkthdr.len = mhlen + len;
< m->m_pkthdr.rcvif = (struct ifnet *)0;
< #ifdef MAC
< mac_create_fragment(m0, m);
< #endif
< m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags;
< mhip->ip_off = htons(mhip->ip_off);
< mhip->ip_sum = 0;
< if (sw_csum & CSUM_DELAY_IP)
< mhip->ip_sum = in_cksum(m, mhlen);
< *mnext = m;
< mnext = &m->m_nextpkt;
< }
< ipstat.ips_ofragments += nfrags;
<
< /* set first marker for fragment chain */
< m0->m_flags |= M_FIRSTFRAG | M_FRAG;
< m0->m_pkthdr.csum_data = nfrags;
<
< /*
< * Update first fragment by trimming what's been copied out
< * and updating header.
< */
< m_adj(m0, hlen + firstlen - ip->ip_len);
< m0->m_pkthdr.len = hlen + firstlen;
< ip->ip_len = htons((u_short)m0->m_pkthdr.len);
< ip->ip_off |= IP_MF;
< ip->ip_off = htons(ip->ip_off);
< ip->ip_sum = 0;
< if (sw_csum & CSUM_DELAY_IP)
< ip->ip_sum = in_cksum(m0, hlen);
<
< done:
< *m_frag = m0;
< return error;
< }
< #endif /* __FreeBSD__ && __FreeBSD_version > 501105 */
<
4976a5115
> struct pf_src_node *sn = NULL;
5035,5037c5174,5175
< pf_map_addr(AF_INET, &r->rpool,
< (struct pf_addr *)&ip->ip_src,
< &naddr, NULL);
---
> pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
> &naddr, NULL, &sn);
5040c5178,5179
< ifp = r->rpool.cur->ifp;
---
> ifp = r->rpool.cur->kif ?
> r->rpool.cur->kif->pfik_ifp : NULL;
5045c5184
< ifp = s->rt_ifp;
---
> ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
5052,5057c5191,5193
< if (m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL) != NULL)
< goto bad;
< mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
< if (mtag == NULL)
< goto bad;
< m_tag_prepend(m0, mtag);
---
> mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
> if (mtag == NULL) {
> struct m_tag *mtag;
5059c5195,5201
< if (oifp != ifp) {
---
> mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
> if (mtag == NULL)
> goto bad;
> m_tag_prepend(m0, mtag);
> }
>
> if (oifp != ifp && mtag == NULL) {
5122a5265,5292
> #ifdef IPSEC
> /*
> * If deferred crypto processing is needed, check that the
> * interface supports it.
> */
> if ((mtag = m_tag_find(m0, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL))
> != NULL && (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
> /* Notify IPsec to do its own crypto. */
> ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
> goto bad;
> }
> #endif /* IPSEC */
>
> /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
> if (m0->m_pkthdr.csum & M_TCPV4_CSUM_OUT) {
> if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
> ifp->if_bridge != NULL) {
> in_delayed_cksum(m0);
> m0->m_pkthdr.csum &= ~M_TCPV4_CSUM_OUT; /* Clear */
> }
> } else if (m0->m_pkthdr.csum & M_UDPV4_CSUM_OUT) {
> if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
> ifp->if_bridge != NULL) {
> in_delayed_cksum(m0);
> m0->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */
> }
> }
>
5229a5400
> struct pf_src_node *sn = NULL;
5288,5289c5459,5460
< pf_map_addr(AF_INET6, &r->rpool,
< (struct pf_addr *)&ip6->ip6_src, &naddr, NULL);
---
> pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
> &naddr, NULL, &sn);
5293c5464
< ifp = r->rpool.cur->ifp;
---
> ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
5298c5469
< ifp = s->rt_ifp;
---
> ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
5508c5679,5680
< pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
---
> pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
> sa_family_t af)
5589a5762,5775
> static int
> pf_add_mbuf_tag(struct mbuf *m, u_int tag)
> {
> struct m_tag *mtag;
>
> if (m_tag_find(m, tag, NULL) != NULL)
> return (0);
> mtag = m_tag_get(tag, 0, M_NOWAIT);
> if (mtag == NULL)
> return (1);
> m_tag_prepend(m, mtag);
> return (0);
> }
>
5594,5602c5780,5788
< u_short action, reason = 0, log = 0;
< struct mbuf *m = *m0;
< struct ip *h = NULL; /* XXX: was uninitialized */
< struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
< struct pf_state *s = NULL;
< struct pf_ruleset *ruleset = NULL;
< struct pf_pdesc pd;
< int off;
< int pqid = 0;
---
> struct pfi_kif *kif;
> u_short action, reason = 0, log = 0;
> struct mbuf *m = *m0;
> struct ip *h = NULL; /* make the compiler happy */
> struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
> struct pf_state *s = NULL;
> struct pf_ruleset *ruleset = NULL;
> struct pf_pdesc pd;
> int off, dirndx, pqid = 0;
5615c5801,5809
< #if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
---
> kif = pfi_index2kif[ifp->if_index];
> if (kif == NULL) {
> #ifdef __FreeBSD__
> PF_UNLOCK();
> #endif
> return (PF_DROP);
> }
>
> #ifdef __FreeBSD__
5623a5818
> memset(&pd, 0, sizeof(pd));
5632c5827
< if (pf_normalize_ip(m0, dir, ifp, &reason) != PF_PASS) {
---
> if (pf_normalize_ip(m0, dir, kif, &reason) != PF_PASS) {
5647d5841
< memset(&pd, 0, sizeof(pd));
5649a5844
> PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
5658c5853
< action = pf_test_fragment(&r, dir, ifp, m, h,
---
> action = pf_test_fragment(&r, dir, kif, m, h,
5682c5877
< action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
---
> action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
5684,5685c5879,5880
< break;
< action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd,
---
> goto done;
> action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
5687a5883,5885
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5688a5887
> a = s->anchor.ptr;
5691,5692c5890,5891
< action = pf_test_tcp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_tcp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5710c5909,5915
< action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd);
---
> if (uh.uh_dport == 0 ||
> ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
> ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
> action = PF_DROP;
> goto done;
> }
> action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
5711a5917,5919
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5716,5717c5924,5925
< action = pf_test_udp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_udp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5735c5943
< action = pf_test_state_icmp(&s, dir, ifp, m, 0, off, h, &pd);
---
> action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd);
5736a5945,5947
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5738,5739d5948
< r->packets++;
< r->bytes += ntohs(h->ip_len);
5741,5744d5949
< if (a != NULL) {
< a->packets++;
< a->bytes += ntohs(h->ip_len);
< }
5747,5748c5952,5953
< action = pf_test_icmp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_icmp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5753c5958
< action = pf_test_state_other(&s, dir, ifp, &pd);
---
> action = pf_test_state_other(&s, dir, kif, &pd);
5754a5960,5962
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5759c5967
< action = pf_test_other(&r, &s, dir, ifp, m, off, h,
---
> action = pf_test_other(&r, &s, dir, kif, m, off, h,
5764,5768d5971
< if (ifp == status_ifp) {
< pf_status.bcounters[0][dir == PF_OUT] += pd.tot_len;
< pf_status.pcounters[0][dir == PF_OUT][action != PF_PASS]++;
< }
<
5770,5783d5972
< tr = r;
< if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL)
< tr = s->nat_rule.ptr;
< if (tr->src.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->src.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->src.not);
< if (tr->dst.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->dst.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->dst.not);
<
5812a6002,6016
> /*
> * connections redirected to loopback should not match sockets
> * bound specifically to loopback due to security implications,
> * see tcp_input() and in_pcblookup_listen().
> */
> if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
> pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
> (s->nat_rule.ptr->action == PF_RDR ||
> s->nat_rule.ptr->action == PF_BINAT) &&
> (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET &&
> pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
> action = PF_DROP;
> REASON_SET(&reason, PFRES_MEMORY);
> }
>
5814c6018
< PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, a, ruleset);
5815a6020,6083
> kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
> kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
>
> if (action == PF_PASS || r->action == PF_DROP) {
> r->packets++;
> r->bytes += pd.tot_len;
> if (a != NULL) {
> a->packets++;
> a->bytes += pd.tot_len;
> }
> if (s != NULL) {
> dirndx = (dir == s->direction) ? 0 : 1;
> s->packets[dirndx]++;
> s->bytes[dirndx] += pd.tot_len;
> if (s->nat_rule.ptr != NULL) {
> s->nat_rule.ptr->packets++;
> s->nat_rule.ptr->bytes += pd.tot_len;
> }
> if (s->src_node != NULL) {
> s->src_node->packets++;
> s->src_node->bytes += pd.tot_len;
> }
> if (s->nat_src_node != NULL) {
> s->nat_src_node->packets++;
> s->nat_src_node->bytes += pd.tot_len;
> }
> }
> tr = r;
> nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
> if (nr != NULL) {
> struct pf_addr *x;
> /*
> * XXX: we need to make sure that the addresses
> * passed to pfr_update_stats() are the same than
> * the addresses used during matching (pfr_match)
> */
> if (r == &pf_default_rule) {
> tr = nr;
> x = (s == NULL || s->direction == dir) ?
> &pd.baddr : &pd.naddr;
> } else
> x = (s == NULL || s->direction == dir) ?
> &pd.naddr : &pd.baddr;
> if (x == &pd.baddr || s == NULL) {
> /* we need to change the address */
> if (dir == PF_OUT)
> pd.src = x;
> else
> pd.dst = x;
> }
> }
> if (tr->src.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.src : pd.dst, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->src.not);
> if (tr->dst.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.dst : pd.src, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->dst.not);
> }
>
>
5836,5843c6104,6112
< u_short action, reason = 0, log = 0;
< struct mbuf *m = *m0;
< struct ip6_hdr *h = NULL; /* make the compiler happy */
< struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
< struct pf_state *s = NULL;
< struct pf_ruleset *ruleset = NULL;
< struct pf_pdesc pd;
< int off, terminal = 0;
---
> struct pfi_kif *kif;
> u_short action, reason = 0, log = 0;
> struct mbuf *m = *m0;
> struct ip6_hdr *h = NULL; /* make the compiler happy */
> struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
> struct pf_state *s = NULL;
> struct pf_ruleset *ruleset = NULL;
> struct pf_pdesc pd;
> int off, terminal = 0, dirndx;
5857c6126,6134
< #if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
---
> kif = pfi_index2kif[ifp->if_index];
> if (kif == NULL) {
> #ifdef __FreeBSD__
> PF_UNLOCK();
> #endif
> return (PF_DROP);
> }
>
> #ifdef __FreeBSD__
5865a6143
> memset(&pd, 0, sizeof(pd));
5874c6152
< if (pf_normalize_ip6(m0, dir, ifp, &reason) != PF_PASS) {
---
> if (pf_normalize_ip6(m0, dir, kif, &reason) != PF_PASS) {
5881d6158
< memset(&pd, 0, sizeof(pd));
5883a6161
> PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
5894c6172
< action = pf_test_fragment(&r, dir, ifp, m, h,
---
> action = pf_test_fragment(&r, dir, kif, m, h,
5946c6224
< action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
---
> action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
5948,5949c6226,6227
< break;
< action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd,
---
> goto done;
> action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
5951a6230,6232
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5952a6234
> a = s->anchor.ptr;
5955,5956c6237,6238
< action = pf_test_tcp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_tcp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5974c6256,6262
< action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd);
---
> if (uh.uh_dport == 0 ||
> ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
> ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
> action = PF_DROP;
> goto done;
> }
> action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
5975a6264,6266
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
5976a6268
> a = s->anchor.ptr;
5979,5980c6271,6272
< action = pf_test_udp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_udp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
5998,5999c6290,6291
< action = pf_test_state_icmp(&s, dir, ifp,
< m, 0, off, h, &pd);
---
> action = pf_test_state_icmp(&s, dir, kif,
> m, off, h, &pd);
6000a6293,6295
> #if NPFSYNC
> pfsync_update_state(s);
> #endif
6002,6003c6297
< r->packets++;
< r->bytes += h->ip6_plen;
---
> a = s->anchor.ptr;
6006,6007c6300,6301
< action = pf_test_icmp(&r, &s, dir, ifp,
< m, 0, off, h, &pd, &a, &ruleset);
---
> action = pf_test_icmp(&r, &s, dir, kif,
> m, off, h, &pd, &a, &ruleset);
6012,6013c6306,6313
< action = pf_test_other(&r, &s, dir, ifp, m, off, h,
< &pd, &a, &ruleset);
---
> action = pf_test_state_other(&s, dir, kif, &pd);
> if (action == PF_PASS) {
> r = s->rule.ptr;
> a = s->anchor.ptr;
> log = s->log;
> } else if (s == NULL)
> action = pf_test_other(&r, &s, dir, kif, m, off, h,
> &pd, &a, &ruleset);
6017,6021d6316
< if (ifp == status_ifp) {
< pf_status.bcounters[1][dir == PF_OUT] += pd.tot_len;
< pf_status.pcounters[1][dir == PF_OUT][action != PF_PASS]++;
< }
<
6023,6036d6317
< tr = r;
< if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL)
< tr = s->nat_rule.ptr;
< if (tr->src.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->src.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->src.not);
< if (tr->dst.addr.type == PF_ADDR_TABLE)
< pfr_update_stats(tr->dst.addr.p.tbl,
< (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af,
< pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
< tr->dst.not);
<
6058a6340,6349
> if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
> pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
> (s->nat_rule.ptr->action == PF_RDR ||
> s->nat_rule.ptr->action == PF_BINAT) &&
> IN6_IS_ADDR_LOOPBACK(&pd.dst->v6) &&
> pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
> action = PF_DROP;
> REASON_SET(&reason, PFRES_MEMORY);
> }
>
6060c6351
< PFLOG_PACKET(ifp, h, m, AF_INET6, dir, reason, r, a, ruleset);
---
> PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, r, a, ruleset);
6061a6353,6416
> kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
> kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
>
> if (action == PF_PASS || r->action == PF_DROP) {
> r->packets++;
> r->bytes += pd.tot_len;
> if (a != NULL) {
> a->packets++;
> a->bytes += pd.tot_len;
> }
> if (s != NULL) {
> dirndx = (dir == s->direction) ? 0 : 1;
> s->packets[dirndx]++;
> s->bytes[dirndx] += pd.tot_len;
> if (s->nat_rule.ptr != NULL) {
> s->nat_rule.ptr->packets++;
> s->nat_rule.ptr->bytes += pd.tot_len;
> }
> if (s->src_node != NULL) {
> s->src_node->packets++;
> s->src_node->bytes += pd.tot_len;
> }
> if (s->nat_src_node != NULL) {
> s->nat_src_node->packets++;
> s->nat_src_node->bytes += pd.tot_len;
> }
> }
> tr = r;
> nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
> if (nr != NULL) {
> struct pf_addr *x;
> /*
> * XXX: we need to make sure that the addresses
> * passed to pfr_update_stats() are the same than
> * the addresses used during matching (pfr_match)
> */
> if (r == &pf_default_rule) {
> tr = nr;
> x = (s == NULL || s->direction == dir) ?
> &pd.baddr : &pd.naddr;
> } else {
> x = (s == NULL || s->direction == dir) ?
> &pd.naddr : &pd.baddr;
> }
> if (x == &pd.baddr || s == NULL) {
> if (dir == PF_OUT)
> pd.src = x;
> else
> pd.dst = x;
> }
> }
> if (tr->src.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.src : pd.dst, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->src.not);
> if (tr->dst.addr.type == PF_ADDR_TABLE)
> pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
> s->direction == dir) ? pd.dst : pd.src, pd.af,
> pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
> tr->dst.not);
> }
>
>