On Thu, 13 Feb 2025 at 22:00, <[email protected]> wrote:

> From: [email protected]
> To: [email protected]
> Date: Wed, 12 Feb 2025 17:49:44 -0800
> Subject: [exim] what is the size of the result of ${eval:FOO} ?
>
> I hoped for at least 64 bits on an amd64 system ... but NOoo ?
>

IPv4 addresses are 32 bit, so why would you need a 64-bit int?

(And before anyone retorts "but negative", that doesn't matter, since the
only useful operations are bitwise union, intersection, and comparison,
which don't actually care that the bits are presented to humans as signed
2's complement numbers. For example:

$ exim -be '${if ==
    {${eval: 1<<63 }}
    {${eval: -(1<<63) }} {Same} {Diff} }'
Same

You'll get the corresponding equivalence using <<31 on a 32-bit system.)

beesty:~# exim -be '${eval10:${extract{1}{.}{11.22.33.44}}<<24 +
> ${extract{2}{.}{11.22.33.44}}<<16}'
> -4611686018427387904
> beesty:~# exim -be '${eval:${extract{1}{.}{11.22.33.44}}<<24 +
> ${extract{2}{.}{11.22.33.44}}<<16}'
> -4611686018427387904
>

The immediate problem is a misunderstanding of operator precedence, but
that belies a deeper misapprehension: failure to use bitwise operators for
bitwise manipulation when inter-bit carrying would clearly be the wrong
behaviour. (Granted, in this case the bit sets don't overlap so there won't
be any carrying in practice, but using addition for bitwise operations is a
dirty habit to get into.)

In this case, use bitwise-or “|” or bitwise-xor “^”, in place of each
addition “+”.

exim -be '${eval10: ${extract{1}{.}{11.22.33.44}}<<24 |
${extract{2}{.}{11.22.33.44}}<<16 }'

(Also, use eval10 rather than eval, so that leading 0's doesn't cause octal
interpretation. Again, won't happen in practice provided it's been
converted from a binary IP address, but not necessarily true if it's been
read as text from an external source. So another bad habit to avoid.)

Or any other pure exim way to convert ipv4 addresses into uint64 numbers?
>

Obviously these conversions only include the leading /16 network prefix.
Most networks are significantly smaller than that, so consider converting
the entire address, not just a prefix.

From: Jeremy Harris <[email protected]>
> To: [email protected]
>
> # exim -be '${eval:${extract{1}{.}{11.22.33.44}}<<24 +
> ${extract{2}{.}{11.22.33.44}}<<16}'
> -4611686018427387904
> # exim -be '${eval:(${extract{1}{.}{11.22.33.44}}<<24) +
> (${extract{2}{.}{11.22.33.44}}<<16)}'
> 185991168


Or avoid “+”.

Let'sactually convert the whole address:

$ exim -be '${eval: (((${sg {11.22.33.44}{\\.}{)<<8 | }} } == (((${sg
{11.22.33.44}{\\.}{)<<8 | }}'
185999660 == (((11)<<8 | 22)<<8 | 33)<<8 | 44

(The 3 extra open-parenthesis at the start are of course intentional and
necessary.)

From there it's easy to obtain the integer corresponding to any prefix
length:

$ exim -be '${eval10: ((((${sg {${extract{1}{/}{11.22.33.44/20}}}{\\.}{)<<8
| }}) & ~0 << ${extract{2}{/}{11.22.33.44/20}} } == ((((${sg
{${extract{1}{/}{11.22.33.44/20}}}{\\.}{)<<8 | }}) & ~0 << ${extract{2}{/}{
11.22.33.44/20}} '
185597952 == ((((11)<<8 | 22)<<8 | 33)<<8 | 44) & ~0 << 20

-Martin

-- 
## subscription configuration (requires account):
##   https://lists.exim.org/mailman3/postorius/lists/exim-users.lists.exim.org/
## unsubscribe (doesn't require an account):
##   [email protected]
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/

Reply via email to