Hello,
the issue has been discovered and analyzed by Luca di Gregorio
on bugs@ [1]. The thread [1] covers all details. People who
wish to read brief summary can skip to Luca's email [2].
To wrap it up the current handling IGMP/MLD messages in pf(4)
is exact opposite. I failed to translate English words from
RFC standards into correct C code. Patch below are two one-liners
which make multicast for IPv4/IPv6 to work again with pf(4) enabled.
Let me quote Luca's summary for IPv6 here:
If the IP Destination Address is multicast, then the TTL
should be 1.
If the IP Destination Address is not multicast, then
no restrictions on TTL.
and Luca's summary for IPv4:
If the IP Destination Address is 224.0.0.0/4, then the TTL
should be 1.
If the IP Destination Address is not 224.0.0.0/4, then no
restrictions on TTL.
As I've said all details and references to RFCs can be found
in Luca's emails on bugs@ [1].
Diff below to fix IGMP/MLD handling has been essentially proposed
by Luca [3]. OK to commit?
thanks and
regards
sashan
[1] https://marc.info/?t=167714059600002&r=1&w=2
[2] https://marc.info/?l=openbsd-bugs&m=167727244015783&w=2
[3] https://marc.info/?l=openbsd-bugs&m=167722460220004&w=2
--------8<---------------8<---------------8<------------------8<--------
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 8cb1326a160..c328109026c 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -6847,7 +6847,7 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short
*reason)
/* IGMP packets have router alert options, allow them */
if (pd->proto == IPPROTO_IGMP) {
/* According to RFC 1112 ttl must be set to 1. */
- if ((h->ip_ttl != 1) || !IN_MULTICAST(h->ip_dst.s_addr)) {
+ if ((h->ip_ttl != 1) && IN_MULTICAST(h->ip_dst.s_addr)) {
DPFPRINTF(LOG_NOTICE, "Invalid IGMP");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
@@ -7101,8 +7101,8 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h,
u_short *reason)
* missing then MLD message is invalid and
* should be discarded.
*/
- if ((h->ip6_hlim != 1) ||
- !IN6_IS_ADDR_LINKLOCAL(&h->ip6_src)) {
+ if ((h->ip6_hlim != 1) &&
+ IN6_IS_ADDR_LINKLOCAL(&h->ip6_src)) {
DPFPRINTF(LOG_NOTICE, "Invalid MLD");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);