Category Archives: vb

Bitwise AND for Large Numbers in Traditional ASP

Once in a while (like today) I have to go back and do something in traditional ASP (Active Server Pages). That’s when I realize how nice .NET is, with typed data and all those framework methods. Something seemingly trivial, like figuring out if an IP address is part of a network, turns out to be quite difficult. The normal approach here would be to convert the IP address, network and subnet into integers, do a bitwise AND of the two items, and then compare the result. Unfortunately, the “AND” operator in ASP only works with integers and “Long” integers (up to 2^31 or 2,147,483,647), and the integer representation of 255.255.255.0 is 4,294,901,760. Uh oh. So, I came up with a double-precision AND function which splits the double value into “high” and “low” chunks (basically, the part below 2^31 and the part above), performs a bitwise AND on the chunks, and then shifts the bits back into place and reassembles a Double value from this. This should be viable for the bits left of the decimal up to about 4.6E+18. At the very least, it’s working for the IP address example.

function DoubleAnd (d1,d2)
    ' bitwise AND for values potentially greater than the Long limit (2147483647)
    dim d1low, d1high, d2low, d2high, lowand, highand
    d1high = fix(d1 / (2^31))
    d1low = fix(d1 - d1high * (2^31))
    d2high = fix(d2 / (2^31))
    d2low = fix(d2 - d2high * (2^31))
    lowand = d1low and d2low
    highand = d1high and d2high
    DoubleAnd = highand * (2^31) + lowand
end function

It’s called like this:

if (DoubleAnd(ipint,subnetint)) = (DoubleAnd(networkint,subnetint)) then
    response.write ("IP is on network")
else
    response.Write ("IP is NOT on network")
end if

Note that I’m ANDing both the ip address and the network address. This shouldn’t technically be necessary, but it helps in cases where the user types in another IP address on the network instead of the network address (e.g. 192.168.1.1 instead of 192.168.1.0).

Here are the helper functions required for the conversions:

function IsValidIpAddress (IP)
    dim aGroups, i, j
    aGroups = split(IP,".")
    if ubound(aGroups) <> 3 then
        IsValidIpAddress = false
        exit function
    end if
    for i = 0 to ubound(aGroups)
        j = aGroups(i)
        if not isNumeric (j) then
            IsValidIpAddress = false
            exit function
        end if
        if j < 0 or j > 255 then
            IsValidIpAddress = false
            exit function
        end if
    next
    IsValidIpAddress = true
end function
function IntegerFromIPAddress (IP)
    if (IsValidIpAddress(IP)) then
        dim aGroups
        aGroups = split(IP,".")
        IntegerFromIPAddress = aGroups(3) + aGroups(2) * 256 + aGroups(1) * 256^2 + aGroups(0) * 256^3  
        exit function
    else
        IntegerFromIPAddress = -1
    end if
end function

Note, all these function assume IPv4. Yes, there’s a potential Y2K-style problem lurking here, but I just can’t deal with the absurdity of making a traditional ASP application IPv6-aware at the moment.