summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/pf.c529
-rw-r--r--sys/net/pf_ioctl.c98
-rw-r--r--sys/net/pf_lb.c312
-rw-r--r--sys/net/pfvar.h37
4 files changed, 379 insertions, 597 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index be23e39d433..607608b3abd 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.657 2009/07/28 11:22:33 henning Exp $ */
+/* $OpenBSD: pf.c,v 1.658 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -103,7 +103,7 @@
struct pf_state_tree pf_statetbl;
struct pf_altqqueue pf_altqs[2];
-struct pf_palist pf_pabuf;
+struct pf_palist pf_pabuf[2];
struct pf_altqqueue *pf_altqs_active;
struct pf_altqqueue *pf_altqs_inactive;
struct pf_status pf_status;
@@ -167,14 +167,16 @@ int pf_test_rule(struct pf_rule **, struct pf_state **,
void *, struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **, struct ifqueue *);
static __inline int pf_create_state(struct pf_rule *, struct pf_rule *,
- struct pf_rule *, struct pf_pdesc *,
- struct pf_src_node *, struct pf_state_key *,
- struct pf_state_key *, struct pf_state_key *,
- struct pf_state_key *, struct mbuf *, int,
- u_int16_t, u_int16_t, int *, struct pfi_kif *,
+ struct pf_pdesc *, struct pf_state_key **,
+ struct pf_state_key **, struct mbuf *, int,
+ struct pf_addr *, u_int16_t, struct pf_addr *,
+ u_int16_t, int *, struct pfi_kif *,
struct pf_state **, int, u_int16_t, u_int16_t,
int, struct pf_rule_slist *,
struct pf_rule_actions *);
+void pf_translate(struct pf_pdesc *, struct pf_addr *,
+ u_int16_t, struct pf_addr *, u_int16_t, u_int16_t,
+ int, struct mbuf *, int);
int pf_test_fragment(struct pf_rule **, int,
struct pfi_kif *, struct mbuf *, void *,
struct pf_pdesc *, struct pf_rule **,
@@ -512,7 +514,8 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
k.af = af;
PF_ACPY(&k.addr, src, af);
if (rule->rule_flag & PFRULE_RULESRCTRACK ||
- rule->rpool.opts & PF_POOL_STICKYADDR)
+ rule->nat.opts & PF_POOL_STICKYADDR ||
+ rule->rdr.opts & PF_POOL_STICKYADDR)
k.rule.ptr = rule;
else
k.rule.ptr = NULL;
@@ -534,7 +537,8 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
(*sn)->af = af;
if (rule->rule_flag & PFRULE_RULESRCTRACK ||
- rule->rpool.opts & PF_POOL_STICKYADDR)
+ rule->nat.opts & PF_POOL_STICKYADDR ||
+ rule->rdr.opts & PF_POOL_STICKYADDR)
(*sn)->rule.ptr = rule;
else
(*sn)->rule.ptr = NULL;
@@ -769,45 +773,52 @@ pf_alloc_state_key(int pool_flags)
}
int
-pf_state_key_setup(struct pf_pdesc *pd, struct pf_rule *nr,
+pf_state_key_setup(struct pf_pdesc *pd,
struct pf_state_key **skw, struct pf_state_key **sks,
- struct pf_state_key **skp, struct pf_state_key **nkp,
- struct pf_addr *saddr, struct pf_addr *daddr,
- u_int16_t sport, u_int16_t dport)
+ struct pf_addr **saddr, struct pf_addr **daddr,
+ u_int16_t *sport, u_int16_t *dport)
{
- KASSERT((*skp == NULL && *nkp == NULL));
+ struct pf_state_key *sk1, *sk2;
- if ((*skp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
+ if ((sk1 = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
return (ENOMEM);
- PF_ACPY(&(*skp)->addr[pd->sidx], saddr, pd->af);
- PF_ACPY(&(*skp)->addr[pd->didx], daddr, pd->af);
- (*skp)->port[pd->sidx] = sport;
- (*skp)->port[pd->didx] = dport;
- (*skp)->proto = pd->proto;
- (*skp)->af = pd->af;
-
- if (nr != NULL) {
- if ((*nkp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
+ PF_ACPY(&sk1->addr[pd->sidx], pd->src, pd->af);
+ PF_ACPY(&sk1->addr[pd->didx], pd->dst, pd->af);
+ sk1->port[pd->sidx] = pd->osport;
+ sk1->port[pd->didx] = pd->odport;
+ sk1->proto = pd->proto;
+ sk1->af = pd->af;
+
+ if (PF_ANEQ(*saddr, pd->src, pd->af) ||
+ PF_ANEQ(*daddr, pd->dst, pd->af) ||
+ *sport != pd->osport || *dport != pd->odport) { /* NAT */
+ if ((sk2 = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
return (ENOMEM); /* caller must handle cleanup */
- /* XXX maybe just bcopy and TAILQ_INIT(&(*nkp)->states) */
- PF_ACPY(&(*nkp)->addr[0], &(*skp)->addr[0], pd->af);
- PF_ACPY(&(*nkp)->addr[1], &(*skp)->addr[1], pd->af);
- (*nkp)->port[0] = (*skp)->port[0];
- (*nkp)->port[1] = (*skp)->port[1];
- (*nkp)->proto = pd->proto;
- (*nkp)->af = pd->af;
+ PF_ACPY(&sk2->addr[pd->sidx], *saddr, pd->af);
+ PF_ACPY(&sk2->addr[pd->didx], *daddr, pd->af);
+ sk2->port[pd->sidx] = *sport;
+ sk2->port[pd->didx] = *dport;
+ sk2->proto = pd->proto;
+ sk2->af = pd->af;
} else
- *nkp = *skp;
+ sk2 = sk1;
if (pd->dir == PF_IN) {
- *skw = *skp;
- *sks = *nkp;
+ *skw = sk1;
+ *sks = sk2;
} else {
- *sks = *skp;
- *skw = *nkp;
+ *sks = sk1;
+ *skw = sk2;
+ }
+
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: key setup: ");
+ pf_print_state_parts(NULL, *skw, *sks);
+ printf("\n");
}
+
return (0);
}
@@ -819,7 +830,6 @@ pf_state_insert(struct pfi_kif *kif, struct pf_state_key *skw,
splsoftassert(IPL_SOFTNET);
s->kif = kif;
-
if (skw == sks) {
if (pf_state_key_attach(skw, s, PF_SK_WIRE))
return (-1);
@@ -906,6 +916,11 @@ pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir,
struct pf_state_item *si;
pf_status.fcounters[FCNT_STATE_SEARCH]++;
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: key search, if=%s: ", kif->pfik_name);
+ pf_print_state_parts(NULL, (struct pf_state_key *)key, NULL);
+ printf("\n");
+ }
if (dir == PF_OUT && m->m_pkthdr.pf.statekey &&
((struct pf_state_key *)m->m_pkthdr.pf.statekey)->reverse)
@@ -1569,17 +1584,18 @@ pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
PF_ACPY(&ao, a, AF_INET6);
PF_ACPY(a, an, AF_INET6);
- *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(*c,
- ao.addr16[0], an->addr16[0], u),
- ao.addr16[1], an->addr16[1], u),
- ao.addr16[2], an->addr16[2], u),
- ao.addr16[3], an->addr16[3], u),
- ao.addr16[4], an->addr16[4], u),
- ao.addr16[5], an->addr16[5], u),
- ao.addr16[6], an->addr16[6], u),
- ao.addr16[7], an->addr16[7], u);
+ if (c)
+ *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(*c,
+ ao.addr16[0], an->addr16[0], u),
+ ao.addr16[1], an->addr16[1], u),
+ ao.addr16[2], an->addr16[2], u),
+ ao.addr16[3], an->addr16[3], u),
+ ao.addr16[4], an->addr16[4], u),
+ ao.addr16[5], an->addr16[5], u),
+ ao.addr16[6], an->addr16[6], u),
+ ao.addr16[7], an->addr16[7], u);
}
#endif /* INET6 */
@@ -1594,6 +1610,7 @@ pf_icmp_mapping(struct pf_pdesc *pd, u_int8_t type,
*/
*icmp_dir = PF_OUT;
*multi = PF_ICMP_MULTI_LINK;
+
/* Queries (and responses) */
switch (type) {
case ICMP_ECHO:
@@ -1714,7 +1731,7 @@ pf_icmp_mapping(struct pf_pdesc *pd, u_int8_t type,
#endif /* INET6 */
/* These will not be used, but set them anyways */
*icmp_dir = PF_IN;
- *icmptype = htons(type);
+ *icmptype = type;
*icmpid = 0;
return (1); /* These types are matched to other state */
/*
@@ -2584,14 +2601,15 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
switch (s->key[PF_SK_WIRE]->af) {
#ifdef INET
case AF_INET:
- pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &sn);
- s->rt_kif = r->rpool.cur->kif;
+ pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &sn, &r->rdr);
+ s->rt_kif = r->rdr.cur->kif;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &sn);
- s->rt_kif = r->rpool.cur->kif;
+ pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &sn,
+ &r->rdr);
+ s->rt_kif = r->rdr.cur->kif;
break;
#endif /* INET6 */
}
@@ -2652,17 +2670,15 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
struct ifqueue *ifq)
{
- struct pf_rule *nr = NULL, *lastr = NULL;
- struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct pf_rule *lastr = NULL;
+ struct pf_addr saddr, daddr;
sa_family_t af = pd->af;
struct pf_rule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL;
struct pf_rule_slist rules;
struct pf_rule_item *ri;
- struct pf_src_node *nsn = NULL;
struct tcphdr *th = pd->hdr.tcp;
struct pf_state_key *skw = NULL, *sks = NULL;
- struct pf_state_key *sk = NULL, *nk = NULL;
struct pf_rule_actions act;
u_short reason;
int rewrite = 0, hdrlen = 0;
@@ -2674,6 +2690,9 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
u_int16_t bproto_sum = 0, bip_sum;
u_int8_t icmptype = 0, icmpcode = 0;
+ PF_ACPY(&saddr, pd->src, pd->af);
+ PF_ACPY(&daddr, pd->dst, pd->af);
+
bzero(&act, sizeof(act));
act.rtableid = -1;
SLIST_INIT(&rules);
@@ -2698,7 +2717,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
case IPPROTO_ICMP:
if (pd->af != AF_INET)
break;
- hdrlen = sizeof(*pd->hdr.icmp);
+ hdrlen = ICMP_MINLEN;
icmptype = pd->hdr.icmp->icmp_type;
icmpcode = pd->hdr.icmp->icmp_code;
state_icmp = pf_icmp_mapping(pd, icmptype,
@@ -2735,143 +2754,10 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
break;
}
- r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
-
- /* check packet for BINAT/NAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn,
- &skw, &sks, &sk, &nk, saddr, daddr, sport, dport)) != NULL) {
- if (nk == NULL || sk == NULL) {
- REASON_SET(&reason, PFRES_MEMORY);
- goto cleanup;
- }
-
- if (pd->ip_sum)
- bip_sum = *pd->ip_sum;
-
- switch (pd->proto) {
- case IPPROTO_TCP:
- bproto_sum = th->th_sum;
- pd->proto_sum = &th->th_sum;
-
- if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
- nk->port[pd->sidx] != sport) {
- pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
- &th->th_sum, &nk->addr[pd->sidx],
- nk->port[pd->sidx], 0, af);
- pd->sport = &th->th_sport;
- sport = th->th_sport;
- }
-
- if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
- nk->port[pd->didx] != dport) {
- pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
- &th->th_sum, &nk->addr[pd->didx],
- nk->port[pd->didx], 0, af);
- dport = th->th_dport;
- pd->dport = &th->th_dport;
- }
- rewrite++;
- break;
- case IPPROTO_UDP:
- bproto_sum = pd->hdr.udp->uh_sum;
- pd->proto_sum = &pd->hdr.udp->uh_sum;
-
- if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
- nk->port[pd->sidx] != sport) {
- pf_change_ap(saddr, &pd->hdr.udp->uh_sport,
- pd->ip_sum, &pd->hdr.udp->uh_sum,
- &nk->addr[pd->sidx],
- nk->port[pd->sidx], 1, af);
- sport = pd->hdr.udp->uh_sport;
- pd->sport = &pd->hdr.udp->uh_sport;
- }
-
- if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
- nk->port[pd->didx] != dport) {
- pf_change_ap(daddr, &pd->hdr.udp->uh_dport,
- pd->ip_sum, &pd->hdr.udp->uh_sum,
- &nk->addr[pd->didx],
- nk->port[pd->didx], 1, af);
- dport = pd->hdr.udp->uh_dport;
- pd->dport = &pd->hdr.udp->uh_dport;
- }
- rewrite++;
- break;
-#ifdef INET
- case IPPROTO_ICMP:
- if (af != AF_INET)
- break;
-
- if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET))
- pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
- nk->addr[pd->sidx].v4.s_addr, 0);
-
- if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET))
- pf_change_a(&daddr->v4.s_addr, pd->ip_sum,
- nk->addr[pd->didx].v4.s_addr, 0);
-
- if (virtual_type == ICMP_ECHO &&
- nk->port[pd->sidx] != pd->hdr.icmp->icmp_id) {
- pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
- pd->hdr.icmp->icmp_cksum, sport,
- nk->port[pd->sidx], 0);
- pd->hdr.icmp->icmp_id = nk->port[pd->sidx];
- pd->sport = &pd->hdr.icmp->icmp_id;
- }
- m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
- break;
-#endif /* INET */
-#ifdef INET6
- case IPPROTO_ICMPV6:
- if (af != AF_INET6)
- break;
-
- if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET6))
- pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
- &nk->addr[pd->sidx], 0);
-
- if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET6))
- pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
- &nk->addr[pd->didx], 0);
- rewrite++;
- break;
-#endif /* INET */
- default:
- switch (af) {
-#ifdef INET
- case AF_INET:
- if (PF_ANEQ(saddr,
- &nk->addr[pd->sidx], AF_INET))
- pf_change_a(&saddr->v4.s_addr,
- pd->ip_sum,
- nk->addr[pd->sidx].v4.s_addr, 0);
-
- if (PF_ANEQ(daddr,
- &nk->addr[pd->didx], AF_INET))
- pf_change_a(&daddr->v4.s_addr,
- pd->ip_sum,
- nk->addr[pd->didx].v4.s_addr, 0);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- if (PF_ANEQ(saddr,
- &nk->addr[pd->sidx], AF_INET6))
- PF_ACPY(saddr, &nk->addr[pd->sidx], af);
-
- if (PF_ANEQ(daddr,
- &nk->addr[pd->didx], AF_INET6))
- PF_ACPY(saddr, &nk->addr[pd->didx], af);
- break;
-#endif /* INET */
- }
- break;
- }
- if (nr->natpass)
- r = NULL;
- pd->nat_rule = nr;
- }
+ pd->osport = sport;
+ pd->odport = dport;
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
while (r != NULL) {
r->evaluations++;
if (pfi_kif_match(r->kif, kif) == r->ifnot)
@@ -2882,14 +2768,14 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
r = r->skip[PF_SKIP_AF].ptr;
else if (r->proto && r->proto != pd->proto)
r = r->skip[PF_SKIP_PROTO].ptr;
- else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
+ else if (PF_MISMATCHAW(&r->src.addr, &saddr, af,
r->src.neg, kif))
r = r->skip[PF_SKIP_SRC_ADDR].ptr;
/* tcp/udp only. port_op always 0 in other cases */
else if (r->src.port_op && !pf_match_port(r->src.port_op,
r->src.port[0], r->src.port[1], sport))
r = r->skip[PF_SKIP_SRC_PORT].ptr;
- else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
+ else if (PF_MISMATCHAW(&r->dst.addr, &daddr, af,
r->dst.neg, NULL))
r = r->skip[PF_SKIP_DST_ADDR].ptr;
/* tcp/udp only. port_op always 0 in other cases */
@@ -2947,6 +2833,8 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
/* order is irrelevant */
SLIST_INSERT_HEAD(&rules, ri, entry);
pf_rule_to_actions(r, &act);
+ pf_get_transaddr(r, pd, &saddr, &sport,
+ &daddr, &dport);
} else {
match = 1;
*rm = r;
@@ -2970,19 +2858,19 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
ruleset = *rsm;
/* apply actions for last matching rule */
- if (lastr && lastr->action != PF_MATCH)
+ if (lastr && lastr->action != PF_MATCH) {
pf_rule_to_actions(lastr, &act);
+ pf_get_transaddr(lastr, pd, &saddr, &sport, &daddr, &dport);
+ }
REASON_SET(&reason, PFRES_MATCH);
- if (act.log || (nr != NULL && nr->log)) {
+ if (act.log) {
struct pf_rule_item *mr;
- if (rewrite)
- m_copyback(m, off, hdrlen, pd->hdr.any);
if (r->log)
PFLOG_PACKET(kif, h, m, af, direction, reason,
- r->log ? r : nr, a, ruleset, pd);
+ r, a, ruleset, pd);
SLIST_FOREACH(mr, &rules, entry)
if (mr->r->log)
PFLOG_PACKET(kif, h, m, af, direction, reason,
@@ -2993,20 +2881,6 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
((r->rule_flag & PFRULE_RETURNRST) ||
(r->rule_flag & PFRULE_RETURNICMP) ||
(r->rule_flag & PFRULE_RETURN))) {
- /* undo NAT changes, if they have taken place */
- if (nr != NULL) {
- PF_ACPY(saddr, &sk->addr[pd->sidx], af);
- PF_ACPY(daddr, &sk->addr[pd->didx], af);
- if (pd->sport)
- *pd->sport = sk->port[pd->sidx];
- if (pd->dport)
- *pd->dport = sk->port[pd->didx];
- if (pd->proto_sum)
- *pd->proto_sum = bproto_sum;
- if (pd->ip_sum)
- *pd->ip_sum = bip_sum;
- m_copyback(m, off, hdrlen, pd->hdr.any);
- }
if (pd->proto == IPPROTO_TCP &&
((r->rule_flag & PFRULE_RETURNRST) ||
(r->rule_flag & PFRULE_RETURN)) &&
@@ -3058,18 +2932,32 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
goto cleanup;
}
- if (!state_icmp && (r->keep_state || nr != NULL)) {
+ if (!state_icmp && r->keep_state) {
int action;
- action = pf_create_state(r, nr, a, pd, nsn, skw, sks, nk, sk, m,
- off, sport, dport, &rewrite, kif, sm, tag, bproto_sum,
- bip_sum, hdrlen, &rules, &act);
+ action = pf_create_state(r, a, pd, &skw, &sks, m,
+ off, &saddr, sport, &daddr, dport, &rewrite, kif, sm, tag,
+ bproto_sum, bip_sum, hdrlen, &rules, &act);
+
if (action != PF_PASS)
return (action);
+ if (sks != skw) {
+ struct pf_state_key *sk;
+
+ if (pd->dir == PF_IN)
+ sk = sks;
+ else
+ sk = skw;
+ pf_translate(pd,
+ &sk->addr[pd->sidx], sk->port[pd->sidx],
+ &sk->addr[pd->didx], sk->port[pd->didx],
+ virtual_type, icmp_dir, m, off);
+ rewrite = 1;
+ }
} else {
- if (sk != NULL)
- pool_put(&pf_state_key_pl, sk);
- if (nk != NULL)
- pool_put(&pf_state_key_pl, nk);
+ if (sks != NULL)
+ pool_put(&pf_state_key_pl, sks);
+ if (skw != NULL)
+ pool_put(&pf_state_key_pl, skw);
while ((ri = SLIST_FIRST(&rules))) {
SLIST_REMOVE_HEAD(&rules, entry);
pool_put(&pf_rule_item_pl, ri);
@@ -3097,10 +2985,10 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
return (PF_PASS);
cleanup:
- if (sk != NULL)
- pool_put(&pf_state_key_pl, sk);
- if (nk != NULL)
- pool_put(&pf_state_key_pl, nk);
+ if (sks != NULL)
+ pool_put(&pf_state_key_pl, sks);
+ if (skw != NULL)
+ pool_put(&pf_state_key_pl, skw);
while ((ri = SLIST_FIRST(&rules))) {
SLIST_REMOVE_HEAD(&rules, entry);
pool_put(&pf_rule_item_pl, ri);
@@ -3110,13 +2998,12 @@ cleanup:
}
static __inline int
-pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
- struct pf_pdesc *pd, struct pf_src_node *nsn, struct pf_state_key *skw,
- struct pf_state_key *sks, struct pf_state_key *nk, struct pf_state_key *sk,
- struct mbuf *m, int off, u_int16_t sport, u_int16_t dport, int *rewrite,
- struct pfi_kif *kif, struct pf_state **sm, int tag, u_int16_t bproto_sum,
- u_int16_t bip_sum, int hdrlen, struct pf_rule_slist *rules,
- struct pf_rule_actions *act)
+pf_create_state(struct pf_rule *r, struct pf_rule *a, struct pf_pdesc *pd,
+ struct pf_state_key **skw, struct pf_state_key **sks, struct mbuf *m,
+ int off, struct pf_addr *saddr, u_int16_t sport, struct pf_addr *daddr,
+ u_int16_t dport, int *rewrite, struct pfi_kif *kif, struct pf_state **sm,
+ int tag, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen,
+ struct pf_rule_slist *rules, struct pf_rule_actions *act)
{
struct pf_state *s = NULL;
struct pf_src_node *sn = NULL;
@@ -3132,24 +3019,18 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
}
/* src node for filter rule */
if ((r->rule_flag & PFRULE_SRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR) &&
+ r->rdr.opts & PF_POOL_STICKYADDR ||
+ r->nat.opts & PF_POOL_STICKYADDR) &&
pf_insert_src_node(&sn, r, pd->src, pd->af) != 0) {
REASON_SET(&reason, PFRES_SRCLIMIT);
goto csfailed;
}
- /* src node for translation rule */
- if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
- pf_insert_src_node(&nsn, nr, &sk->addr[pd->sidx], pd->af)) {
- REASON_SET(&reason, PFRES_SRCLIMIT);
- goto csfailed;
- }
s = pool_get(&pf_state_pl, PR_NOWAIT | PR_ZERO);
if (s == NULL) {
REASON_SET(&reason, PFRES_MEMORY);
goto csfailed;
}
s->rule.ptr = r;
- s->nat_rule.ptr = nr;
s->anchor.ptr = a;
bcopy(rules, &s->match_rules, sizeof(s->match_rules));
STATE_INC_COUNTERS(s);
@@ -3168,8 +3049,6 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
s->max_mss = act->max_mss;
s->state_flags |= act->flags;
s->sync_state = PFSYNC_S_NONE;
- if (nr != NULL)
- s->log |= nr->log & PF_LOG_ALL;
switch (pd->proto) {
case IPPROTO_TCP:
s->src.seqlo = ntohl(th->th_seq);
@@ -3230,12 +3109,6 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
s->src_node = sn;
s->src_node->states++;
}
- if (nsn != NULL) {
- /* XXX We only modify one side for now. */
- PF_ACPY(&nsn->raddr, &nk->addr[1], pd->af);
- s->nat_src_node = nsn;
- s->nat_src_node->states++;
- }
if (pd->proto == IPPROTO_TCP) {
if (s->state_flags & PFSTATE_SCRUB_TCP &&
pf_normalize_tcp_init(m, off, pd, th, &s->src, &s->dst)) {
@@ -3260,11 +3133,10 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
}
s->direction = pd->dir;
- if (sk == NULL && pf_state_key_setup(pd, nr, &skw, &sks, &sk, &nk,
- pd->src, pd->dst, sport, dport))
+ if (pf_state_key_setup(pd, skw, sks, &saddr, &daddr, &sport, &dport))
goto csfailed;
- if (pf_state_insert(BOUND_IFACE(r, kif), skw, sks, s)) {
+ if (pf_state_insert(BOUND_IFACE(r, kif), *skw, *sks, s)) {
if (pd->proto == IPPROTO_TCP)
pf_normalize_tcp_cleanup(s);
REASON_SET(&reason, PFRES_STATEINS);
@@ -3283,23 +3155,6 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
if (pd->proto == IPPROTO_TCP && (th->th_flags & (TH_SYN|TH_ACK)) ==
TH_SYN && r->keep_state == PF_STATE_SYNPROXY) {
s->src.state = PF_TCPS_PROXY_SRC;
- /* undo NAT changes, if they have taken place */
- if (nr != NULL) {
- struct pf_state_key *skt = s->key[PF_SK_WIRE];
- if (pd->dir == PF_OUT)
- skt = s->key[PF_SK_STACK];
- PF_ACPY(pd->src, &skt->addr[pd->sidx], pd->af);
- PF_ACPY(pd->dst, &skt->addr[pd->didx], pd->af);
- if (pd->sport)
- *pd->sport = skt->port[pd->sidx];
- if (pd->dport)
- *pd->dport = skt->port[pd->didx];
- if (pd->proto_sum)
- *pd->proto_sum = bproto_sum;
- if (pd->ip_sum)
- *pd->ip_sum = bip_sum;
- m_copyback(m, off, hdrlen, pd->hdr.any);
- }
s->src.seqhi = htonl(arc4random());
/* Find mss option */
mss = pf_get_mss(m, off, th->th_off, pd->af);
@@ -3316,10 +3171,14 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
return (PF_PASS);
csfailed:
- if (sk != NULL)
- pool_put(&pf_state_key_pl, sk);
- if (nk != NULL)
- pool_put(&pf_state_key_pl, nk);
+ if (*skw != NULL) {
+ pool_put(&pf_state_key_pl, *skw);
+ *skw = NULL;
+ }
+ if (*sks != NULL) {
+ pool_put(&pf_state_key_pl, *sks);
+ *sks = NULL;
+ }
if (sn != NULL && sn->states == 0 && sn->expire == 0) {
RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
@@ -3327,15 +3186,92 @@ csfailed:
pf_status.src_nodes--;
pool_put(&pf_src_tree_pl, sn);
}
- if (nsn != sn && nsn != NULL && nsn->states == 0 && nsn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, nsn);
- }
return (PF_DROP);
}
+void
+pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
+ struct pf_addr *daddr, u_int16_t dport, u_int16_t virtual_type,
+ int icmp_dir, struct mbuf *m, int off)
+{
+ switch (pd->proto) {
+ case IPPROTO_TCP:
+ if (PF_ANEQ(saddr, pd->src, pd->af) || *pd->sport != sport)
+ pf_change_ap(pd->src, pd->sport, pd->ip_sum,
+ &pd->hdr.tcp->th_sum, saddr, sport, 0, pd->af);
+ if (PF_ANEQ(daddr, pd->dst, pd->af) || *pd->dport != dport)
+ pf_change_ap(pd->dst, pd->dport, pd->ip_sum,
+ &pd->hdr.tcp->th_sum, daddr, dport, 0, pd->af);
+ break;
+
+ case IPPROTO_UDP:
+ if (PF_ANEQ(saddr, pd->src, pd->af) || *pd->sport != sport)
+ pf_change_ap(pd->src, pd->sport, pd->ip_sum,
+ &pd->hdr.udp->uh_sum, saddr, sport, 1, pd->af);
+ if (PF_ANEQ(daddr, pd->dst, pd->af) || *pd->dport != dport)
+ pf_change_ap(pd->dst, pd->dport, pd->ip_sum,
+ &pd->hdr.udp->uh_sum, daddr, dport, 1, pd->af);
+ break;
+
+#ifdef INET
+ case IPPROTO_ICMP:
+ if (PF_ANEQ(saddr, pd->src, pd->af))
+ pf_change_a(&pd->src->v4.s_addr, pd->ip_sum,
+ saddr->v4.s_addr, 0);
+ if (PF_ANEQ(daddr, pd->dst, pd->af))
+ pf_change_a(&pd->dst->v4.s_addr, pd->ip_sum,
+ daddr->v4.s_addr, 0);
+ if (virtual_type == htons(ICMP_ECHO)) {
+ u_int16_t icmpid = (icmp_dir == PF_IN) ? sport : dport;
+
+ if (icmpid != pd->hdr.icmp->icmp_id) {
+ pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum,
+ pd->hdr.icmp->icmp_id, icmpid, 0);
+ pd->hdr.icmp->icmp_id = icmpid;
+ }
+ }
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+ if (pd->af == AF_INET6) {
+ if (PF_ANEQ(saddr, pd->src, pd->af))
+ pf_change_a6(pd->src,
+ &pd->hdr.icmp6->icmp6_cksum, saddr, 0);
+ if (PF_ANEQ(daddr, pd->dst, pd->af))
+ pf_change_a6(pd->dst,
+ &pd->hdr.icmp6->icmp6_cksum, daddr, 0);
+ break;
+ }
+ /* FALLTHROUGH */
+#endif /* INET6 */
+
+ default:
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ if (PF_ANEQ(saddr, pd->src, pd->af))
+ pf_change_a(&pd->src->v4.s_addr, pd->ip_sum,
+ saddr->v4.s_addr, 0);
+ if (PF_ANEQ(daddr, pd->dst, pd->af))
+ pf_change_a(&pd->dst->v4.s_addr, pd->ip_sum,
+ daddr->v4.s_addr, 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (PF_ANEQ(saddr, pd->src, pd->af))
+ pf_change_a6(pd->src, pd->ip_sum, saddr, 0);
+ if (PF_ANEQ(daddr, pd->dst, pd->af))
+ pf_change_a6(pd->dst, pd->ip_sum, daddr, 0);
+ break;
+#endif /* INET6 */
+ }
+ }
+}
+
int
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,
@@ -4100,7 +4036,7 @@ pf_icmp_state_lookup(struct pf_state_key_cmp *key, struct pf_pdesc *pd,
STATE_LOOKUP(kif, key, direction, *state, m);
/* Is this ICMP message flowing in right direction? */
- if ((*state)->rule.ptr->type &&
+ if ((*state)->rule.ptr->type &&
(((!inner && (*state)->direction == direction) ||
(inner && (*state)->direction != direction)) ?
PF_IN : PF_OUT) != icmp_dir) {
@@ -4141,7 +4077,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
break;
#endif /* INET6 */
}
-
+
if (pf_icmp_mapping(pd, icmptype, &icmp_dir, &multi,
&virtual_id, &virtual_type) == 0) {
/*
@@ -4189,7 +4125,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
pd->hdr.icmp->icmp_id) {
pd->hdr.icmp->icmp_cksum =
pf_cksum_fixup(
- pd->hdr.icmp->icmp_cksum, icmpid,
+ pd->hdr.icmp->icmp_cksum,
+ pd->hdr.icmp->icmp_id,
nk->port[iidx], 0);
pd->hdr.icmp->icmp_id = nk->port[iidx];
}
@@ -5037,18 +4974,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->rpool.list)) {
+ if (TAILQ_EMPTY(&r->rdr.list)) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("pf_route: TAILQ_EMPTY(&r->rpool.list)\n"));
+ ("pf_route: TAILQ_EMPTY(&r->rdr.list)\n"));
goto bad;
}
if (s == NULL) {
pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
- &naddr, NULL, &sn);
+ &naddr, NULL, &sn, &r->rdr);
if (!PF_AZERO(&naddr, AF_INET))
dst->sin_addr.s_addr = naddr.v4.s_addr;
- ifp = r->rpool.cur->kif ?
- r->rpool.cur->kif->pfik_ifp : NULL;
+ ifp = r->rdr.cur->kif ?
+ r->rdr.cur->kif->pfik_ifp : NULL;
} else {
if (!PF_AZERO(&s->rt_addr, AF_INET))
dst->sin_addr.s_addr =
@@ -5219,18 +5156,18 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
return;
}
- if (TAILQ_EMPTY(&r->rpool.list)) {
+ if (TAILQ_EMPTY(&r->rdr.list)) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("pf_route6: TAILQ_EMPTY(&r->rpool.list)\n"));
+ ("pf_route6: TAILQ_EMPTY(&r->rdr.list)\n"));
goto bad;
}
if (s == NULL) {
pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
- &naddr, NULL, &sn);
+ &naddr, NULL, &sn, &r->rdr);
if (!PF_AZERO(&naddr, AF_INET6))
PF_ACPY((struct pf_addr *)&dst->sin6_addr,
&naddr, AF_INET6);
- ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
+ ifp = r->rdr.cur->kif ? r->rdr.cur->kif->pfik_ifp : NULL;
} else {
if (!PF_AZERO(&s->rt_addr, AF_INET6))
PF_ACPY((struct pf_addr *)&dst->sin6_addr,
@@ -5502,6 +5439,8 @@ 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;
+ pd.sport = &th.th_sport;
+ pd.dport = &th.th_dport;
action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
if (action == PF_DROP)
goto done;
@@ -5544,6 +5483,8 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
REASON_SET(&reason, PFRES_SHORT);
goto done;
}
+ pd.sport = &uh.uh_sport;
+ pd.dport = &uh.uh_dport;
action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
if (action == PF_PASS) {
#if NPFSYNC > 0
@@ -5919,6 +5860,8 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
goto done;
}
pd.p_len = pd.tot_len - off - (th.th_off << 2);
+ pd.sport = &th.th_sport;
+ pd.dport = &th.th_dport;
action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
if (action == PF_DROP)
goto done;
@@ -5960,6 +5903,8 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
REASON_SET(&reason, PFRES_SHORT);
goto done;
}
+ pd.sport = &uh.uh_sport;
+ pd.dport = &uh.uh_dport;
action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
if (action == PF_PASS) {
#if NPFSYNC > 0
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 6b254c72e84..ef4c2b18819 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.219 2009/05/31 19:10:51 henning Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.220 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -92,7 +92,7 @@ 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);
+ 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 *);
@@ -187,7 +187,8 @@ pfattach(int num)
pf_init_ruleset(&pf_main_ruleset);
TAILQ_INIT(&pf_altqs[0]);
TAILQ_INIT(&pf_altqs[1]);
- TAILQ_INIT(&pf_pabuf);
+ TAILQ_INIT(&pf_pabuf[0]);
+ TAILQ_INIT(&pf_pabuf[1]);
pf_altqs_active = &pf_altqs[0];
pf_altqs_inactive = &pf_altqs[1];
TAILQ_INIT(&state_list);
@@ -258,7 +259,7 @@ pfclose(dev_t dev, int flags, int fmt, struct proc *p)
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)
+ u_int8_t check_ticket, int which)
{
struct pf_ruleset *ruleset;
struct pf_rule *rule;
@@ -295,8 +296,10 @@ pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
}
if (rule == NULL)
return (NULL);
-
- return (&rule->rpool);
+ if (which == PF_NAT)
+ return (&rule->nat);
+ else
+ return (&rule->rdr);
}
void
@@ -366,7 +369,8 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
}
pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
pf_anchor_remove(rule);
- pf_empty_pool(&rule->rpool.list);
+ pf_empty_pool(&rule->rdr.list);
+ pf_empty_pool(&rule->nat.list);
pool_put(&pf_rule_pl, rule);
}
@@ -1096,7 +1100,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
rule->cpid = p->p_pid;
rule->anchor = NULL;
rule->kif = NULL;
- TAILQ_INIT(&rule->rpool.list);
+ TAILQ_INIT(&rule->rdr.list);
+ TAILQ_INIT(&rule->nat.list);
/* initialize refcounting */
rule->states_cur = 0;
rule->src_nodes = 0;
@@ -1171,7 +1176,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
error = EINVAL;
- TAILQ_FOREACH(pa, &pf_pabuf, entries)
+ 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;
@@ -1184,18 +1192,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
PFR_TFLAG_ACTIVE;
}
- pf_mv_pool(&pf_pabuf, &rule->rpool.list);
- if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
- (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
- (rule->rt > PF_FASTROUTE)) &&
- (TAILQ_FIRST(&rule->rpool.list) == NULL))
+ pf_mv_pool(&pf_pabuf[0], &rule->nat.list);
+ pf_mv_pool(&pf_pabuf[1], &rule->rdr.list);
+
+ if (rule->rt > PF_FASTROUTE &&
+ (TAILQ_FIRST(&rule->rdr.list) == NULL))
error = EINVAL;
if (error) {
pf_rm_rule(NULL, rule);
break;
}
- rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
+ rule->nat.cur = TAILQ_FIRST(&rule->nat.list);
+ rule->rdr.cur = TAILQ_FIRST(&rule->rdr.list);
rule->evaluations = rule->packets[0] = rule->packets[1] =
rule->bytes[0] = rule->bytes[1] = 0;
TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
@@ -1336,7 +1345,8 @@ 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->rpool.list);
+ TAILQ_INIT(&newrule->rdr.list);
+ TAILQ_INIT(&newrule->nat.list);
/* initialize refcounting */
newrule->states_cur = 0;
newrule->entries.tqe_prev = NULL;
@@ -1408,7 +1418,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
error = EINVAL;
- TAILQ_FOREACH(pa, &pf_pabuf, entries)
+ 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;
@@ -1422,25 +1435,25 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
PFR_TFLAG_ACTIVE;
}
- pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
- if (((((newrule->action == PF_NAT) ||
- (newrule->action == PF_RDR) ||
- (newrule->action == PF_BINAT) ||
- (newrule->rt > PF_FASTROUTE)) &&
- !newrule->anchor)) &&
- (TAILQ_FIRST(&newrule->rpool.list) == NULL))
+ pf_mv_pool(&pf_pabuf[0], &newrule->nat.list);
+ pf_mv_pool(&pf_pabuf[1], &newrule->rdr.list);
+ if (newrule->rt > PF_FASTROUTE &&
+ !newrule->anchor &&
+ (TAILQ_FIRST(&newrule->rdr.list) == NULL))
error = EINVAL;
if (error) {
pf_rm_rule(NULL, newrule);
break;
}
- newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
+ newrule->rdr.cur = TAILQ_FIRST(&newrule->rdr.list);
+ newrule->nat.cur = TAILQ_FIRST(&newrule->nat.list);
newrule->evaluations = 0;
newrule->packets[0] = newrule->packets[1] = 0;
newrule->bytes[0] = newrule->bytes[1] = 0;
}
- pf_empty_pool(&pf_pabuf);
+ pf_empty_pool(&pf_pabuf[0]);
+ pf_empty_pool(&pf_pabuf[1]);
if (pcr->action == PF_CHANGE_ADD_HEAD)
oldrule = TAILQ_FIRST(
@@ -1954,7 +1967,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCBEGINADDRS: {
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
- pf_empty_pool(&pf_pabuf);
+ pf_empty_pool(&pf_pabuf[0]);
+ pf_empty_pool(&pf_pabuf[1]);
pp->ticket = ++ticket_pabuf;
break;
}
@@ -1962,6 +1976,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCADDADDR: {
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+ if (pp->which != PF_NAT && pp->which != PF_RDR) {
+ error = EINVAL;
+ break;
+ }
+
if (pp->ticket != ticket_pabuf) {
error = EBUSY;
break;
@@ -2006,16 +2025,23 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
+
+ TAILQ_INSERT_TAIL(&pf_pabuf[pp->which == PF_NAT ? 0 : 1], pa,
+ entries);
break;
}
case DIOCGETADDRS: {
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+ if (pp->which != PF_NAT && pp->which != PF_RDR) {
+ error = EINVAL;
+ break;
+ }
+
pp->nr = 0;
pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
- pp->r_num, 0, 1, 0);
+ pp->r_num, 0, 1, 0, pp->which);
if (pool == NULL) {
error = EBUSY;
break;
@@ -2029,8 +2055,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
u_int32_t nr = 0;
+ if (pp->which != PF_NAT && pp->which != PF_RDR) {
+ error = EINVAL;
+ break;
+ }
+
pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
- pp->r_num, 0, 1, 1);
+ pp->r_num, 0, 1, 1, pp->which);
if (pool == NULL) {
error = EBUSY;
break;
@@ -2054,6 +2085,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_pooladdr *oldpa = NULL, *newpa = NULL;
struct pf_ruleset *ruleset;
+ if (pca->which != PF_NAT && pca->which != PF_RDR) {
+ error = EINVAL;
+ break;
+ }
+
if (pca->action < PF_CHANGE_ADD_HEAD ||
pca->action > PF_CHANGE_REMOVE) {
error = EINVAL;
@@ -2072,7 +2108,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
- pca->r_num, pca->r_last, 1, 1);
+ pca->r_num, pca->r_last, 1, 1, pca->which);
if (pool == NULL) {
error = EBUSY;
break;
diff --git a/sys/net/pf_lb.c b/sys/net/pf_lb.c
index d8972e27416..1f4c0e3d9b2 100644
--- a/sys/net/pf_lb.c
+++ b/sys/net/pf_lb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_lb.c,v 1.5 2009/06/24 13:27:34 sthen Exp $ */
+/* $OpenBSD: pf_lb.c,v 1.6 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -101,13 +101,9 @@
void pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
-struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
- int, int, struct pfi_kif *,
- struct pf_addr *, u_int16_t, struct pf_addr *,
- u_int16_t, int);
int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
struct pf_addr *, struct pf_addr *, u_int16_t,
- struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
+ struct pf_addr *, u_int16_t *, u_int16_t, u_int16_t,
struct pf_src_node **);
#define mix(a,b,c) \
@@ -167,87 +163,6 @@ pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
}
}
-struct pf_rule *
-pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
- 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;
- struct pf_ruleset *ruleset = NULL;
- int tag = -1;
- int rtableid = -1;
- int asd = 0;
-
- r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
- while (r && rm == NULL) {
- struct pf_rule_addr *src = NULL, *dst = NULL;
- struct pf_addr_wrap *xdst = NULL;
-
- if (r->action == PF_BINAT && direction == PF_IN) {
- src = &r->dst;
- if (r->rpool.cur != NULL)
- xdst = &r->rpool.cur->addr;
- } else {
- src = &r->src;
- dst = &r->dst;
- }
-
- r->evaluations++;
- if (pfi_kif_match(r->kif, kif) == r->ifnot)
- r = r->skip[PF_SKIP_IFP].ptr;
- else if (r->direction && r->direction != direction)
- r = r->skip[PF_SKIP_DIR].ptr;
- else if (r->af && r->af != pd->af)
- r = r->skip[PF_SKIP_AF].ptr;
- else if (r->proto && r->proto != pd->proto)
- r = r->skip[PF_SKIP_PROTO].ptr;
- else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
- src->neg, kif))
- r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
- PF_SKIP_DST_ADDR].ptr;
- else if (src->port_op && !pf_match_port(src->port_op,
- src->port[0], src->port[1], sport))
- r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
- PF_SKIP_DST_PORT].ptr;
- else if (dst != NULL &&
- PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL))
- r = r->skip[PF_SKIP_DST_ADDR].ptr;
- else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
- 0, NULL))
- r = TAILQ_NEXT(r, entries);
- else if (dst != NULL && dst->port_op &&
- !pf_match_port(dst->port_op, dst->port[0],
- dst->port[1], dport))
- r = r->skip[PF_SKIP_DST_PORT].ptr;
- else if (r->match_tag && !pf_match_tag(m, r, &tag))
- r = TAILQ_NEXT(r, entries);
- else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
- IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
- off, pd->hdr.tcp), r->os_fingerprint)))
- r = TAILQ_NEXT(r, entries);
- else {
- if (r->tag)
- tag = r->tag;
- if (r->rtableid >= 0)
- rtableid = r->rtableid;
- if (r->anchor == NULL) {
- rm = r;
- } else
- pf_step_into_anchor(&asd, &ruleset, rs_num,
- &r, NULL, NULL);
- }
- if (r == NULL)
- pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
- NULL, NULL);
- }
- if (pf_tag_packet(m, tag, rtableid))
- return (NULL);
- if (rm != NULL && (rm->action == PF_NONAT ||
- rm->action == PF_NORDR || rm->action == PF_NOBINAT))
- return (NULL);
- return (rm);
-}
-
int
pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
@@ -259,11 +174,12 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
u_int16_t cut;
bzero(&init_addr, sizeof(init_addr));
- if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+ if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn, &r->nat))
return (1);
if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
- if (dport == ICMP6_ECHO_REQUEST || dport == ICMP_ECHO) {
+ if (dport == htons(ICMP6_ECHO_REQUEST) ||
+ dport == htons(ICMP_ECHO)) {
low = 1;
high = 65535;
} else
@@ -283,6 +199,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
*/
if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
proto == IPPROTO_ICMP)) {
+ /* XXX bug icmp states dont use the id on both sides */
key.port[0] = dport;
if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
return (0);
@@ -325,10 +242,11 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
}
}
- switch (r->rpool.opts & PF_POOL_TYPEMASK) {
+ switch (r->nat.opts & PF_POOL_TYPEMASK) {
case PF_POOL_RANDOM:
case PF_POOL_ROUNDROBIN:
- if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+ if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn,
+ &r->nat))
return (1);
break;
case PF_POOL_NONE:
@@ -343,21 +261,21 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
int
pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
- struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
+ struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn,
+ struct pf_pool *rpool)
{
unsigned char hash[16];
- struct pf_pool *rpool = &r->rpool;
struct pf_addr *raddr = &rpool->cur->addr.v.a.addr;
struct pf_addr *rmask = &rpool->cur->addr.v.a.mask;
struct pf_pooladdr *acur = rpool->cur;
struct pf_src_node k;
- if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
- (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
+ if (*sn == NULL && rpool->opts & PF_POOL_STICKYADDR &&
+ (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
k.af = af;
PF_ACPY(&k.addr, saddr, af);
if (r->rule_flag & PFRULE_RULESRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR)
+ rpool->opts & PF_POOL_STICKYADDR)
k.rule.ptr = r;
else
k.rule.ptr = NULL;
@@ -522,177 +440,57 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
return (0);
}
-struct pf_rule *
-pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
- struct pfi_kif *kif, struct pf_src_node **sn,
- struct pf_state_key **skw, struct pf_state_key **sks,
- struct pf_state_key **skp, struct pf_state_key **nkp,
- struct pf_addr *saddr, struct pf_addr *daddr,
- u_int16_t sport, u_int16_t dport)
+int
+pf_get_transaddr(struct pf_rule *r, struct pf_pdesc *pd, struct pf_addr *saddr,
+ u_int16_t *sport, struct pf_addr *daddr, u_int16_t *dport)
{
- struct pf_rule *r = NULL;
-
-
- if (direction == PF_OUT) {
- 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, kif,
- saddr, sport, daddr, dport, PF_RULESET_NAT);
- } else {
- 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, kif,
- saddr, sport, daddr, dport, PF_RULESET_BINAT);
+ struct pf_addr naddr;
+ u_int16_t nport = 0;
+
+ struct pf_src_node srcnode, *sn = &srcnode;
+
+ if (!TAILQ_EMPTY(&r->nat.list)) {
+ if (pf_get_sport(pd->af, pd->proto, r, saddr,
+ daddr, *dport, &naddr, &nport, r->nat.proxy_port[0],
+ r->nat.proxy_port[1], &sn)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: NAT proxy port allocation "
+ "(%u-%u) failed\n",
+ r->nat.proxy_port[0],
+ r->nat.proxy_port[1]));
+ return (-1);
+ }
+ PF_ACPY(saddr, &naddr, pd->af);
+ *sport = nport;
}
-
- if (r != NULL) {
- struct pf_addr *naddr;
- u_int16_t *nport;
-
- if (pf_state_key_setup(pd, r, skw, sks, skp, nkp,
- saddr, daddr, sport, dport))
- return r;
-
- /* XXX We only modify one side for now. */
- naddr = &(*nkp)->addr[1];
- nport = &(*nkp)->port[1];
-
- switch (r->action) {
- case PF_NONAT:
- case PF_NOBINAT:
- case PF_NORDR:
- return (NULL);
- case PF_NAT:
- if (pf_get_sport(pd->af, pd->proto, r, saddr,
- daddr, dport, naddr, nport, r->rpool.proxy_port[0],
- r->rpool.proxy_port[1], sn)) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: NAT proxy port allocation "
- "(%u-%u) failed\n",
- r->rpool.proxy_port[0],
- r->rpool.proxy_port[1]));
- return (NULL);
- }
- break;
- case PF_BINAT:
- switch (direction) {
- case PF_OUT:
- if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
- switch (pd->af) {
-#ifdef INET
- case 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);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- 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);
- break;
-#endif /* 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) {
- switch (pd->af) {
-#ifdef INET
- case 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);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- 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);
- break;
-#endif /* INET6 */
- }
- } else
- PF_POOLMASK(naddr,
- &r->src.addr.v.a.addr,
- &r->src.addr.v.a.mask, daddr,
- pd->af);
- break;
- }
- break;
- case PF_RDR: {
- if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
- return (NULL);
- if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
- PF_POOL_BITMASK)
- PF_POOLMASK(naddr, naddr,
- &r->rpool.cur->addr.v.a.mask, daddr,
- pd->af);
-
- if (r->rpool.proxy_port[1]) {
+ if (!TAILQ_EMPTY(&r->rdr.list)) {
+ if (pf_map_addr(pd->af, r, saddr, &naddr, NULL, &sn, &r->rdr))
+ return (-1);
+ if ((r->rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
+ PF_POOLMASK(&naddr, &naddr, &r->rdr.cur->addr.v.a.mask,
+ daddr, pd->af);
+
+ if (r->rdr.proxy_port[1]) {
u_int32_t tmp_nport;
- tmp_nport = ((ntohs(dport) -
+ tmp_nport = ((ntohs(*dport) -
ntohs(r->dst.port[0])) %
- (r->rpool.proxy_port[1] -
- r->rpool.proxy_port[0] + 1)) +
- r->rpool.proxy_port[0];
+ (r->rdr.proxy_port[1] -
+ r->rdr.proxy_port[0] + 1)) +
+ r->rdr.proxy_port[0];
/* wrap around if necessary */
if (tmp_nport > 65535)
tmp_nport -= 65535;
- *nport = htons((u_int16_t)tmp_nport);
- } else if (r->rpool.proxy_port[0])
- *nport = htons(r->rpool.proxy_port[0]);
- break;
- }
- default:
- return (NULL);
- }
- /*
- * Translation was a NOP.
- * Pretend there was no match.
- */
- if (!bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp))) {
- pool_put(&pf_state_key_pl, *nkp);
- pool_put(&pf_state_key_pl, *skp);
- *skw = *sks = *nkp = *skp = NULL;
- return (NULL);
- }
+ nport = htons((u_int16_t)tmp_nport);
+ } else if (r->rdr.proxy_port[0])
+ nport = htons(r->rdr.proxy_port[0]);
+
+ PF_ACPY(daddr, &naddr, pd->af);
+ if (nport)
+ *dport = nport;
}
- return (r);
+ return (0);
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index d9e2ade4790..5e86421708f 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.290 2009/06/25 09:30:28 sthen Exp $ */
+/* $OpenBSD: pfvar.h,v 1.291 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -541,7 +541,8 @@ struct pf_rule {
char overload_tblname[PF_TABLE_NAME_SIZE];
TAILQ_ENTRY(pf_rule) entries;
- struct pf_pool rpool;
+ struct pf_pool nat;
+ struct pf_pool rdr;
u_int64_t evaluations;
u_int64_t packets[2];
@@ -1131,8 +1132,10 @@ struct pf_pdesc {
*eh;
struct pf_addr *src; /* src address */
struct pf_addr *dst; /* dst address */
- u_int16_t *sport;
- u_int16_t *dport;
+ u_int16_t *sport;
+ u_int16_t *dport;
+ u_int16_t osport;
+ u_int16_t odport;
u_int32_t p_len; /* total length of payload */
@@ -1380,6 +1383,8 @@ struct pfioc_pooladdr {
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;
};
@@ -1626,7 +1631,7 @@ TAILQ_HEAD(pf_poolqueue, pf_pool);
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_palist pf_pabuf[2];
extern u_int32_t ticket_altqs_active;
extern u_int32_t ticket_altqs_inactive;
@@ -1860,21 +1865,19 @@ int pf_step_out_of_anchor(int *, struct pf_ruleset **,
int, struct pf_rule **, struct pf_rule **,
int *);
-int pf_map_addr(u_int8_t, struct pf_rule *,
- struct pf_addr *, struct pf_addr *,
- struct pf_addr *, struct pf_src_node **);
-struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
- int, int, struct pfi_kif *, struct pf_src_node **,
- struct pf_state_key **, struct pf_state_key **,
- struct pf_state_key **, struct pf_state_key **,
+int pf_get_transaddr(struct pf_rule *, struct pf_pdesc *,
+ struct pf_addr *, u_int16_t *, struct pf_addr *,
+ u_int16_t *);
+
+int pf_map_addr(sa_family_t, struct pf_rule *,
struct pf_addr *, struct pf_addr *,
- u_int16_t, u_int16_t);
+ struct pf_addr *, struct pf_src_node **,
+ struct pf_pool *);
-int pf_state_key_setup(struct pf_pdesc *, struct pf_rule *,
- struct pf_state_key **, struct pf_state_key **,
+int pf_state_key_setup(struct pf_pdesc *,
struct pf_state_key **, struct pf_state_key **,
- struct pf_addr *, struct pf_addr *,
- u_int16_t, u_int16_t);
+ struct pf_addr **, struct pf_addr **,
+ u_int16_t *, u_int16_t *);
#endif /* _KERNEL */