On Sat, Feb 05, 2011 at 02:03:25PM +0100, Mike Belopuhov wrote:
> we can check if "af == inet" in icmp case obviously, but how and why
> can we end up with af == inet6 and an icmp payload (or af == inet
> and icmp6 payload for that matter)?
Somebody could send us such a packet.
It is strange but not illegal. If we decide, pf should drop such
packets that is a complete different thing.
Anyway we should make sure that pf_translate() can handle these
packets by itself. Protocol 1 for IPv6 packets means no special
treatment so it should end in the else case.
I suggest that diff (untested):
Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.722
diff -u -p -r1.722 pf.c
--- net/pf.c 22 Jan 2011 11:43:57 -0000 1.722
+++ net/pf.c 5 Feb 2011 13:43:58 -0000
@@ -3281,8 +3281,7 @@ pf_translate(struct pf_pdesc *pd, struct
if (PF_ANEQ(daddr, pd->dst, pd->af))
pd->destchg = 1;
- switch (pd->proto) {
- case IPPROTO_TCP:
+ if (pd->proto == 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);
@@ -3293,9 +3292,7 @@ pf_translate(struct pf_pdesc *pd, struct
&pd->hdr.tcp->th_sum, daddr, dport, 0, pd->af);
rewrite = 1;
}
- break;
-
- case IPPROTO_UDP:
+ } else if (pd->proto == 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);
@@ -3306,10 +3303,8 @@ pf_translate(struct pf_pdesc *pd, struct
&pd->hdr.udp->uh_sum, daddr, dport, 1, pd->af);
rewrite = 1;
}
- break;
-
#ifdef INET
- case IPPROTO_ICMP:
+ } else if (pd->proto == IPPROTO_ICMP && pd->af == 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);
@@ -3331,28 +3326,21 @@ pf_translate(struct pf_pdesc *pd, struct
rewrite = 1;
}
}
- 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);
- rewrite = 1;
- }
- if (PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a6(pd->dst,
- &pd->hdr.icmp6->icmp6_cksum, daddr, 0);
- rewrite = 1;
- }
- break;
+ } else if (pd->proto == IPPROTO_ICMPV6 && pd->af == AF_INET6) {
+ if (PF_ANEQ(saddr, pd->src, pd->af)) {
+ pf_change_a6(pd->src, &pd->hdr.icmp6->icmp6_cksum,
+ saddr, 0);
+ rewrite = 1;
+ }
+ if (PF_ANEQ(daddr, pd->dst, pd->af)) {
+ pf_change_a6(pd->dst, &pd->hdr.icmp6->icmp6_cksum,
+ daddr, 0);
+ rewrite = 1;
}
- /* FALLTHROUGH */
#endif /* INET6 */
-
- default:
+ } else {
switch (pd->af) {
#ifdef INET
case AF_INET: