summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2005-08-22 11:54:26 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2005-08-22 11:54:26 +0000
commite13f67d7920a6cc99092b952bd01767a26721734 (patch)
treecdf2ca82d708cb0c68586ba76f6c890bde3bc01f /sys/net/pf.c
parent1354a37d6c1247688efcbc8d3076b7df6bb75c4b (diff)
when nat'ing icmp 'connections', replace icmp id with proxy values
(similar to proxy ports for tcp/udp). not all clients use per-invokation random ids, this allows multiple concurrent connections from such clients. thanks for testing to Rod Whitworth, "looks ok" markus@
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c78
1 files changed, 56 insertions, 22 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 511cc49f6d9..bdf1480471d 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.501 2005/08/22 09:48:05 dhartmei Exp $ */
+/* $OpenBSD: pf.c,v 1.502 2005/08/22 11:54:25 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -2161,6 +2161,11 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
return (1);
+ if (proto == IPPROTO_ICMP) {
+ low = 1;
+ high = 65535;
+ }
+
do {
key.af = af;
key.proto = proto;
@@ -2172,7 +2177,8 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
* port search; start random, step;
* similar 2 portloop in in_pcbbind
*/
- if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP)) {
+ if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
+ proto == IPPROTO_ICMP)) {
key.gwy.port = dport;
if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
return (0);
@@ -3353,7 +3359,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pf_ruleset *ruleset = NULL;
struct pf_src_node *nsn = NULL;
u_short reason;
- u_int16_t icmpid;
+ u_int16_t icmpid, bport, nport = 0;
sa_family_t af = pd->af;
u_int8_t icmptype, icmpcode;
int state_icmp = 0;
@@ -3402,15 +3408,21 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
if (direction == PF_OUT) {
+ bport = nport = icmpid;
/* check outgoing packet for BINAT/NAT */
if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
- saddr, icmpid, daddr, icmpid, &pd->naddr, NULL)) != NULL) {
+ saddr, icmpid, daddr, icmpid, &pd->naddr, &nport)) !=
+ NULL) {
PF_ACPY(&pd->baddr, saddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
pd->naddr.v4.s_addr, 0);
+ pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum, icmpid, nport, 0);
+ pd->hdr.icmp->icmp_id = nport;
+ m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
break;
#endif /* INET */
#ifdef INET6
@@ -3426,9 +3438,11 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
pd->nat_rule = nr;
}
} else {
+ bport = nport = icmpid;
/* check incoming packet for BINAT/RDR */
if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
- saddr, icmpid, daddr, icmpid, &pd->naddr, NULL)) != NULL) {
+ saddr, icmpid, daddr, icmpid, &pd->naddr, &nport)) !=
+ NULL) {
PF_ACPY(&pd->baddr, daddr, af);
switch (af) {
#ifdef INET
@@ -3580,24 +3594,28 @@ cleanup:
s->af = af;
if (direction == PF_OUT) {
PF_ACPY(&s->gwy.addr, saddr, af);
- s->gwy.port = icmpid;
+ s->gwy.port = nport;
PF_ACPY(&s->ext.addr, daddr, af);
- s->ext.port = icmpid;
- if (nr != NULL)
+ s->ext.port = 0;
+ if (nr != NULL) {
PF_ACPY(&s->lan.addr, &pd->baddr, af);
- else
+ s->lan.port = bport;
+ } else {
PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
- s->lan.port = icmpid;
+ s->lan.port = s->gwy.port;
+ }
} else {
PF_ACPY(&s->lan.addr, daddr, af);
- s->lan.port = icmpid;
+ s->lan.port = nport;
PF_ACPY(&s->ext.addr, saddr, af);
- s->ext.port = icmpid;
- if (nr != NULL)
+ s->ext.port = 0;
+ if (nr != NULL) {
PF_ACPY(&s->gwy.addr, &pd->baddr, af);
- else
+ s->gwy.port = bport;
+ } else {
PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
- s->gwy.port = icmpid;
+ s->gwy.port = s->lan.port;
+ }
}
s->creation = time_second;
s->expire = time_second;
@@ -4527,13 +4545,13 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
if (direction == PF_IN) {
PF_ACPY(&key.ext.addr, pd->src, key.af);
PF_ACPY(&key.gwy.addr, pd->dst, key.af);
- key.ext.port = icmpid;
+ key.ext.port = 0;
key.gwy.port = icmpid;
} else {
PF_ACPY(&key.lan.addr, pd->src, key.af);
PF_ACPY(&key.ext.addr, pd->dst, key.af);
key.lan.port = icmpid;
- key.ext.port = icmpid;
+ key.ext.port = 0;
}
STATE_LOOKUP();
@@ -4542,7 +4560,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
(*state)->timeout = PFTM_ICMP_ERROR_REPLY;
/* translate source/destination address, if necessary */
- if (PF_ANEQ(&(*state)->lan.addr, &(*state)->gwy.addr, pd->af)) {
+ if (STATE_TRANSLATE(*state)) {
if (direction == PF_OUT) {
switch (pd->af) {
#ifdef INET
@@ -4550,6 +4568,14 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
pf_change_a(&saddr->v4.s_addr,
pd->ip_sum,
(*state)->gwy.addr.v4.s_addr, 0);
+ pd->hdr.icmp->icmp_cksum =
+ pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum, icmpid,
+ (*state)->gwy.port, 0);
+ pd->hdr.icmp->icmp_id =
+ (*state)->gwy.port;
+ m_copyback(m, off, ICMP_MINLEN,
+ pd->hdr.icmp);
break;
#endif /* INET */
#ifdef INET6
@@ -4570,6 +4596,14 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
pf_change_a(&daddr->v4.s_addr,
pd->ip_sum,
(*state)->lan.addr.v4.s_addr, 0);
+ pd->hdr.icmp->icmp_cksum =
+ pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum, icmpid,
+ (*state)->lan.port, 0);
+ pd->hdr.icmp->icmp_id =
+ (*state)->lan.port;
+ m_copyback(m, off, ICMP_MINLEN,
+ pd->hdr.icmp);
break;
#endif /* INET */
#ifdef INET6
@@ -4893,13 +4927,13 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
if (direction == PF_IN) {
PF_ACPY(&key.ext.addr, pd2.dst, key.af);
PF_ACPY(&key.gwy.addr, pd2.src, key.af);
- key.ext.port = iih.icmp_id;
+ key.ext.port = 0;
key.gwy.port = iih.icmp_id;
} else {
PF_ACPY(&key.lan.addr, pd2.dst, key.af);
PF_ACPY(&key.ext.addr, pd2.src, key.af);
key.lan.port = iih.icmp_id;
- key.ext.port = iih.icmp_id;
+ key.ext.port = 0;
}
STATE_LOOKUP();
@@ -4944,13 +4978,13 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
if (direction == PF_IN) {
PF_ACPY(&key.ext.addr, pd2.dst, key.af);
PF_ACPY(&key.gwy.addr, pd2.src, key.af);
- key.ext.port = iih.icmp6_id;
+ key.ext.port = 0;
key.gwy.port = iih.icmp6_id;
} else {
PF_ACPY(&key.lan.addr, pd2.dst, key.af);
PF_ACPY(&key.ext.addr, pd2.src, key.af);
key.lan.port = iih.icmp6_id;
- key.ext.port = iih.icmp6_id;
+ key.ext.port = 0;
}
STATE_LOOKUP();