aboutsummaryrefslogtreecommitdiffstats
path: root/lua/inet/core.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/inet/core.lua')
-rw-r--r--lua/inet/core.lua121
1 files changed, 76 insertions, 45 deletions
diff --git a/lua/inet/core.lua b/lua/inet/core.lua
index 2b36543..a12a036 100644
--- a/lua/inet/core.lua
+++ b/lua/inet/core.lua
@@ -79,13 +79,42 @@ function inet:full_family()
return format('ipv%d', self:family())
end
+local function build_bip(o1, o2, o3, o4)
+ return lshift(o1, 24) + lshift(o2, 16) + lshift(o3, 8) + o4
+end
+
+local function make_inet4(bip, mask)
+ return setmetatable({
+ bip = bip,
+ mask = mask or 32,
+ }, inet4)
+end
+
+local function make_inet6(pcs, mask)
+ local r = setmetatable({
+ pcs = pcs,
+ mask = mask or 128,
+ }, inet6)
+
+ -- ensure that the result is balanced
+ if not r:is_balanced() then
+ r:balance()
+ return nil, tostring(r)..' unbalanced'
+ end
+
+ return r
+end
+
+local ipv4_peg
local ipv4_parser
+local ipv6_peg
local ipv6_parser
do
local lpeg = require 'lpeg'
local C, Ct = lpeg.C, lpeg.Ct
local S, R = lpeg.S, lpeg.R
local B, Cc = lpeg.B, lpeg.Cc
+ local Cmt = lpeg.Cmt
local digit = R('09')
@@ -105,7 +134,13 @@ do
local mask12 = R('12') * digit
local mask3 = S('3') * R('02')
local netmask = S('/') * C(mask12 + mask3 + digit)
- ipv4_parser = ipv4addr * (netmask + Cc()) * -1
+ local ipv4_base = ipv4addr * (netmask + Cc()) /
+ function (o1, o2, o3, o4, mask)
+ local bip = build_bip(o1, o2, o3, o4)
+ return bip, tonumber(mask)
+ end
+ ipv4_parser = ipv4_base * -1
+ ipv4_peg = ipv4_base / make_inet4
end
do
@@ -124,20 +159,43 @@ do
local partial = (piece * (colpi^-6))^-1 * colcol * ((picol^-6)*(ipv4embed+piece))^-1
local netmask = S('/') * C((digit^-3)) / tonumber
local pieces = full + partial
- ipv6_parser = Ct(pieces) * ((netmask + Cc())^-1) * -1
- end
-end
+ local function check_pcs(_, _, pcs, mask)
+ if #pcs > 8 then return false end
+ if mask ~= nil and mask > 128 then return false end
+ return true, pcs, mask
+ end
-local function build_bip(o1, o2, o3, o4)
- return lshift(o1, 24) + lshift(o2, 16) + lshift(o3, 8) + o4
+ local function expand_pieces(pcs)
+ local zero_pieces = 8 - #pcs
+ for i=1,#pcs do
+ if pcs[i] == '::' then
+ pcs[i] = 0
+ for j=#pcs,i,-1 do
+ pcs[j+zero_pieces] = pcs[j]
+ end
+ for j=1,zero_pieces do
+ pcs[i+j] = 0
+ end
+ end
+ end
+ assert(#pcs == 8, 'incorrect number of pieces')
+ return pcs
+ end
+
+ local ipv6_base = Cmt(Ct(pieces) * ((netmask + Cc())^-1), check_pcs) /
+ function (pcs, mask)
+ expand_pieces(pcs)
+ return pcs, mask
+ end
+ ipv6_parser = ipv6_base * -1
+ ipv6_peg = ipv6_base / make_inet6
+ end
end
local function inet4_from_string(ipstr)
- local o1, o2, o3, o4, mask = ipv4_parser:match(ipstr)
- if not o1 then return nil, 'parse error' end
-
- local bip = build_bip(o1, o2, o3, o4)
- return bip, tonumber(mask)
+ local bip, mask = ipv4_parser:match(ipstr)
+ if not bip then return nil, 'parse error' end
+ return bip, mask
end
local function inet4_from_number(bip)
@@ -166,23 +224,6 @@ local inet4_constructors = {
local function inet6_from_string(ipstr)
local pcs, netmask = ipv6_parser:match(ipstr)
if not pcs then return nil, 'parse error' end
- if #pcs > 8 then return nil, 'too many pieces' end
- local zero_pieces = 8 - #pcs
- for i=1,#pcs do
- if pcs[i] == '::' then
- pcs[i] = 0
- for j=#pcs,i,-1 do
- pcs[j+zero_pieces] = pcs[j]
- end
- for j=1,zero_pieces do
- pcs[i+j] = 0
- end
- end
- end
- if #pcs > 8 then return nil, 'too many pieces' end
- if netmask ~= nil and netmask > 128 then
- return nil, 'invalid netmask'
- end
return pcs, netmask
end
@@ -239,28 +280,13 @@ end
local function new_inet4(ip, mask)
local bip, outmask = generic_new(inet4_constructors, 32, ip, mask)
if not bip then return nil, outmask end
- return setmetatable({
- bip = bip,
- mask = outmask,
- }, inet4)
+ return make_inet4(bip, outmask)
end
local function new_inet6(ip, mask)
local pcs, outmask = generic_new(inet6_constructors, 128, ip, mask)
if not pcs then return nil, outmask end
-
- local r = setmetatable({
- pcs = pcs,
- mask = outmask,
- }, inet6)
-
- -- ensure that the result is balanced
- if not r:is_balanced() then
- r:balance()
- return nil, tostring(r)..' unbalanced'
- end
-
- return r
+ return make_inet6(pcs, outmask)
end
local function new_inet(ip, mask)
@@ -877,5 +903,10 @@ M.is_inet4 = is_inet4
M.is_inet6 = is_inet6
M.is_inet = is_inet
M.new_inet = new_inet
+M.lpeg = {
+ ipv4 = ipv4_peg,
+ ipv6 = ipv6_peg,
+ ip = ipv4_peg + ipv6_peg,
+}
return M