mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 01:30:30 -04:00
pf: add post-NAT src/dst address/port to pf_pdesc
stuff nsaddr/ndaddr/nsport/ndport (addrs/ports after NAT, used a lot while
walking the ruleset and up until state is fully set up) into pf_pdesc instead
of passing around those 4 seperately all the time, also shrinks the argument
count for a few functions that have/partialy had an insane count of arguments.
kinda preparational since we'll need them elsewhere too, soon
ok ryan jsing
Obtained from: OpenBSD, henning <henning@openbsd.org>, ccf63ac6cb
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D47784
This commit is contained in:
parent
e11dacbf84
commit
2d7e68d5cd
3 changed files with 176 additions and 163 deletions
|
|
@ -1600,6 +1600,9 @@ struct pf_pdesc {
|
|||
char any[0];
|
||||
} hdr;
|
||||
|
||||
struct pf_addr nsaddr; /* src address after NAT */
|
||||
struct pf_addr ndaddr; /* dst address after NAT */
|
||||
|
||||
struct pfi_kkif *kif; /* incomming interface */
|
||||
struct mbuf *m;
|
||||
|
||||
|
|
@ -1609,6 +1612,8 @@ struct pf_pdesc {
|
|||
u_int16_t *dport;
|
||||
u_int16_t osport;
|
||||
u_int16_t odport;
|
||||
u_int16_t nsport; /* src port after NAT */
|
||||
u_int16_t ndport; /* dst port after NAT */
|
||||
struct pf_mtag *pf_mtag;
|
||||
struct pf_rule_actions act;
|
||||
|
||||
|
|
@ -2644,13 +2649,11 @@ u_short pf_map_addr_sn(u_int8_t, struct pf_krule *,
|
|||
struct pf_ksrc_node **, struct pf_srchash **);
|
||||
u_short pf_get_translation(struct pf_pdesc *,
|
||||
int, struct pf_state_key **, struct pf_state_key **,
|
||||
struct pf_addr *, struct pf_addr *,
|
||||
uint16_t, uint16_t, struct pf_kanchor_stackframe *,
|
||||
struct pf_krule **,
|
||||
struct pf_kanchor_stackframe *, struct pf_krule **,
|
||||
struct pf_udp_mapping **udp_mapping);
|
||||
|
||||
struct pf_state_key *pf_state_key_setup(struct pf_pdesc *,
|
||||
struct pf_addr *, struct pf_addr *, u_int16_t, u_int16_t);
|
||||
u_int16_t, u_int16_t);
|
||||
struct pf_state_key *pf_state_key_clone(const struct pf_state_key *);
|
||||
void pf_rule_to_actions(struct pf_krule *,
|
||||
struct pf_rule_actions *);
|
||||
|
|
|
|||
|
|
@ -1653,9 +1653,7 @@ copy:
|
|||
}
|
||||
|
||||
struct pf_state_key *
|
||||
pf_state_key_setup(struct pf_pdesc *pd,
|
||||
struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t sport,
|
||||
u_int16_t dport)
|
||||
pf_state_key_setup(struct pf_pdesc *pd, u_int16_t sport, u_int16_t dport)
|
||||
{
|
||||
struct pf_state_key *sk;
|
||||
|
||||
|
|
@ -4898,8 +4896,6 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
struct pf_kruleset **rsm, struct inpcb *inp)
|
||||
{
|
||||
struct pf_krule *nr = NULL;
|
||||
struct pf_addr * const saddr = pd->src;
|
||||
struct pf_addr * const daddr = pd->dst;
|
||||
struct pf_krule *r, *a = NULL;
|
||||
struct pf_kruleset *ruleset = NULL;
|
||||
struct pf_krule_slist match_rules;
|
||||
|
|
@ -4912,7 +4908,7 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
int asd = 0;
|
||||
int match = 0;
|
||||
int state_icmp = 0, icmp_dir, multi;
|
||||
u_int16_t sport = 0, dport = 0, virtual_type, virtual_id;
|
||||
u_int16_t virtual_type, virtual_id;
|
||||
u_int16_t bproto_sum = 0, bip_sum = 0;
|
||||
u_int8_t icmptype = 0, icmpcode = 0;
|
||||
struct pf_kanchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE];
|
||||
|
|
@ -4920,6 +4916,9 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
|
||||
PF_RULES_RASSERT();
|
||||
|
||||
PF_ACPY(&pd->nsaddr, pd->src, pd->af);
|
||||
PF_ACPY(&pd->ndaddr, pd->dst, pd->af);
|
||||
|
||||
SLIST_INIT(&match_rules);
|
||||
|
||||
if (inp != NULL) {
|
||||
|
|
@ -4931,16 +4930,16 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
|
||||
switch (pd->virtual_proto) {
|
||||
case IPPROTO_TCP:
|
||||
sport = th->th_sport;
|
||||
dport = th->th_dport;
|
||||
pd->nsport = th->th_sport;
|
||||
pd->ndport = th->th_dport;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
sport = pd->hdr.udp.uh_sport;
|
||||
dport = pd->hdr.udp.uh_dport;
|
||||
pd->nsport = pd->hdr.udp.uh_sport;
|
||||
pd->ndport = pd->hdr.udp.uh_dport;
|
||||
break;
|
||||
case IPPROTO_SCTP:
|
||||
sport = pd->hdr.sctp.src_port;
|
||||
dport = pd->hdr.sctp.dest_port;
|
||||
pd->nsport = pd->hdr.sctp.src_port;
|
||||
pd->ndport = pd->hdr.sctp.dest_port;
|
||||
break;
|
||||
#ifdef INET
|
||||
case IPPROTO_ICMP:
|
||||
|
|
@ -4950,11 +4949,11 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
state_icmp = pf_icmp_mapping(pd, icmptype,
|
||||
&icmp_dir, &multi, &virtual_id, &virtual_type);
|
||||
if (icmp_dir == PF_IN) {
|
||||
sport = virtual_id;
|
||||
dport = virtual_type;
|
||||
pd->nsport = virtual_id;
|
||||
pd->ndport = virtual_type;
|
||||
} else {
|
||||
sport = virtual_type;
|
||||
dport = virtual_id;
|
||||
pd->nsport = virtual_type;
|
||||
pd->ndport = virtual_id;
|
||||
}
|
||||
break;
|
||||
#endif /* INET */
|
||||
|
|
@ -4966,27 +4965,27 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
state_icmp = pf_icmp_mapping(pd, icmptype,
|
||||
&icmp_dir, &multi, &virtual_id, &virtual_type);
|
||||
if (icmp_dir == PF_IN) {
|
||||
sport = virtual_id;
|
||||
dport = virtual_type;
|
||||
pd->nsport = virtual_id;
|
||||
pd->ndport = virtual_type;
|
||||
} else {
|
||||
sport = virtual_type;
|
||||
dport = virtual_id;
|
||||
pd->nsport = virtual_type;
|
||||
pd->ndport = virtual_id;
|
||||
}
|
||||
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
sport = dport = 0;
|
||||
pd->nsport = pd->ndport = 0;
|
||||
break;
|
||||
}
|
||||
pd->osport = sport;
|
||||
pd->odport = dport;
|
||||
pd->osport = pd->nsport;
|
||||
pd->odport = pd->ndport;
|
||||
|
||||
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
|
||||
|
||||
/* check packet for BINAT/NAT/RDR */
|
||||
transerror = pf_get_translation(pd, pd->off, &sk, &nk, saddr, daddr,
|
||||
sport, dport, anchor_stack, &nr, &udp_mapping);
|
||||
transerror = pf_get_translation(pd, pd->off, &sk, &nk, anchor_stack,
|
||||
&nr, &udp_mapping);
|
||||
switch (transerror) {
|
||||
default:
|
||||
/* A translation error occurred. */
|
||||
|
|
@ -5011,82 +5010,94 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
case IPPROTO_TCP:
|
||||
bproto_sum = th->th_sum;
|
||||
|
||||
if (PF_ANEQ(saddr, &nk->addr[pd->sidx], pd->af) ||
|
||||
nk->port[pd->sidx] != sport) {
|
||||
pf_change_ap(pd->m, saddr, &th->th_sport, pd->ip_sum,
|
||||
&th->th_sum, &nk->addr[pd->sidx],
|
||||
if (PF_ANEQ(&pd->nsaddr, &nk->addr[pd->sidx], pd->af) ||
|
||||
nk->port[pd->sidx] != pd->nsport) {
|
||||
pf_change_ap(pd->m, pd->src, &th->th_sport,
|
||||
pd->ip_sum, &th->th_sum, &nk->addr[pd->sidx],
|
||||
nk->port[pd->sidx], 0, pd->af);
|
||||
pd->sport = &th->th_sport;
|
||||
sport = th->th_sport;
|
||||
pd->nsport = th->th_sport;
|
||||
PF_ACPY(&pd->nsaddr, pd->src, pd->af);
|
||||
}
|
||||
|
||||
if (PF_ANEQ(daddr, &nk->addr[pd->didx], pd->af) ||
|
||||
nk->port[pd->didx] != dport) {
|
||||
pf_change_ap(pd->m, daddr, &th->th_dport, pd->ip_sum,
|
||||
&th->th_sum, &nk->addr[pd->didx],
|
||||
if (PF_ANEQ(&pd->ndaddr, &nk->addr[pd->didx], pd->af) ||
|
||||
nk->port[pd->didx] != pd->ndport) {
|
||||
pf_change_ap(pd->m, pd->dst, &th->th_dport,
|
||||
pd->ip_sum, &th->th_sum, &nk->addr[pd->didx],
|
||||
nk->port[pd->didx], 0, pd->af);
|
||||
dport = th->th_dport;
|
||||
pd->ndport = th->th_dport;
|
||||
pd->dport = &th->th_dport;
|
||||
PF_ACPY(&pd->ndaddr, pd->dst, pd->af);
|
||||
}
|
||||
rewrite++;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
bproto_sum = pd->hdr.udp.uh_sum;
|
||||
|
||||
if (PF_ANEQ(saddr, &nk->addr[pd->sidx], pd->af) ||
|
||||
nk->port[pd->sidx] != sport) {
|
||||
pf_change_ap(pd->m, saddr, &pd->hdr.udp.uh_sport,
|
||||
if (PF_ANEQ(&pd->nsaddr, &nk->addr[pd->sidx], pd->af) ||
|
||||
nk->port[pd->sidx] != pd->nsport) {
|
||||
pf_change_ap(pd->m, pd->src,
|
||||
&pd->hdr.udp.uh_sport,
|
||||
pd->ip_sum, &pd->hdr.udp.uh_sum,
|
||||
&nk->addr[pd->sidx],
|
||||
nk->port[pd->sidx], 1, pd->af);
|
||||
sport = pd->hdr.udp.uh_sport;
|
||||
pd->nsport = pd->hdr.udp.uh_sport;
|
||||
pd->sport = &pd->hdr.udp.uh_sport;
|
||||
PF_ACPY(&pd->nsaddr, pd->src, pd->af);
|
||||
}
|
||||
|
||||
if (PF_ANEQ(daddr, &nk->addr[pd->didx], pd->af) ||
|
||||
nk->port[pd->didx] != dport) {
|
||||
pf_change_ap(pd->m, daddr, &pd->hdr.udp.uh_dport,
|
||||
if (PF_ANEQ(&pd->ndaddr, &nk->addr[pd->didx], pd->af) ||
|
||||
nk->port[pd->didx] != pd->ndport) {
|
||||
pf_change_ap(pd->m, pd->dst,
|
||||
&pd->hdr.udp.uh_dport,
|
||||
pd->ip_sum, &pd->hdr.udp.uh_sum,
|
||||
&nk->addr[pd->didx],
|
||||
nk->port[pd->didx], 1, pd->af);
|
||||
dport = pd->hdr.udp.uh_dport;
|
||||
pd->ndport = pd->hdr.udp.uh_dport;
|
||||
pd->dport = &pd->hdr.udp.uh_dport;
|
||||
PF_ACPY(&pd->ndaddr, pd->dst, pd->af);
|
||||
}
|
||||
rewrite++;
|
||||
break;
|
||||
case IPPROTO_SCTP: {
|
||||
uint16_t checksum = 0;
|
||||
|
||||
if (PF_ANEQ(saddr, &nk->addr[pd->sidx], pd->af) ||
|
||||
nk->port[pd->sidx] != sport) {
|
||||
pf_change_ap(pd->m, saddr, &pd->hdr.sctp.src_port,
|
||||
pd->ip_sum, &checksum,
|
||||
if (PF_ANEQ(&pd->nsaddr, &nk->addr[pd->sidx], pd->af) ||
|
||||
nk->port[pd->sidx] != pd->nsport) {
|
||||
pf_change_ap(pd->m, pd->src,
|
||||
&pd->hdr.sctp.src_port, pd->ip_sum, &checksum,
|
||||
&nk->addr[pd->sidx],
|
||||
nk->port[pd->sidx], 1, pd->af);
|
||||
PF_ACPY(&pd->nsaddr, pd->src, pd->af);
|
||||
}
|
||||
if (PF_ANEQ(daddr, &nk->addr[pd->didx], pd->af) ||
|
||||
nk->port[pd->didx] != dport) {
|
||||
pf_change_ap(pd->m, daddr, &pd->hdr.sctp.dest_port,
|
||||
pd->ip_sum, &checksum,
|
||||
if (PF_ANEQ(&pd->ndaddr, &nk->addr[pd->didx], pd->af) ||
|
||||
nk->port[pd->didx] != pd->ndport) {
|
||||
pf_change_ap(pd->m, pd->dst,
|
||||
&pd->hdr.sctp.dest_port, pd->ip_sum, &checksum,
|
||||
&nk->addr[pd->didx],
|
||||
nk->port[pd->didx], 1, pd->af);
|
||||
PF_ACPY(&pd->ndaddr, pd->dst, pd->af);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef INET
|
||||
case IPPROTO_ICMP:
|
||||
if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET))
|
||||
pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
|
||||
if (PF_ANEQ(&pd->nsaddr, &nk->addr[pd->sidx], AF_INET)) {
|
||||
pf_change_a(&pd->src->v4.s_addr, pd->ip_sum,
|
||||
nk->addr[pd->sidx].v4.s_addr, 0);
|
||||
PF_ACPY(&pd->nsaddr, pd->src, pd->af);
|
||||
}
|
||||
|
||||
if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET))
|
||||
pf_change_a(&daddr->v4.s_addr, pd->ip_sum,
|
||||
if (PF_ANEQ(&pd->ndaddr, &nk->addr[pd->didx], AF_INET)) {
|
||||
pf_change_a(&pd->dst->v4.s_addr, pd->ip_sum,
|
||||
nk->addr[pd->didx].v4.s_addr, 0);
|
||||
PF_ACPY(&pd->ndaddr, pd->dst, pd->af);
|
||||
}
|
||||
|
||||
if (virtual_type == htons(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,
|
||||
pd->hdr.icmp.icmp_cksum, pd->nsport,
|
||||
nk->port[pd->sidx], 0);
|
||||
pd->hdr.icmp.icmp_id = nk->port[pd->sidx];
|
||||
pd->sport = &pd->hdr.icmp.icmp_id;
|
||||
|
|
@ -5096,13 +5107,17 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case IPPROTO_ICMPV6:
|
||||
if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET6))
|
||||
pf_change_a6(saddr, &pd->hdr.icmp6.icmp6_cksum,
|
||||
if (PF_ANEQ(&pd->nsaddr, &nk->addr[pd->sidx], AF_INET6)) {
|
||||
pf_change_a6(pd->src, &pd->hdr.icmp6.icmp6_cksum,
|
||||
&nk->addr[pd->sidx], 0);
|
||||
PF_ACPY(&pd->nsaddr, pd->src, pd->af);
|
||||
}
|
||||
|
||||
if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET6))
|
||||
pf_change_a6(daddr, &pd->hdr.icmp6.icmp6_cksum,
|
||||
if (PF_ANEQ(&pd->ndaddr, &nk->addr[pd->didx], AF_INET6)) {
|
||||
pf_change_a6(pd->dst, &pd->hdr.icmp6.icmp6_cksum,
|
||||
&nk->addr[pd->didx], 0);
|
||||
PF_ACPY(&pd->ndaddr, pd->dst, pd->af);
|
||||
}
|
||||
rewrite++;
|
||||
break;
|
||||
#endif /* INET */
|
||||
|
|
@ -5110,28 +5125,36 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
switch (pd->af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (PF_ANEQ(saddr,
|
||||
&nk->addr[pd->sidx], AF_INET))
|
||||
pf_change_a(&saddr->v4.s_addr,
|
||||
if (PF_ANEQ(&pd->nsaddr,
|
||||
&nk->addr[pd->sidx], AF_INET)) {
|
||||
pf_change_a(&pd->src->v4.s_addr,
|
||||
pd->ip_sum,
|
||||
nk->addr[pd->sidx].v4.s_addr, 0);
|
||||
PF_ACPY(&pd->nsaddr, pd->src, pd->af);
|
||||
}
|
||||
|
||||
if (PF_ANEQ(daddr,
|
||||
&nk->addr[pd->didx], AF_INET))
|
||||
pf_change_a(&daddr->v4.s_addr,
|
||||
if (PF_ANEQ(&pd->ndaddr,
|
||||
&nk->addr[pd->didx], AF_INET)) {
|
||||
pf_change_a(&pd->dst->v4.s_addr,
|
||||
pd->ip_sum,
|
||||
nk->addr[pd->didx].v4.s_addr, 0);
|
||||
PF_ACPY(&pd->ndaddr, pd->dst, pd->af);
|
||||
}
|
||||
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], pd->af);
|
||||
if (PF_ANEQ(&pd->nsaddr,
|
||||
&nk->addr[pd->sidx], AF_INET6)) {
|
||||
PF_ACPY(&pd->nsaddr, &nk->addr[pd->sidx], pd->af);
|
||||
PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af);
|
||||
}
|
||||
|
||||
if (PF_ANEQ(daddr,
|
||||
&nk->addr[pd->didx], AF_INET6))
|
||||
PF_ACPY(daddr, &nk->addr[pd->didx], pd->af);
|
||||
if (PF_ANEQ(&pd->ndaddr,
|
||||
&nk->addr[pd->didx], AF_INET6)) {
|
||||
PF_ACPY(&pd->ndaddr, &nk->addr[pd->didx], pd->af);
|
||||
PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af);
|
||||
}
|
||||
break;
|
||||
#endif /* INET */
|
||||
}
|
||||
|
|
@ -5151,10 +5174,10 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
r->skip[PF_SKIP_AF]);
|
||||
PF_TEST_ATTRIB(r->proto && r->proto != pd->proto,
|
||||
r->skip[PF_SKIP_PROTO]);
|
||||
PF_TEST_ATTRIB(PF_MISMATCHAW(&r->src.addr, saddr, pd->af,
|
||||
PF_TEST_ATTRIB(PF_MISMATCHAW(&r->src.addr, &pd->nsaddr, pd->af,
|
||||
r->src.neg, pd->kif, M_GETFIB(pd->m)),
|
||||
r->skip[PF_SKIP_SRC_ADDR]);
|
||||
PF_TEST_ATTRIB(PF_MISMATCHAW(&r->dst.addr, daddr, pd->af,
|
||||
PF_TEST_ATTRIB(PF_MISMATCHAW(&r->dst.addr, &pd->ndaddr, pd->af,
|
||||
r->dst.neg, NULL, M_GETFIB(pd->m)),
|
||||
r->skip[PF_SKIP_DST_ADDR]);
|
||||
switch (pd->virtual_proto) {
|
||||
|
|
@ -5180,11 +5203,11 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
|
|||
case IPPROTO_UDP:
|
||||
/* tcp/udp only. port_op always 0 in other cases */
|
||||
PF_TEST_ATTRIB(r->src.port_op && !pf_match_port(r->src.port_op,
|
||||
r->src.port[0], r->src.port[1], sport),
|
||||
r->src.port[0], r->src.port[1], pd->nsport),
|
||||
r->skip[PF_SKIP_SRC_PORT]);
|
||||
/* tcp/udp only. port_op always 0 in other cases */
|
||||
PF_TEST_ATTRIB(r->dst.port_op && !pf_match_port(r->dst.port_op,
|
||||
r->dst.port[0], r->dst.port[1], dport),
|
||||
r->dst.port[0], r->dst.port[1], pd->ndport),
|
||||
r->skip[PF_SKIP_DST_PORT]);
|
||||
/* tcp/udp only. uid.op always 0 in other cases */
|
||||
PF_TEST_ATTRIB(r->uid.op && (pd->lookup.done || (pd->lookup.done =
|
||||
|
|
@ -5539,7 +5562,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
|
|||
__func__, nr, sk, nk));
|
||||
MPASS(pd->sport == NULL || (pd->osport == *pd->sport));
|
||||
MPASS(pd->dport == NULL || (pd->odport == *pd->dport));
|
||||
sk = pf_state_key_setup(pd, pd->src, pd->dst, pd->osport, pd->odport);
|
||||
sk = pf_state_key_setup(pd, pd->osport, pd->odport);
|
||||
if (sk == NULL)
|
||||
goto csfailed;
|
||||
nk = sk;
|
||||
|
|
|
|||
|
|
@ -64,13 +64,10 @@ VNET_DEFINE_STATIC(int, pf_rdr_srcport_rewrite_tries) = 16;
|
|||
static void pf_hash(struct pf_addr *, struct pf_addr *,
|
||||
struct pf_poolhashkey *, sa_family_t);
|
||||
static struct pf_krule *pf_match_translation(struct pf_pdesc *,
|
||||
struct pf_addr *, u_int16_t,
|
||||
struct pf_addr *, uint16_t, int,
|
||||
struct pf_kanchor_stackframe *);
|
||||
static int pf_get_sport(sa_family_t, uint8_t, struct pf_krule *,
|
||||
struct pf_addr *, uint16_t, struct pf_addr *, uint16_t, struct pf_addr *,
|
||||
uint16_t *, uint16_t, uint16_t, struct pf_ksrc_node **, struct pf_srchash**,
|
||||
struct pf_udp_mapping **);
|
||||
int, struct pf_kanchor_stackframe *);
|
||||
static int pf_get_sport(struct pf_pdesc *, struct pf_krule *,
|
||||
struct pf_addr *, uint16_t *, uint16_t, uint16_t, struct pf_ksrc_node **,
|
||||
struct pf_srchash **, struct pf_udp_mapping **);
|
||||
static bool pf_islinklocal(const sa_family_t, const struct pf_addr *);
|
||||
|
||||
#define mix(a,b,c) \
|
||||
|
|
@ -132,9 +129,7 @@ pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
|
|||
|
||||
static struct pf_krule *
|
||||
pf_match_translation(struct pf_pdesc *pd,
|
||||
struct pf_addr *saddr, u_int16_t sport,
|
||||
struct pf_addr *daddr, uint16_t dport, int rs_num,
|
||||
struct pf_kanchor_stackframe *anchor_stack)
|
||||
int rs_num, struct pf_kanchor_stackframe *anchor_stack)
|
||||
{
|
||||
struct pf_krule *r, *rm = NULL;
|
||||
struct pf_kruleset *ruleset = NULL;
|
||||
|
|
@ -165,24 +160,24 @@ pf_match_translation(struct pf_pdesc *pd,
|
|||
r = r->skip[PF_SKIP_AF];
|
||||
else if (r->proto && r->proto != pd->proto)
|
||||
r = r->skip[PF_SKIP_PROTO];
|
||||
else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
|
||||
else if (PF_MISMATCHAW(&src->addr, &pd->nsaddr, pd->af,
|
||||
src->neg, pd->kif, M_GETFIB(pd->m)))
|
||||
r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
|
||||
PF_SKIP_DST_ADDR];
|
||||
else if (src->port_op && !pf_match_port(src->port_op,
|
||||
src->port[0], src->port[1], sport))
|
||||
src->port[0], src->port[1], pd->nsport))
|
||||
r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
|
||||
PF_SKIP_DST_PORT];
|
||||
else if (dst != NULL &&
|
||||
PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL,
|
||||
PF_MISMATCHAW(&dst->addr, &pd->ndaddr, pd->af, dst->neg, NULL,
|
||||
M_GETFIB(pd->m)))
|
||||
r = r->skip[PF_SKIP_DST_ADDR];
|
||||
else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
|
||||
else if (xdst != NULL && PF_MISMATCHAW(xdst, &pd->ndaddr, pd->af,
|
||||
0, NULL, M_GETFIB(pd->m)))
|
||||
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))
|
||||
dst->port[1], pd->ndport))
|
||||
r = r->skip[PF_SKIP_DST_PORT];
|
||||
else if (r->match_tag && !pf_match_tag(pd->m, r, &tag,
|
||||
pd->pf_mtag ? pd->pf_mtag->tag : 0))
|
||||
|
|
@ -222,11 +217,10 @@ pf_match_translation(struct pf_pdesc *pd,
|
|||
}
|
||||
|
||||
static int
|
||||
pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
||||
struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
|
||||
uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low,
|
||||
uint16_t high, struct pf_ksrc_node **sn, struct pf_srchash **sh,
|
||||
struct pf_udp_mapping **udp_mapping)
|
||||
pf_get_sport(struct pf_pdesc *pd, struct pf_krule *r,
|
||||
struct pf_addr *naddr, uint16_t *nport, uint16_t low,
|
||||
uint16_t high, struct pf_ksrc_node **sn,
|
||||
struct pf_srchash **sh, struct pf_udp_mapping **udp_mapping)
|
||||
{
|
||||
struct pf_state_key_cmp key;
|
||||
struct pf_addr init_addr;
|
||||
|
|
@ -240,35 +234,36 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
|||
* from the mapping. In this case we have to look up the src_node as
|
||||
* pf_map_addr would.
|
||||
*/
|
||||
if (proto == IPPROTO_UDP && (r->rdr.opts & PF_POOL_ENDPI)) {
|
||||
if (pd->proto == IPPROTO_UDP && (r->rdr.opts & PF_POOL_ENDPI)) {
|
||||
struct pf_udp_endpoint_cmp udp_source;
|
||||
|
||||
bzero(&udp_source, sizeof(udp_source));
|
||||
udp_source.af = af;
|
||||
PF_ACPY(&udp_source.addr, saddr, af);
|
||||
udp_source.port = sport;
|
||||
udp_source.af = pd->af;
|
||||
PF_ACPY(&udp_source.addr, &pd->nsaddr, pd->af);
|
||||
udp_source.port = pd->nsport;
|
||||
*udp_mapping = pf_udp_mapping_find(&udp_source);
|
||||
if (*udp_mapping) {
|
||||
PF_ACPY(naddr, &(*udp_mapping)->endpoints[1].addr, af);
|
||||
PF_ACPY(naddr, &(*udp_mapping)->endpoints[1].addr, pd->af);
|
||||
*nport = (*udp_mapping)->endpoints[1].port;
|
||||
/* Try to find a src_node as per pf_map_addr(). */
|
||||
if (*sn == NULL && r->rdr.opts & PF_POOL_STICKYADDR &&
|
||||
(r->rdr.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE)
|
||||
*sn = pf_find_src_node(saddr, r, af, sh, false);
|
||||
*sn = pf_find_src_node(&pd->nsaddr, r, pd->af, sh, false);
|
||||
if (*sn != NULL)
|
||||
PF_SRC_NODE_UNLOCK(*sn);
|
||||
return (0);
|
||||
} else {
|
||||
*udp_mapping = pf_udp_mapping_create(af, saddr, sport, &init_addr, 0);
|
||||
*udp_mapping = pf_udp_mapping_create(pd->af, &pd->nsaddr,
|
||||
pd->nsport, &init_addr, 0);
|
||||
if (*udp_mapping == NULL)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (pf_map_addr_sn(af, r, saddr, naddr, NULL, &init_addr, sn, sh))
|
||||
if (pf_map_addr_sn(pd->af, r, &pd->nsaddr, naddr, NULL, &init_addr, sn, sh))
|
||||
goto failed;
|
||||
|
||||
if (proto == IPPROTO_ICMP) {
|
||||
if (pd->proto == IPPROTO_ICMP) {
|
||||
if (*nport == htons(ICMP_ECHO)) {
|
||||
low = 1;
|
||||
high = 65535;
|
||||
|
|
@ -276,7 +271,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
|||
return (0); /* Don't try to modify non-echo ICMP */
|
||||
}
|
||||
#ifdef INET6
|
||||
if (proto == IPPROTO_ICMPV6) {
|
||||
if (pd->proto == IPPROTO_ICMPV6) {
|
||||
if (*nport == htons(ICMP6_ECHO_REQUEST)) {
|
||||
low = 1;
|
||||
high = 65535;
|
||||
|
|
@ -286,37 +281,37 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
|||
#endif /* INET6 */
|
||||
|
||||
bzero(&key, sizeof(key));
|
||||
key.af = af;
|
||||
key.proto = proto;
|
||||
key.port[0] = dport;
|
||||
PF_ACPY(&key.addr[0], daddr, key.af);
|
||||
key.af = pd->af;
|
||||
key.proto = pd->proto;
|
||||
key.port[0] = pd->ndport;
|
||||
PF_ACPY(&key.addr[0], &pd->ndaddr, key.af);
|
||||
|
||||
do {
|
||||
PF_ACPY(&key.addr[1], naddr, key.af);
|
||||
if (*udp_mapping)
|
||||
PF_ACPY(&(*udp_mapping)->endpoints[1].addr, naddr, af);
|
||||
PF_ACPY(&(*udp_mapping)->endpoints[1].addr, naddr, pd->af);
|
||||
|
||||
/*
|
||||
* port search; start random, step;
|
||||
* similar 2 portloop in in_pcbbind
|
||||
*/
|
||||
if (proto == IPPROTO_SCTP) {
|
||||
key.port[1] = sport;
|
||||
if (pd->proto == IPPROTO_SCTP) {
|
||||
key.port[1] = pd->nsport;
|
||||
if (!pf_find_state_all_exists(&key, PF_IN)) {
|
||||
*nport = sport;
|
||||
*nport = pd->nsport;
|
||||
return (0);
|
||||
} else {
|
||||
return (1); /* Fail mapping. */
|
||||
}
|
||||
} else if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
|
||||
proto == IPPROTO_ICMP) || (low == 0 && high == 0)) {
|
||||
} else if (!(pd->proto == IPPROTO_TCP || pd->proto == IPPROTO_UDP ||
|
||||
pd->proto == IPPROTO_ICMP) || (low == 0 && high == 0)) {
|
||||
/*
|
||||
* XXX bug: icmp states don't use the id on both sides.
|
||||
* (traceroute -I through nat)
|
||||
*/
|
||||
key.port[1] = sport;
|
||||
key.port[1] = pd->nsport;
|
||||
if (!pf_find_state_all_exists(&key, PF_IN)) {
|
||||
*nport = sport;
|
||||
*nport = pd->nsport;
|
||||
return (0);
|
||||
}
|
||||
} else if (low == high) {
|
||||
|
|
@ -362,7 +357,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
|||
}
|
||||
tmp = cut;
|
||||
for (tmp -= 1; tmp >= low && tmp <= 0xffff; --tmp) {
|
||||
if (proto == IPPROTO_UDP &&
|
||||
if (pd->proto == IPPROTO_UDP &&
|
||||
(r->rdr.opts & PF_POOL_ENDPI)) {
|
||||
(*udp_mapping)->endpoints[1].port = htons(tmp);
|
||||
if (pf_udp_mapping_insert(*udp_mapping) == 0) {
|
||||
|
|
@ -387,7 +382,8 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
|||
* of free port choices for the current one.
|
||||
*/
|
||||
(*sn) = NULL;
|
||||
if (pf_map_addr_sn(af, r, saddr, naddr, NULL, &init_addr, sn, sh))
|
||||
if (pf_map_addr_sn(pd->af, r, &pd->nsaddr, naddr, NULL,
|
||||
&init_addr, sn, sh))
|
||||
return (1);
|
||||
break;
|
||||
case PF_POOL_NONE:
|
||||
|
|
@ -396,7 +392,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
|||
default:
|
||||
return (1);
|
||||
}
|
||||
} while (! PF_AEQ(&init_addr, naddr, af) );
|
||||
} while (! PF_AEQ(&init_addr, naddr, pd->af) );
|
||||
|
||||
failed:
|
||||
uma_zfree(V_pf_udp_mapping_z, *udp_mapping);
|
||||
|
|
@ -413,9 +409,8 @@ pf_islinklocal(const sa_family_t af, const struct pf_addr *addr)
|
|||
}
|
||||
|
||||
static int
|
||||
pf_get_mape_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
||||
struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
|
||||
uint16_t dport, struct pf_addr *naddr, uint16_t *nport,
|
||||
pf_get_mape_sport(struct pf_pdesc *pd, struct pf_krule *r,
|
||||
struct pf_addr *naddr, uint16_t *nport,
|
||||
struct pf_ksrc_node **sn, struct pf_srchash **sh,
|
||||
struct pf_udp_mapping **udp_mapping)
|
||||
{
|
||||
|
|
@ -436,13 +431,13 @@ pf_get_mape_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
|
|||
|
||||
for (i = cut; i <= ahigh; i++) {
|
||||
low = (i << ashift) | psmask;
|
||||
if (!pf_get_sport(af, proto, r, saddr, sport, daddr, dport,
|
||||
if (!pf_get_sport(pd, r,
|
||||
naddr, nport, low, low | highmask, sn, sh, udp_mapping))
|
||||
return (0);
|
||||
}
|
||||
for (i = cut - 1; i > 0; i--) {
|
||||
low = (i << ashift) | psmask;
|
||||
if (!pf_get_sport(af, proto, r, saddr, sport, daddr, dport,
|
||||
if (!pf_get_sport(pd, r,
|
||||
naddr, nport, low, low | highmask, sn, sh, udp_mapping))
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -699,8 +694,7 @@ done:
|
|||
|
||||
u_short
|
||||
pf_get_translation(struct pf_pdesc *pd, int off,
|
||||
struct pf_state_key **skp, struct pf_state_key **nkp, struct pf_addr *saddr,
|
||||
struct pf_addr *daddr, uint16_t sport, uint16_t dport,
|
||||
struct pf_state_key **skp, struct pf_state_key **nkp,
|
||||
struct pf_kanchor_stackframe *anchor_stack, struct pf_krule **rp,
|
||||
struct pf_udp_mapping **udp_mapping)
|
||||
{
|
||||
|
|
@ -719,19 +713,13 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
*rp = NULL;
|
||||
|
||||
if (pd->dir == PF_OUT) {
|
||||
r = pf_match_translation(pd, saddr,
|
||||
sport, daddr, dport, PF_RULESET_BINAT, anchor_stack);
|
||||
r = pf_match_translation(pd, PF_RULESET_BINAT, anchor_stack);
|
||||
if (r == NULL)
|
||||
r = pf_match_translation(pd,
|
||||
saddr, sport, daddr, dport, PF_RULESET_NAT,
|
||||
anchor_stack);
|
||||
r = pf_match_translation(pd, PF_RULESET_NAT, anchor_stack);
|
||||
} else {
|
||||
r = pf_match_translation(pd, saddr,
|
||||
sport, daddr, dport, PF_RULESET_RDR, anchor_stack);
|
||||
r = pf_match_translation(pd, PF_RULESET_RDR, anchor_stack);
|
||||
if (r == NULL)
|
||||
r = pf_match_translation(pd,
|
||||
saddr, sport, daddr, dport, PF_RULESET_BINAT,
|
||||
anchor_stack);
|
||||
r = pf_match_translation(pd, PF_RULESET_BINAT, anchor_stack);
|
||||
}
|
||||
|
||||
if (r == NULL)
|
||||
|
|
@ -744,7 +732,7 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
return (PFRES_MAX);
|
||||
}
|
||||
|
||||
*skp = pf_state_key_setup(pd, saddr, daddr, sport, dport);
|
||||
*skp = pf_state_key_setup(pd, pd->nsport, pd->ndport);
|
||||
if (*skp == NULL)
|
||||
return (PFRES_MEMORY);
|
||||
*nkp = pf_state_key_clone(*skp);
|
||||
|
|
@ -767,9 +755,8 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
high = r->rdr.proxy_port[1];
|
||||
}
|
||||
if (r->rdr.mape.offset > 0) {
|
||||
if (pf_get_mape_sport(pd->af, pd->proto, r, saddr,
|
||||
sport, daddr, dport, naddr, nportp, &sn, &sh,
|
||||
udp_mapping)) {
|
||||
if (pf_get_mape_sport(pd, r, naddr, nportp, &sn,
|
||||
&sh, udp_mapping)) {
|
||||
DPFPRINTF(PF_DEBUG_MISC,
|
||||
("pf: MAP-E port allocation (%u/%u/%u)"
|
||||
" failed\n",
|
||||
|
|
@ -779,9 +766,8 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
reason = PFRES_MAPFAILED;
|
||||
goto notrans;
|
||||
}
|
||||
} else if (pf_get_sport(pd->af, pd->proto, r, saddr, sport,
|
||||
daddr, dport, naddr, nportp, low, high, &sn, &sh,
|
||||
udp_mapping)) {
|
||||
} else if (pf_get_sport(pd, r, naddr, nportp, low, high, &sn,
|
||||
&sh, udp_mapping)) {
|
||||
DPFPRINTF(PF_DEBUG_MISC,
|
||||
("pf: NAT proxy port allocation (%u-%u) failed\n",
|
||||
r->rdr.proxy_port[0], r->rdr.proxy_port[1]));
|
||||
|
|
@ -805,7 +791,7 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
&r->rdr.cur->addr.p.dyn->
|
||||
pfid_addr4,
|
||||
&r->rdr.cur->addr.p.dyn->
|
||||
pfid_mask4, saddr, AF_INET);
|
||||
pfid_mask4, &pd->nsaddr, AF_INET);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
|
|
@ -819,14 +805,14 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
&r->rdr.cur->addr.p.dyn->
|
||||
pfid_addr6,
|
||||
&r->rdr.cur->addr.p.dyn->
|
||||
pfid_mask6, saddr, AF_INET6);
|
||||
pfid_mask6, &pd->nsaddr, AF_INET6);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
} else
|
||||
PF_POOLMASK(naddr,
|
||||
&r->rdr.cur->addr.v.a.addr,
|
||||
&r->rdr.cur->addr.v.a.mask, saddr,
|
||||
&r->rdr.cur->addr.v.a.mask, &pd->nsaddr,
|
||||
pd->af);
|
||||
break;
|
||||
case PF_IN:
|
||||
|
|
@ -841,7 +827,7 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
PF_POOLMASK(naddr,
|
||||
&r->src.addr.p.dyn->pfid_addr4,
|
||||
&r->src.addr.p.dyn->pfid_mask4,
|
||||
daddr, AF_INET);
|
||||
&pd->ndaddr, AF_INET);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
|
|
@ -853,13 +839,13 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
PF_POOLMASK(naddr,
|
||||
&r->src.addr.p.dyn->pfid_addr6,
|
||||
&r->src.addr.p.dyn->pfid_mask6,
|
||||
daddr, AF_INET6);
|
||||
&pd->ndaddr, AF_INET6);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
} else
|
||||
PF_POOLMASK(naddr, &r->src.addr.v.a.addr,
|
||||
&r->src.addr.v.a.mask, daddr, pd->af);
|
||||
&r->src.addr.v.a.mask, &pd->ndaddr, pd->af);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -868,12 +854,13 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
int tries;
|
||||
uint16_t cut, low, high, nport;
|
||||
|
||||
reason = pf_map_addr_sn(pd->af, r, saddr, naddr, NULL, NULL, &sn, &sh);
|
||||
reason = pf_map_addr_sn(pd->af, r, &pd->nsaddr, naddr, NULL,
|
||||
NULL, &sn, &sh);
|
||||
if (reason != 0)
|
||||
goto notrans;
|
||||
if ((r->rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
|
||||
PF_POOLMASK(naddr, naddr, &r->rdr.cur->addr.v.a.mask,
|
||||
daddr, pd->af);
|
||||
&pd->ndaddr, pd->af);
|
||||
|
||||
/* Do not change SCTP ports. */
|
||||
if (pd->proto == IPPROTO_SCTP)
|
||||
|
|
@ -882,7 +869,7 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
if (r->rdr.proxy_port[1]) {
|
||||
uint32_t tmp_nport;
|
||||
|
||||
tmp_nport = ((ntohs(dport) - ntohs(r->dst.port[0])) %
|
||||
tmp_nport = ((ntohs(pd->ndport) - ntohs(r->dst.port[0])) %
|
||||
(r->rdr.proxy_port[1] - r->rdr.proxy_port[0] +
|
||||
1)) + r->rdr.proxy_port[0];
|
||||
|
||||
|
|
@ -893,7 +880,7 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
} else if (r->rdr.proxy_port[0])
|
||||
nport = htons(r->rdr.proxy_port[0]);
|
||||
else
|
||||
nport = dport;
|
||||
nport = pd->ndport;
|
||||
|
||||
/*
|
||||
* Update the destination port.
|
||||
|
|
@ -909,8 +896,8 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
bzero(&key, sizeof(key));
|
||||
key.af = pd->af;
|
||||
key.proto = pd->proto;
|
||||
key.port[0] = sport;
|
||||
PF_ACPY(&key.addr[0], saddr, key.af);
|
||||
key.port[0] = pd->nsport;
|
||||
PF_ACPY(&key.addr[0], &pd->nsaddr, key.af);
|
||||
key.port[1] = nport;
|
||||
PF_ACPY(&key.addr[1], naddr, key.af);
|
||||
|
||||
|
|
@ -957,7 +944,7 @@ pf_get_translation(struct pf_pdesc *pd, int off,
|
|||
out:
|
||||
DPFPRINTF(PF_DEBUG_MISC,
|
||||
("pf: RDR source port allocation %u->%u\n",
|
||||
ntohs(sport), ntohs((*nkp)->port[0])));
|
||||
ntohs(pd->nsport), ntohs((*nkp)->port[0])));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
Loading…
Reference in a new issue