From ae2d82548e03e3028f9752c263ff4a49c932b794 Mon Sep 17 00:00:00 2001 From: Ryan Thomas McBride Date: Tue, 12 Jan 2010 03:20:52 +0000 Subject: First pass at removing the 'pf_pool' mechanism for translation and routing actions. Allow interfaces to be specified in special table entries for the routing actions. Lists of addresses can now only be done using tables, which pfctl will generate automatically from the existing syntax. Functionally, this deprecates the use of multiple tables or dynamic interfaces in a single nat or rdr rule. ok henning dlg claudio --- sys/net/pf.c | 45 +++-- sys/net/pf_if.c | 14 +- sys/net/pf_ioctl.c | 512 ++++++++--------------------------------------------- sys/net/pf_lb.c | 85 +++------ sys/net/pf_table.c | 128 +++++++++----- sys/net/pfvar.h | 109 ++++++------ 6 files changed, 277 insertions(+), 616 deletions(-) (limited to 'sys/net') diff --git a/sys/net/pf.c b/sys/net/pf.c index 758d92d8385..77176009854 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.682 2010/01/11 04:07:07 henning Exp $ */ +/* $OpenBSD: pf.c,v 1.683 2010/01/12 03:20:51 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -105,7 +105,6 @@ struct pf_state_tree pf_statetbl; struct pf_altqqueue pf_altqs[2]; -struct pf_palist pf_pabuf[3]; struct pf_altqqueue *pf_altqs_active; struct pf_altqqueue *pf_altqs_inactive; struct pf_status pf_status; @@ -113,7 +112,6 @@ struct pf_status pf_status; u_int32_t ticket_altqs_active; u_int32_t ticket_altqs_inactive; int altqs_inactive_open; -u_int32_t ticket_pabuf; MD5_CTX pf_tcp_secret_ctx; u_char pf_tcp_secret[16]; @@ -127,7 +125,7 @@ struct pf_anchor_stackframe { struct pf_anchor *child; } pf_anchor_stack[64]; -struct pool pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl; +struct pool pf_src_tree_pl, pf_rule_pl; struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl; struct pool pf_altq_pl, pf_rule_item_pl, pf_sn_item_pl; @@ -1521,6 +1519,7 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2) return (0); case PF_ADDR_DYNIFTL: return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt); + case PF_ADDR_NONE: case PF_ADDR_NOROUTE: case PF_ADDR_URPFFAILED: return (0); @@ -2656,14 +2655,14 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr) case AF_INET: pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &sn, &r->route, PF_SN_ROUTE); - s->rt_kif = r->route.cur->kif; + s->rt_kif = r->route.kif; break; #endif /* INET */ #ifdef INET6 case AF_INET6: pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &sn, &r->route, PF_SN_ROUTE); - s->rt_kif = r->route.cur->kif; + s->rt_kif = r->route.kif; break; #endif /* INET6 */ } @@ -5095,18 +5094,18 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, if (ro->ro_rt->rt_flags & RTF_GATEWAY) dst = satosin(ro->ro_rt->rt_gateway); } else { - if (TAILQ_EMPTY(&r->route.list)) { - DPFPRINTF(PF_DEBUG_URGENT, - ("pf_route: TAILQ_EMPTY(&r->route.list)\n")); - goto bad; - } if (s == NULL) { - pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src, - &naddr, NULL, &sn, &r->route, PF_SN_ROUTE); + if (pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src, + &naddr, NULL, &sn, &r->route, PF_SN_ROUTE)) { + DPFPRINTF(PF_DEBUG_URGENT, + ("pf_route: pf_map_addr() failed.\n")); + goto bad; + } + if (!PF_AZERO(&naddr, AF_INET)) dst->sin_addr.s_addr = naddr.v4.s_addr; - ifp = r->route.cur->kif ? - r->route.cur->kif->pfik_ifp : NULL; + ifp = r->route.kif ? + r->route.kif->pfik_ifp : NULL; } else { if (!PF_AZERO(&s->rt_addr, AF_INET)) dst->sin_addr.s_addr = @@ -5117,6 +5116,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, if (ifp == NULL) goto bad; + if (oifp != ifp) { if (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS) goto bad; @@ -5277,18 +5277,17 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, return; } - if (TAILQ_EMPTY(&r->route.list)) { - DPFPRINTF(PF_DEBUG_URGENT, - ("pf_route6: TAILQ_EMPTY(&r->route.list)\n")); - goto bad; - } if (s == NULL) { - pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src, - &naddr, NULL, &sn, &r->route, PF_SN_ROUTE); + if (pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src, + &naddr, NULL, &sn, &r->route, PF_SN_ROUTE)) { + DPFPRINTF(PF_DEBUG_URGENT, + ("pf_route6: pf_map_addr() failed.\n")); + goto bad; + } if (!PF_AZERO(&naddr, AF_INET6)) PF_ACPY((struct pf_addr *)&dst->sin6_addr, &naddr, AF_INET6); - ifp = r->route.cur->kif ? r->route.cur->kif->pfik_ifp : NULL; + ifp = r->route.kif ? r->route.kif->pfik_ifp : NULL; } else { if (!PF_AZERO(&s->rt_addr, AF_INET6)) PF_ACPY((struct pf_addr *)&dst->sin6_addr, diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c index 47643e12c50..d598e224cc5 100644 --- a/sys/net/pf_if.c +++ b/sys/net/pf_if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_if.c,v 1.58 2009/08/25 23:21:04 krw Exp $ */ +/* $OpenBSD: pf_if.c,v 1.59 2010/01/12 03:20:51 mcbride Exp $ */ /* * Copyright 2005 Henning Brauer @@ -132,6 +132,9 @@ pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what) case PFI_KIF_REF_STATE: kif->pfik_states++; break; + case PFI_KIF_REF_ROUTE: + kif->pfik_routes++; + break; default: panic("pfi_kif_ref with unknown type"); } @@ -160,6 +163,13 @@ pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what) } kif->pfik_states--; break; + case PFI_KIF_REF_ROUTE: + if (kif->pfik_routes <= 0) { + printf("pfi_kif_unref: state refcount <= 0\n"); + return; + } + kif->pfik_routes--; + break; default: panic("pfi_kif_unref with unknown type"); } @@ -167,7 +177,7 @@ pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what) if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all) return; - if (kif->pfik_rules || kif->pfik_states) + if (kif->pfik_rules || kif->pfik_states || kif->pfik_routes) return; RB_REMOVE(pfi_ifhead, &pfi_ifs, kif); diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index e0c11d9f95e..4e898f9610b 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.230 2009/12/24 04:24:19 dlg Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.231 2010/01/12 03:20:51 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -91,11 +91,6 @@ void pfattach(int); void pf_thread_create(void *); int pfopen(dev_t, int, int, struct proc *); int pfclose(dev_t, int, int, struct proc *); -struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t, - u_int8_t, u_int8_t, u_int8_t, int); - -void pf_mv_pool(struct pf_palist *, struct pf_palist *); -void pf_empty_pool(struct pf_palist *); int pfioctl(dev_t, u_long, caddr_t, int, struct proc *); #ifdef ALTQ int pf_begin_altq(u_int32_t *); @@ -112,6 +107,7 @@ void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *); int pf_commit_rules(u_int32_t, char *); int pf_addr_setup(struct pf_ruleset *, struct pf_addr_wrap *, sa_family_t); +int pf_kif_setup(char *, struct pfi_kif **); void pf_addr_copyout(struct pf_addr_wrap *); void pf_trans_set_commit(void); @@ -171,8 +167,6 @@ pfattach(int num) "pfruleitempl", NULL); pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl", &pool_allocator_nointr); - pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0, - "pfpooladdrpl", &pool_allocator_nointr); pfr_initialize(); pfi_initialize(); pf_osfp_initialize(); @@ -189,9 +183,6 @@ pfattach(int num) pf_init_ruleset(&pf_main_ruleset); TAILQ_INIT(&pf_altqs[0]); TAILQ_INIT(&pf_altqs[1]); - TAILQ_INIT(&pf_pabuf[0]); - TAILQ_INIT(&pf_pabuf[1]); - TAILQ_INIT(&pf_pabuf[2]); pf_altqs_active = &pf_altqs[0]; pf_altqs_inactive = &pf_altqs[1]; TAILQ_INIT(&state_list); @@ -224,6 +215,12 @@ pfattach(int num) timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; + pf_default_rule.src.addr.type = PF_ADDR_ADDRMASK; + pf_default_rule.dst.addr.type = PF_ADDR_ADDRMASK; + pf_default_rule.rdr.addr.type = PF_ADDR_NONE; + pf_default_rule.nat.addr.type = PF_ADDR_NONE; + pf_default_rule.route.addr.type = PF_ADDR_NONE; + pf_normalize_init(); bzero(&pf_status, sizeof(pf_status)); pf_status.debug = PF_DEBUG_URGENT; @@ -259,73 +256,6 @@ pfclose(dev_t dev, int flags, int fmt, struct proc *p) return (0); } -struct pf_pool * -pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action, - u_int32_t rule_number, u_int8_t r_last, u_int8_t active, - u_int8_t check_ticket, int which) -{ - struct pf_ruleset *ruleset; - struct pf_rule *rule; - - ruleset = pf_find_ruleset(anchor); - if (ruleset == NULL) - return (NULL); - if (active) { - if (check_ticket && ticket != ruleset->rules.active.ticket) - return (NULL); - if (r_last) - rule = TAILQ_LAST(ruleset->rules.active.ptr, - pf_rulequeue); - else - rule = TAILQ_FIRST(ruleset->rules.active.ptr); - } else { - if (check_ticket && ticket != ruleset->rules.inactive.ticket) - return (NULL); - if (r_last) - rule = TAILQ_LAST(ruleset->rules.inactive.ptr, - pf_rulequeue); - else - rule = TAILQ_FIRST(ruleset->rules.inactive.ptr); - } - if (!r_last) { - while ((rule != NULL) && (rule->nr != rule_number)) - rule = TAILQ_NEXT(rule, entries); - } - if (rule == NULL) - return (NULL); - if (which == PF_NAT) - return (&rule->nat); - else if (which == PF_RT) - return (&rule->route); - else - return (&rule->rdr); -} - -void -pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb) -{ - struct pf_pooladdr *mv_pool_pa; - - while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) { - TAILQ_REMOVE(poola, mv_pool_pa, entries); - TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries); - } -} - -void -pf_empty_pool(struct pf_palist *poola) -{ - struct pf_pooladdr *empty_pool_pa; - - while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) { - pfi_dynaddr_remove(&empty_pool_pa->addr); - pf_tbladdr_remove(&empty_pool_pa->addr); - pfi_kif_unref(empty_pool_pa->kif, PFI_KIF_REF_RULE); - TAILQ_REMOVE(poola, empty_pool_pa, entries); - pool_put(&pf_pooladdr_pl, empty_pool_pa); - } -} - void pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) { @@ -338,6 +268,9 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) */ pf_tbladdr_remove(&rule->src.addr); pf_tbladdr_remove(&rule->dst.addr); + pf_tbladdr_remove(&rule->rdr.addr); + pf_tbladdr_remove(&rule->nat.addr); + pf_tbladdr_remove(&rule->route.addr); if (rule->overload_tbl) pfr_detach_table(rule->overload_tbl); } @@ -360,18 +293,24 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) pf_rtlabel_remove(&rule->dst.addr); pfi_dynaddr_remove(&rule->src.addr); pfi_dynaddr_remove(&rule->dst.addr); + pfi_dynaddr_remove(&rule->rdr.addr); + pfi_dynaddr_remove(&rule->nat.addr); + pfi_dynaddr_remove(&rule->route.addr); if (rulequeue == NULL) { pf_tbladdr_remove(&rule->src.addr); pf_tbladdr_remove(&rule->dst.addr); + pf_tbladdr_remove(&rule->rdr.addr); + pf_tbladdr_remove(&rule->nat.addr); + pf_tbladdr_remove(&rule->route.addr); if (rule->overload_tbl) pfr_detach_table(rule->overload_tbl); } pfi_kif_unref(rule->rcv_kif, PFI_KIF_REF_RULE); pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE); + pfi_kif_unref(rule->rdr.kif, PFI_KIF_REF_RULE); + pfi_kif_unref(rule->nat.kif, PFI_KIF_REF_RULE); + pfi_kif_unref(rule->route.kif, PFI_KIF_REF_RULE); pf_anchor_remove(rule); - pf_empty_pool(&rule->rdr.list); - pf_empty_pool(&rule->nat.list); - pf_empty_pool(&rule->route.list); pool_put(&pf_rule_pl, rule); } @@ -889,12 +828,28 @@ pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr, sa_family_t af) { if (pfi_dynaddr_setup(addr, af) || - pf_tbladdr_setup(ruleset, addr)) + pf_tbladdr_setup(ruleset, addr) || + pf_rtlabel_add(addr)) return (EINVAL); return (0); } +int +pf_kif_setup(char *ifname, struct pfi_kif **kif) +{ + if (ifname[0]) { + *kif = pfi_kif_get(ifname); + if (*kif == NULL) + return (EINVAL); + + pfi_kif_ref(*kif, PFI_KIF_REF_RULE); + } else + *kif = NULL; + + return (0); +} + void pf_addr_copyout(struct pf_addr_wrap *addr) { @@ -906,8 +861,6 @@ pf_addr_copyout(struct pf_addr_wrap *addr) int pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) { - struct pf_pooladdr *pa = NULL; - struct pf_pool *pool = NULL; int s; int error = 0; @@ -916,8 +869,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) switch (cmd) { case DIOCGETRULES: case DIOCGETRULE: - case DIOCGETADDRS: - case DIOCGETADDR: case DIOCGETSTATE: case DIOCSETSTATUSIF: case DIOCGETSTATUS: @@ -940,7 +891,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) case DIOCRADDADDRS: case DIOCRDELADDRS: case DIOCRSETADDRS: - case DIOCRGETADDRS: case DIOCRGETASTATS: case DIOCRCLRASTATS: case DIOCRTSTADDRS: @@ -966,8 +916,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (!(flags & FWRITE)) switch (cmd) { case DIOCGETRULES: - case DIOCGETADDRS: - case DIOCGETADDR: case DIOCGETSTATE: case DIOCGETSTATUS: case DIOCGETSTATES: @@ -1048,7 +996,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pfioc_rule *pr = (struct pfioc_rule *)addr; struct pf_ruleset *ruleset; struct pf_rule *rule, *tail; - struct pf_pooladdr *pa; pr->anchor[sizeof(pr->anchor) - 1] = 0; ruleset = pf_find_ruleset(pr->anchor); @@ -1064,10 +1011,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EBUSY; break; } - if (pr->pool_ticket != ticket_pabuf) { - error = EBUSY; - break; - } rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL); if (rule == NULL) { error = ENOMEM; @@ -1079,9 +1022,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) rule->anchor = NULL; rule->kif = NULL; rule->rcv_kif = NULL; - TAILQ_INIT(&rule->rdr.list); - TAILQ_INIT(&rule->nat.list); - TAILQ_INIT(&rule->route.list); /* initialize refcounting */ rule->states_cur = 0; rule->src_nodes = 0; @@ -1109,22 +1049,21 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) rule->nr = tail->nr + 1; else rule->nr = 0; - if (rule->ifname[0]) { - rule->kif = pfi_kif_get(rule->ifname); - if (rule->kif == NULL) { - pool_put(&pf_rule_pl, rule); - error = EINVAL; - break; - } - pfi_kif_ref(rule->kif, PFI_KIF_REF_RULE); - } - if (rule->rcv_ifname[0]) { - rule->rcv_kif = pfi_kif_get(rule->rcv_ifname); - if (rule->rcv_kif == NULL) { - error = EINVAL; - } else - pfi_kif_ref(rule->rcv_kif, PFI_KIF_REF_RULE); - } + + if (rule->src.addr.type == PF_ADDR_NONE || + rule->dst.addr.type == PF_ADDR_NONE) + error = EINVAL; + + if (pf_kif_setup(rule->ifname, &rule->kif)) + error = EINVAL; + if (pf_kif_setup(rule->rcv_ifname, &rule->rcv_kif)) + error = EINVAL; + if (pf_kif_setup(rule->rdr.ifname, &rule->rdr.kif)) + error = EINVAL; + if (pf_kif_setup(rule->nat.ifname, &rule->nat.kif)) + error = EINVAL; + if (pf_kif_setup(rule->route.ifname, &rule->route.kif)) + error = EINVAL; if (rule->rtableid > 0 && !rtable_exists(rule->rtableid)) error = EBUSY; @@ -1164,17 +1103,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EINVAL; if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af)) error = EINVAL; + if (pf_addr_setup(ruleset, &rule->rdr.addr, rule->af)) + error = EINVAL; + if (pf_addr_setup(ruleset, &rule->nat.addr, rule->af)) + error = EINVAL; + if (pf_addr_setup(ruleset, &rule->route.addr, rule->af)) + error = EINVAL; if (pf_anchor_setup(rule, ruleset, pr->anchor_call)) error = EINVAL; - TAILQ_FOREACH(pa, &pf_pabuf[0], entries) - if (pf_tbladdr_setup(ruleset, &pa->addr)) - error = EINVAL; - TAILQ_FOREACH(pa, &pf_pabuf[1], entries) - if (pf_tbladdr_setup(ruleset, &pa->addr)) - error = EINVAL; - TAILQ_FOREACH(pa, &pf_pabuf[2], entries) - if (pf_tbladdr_setup(ruleset, &pa->addr)) - error = EINVAL; if (rule->overload_tblname[0]) { if ((rule->overload_tbl = pfr_attach_table(ruleset, @@ -1185,21 +1121,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) PFR_TFLAG_ACTIVE; } - pf_mv_pool(&pf_pabuf[0], &rule->nat.list); - pf_mv_pool(&pf_pabuf[1], &rule->rdr.list); - pf_mv_pool(&pf_pabuf[2], &rule->route.list); - - if (rule->rt > PF_FASTROUTE && - (TAILQ_FIRST(&rule->route.list) == NULL)) - error = EINVAL; - if (error) { pf_rm_rule(NULL, rule); break; } - rule->nat.cur = TAILQ_FIRST(&rule->nat.list); - rule->rdr.cur = TAILQ_FIRST(&rule->rdr.list); - rule->route.cur = TAILQ_FIRST(&rule->route.list); rule->evaluations = rule->packets[0] = rule->packets[1] = rule->bytes[0] = rule->bytes[1] = 0; TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr, @@ -1258,6 +1183,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } pf_addr_copyout(&pr->rule.src.addr); pf_addr_copyout(&pr->rule.dst.addr); + pf_addr_copyout(&pr->rule.rdr.addr); + pf_addr_copyout(&pr->rule.nat.addr); + pf_addr_copyout(&pr->rule.route.addr); for (i = 0; i < PF_SKIP_COUNT; ++i) if (rule->skip[i].ptr == NULL) pr->rule.skip[i].nr = -1; @@ -1281,8 +1209,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) u_int32_t nr = 0; if (!(pcr->action == PF_CHANGE_REMOVE || - pcr->action == PF_CHANGE_GET_TICKET) && - pcr->pool_ticket != ticket_pabuf) { + pcr->action == PF_CHANGE_GET_TICKET)) { error = EBUSY; break; } @@ -1322,9 +1249,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); newrule->cuid = p->p_cred->p_ruid; newrule->cpid = p->p_pid; - TAILQ_INIT(&newrule->rdr.list); - TAILQ_INIT(&newrule->nat.list); - TAILQ_INIT(&newrule->route.list); /* initialize refcounting */ newrule->states_cur = 0; newrule->entries.tqe_prev = NULL; @@ -1346,28 +1270,16 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) goto fail; } - if (newrule->ifname[0]) { - newrule->kif = pfi_kif_get(newrule->ifname); - if (newrule->kif == NULL) { - pool_put(&pf_rule_pl, newrule); - error = EINVAL; - break; - } - pfi_kif_ref(newrule->kif, PFI_KIF_REF_RULE); - } else - newrule->kif = NULL; - - if (newrule->rcv_ifname[0]) { - newrule->rcv_kif = - pfi_kif_get(newrule->rcv_ifname); - if (newrule->rcv_kif == NULL) { - error = EINVAL; - } else { - pfi_kif_ref(newrule->rcv_kif, - PFI_KIF_REF_RULE); - } - } else - newrule->kif = NULL; + if (pf_kif_setup(newrule->ifname, &newrule->kif)) + error = EINVAL; + if (pf_kif_setup(newrule->rcv_ifname, &newrule->rcv_kif)) + error = EINVAL; + if (pf_kif_setup(newrule->rdr.ifname, &newrule->rdr.kif)) + error = EINVAL; + if (pf_kif_setup(newrule->nat.ifname, &newrule->nat.kif)) + error = EINVAL; + if (pf_kif_setup(newrule->route.ifname, &newrule->route.kif)) + error = EINVAL; if (newrule->rtableid > 0 && !rtable_exists(newrule->rtableid)) @@ -1410,17 +1322,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EINVAL; if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af)) error = EINVAL; + if (pf_addr_setup(ruleset, &newrule->rdr.addr, newrule->af)) + error = EINVAL; + if (pf_addr_setup(ruleset, &newrule->nat.addr, newrule->af)) + error = EINVAL; + if (pf_addr_setup(ruleset, &newrule->route.addr, newrule->af)) + error = EINVAL; if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call)) error = EINVAL; - TAILQ_FOREACH(pa, &pf_pabuf[0], entries) - if (pf_tbladdr_setup(ruleset, &pa->addr)) - error = EINVAL; - TAILQ_FOREACH(pa, &pf_pabuf[1], entries) - if (pf_tbladdr_setup(ruleset, &pa->addr)) - error = EINVAL; - TAILQ_FOREACH(pa, &pf_pabuf[2], entries) - if (pf_tbladdr_setup(ruleset, &pa->addr)) - error = EINVAL; if (newrule->overload_tblname[0]) { if ((newrule->overload_tbl = pfr_attach_table( @@ -1432,28 +1341,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) PFR_TFLAG_ACTIVE; } - pf_mv_pool(&pf_pabuf[0], &newrule->nat.list); - pf_mv_pool(&pf_pabuf[1], &newrule->rdr.list); - pf_mv_pool(&pf_pabuf[2], &newrule->route.list); - if (newrule->rt > PF_FASTROUTE && - !newrule->anchor && - (TAILQ_FIRST(&newrule->route.list) == NULL)) - error = EINVAL; - if (error) { pf_rm_rule(NULL, newrule); break; } - newrule->rdr.cur = TAILQ_FIRST(&newrule->rdr.list); - newrule->nat.cur = TAILQ_FIRST(&newrule->nat.list); - newrule->route.cur = TAILQ_FIRST(&newrule->route.list); newrule->evaluations = 0; newrule->packets[0] = newrule->packets[1] = 0; newrule->bytes[0] = newrule->bytes[1] = 0; } - pf_empty_pool(&pf_pabuf[0]); - pf_empty_pool(&pf_pabuf[1]); - pf_empty_pool(&pf_pabuf[2]); if (pcr->action == PF_CHANGE_ADD_HEAD) oldrule = TAILQ_FIRST(ruleset->rules.active.ptr); @@ -1964,257 +1859,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } #endif /* ALTQ */ - case DIOCBEGINADDRS: { - struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; - - pf_empty_pool(&pf_pabuf[0]); - pf_empty_pool(&pf_pabuf[1]); - pf_empty_pool(&pf_pabuf[2]); - pp->ticket = ++ticket_pabuf; - break; - } - - case DIOCADDADDR: { - struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; - - if (pp->which != PF_NAT && pp->which != PF_RDR && pp->which != PF_RT) { - error = EINVAL; - break; - } - - if (pp->ticket != ticket_pabuf) { - error = EBUSY; - break; - } - - switch (pp->af) { - case 0: - break; -#ifdef INET - case AF_INET: - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - break; -#endif /* INET6 */ - default: - error = EAFNOSUPPORT; - goto fail; - } - - if (pp->addr.addr.type != PF_ADDR_ADDRMASK && - pp->addr.addr.type != PF_ADDR_DYNIFTL && - pp->addr.addr.type != PF_ADDR_TABLE) { - error = EINVAL; - break; - } - pa = pool_get(&pf_pooladdr_pl, PR_WAITOK|PR_LIMITFAIL); - if (pa == NULL) { - error = ENOMEM; - break; - } - bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr)); - if (pa->ifname[0]) { - pa->kif = pfi_kif_get(pa->ifname); - if (pa->kif == NULL) { - pool_put(&pf_pooladdr_pl, pa); - error = EINVAL; - break; - } - pfi_kif_ref(pa->kif, PFI_KIF_REF_RULE); - } - if (pfi_dynaddr_setup(&pa->addr, pp->af)) { - pfi_dynaddr_remove(&pa->addr); - pfi_kif_unref(pa->kif, PFI_KIF_REF_RULE); - pool_put(&pf_pooladdr_pl, pa); - error = EINVAL; - break; - } - - switch (pp->which) { - case PF_NAT: - TAILQ_INSERT_TAIL(&pf_pabuf[0], pa, entries); - break; - case PF_RDR: - TAILQ_INSERT_TAIL(&pf_pabuf[1], pa, entries); - break; - case PF_RT: - TAILQ_INSERT_TAIL(&pf_pabuf[2], pa, entries); - break; - } - break; - } - - case DIOCGETADDRS: { - struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; - - if (pp->which != PF_NAT && pp->which != PF_RDR && pp->which != PF_RT) { - error = EINVAL; - break; - } - - pp->nr = 0; - pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action, - pp->r_num, 0, 1, 0, pp->which); - if (pool == NULL) { - error = EBUSY; - break; - } - TAILQ_FOREACH(pa, &pool->list, entries) - pp->nr++; - break; - } - - case DIOCGETADDR: { - struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; - u_int32_t nr = 0; - - if (pp->which != PF_NAT && pp->which != PF_RDR && pp->which != PF_RT) { - error = EINVAL; - break; - } - - pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action, - pp->r_num, 0, 1, 1, pp->which); - if (pool == NULL) { - error = EBUSY; - break; - } - pa = TAILQ_FIRST(&pool->list); - while ((pa != NULL) && (nr < pp->nr)) { - pa = TAILQ_NEXT(pa, entries); - nr++; - } - if (pa == NULL) { - error = EBUSY; - break; - } - bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr)); - pf_addr_copyout(&pp->addr.addr); - break; - } - - case DIOCCHANGEADDR: { - struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; - struct pf_pooladdr *oldpa = NULL, *newpa = NULL; - struct pf_ruleset *ruleset; - - if (pca->which != PF_NAT && pca->which != PF_RDR && pca->which != PF_RT) { - error = EINVAL; - break; - } - - if (pca->action < PF_CHANGE_ADD_HEAD || - pca->action > PF_CHANGE_REMOVE) { - error = EINVAL; - break; - } - if (pca->addr.addr.type != PF_ADDR_ADDRMASK && - pca->addr.addr.type != PF_ADDR_DYNIFTL && - pca->addr.addr.type != PF_ADDR_TABLE) { - error = EINVAL; - break; - } - - ruleset = pf_find_ruleset(pca->anchor); - if (ruleset == NULL) { - error = EBUSY; - break; - } - pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action, - pca->r_num, pca->r_last, 1, 1, pca->which); - if (pool == NULL) { - error = EBUSY; - break; - } - if (pca->action != PF_CHANGE_REMOVE) { - newpa = pool_get(&pf_pooladdr_pl, - PR_WAITOK|PR_LIMITFAIL); - if (newpa == NULL) { - error = ENOMEM; - break; - } - bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr)); - - switch (pca->af) { - case 0: - break; -#ifdef INET - case AF_INET: - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - break; -#endif /* INET6 */ - default: - pool_put(&pf_pooladdr_pl, newpa); - error = EAFNOSUPPORT; - goto fail; - } - - if (newpa->ifname[0]) { - newpa->kif = pfi_kif_get(newpa->ifname); - if (newpa->kif == NULL) { - pool_put(&pf_pooladdr_pl, newpa); - error = EINVAL; - break; - } - pfi_kif_ref(newpa->kif, PFI_KIF_REF_RULE); - } else - newpa->kif = NULL; - if (pfi_dynaddr_setup(&newpa->addr, pca->af) || - pf_tbladdr_setup(ruleset, &newpa->addr)) { - pfi_dynaddr_remove(&newpa->addr); - pfi_kif_unref(newpa->kif, PFI_KIF_REF_RULE); - pool_put(&pf_pooladdr_pl, newpa); - error = EINVAL; - break; - } - } - - if (pca->action == PF_CHANGE_ADD_HEAD) - oldpa = TAILQ_FIRST(&pool->list); - else if (pca->action == PF_CHANGE_ADD_TAIL) - oldpa = TAILQ_LAST(&pool->list, pf_palist); - else { - int i = 0; - - oldpa = TAILQ_FIRST(&pool->list); - while ((oldpa != NULL) && (i < pca->nr)) { - oldpa = TAILQ_NEXT(oldpa, entries); - i++; - } - if (oldpa == NULL) { - error = EINVAL; - break; - } - } - - if (pca->action == PF_CHANGE_REMOVE) { - TAILQ_REMOVE(&pool->list, oldpa, entries); - pfi_dynaddr_remove(&oldpa->addr); - pf_tbladdr_remove(&oldpa->addr); - pfi_kif_unref(oldpa->kif, PFI_KIF_REF_RULE); - pool_put(&pf_pooladdr_pl, oldpa); - } else { - if (oldpa == NULL) - TAILQ_INSERT_TAIL(&pool->list, newpa, entries); - else if (pca->action == PF_CHANGE_ADD_HEAD || - pca->action == PF_CHANGE_ADD_BEFORE) - TAILQ_INSERT_BEFORE(oldpa, newpa, entries); - else - TAILQ_INSERT_AFTER(&pool->list, oldpa, - newpa, entries); - } - - pool->cur = TAILQ_FIRST(&pool->list); - PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, - pca->af); - break; - } - case DIOCGETRULESETS: { struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; struct pf_ruleset *ruleset; diff --git a/sys/net/pf_lb.c b/sys/net/pf_lb.c index ee502e22035..52c6a0f7e7f 100644 --- a/sys/net/pf_lb.c +++ b/sys/net/pf_lb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_lb.c,v 1.9 2009/12/14 12:31:45 henning Exp $ */ +/* $OpenBSD: pf_lb.c,v 1.10 2010/01/12 03:20:51 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -267,9 +267,8 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, struct pf_pool *rpool, enum pf_sn_types type) { unsigned char hash[16]; - struct pf_addr *raddr = &rpool->cur->addr.v.a.addr; - struct pf_addr *rmask = &rpool->cur->addr.v.a.mask; - struct pf_pooladdr *acur = rpool->cur; + struct pf_addr *raddr = &rpool->addr.v.a.addr; + struct pf_addr *rmask = &rpool->addr.v.a.mask; struct pf_src_node k; if (sns[type] == NULL && rpool->opts & PF_POOL_STICKYADDR && @@ -283,7 +282,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, if (sns[type] != NULL) { if (!PF_AZERO(&(sns[type])->raddr, af)) PF_ACPY(naddr, &(sns[type])->raddr, af); - if (pf_status.debug >= PF_DEBUG_MISC) { + if (pf_status.debug >= PF_DEBUG_NOISY) { printf("pf_map_addr: src tracking (%u) maps ", type); pf_print_host(&k.addr, 0, af); @@ -295,37 +294,37 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, } } - if (rpool->cur->addr.type == PF_ADDR_NOROUTE) + if (rpool->addr.type == PF_ADDR_NOROUTE) return (1); - if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { + if (rpool->addr.type == PF_ADDR_DYNIFTL) { switch (af) { #ifdef INET case AF_INET: - if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 && + if (rpool->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; + raddr = &rpool->addr.p.dyn->pfid_addr4; + rmask = &rpool->addr.p.dyn->pfid_mask4; break; #endif /* INET */ #ifdef INET6 case AF_INET6: - if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 && + if (rpool->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; + raddr = &rpool->addr.p.dyn->pfid_addr6; + rmask = &rpool->addr.p.dyn->pfid_mask6; break; #endif /* INET6 */ } - } else if (rpool->cur->addr.type == PF_ADDR_TABLE) { + } else if (rpool->addr.type == PF_ADDR_TABLE) { if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) return (1); /* unsupported */ } else { - raddr = &rpool->cur->addr.v.a.addr; - rmask = &rpool->cur->addr.v.a.mask; + raddr = &rpool->addr.v.a.addr; + rmask = &rpool->addr.v.a.mask; } switch (rpool->opts & PF_POOL_TYPEMASK) { @@ -379,49 +378,19 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af); break; case PF_POOL_ROUNDROBIN: - if (rpool->cur->addr.type == PF_ADDR_TABLE) { - if (!pfr_pool_get(rpool->cur->addr.p.tbl, + if (rpool->addr.type == PF_ADDR_TABLE) { + if (pfr_pool_get(rpool->addr.p.tbl, &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; - - try_next: - if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL) - rpool->cur = TAILQ_FIRST(&rpool->list); - if (rpool->cur->addr.type == PF_ADDR_TABLE) { - rpool->tblidx = -1; - if (pfr_pool_get(rpool->cur->addr.p.tbl, - &rpool->tblidx, &rpool->counter, - &raddr, &rmask, af)) { - /* table contains no address of type 'af' */ - if (rpool->cur != acur) - goto try_next; + &raddr, &rmask, &rpool->kif, af)) 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, + } else if (rpool->addr.type == PF_ADDR_DYNIFTL) { + if (pfr_pool_get(rpool->addr.p.dyn->pfid_kt, &rpool->tblidx, &rpool->counter, - &raddr, &rmask, af)) { - /* table contains no address of type 'af' */ - if (rpool->cur != acur) - goto try_next; + &raddr, &rmask, &rpool->kif, af)) return (1); - } - } else { - raddr = &rpool->cur->addr.v.a.addr; - rmask = &rpool->cur->addr.v.a.mask; - PF_ACPY(&rpool->counter, raddr, af); - } + } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) + return (1); - get_addr: PF_ACPY(naddr, &rpool->counter, af); if (init_addr != NULL && PF_AZERO(init_addr, af)) PF_ACPY(init_addr, naddr, af); @@ -439,7 +408,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, return (1); } - if (pf_status.debug >= PF_DEBUG_NOISY && + if (pf_status.debug >= PF_DEBUG_MISC && (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { printf("pf_map_addr: selected address "); pf_print_host(naddr, 0, af); @@ -457,7 +426,7 @@ pf_get_transaddr(struct pf_rule *r, struct pf_pdesc *pd, struct pf_addr *saddr, struct pf_addr naddr; u_int16_t nport = 0; - if (!TAILQ_EMPTY(&r->nat.list)) { + if (r->nat.addr.type != PF_ADDR_NONE) { /* XXX is this right? what if rtable is changed at the same * XXX time? where do I need to figure out the sport? */ if (pf_get_sport(pd->af, pd->proto, r, saddr, @@ -474,12 +443,12 @@ pf_get_transaddr(struct pf_rule *r, struct pf_pdesc *pd, struct pf_addr *saddr, if (nport) *sport = nport; } - if (!TAILQ_EMPTY(&r->rdr.list)) { + if (r->rdr.addr.type != PF_ADDR_NONE) { if (pf_map_addr(pd->af, r, saddr, &naddr, NULL, sns, &r->rdr, PF_SN_RDR)) return (-1); if ((r->rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK) - PF_POOLMASK(&naddr, &naddr, &r->rdr.cur->addr.v.a.mask, + PF_POOLMASK(&naddr, &naddr, &r->rdr.addr.v.a.mask, daddr, pd->af); if (r->rdr.proxy_port[1]) { diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c index 2369a2993c0..42fa919c4b4 100644 --- a/sys/net/pf_table.c +++ b/sys/net/pf_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_table.c,v 1.80 2008/11/24 13:22:09 mikeb Exp $ */ +/* $OpenBSD: pf_table.c,v 1.81 2010/01/12 03:20:51 mcbride Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -125,7 +125,7 @@ struct pfr_walktree { #define senderr(e) do { rv = (e); goto _bad; } while (0) struct pool pfr_ktable_pl; -struct pool pfr_kentry_pl; +struct pool pfr_kentry_pl[PFRKE_MAX]; struct pool pfr_kcounters_pl; struct sockaddr_in pfr_sin; struct sockaddr_in6 pfr_sin6; @@ -140,7 +140,7 @@ void pfr_enqueue_addrs(struct pfr_ktable *, void pfr_mark_addrs(struct pfr_ktable *); struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *, struct pfr_addr *, int); -struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, int); +struct pfr_kentry *pfr_create_kentry(struct pfr_addr *); void pfr_destroy_kentries(struct pfr_kentryworkq *); void pfr_destroy_kentry(struct pfr_kentry *); void pfr_insert_kentries(struct pfr_ktable *, @@ -191,10 +191,13 @@ pfr_initialize(void) { pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0, "pfrktable", NULL); - pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0, - "pfrkentry", NULL); - pool_init(&pfr_kcounters_pl, sizeof(struct pfr_kcounters), 0, 0, 0, - "pfrkcounters", NULL); + pool_init(&pfr_kentry_pl[PFRKE_PLAIN], sizeof(struct pfr_kentry), + 0, 0, 0, "pfrke_plain", NULL); + pool_init(&pfr_kentry_pl[PFRKE_ROUTE], sizeof(struct pfr_kentry_route), + 0, 0, 0, "pfrke_route", NULL); + + pool_init(&pfr_kcounters_pl, sizeof(struct pfr_kcounters), + 0, 0, 0, "pfrkcounters", NULL); pfr_sin.sin_len = sizeof(pfr_sin); pfr_sin.sin_family = AF_INET; @@ -273,14 +276,14 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, ad.pfra_fback = PFR_FB_DUPLICATE; else if (p == NULL) ad.pfra_fback = PFR_FB_ADDED; - else if (p->pfrke_not != ad.pfra_not) + else if ((p->pfrke_flags & PFRKE_FLAG_NOT) != + ad.pfra_not) ad.pfra_fback = PFR_FB_CONFLICT; else ad.pfra_fback = PFR_FB_NONE; } if (p == NULL && q == NULL) { - p = pfr_create_kentry(&ad, - !(flags & PFR_FLAG_USERIOCTL)); + p = pfr_create_kentry(&ad); if (p == NULL) senderr(ENOMEM); if (pfr_route_kentry(tmpkt, p)) { @@ -361,7 +364,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, return (EINVAL); p = pfr_lookup_addr(kt, &ad, 1); if (p != NULL) - p->pfrke_mark = 0; + p->pfrke_flags &= ~PFRKE_FLAG_MARK; } } SLIST_INIT(&workq); @@ -374,16 +377,18 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, if (flags & PFR_FLAG_FEEDBACK) { if (p == NULL) ad.pfra_fback = PFR_FB_NONE; - else if (p->pfrke_not != ad.pfra_not) + else if ((p->pfrke_flags & PFRKE_FLAG_NOT) != + ad.pfra_not) ad.pfra_fback = PFR_FB_CONFLICT; - else if (p->pfrke_mark) + else if (p->pfrke_flags & PFRKE_FLAG_MARK) ad.pfra_fback = PFR_FB_DUPLICATE; else ad.pfra_fback = PFR_FB_DELETED; } - if (p != NULL && p->pfrke_not == ad.pfra_not && - !p->pfrke_mark) { - p->pfrke_mark = 1; + if (p != NULL && + (p->pfrke_flags & PFRKE_FLAG_NOT) == ad.pfra_not && + !(p->pfrke_flags & PFRKE_FLAG_MARK)) { + p->pfrke_flags |= PFRKE_FLAG_MARK; SLIST_INSERT_HEAD(&workq, p, pfrke_workq); xdel++; } @@ -445,12 +450,12 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, ad.pfra_fback = PFR_FB_NONE; p = pfr_lookup_addr(kt, &ad, 1); if (p != NULL) { - if (p->pfrke_mark) { + if (p->pfrke_flags & PFRKE_FLAG_MARK) { ad.pfra_fback = PFR_FB_DUPLICATE; goto _skip; } - p->pfrke_mark = 1; - if (p->pfrke_not != ad.pfra_not) { + p->pfrke_flags |= PFRKE_FLAG_MARK; + if ((p->pfrke_flags & PFRKE_FLAG_NOT) != ad.pfra_not) { SLIST_INSERT_HEAD(&changeq, p, pfrke_workq); ad.pfra_fback = PFR_FB_CHANGED; xchange++; @@ -461,8 +466,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, ad.pfra_fback = PFR_FB_DUPLICATE; goto _skip; } - p = pfr_create_kentry(&ad, - !(flags & PFR_FLAG_USERIOCTL)); + p = pfr_create_kentry(&ad); if (p == NULL) senderr(ENOMEM); if (pfr_route_kentry(tmpkt, p)) { @@ -551,8 +555,9 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, if (flags & PFR_FLAG_REPLACE) pfr_copyout_addr(&ad, p); ad.pfra_fback = (p == NULL) ? PFR_FB_NONE : - (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH); - if (p != NULL && !p->pfrke_not) + ((p->pfrke_flags & PFRKE_FLAG_NOT) ? + PFR_FB_NOTMATCH : PFR_FB_MATCH); + if (p != NULL && !(p->pfrke_flags & PFRKE_FLAG_NOT)) xmatch++; if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) return (EFAULT); @@ -805,25 +810,38 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact) } struct pfr_kentry * -pfr_create_kentry(struct pfr_addr *ad, int intr) +pfr_create_kentry(struct pfr_addr *ad) { - struct pfr_kentry *ke; + struct pfr_kentry_all *ke; - if (intr) - ke = pool_get(&pfr_kentry_pl, PR_NOWAIT | PR_ZERO); - else - ke = pool_get(&pfr_kentry_pl, PR_WAITOK|PR_ZERO|PR_LIMITFAIL); + ke = pool_get(&pfr_kentry_pl[ad->pfra_type], PR_NOWAIT | PR_ZERO); if (ke == NULL) return (NULL); + ke->pfrke_type = ad->pfra_type; + + switch (ke->pfrke_type) { + case PFRKE_PLAIN: + break; + case PFRKE_ROUTE: + ke->pfrke_rkif = pfi_kif_get(ad->pfra_ifname); + if (ke->pfrke_rkif) + pfi_kif_ref(ke->pfrke_rkif, PFI_KIF_REF_ROUTE); + break; + default: + panic("unknown pfrke_type %d\n", ke->pfrke_type); + break; + } + if (ad->pfra_af == AF_INET) FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr); else if (ad->pfra_af == AF_INET6) FILLIN_SIN6(ke->pfrke_sa.sin6, ad->pfra_ip6addr); ke->pfrke_af = ad->pfra_af; ke->pfrke_net = ad->pfra_net; - ke->pfrke_not = ad->pfra_not; - return (ke); + if (ad->pfra_not) + ke->pfrke_flags |= PFRKE_FLAG_NOT; + return ((struct pfr_kentry *)ke); } void @@ -842,7 +860,7 @@ pfr_destroy_kentry(struct pfr_kentry *ke) { if (ke->pfrke_counters) pool_put(&pfr_kcounters_pl, ke->pfrke_counters); - pool_put(&pfr_kentry_pl, ke); + pool_put(&pfr_kentry_pl[ke->pfrke_type], ke); } void @@ -874,7 +892,7 @@ pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero) p = pfr_lookup_addr(kt, ad, 1); if (p != NULL) return (0); - p = pfr_create_kentry(ad, 1); + p = pfr_create_kentry(ad); if (p == NULL) return (EINVAL); @@ -922,7 +940,7 @@ pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange) SLIST_FOREACH(p, workq, pfrke_workq) { s = splsoftnet(); if (negchange) - p->pfrke_not = !p->pfrke_not; + p->pfrke_flags ^= p->pfrke_flags & PFRKE_FLAG_NOT; if (p->pfrke_counters) { pool_put(&pfr_kcounters_pl, p->pfrke_counters); p->pfrke_counters = NULL; @@ -1033,11 +1051,17 @@ pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke) return; ad->pfra_af = ke->pfrke_af; ad->pfra_net = ke->pfrke_net; - ad->pfra_not = ke->pfrke_not; + if (ke->pfrke_flags & PFRKE_FLAG_NOT) + ad->pfra_not = 1; if (ad->pfra_af == AF_INET) ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr; else if (ad->pfra_af == AF_INET6) ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr; + if (ke->pfrke_type == PFRKE_ROUTE && + ((struct pfr_kentry_route *)ke)->kif != NULL) + strlcpy(ad->pfra_ifname, + ((struct pfr_kentry_route *)ke)->kif->pfik_name, + IFNAMSIZ); } int @@ -1049,10 +1073,10 @@ pfr_walktree(struct radix_node *rn, void *arg) switch (w->pfrw_op) { case PFRW_MARK: - ke->pfrke_mark = 0; + ke->pfrke_flags &= ~PFRKE_FLAG_MARK; break; case PFRW_SWEEP: - if (ke->pfrke_mark) + if (ke->pfrke_flags & PFRKE_FLAG_MARK) break; /* FALLTHROUGH */ case PFRW_ENQUEUE: @@ -1087,7 +1111,6 @@ pfr_walktree(struct radix_node *rn, void *arg) as.pfras_a.pfra_fback = PFR_FB_NOCOUNT; } splx(s); - as.pfras_tzero = ke->pfrke_tzero; if (COPYOUT(&as, w->pfrw_astats, sizeof(as), flags)) return (EFAULT); @@ -1095,7 +1118,7 @@ pfr_walktree(struct radix_node *rn, void *arg) } break; case PFRW_POOL_GET: - if (ke->pfrke_not) + if (ke->pfrke_flags & PFRKE_FLAG_NOT) break; /* negative entries are ignored */ if (!w->pfrw_cnt--) { w->pfrw_kentry = ke; @@ -1556,7 +1579,7 @@ _skip: senderr(EINVAL); if (pfr_lookup_addr(shadow, &ad, 1) != NULL) continue; - p = pfr_create_kentry(&ad, 0); + p = pfr_create_kentry(&ad); if (p == NULL) senderr(ENOMEM); if (pfr_route_kentry(shadow, p)) { @@ -1697,10 +1720,11 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero) pfr_copyout_addr(&ad, p); q = pfr_lookup_addr(kt, &ad, 1); if (q != NULL) { - if (q->pfrke_not != p->pfrke_not) + if ((q->pfrke_flags & PFRKE_FLAG_NOT) != + (p->pfrke_flags & PFRKE_FLAG_NOT)) SLIST_INSERT_HEAD(&changeq, q, pfrke_workq); - q->pfrke_mark = 1; + q->pfrke_flags |= PFRKE_FLAG_MARK; SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq); } else { p->pfrke_tzero = tzero; @@ -2011,7 +2035,7 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) break; #endif /* INET6 */ } - match = (ke && !ke->pfrke_not); + match = (ke && !(ke->pfrke_flags & PFRKE_FLAG_NOT)); if (match) kt->pfrkt_match++; else @@ -2050,7 +2074,7 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, default: ; } - if ((ke == NULL || ke->pfrke_not) != notrule) { + if ((ke == NULL || (ke->pfrke_flags & PFRKE_FLAG_NOT)) != notrule) { if (op_pass != PFR_OP_PASS) printf("pfr_update_stats: assertion failed.\n"); op_pass = PFR_OP_XPASS; @@ -2117,7 +2141,8 @@ pfr_detach_table(struct pfr_ktable *kt) int pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, - struct pf_addr **raddr, struct pf_addr **rmask, sa_family_t af) + struct pf_addr **raddr, struct pf_addr **rmask, struct pfi_kif **kif, + sa_family_t af) { struct pfr_kentry *ke, *ke2; struct pf_addr *addr; @@ -2143,8 +2168,13 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, _next_block: ke = pfr_kentry_byidx(kt, idx, af); if (ke == NULL) { - kt->pfrkt_nomatch++; - return (1); + /* we don't have this idx, try looping */ + idx = 0; + ke = pfr_kentry_byidx(kt, idx, af); + if (ke == NULL) { + kt->pfrkt_nomatch++; + return (1); + } } pfr_prepare_network(&pfr_mask, af, ke->pfrke_net); *raddr = SUNION2PF(&ke->pfrke_sa, af); @@ -2169,6 +2199,8 @@ _next_block: PF_ACPY(counter, addr, af); *pidx = idx; kt->pfrkt_match++; + if (ke->pfrke_type == PFRKE_ROUTE) + *kif = ((struct pfr_kentry_route *)ke)->kif; return (0); } for (;;) { @@ -2185,6 +2217,8 @@ _next_block: PF_ACPY(counter, addr, af); *pidx = idx; kt->pfrkt_match++; + if (ke->pfrke_type == PFRKE_ROUTE) + *kif = ((struct pfr_kentry_route *)ke)->kif; return (0); } diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 596e44f9277..81f2b3c59f5 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.303 2009/12/24 04:24:19 dlg Exp $ */ +/* $OpenBSD: pfvar.h,v 1.304 2010/01/12 03:20:51 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -113,7 +113,7 @@ enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM, PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN }; enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, PF_ADDR_TABLE, PF_ADDR_RTLABEL, PF_ADDR_URPFFAILED, - PF_ADDR_RANGE }; + PF_ADDR_RANGE, PF_ADDR_NONE }; #define PF_POOL_TYPEMASK 0x0f #define PF_POOL_STICKYADDR 0x20 #define PF_WSCALE_FLAG 0x80 @@ -361,15 +361,6 @@ struct pf_rule_addr { u_int8_t port_op; }; -struct pf_pooladdr { - struct pf_addr_wrap addr; - TAILQ_ENTRY(pf_pooladdr) entries; - char ifname[IFNAMSIZ]; - struct pfi_kif *kif; -}; - -TAILQ_HEAD(pf_palist, pf_pooladdr); - struct pf_poolhashkey { union { u_int8_t key8[16]; @@ -382,10 +373,11 @@ struct pf_poolhashkey { }; struct pf_pool { - struct pf_palist list; - struct pf_pooladdr *cur; + struct pf_addr_wrap addr; struct pf_poolhashkey key; - struct pf_addr counter; + struct pf_addr counter; + char ifname[IFNAMSIZ]; + struct pfi_kif *kif; int tblidx; u_int16_t proxy_port[2]; u_int8_t port_op; @@ -993,10 +985,13 @@ struct pfr_addr { struct in_addr _pfra_ip4addr; struct in6_addr _pfra_ip6addr; } pfra_u; + char pfra_ifname[IFNAMSIZ]; u_int8_t pfra_af; u_int8_t pfra_net; u_int8_t pfra_not; u_int8_t pfra_fback; + u_int8_t pfra_type; + u_int8_t pad[7]; }; #define pfra_ip4addr pfra_u._pfra_ip4addr #define pfra_ip6addr pfra_u._pfra_ip6addr @@ -1033,26 +1028,53 @@ struct pfr_kcounters { }; SLIST_HEAD(pfr_kentryworkq, pfr_kentry); +struct _pfr_kentry { + struct radix_node _pfrke_node[2]; + union sockaddr_union _pfrke_sa; + SLIST_ENTRY(pfr_kentry) _pfrke_workq; + struct pfr_kcounters *_pfrke_counters; + long _pfrke_tzero; + u_int8_t _pfrke_af; + u_int8_t _pfrke_net; + u_int8_t _pfrke_flags; + u_int8_t _pfrke_type; +}; +#define PFRKE_FLAG_NOT 0x01 +#define PFRKE_FLAG_MARK 0x02 + +/* pfrke_type */ +enum { PFRKE_PLAIN, PFRKE_ROUTE, PFRKE_MAX }; + struct pfr_kentry { - struct radix_node pfrke_node[2]; - union sockaddr_union pfrke_sa; - SLIST_ENTRY(pfr_kentry) pfrke_workq; union { - - struct pfr_kcounters *pfrke_counters; -#if 0 - struct pfr_kroute *pfrke_route; -#endif + struct _pfr_kentry _ke; } u; - long pfrke_tzero; - u_int8_t pfrke_af; - u_int8_t pfrke_net; - u_int8_t pfrke_not; - u_int8_t pfrke_mark; }; -#define pfrke_counters u.pfrke_counters -#define pfrke_route u.pfrke_route +#define pfrke_node u._ke._pfrke_node +#define pfrke_sa u._ke._pfrke_sa +#define pfrke_workq u._ke._pfrke_workq +#define pfrke_counters u._ke._pfrke_counters +#define pfrke_tzero u._ke._pfrke_tzero +#define pfrke_af u._ke._pfrke_af +#define pfrke_net u._ke._pfrke_net +#define pfrke_flags u._ke._pfrke_flags +#define pfrke_type u._ke._pfrke_type + +struct pfr_kentry_route { + union { + struct _pfr_kentry _ke; + } u; + struct pfi_kif *kif; +}; + +struct pfr_kentry_all { + union { + struct _pfr_kentry _ke; + struct pfr_kentry_route kr; + } u; +}; +#define pfrke_rkif u.kr.kif SLIST_HEAD(pfr_ktableworkq, pfr_ktable); RB_HEAD(pfr_ktablehead, pfr_ktable); @@ -1111,13 +1133,15 @@ struct pfi_kif { struct ifg_group *pfik_group; int pfik_states; int pfik_rules; + int pfik_routes; TAILQ_HEAD(, pfi_dynaddr) pfik_dynaddrs; }; enum pfi_kif_refs { PFI_KIF_REF_NONE, PFI_KIF_REF_STATE, - PFI_KIF_REF_RULE + PFI_KIF_REF_RULE, + PFI_KIF_REF_ROUTE }; #define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */ @@ -1390,24 +1414,9 @@ struct pf_divert { * ioctl parameter structures */ -struct pfioc_pooladdr { - u_int32_t action; - u_int32_t ticket; - u_int32_t nr; - u_int32_t r_num; - u_int8_t r_action; - u_int8_t r_last; - u_int8_t af; - u_int8_t which; - u_int8_t pad[3]; - char anchor[MAXPATHLEN]; - struct pf_pooladdr addr; -}; - struct pfioc_rule { u_int32_t action; u_int32_t ticket; - u_int32_t pool_ticket; u_int32_t nr; char anchor[MAXPATHLEN]; char anchor_call[MAXPATHLEN]; @@ -1592,12 +1601,7 @@ struct pfioc_iface { #define DIOCGETALTQ _IOWR('D', 48, struct pfioc_altq) #define DIOCCHANGEALTQ _IOWR('D', 49, struct pfioc_altq) #define DIOCGETQSTATS _IOWR('D', 50, struct pfioc_qstats) -#define DIOCBEGINADDRS _IOWR('D', 51, struct pfioc_pooladdr) -#define DIOCADDADDR _IOWR('D', 52, struct pfioc_pooladdr) -#define DIOCGETADDRS _IOWR('D', 53, struct pfioc_pooladdr) -#define DIOCGETADDR _IOWR('D', 54, struct pfioc_pooladdr) -#define DIOCCHANGEADDR _IOWR('D', 55, struct pfioc_pooladdr) -/* XXX cut 55 - 57 */ +/* XXX cut 51 - 57 */ #define DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset) #define DIOCGETRULESET _IOWR('D', 59, struct pfioc_ruleset) #define DIOCRCLRTABLES _IOWR('D', 60, struct pfioc_table) @@ -1758,7 +1762,8 @@ int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t); void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t, 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); + struct pf_addr **, struct pf_addr **, struct pfi_kif **, + sa_family_t); void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); struct pfr_ktable * pfr_attach_table(struct pf_ruleset *, char *, int); -- cgit v1.2.3