libs/core: fix type in luci.model.wireless
[project/luci.git] / libs / core / luasrc / ip.lua
index 75311bf..3b0ca67 100644 (file)
@@ -17,11 +17,12 @@ $Id$
 --- LuCI IP calculation library.
 module( "luci.ip", package.seeall )
 
-require("bit")
-require("luci.util")
+require "nixio"
+local bit  = nixio.bit
+local util = require "luci.util"
 
 --- Boolean; true if system is little endian
-LITTLE_ENDIAN = not luci.util.bigendian()
+LITTLE_ENDIAN = not util.bigendian()
 
 --- Boolean; true if system is big endian
 BIG_ENDIAN    = not LITTLE_ENDIAN
@@ -65,7 +66,7 @@ local function __array16( x, family )
                list = { unpack(x[2]) }
 
        elseif type(x) == "table" then
-               list = x
+               list = { unpack(x) }
        end
 
        assert( list, "Invalid operand" )
@@ -159,6 +160,7 @@ function IPv4(address, netmask)
        local data = {}
        local prefix = address:match("/(.+)")
        address = address:gsub("/.+","")
+       address = address:gsub("^%[(.*)%]$", "%1"):upper():gsub("^::FFFF:", "")
 
        if netmask then
                prefix = obj:prefix(netmask)
@@ -206,6 +208,7 @@ function IPv6(address, netmask)
        local data = {}
        local prefix = address:match("/(.+)")
        address = address:gsub("/.+","")
+       address = address:gsub("^%[(.*)%]$", "%1")
 
        if netmask then
                prefix = obj:prefix(netmask)
@@ -227,7 +230,7 @@ function IPv6(address, netmask)
 
                block = tonumber(address:sub(borderl, borderh - 1), 16)
                if block and block <= 0xFFFF then
-                       table.insert(data, block)
+                       data[#data+1] = block
                else
                        if zeroh or borderh - borderl > 1 then return nil end
                        zeroh = #data + 1
@@ -241,7 +244,7 @@ function IPv6(address, netmask)
                block = tonumber(chunk, 16)
                if not block or block > 0xFFFF then return nil end
 
-               table.insert(data, block)
+               data[#data+1] = block
        elseif #chunk > 4 then
                if #data == 7 or #chunk > 15 then return nil end
                borderl = 1
@@ -254,7 +257,7 @@ function IPv6(address, netmask)
                        if not block or block > 255 then return nil end
 
                        if i == 1 or i == 3 then
-                               table.insert(data, block * 256)
+                               data[#data+1] = block * 256
                        else
                                data[#data] = data[#data] + block
                        end
@@ -308,13 +311,13 @@ function Hex( hex, prefix, family, swap )
        for i = 1, ( len / 4 ), 4 do
                local n = tonumber( hex:sub( i, i+3 ), 16 )
                if n then
-                       table.insert( data, n )
+                       data[#data+1] = n
                else
                        return nil
                end
        end
 
-       return __bless({ family, data, len })
+       return __bless({ family, data, prefix })
 end
 
 
@@ -322,7 +325,7 @@ end
 -- @class      module
 -- @cstyle     instance
 -- @name       luci.ip.cidr
-cidr = luci.util.class()
+cidr = util.class()
 
 --- Test whether the instance is a IPv4 address.
 -- @return     Boolean indicating a IPv4 address type
@@ -414,32 +417,31 @@ function cidr.equal( self, addr )
 end
 
 --- Return the prefix length of this CIDR instance.
--- @return     Prefix length in bit
+-- @param mask Override instance prefix with given netmask (optional)
+-- @return             Prefix length in bit
 function cidr.prefix( self, mask )
        local prefix = self[3]
 
        if mask then
                prefix = 0
+
                local stop = false
-               local obj = self:is4() and IPv4(mask) or IPv6(mask)
+               local obj = type(mask) ~= "table"
+                       and ( self:is4() and IPv4(mask) or IPv6(mask) ) or mask
 
-               if not obj then
-                       return nil
-               end
+               if not obj then return nil end
 
-               for i, block in ipairs(obj[2]) do
-                       local pos = bit.lshift(1, 15)
-                       for i=15, 0, -1 do
-                               if bit.band(block, pos) == pos then
-                                       if not stop then
-                                               prefix = prefix + 1
-                                       else
-                                               return nil
-                                       end
-                               else
-                                       stop = true
+               for _, word in ipairs(obj[2]) do
+                       if word == 0xFFFF then
+                               prefix = prefix + 16
+                       else
+                               local bitmask = bit.lshift(1, 15)
+                               while bit.band(word, bitmask) == bitmask do
+                                       prefix  = prefix + 1
+                                       bitmask = bit.lshift(1, 15 - (prefix % 16))
                                end
-                               pos = bit.rshift(pos, 1)
+
+                               break
                        end
                end
        end
@@ -459,14 +461,14 @@ function cidr.network( self, bits )
        bits = bits or self[3]
 
        for i = 1, math.floor( bits / 16 ) do
-               table.insert( data, self[2][i] )
+               data[#data+1] = self[2][i]
        end
 
        if #data < #self[2] then
-               table.insert( data, bit.band( self[2][1+#data], __mask16(bits) ) )
+               data[#data+1] = bit.band( self[2][1+#data], __mask16(bits) )
 
                for i = #data + 1, #self[2] do
-                       table.insert( data, 0 )
+                       data[#data+1] = 0
                end
        end
 
@@ -480,7 +482,7 @@ end
 -- @see                        cidr.broadcast
 -- @see                        cidr.mask
 function cidr.host( self )
-       return __bless({ self[1], data, __maxlen(self[1]) })
+       return __bless({ self[1], self[2], __maxlen(self[1]) })
 end
 
 --- Return a corresponding CIDR representing the netmask of this instance.
@@ -494,14 +496,14 @@ function cidr.mask( self, bits )
        bits = bits or self[3]
 
        for i = 1, math.floor( bits / 16 ) do
-               table.insert( data, 0xFFFF )
+               data[#data+1] = 0xFFFF
        end
 
        if #data < #self[2] then
-               table.insert( data, __mask16(bits) )
+               data[#data+1] = __mask16(bits)
 
                for i = #data + 1, #self[2] do
-                       table.insert( data, 0 )
+                       data[#data+1] = 0
                end
        end
 
@@ -550,19 +552,17 @@ function cidr.add( self, amount, inplace )
        local data   = { unpack(self[2]) }
        local shorts = __array16( amount, self[1] )
 
-       if shorts then
-               for pos = #data, 1, -1 do
-                       local add = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0
-                       if ( data[pos] + add ) > 0xFFFF then
-                               data[pos] = ( data[pos] + add ) % 0xFFFF
-                               if pos > 1 then
-                                       data[pos-1] = data[pos-1] + ( add - data[pos] )
-                               else
-                                       return nil
-                               end
+       for pos = #data, 1, -1 do
+               local add = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0
+               if ( data[pos] + add ) > 0xFFFF then
+                       data[pos] = ( data[pos] + add ) % 0xFFFF
+                       if pos > 1 then
+                               data[pos-1] = data[pos-1] + ( add - data[pos] )
                        else
-                               data[pos] = data[pos] + add
+                               return nil
                        end
+               else
+                       data[pos] = data[pos] + add
                end
        end
 
@@ -583,19 +583,17 @@ function cidr.sub( self, amount, inplace )
        local data   = { unpack(self[2]) }
        local shorts = __array16( amount, self[1] )
 
-       if shorts then
-               for pos = #data, 1, -1 do
-                       local sub = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0
-                       if ( data[pos] - sub ) < 0 then
-                               data[pos] = ( sub - data[pos] ) % 0xFFFF
-                               if pos > 1 then
-                                       data[pos-1] = data[pos-1] - ( sub + data[pos] )
-                               else
-                                       return nil
-                               end
+       for pos = #data, 1, -1 do
+               local sub = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0
+               if ( data[pos] - sub ) < 0 then
+                       data[pos] = ( sub - data[pos] ) % 0xFFFF
+                       if pos > 1 then
+                               data[pos-1] = data[pos-1] - ( sub + data[pos] )
                        else
-                               data[pos] = data[pos] - sub
+                               return nil
                        end
+               else
+                       data[pos] = data[pos] - sub
                end
        end