1-- Copyright (c) 2018-2021, OARC, Inc. 2-- All rights reserved. 3-- 4-- This file is part of dnsjit. 5-- 6-- dnsjit is free software: you can redistribute it and/or modify 7-- it under the terms of the GNU General Public License as published by 8-- the Free Software Foundation, either version 3 of the License, or 9-- (at your option) any later version. 10-- 11-- dnsjit is distributed in the hope that it will be useful, 12-- but WITHOUT ANY WARRANTY; without even the implied warranty of 13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14-- GNU General Public License for more details. 15-- 16-- You should have received a copy of the GNU General Public License 17-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>. 18 19-- dnsjit.lib.ip 20-- IP address utility library 21-- local ip = require("dnsjit.lib.ip") 22-- print(ip.ipstring(ipv4_cdata)) 23-- print(ip.ip6string(ipv6_cdata), true) 24-- 25-- A library to help with various IP address related tasks, such as 26-- printing them. 27module(...,package.seeall) 28 29local ffi = require("ffi") 30 31Ip = {} 32 33-- Return an IPv4 or IPv6 address as a string. 34-- If it's an IPv6 address the optional argument 35-- .I pretty 36-- is true then return an easier to read IPv6 address. 37-- Return an empty string on invalid input. 38function Ip.tostring(ip, pretty) 39 if type(ip) == "cdata" then 40 if ffi.sizeof(ip) == 4 then 41 return Ip.ipstring(ip) 42 elseif ffi.sizeof(ip) == 16 then 43 return Ip.ip6string(ip, pretty) 44 end 45 end 46 return "" 47end 48 49-- Return a IPv4 address as a string. 50-- The input is a 4-byte cdata array. 51function Ip.ipstring(ip) 52 return ip[0] ..".".. ip[1] ..".".. ip[2] ..".".. ip[3] 53end 54 55local function _pretty(ip) 56 local src = {} 57 58 local n, nn 59 nn = 1 60 for n = 0, 15, 2 do 61 if ip[n] ~= 0 then 62 src[nn] = string.format("%x%02x", ip[n], ip[n + 1]) 63 elseif ip[n + 1] ~= 0 then 64 src[nn] = string.format("%x", ip[n + 1]) 65 else 66 src[nn] = "0" 67 end 68 nn = nn + 1 69 end 70 71 local best_n, best_at, at = 0, 0, 0 72 n = 0 73 for nn = 1, 8 do 74 if src[nn] == "0" then 75 if n == 0 then 76 at = nn 77 end 78 n = n + 1 79 else 80 if n > 0 then 81 if n > best_n then 82 best_n = n 83 best_at = at 84 end 85 n = 0 86 end 87 end 88 end 89 if n > 0 then 90 if n > best_n then 91 best_n = n 92 best_at = at 93 end 94 end 95 if best_n > 1 then 96 for n = 2, best_n do 97 table.remove(src, best_at) 98 end 99 if best_at == 1 or best_at + best_n > 8 then 100 src[best_at] = ":" 101 else 102 src[best_at] = "" 103 end 104 end 105 106 return table.concat(src,":") 107end 108 109-- Return the IPv6 address as a string. 110-- The input is a 16-byte cdata array. 111-- If 112-- .I pretty 113-- is true then return an easier to read IPv6 address. 114function Ip.ip6string(ip6, pretty) 115 if pretty == true then 116 return _pretty(ip6) 117 end 118 return string.format("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 119 ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7], 120 ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]) 121end 122 123-- dnsjit.core.object.ip (3), 124-- dnsjit.core.object.ip6 (3) 125return Ip 126