On Thu, Apr 21, 2022 at 07:08:38PM +0200, Alexander Bluhm wrote:

> Hi,
> 
> IGMP and ICMP6 for multicast packets have router alert options.
> Per default pf drops all IP packets with options.  Usually people
> ask what is wrong until someone points out that they have to use a
> pf rule with allow-opts.
> 
> As this is normal behavior and our kernel generates such packets,
> the pf default is bad.
> 
> Diff is untested, but otto@ and florian@ could try it.

Tested this with success on two hosts that hasd issues because their
outgoing icmp6 messages were blcoked. 

> Currently it allows all options.  Should I make it specific to
> router alert with IGMP or ICMP6?

To me it looks like the icmp6 case already is limited to MLD?

        -Otto

> 
> bluhm
> 
> Index: net/pf.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
> retrieving revision 1.1126
> diff -u -p -r1.1126 pf.c
> --- net/pf.c  17 Mar 2022 18:27:55 -0000      1.1126
> +++ net/pf.c  21 Apr 2022 16:30:18 -0000
> @@ -6398,6 +6398,9 @@ pf_walk_header(struct pf_pdesc *pd, stru
>       end = pd->off + ntohs(h->ip_len);
>       pd->off += hlen;
>       pd->proto = h->ip_p;
> +     /* IGMP packets have router alert options, allow them */
> +     if (pd->proto == IPPROTO_IGMP)
> +             pd->badopts = 0;
>       /* stop walking over non initial fragments */
>       if ((h->ip_off & htons(IP_OFFMASK)) != 0)
>               return (PF_PASS);
> @@ -6494,6 +6497,7 @@ pf_walk_header6(struct pf_pdesc *pd, str
>  {
>       struct ip6_frag          frag;
>       struct ip6_ext           ext;
> +     struct icmp6_hdr         icmp6;
>       struct ip6_rthdr         rthdr;
>       u_int32_t                end;
>       int                      hdr_cnt, fraghdr_cnt = 0, rthdr_cnt = 0;
> @@ -6607,9 +6611,23 @@ pf_walk_header6(struct pf_pdesc *pd, str
>                               pd->off += (ext.ip6e_len + 1) * 8;
>                       pd->proto = ext.ip6e_nxt;
>                       break;
> +             case IPPROTO_ICMPV6:
> +                     if (!pf_pull_hdr(pd->m, pd->off, &icmp6, sizeof(icmp6),
> +                         NULL, reason, AF_INET6)) {
> +                             DPFPRINTF(LOG_NOTICE, "IPv6 short icmp6hdr");
> +                             return (PF_DROP);
> +                     }
> +                     /* ICMP multicast packets have router alert options */
> +                     switch (icmp6.icmp6_type) {
> +                     case MLD_LISTENER_QUERY:
> +                     case MLD_LISTENER_REPORT:
> +                     case MLD_LISTENER_DONE:
> +                             pd->badopts = 0;
> +                             break;
> +                     }
> +                     /* FALLTHROUGH */
>               case IPPROTO_TCP:
>               case IPPROTO_UDP:
> -             case IPPROTO_ICMPV6:
>                       /* fragments may be short, ignore inner header then */
>                       if (pd->fragoff != 0 && end < pd->off +
>                           (pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) :
> 

Reply via email to