diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if.c | 18 | ||||
-rw-r--r-- | sys/net/if_pflog.c | 8 | ||||
-rw-r--r-- | sys/net/if_pfsync.c | 33 | ||||
-rw-r--r-- | sys/net/if_pfsync.h | 5 | ||||
-rw-r--r-- | sys/net/pf.c | 432 | ||||
-rw-r--r-- | sys/net/pf_if.c | 822 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 253 | ||||
-rw-r--r-- | sys/net/pf_norm.c | 32 | ||||
-rw-r--r-- | sys/net/pf_table.c | 153 | ||||
-rw-r--r-- | sys/net/pfvar.h | 211 |
10 files changed, 1508 insertions, 459 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 1aba9d82eaf..6a4bbdedf65 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.79 2003/12/16 20:33:24 markus Exp $ */ +/* $OpenBSD: if.c,v 1.80 2003/12/31 11:18:25 cedric Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -64,6 +64,7 @@ #include "bpfilter.h" #include "bridge.h" #include "carp.h" +#include "pf.h" #include <sys/param.h> #include <sys/systm.h> @@ -110,6 +111,10 @@ #include <netinet/ip_carp.h> #endif +#if NPF > 0 +#include <net/pfvar.h> +#endif + void if_attachsetup(struct ifnet *); void if_attachdomain1(struct ifnet *); int if_detach_rtdelete(struct radix_node *, void *); @@ -244,6 +249,9 @@ if_attachsetup(ifp) if (domains) if_attachdomain1(ifp); +#if NPF > 0 + pfi_attach_ifnet(ifp); +#endif } /* @@ -434,6 +442,10 @@ if_detach(ifp) ifp->if_init = if_detached_init; ifp->if_watchdog = if_detached_watchdog; +#if NPF > 0 + pfi_detach_ifnet(ifp); +#endif + #if NBRIDGE > 0 /* Remove the interface from any bridge it is part of. */ if (ifp->if_bridge) @@ -688,9 +700,11 @@ void if_clone_attach(ifc) struct if_clone *ifc; { - LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list); if_cloners_count++; +#if NPF > 0 + pfi_attach_clone(ifc); +#endif } /* diff --git a/sys/net/if_pflog.c b/sys/net/if_pflog.c index 9def6c6371a..3b93226a439 100644 --- a/sys/net/if_pflog.c +++ b/sys/net/if_pflog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pflog.c,v 1.10 2003/10/01 21:21:35 canacar Exp $ */ +/* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -172,7 +172,7 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } int -pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir, +pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir, u_int8_t reason, struct pf_rule *rm, struct pf_rule *am, struct pf_ruleset *ruleset) { @@ -181,7 +181,7 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir, struct pfloghdr hdr; struct mbuf m1; - if (ifp == NULL || m == NULL || rm == NULL) + if (kif == NULL || m == NULL || rm == NULL) return (-1); bzero(&hdr, sizeof(hdr)); @@ -189,7 +189,7 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir, hdr.af = af; hdr.action = rm->action; hdr.reason = reason; - memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname)); + memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname)); if (am == NULL) { hdr.rulenr = htonl(rm->nr); diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c index 0f00a29c367..89862b8ac50 100644 --- a/sys/net/if_pfsync.c +++ b/sys/net/if_pfsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.13 2003/12/28 17:18:58 mcbride Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.14 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -149,6 +149,7 @@ pfsync_insert_net_state(struct pfsync_state *sp) { struct pf_state *st = NULL; struct pf_rule *r = NULL; + struct pfi_kif *kif; u_long secs; if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) { @@ -158,6 +159,15 @@ pfsync_insert_net_state(struct pfsync_state *sp) return (EINVAL); } + kif = pfi_lookup_create(sp->ifname); + if (kif == NULL) { + if (pf_status.debug >= PF_DEBUG_MISC) + printf("pfsync_insert_net_state: " + "unknown interface: %s\n", sp->ifname); + /* skip this state */ + return (0); + } + /* * Just use the default rule until we have infrastructure to find the * best matching rule. @@ -166,8 +176,10 @@ pfsync_insert_net_state(struct pfsync_state *sp) if (!r->max_states || r->states < r->max_states) st = pool_get(&pf_state_pl, PR_NOWAIT); - if (st == NULL) + if (st == NULL) { + pfi_maybe_destroy(kif); return (ENOMEM); + } bzero(st, sizeof(*st)); st->rule.ptr = r; @@ -201,7 +213,8 @@ pfsync_insert_net_state(struct pfsync_state *sp) else st->expire = ntohl(sp->expire) + secs; - if (pf_insert_state(st)) { + if (pf_insert_state(kif, st)) { + pfi_maybe_destroy(kif); pool_put(&pf_state_pl, st); return (EINVAL); } @@ -291,7 +304,7 @@ pfsync_input(struct mbuf *m, ...) cp = (void *)((char *)mp->m_data + iplen + PFSYNC_HDRLEN); creatorid = cp->creatorid; - RB_FOREACH(st, pf_state_tree_ext_gwy, &tree_ext_gwy) { + RB_FOREACH(st, pf_state_tree_id, &tree_id) { if (st->creatorid == creatorid) st->timeout = PFTM_PURGE; } @@ -337,7 +350,7 @@ pfsync_input(struct mbuf *m, ...) key.id = sp->id; key.creatorid = sp->creatorid; - st = pf_find_state(&key, PF_ID); + st = pf_find_state_byid(&key); if (st == NULL) { /* insert the update */ if (pfsync_insert_net_state(sp)) @@ -368,7 +381,7 @@ pfsync_input(struct mbuf *m, ...) key.id = sp->id; key.creatorid = sp->creatorid; - st = pf_find_state(&key, PF_ID); + st = pf_find_state_byid(&key); if (st == NULL) { pfsyncstats.pfsyncs_badstate++; continue; @@ -399,7 +412,7 @@ pfsync_input(struct mbuf *m, ...) key.id = up->id; key.creatorid = up->creatorid; - st = pf_find_state(&key, PF_ID); + st = pf_find_state_byid(&key); if (st == NULL) { /* We don't have this state. Ask for it. */ pfsync_request_update(up, &src); @@ -434,7 +447,7 @@ pfsync_input(struct mbuf *m, ...) key.id = dp->id; key.creatorid = dp->creatorid; - st = pf_find_state(&key, PF_ID); + st = pf_find_state_byid(&key); if (st == NULL) { pfsyncstats.pfsyncs_badstate++; continue; @@ -471,7 +484,7 @@ pfsync_input(struct mbuf *m, ...) key.id = rup->id; key.creatorid = rup->creatorid; - st = pf_find_state(&key, PF_ID); + st = pf_find_state_byid(&key); if (st == NULL) { pfsyncstats.pfsyncs_badstate++; continue; @@ -685,7 +698,6 @@ pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp) return (m); } - int pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress) { @@ -770,6 +782,7 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress) sp->id = st->id; sp->creatorid = st->creatorid; + strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname)); pf_state_host_hton(&st->lan, &sp->lan); pf_state_host_hton(&st->gwy, &sp->gwy); pf_state_host_hton(&st->ext, &sp->ext); diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h index 70d6e1811a0..221cd93f537 100644 --- a/sys/net/if_pfsync.h +++ b/sys/net/if_pfsync.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.h,v 1.7 2003/12/28 17:18:58 mcbride Exp $ */ +/* $OpenBSD: if_pfsync.h,v 1.8 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -57,6 +57,7 @@ struct pfsync_state_peer { struct pfsync_state { u_int64_t id; + char ifname[IFNAMSIZ]; struct pfsync_state_host lan; struct pfsync_state_host gwy; struct pfsync_state_host ext; @@ -143,7 +144,7 @@ struct pfsync_softc { struct pfsync_header { u_int8_t version; -#define PFSYNC_VERSION 1 +#define PFSYNC_VERSION 2 u_int8_t af; u_int8_t action; #define PFSYNC_ACT_CLR 0 /* clear all states */ diff --git a/sys/net/pf.c b/sys/net/pf.c index 0b74b93a371..a74f21ecd73 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.413 2003/12/19 16:12:43 henning Exp $ */ +/* $OpenBSD: pf.c,v 1.414 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -99,7 +99,6 @@ struct pf_palist pf_pabuf; struct pf_altqqueue *pf_altqs_active; struct pf_altqqueue *pf_altqs_inactive; struct pf_status pf_status; -struct ifnet *status_ifp; u_int32_t ticket_altqs_active; u_int32_t ticket_altqs_inactive; @@ -108,7 +107,7 @@ u_int32_t ticket_pabuf; struct timeout pf_expire_to; /* expire timeout */ -struct pool pf_src_tree_pl, pf_rule_pl, pf_addr_pl; +struct pool pf_src_tree_pl, pf_rule_pl; struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl; void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t); @@ -135,45 +134,45 @@ void pf_send_tcp(const struct pf_rule *, sa_family_t, void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t, sa_family_t, struct pf_rule *); struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *, - int, int, struct ifnet *, + int, int, struct pfi_kif *, struct pf_addr *, u_int16_t, struct pf_addr *, u_int16_t, int); struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *, - int, int, struct ifnet *, struct pf_src_node **, + int, int, struct pfi_kif *, struct pf_src_node **, struct pf_addr *, u_int16_t, struct pf_addr *, u_int16_t, struct pf_addr *, u_int16_t *); int pf_test_tcp(struct pf_rule **, struct pf_state **, - int, struct ifnet *, struct mbuf *, int, + int, struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *, struct pf_rule **, struct pf_ruleset **); int pf_test_udp(struct pf_rule **, struct pf_state **, - int, struct ifnet *, struct mbuf *, int, + int, struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *, struct pf_rule **, struct pf_ruleset **); int pf_test_icmp(struct pf_rule **, struct pf_state **, - int, struct ifnet *, struct mbuf *, int, + int, struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *, struct pf_rule **, struct pf_ruleset **); int pf_test_other(struct pf_rule **, struct pf_state **, - int, struct ifnet *, struct mbuf *, int, void *, + int, struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *, struct pf_rule **, struct pf_ruleset **); int pf_test_fragment(struct pf_rule **, int, - struct ifnet *, struct mbuf *, void *, + struct pfi_kif *, struct mbuf *, void *, struct pf_pdesc *, struct pf_rule **, struct pf_ruleset **); int pf_test_state_tcp(struct pf_state **, int, - struct ifnet *, struct mbuf *, int, + struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *, u_short *); int pf_test_state_udp(struct pf_state **, int, - struct ifnet *, struct mbuf *, int, + struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *); int pf_test_state_icmp(struct pf_state **, int, - struct ifnet *, struct mbuf *, int, + struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *); int pf_test_state_other(struct pf_state **, int, - struct ifnet *, struct pf_pdesc *); + struct pfi_kif *, struct pf_pdesc *); struct pf_tag *pf_get_tag(struct mbuf *); int pf_match_tag(struct mbuf *, struct pf_rule *, struct pf_rule *, struct pf_tag *, int *); @@ -205,7 +204,8 @@ int pf_check_proto_cksum(struct mbuf *, int, int, int pf_addr_wrap_neq(struct pf_addr_wrap *, struct pf_addr_wrap *); 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); struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } }; @@ -213,9 +213,11 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = #define STATE_LOOKUP() \ do { \ if (direction == PF_IN) \ - *state = pf_find_state(&key, PF_EXT_GWY); \ + *state = pf_find_state_recurse( \ + kif, &key, PF_EXT_GWY); \ else \ - *state = pf_find_state(&key, PF_LAN_EXT); \ + *state = pf_find_state_recurse( \ + kif, &key, PF_LAN_EXT); \ if (*state == NULL) \ return (PF_DROP); \ if (direction == PF_OUT && \ @@ -223,8 +225,8 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = (*state)->rule.ptr->direction == PF_OUT) || \ ((*state)->rule.ptr->rt == PF_REPLYTO && \ (*state)->rule.ptr->direction == PF_IN)) && \ - (*state)->rt_ifp != NULL && \ - (*state)->rt_ifp != ifp) \ + (*state)->rt_kif != NULL && \ + (*state)->rt_kif != kif) \ return (PF_PASS); \ } while (0) @@ -236,6 +238,10 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = (s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \ (s)->lan.port != (s)->gwy.port +#define LOCKED_IF(r, k) (((r)->rule_flag & PFRULE_IFBOUND) ? (k) : \ + ((r)->rule_flag & PFRULE_GRBOUND) ? (k)->pfik_parent : \ + (k)->pfik_parent->pfik_parent) + 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 *); @@ -245,17 +251,16 @@ static __inline int pf_state_compare_id(struct pf_state *, struct pf_state *); struct pf_src_tree tree_src_tracking; -struct pf_state_tree_lan_ext tree_lan_ext; -struct pf_state_tree_ext_gwy tree_ext_gwy; + struct pf_state_tree_id tree_id; RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare); RB_GENERATE(pf_state_tree_lan_ext, pf_state, - entry_lan_ext, pf_state_compare_lan_ext); + u.s.entry_lan_ext, pf_state_compare_lan_ext); RB_GENERATE(pf_state_tree_ext_gwy, pf_state, - entry_ext_gwy, pf_state_compare_ext_gwy); + u.s.entry_ext_gwy, pf_state_compare_ext_gwy); RB_GENERATE(pf_state_tree_id, pf_state, - entry_id, pf_state_compare_id); + u.s.entry_id, pf_state_compare_id); static __inline int pf_src_compare(struct pf_src_node *a, struct pf_src_node *b) @@ -473,29 +478,77 @@ pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af) #endif struct pf_state * -pf_find_state(struct pf_state *key, u_int8_t tree) +pf_find_state_byid(struct pf_state *key) +{ + pf_status.fcounters[FCNT_STATE_SEARCH]++; + return RB_FIND(pf_state_tree_id, &tree_id, key); +} + +struct pf_state * +pf_find_state_recurse(struct pfi_kif *kif, struct pf_state *key, u_int8_t tree) { - struct pf_state *s; + struct pf_state *s; pf_status.fcounters[FCNT_STATE_SEARCH]++; switch (tree) { case PF_LAN_EXT: - s = RB_FIND(pf_state_tree_lan_ext, &tree_lan_ext, key); - break; + 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); + } + return (NULL); case PF_EXT_GWY: - s = RB_FIND(pf_state_tree_ext_gwy, &tree_ext_gwy, key); - break; - case PF_ID: - s = RB_FIND(pf_state_tree_id, &tree_id, key); - break; + 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: - /* XXX should we just return NULL? */ - panic("pf_find_state"); - break; + panic("pf_find_state_recurse"); } +} + +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; - return (s); + 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"); + } } int @@ -554,10 +607,11 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule, } int -pf_insert_state(struct pf_state *state) +pf_insert_state(struct pfi_kif *kif, struct pf_state *state) { /* Thou MUST NOT insert multiple duplicate keys */ - if (RB_INSERT(pf_state_tree_lan_ext, &tree_lan_ext, state)) { + state->u.s.kif = kif; + if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) { if (pf_status.debug >= PF_DEBUG_MISC) { printf("pf: state insert failed: tree_lan_ext"); printf(" lan: "); @@ -577,7 +631,7 @@ pf_insert_state(struct pf_state *state) return (-1); } - if (RB_INSERT(pf_state_tree_ext_gwy, &tree_ext_gwy, state) != NULL) { + if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) { if (pf_status.debug >= PF_DEBUG_MISC) { printf("pf: state insert failed: tree_ext_gwy"); printf(" lan: "); @@ -593,7 +647,7 @@ pf_insert_state(struct pf_state *state) printf(" (from sync)"); printf("\n"); } - RB_REMOVE(pf_state_tree_lan_ext, &tree_lan_ext, state); + RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state); pf_src_tree_remove_state(state); return (-1); } @@ -611,13 +665,14 @@ pf_insert_state(struct pf_state *state) printf(" (from sync)"); printf("\n"); } - RB_REMOVE(pf_state_tree_lan_ext, &tree_lan_ext, state); - RB_REMOVE(pf_state_tree_ext_gwy, &tree_ext_gwy, state); + 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); } pf_status.fcounters[FCNT_STATE_INSERT]++; pf_status.states++; + pfi_attach_state(kif); #if NPFSYNC pfsync_insert_state(state); #endif @@ -726,8 +781,9 @@ pf_purge_expired_states(void) { struct pf_state *cur, *next; - for (cur = RB_MIN(pf_state_tree_ext_gwy, &tree_ext_gwy); cur; cur = next) { - next = RB_NEXT(pf_state_tree_ext_gwy, &tree_ext_gwy, cur); + for (cur = RB_MIN(pf_state_tree_id, &tree_id); + cur; cur = next) { + next = RB_NEXT(pf_state_tree_id, &tree_id, cur); if (pf_state_expires(cur) <= time.tv_sec) { if (cur->src.state == PF_TCPS_PROXY_DST) @@ -736,10 +792,11 @@ pf_purge_expired_states(void) 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, &tree_ext_gwy, cur); - RB_REMOVE(pf_state_tree_lan_ext, &tree_lan_ext, cur); + RB_REMOVE(pf_state_tree_ext_gwy, + &cur->u.s.kif->pfik_ext_gwy, cur); + RB_REMOVE(pf_state_tree_lan_ext, + &cur->u.s.kif->pfik_lan_ext, cur); RB_REMOVE(pf_state_tree_id, &tree_id, cur); - #if NPFSYNC pfsync_delete_state(cur); #endif @@ -755,6 +812,7 @@ pf_purge_expired_states(void) 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); pool_put(&pf_state_pl, cur); pf_status.fcounters[FCNT_STATE_REMOVALS]++; pf_status.states--; @@ -940,7 +998,7 @@ pf_calc_skip_steps(struct pf_rulequeue *rules) head[i] = cur; while (cur != NULL) { - if (cur->ifp != prev->ifp || cur->ifnot != prev->ifnot) + if (cur->kif != prev->kif || cur->ifnot != prev->ifnot) PF_SET_SKIP_STEPS(PF_SKIP_IFP); if (cur->direction != prev->direction) PF_SET_SKIP_STEPS(PF_SKIP_DIR); @@ -983,11 +1041,7 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2) return (1); return (0); case PF_ADDR_DYNIFTL: - 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); case PF_ADDR_NOROUTE: return (0); case PF_ADDR_TABLE: @@ -1739,10 +1793,23 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, if (rpool->cur->addr.type == PF_ADDR_NOROUTE) return (1); - 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) { if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) return (1); /* unsupported */ } else { @@ -1802,6 +1869,11 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, &rpool->tblidx, &rpool->counter, &raddr, &rmask, af)) goto get_addr; + } 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; } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) goto get_addr; @@ -1818,6 +1890,16 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, goto try_next; return (1); } + } 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 contain no address of type 'af' */ + if (rpool->cur != acur) + goto try_next; + return (1); + } } else { raddr = &rpool->cur->addr.v.a.addr; rmask = &rpool->cur->addr.v.a.mask; @@ -1869,16 +1951,15 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, */ if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP)) { key.gwy.port = 0; - if (pf_find_state(&key, PF_EXT_GWY) == NULL) + if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) return (0); } else if (low == 0 && high == 0) { key.gwy.port = *nport; - if (pf_find_state(&key, PF_EXT_GWY) == NULL) { + if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) return (0); - } } else if (low == high) { key.gwy.port = htons(low); - if (pf_find_state(&key, PF_EXT_GWY) == NULL) { + if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) { *nport = htons(low); return (0); } @@ -1895,7 +1976,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, /* low <= cut <= high */ for (tmp = cut; tmp <= high; ++(tmp)) { key.gwy.port = htons(tmp); - if (pf_find_state(&key, PF_EXT_GWY) == + if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) { *nport = htons(tmp); return (0); @@ -1903,7 +1984,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, } for (tmp = cut - 1; tmp >= low; --(tmp)) { key.gwy.port = htons(tmp); - if (pf_find_state(&key, PF_EXT_GWY) == + if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) { *nport = htons(tmp); return (0); @@ -1931,7 +2012,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, struct pf_rule * pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, - 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, struct pf_addr *daddr, u_int16_t dport, int rs_num) { struct pf_rule *r, *rm = NULL, *anchorrule = NULL; @@ -1952,8 +2033,8 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, } r->evaluations++; - 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) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != direction) r = r->skip[PF_SKIP_DIR].ptr; @@ -1999,7 +2080,7 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, struct pf_rule * pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, - struct ifnet *ifp, struct pf_src_node **sn, + struct pfi_kif *kif, struct pf_src_node **sn, struct pf_addr *saddr, u_int16_t sport, struct pf_addr *daddr, u_int16_t dport, struct pf_addr *naddr, u_int16_t *nport) @@ -2007,16 +2088,16 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, struct pf_rule *r = NULL; if (direction == PF_OUT) { - r = pf_match_translation(pd, m, off, direction, ifp, saddr, + r = pf_match_translation(pd, m, off, direction, kif, saddr, sport, daddr, dport, PF_RULESET_BINAT); if (r == NULL) - r = pf_match_translation(pd, m, off, direction, ifp, + r = pf_match_translation(pd, m, off, direction, kif, saddr, sport, daddr, dport, PF_RULESET_NAT); } else { - r = pf_match_translation(pd, m, off, direction, ifp, saddr, + r = pf_match_translation(pd, m, off, direction, kif, saddr, sport, daddr, dport, PF_RULESET_RDR); if (r == NULL) - r = pf_match_translation(pd, m, off, direction, ifp, + r = pf_match_translation(pd, m, off, direction, kif, saddr, sport, daddr, dport, PF_RULESET_BINAT); } @@ -2042,21 +2123,58 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, case PF_BINAT: switch (direction) { case PF_OUT: - 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 PF_POOLMASK(naddr, &r->rpool.cur->addr.v.a.addr, &r->rpool.cur->addr.v.a.mask, saddr, pd->af); break; case PF_IN: - 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 PF_POOLMASK(naddr, &r->src.addr.v.a.addr, &r->src.addr.v.a.mask, daddr, @@ -2291,20 +2409,20 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr) { struct pf_rule *r = s->rule.ptr; - s->rt_ifp = NULL; + s->rt_kif = NULL; if (!r->rt || r->rt == PF_FASTROUTE) return; switch (s->af) { #ifdef INET case AF_INET: pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &s->nat_src_node); - s->rt_ifp = r->rpool.cur->ifp; + s->rt_kif = r->rpool.cur->kif; break; #endif /* INET */ #ifdef INET6 case AF_INET6: pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &s->nat_src_node); - s->rt_ifp = r->rpool.cur->ifp; + s->rt_kif = r->rpool.cur->kif; break; #endif /* INET6 */ } @@ -2312,7 +2430,7 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr) int pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction, - struct ifnet *ifp, struct mbuf *m, int off, void *h, + struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) { struct pf_rule *nr = NULL; @@ -2337,7 +2455,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction, if (direction == PF_OUT) { bport = nport = th->th_sport; /* check outgoing packet for BINAT/NAT */ - if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn, + if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn, saddr, th->th_sport, daddr, th->th_dport, &pd->naddr, &nport)) != NULL) { PF_ACPY(&pd->baddr, saddr, af); @@ -2351,7 +2469,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction, } else { bport = nport = th->th_dport; /* check incoming packet for BINAT/RDR */ - if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn, + 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); @@ -2366,8 +2484,8 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction, while (r != NULL) { r->evaluations++; - 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) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != direction) r = r->skip[PF_SKIP_DIR].ptr; @@ -2435,7 +2553,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction, if (r->log) { if (rewrite) m_copyback(m, off, sizeof(*th), th); - PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); + PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset); } if ((r->action == PF_DROP) && @@ -2623,7 +2741,7 @@ cleanup: pool_put(&pf_state_pl, s); return (PF_DROP); } - if (pf_insert_state(s)) { + if (pf_insert_state(LOCKED_IF(r, kif), s)) { pf_normalize_tcp_cleanup(s); REASON_SET(&reason, PFRES_MEMORY); pf_src_tree_remove_state(s); @@ -2667,7 +2785,7 @@ cleanup: int pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction, - struct ifnet *ifp, struct mbuf *m, int off, void *h, + struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) { struct pf_rule *nr = NULL; @@ -2691,7 +2809,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction, if (direction == PF_OUT) { bport = nport = uh->uh_sport; /* check outgoing packet for BINAT/NAT */ - if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn, + if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn, saddr, uh->uh_sport, daddr, uh->uh_dport, &pd->naddr, &nport)) != NULL) { PF_ACPY(&pd->baddr, saddr, af); @@ -2705,7 +2823,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction, } else { bport = nport = uh->uh_dport; /* check incoming packet for BINAT/RDR */ - if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn, + 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); @@ -2720,8 +2838,8 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction, while (r != NULL) { r->evaluations++; - 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) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != direction) r = r->skip[PF_SKIP_DIR].ptr; @@ -2786,7 +2904,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction, if (r->log) { if (rewrite) m_copyback(m, off, sizeof(*uh), uh); - PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); + PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset); } if ((r->action == PF_DROP) && @@ -2912,7 +3030,7 @@ cleanup: s->nat_src_node = nsn; s->nat_src_node->states++; } - if (pf_insert_state(s)) { + if (pf_insert_state(LOCKED_IF(r, kif), s)) { REASON_SET(&reason, PFRES_MEMORY); pf_src_tree_remove_state(s); pool_put(&pf_state_pl, s); @@ -2930,7 +3048,7 @@ cleanup: int pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction, - struct ifnet *ifp, struct mbuf *m, int off, void *h, + struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) { struct pf_rule *nr = NULL; @@ -2983,7 +3101,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction, if (direction == PF_OUT) { /* check outgoing packet for BINAT/NAT */ - if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn, + 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); switch (af) { @@ -3007,7 +3125,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction, } } else { /* check incoming packet for BINAT/RDR */ - if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn, + 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); switch (af) { @@ -3033,8 +3151,8 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction, while (r != NULL) { r->evaluations++; - 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) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != direction) r = r->skip[PF_SKIP_DIR].ptr; @@ -3090,7 +3208,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction, m_copyback(m, off, sizeof(struct icmp6_hdr), pd->hdr.icmp6); #endif /* INET6 */ - PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); + PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset); } if (r->action != PF_PASS) @@ -3187,7 +3305,7 @@ cleanup: s->nat_src_node = nsn; s->nat_src_node->states++; } - if (pf_insert_state(s)) { + if (pf_insert_state(LOCKED_IF(r, kif), s)) { REASON_SET(&reason, PFRES_MEMORY); pf_src_tree_remove_state(s); pool_put(&pf_state_pl, s); @@ -3208,7 +3326,7 @@ cleanup: int pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction, - 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, struct pf_rule **am, struct pf_ruleset **rsm) { struct pf_rule *nr = NULL; @@ -3225,7 +3343,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction, if (direction == PF_OUT) { /* check outgoing packet for BINAT/NAT */ - if ((nr = pf_get_translation(pd, m, off, PF_OUT, ifp, &nsn, + 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); switch (af) { @@ -3247,7 +3365,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction, } } else { /* check incoming packet for BINAT/RDR */ - if ((nr = pf_get_translation(pd, m, off, PF_IN, ifp, &nsn, + 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); switch (af) { @@ -3271,8 +3389,8 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction, while (r != NULL) { r->evaluations++; - 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) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != direction) r = r->skip[PF_SKIP_DIR].ptr; @@ -3319,7 +3437,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction, REASON_SET(&reason, PFRES_MATCH); if (r->log) - PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); + PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset); if ((r->action == PF_DROP) && ((r->rule_flag & PFRULE_RETURNICMP) || @@ -3445,10 +3563,10 @@ cleanup: s->nat_src_node = nsn; s->nat_src_node->states++; } - if (pf_insert_state(s)) { + if (pf_insert_state(LOCKED_IF(r, kif), s)) { REASON_SET(&reason, PFRES_MEMORY); if (r->log) - PFLOG_PACKET(ifp, h, m, af, direction, reason, + PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset); pf_src_tree_remove_state(s); pool_put(&pf_state_pl, s); @@ -3461,7 +3579,7 @@ cleanup: } int -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, struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) { @@ -3475,8 +3593,8 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp, r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); while (r != NULL) { r->evaluations++; - 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) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != direction) r = r->skip[PF_SKIP_DIR].ptr; @@ -3521,7 +3639,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp, REASON_SET(&reason, PFRES_MATCH); if (r->log) - PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); + PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset); if (r->action != PF_PASS) return (PF_DROP); @@ -3535,7 +3653,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp, } int -pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, +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, u_short *reason) { @@ -3943,7 +4061,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, } int -pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp, +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) { struct pf_state_peer *src, *dst; @@ -4004,7 +4122,7 @@ pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp, } int -pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, +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) { struct pf_addr *saddr = pd->src, *daddr = pd->dst; @@ -4561,7 +4679,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, } int -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, struct pf_pdesc *pd) { struct pf_state_peer *src, *dst; @@ -4782,12 +4900,13 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, &naddr, NULL, &sn); if (!PF_AZERO(&naddr, AF_INET)) dst->sin_addr.s_addr = naddr.v4.s_addr; - ifp = r->rpool.cur->ifp; + ifp = r->rpool.cur->kif ? + r->rpool.cur->kif->pfik_ifp : NULL; } else { if (!PF_AZERO(&s->rt_addr, AF_INET)) dst->sin_addr.s_addr = s->rt_addr.v4.s_addr; - ifp = s->rt_ifp; + ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; } } @@ -4973,12 +5092,12 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, if (!PF_AZERO(&naddr, AF_INET6)) PF_ACPY((struct pf_addr *)&dst->sin6_addr, &naddr, AF_INET6); - ifp = r->rpool.cur->ifp; + ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL; } else { if (!PF_AZERO(&s->rt_addr, AF_INET6)) PF_ACPY((struct pf_addr *)&dst->sin6_addr, &s->rt_addr, AF_INET6); - ifp = s->rt_ifp; + ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; } if (ifp == NULL) @@ -5132,6 +5251,7 @@ pf_add_mbuf_tag(struct mbuf *m, u_int tag) int pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) { + struct pfi_kif *kif = pfi_index2kif[ifp->if_index]; u_short action, reason = 0, log = 0; struct mbuf *m = *m0; struct ip *h; @@ -5159,7 +5279,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) } /* We do IP header normalization and packet reassembly here */ - if (pf_normalize_ip(m0, dir, ifp, &reason) != PF_PASS) { + if (pf_normalize_ip(m0, dir, kif, &reason) != PF_PASS) { action = PF_DROP; goto done; } @@ -5185,7 +5305,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) /* handle fragments that didn't get reassembled by normalization */ if (h->ip_off & htons(IP_MF | IP_OFFMASK)) { - action = pf_test_fragment(&r, dir, ifp, m, h, + action = pf_test_fragment(&r, dir, kif, m, h, &pd, &a, &ruleset); goto done; } @@ -5209,10 +5329,10 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) pd.p_len = pd.tot_len - off - (th.th_off << 2); if ((th.th_flags & TH_ACK) && pd.p_len == 0) pqid = 1; - action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd); + action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd); if (action == PF_DROP) goto done; - action = pf_test_state_tcp(&s, dir, ifp, m, off, h, &pd, + action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd, &reason); if (action == PF_PASS) { #if NPFSYNC @@ -5222,7 +5342,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) a = s->anchor.ptr; log = s->log; } else if (s == NULL) - action = pf_test_tcp(&r, &s, dir, ifp, + action = pf_test_tcp(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } @@ -5241,7 +5361,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) action = PF_DROP; goto done; } - action = pf_test_state_udp(&s, dir, ifp, m, off, h, &pd); + action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd); if (action == PF_PASS) { #if NPFSYNC pfsync_update_state(s); @@ -5250,7 +5370,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) a = s->anchor.ptr; log = s->log; } else if (s == NULL) - action = pf_test_udp(&r, &s, dir, ifp, + action = pf_test_udp(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } @@ -5269,23 +5389,22 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) action = PF_DROP; goto done; } - action = pf_test_state_icmp(&s, dir, ifp, m, off, h, &pd); + action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd); if (action == PF_PASS) { #if NPFSYNC pfsync_update_state(s); #endif - r = s->rule.ptr; a = s->anchor.ptr; log = s->log; } else if (s == NULL) - action = pf_test_icmp(&r, &s, dir, ifp, + action = pf_test_icmp(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } default: - action = pf_test_state_other(&s, dir, ifp, &pd); + action = pf_test_state_other(&s, dir, kif, &pd); if (action == PF_PASS) { #if NPFSYNC pfsync_update_state(s); @@ -5294,7 +5413,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) a = s->anchor.ptr; log = s->log; } else if (s == NULL) - action = pf_test_other(&r, &s, dir, ifp, m, off, h, + action = pf_test_other(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } @@ -5345,12 +5464,10 @@ done: } if (log) - PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, a, ruleset); + PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, a, ruleset); - if (ifp == status_ifp) { - pf_status.bcounters[0][dir == PF_OUT] += pd.tot_len; - pf_status.pcounters[0][dir == PF_OUT][action != PF_PASS]++; - } + 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++; @@ -5429,6 +5546,7 @@ done: int pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) { + struct pfi_kif *kif = pfi_index2kif[ifp->if_index]; u_short action, reason = 0, log = 0; struct mbuf *m = *m0; struct ip6_hdr *h; @@ -5456,7 +5574,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) } /* We do IP header normalization and packet reassembly here */ - if (pf_normalize_ip6(m0, dir, ifp, &reason) != PF_PASS) { + if (pf_normalize_ip6(m0, dir, kif, &reason) != PF_PASS) { action = PF_DROP; goto done; } @@ -5476,7 +5594,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) do { switch (pd.proto) { case IPPROTO_FRAGMENT: - action = pf_test_fragment(&r, dir, ifp, m, h, + action = pf_test_fragment(&r, dir, kif, m, h, &pd, &a, &ruleset); if (action == PF_DROP) REASON_SET(&reason, PFRES_FRAG); @@ -5528,10 +5646,10 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) goto done; } pd.p_len = pd.tot_len - off - (th.th_off << 2); - action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd); + action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd); if (action == PF_DROP) goto done; - action = pf_test_state_tcp(&s, dir, ifp, m, off, h, &pd, + action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd, &reason); if (action == PF_PASS) { #if NPFSYNC @@ -5541,7 +5659,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) a = s->anchor.ptr; log = s->log; } else if (s == NULL) - action = pf_test_tcp(&r, &s, dir, ifp, + action = pf_test_tcp(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } @@ -5560,7 +5678,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) action = PF_DROP; goto done; } - action = pf_test_state_udp(&s, dir, ifp, m, off, h, &pd); + action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd); if (action == PF_PASS) { #if NPFSYNC pfsync_update_state(s); @@ -5569,7 +5687,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) a = s->anchor.ptr; log = s->log; } else if (s == NULL) - action = pf_test_udp(&r, &s, dir, ifp, + action = pf_test_udp(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } @@ -5588,7 +5706,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) action = PF_DROP; goto done; } - action = pf_test_state_icmp(&s, dir, ifp, + action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd); if (action == PF_PASS) { #if NPFSYNC @@ -5598,19 +5716,19 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) a = s->anchor.ptr; log = s->log; } else if (s == NULL) - action = pf_test_icmp(&r, &s, dir, ifp, + action = pf_test_icmp(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } default: - action = pf_test_state_other(&s, dir, ifp, &pd); + 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, ifp, m, off, h, + action = pf_test_other(&r, &s, dir, kif, m, off, h, &pd, &a, &ruleset); break; } @@ -5649,12 +5767,10 @@ done: } if (log) - PFLOG_PACKET(ifp, h, m, AF_INET6, dir, reason, r, a, ruleset); + PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, r, a, ruleset); - if (ifp == status_ifp) { - pf_status.bcounters[1][dir == PF_OUT] += pd.tot_len; - pf_status.pcounters[1][dir == PF_OUT][action != PF_PASS]++; - } + 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++; diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c index 21574183104..485511bc182 100644 --- a/sys/net/pf_if.c +++ b/sys/net/pf_if.c @@ -1,7 +1,8 @@ -/* $OpenBSD: pf_if.c,v 1.1 2003/12/12 20:05:45 cedric Exp $ */ +/* $OpenBSD: pf_if.c,v 1.2 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier + * Copyright (c) 2003 Cedric Berger * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,11 +28,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * Effort sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F30602-01-2-0537. - * */ #include <sys/param.h> @@ -41,8 +37,8 @@ #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/kernel.h> +#include <sys/device.h> #include <sys/time.h> -#include <sys/pool.h> #include <net/if.h> #include <net/if_types.h> @@ -59,105 +55,781 @@ #include <netinet/ip6.h> #endif /* INET6 */ -#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x +#define ACCEPT_FLAGS(oklist) \ + do { \ + if ((flags & ~(oklist)) & \ + PFI_FLAG_ALLMASK) \ + return (EINVAL); \ + } while (0) -/* - * Global variables - */ +#define senderr(e) do { rv = (e); goto _bad; } while (0) + +struct pfi_kif **pfi_index2kif; +struct pfi_kif *pfi_self; +int pfi_indexlim; +struct pfi_ifhead pfi_ifs; +struct pfi_statehead pfi_statehead; +int pfi_ifcnt; +struct pool pfi_addr_pl; +long pfi_update = 1; +struct pfr_addr *pfi_buffer; +int pfi_buffer_cnt; +int pfi_buffer_max; +char pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] = + PF_RESERVED_ANCHOR; +char pfi_interface_ruleset[PF_RULESET_NAME_SIZE] = + PF_INTERFACE_RULESET; + +void pfi_dynaddr_update(void *); +void pfi_kifaddr_update(void *); +void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, + int, int); +void pfi_instance_add(struct ifnet *, int, int); +void pfi_address_add(struct sockaddr *, int, int); +int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); +struct pfi_kif *pfi_if_create(const char *, struct pfi_kif *, int); +void pfi_copy_group(char *, const char *, int); +void pfi_dynamic_drivers(void); +void pfi_newgroup(const char *, int); +struct pfi_kif *pfi_lookup_if(const char *); +int pfi_skip_if(const char *, struct pfi_kif *, int); +int pfi_unmask(void *); +void pfi_dohooks(struct pfi_kif *); + +RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); +RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); + +#define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" } +#define PFI_BUFFER_MAX 0x10000 +#define PFI_MTYPE M_IFADDR + +void +pfi_initialize(void) +{ + if (pfi_self != NULL) /* already initialized */ + return; + + TAILQ_INIT(&pfi_statehead); + pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0, + "pfiaddrpl", &pool_allocator_nointr); + pfi_dynamic_drivers(); + pfi_buffer_max = 64; + pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer), + PFI_MTYPE, M_WAITOK); + pfi_self = pfi_if_create("self", NULL, PFI_IFLAG_GROUP); +} + +void +pfi_attach_clone(struct if_clone *ifc) +{ + pfi_initialize(); + pfi_newgroup(ifc->ifc_name, PFI_IFLAG_CLONABLE); +} + +void +pfi_attach_ifnet(struct ifnet *ifp) +{ + struct pfi_kif *p, *q, key; + int s; + + pfi_initialize(); + s = splsoftnet(); + pfi_update++; + if (ifp->if_index >= pfi_indexlim) { + /* + * grow pfi_index2kif, similar to ifindex2ifnet code in if.c + */ + size_t m, n, oldlim; + struct pfi_kif **mp, **np; + + oldlim = pfi_indexlim; + if (pfi_indexlim == 0) + pfi_indexlim = 64; + while (ifp->if_index >= pfi_indexlim) + pfi_indexlim <<= 1; + + m = oldlim * sizeof(struct pfi_kif *); + mp = pfi_index2kif; + n = pfi_indexlim * sizeof(struct pfi_kif *); + np = malloc(n, PFI_MTYPE, M_DONTWAIT); + if (np == NULL) + panic("pfi_attach_ifnet: " + "cannot allocate translation table"); + bzero(np, n); + if (mp != NULL) + bcopy(mp, np, m); + pfi_index2kif = np; + if (mp != NULL) + free(mp, PFI_MTYPE); + } + + strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); + p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); + if (p == NULL) { + /* add group */ + pfi_copy_group(key.pfik_name, ifp->if_xname, + sizeof(key.pfik_name)); + q = RB_FIND(pfi_ifhead, &pfi_ifs, &key); + if (q == NULL) + q = pfi_if_create(key.pfik_name, pfi_self, PFI_IFLAG_GROUP); + if (q == NULL) + panic("pfi_attach_ifnet: " + "cannot allocate '%s' group", key.pfik_name); + + /* add interface */ + p = pfi_if_create(ifp->if_xname, q, PFI_IFLAG_INSTANCE); + if (p == NULL) + panic("pfi_attach_ifnet: " + "cannot allocate '%s' interface", ifp->if_xname); + } else + q = p->pfik_parent; + p->pfik_ifp = ifp; + p->pfik_flags |= PFI_IFLAG_ATTACHED; + p->pfik_ah_cookie = hook_establish(ifp->if_addrhooks, + 1, pfi_kifaddr_update, p); + pfi_index2kif[ifp->if_index] = p; + pfi_dohooks(p); + splx(s); +} + +void +pfi_detach_ifnet(struct ifnet *ifp) +{ + struct pfi_kif *p, *q, key; + int s; + + strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name)); + + s = splsoftnet(); + pfi_update++; + p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); + if (p == NULL) { + printf("pfi_detach_ifnet: cannot find %s", ifp->if_xname); + splx(s); + return; + } + hook_disestablish(p->pfik_ifp->if_addrhooks, p->pfik_ah_cookie); + q = p->pfik_parent; + p->pfik_ifp = NULL; + p->pfik_flags &= ~PFI_IFLAG_ATTACHED; + pfi_index2kif[ifp->if_index] = NULL; + pfi_dohooks(p); + pfi_maybe_destroy(p); + splx(s); +} + +struct pfi_kif * +pfi_lookup_create(const char *name) +{ + struct pfi_kif *p, *q, key; + int s; -void pfi_dynaddr_update(void *); + s = splsoftnet(); + p = pfi_lookup_if(name); + if (p == NULL) { + pfi_copy_group(key.pfik_name, name, sizeof(key.pfik_name)); + q = pfi_lookup_if(key.pfik_name); + if (q != NULL) + p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE); + } + splx(s); + return (p); +} + +struct pfi_kif * +pfi_attach_rule(const char *name) +{ + struct pfi_kif *p; + + p = pfi_lookup_create(name); + if (p != NULL) + p->pfik_rules++; + return (p); +} + +void +pfi_detach_rule(struct pfi_kif *p) +{ + if (p == NULL) + return; + if (p->pfik_rules > 0) + p->pfik_rules--; + else + printf("pfi_detach_rule: reference count at 0\n"); + pfi_maybe_destroy(p); +} + +void +pfi_attach_state(struct pfi_kif *p) +{ + if (!p->pfik_states++) + TAILQ_INSERT_TAIL(&pfi_statehead, p, pfik_w_states); +} + +void +pfi_detach_state(struct pfi_kif *p) +{ + if (p == NULL) + return; + if (p->pfik_states <= 0) { + printf("pfi_detach_state: reference count <= 0\n"); + return; + } + if (!--p->pfik_states) + TAILQ_REMOVE(&pfi_statehead, p, pfik_w_states); + pfi_maybe_destroy(p); +} int pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) { + struct pfi_dynaddr *dyn; + char tblname[PF_TABLE_NAME_SIZE]; + struct pf_ruleset *ruleset = NULL; + int s, rv = 0; + 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; - aw->p.dyn->hook_cookie = hook_establish( - aw->p.dyn->ifp->if_addrhooks, 1, - pfi_dynaddr_update, aw->p.dyn); - if (aw->p.dyn->hook_cookie == NULL) { - pool_put(&pf_addr_pl, aw->p.dyn); - aw->p.dyn = NULL; + dyn = pool_get(&pfi_addr_pl, PR_NOWAIT); + if (dyn == NULL) return (1); - } + bzero(dyn, sizeof(*dyn)); + + s = splsoftnet(); + dyn->pfid_kif = pfi_attach_rule(aw->v.ifname); + if (dyn->pfid_kif == NULL) + senderr(1); + + dyn->pfid_net = pfi_unmask(&aw->v.a.mask); + if (af == AF_INET && dyn->pfid_net == 32) + dyn->pfid_net = 128; + strlcpy(tblname, aw->v.ifname, sizeof(tblname)); + if (aw->iflags & PFI_AFLAG_NETWORK) + strlcat(tblname, ":network", sizeof(tblname)); + if (aw->iflags & PFI_AFLAG_BROADCAST) + strlcat(tblname, ":broadcast", sizeof(tblname)); + if (aw->iflags & PFI_AFLAG_PEER) + strlcat(tblname, ":peer", sizeof(tblname)); + if (aw->iflags & PFI_AFLAG_NOALIAS) + strlcat(tblname, ":0", sizeof(tblname)); + if (dyn->pfid_net != 128) + snprintf(tblname+strlen(tblname), + sizeof(tblname)-strlen(tblname), + "/%d", dyn->pfid_net); + ruleset = pf_find_or_create_ruleset(pfi_reserved_anchor, + pfi_interface_ruleset); + if (ruleset == NULL) + senderr(1); + + dyn->pfid_kt = pfr_attach_table(ruleset, tblname); + if (dyn->pfid_kt == NULL) + senderr(1); + + dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; + dyn->pfid_iflags = aw->iflags; + dyn->pfid_af = af; + dyn->pfid_hook_cookie = hook_establish( + dyn->pfid_kif->pfik_ah_head, 1, + pfi_dynaddr_update, dyn); + if (dyn->pfid_hook_cookie == NULL) + senderr(1); + + aw->p.dyn = dyn; pfi_dynaddr_update(aw->p.dyn); + splx(s); return (0); + +_bad: + if (dyn->pfid_kt != NULL) + pfr_detach_table(dyn->pfid_kt); + if (ruleset != NULL) + pf_remove_if_empty_ruleset(ruleset); + if (dyn->pfid_kif != NULL) + pfi_detach_rule(dyn->pfid_kif); + pool_put(&pfi_addr_pl, dyn); + splx(s); + return (rv); } void pfi_dynaddr_update(void *p) { - struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p; - struct ifaddr *ia; - int s, changed = 0; + struct pfi_dynaddr *dyn = (struct pfi_dynaddr *)p; + struct pfi_kif *kif = dyn->pfid_kif; + struct pfr_ktable *kt = dyn->pfid_kt; - if (ad == NULL || ad->ifp == NULL) + if (dyn == NULL || kif == NULL || kt == NULL) panic("pfi_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 (kt->pfrkt_larg != pfi_update) { + /* this table need to be brought up-to-date */ + pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); + kt->pfrkt_larg = pfi_update; + } + pfr_dynaddr_update(kt, dyn); +} + +void +pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) +{ + int e, size2 = 0; + struct pfi_kif *p; + struct pfr_table t; + + if ((kif->pfik_flags & PFI_IFLAG_INSTANCE) && kif->pfik_ifp == NULL) { + pfr_clr_addrs(&kt->pfrkt_t, NULL, 0); + return; + } + pfi_buffer_cnt = 0; + if ((kif->pfik_flags & PFI_IFLAG_INSTANCE)) + pfi_instance_add(kif->pfik_ifp, net, flags); + else if (strcmp(kif->pfik_name, "self")) { + TAILQ_FOREACH(p, &kif->pfik_grouphead, pfik_instances) + pfi_instance_add(p->pfik_ifp, net, flags); + } else { + RB_FOREACH(p, pfi_ifhead, &pfi_ifs) + if (p->pfik_flags & PFI_IFLAG_INSTANCE) + pfi_instance_add(p->pfik_ifp, net, flags); + } + t = kt->pfrkt_t; + t.pfrt_flags = 0; + if ((e = pfr_set_addrs(&t, pfi_buffer, pfi_buffer_cnt, &size2, + NULL, NULL, NULL, 0))) + printf("pfi_table_update: cannot set %d new addresses " + "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e); +} + +void +pfi_instance_add(struct ifnet *ifp, int net, int flags) +{ + struct ifaddr *ia; + int got4 = 0, got6 = 0; + int net2, af; + + if (ifp == NULL) + return; + TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) { + if (ia->ifa_addr == NULL) + continue; + af = ia->ifa_addr->sa_family; + if (af != AF_INET && af != AF_INET6) + continue; + if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) + continue; + if ((flags & PFI_AFLAG_BROADCAST) && + !(ifp->if_flags & IFF_BROADCAST)) + continue; + if ((flags & PFI_AFLAG_PEER) && + !(ifp->if_flags & IFF_POINTOPOINT)) + continue; + if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && + IN6_IS_ADDR_LINKLOCAL( + &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr)) + continue; + if (flags & PFI_AFLAG_NOALIAS) { + if (af == AF_INET && got4) + continue; + if (af == AF_INET6 && got6) + continue; + } + if (af == AF_INET) + got4 = 1; + else + got6 = 1; + net2 = net; + if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { + if (af == AF_INET) { + net2 = pfi_unmask(&((struct sockaddr_in *) + ia->ifa_netmask)->sin_addr); + } else { + net2 = pfi_unmask(&((struct sockaddr_in6 *) + ia->ifa_netmask)->sin6_addr); } - if (changed) - ad->undefined = 0; - break; } - if (ia == NULL) - ad->undefined = 1; - splx(s); + if (af == AF_INET && net2 > 32) + net2 = 32; + if (flags & PFI_AFLAG_BROADCAST) + pfi_address_add(ia->ifa_broadaddr, af, net2); + else if (flags & PFI_AFLAG_PEER) + pfi_address_add(ia->ifa_dstaddr, af, net2); + else + pfi_address_add(ia->ifa_addr, af, net2); + } +} + +void +pfi_address_add(struct sockaddr *sa, int af, int net) +{ + struct pfr_addr *p; + int i; + + if (pfi_buffer_cnt >= pfi_buffer_max) { + int new_max = pfi_buffer_max * 2; + + if (new_max > PFI_BUFFER_MAX) { + printf("pfi_address_add: address buffer full " + "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); + return; + } + p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE, + M_DONTWAIT); + if (p == NULL) { + printf("pfi_address_add: no memory to grow buffer " + " (%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); + return; + } + memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer)); + /* no need to zero buffer */ + free(pfi_buffer, PFI_MTYPE); + pfi_buffer = p; + pfi_buffer_max = new_max; + } + if (af == AF_INET && net > 32) + net = 128; + p = pfi_buffer + pfi_buffer_cnt++; + bzero(p, sizeof(*p)); + p->pfra_af = af; + p->pfra_net = net; + if (af == AF_INET) + p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; + if (af == AF_INET6) { + p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; + if (IN6_IS_ADDR_LINKLOCAL(&p->pfra_ip6addr)) + p->pfra_ip6addr.s6_addr16[1] = 0; + } + /* mask network address bits */ + if (net < 128) + ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); + for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) + ((caddr_t)p)[i] = 0; } void pfi_dynaddr_remove(struct pf_addr_wrap *aw) { - if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL) + int s; + + if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || + aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) return; - hook_disestablish(aw->p.dyn->ifp->if_addrhooks, - aw->p.dyn->hook_cookie); - pool_put(&pf_addr_pl, aw->p.dyn); + + s = splsoftnet(); + hook_disestablish(aw->p.dyn->pfid_kif->pfik_ah_head, + aw->p.dyn->pfid_hook_cookie); + pfi_detach_rule(aw->p.dyn->pfid_kif); + aw->p.dyn->pfid_kif = NULL; + pfr_detach_table(aw->p.dyn->pfid_kt); + aw->p.dyn->pfid_kt = NULL; + pool_put(&pfi_addr_pl, aw->p.dyn); aw->p.dyn = NULL; + splx(s); } void pfi_dynaddr_copyout(struct pf_addr_wrap *aw) { - if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL) + if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || + aw->p.dyn->pfid_kif == NULL) + return; + aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; +} + +void +pfi_kifaddr_update(void *v) +{ + int s; + + s = splsoftnet(); + pfi_update++; + pfi_dohooks(v); + splx(s); +} + +int +pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) +{ + return strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ); +} + +struct pfi_kif * +pfi_if_create(const char *name, struct pfi_kif *q, int flags) +{ + struct pfi_kif *p; + + p = malloc(sizeof(*p), PFI_MTYPE, M_DONTWAIT); + if (p == NULL) + return (NULL); + bzero(p, sizeof(*p)); + p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE, + M_DONTWAIT); + if (p->pfik_ah_head == NULL) { + free(p, PFI_MTYPE); + return (NULL); + } + bzero(p->pfik_ah_head, sizeof(*p->pfik_ah_head)); + TAILQ_INIT(p->pfik_ah_head); + TAILQ_INIT(&p->pfik_grouphead); + strlcpy(p->pfik_name, name, sizeof(p->pfik_name)); + RB_INIT(&p->pfik_lan_ext); + RB_INIT(&p->pfik_ext_gwy); + p->pfik_flags = flags; + p->pfik_parent = q; + p->pfik_tzero = time.tv_sec; + + RB_INSERT(pfi_ifhead, &pfi_ifs, p); + if (q != NULL) { + q->pfik_addcnt++; + TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, pfik_instances); + } + pfi_ifcnt++; + return (p); +} + +int +pfi_maybe_destroy(struct pfi_kif *p) +{ + int i, j, k, s; + struct pfi_kif *q = p->pfik_parent; + + if ((p->pfik_flags & (PFI_IFLAG_ATTACHED | PFI_IFLAG_GROUP)) || + p->pfik_rules > 0 || p->pfik_states > 0) + return (0); + + s = splsoftnet(); + if (q != NULL) { + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + for (k = 0; k < 2; k++) { + q->pfik_bytes[i][j][k] += + p->pfik_bytes[i][j][k]; + q->pfik_packets[i][j][k] += + p->pfik_packets[i][j][k]; + } + q->pfik_delcnt++; + TAILQ_REMOVE(&q->pfik_grouphead, p, pfik_instances); + } + pfi_ifcnt--; + RB_REMOVE(pfi_ifhead, &pfi_ifs, p); + splx(s); + + free(p, PFI_MTYPE); + return (1); +} + +void +pfi_copy_group(char *p, const char *q, int m) +{ + while (m > 1 && *q && !(*q >= '0' && *q <= '9')) { + *p++ = *q++; + m--; + } + if (m > 0) + *p++ = '\0'; +} + +void +pfi_dynamic_drivers(void) +{ + char *buses[] = PFI_DYNAMIC_BUSES; + int nbuses = sizeof(buses)/sizeof(buses[0]); + int enabled[sizeof(buses)/sizeof(buses[0])]; + struct device *dev; + struct cfdata *cf; + struct cfdriver *drv; + short *p; + int i; + + bzero(enabled, sizeof(enabled)); + TAILQ_FOREACH(dev, &alldevs, dv_list) { + if (!(dev->dv_flags & DVF_ACTIVE)) + continue; + for (i = 0; i < nbuses; i++) + if (!enabled[i] && !strcmp(buses[i], + dev->dv_cfdata->cf_driver->cd_name)) + enabled[i] = 1; + } + for (cf = cfdata; cf->cf_driver; cf++) { + if (cf->cf_driver->cd_class != DV_IFNET) + continue; + for (p = cf->cf_parents; p && *p >= 0; p++) { + if ((drv = cfdata[*p].cf_driver) == NULL) + continue; + for (i = 0; i < nbuses; i++) + if (enabled[i] && + !strcmp(drv->cd_name, buses[i])) + break; + if (i < nbuses) { + pfi_newgroup(cf->cf_driver->cd_name, + PFI_IFLAG_DYNAMIC); + break; + } + } + } +} + +void +pfi_newgroup(const char *name, int flags) +{ + struct pfi_kif *p; + + p = pfi_lookup_if(name); + if (p == NULL) + p = pfi_if_create(name, pfi_self, PFI_IFLAG_GROUP); + if (p == NULL) { + printf("pfi_newgroup: cannot allocate '%s' group", name); + return; + } + p->pfik_flags |= flags; +} + +void +pfi_fill_oldstatus(struct pf_status *pfs) +{ + struct pfi_kif *p, key; + int i, j, k, s; + + strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name)); + s = splsoftnet(); + p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); + if (p == NULL) { + splx(s); return; - bcopy(aw->p.dyn->ifname, aw->v.ifname, sizeof(aw->v.ifname)); - aw->p.dyn = (struct pf_addr_dyn *)1; + } + bzero(pfs->pcounters, sizeof(pfs->pcounters)); + bzero(pfs->bcounters, sizeof(pfs->bcounters)); + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + for (k = 0; k < 2; k++) { + pfs->pcounters[i][j][k] = + p->pfik_packets[i][j][k]; + pfs->bcounters[i][j] += + p->pfik_bytes[i][j][k]; + } + splx(s); +} + +int +pfi_clr_istats(const char *name, int *nzero, int flags) +{ + struct pfi_kif *p; + int n = 0, s; + long tzero = time.tv_sec; + + s = splsoftnet(); + ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); + RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { + if (pfi_skip_if(name, p, flags)) + continue; + bzero(p->pfik_packets, sizeof(p->pfik_packets)); + bzero(p->pfik_bytes, sizeof(p->pfik_bytes)); + p->pfik_tzero = tzero; + n++; + } + splx(s); + if (nzero != NULL) + *nzero = n; + return (0); +} + +int +pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags) +{ + struct pfi_kif *p; + int s, n = 0; + + ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE); + s = splsoftnet(); + RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { + if (pfi_skip_if(name, p, flags)) + continue; + if (*size > n++) { + if (!p->pfik_tzero) + p->pfik_tzero = boottime.tv_sec; + if (copyout(p, buf++, sizeof(*buf))) { + splx(s); + return (EFAULT); + } + } + } + splx(s); + *size = n; + return (0); +} + +struct pfi_kif * +pfi_lookup_if(const char *name) +{ + struct pfi_kif *p, key; + + strlcpy(key.pfik_name, name, sizeof(key.pfik_name)); + p = RB_FIND(pfi_ifhead, &pfi_ifs, &key); + return (p); +} + +int +pfi_skip_if(const char *filter, struct pfi_kif *p, int f) +{ + if ((p->pfik_flags & PFI_IFLAG_GROUP) && !(f & PFI_FLAG_GROUP)) + return (1); + if ((p->pfik_flags & PFI_IFLAG_INSTANCE) && !(f & PFI_FLAG_INSTANCE)) + return (1); + if (filter == NULL || !*filter) + return (0); + return !strncmp(p->pfik_name, filter, strlen(filter)); +} + +/* from pf_print_state.c */ +int +pfi_unmask(void *addr) +{ + struct pf_addr *m = addr; + int i = 31, j = 0, b = 0; + u_int32_t tmp; + + while (j < 4 && m->addr32[j] == 0xffffffff) { + b += 32; + j++; + } + if (j < 4) { + tmp = ntohl(m->addr32[j]); + for (i = 31; tmp & (1 << i); --i) + b++; + } + return (b); +} + +void +pfi_dohooks(struct pfi_kif *p) +{ + for (; p != NULL; p = p->pfik_parent) + dohooks(p->pfik_ah_head, 0); +} + +int +pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) +{ + if (af == AF_INET) { + switch (dyn->pfid_acnt4) { + case 0: + return (0); + case 1: + if (PF_AZERO(&dyn->pfid_mask4, AF_INET)) + return (1); + return (PF_MATCHA(0, &dyn->pfid_addr4, + &dyn->pfid_mask4, a, AF_INET)); + default: + return pfr_match_addr(dyn->pfid_kt, a, AF_INET); + } + } else { + switch (dyn->pfid_acnt6) { + case (0): + return (0); + case 1: + if (PF_AZERO(&dyn->pfid_mask6, AF_INET6)); + return (1); + return (PF_MATCHA(0, &dyn->pfid_addr6, + &dyn->pfid_mask6, a, AF_INET6)); + default: + return pfr_match_addr(dyn->pfid_kt, a, AF_INET6); + } + } } diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index 3f1af4d5f5f..71e048c4233 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,8 +1,7 @@ -/* $OpenBSD: pf_ioctl.c,v 1.96 2003/12/22 10:10:06 dhartmei Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.97 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier - * Copyright (c) 2002,2003 Henning Brauer * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -107,8 +106,6 @@ pfattach(int num) pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl", &pool_allocator_nointr); - pool_init(&pf_addr_pl, sizeof(struct pf_addr_dyn), 0, 0, 0, "pfaddrpl", - &pool_allocator_nointr); pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0, "pfsrctrpl", NULL); pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl", @@ -118,13 +115,12 @@ pfattach(int num) pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0, "pfpooladdrpl", NULL); pfr_initialize(); + pfi_initialize(); pf_osfp_initialize(); pool_sethardlimit(&pf_state_pl, pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0); - RB_INIT(&tree_lan_ext); - RB_INIT(&tree_ext_gwy); RB_INIT(&tree_src_tracking); TAILQ_INIT(&pf_anchors); pf_init_ruleset(&pf_main_ruleset); @@ -313,7 +309,8 @@ pf_find_ruleset(char *anchorname, char *rulesetname) } struct pf_ruleset * -pf_find_or_create_ruleset(char *anchorname, char *rulesetname) +pf_find_or_create_ruleset(char anchorname[PF_ANCHOR_NAME_SIZE], + char rulesetname[PF_RULESET_NAME_SIZE]) { struct pf_anchor *anchor, *a; struct pf_ruleset *ruleset, *r; @@ -404,6 +401,7 @@ pf_empty_pool(struct pf_palist *poola) while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) { pfi_dynaddr_remove(&empty_pool_pa->addr); pf_tbladdr_remove(&empty_pool_pa->addr); + pfi_detach_rule(empty_pool_pa->kif); TAILQ_REMOVE(poola, empty_pool_pa, entries); pool_put(&pf_pooladdr_pl, empty_pool_pa); } @@ -438,6 +436,7 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) pf_tbladdr_remove(&rule->src.addr); pf_tbladdr_remove(&rule->dst.addr); } + pfi_detach_rule(rule->kif); pf_empty_pool(&rule->rpool.list); pool_put(&pf_rule_pl, rule); } @@ -748,7 +747,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) case DIOCOSFPGET: case DIOCGETSRCNODES: case DIOCCLRSRCNODES: - break; + case DIOCIGETIFACES: + case DIOCICLRISTATS: + break; + case DIOCRCLRTABLES: + case DIOCRADDTABLES: + case DIOCRDELTABLES: + case DIOCRSETTFLAGS: + if (((struct pfioc_table *)addr)->pfrio_flags & + PFR_FLAG_DUMMY) + break; /* dummy operation ok */ + return (EPERM); default: return (EPERM); } @@ -778,7 +787,21 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) case DIOCRTSTADDRS: case DIOCOSFPGET: case DIOCGETSRCNODES: + case DIOCIGETIFACES: break; + case DIOCRCLRTABLES: + case DIOCRADDTABLES: + case DIOCRDELTABLES: + case DIOCRCLRTSTATS: + case DIOCRCLRADDRS: + case DIOCRADDADDRS: + case DIOCRDELADDRS: + case DIOCRSETADDRS: + case DIOCRSETTFLAGS: + if (((struct pfioc_table *)addr)->pfrio_flags & + PFR_FLAG_DUMMY) + break; /* dummy operation ok */ + return (EACCES); default: return (EACCES); } @@ -800,11 +823,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_status.debug = debug; pf_status.stateid = stateid; pf_status.hostid = hostid; - pf_status.src_nodes = src_nodes; + pf_status.states = src_nodes; pf_status.since = time.tv_sec; - if (status_ifp != NULL) - strlcpy(pf_status.ifname, - status_ifp->if_xname, IFNAMSIZ); DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n")); } break; @@ -866,7 +886,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } bcopy(&pr->rule, rule, sizeof(struct pf_rule)); rule->anchor = NULL; - rule->ifp = NULL; + rule->kif = NULL; TAILQ_INIT(&rule->rpool.list); /* initialize refcounting */ rule->states = 0; @@ -893,8 +913,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) else rule->nr = 0; if (rule->ifname[0]) { - rule->ifp = ifunit(rule->ifname); - if (rule->ifp == NULL) { + rule->kif = pfi_attach_rule(rule->ifname); + if (rule->kif == NULL) { pool_put(&pf_rule_pl, rule); error = EINVAL; break; @@ -1091,14 +1111,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } #endif /* INET6 */ if (newrule->ifname[0]) { - newrule->ifp = ifunit(newrule->ifname); - if (newrule->ifp == NULL) { + newrule->kif = pfi_attach_rule(newrule->ifname); + if (newrule->kif == NULL) { pool_put(&pf_rule_pl, newrule); error = EINVAL; break; } } else - newrule->ifp = NULL; + newrule->kif = NULL; #ifdef ALTQ /* set queue IDs */ @@ -1205,14 +1225,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_state *state; s = splsoftnet(); - RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) + RB_FOREACH(state, pf_state_tree_id, &tree_id) state->timeout = PFTM_PURGE; pf_purge_expired_states(); pf_status.states = 0; splx(s); -#if NPFSYNC pfsync_clear_states(pf_status.hostid); -#endif break; } @@ -1222,17 +1240,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) int killed = 0; s = splsoftnet(); - RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) { - if ((!psk->psk_af || state->af == psk->psk_af) && - (!psk->psk_proto || psk->psk_proto == state->proto) && + RB_FOREACH(state, pf_state_tree_id, &tree_id) { + if ((!psk->psk_af || state->af == psk->psk_af) + && (!psk->psk_proto || psk->psk_proto == + state->proto) && PF_MATCHA(psk->psk_src.not, &psk->psk_src.addr.v.a.addr, - &psk->psk_src.addr.v.a.mask, &state->lan.addr, - state->af) && + &psk->psk_src.addr.v.a.mask, + &state->lan.addr, state->af) && PF_MATCHA(psk->psk_dst.not, &psk->psk_dst.addr.v.a.addr, - &psk->psk_dst.addr.v.a.mask, &state->ext.addr, - state->af) && + &psk->psk_dst.addr.v.a.mask, + &state->ext.addr, state->af) && (psk->psk_src.port_op == 0 || pf_match_port(psk->psk_src.port_op, psk->psk_src.port[0], psk->psk_src.port[1], @@ -1254,6 +1273,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) case DIOCADDSTATE: { struct pfioc_state *ps = (struct pfioc_state *)addr; struct pf_state *state; + struct pfi_kif *kif; if (ps->state.timeout >= PFTM_MAX && ps->state.timeout != PFTM_UNTIL_PACKET) { @@ -1266,15 +1286,23 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } s = splsoftnet(); + kif = pfi_lookup_create(ps->state.u.ifname); + if (kif == NULL) { + error = ENOENT; + splx(s); + } bcopy(&ps->state, state, sizeof(struct pf_state)); + bzero(&state->u, sizeof(state->u)); state->rule.ptr = NULL; state->nat_rule.ptr = NULL; state->anchor.ptr = NULL; - state->rt_ifp = NULL; + state->rt_kif = NULL; state->creation = time.tv_sec; state->packets[0] = state->packets[1] = 0; state->bytes[0] = state->bytes[1] = 0; - if (pf_insert_state(state)) { + + if (pf_insert_state(kif, state)) { + pfi_maybe_destroy(kif); pool_put(&pf_state_pl, state); error = ENOMEM; } @@ -1289,7 +1317,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) nr = 0; s = splsoftnet(); - RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) { + RB_FOREACH(state, pf_state_tree_id, &tree_id) { if (nr >= ps->nr) break; nr++; @@ -1318,13 +1346,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pfioc_states *ps = (struct pfioc_states *)addr; struct pf_state *state; struct pf_state *p, pstore; + struct pfi_kif *kif; u_int32_t nr = 0; int space = ps->ps_len; if (space == 0) { s = splsoftnet(); - RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) - nr++; + TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) + nr += kif->pfik_states; splx(s); ps->ps_len = sizeof(struct pf_state) * nr; return (0); @@ -1332,32 +1361,36 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) s = splsoftnet(); p = ps->ps_states; - RB_FOREACH(state, pf_state_tree_ext_gwy, &tree_ext_gwy) { - int secs = time.tv_sec; + TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) + RB_FOREACH(state, pf_state_tree_ext_gwy, + &kif->pfik_ext_gwy) { + int secs = time.tv_sec; - if ((nr + 1) * sizeof(*p) > (unsigned)ps->ps_len) - break; + if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len) + break; - bcopy(state, &pstore, sizeof(pstore)); - pstore.rule.nr = state->rule.ptr->nr; - pstore.nat_rule.nr = (state->nat_rule.ptr == NULL) ? - -1 : state->nat_rule.ptr->nr; - pstore.anchor.nr = (state->anchor.ptr == NULL) ? - -1 : state->anchor.ptr->nr; - pstore.creation = secs - pstore.creation; - pstore.expire = pf_state_expires(state); - if (pstore.expire > secs) - pstore.expire -= secs; - else - pstore.expire = 0; - error = copyout(&pstore, p, sizeof(*p)); - if (error) { - splx(s); - goto fail; + bcopy(state, &pstore, sizeof(pstore)); + strlcpy(pstore.u.ifname, kif->pfik_name, + sizeof(pstore.u.ifname)); + pstore.rule.nr = state->rule.ptr->nr; + pstore.nat_rule.nr = (state->nat_rule.ptr == + NULL) ? -1 : state->nat_rule.ptr->nr; + pstore.anchor.nr = (state->anchor.ptr == + NULL) ? -1 : state->anchor.ptr->nr; + pstore.creation = secs - pstore.creation; + pstore.expire = pf_state_expires(state); + if (pstore.expire > secs) + pstore.expire -= secs; + else + pstore.expire = 0; + error = copyout(&pstore, p, sizeof(*p)); + if (error) { + splx(s); + goto fail; + } + p++; + nr++; } - p++; - nr++; - } ps->ps_len = sizeof(struct pf_state) * nr; splx(s); break; @@ -1366,35 +1399,31 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) case DIOCGETSTATUS: { struct pf_status *s = (struct pf_status *)addr; bcopy(&pf_status, s, sizeof(struct pf_status)); + pfi_fill_oldstatus(s); break; } case DIOCSETSTATUSIF: { struct pfioc_if *pi = (struct pfioc_if *)addr; - struct ifnet *ifp; if (pi->ifname[0] == 0) { - status_ifp = NULL; bzero(pf_status.ifname, IFNAMSIZ); break; } - if ((ifp = ifunit(pi->ifname)) == NULL) { + if (ifunit(pi->ifname) == NULL) { error = EINVAL; break; - } else if (ifp == status_ifp) - break; - status_ifp = ifp; - /* fallthrough into DIOCCLRSTATUS */ + } + strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ); + break; } case DIOCCLRSTATUS: { - u_int64_t stateid = pf_status.stateid; u_int32_t running = pf_status.running; u_int32_t states = pf_status.states; u_int32_t src_nodes = pf_status.src_nodes; u_int32_t since = pf_status.since; u_int32_t debug = pf_status.debug; - u_int32_t hostid = pf_status.hostid; bzero(&pf_status, sizeof(struct pf_status)); pf_status.running = running; @@ -1402,11 +1431,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_status.src_nodes = src_nodes; pf_status.since = since; pf_status.debug = debug; - pf_status.hostid = hostid; - pf_status.stateid = stateid; - if (status_ifp != NULL) - strlcpy(pf_status.ifname, - status_ifp->if_xname, IFNAMSIZ); + if (*pf_status.ifname) + pfi_clr_istats(pf_status.ifname, NULL, 0); break; } @@ -1414,7 +1440,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr; struct pf_state *state; struct pf_state key; - int direction = pnl->direction; + int m = 0, direction = pnl->direction; key.af = pnl->af; key.proto = pnl->proto; @@ -1438,15 +1464,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) key.ext.port = pnl->dport; PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af); key.gwy.port = pnl->sport; - state = pf_find_state(&key, PF_EXT_GWY); + state = pf_find_state_all(&key, PF_EXT_GWY, &m); } else { PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af); key.lan.port = pnl->dport; PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af); key.ext.port = pnl->sport; - state = pf_find_state(&key, PF_LAN_EXT); + state = pf_find_state_all(&key, PF_LAN_EXT, &m); } - if (state != NULL) { + if (m > 1) + error = E2BIG; /* more than one state */ + else if (state != NULL) { if (direction == PF_IN) { PF_ACPY(&pnl->rsaddr, &state->lan.addr, state->af); @@ -1780,8 +1808,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr)); if (pa->ifname[0]) { - pa->ifp = ifunit(pa->ifname); - if (pa->ifp == NULL) { + pa->kif = pfi_attach_rule(pa->ifname); + if (pa->kif == NULL) { pool_put(&pf_pooladdr_pl, pa); error = EINVAL; break; @@ -1789,6 +1817,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } if (pfi_dynaddr_setup(&pa->addr, pp->af)) { pfi_dynaddr_remove(&pa->addr); + pfi_detach_rule(pa->kif); pool_put(&pf_pooladdr_pl, pa); error = EINVAL; break; @@ -1894,17 +1923,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } #endif /* INET6 */ if (newpa->ifname[0]) { - newpa->ifp = ifunit(newpa->ifname); - if (newpa->ifp == NULL) { + newpa->kif = pfi_attach_rule(newpa->ifname); + if (newpa->kif == NULL) { pool_put(&pf_pooladdr_pl, newpa); error = EINVAL; break; } } else - newpa->ifp = NULL; + newpa->kif = NULL; if (pfi_dynaddr_setup(&newpa->addr, pca->af) || pf_tbladdr_setup(ruleset, &newpa->addr)) { pfi_dynaddr_remove(&newpa->addr); + pfi_detach_rule(newpa->kif); pool_put(&pf_pooladdr_pl, newpa); error = EINVAL; break; @@ -1936,6 +1966,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) TAILQ_REMOVE(&pool->list, oldpa, entries); pfi_dynaddr_remove(&oldpa->addr); pf_tbladdr_remove(&oldpa->addr); + pfi_detach_rule(oldpa->kif); pool_put(&pf_pooladdr_pl, oldpa); } else { if (oldpa == NULL) @@ -2028,7 +2059,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, - io->pfrio_flags); + io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2040,7 +2071,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size, - &io->pfrio_nadd, io->pfrio_flags); + &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2052,7 +2083,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size, - &io->pfrio_ndel, io->pfrio_flags); + &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2064,7 +2095,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer, - &io->pfrio_size, io->pfrio_flags); + &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2076,7 +2107,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer, - &io->pfrio_size, io->pfrio_flags); + &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2088,7 +2119,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size, - &io->pfrio_nzero, io->pfrio_flags); + &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2101,7 +2132,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size, io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange, - &io->pfrio_ndel, io->pfrio_flags); + &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2113,7 +2144,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel, - io->pfrio_flags); + io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2125,7 +2156,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer, - io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags); + io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags | + PFR_FLAG_USERIOCTL); break; } @@ -2137,7 +2169,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer, - io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags); + io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | + PFR_FLAG_USERIOCTL); break; } @@ -2150,7 +2183,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd, - &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags); + &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags | + PFR_FLAG_USERIOCTL); break; } @@ -2162,7 +2196,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer, - &io->pfrio_size, io->pfrio_flags); + &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2174,7 +2208,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer, - &io->pfrio_size, io->pfrio_flags); + &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2186,7 +2220,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer, - io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags); + io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags | + PFR_FLAG_USERIOCTL); break; } @@ -2198,7 +2233,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer, - io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags); + io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags | + PFR_FLAG_USERIOCTL); break; } @@ -2210,7 +2246,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_ina_begin(&io->pfrio_table, &io->pfrio_ticket, - &io->pfrio_ndel, io->pfrio_flags); + &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2222,7 +2258,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } error = pfr_ina_commit(&io->pfrio_table, io->pfrio_ticket, - &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags); + &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags | + PFR_FLAG_USERIOCTL); break; } @@ -2235,7 +2272,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr, - io->pfrio_ticket, io->pfrio_flags); + io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } @@ -2490,7 +2527,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_state *state; s = splsoftnet(); - RB_FOREACH(state, pf_state_tree_lan_ext, &tree_lan_ext) { + RB_FOREACH(state, pf_state_tree_id, &tree_id) { state->src_node = NULL; state->nat_src_node = NULL; } @@ -2521,6 +2558,26 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) splx(s); break; + case DIOCIGETIFACES: { + struct pfioc_iface *io = (struct pfioc_iface *)addr; + + if (io->pfiio_esize != sizeof(struct pfi_if)) { + error = ENODEV; + break; + } + error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer, + &io->pfiio_size, io->pfiio_flags); + break; + } + + case DIOCICLRISTATS: { + struct pfioc_iface *io = (struct pfioc_iface *)addr; + + error = pfi_clr_istats(io->pfiio_name, &io->pfiio_nzero, + io->pfiio_flags); + break; + } + default: error = ENODEV; break; diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c index 13c7f50eaf2..cf2e897baba 100644 --- a/sys/net/pf_norm.c +++ b/sys/net/pf_norm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_norm.c,v 1.76 2003/12/18 20:13:23 dhartmei Exp $ */ +/* $OpenBSD: pf_norm.c,v 1.77 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright 2001 Niels Provos <provos@citi.umich.edu> @@ -807,7 +807,7 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff, } int -pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) +pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason) { struct mbuf *m = *m0; struct pf_rule *r; @@ -824,7 +824,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr); while (r != NULL) { r->evaluations++; - if (r->ifp != NULL && r->ifp != ifp) + if (r->kif != NULL && + (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != dir) r = r->skip[PF_SKIP_DIR].ptr; @@ -987,13 +988,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) no_mem: REASON_SET(reason, PFRES_MEMORY); if (r != NULL && r->log) - PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL); + PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL); return (PF_DROP); drop: REASON_SET(reason, PFRES_NORM); if (r != NULL && r->log) - PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL); + PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL); return (PF_DROP); bad: @@ -1005,14 +1006,15 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) REASON_SET(reason, PFRES_FRAG); if (r != NULL && r->log) - PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL); + PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL); return (PF_DROP); } #ifdef INET6 int -pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) +pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, + u_short *reason) { struct mbuf *m = *m0; struct pf_rule *r; @@ -1032,7 +1034,8 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr); while (r != NULL) { r->evaluations++; - if (r->ifp != NULL && r->ifp != ifp) + if (r->kif != NULL && + (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != dir) r = r->skip[PF_SKIP_DIR].ptr; @@ -1166,25 +1169,25 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) shortpkt: REASON_SET(reason, PFRES_SHORT); if (r != NULL && r->log) - PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL); + PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL); return (PF_DROP); drop: REASON_SET(reason, PFRES_NORM); if (r != NULL && r->log) - PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL); + PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL); return (PF_DROP); badfrag: REASON_SET(reason, PFRES_FRAG); if (r != NULL && r->log) - PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL); + PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL); return (PF_DROP); } #endif int -pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff, +pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd) { struct pf_rule *r, *rm = NULL; @@ -1197,7 +1200,8 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff, r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr); while (r != NULL) { r->evaluations++; - if (r->ifp != NULL && r->ifp != ifp) + if (r->kif != NULL && + (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot) r = r->skip[PF_SKIP_IFP].ptr; else if (r->direction && r->direction != dir) r = r->skip[PF_SKIP_DIR].ptr; @@ -1290,7 +1294,7 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff, tcp_drop: REASON_SET(&reason, PFRES_NORM); if (rm != NULL && r->log) - PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL); + PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL); return (PF_DROP); } diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c index 490edb2393c..8862b22b647 100644 --- a/sys/net/pf_table.c +++ b/sys/net/pf_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_table.c,v 1.42 2003/09/26 21:44:09 cedric Exp $ */ +/* $OpenBSD: pf_table.c,v 1.43 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -49,6 +49,16 @@ return (EINVAL); \ } while (0) +#define COPYIN(from, to, size) \ + ((flags & PFR_FLAG_USERIOCTL) ? \ + copyin((from), (to), (size)) : \ + (bcopy((from), (to), (size)), 0)) + +#define COPYOUT(from, to, size) \ + ((flags & PFR_FLAG_USERIOCTL) ? \ + copyout((from), (to), (size)) : \ + (bcopy((from), (to), (size)), 0)) + #define FILLIN_SIN(sin, addr) \ do { \ (sin).sin_len = sizeof(sin); \ @@ -91,20 +101,24 @@ struct pfr_walktree { PFRW_ENQUEUE, PFRW_GET_ADDRS, PFRW_GET_ASTATS, - PFRW_POOL_GET + PFRW_POOL_GET, + PFRW_DYNADDR_UPDATE } pfrw_op; union { struct pfr_addr *pfrw1_addr; struct pfr_astats *pfrw1_astats; struct pfr_kentryworkq *pfrw1_workq; struct pfr_kentry *pfrw1_kentry; + struct pfi_dynaddr *pfrw1_dyn; } pfrw_1; int pfrw_free; + int pfrw_flags; }; #define pfrw_addr pfrw_1.pfrw1_addr #define pfrw_astats pfrw_1.pfrw1_astats #define pfrw_workq pfrw_1.pfrw1_workq #define pfrw_kentry pfrw_1.pfrw1_kentry +#define pfrw_dyn pfrw_1.pfrw1_dyn #define pfrw_cnt pfrw_free #define senderr(e) do { rv = (e); goto _bad; } while (0) @@ -133,14 +147,14 @@ void pfr_remove_kentries(struct pfr_ktable *, struct pfr_kentryworkq *); void pfr_clstats_kentries(struct pfr_kentryworkq *, long, int); -void pfr_reset_feedback(struct pfr_addr *, int); +void pfr_reset_feedback(struct pfr_addr *, int, int); void pfr_prepare_network(union sockaddr_union *, int, int); int pfr_route_kentry(struct pfr_ktable *, struct pfr_kentry *); int pfr_unroute_kentry(struct pfr_ktable *, struct pfr_kentry *); int pfr_walktree(struct radix_node *, void *); -int pfr_validate_table(struct pfr_table *, int); +int pfr_validate_table(struct pfr_table *, int, int); void pfr_commit_ktable(struct pfr_ktable *, long); void pfr_insert_ktables(struct pfr_ktableworkq *); void pfr_insert_ktable(struct pfr_ktable *); @@ -193,7 +207,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags) int s; ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY); - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) @@ -229,7 +243,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, long tzero = time.tv_sec; ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK); - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) @@ -241,7 +255,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, return (ENOMEM); SLIST_INIT(&workq); for (i = 0; i < size; i++) { - if (copyin(addr+i, &ad, sizeof(ad))) + if (COPYIN(addr+i, &ad, sizeof(ad))) senderr(EFAULT); if (pfr_validate_addr(&ad)) senderr(EINVAL); @@ -270,7 +284,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, } } if (flags & PFR_FLAG_FEEDBACK) - if (copyout(&ad, addr+i, sizeof(ad))) + if (COPYOUT(&ad, addr+i, sizeof(ad))) senderr(EFAULT); } pfr_clean_node_mask(tmpkt, &workq); @@ -290,7 +304,7 @@ _bad: pfr_clean_node_mask(tmpkt, &workq); pfr_destroy_kentries(&workq); if (flags & PFR_FLAG_FEEDBACK) - pfr_reset_feedback(addr, size); + pfr_reset_feedback(addr, size, flags); pfr_destroy_ktable(tmpkt, 0); return (rv); } @@ -306,7 +320,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, int i, rv, s, xdel = 0; ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK); - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) @@ -316,7 +330,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, pfr_mark_addrs(kt); SLIST_INIT(&workq); for (i = 0; i < size; i++) { - if (copyin(addr+i, &ad, sizeof(ad))) + if (COPYIN(addr+i, &ad, sizeof(ad))) senderr(EFAULT); if (pfr_validate_addr(&ad)) senderr(EINVAL); @@ -338,7 +352,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, xdel++; } if (flags & PFR_FLAG_FEEDBACK) - if (copyout(&ad, addr+i, sizeof(ad))) + if (COPYOUT(&ad, addr+i, sizeof(ad))) senderr(EFAULT); } if (!(flags & PFR_FLAG_DUMMY)) { @@ -353,7 +367,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, return (0); _bad: if (flags & PFR_FLAG_FEEDBACK) - pfr_reset_feedback(addr, size); + pfr_reset_feedback(addr, size, flags); return (rv); } @@ -369,7 +383,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, long tzero = time.tv_sec; ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK); - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) @@ -384,7 +398,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, SLIST_INIT(&delq); SLIST_INIT(&changeq); for (i = 0; i < size; i++) { - if (copyin(addr+i, &ad, sizeof(ad))) + if (COPYIN(addr+i, &ad, sizeof(ad))) senderr(EFAULT); if (pfr_validate_addr(&ad)) senderr(EINVAL); @@ -421,7 +435,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, } _skip: if (flags & PFR_FLAG_FEEDBACK) - if (copyout(&ad, addr+i, sizeof(ad))) + if (COPYOUT(&ad, addr+i, sizeof(ad))) senderr(EFAULT); } pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY); @@ -434,7 +448,7 @@ _skip: SLIST_FOREACH(p, &delq, pfrke_workq) { pfr_copyout_addr(&ad, p); ad.pfra_fback = PFR_FB_DELETED; - if (copyout(&ad, addr+size+i, sizeof(ad))) + if (COPYOUT(&ad, addr+size+i, sizeof(ad))) senderr(EFAULT); i++; } @@ -456,7 +470,7 @@ _skip: *ndel = xdel; if (nchange != NULL) *nchange = xchange; - if ((flags & PFR_FLAG_FEEDBACK) && *size2) + if ((flags & PFR_FLAG_FEEDBACK) && size2) *size2 = size+xdel; pfr_destroy_ktable(tmpkt, 0); return (0); @@ -464,7 +478,7 @@ _bad: pfr_clean_node_mask(tmpkt, &addq); pfr_destroy_kentries(&addq); if (flags & PFR_FLAG_FEEDBACK) - pfr_reset_feedback(addr, size); + pfr_reset_feedback(addr, size, flags); pfr_destroy_ktable(tmpkt, 0); return (rv); } @@ -479,14 +493,14 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, int i, xmatch = 0; ACCEPT_FLAGS(PFR_FLAG_REPLACE); - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, 0)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) return (ESRCH); for (i = 0; i < size; i++) { - if (copyin(addr+i, &ad, sizeof(ad))) + if (COPYIN(addr+i, &ad, sizeof(ad))) return (EFAULT); if (pfr_validate_addr(&ad)) return (EINVAL); @@ -499,7 +513,7 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH); if (p != NULL && !p->pfrke_not) xmatch++; - if (copyout(&ad, addr+i, sizeof(ad))) + if (COPYOUT(&ad, addr+i, sizeof(ad))) return (EFAULT); } if (nmatch != NULL) @@ -516,7 +530,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size, int rv; ACCEPT_FLAGS(0); - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, 0)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) @@ -530,6 +544,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size, w.pfrw_op = PFRW_GET_ADDRS; w.pfrw_addr = addr; w.pfrw_free = kt->pfrkt_cnt; + w.pfrw_flags = flags; rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); if (!rv) rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); @@ -556,7 +571,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, long tzero = time.tv_sec; ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */ - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, 0)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) @@ -570,6 +585,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, w.pfrw_op = PFRW_GET_ASTATS; w.pfrw_astats = addr; w.pfrw_free = kt->pfrkt_cnt; + w.pfrw_flags = flags; if (flags & PFR_FLAG_ATOMIC) s = splsoftnet(); rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); @@ -604,14 +620,14 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, int i, rv, s, xzero = 0; ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK); - if (pfr_validate_table(tbl, 0)) + if (pfr_validate_table(tbl, 0, 0)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) return (ESRCH); SLIST_INIT(&workq); for (i = 0; i < size; i++) { - if (copyin(addr+i, &ad, sizeof(ad))) + if (COPYIN(addr+i, &ad, sizeof(ad))) senderr(EFAULT); if (pfr_validate_addr(&ad)) senderr(EINVAL); @@ -619,7 +635,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, if (flags & PFR_FLAG_FEEDBACK) { ad.pfra_fback = (p != NULL) ? PFR_FB_CLEARED : PFR_FB_NONE; - if (copyout(&ad, addr+i, sizeof(ad))) + if (COPYOUT(&ad, addr+i, sizeof(ad))) senderr(EFAULT); } if (p != NULL) { @@ -640,7 +656,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, return (0); _bad: if (flags & PFR_FLAG_FEEDBACK) - pfr_reset_feedback(addr, size); + pfr_reset_feedback(addr, size, flags); return (rv); } @@ -841,16 +857,16 @@ pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange) } void -pfr_reset_feedback(struct pfr_addr *addr, int size) +pfr_reset_feedback(struct pfr_addr *addr, int size, int flags) { struct pfr_addr ad; int i; for (i = 0; i < size; i++) { - if (copyin(addr+i, &ad, sizeof(ad))) + if (COPYIN(addr+i, &ad, sizeof(ad))) break; ad.pfra_fback = PFR_FB_NONE; - if (copyout(&ad, addr+i, sizeof(ad))) + if (COPYOUT(&ad, addr+i, sizeof(ad))) break; } } @@ -953,7 +969,7 @@ pfr_walktree(struct radix_node *rn, void *arg) { struct pfr_kentry *ke = (struct pfr_kentry *)rn; struct pfr_walktree *w = arg; - int s; + int s, flags = w->pfrw_flags; switch (w->pfrw_op) { case PFRW_MARK: @@ -991,7 +1007,7 @@ pfr_walktree(struct radix_node *rn, void *arg) splx(s); as.pfras_tzero = ke->pfrke_tzero; - if (copyout(&as, w->pfrw_astats, sizeof(as))) + if (COPYOUT(&as, w->pfrw_astats, sizeof(as))) return (EFAULT); w->pfrw_astats++; } @@ -1004,6 +1020,24 @@ pfr_walktree(struct radix_node *rn, void *arg) return (1); /* finish search */ } break; + case PFRW_DYNADDR_UPDATE: + if (ke->pfrke_af == AF_INET) { + if (w->pfrw_dyn->pfid_acnt4++ > 0) + break; + pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net); + w->pfrw_dyn->pfid_addr4 = *SUNION2PF( + &ke->pfrke_sa, AF_INET); + w->pfrw_dyn->pfid_mask4 = *SUNION2PF( + &pfr_mask, AF_INET); + } else { + if (w->pfrw_dyn->pfid_acnt6++ > 0) + break; + pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net); + w->pfrw_dyn->pfid_addr6 = *SUNION2PF( + &ke->pfrke_sa, AF_INET6); + w->pfrw_dyn->pfid_mask6 = *SUNION2PF( + &pfr_mask, AF_INET6); + } } return (0); } @@ -1023,6 +1057,8 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags) RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { if (pfr_skip_table(filter, p, flags)) continue; + if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR)) + continue; if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) continue; p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE; @@ -1053,9 +1089,10 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags) SLIST_INIT(&addq); SLIST_INIT(&changeq); for (i = 0; i < size; i++) { - if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) + if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) senderr(EFAULT); - if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK)) + if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK, + flags & PFR_FLAG_USERIOCTL)) senderr(EINVAL); key.pfrkt_flags |= PFR_TFLAG_ACTIVE; p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); @@ -1131,9 +1168,10 @@ pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags) ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY); SLIST_INIT(&workq); for (i = 0; i < size; i++) { - if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) + if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) return (EFAULT); - if (pfr_validate_table(&key.pfrkt_t, 0)) + if (pfr_validate_table(&key.pfrkt_t, 0, + flags & PFR_FLAG_USERIOCTL)) return (EINVAL); p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { @@ -1180,7 +1218,7 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size, continue; if (n-- <= 0) continue; - if (copyout(&p->pfrkt_t, tbl++, sizeof(*tbl))) + if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl))) return (EFAULT); } if (n) { @@ -1219,7 +1257,7 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, continue; if (!(flags & PFR_FLAG_ATOMIC)) s = splsoftnet(); - if (copyout(&p->pfrkt_ts, tbl++, sizeof(*tbl))) { + if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) { splx(s); return (EFAULT); } @@ -1251,9 +1289,9 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags) ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO); SLIST_INIT(&workq); for (i = 0; i < size; i++) { - if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) + if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) return (EFAULT); - if (pfr_validate_table(&key.pfrkt_t, 0)) + if (pfr_validate_table(&key.pfrkt_t, 0, 0)) return (EINVAL); p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); if (p != NULL) { @@ -1288,9 +1326,10 @@ pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag, return (EINVAL); SLIST_INIT(&workq); for (i = 0; i < size; i++) { - if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) + if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t))) return (EFAULT); - if (pfr_validate_table(&key.pfrkt_t, 0)) + if (pfr_validate_table(&key.pfrkt_t, 0, + flags & PFR_FLAG_USERIOCTL)) return (EINVAL); p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { @@ -1374,7 +1413,8 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO); if (size && !(flags & PFR_FLAG_ADDRSTOO)) return (EINVAL); - if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK)) + if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK, + flags & PFR_FLAG_USERIOCTL)) return (EINVAL); rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset); if (rs == NULL || !rs->topen || ticket != rs->tticket) @@ -1416,7 +1456,7 @@ _skip: } SLIST_INIT(&addrq); for (i = 0; i < size; i++) { - if (copyin(addr+i, &ad, sizeof(ad))) + if (COPYIN(addr+i, &ad, sizeof(ad))) senderr(EFAULT); if (pfr_validate_addr(&ad)) senderr(EINVAL); @@ -1594,12 +1634,14 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero) } int -pfr_validate_table(struct pfr_table *tbl, int allowedflags) +pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved) { int i; if (!tbl->pfrt_name[0]) return (-1); + if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR)) + return (-1); if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1]) return (-1); for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++) @@ -2047,3 +2089,22 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af) } } +void +pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn) +{ + struct pfr_walktree w; + int s; + + bzero(&w, sizeof(w)); + w.pfrw_op = PFRW_DYNADDR_UPDATE; + w.pfrw_dyn = dyn; + + s = splsoftnet(); + dyn->pfid_acnt4 = 0; + dyn->pfid_acnt6 = 0; + if (!dyn->pfid_af || dyn->pfid_af == AF_INET) + rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); + if (!dyn->pfid_af || dyn->pfid_af == AF_INET6) + rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); + splx(s); +} diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index cc9081f887d..1b3fa417756 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.179 2003/12/15 09:10:26 henning Exp $ */ +/* $OpenBSD: pfvar.h,v 1.180 2003/12/31 11:18:25 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -99,6 +99,12 @@ struct pf_addr { #define PF_TABLE_NAME_SIZE 32 +#define PFI_AFLAG_NETWORK 0x01 +#define PFI_AFLAG_BROADCAST 0x02 +#define PFI_AFLAG_PEER 0x04 +#define PFI_AFLAG_MODEMASK 0x07 +#define PFI_AFLAG_NOALIAS 0x08 + struct pf_addr_wrap { union { struct { @@ -109,28 +115,36 @@ struct pf_addr_wrap { char tblname[PF_TABLE_NAME_SIZE]; } v; union { - struct pf_addr_dyn *dyn; + struct pfi_dynaddr *dyn; struct pfr_ktable *tbl; + int dyncnt; int tblcnt; } p; u_int8_t type; /* PF_ADDR_* */ + u_int8_t iflags; /* PFI_AFLAG_* */ }; -struct pf_addr_dyn { - char ifname[IFNAMSIZ]; - struct ifnet *ifp; - struct pf_addr *addr; - sa_family_t af; - void *hook_cookie; - u_int8_t undefined; +#ifdef _KERNEL + +struct pfi_dynaddr { + struct pf_addr pfid_addr4; + struct pf_addr pfid_mask4; + struct pf_addr pfid_addr6; + struct pf_addr pfid_mask6; + struct pfr_ktable *pfid_kt; + struct pfi_kif *pfid_kif; + void *pfid_hook_cookie; + int pfid_net; /* optional mask, or 128 */ + int pfid_acnt4; /* address count, IPv4 */ + int pfid_acnt6; /* address count, IPv6 */ + sa_family_t pfid_af; /* rule address family */ + u_int8_t pfid_iflags; /* PFI_AFLAG_* */ }; /* * Address manipulation macros */ -#ifdef _KERNEL - #ifdef INET #ifndef INET6 #define PF_INET_ONLY @@ -267,10 +281,7 @@ struct pf_addr_dyn { ((aw)->type == PF_ADDR_TABLE && \ !pfr_match_addr((aw)->p.tbl, (x), (af))) || \ ((aw)->type == PF_ADDR_DYNIFTL && \ - ((aw)->p.dyn->undefined || \ - (!PF_AZERO(&(aw)->v.a.mask, (af)) && \ - !PF_MATCHA(0, &(aw)->v.a.addr, \ - &(aw)->v.a.mask, (x), (af))))) || \ + !pfi_match_addr((aw)->p.dyn, (x), (af))) || \ ((aw)->type == PF_ADDR_ADDRMASK && \ !PF_AZERO(&(aw)->v.a.mask, (af)) && \ !PF_MATCHA(0, &(aw)->v.a.addr, \ @@ -299,7 +310,7 @@ struct pf_pooladdr { struct pf_addr_wrap addr; TAILQ_ENTRY(pf_pooladdr) entries; char ifname[IFNAMSIZ]; - struct ifnet *ifp; + struct pfi_kif *kif; }; TAILQ_HEAD(pf_palist, pf_pooladdr); @@ -465,7 +476,7 @@ struct pf_rule { u_int64_t packets; u_int64_t bytes; - struct ifnet *ifp; + struct pfi_kif *kif; struct pf_anchor *anchor; pf_osfp_t os_fingerprint; @@ -533,6 +544,10 @@ struct pf_rule { #define PFRULE_RANDOMID 0x0800 #define PFRULE_REASSEMBLE_TCP 0x1000 +/* rule flags again */ +#define PFRULE_IFBOUND 0x00010000 /* if-bound */ +#define PFRULE_GRBOUND 0x00020000 /* group-bound */ + #define PFSTATE_HIWAT 10000 /* default state table size */ struct pf_src_node { @@ -540,7 +555,7 @@ struct pf_src_node { struct pf_addr addr; struct pf_addr raddr; union pf_rule_ptr rule; - struct ifnet *ifp; + struct pfi_kif *kif; u_int32_t bytes; u_int32_t packets; u_int32_t states; @@ -577,9 +592,15 @@ struct pf_state_peer { struct pf_state { u_int64_t id; - RB_ENTRY(pf_state) entry_lan_ext; - RB_ENTRY(pf_state) entry_ext_gwy; - RB_ENTRY(pf_state) entry_id; + union { + struct { + RB_ENTRY(pf_state) entry_lan_ext; + RB_ENTRY(pf_state) entry_ext_gwy; + RB_ENTRY(pf_state) entry_id; + struct pfi_kif *kif; + } s; + char ifname[IFNAMSIZ]; + } u; struct pf_state_host lan; struct pf_state_host gwy; struct pf_state_host ext; @@ -589,7 +610,7 @@ struct pf_state { union pf_rule_ptr anchor; union pf_rule_ptr nat_rule; struct pf_addr rt_addr; - struct ifnet *rt_ifp; + struct pfi_kif *rt_kif; struct pf_src_node *src_node; struct pf_src_node *nat_src_node; u_int32_t creation; @@ -642,6 +663,9 @@ struct pf_anchor { TAILQ_HEAD(pf_anchorqueue, pf_anchor); +#define PF_RESERVED_ANCHOR "_pf" +#define PF_INTERFACE_RULESET "_if" + #define PFR_TFLAG_PERSIST 0x00000001 #define PFR_TFLAG_CONST 0x00000002 #define PFR_TFLAG_ACTIVE 0x00000004 @@ -728,6 +752,7 @@ struct pfr_ktable { struct pfr_ktable *pfrkt_shadow; struct pfr_ktable *pfrkt_root; struct pf_ruleset *pfrkt_rs; + long pfrkt_larg; int pfrkt_nflags; }; #define pfrkt_t pfrkt_ts.pfrts_t @@ -743,6 +768,60 @@ struct pfr_ktable { #define pfrkt_nomatch pfrkt_ts.pfrts_nomatch #define pfrkt_tzero pfrkt_ts.pfrts_tzero +RB_HEAD(pf_state_tree_lan_ext, pf_state); +RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state, + u.s.entry_lan_ext, pf_state_compare_lan_ext); + +RB_HEAD(pf_state_tree_ext_gwy, pf_state); +RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state, + u.s.entry_ext_gwy, pf_state_compare_ext_gwy); + +struct pfi_if { + char pfif_name[IFNAMSIZ]; + u_int64_t pfif_packets[2][2][2]; + u_int64_t pfif_bytes[2][2][2]; + u_int64_t pfif_addcnt; + u_int64_t pfif_delcnt; + long pfif_tzero; + int pfif_states; + int pfif_rules; + int pfif_flags; +}; + +TAILQ_HEAD(pfi_grouphead, pfi_kif); +TAILQ_HEAD(pfi_statehead, pfi_kif); +RB_HEAD(pfi_ifhead, pfi_kif); +struct pfi_kif { + struct pfi_if pfik_if; + RB_ENTRY(pfi_kif) pfik_tree; + struct pf_state_tree_lan_ext pfik_lan_ext; + struct pf_state_tree_ext_gwy pfik_ext_gwy; + struct pfi_grouphead pfik_grouphead; + TAILQ_ENTRY(pfi_kif) pfik_instances; + TAILQ_ENTRY(pfi_kif) pfik_w_states; + struct hook_desc_head *pfik_ah_head; + void *pfik_ah_cookie; + struct pfi_kif *pfik_parent; + struct ifnet *pfik_ifp; + int pfik_states; + int pfik_rules; +}; +#define pfik_name pfik_if.pfif_name +#define pfik_packets pfik_if.pfif_packets +#define pfik_bytes pfik_if.pfif_bytes +#define pfik_tzero pfik_if.pfif_tzero +#define pfik_flags pfik_if.pfif_flags +#define pfik_addcnt pfik_if.pfif_addcnt +#define pfik_delcnt pfik_if.pfif_delcnt +#define pfik_states pfik_if.pfif_states +#define pfik_rules pfik_if.pfif_rules + +#define PFI_IFLAG_GROUP 0x0001 /* group of interfaces */ +#define PFI_IFLAG_INSTANCE 0x0002 /* single instance */ +#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */ +#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */ +#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */ + struct pf_pdesc { u_int64_t tot_len; /* Make Mickey money */ union { @@ -1071,6 +1150,9 @@ struct pfioc_trans { #define PFR_FLAG_REPLACE 0x00000020 #define PFR_FLAG_ALLRSETS 0x00000040 #define PFR_FLAG_ALLMASK 0x0000007F +#ifdef _KERNEL +#define PFR_FLAG_USERIOCTL 0x10000000 +#endif struct pfioc_table { struct pfr_table pfrio_table; @@ -1092,6 +1174,20 @@ struct pfioc_table { #define pfrio_clrflag pfrio_nadd +#define PFI_FLAG_GROUP 0x0001 /* gets groups of interfaces */ +#define PFI_FLAG_INSTANCE 0x0002 /* gets single interfaces */ +#define PFI_FLAG_ALLMASK 0x0003 + +struct pfioc_iface { + char pfiio_name[IFNAMSIZ]; + void *pfiio_buffer; + int pfiio_esize; + int pfiio_size; + int pfiio_nzero; + int pfiio_flags; +}; + + /* * ioctl operations */ @@ -1166,35 +1262,27 @@ struct pfioc_table { #define DIOCGETSRCNODES _IOWR('D', 84, struct pfioc_src_nodes) #define DIOCCLRSRCNODES _IO('D', 85) #define DIOCSETHOSTID _IOWR('D', 86, u_int32_t) +#define DIOCIGETIFACES _IOWR('D', 87, struct pfioc_iface) +#define DIOCICLRISTATS _IOWR('D', 88, struct pfioc_iface) #ifdef _KERNEL RB_HEAD(pf_src_tree, pf_src_node); RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare); extern struct pf_src_tree tree_src_tracking; -RB_HEAD(pf_state_tree_lan_ext, pf_state); -RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state, - entry_lan_ext, pf_state_compare_lan_ext); -extern struct pf_state_tree_lan_ext tree_lan_ext; - -RB_HEAD(pf_state_tree_ext_gwy, pf_state); -RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state, - entry_ext_gwy, pf_state_compare_ext_gwy); -extern struct pf_state_tree_ext_gwy tree_ext_gwy; - RB_HEAD(pf_state_tree_id, pf_state); RB_PROTOTYPE(pf_state_tree_id, pf_state, entry_id, pf_state_compare_id); extern struct pf_state_tree_id tree_id; -extern struct pf_anchorqueue pf_anchors; -extern struct pf_ruleset pf_main_ruleset; +extern struct pf_anchorqueue pf_anchors; +extern struct pf_ruleset pf_main_ruleset; TAILQ_HEAD(pf_poolqueue, pf_pool); -extern struct pf_poolqueue pf_pools[2]; +extern struct pf_poolqueue pf_pools[2]; TAILQ_HEAD(pf_altqqueue, pf_altq); -extern struct pf_altqqueue pf_altqs[2]; -extern struct pf_palist pf_pabuf; - +extern struct pf_altqqueue pf_altqs[2]; +extern struct pf_palist pf_pabuf; +extern struct pfi_kif **pfi_index2kif; extern u_int32_t ticket_altqs_active; extern u_int32_t ticket_altqs_inactive; @@ -1212,25 +1300,30 @@ extern void pf_calc_skip_steps(struct pf_rulequeue *); extern void pf_rule_set_qid(struct pf_rulequeue *); extern u_int32_t pf_qname_to_qid(char *); extern void pf_update_anchor_rules(void); -extern struct pool pf_src_tree_pl, pf_rule_pl, pf_addr_pl; +extern struct pool pf_src_tree_pl, pf_rule_pl; extern struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl; extern struct pool pf_state_scrub_pl; extern void pf_purge_timeout(void *); extern void pf_purge_expired_src_nodes(void); extern void pf_purge_expired_states(void); -extern int pf_insert_state(struct pf_state *); +extern int pf_insert_state(struct pfi_kif *, + struct pf_state *); extern int pf_insert_src_node(struct pf_src_node **, struct pf_rule *, struct pf_addr *, sa_family_t); void pf_src_tree_remove_state(struct pf_state *); -extern struct pf_state *pf_find_state(struct pf_state *, u_int8_t); +extern struct pf_state *pf_find_state_byid(struct pf_state *); +extern struct pf_state *pf_find_state_all(struct pf_state *key, + u_int8_t tree, int *more); extern struct pf_anchor *pf_find_anchor(const char *); extern struct pf_ruleset *pf_find_ruleset(char *, char *); -extern struct pf_ruleset *pf_find_or_create_ruleset(char *, char *); +extern struct pf_ruleset *pf_find_or_create_ruleset( + char[PF_ANCHOR_NAME_SIZE], + char[PF_RULESET_NAME_SIZE]); extern void pf_remove_if_empty_ruleset( struct pf_ruleset *); -extern struct ifnet *status_ifp, *sync_ifp; +extern struct ifnet *sync_ifp; extern struct pf_rule pf_default_rule; extern void pf_addrcpy(struct pf_addr *, struct pf_addr *, u_int8_t); @@ -1251,7 +1344,7 @@ void pf_addr_inc(struct pf_addr *, sa_family_t); void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *, sa_family_t); void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t); -int pflog_packet(struct ifnet *, struct mbuf *, sa_family_t, u_int8_t, +int pflog_packet(struct pfi_kif *, struct mbuf *, sa_family_t, u_int8_t, u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *); int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *, struct pf_addr *, sa_family_t); @@ -1261,9 +1354,9 @@ int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t); int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t); void pf_normalize_init(void); -int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *); -int pf_normalize_ip6(struct mbuf **, int, struct ifnet *, u_short *); -int pf_normalize_tcp(int, struct ifnet *, struct mbuf *, int, int, void *, +int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *); +int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *); +int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *, struct pf_pdesc *); void pf_normalize_tcp_cleanup(struct pf_state *); int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *, @@ -1281,6 +1374,7 @@ void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t, u_int64_t, int, int, int); int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, struct pf_addr **, struct pf_addr **, sa_family_t); +void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); struct pfr_ktable * pfr_attach_table(struct pf_ruleset *, char *); void pfr_detach_table(struct pfr_ktable *); @@ -1310,9 +1404,26 @@ int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int); int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *, int *, u_int32_t, int); -int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t); -void pfi_dynaddr_copyout(struct pf_addr_wrap *); -void pfi_dynaddr_remove(struct pf_addr_wrap *); +void pfi_initialize(void); +void pfi_attach_clone(struct if_clone *); +void pfi_attach_ifnet(struct ifnet *); +void pfi_detach_ifnet(struct ifnet *); +struct pfi_kif *pfi_lookup_create(const char *); +int pfi_maybe_destroy(struct pfi_kif *); +struct pfi_kif *pfi_attach_rule(const char *); +void pfi_detach_rule(struct pfi_kif *); +void pfi_attach_state(struct pfi_kif *); +void pfi_detach_state(struct pfi_kif *); +int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t); +void pfi_dynaddr_copyout(struct pf_addr_wrap *); +void pfi_dynaddr_remove(struct pf_addr_wrap *); +void pfi_fill_oldstatus(struct pf_status *); +int pfi_clr_istats(const char *, int *, int); +int pfi_get_ifaces(const char *, struct pfi_if *, int *, int); +int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *, + sa_family_t); + +extern struct pfi_statehead pfi_statehead; u_int16_t pf_tagname2tag(char *); void pf_tag2tagname(u_int16_t, char *); |