Hi,

On Wed, Jun 07, Willy Tarreau wrote:
> On Sun, Jun 04, 2017 at 07:12:38PM +0300, Jarno Huuskonen wrote:
> > Hi Willy,
> > 
> > On Sat, May 27, Willy Tarreau wrote:
> > > On Sun, May 21, 2017 at 07:49:00PM +0300, Jarno Huuskonen wrote:
> > > > I noticed that ipv6 version of ipmask() converter is missing ?
> > > > 
> > > > I'm attaching an example implementation for ipv6mask (incomplete:
> > > > missing at least documentation / lua) for comments.
> > > > 
> > > > Maybe instead of just working with one mask ipv6mask(converter) could
> > > > take two arguments: first ipv6mask, second(optional) ipv4 mask applied 
> > > > to
> > > > ipv4mapped ipv6 address(::ffff:1.2.3.4).
> > > 
> > > That could indeed be a good idea. Thinking a bit further, shouldn't we
> > > extend the current ipmask to support an optional ipv6 mask as a second
> > > argument (ie exactly what you did but with ipv6 optional instead of
> > > ipv4) ? This would allow it to be used on any address. It would end
> > > up like this :
> > >   - ipv4 in => ipv4 out, using ipv4 mask
> > >   - ipv4-in-ipv6 in => ipv4-in-ipv6 out, using ipv4 mask
> > >   - ipv6 in => ipv6 out, using ipv6 mask
> > 
> > So ipmask would internally work on ipv6 addresses and ipv4
> > addresses are converted to/from mapped (::ffff:1.2.3.4) addresses ?
> 
> No, not necessarily, we know the type of the input sample so we can apply
> the mask we want and emit the same type on output. I was only saying that
> the ipv4 mask should be used when you face ipv4-in-ipv6 addresses.
> 
> > > What do you think ?
> > 
> > ipmask() with optional ipv6mask is fine with me, I guess it won't break
> > existing configs because ipv6 mask is optional. For ipv4 only it probably
> > adds a little overhead when converting to/from mapped ::ffff:1.2.3.4 
> > addresses.
> 
> It would cause other trouble such as conversion to strings which will be
> mangled by this "::ffff:" prefix. That's why it's better to maintain the
> same type.
> 
> > @@ -2736,7 +2747,7 @@ static struct sample_conv_kw_list sample_conv_kws = 
> > {ILH, {
> >     { "upper",  sample_conv_str2upper, 0,            NULL, SMP_T_STR,  
> > SMP_T_STR  },
> >     { "lower",  sample_conv_str2lower, 0,            NULL, SMP_T_STR,  
> > SMP_T_STR  },
> >     { "hex",    sample_conv_bin2hex,   0,            NULL, SMP_T_BIN,  
> > SMP_T_STR  },
> > -   { "ipmask", sample_conv_ipmask,    ARG1(1,MSK4), NULL, SMP_T_IPV4, 
> > SMP_T_IPV4 },
> > +   { "ipmask", sample_conv_ipmask,    ARG2(1,MSK4,MSK6), NULL, SMP_T_IPV6, 
> > SMP_T_IPV6 },
> 
> You need to use SMP_T_ADDR instead of SMP_T_IPV6 in order to adapt to any
> address family type and not enforce it. Maybe this is what led you to think
> that you needed to convert ipv4 to ipv6.

I might be finally getting it:)

So something like:
> > +   { "ipmask", sample_conv_ipmask,    ARG2(1,MSK4,MSK6), NULL, SMP_T_ADDR, 
> > SMP_T_ADDR },

(using SMP_T_ADDR output type makes stick table complain:
http-request track-sc0 req.hdr_ip(X,1),ipmask(24,64) table test_be
...stick-table 'test_be' uses a type incompatible with the 'track-sc0' rule.
Might work by adding ADDR->IPV4/IPV6 c_none casts to sample_casts
(or using SMP_T_IPV4 or SMP_T_IPV6 output)).

(setting headers works with SMP_T_ADDR output:
http-request set-var(sess.myx) req.hdr_ip(X,1),ipmask(24,64)
http-response set-header X-MY %[var(sess.myx)]
)

and sample_conv_ipmask with SMP_T_ADDR input:
if (smp->data.type == SMP_T_IPV4) {
        /* ipv4 address & ipv4 mask */
        ...
}
else if (smp->data.type == SMP_T_IPV6) {
        if (*(uint32_t*)&smp->data.u.ipv6.s6_addr[8] == htonl(0xFFFF))...) {
                /* ipv4 mapped ipv6 & ipv4mask */
                ...
        }
        else if (arg_p[1].type == ARGT_IPV6) {
                /* ipv6 & ipv6 mask */
                ...
        }
}

-Jarno

-- 
Jarno Huuskonen

Reply via email to