Comparison

util/ip.lua @ 8430:a58d560aa8d5

util.ip: Parse IP address using inet_pton
author Kim Alvefur <zash@zash.se>
date Fri, 01 Dec 2017 04:39:12 +0100
parent 8429:b3562a1b1caa
child 8431:a5a03d40a20c
comparison
equal deleted inserted replaced
8429:b3562a1b1caa 8430:a58d560aa8d5
2 -- Copyright (C) 2008-2011 Florian Zeitz 2 -- Copyright (C) 2008-2011 Florian Zeitz
3 -- 3 --
4 -- This project is MIT/X11 licensed. Please see the 4 -- This project is MIT/X11 licensed. Please see the
5 -- COPYING file in the source package for more information. 5 -- COPYING file in the source package for more information.
6 -- 6 --
7
8 local net = require "util.net";
7 9
8 local ip_methods = {}; 10 local ip_methods = {};
9 11
10 local ip_mt = { 12 local ip_mt = {
11 __index = function (ip, key) 13 __index = function (ip, key)
21 ["8"] = "1000", ["9"] = "1001", ["A"] = "1010", ["B"] = "1011", 23 ["8"] = "1000", ["9"] = "1001", ["A"] = "1010", ["B"] = "1011",
22 ["C"] = "1100", ["D"] = "1101", ["E"] = "1110", ["F"] = "1111", 24 ["C"] = "1100", ["D"] = "1101", ["E"] = "1110", ["F"] = "1111",
23 }; 25 };
24 26
25 local function new_ip(ipStr, proto) 27 local function new_ip(ipStr, proto)
26 if not proto then 28 local zone;
27 local sep = ipStr:match("^%x+(.)"); 29 if (not proto or proto == "IPv6") and ipStr:find('%', 1, true) then
28 if sep == ":" or (not(sep) and ipStr:sub(1,1) == ":") then 30 ipStr, zone = ipStr:match("^(.-)%%(.*)");
29 proto = "IPv6" 31 end
30 elseif sep == "." then 32
31 proto = "IPv4" 33 local packed, err = net.pton(ipStr);
32 end 34 if not packed then return packed, err end
33 if not proto then 35 if proto == "IPv6" and #packed ~= 16 then
34 return nil, "invalid address"; 36 return nil, "invalid-ipv6";
35 end 37 elseif proto == "IPv4" and #packed ~= 4 then
36 elseif proto ~= "IPv4" and proto ~= "IPv6" then 38 return nil, "invalid-ipv4";
39 elseif not proto then
40 if #packed == 16 then
41 proto = "IPv6";
42 elseif #packed == 4 then
43 proto = "IPv4";
44 else
45 return nil, "unknown protocol";
46 end
47 elseif proto ~= "IPv6" and proto ~= "IPv4" then
37 return nil, "invalid protocol"; 48 return nil, "invalid protocol";
38 end 49 end
39 local zone; 50
40 if proto == "IPv6" and ipStr:find('%', 1, true) then 51 return setmetatable({ addr = ipStr, packed = packed, proto = proto, zone = zone }, ip_mt);
41 ipStr, zone = ipStr:match("^(.-)%%(.*)");
42 end
43 if proto == "IPv6" and ipStr:find('.', 1, true) then
44 local changed;
45 ipStr, changed = ipStr:gsub(":(%d+)%.(%d+)%.(%d+)%.(%d+)$", function(a,b,c,d)
46 return (":%04X:%04X"):format(a*256+b,c*256+d);
47 end);
48 if changed ~= 1 then return nil, "invalid-address"; end
49 end
50
51 return setmetatable({ addr = ipStr, proto = proto, zone = zone }, ip_mt);
52 end 52 end
53 53
54 local function toBits(ip) 54 local function toBits(ip)
55 local result = ""; 55 local result = "";
56 local fields = {}; 56 local fields = {};