Andrew Suffield wrote:
> On Wed, Dec 19, 2007 at 03:54:55PM -0800, Tom Eastep wrote:
>> Tom Eastep wrote:
>>
>>> 172.16.0.0 decodes to 0x100000. Does BusyBox on that architecture only
>>> support 20-bit arithmatic?
>> What spelling -- and I hold an advanced degree in Mathematics :-(
> 
> And perhaps more significantly, it decodes to 0xac100000.

The IP address in Brian's case was 176.16.0.0, not 172.16.0.0 (my bad).
I had inadvertently ignored the leading "B" when I converted the decimal
number to Hex using a calculator. 2953838592 == 0xb0100000. This is the same
result as given by bash and by ash (OpenSuSE). dash (Ubuntu) gives
-1341128704 (0xffffffffb0100000).

> 
> 
> As for the problem itself:
> 
> Shell arithmetic was never guaranteed on large numbers, it's mostly
> intended for loop counters and the like. You're expected to use dc for
> this kind of thing, so I suggest you do that.
> 
> Here's a dc expression for arbitrary-precision bitwise and, if you need it:
> 
> 7sa 5sb 1st 0sr [La2~sxsa lb2%Lx*lt*Lr+sr Lb2/sb Lt2*st lalb*0!=l]dslx Lrp
> 
> Where 7 and 5 are the operands, and the result is on stdout. I know,
> dc's ugly, but it's the only thing busybox implements, and most of the
> other stuff is much neater.

Barf. I'm certainly not going to convert to 'dc' for the normal Shorewall
distributions.

LEFTSHIFT='<<'

#
# Convert an IP address in dot quad format to an integer
#
decodeaddr() {
    local x
    local temp=0
    local ifs=$IFS

    IFS=.

    for x in $1; do
        temp=$(( $(( $temp $LEFTSHIFT 8 )) | $x ))
    done

    echo $temp

    IFS=$ifs
}

The curious use of LEFTSHIFT prevents emacs from interpreting "<<" as "here
documents".

Again, the problem is not that the shell is calculating the wrong value but
rather that when it converts the value to a string, it produces an unsigned
number > 2 ** 31.

The problem is occurring on this call:

in_network 66.11.173.224 176.16.0.0/12

ip_netmask() {
    local vlsm=${1#*/}

    [ $vlsm -eq 0 ] && echo 0 || echo $(( -1 $LEFTSHIFT $(( 32 - $vlsm )) ))
}

in_network() # $1 = IP address, $2 = CIDR network
{
    local netmask=$(ip_netmask $2)

    test $(( $(decodeaddr $1) & $netmask)) -eq \
         $(( $(decodeaddr ${2%/*}) & $netmask ))
}

The netmask is being calculated as -1048576 (0xfff00000) which is correct.

decodeaddr 66.11.173.224 returns 1108061664 (0x420BADE0) which is correct.

decodeaddr 176.16.0.0 returns 2953838592 (0xb0100000) which is correct but
BusyBox shell chokes on it when it tries to convert it back into an integer
(because it is > 2 ** 31). I suspect that if decodeaddr returned -1341128704
(which is equivalent), then all would be well.

Brian: If you modify /usr/share/shorewall-lite/lib.base using the attached
patch, what does "shorewall-lite ipdecimal 176.16.0.0" print?

Thanks,
-Tom
-- 
Tom Eastep    \ Nothing is foolproof to a sufficiently talented fool
Shoreline,     \ http://shorewall.net
Washington USA  \ [EMAIL PROTECTED]
PGP Public Key   \ https://lists.shorewall.net/teastep.pgp.key
Index: lib.base
===================================================================
--- lib.base	(revision 7928)
+++ lib.base	(working copy)
@@ -431,7 +431,7 @@
     IFS=.
 
     for x in $1; do
-	temp=$(( $(( $temp $LEFTSHIFT 8 )) | $x ))
+	temp=$(( $(( $temp $LEFTSHIFT 8 )) + $x ))
     done
 
     echo $temp

Attachment: signature.asc
Description: OpenPGP digital signature

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Shorewall-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/shorewall-users

Reply via email to