From 7140c113b09266747c9add120e27b3e0eb017214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Sloth=20T=C3=B8nnesen?= Date: Thu, 18 Jul 2019 18:45:50 +0000 Subject: add more power to add/sub operators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Asbjørn Sloth Tønnesen --- README.rst | 17 ++++++++++-- lua/inet/core.lua | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index fae2397..208ddbd 100644 --- a/README.rst +++ b/README.rst @@ -157,9 +157,12 @@ Addition :: + inet('192.0.2.0') + 24 -- returns inet('192.0.2.24') inet('2001:db8::/64') + 5 -- returns inet('2001:db8::5/64') - --inet('::ffff:0.0.0.0/96') + inet('192.0.2.24') -- returns inet('192.0.2.24') + -- mixed networks special: + inet('::ffff:0.0.0.0/96') + inet('192.0.2.24') -- returns inet('::ffff:192.0.2.24') + inet('192.0.2.24') + inet('::ffff:0.0.0.0/96') -- returns inet('::ffff:192.0.2.24') ``foo - bar`` ~~~~~~~~~~~~~ @@ -170,7 +173,17 @@ Subtract inet('2001:db8::5/64') - 5 -- returns inet('2001:db8::/64') - --inet('2001:db8::5/64') - inet('2001:db8::') -- returns 5 + inet('192.0.2.24') - inet('192.0.2.0') -- returns 24 + + inet('2001:db8::5/64') - inet('2001:db8::') -- returns 5 + + -- by calling the operator method directly additional debuging info are available: + inet('2001:db8::5/64') - inet('ffff::') -- returns nil + inet('2001:db8::5/64'):__sub(inet('ffff::')) + -- returns nil, 'result is out of range', { 8194, 3512, 0, 0, 0, 0, 0, 5 } + + -- mixed networks special: + inet('::ffff:192.0.2.24') - inet('::ffff:0.0.0.0/96') -- returns inet('192.0.2.24') ``foo / bar`` ~~~~~~~~~~~~~ diff --git a/lua/inet/core.lua b/lua/inet/core.lua index f3ae228..9848e52 100644 --- a/lua/inet/core.lua +++ b/lua/inet/core.lua @@ -299,11 +299,25 @@ function inet4:cidrstring() end function inet4:__add(n) - return new_inet4(self.bip + n, self.mask) + local type_n = type(n) + if type_n == 'number' then + return new_inet4(self.bip + n, self.mask) + elseif type_n == 'table' and is_inet6(n) then + return inet6.__add(n, self) + else + return nil, 'invalid argument' + end end function inet4:__sub(n) - return new_inet4(self.bip - n, self.mask) + local type_n = type(n) + if type_n == 'number' then + return new_inet4(self.bip - n, self.mask) + elseif type_n == 'table' and is_inet4(n) then + return self.bip - n.bip + else + return nil, 'invalid argument' + end end function inet4:__mul(n) @@ -392,8 +406,7 @@ function inet6:is_balanced() return true end -function inet6:balance(quick) - local pcs = self.pcs +local function do_balance(pcs, quick) local i = 8 while i > 1 do if quick and pcs[i] > 0 then @@ -416,6 +429,10 @@ function inet6:balance(quick) i = i - 1 end pcs[1] = band(pcs[1], 0xffff) +end + +function inet6:balance(quick) + do_balance(self.pcs, quick) return self end @@ -596,13 +613,62 @@ end function inet6:__add(n) local new = self:clone() local pcs = new.pcs - pcs[8] = pcs[8] + n + local type_n = type(n) + if type_n == 'number' then + pcs[8] = pcs[8] + n + elseif type_n == 'table' and is_inet4(n) then + if #new ~= 96 then return nil, 'inet6 must be a /96' end + if #n ~= 32 then return nil, 'inet4 must be a /32' end + if not mixed_networks:contains(new) then + return nil, 'inet6 is not a mixed notation network' + end + if new ~= new:network() then + return nil, 'inet6 must be a network address' + end + local bip = n.bip + pcs[7] = band(rshift(bip, 16), 0xffff) + pcs[8] = band(bip, 0xffff) + new.mask = 128 + else + return nil, 'invalid argument' + end new:balance(true) return new end function inet6:__sub(n) - return self + (n*-1) + local type_n = type(n) + if type_n == 'number' then + return self + (n*-1) + elseif type_n == 'table' and is_inet6(n) then + local spcs = self.pcs + local npcs = n.pcs + + local dpcs = {} + for i=1,8 do + dpcs[i] = spcs[i] - npcs[i] + end + do_balance(dpcs) + + local ret = 0 + for i=1,8 do + local v = dpcs[i] + if (i < 7 and v > 0) or v < 0 or v > 0xffff then + return nil, 'result is out of range', dpcs + end + local bits = (8 - i) * 16 + ret = ret + lshift(band(v, 0xffff), bits) + end + + if #self == 128 and #n == 96 and mixed_networks:contains(self) + and mixed_networks:contains(n) then + return new_inet4(ret) + else + return ret + end + else + return nil, 'invalid argument' + end end function inet6:network() -- cgit v1.2.1