)
end
+local function __length(family)
+ if family == FAMILY_INET4 then
+ return 32
+ else
+ return 128
+ end
+end
+
-- htons(), htonl(), ntohs(), ntohl()
function htons(x)
ntohl = htonl
-function IPv4(address)
+function IPv4(address, netmask)
+ address = address or "0.0.0.0/0"
+
+ local obj = __bless({ FAMILY_INET4 })
+
local data = {}
local prefix = address:match("/(.+)")
- if prefix then
+ if netmask then
+ prefix = obj:prefix(netmask)
+ elseif prefix then
address = address:gsub("/.+","")
prefix = tonumber(prefix)
if not prefix or prefix < 0 or prefix > 32 then return nil end
prefix = 32
end
- local b1, b2, b3, b4 = address:match("(%d+)%.(%d+)%.(%d+)%.(%d+)")
+ local b1, b2, b3, b4 = address:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
b1 = tonumber(b1)
b2 = tonumber(b2)
if b1 and b1 <= 255 and
b2 and b2 <= 255 and
b3 and b3 <= 255 and
- b4 and b4 <= 255
+ b4 and b4 <= 255 and
+ prefix
then
- return __bless({
- FAMILY_INET4,
- { b1 * 256 + b2, b3 * 256 + b4 },
- prefix
- })
+ table.insert(obj, { b1 * 256 + b2, b3 * 256 + b4 })
+ table.insert(obj, prefix)
+ return obj
end
end
-function IPv6(address)
+function IPv6(address, netmask)
+ address = address or "::/0"
+
+ local obj = __bless({ FAMILY_INET6 })
+
local data = {}
local prefix = address:match("/(.+)")
- if prefix then
+ if netmask then
+ prefix = obj:prefix(netmask)
+ elseif prefix then
address = address:gsub("/.+","")
prefix = tonumber(prefix)
if not prefix or prefix < 0 or prefix > 128 then return nil end
end
end
- if #data == 8 then
- return __bless({ FAMILY_INET6, data, prefix })
+ if #data == 8 and prefix then
+ table.insert(obj, data)
+ table.insert(obj, prefix)
+ return obj
end
end
+function Hex( hex, prefix, family, swap )
+ family = ( family ~= nil ) and family or FAMILY_INET4
+ swap = ( swap == nil ) and true or swap
+ prefix = prefix or __length(family)
+
+ local len = __length(family)
+ local tmp = ""
+ local data = { }
+
+ for i = 1, (len/4) - #hex do tmp = tmp .. '0' end
+
+ if swap and LITTLE_ENDIAN then
+ for i = #hex, 1, -2 do tmp = tmp .. hex:sub( i - 1, i ) end
+ end
+
+ hex = tmp
+
+ for i = 1, ( len / 4 ), 4 do
+ local n = tonumber( hex:sub( i, i+3 ), 16 )
+ if n then
+ table.insert( data, n )
+ else
+ return nil
+ end
+ end
+
+ return __bless({ family, data, len })
+end
+
cidr = luci.util.class()
return true
end
-function cidr.prefix( self )
- return self[3]
+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)
+
+ 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
+ end
+ pos = bit.rshift(pos, 1)
+ end
+ end
+ end
+
+ return prefix
end
function cidr.network( self )
table.insert( data, 0 )
end
- return __bless({ self[1], data, self:is4() and 32 or 128 })
+ return __bless({ self[1], data, __length(self[1]) })
end
function cidr.host( self )
- return __bless({ self[1], data, self:is4() and 32 or 128 })
+ return __bless({ self[1], data, __length(self[1]) })
end
function cidr.mask( self, bits )
table.insert( data, 0 )
end
- return __bless({ self[1], data, self:is4() and 32 or 128 })
+ return __bless({ self[1], data, __length(self[1]) })
end
function cidr.contains( self, addr )
- if self:mask() <= addr:mask() then
- return self:mask(addr:prefix()) == addr:mask()
+ local mask1 = self:mask()
+ local mask2 = addr:mask()
+ if mask1 <= mask2 then
+ return self:mask(addr:prefix()) == mask2
end
return false