On Tue, May 09, 2017 at 01:55:18PM +0200, Mike Belopuhov wrote:
> On Tue, May 09, 2017 at 10:36 +0200, Patrick Wildt wrote:
> > On Mon, May 08, 2017 at 02:56:55PM +0200, Patrick Wildt wrote:
> > > @@ -2307,9 +2326,9 @@ pfr_pool_get(struct pf_pool *rpool, struct pf_addr 
> > > **raddr,
> > >                   rpool->curweight = kt->pfrkt_maxweight;
> > >   }
> > >  
> > > - pfr_prepare_network(&pfr_mask, af, ke->pfrke_net);
> > > + pfr_prepare_network(&mask, af, ke->pfrke_net);
> > >   *raddr = SUNION2PF(&ke->pfrke_sa, af);
> > > - *rmask = SUNION2PF(&pfr_mask, af);
> > > + *rmask = SUNION2PF(&mask, af);
> > >  
> > >   if (use_counter && !PF_AZERO(counter, af)) {
> > >           /* is supplied address within block? */
> > 
> > Before committing I realised that this actually returns the pointer
> > instead of the contents, which would mean that we would now return
> > a pointer to the callee's stack.
> > 
> > I think we should change pfr_pool_get() so that it's the caller's
> > responsibility to pass a structure where the rmask can fit into.  Then
> > we should always work with that structure and copy the elements instead
> > of changing rmask by setting it to a different pointer.
> > 
> > Maybe we should do the same for raddr.
> > 
> > Opinions?
> >
> 
> You have to take extreme care with this fragile code.
> 
> raddr is the current address of the pool.  It gets modified
> by the pfr_pool_get each time you call it, the same with rmask.
> 
> Try to round-robin through a table (all 22 entries) like this:
> { 1.0.0.0/30 2.0.0.0/29 3.0.0.0/28} and see how raddr and rmask
> change.
> 
> Right now I believe this diff is incorrect as you're not putting
> back your updated rmask value back into the pool where you took
> it so that the next iteration starts up where you left.
> 
> Getting rid of the global value is a good thing though.

I don't see where rmask is put back into the pool?  pfr_pool_get
only replaced the pointer pointing to the rmask value, so the
value in the pool never changed.  Instead the rmask pointer in
pf_map_addr() simply pointed to the global variable instead of
the pool value.

pf_lb.c:342:
        struct pf_addr          *rmask = rpool->addr.v.a.mask;

pf_lb.c:401:
        pfr_pool_get(rpool, &raddr, &rmask, af)

pf_table.c:2331:
        *rmask = SUNION2PF(&mask, af);

Am I missing something?

Patrick

> 
> > diff --git a/sys/net/pf_lb.c b/sys/net/pf_lb.c
> > index 74acc538b8f..af57272c4dc 100644
> > --- a/sys/net/pf_lb.c
> > +++ b/sys/net/pf_lb.c
> > @@ -339,7 +339,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >     unsigned char            hash[16];
> >     struct pf_addr           faddr;
> >     struct pf_addr          *raddr = &rpool->addr.v.a.addr;
> > -   struct pf_addr          *rmask = &rpool->addr.v.a.mask;
> > +   struct pf_addr           rmask = rpool->addr.v.a.mask;
> >     u_int64_t                states;
> >     u_int16_t                weight;
> >     u_int64_t                load;
> > @@ -361,7 +361,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                         !PF_POOL_DYNTYPE(rpool->opts))
> >                             return (1);
> >                     raddr = &rpool->addr.p.dyn->pfid_addr4;
> > -                   rmask = &rpool->addr.p.dyn->pfid_mask4;
> > +                   rmask = rpool->addr.p.dyn->pfid_mask4;
> >                     break;
> >  #ifdef INET6
> >             case AF_INET6:
> > @@ -369,7 +369,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                         !PF_POOL_DYNTYPE(rpool->opts))
> >                             return (1);
> >                     raddr = &rpool->addr.p.dyn->pfid_addr6;
> > -                   rmask = &rpool->addr.p.dyn->pfid_mask6;
> > +                   rmask = rpool->addr.p.dyn->pfid_mask6;
> >                     break;
> >  #endif /* INET6 */
> >             default:
> > @@ -380,7 +380,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                     return (1); /* unsupported */
> >     } else {
> >             raddr = &rpool->addr.v.a.addr;
> > -           rmask = &rpool->addr.v.a.mask;
> > +           rmask = rpool->addr.v.a.mask;
> >     }
> >  
> >     switch (rpool->opts & PF_POOL_TYPEMASK) {
> > @@ -388,7 +388,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >             PF_ACPY(naddr, raddr, af);
> >             break;
> >     case PF_POOL_BITMASK:
> > -           PF_POOLMASK(naddr, raddr, rmask, saddr, af);
> > +           PF_POOLMASK(naddr, raddr, &rmask, saddr, af);
> >             break;
> >     case PF_POOL_RANDOM:
> >             if (rpool->addr.type == PF_ADDR_TABLE) {
> > @@ -418,31 +418,31 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                             break;
> >  #ifdef INET6
> >                     case AF_INET6:
> > -                           if (rmask->addr32[3] != 0xffffffff)
> > +                           if (rmask.addr32[3] != 0xffffffff)
> >                                     rpool->counter.addr32[3] = arc4random();
> >                             else
> >                                     break;
> > -                           if (rmask->addr32[2] != 0xffffffff)
> > +                           if (rmask.addr32[2] != 0xffffffff)
> >                                     rpool->counter.addr32[2] = arc4random();
> >                             else
> >                                     break;
> > -                           if (rmask->addr32[1] != 0xffffffff)
> > +                           if (rmask.addr32[1] != 0xffffffff)
> >                                     rpool->counter.addr32[1] = arc4random();
> >                             else
> >                                     break;
> > -                           if (rmask->addr32[0] != 0xffffffff)
> > +                           if (rmask.addr32[0] != 0xffffffff)
> >                                     rpool->counter.addr32[0] = arc4random();
> >                             break;
> >  #endif /* INET6 */
> >                     default:
> >                             unhandled_af(af);
> >                     }
> > -                   PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
> > +                   PF_POOLMASK(naddr, raddr, &rmask, &rpool->counter, af);
> >                     PF_ACPY(init_addr, naddr, af);
> >  
> >             } else {
> >                     PF_AINC(&rpool->counter, af);
> > -                   PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
> > +                   PF_POOLMASK(naddr, raddr, &rmask, &rpool->counter, af);
> >             }
> >             break;
> >     case PF_POOL_SRCHASH:
> > @@ -469,7 +469,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                             return (1);
> >                     PF_ACPY(naddr, &rpool->counter, af);
> >             } else {
> > -                   PF_POOLMASK(naddr, raddr, rmask,
> > +                   PF_POOLMASK(naddr, raddr, &rmask,
> >                         (struct pf_addr *)&hash, af);
> >             }
> >             break;
> > @@ -485,7 +485,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                             if (pfr_pool_get(rpool, &raddr, &rmask, af))
> >                                     return (1);
> >                     }
> > -           } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
> > +           } else if (pf_match_addr(0, raddr, &rmask, &rpool->counter, af))
> >                     return (1);
> >  
> >             /* iterate over table if it contains entries which are weighted 
> > */
> > @@ -527,7 +527,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                             if (pfr_pool_get(rpool, &raddr, &rmask, af))
> >                                     return (1);
> >                     }
> > -           } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
> > +           } else if (pf_match_addr(0, raddr, &rmask, &rpool->counter, af))
> >                     return (1);
> >  
> >             states = rpool->states;
> > @@ -557,7 +557,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                         rpool->addr.type == PF_ADDR_DYNIFTL) {
> >                             if (pfr_pool_get(rpool, &raddr, &rmask, af))
> >                                     return (1);
> > -                   } else if (pf_match_addr(0, raddr, rmask,
> > +                   } else if (pf_match_addr(0, raddr, &rmask,
> >                         &rpool->counter, af))
> >                             return (1);
> >  
> > @@ -581,7 +581,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct 
> > pf_addr *saddr,
> >                                 PF_AZERO(init_addr, af))
> >                                 PF_ACPY(init_addr, naddr, af);
> >                     }
> > -           } while (pf_match_addr(1, &faddr, rmask, &rpool->counter, af) &&
> > +           } while (pf_match_addr(1, &faddr, &rmask, &rpool->counter, af) 
> > &&
> >                 (states > 0));
> >  
> >             if (rpool->addr.type == PF_ADDR_TABLE) {
> > diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
> > index 7666ec7013c..f23739e8565 100644
> > --- a/sys/net/pf_table.c
> > +++ b/sys/net/pf_table.c
> > @@ -140,7 +140,6 @@ struct pfr_walktree {
> >  struct pool                 pfr_ktable_pl;
> >  struct pool                 pfr_kentry_pl[PFRKE_MAX];
> >  struct pool                 pfr_kcounters_pl;
> > -union sockaddr_union        pfr_mask;
> >  struct pf_addr              pfr_ffaddr;
> >  
> >  int                         pfr_gcd(int, int);
> > @@ -2252,7 +2251,7 @@ pfr_islinklocal(sa_family_t af, struct pf_addr *addr)
> >  
> >  int
> >  pfr_pool_get(struct pf_pool *rpool, struct pf_addr **raddr,
> > -    struct pf_addr **rmask, sa_family_t af)
> > +    struct pf_addr *rmask, sa_family_t af)
> >  {
> >     struct pfr_ktable       *kt;
> >     struct pfr_kentry       *ke, *ke2;
> > @@ -2327,13 +2326,13 @@ pfr_pool_get(struct pf_pool *rpool, struct pf_addr 
> > **raddr,
> >                     rpool->curweight = kt->pfrkt_maxweight;
> >     }
> >  
> > -   pfr_prepare_network(&pfr_mask, af, ke->pfrke_net);
> > +   pfr_prepare_network(&mask, af, ke->pfrke_net);
> >     *raddr = SUNION2PF(&ke->pfrke_sa, af);
> > -   *rmask = SUNION2PF(&pfr_mask, af);
> > +   *rmask = *SUNION2PF(&mask, af);
> >  
> >     if (use_counter && !PF_AZERO(counter, af)) {
> >             /* is supplied address within block? */
> > -           if (!PF_MATCHA(0, *raddr, *rmask, counter, af)) {
> > +           if (!PF_MATCHA(0, *raddr, rmask, counter, af)) {
> >                     /* no, go to next block in table */
> >                     idx++;
> >                     use_counter = 0;
> > @@ -2417,7 +2416,7 @@ _next_entry:
> >             pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net);
> >             PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af);
> >             PF_AINC(addr, af);
> > -           if (!PF_MATCHA(0, *raddr, *rmask, addr, af)) {
> > +           if (!PF_MATCHA(0, *raddr, rmask, addr, af)) {
> >                     /* ok, we reached the end of our main block */
> >                     /* go to next block in table */
> >                     idx++;
> > diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
> > index 981d778e37a..982437b64ca 100644
> > --- a/sys/net/pfvar.h
> > +++ b/sys/net/pfvar.h
> > @@ -1725,7 +1725,7 @@ int   pfr_match_addr(struct pfr_ktable *, struct 
> > pf_addr *, sa_family_t);
> >  void       pfr_update_stats(struct pfr_ktable *, struct pf_addr *,
> >         struct pf_pdesc *, int, int);
> >  int        pfr_pool_get(struct pf_pool *, struct pf_addr **,
> > -       struct pf_addr **, sa_family_t);
> > +       struct pf_addr *, sa_family_t);
> >  int        pfr_states_increase(struct pfr_ktable *, struct pf_addr *, int);
> >  int        pfr_states_decrease(struct pfr_ktable *, struct pf_addr *, int);
> >  struct pfr_kentry *
> > 

Reply via email to