Software /
code /
prosody
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 = {}; |