On Sat, Dec 04, 2021 at 07:01:23PM +0100, Alexandr Nedvedicky wrote:
> Hello,
> 
> </snip>
> On Fri, Dec 03, 2021 at 03:42:09PM +0100, Claudio Jeker wrote:
> > 
> > See comments below.
> > 
> > 
> > > +void
> > > +pfi_group_delmember(const char *group, struct ifnet *ifp)
> > > +{
> > > + struct pfi_kif          *gkif, *ikif;
> > > +
> > > + if ((gkif = pfi_kif_get(group, NULL)) == NULL ||
> > > +     (ikif = pfi_kif_get(ifp->if_xname, NULL)) == NULL)
> > > +         panic("%s: pfi_kif_get failed", __func__);
> > > + ikif->pfik_flags_new = ikif->pfik_flags & ~gkif->pfik_flags;
> > > +
> > > + pfi_group_change(group);
> > > +}
> > > +
> > 
> > This function is not quite right. For example:
> > 
> > ifconfig vio0 group foo group bar
> > pfctl -f - <<EOF
> > set skip on { foo bar }
> > block return
> > EOF
> > ping -qc2 100.64.1.2
> > 
> > PING 100.64.1.2 (100.64.1.2): 56 data bytes
> > 
> > --- 100.64.1.2 ping statistics ---
> > 2 packets transmitted, 2 packets received, 0.0% packet loss
> > round-trip min/avg/max/std-dev = 0.153/0.178/0.202/0.024 ms
> > 
> > 
> > Now lets remove just group bar from the interface.
> > 
> > ifconfig vio0 -group bar          
> > ping -qc2 100.64.1.2      
> > 
> > PING 100.64.1.2 (100.64.1.2): 56 data bytes
> > ping: sendmsg: Permission denied
> > ping: wrote 100.64.1.2 64 chars, ret=-1
> > ping: sendmsg: Permission denied
> > ping: wrote 100.64.1.2 64 chars, ret=-1
> >  
> > pfi_group_delmember() does not take into consideration other groups
> > (including the interface itself) that may still allow PFI_IFLAG_SKIP.
> > It just clears the flag.
> > 
> > I think on delete the flag needs to be recalculated after the group has
> > been removed. Not sure if this is easy possible though.
> > 
> 
>     yes, you are absolutely right. the current logic around pfi_skip_if() is
>     bit convoluted. in  order to fix it I must rework pfi_xcommit() and 
> related
>     set_flags()/clear_flags() functions. The idea is to let pfi_xcommit() to
>     combine skip flags from all groups, which are attached to interface.
> 
> 
> updated diff is attached.

One comment below but this diff is OK claudio@
 
> thanks and
> regards
> sashan
> 
> --------8<---------------8<---------------8<------------------8<--------
>  void
>  pfi_xcommit(void)
>  {
> -     struct pfi_kif  *p;
> +     struct pfi_kif  *p, *gkif;
> +     struct ifg_list *g;
> +     struct ifnet    *ifp;
> +     size_t n;
>  
> -     RB_FOREACH(p, pfi_ifhead, &pfi_ifs)
> +     RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
>               p->pfik_flags = p->pfik_flags_new;
> +             n = strlen(p->pfik_name);
> +             ifp = p->pfik_ifp;
> +             /*
> +              * if kif is backed by existing interface, then we must use
> +              * skip flags found in groups. We use pfik_flags_new, otherwise
> +              * we would need to do two RB_FOREACH() passes: the first to
> +              * commit group changes the second to commit flag changes for
> +              * interfaces.
> +              */
> +             if (isdigit(p->pfik_name[n - 1]) && ifp != NULL)

No other code in pf_if.c is checking both pfik_name and ifp != NULL in
similar situations.  I think you should skip the isdigit() check here.
If there is a real interface connected to a pfi_kif than it should be updated.
Lets not introduce more complexity here.

> +                     TAILQ_FOREACH(g, &ifp->if_groups, ifgl_next) {
> +                             gkif =
> +                                 (struct pfi_kif *)g->ifgl_group->ifg_pf_kif;
> +                             KASSERT(gkif != NULL);
> +                             p->pfik_flags |= gkif->pfik_flags_new;
> +                     }
> +     }
>  }

-- 
:wq Claudio

Reply via email to