diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2005-08-22 11:54:26 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2005-08-22 11:54:26 +0000 |
commit | e13f67d7920a6cc99092b952bd01767a26721734 (patch) | |
tree | cdf2ca82d708cb0c68586ba76f6c890bde3bc01f /sys/net/pf.c | |
parent | 1354a37d6c1247688efcbc8d3076b7df6bb75c4b (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.c | 78 |
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(); |