aboutsummaryrefslogtreecommitdiff
path: root/wireshark/ndpi.lua
diff options
context:
space:
mode:
Diffstat (limited to 'wireshark/ndpi.lua')
-rw-r--r--wireshark/ndpi.lua174
1 files changed, 174 insertions, 0 deletions
diff --git a/wireshark/ndpi.lua b/wireshark/ndpi.lua
new file mode 100644
index 000000000..3d35c9083
--- /dev/null
+++ b/wireshark/ndpi.lua
@@ -0,0 +1,174 @@
+--
+-- (C) 2017 - ntop.org
+--
+-- This plugin is part of nDPI (https://github.com/ntop/nDPI)
+--
+--
+local ndpi_proto = Proto("ndpi", "nDPI", "nDPI Protocol Interpreter")
+
+ndpi_proto.fields = {}
+local fds = ndpi_proto.fields
+
+fds.network_protocol = ProtoField.new("nDPI Network Protocol", "ndpi.protocol.network", ftypes.UINT8, nil, base.DEC)
+fds.application_protocol = ProtoField.new("nDPI Application Protocol", "ndpi.protocol.application", ftypes.UINT8, nil, base.DEC)
+fds.name = ProtoField.new("nDPI Protocol Name", "ndpi.protocol.name", ftypes.STRING)
+
+local f_eth_trailer = Field.new("eth.trailer")
+
+local ndpi_protos = {}
+local ndpi_flows = {}
+local compute_flows_stats = true
+
+-- ###############################################
+
+function ndpi_proto.init()
+ ndpi_protos = {}
+ ndpi_flows = {}
+end
+
+function slen(str)
+ local i = 1
+ local len = 0
+ local zero = string.char(0)
+
+ for i = 1, 16 do
+ local c = str:sub(i,i)
+
+ if(c ~= zero) then
+ len = len + 1
+ else
+ break
+ end
+ end
+
+ return(str:sub(1, len))
+end
+
+-- the dissector function callback
+function ndpi_proto.dissector(tvb, pinfo, tree)
+ local pktlen = tvb:len()
+ local eth_trailer = f_eth_trailer()
+ local magic = tostring(tvb(pktlen-28,4))
+
+ if(magic == "19680924") then
+ local ndpi_subtree = tree:add(ndpi_proto, tvb(), "nDPI Protocol")
+ local network_protocol = tvb(pktlen-24,2)
+ local application_protocol = tvb(pktlen-22,2)
+ local name = tvb(pktlen-20,16)
+ local name_str = name:string(ENC_ASCII)
+ local ndpikey, srckey, dstkey, flowkey
+
+ ndpi_subtree:add(fds.network_protocol, network_protocol)
+ ndpi_subtree:add(fds.application_protocol, application_protocol)
+ ndpi_subtree:add(fds.name, name)
+
+ local pname = ""..application_protocol
+ if(pname ~= "0000") then
+ -- Set protocol name in the wireshark protocol column (if not Unknown)
+ pinfo.cols.protocol = name_str
+ end
+
+ if(compute_flows_stats) then
+ ndpikey = tostring(slen(name_str))
+
+ if(ndpi_protos[ndpikey] == nil) then ndpi_protos[ndpikey] = 0 end
+ ndpi_protos[ndpikey] = ndpi_protos[ndpikey] + pinfo.len
+
+ srckey = tostring(pinfo.src)
+ dstkey = tostring(pinfo.dst)
+
+ flowkey = srckey.." / "..dstkey.." ["..ndpikey.."]"
+ if(ndpi_flows[flowkey] == nil) then
+ ndpi_flows[flowkey] = 0
+ end
+
+ ndpi_flows[flowkey] = ndpi_flows[flowkey] + pinfo.len
+ end
+ end
+end
+
+register_postdissector(ndpi_proto)
+
+-- ###############################################
+
+function round(num, idp) return tonumber(string.format("%." .. (idp or 0) .. "f", num)) end
+
+-- Convert bytes to human readable format
+function bytesToSize(bytes)
+ if(bytes == nil) then
+ return("0")
+ else
+ precision = 2
+ kilobyte = 1024;
+ megabyte = kilobyte * 1024;
+ gigabyte = megabyte * 1024;
+ terabyte = gigabyte * 1024;
+
+ bytes = tonumber(bytes)
+ if((bytes >= 0) and (bytes < kilobyte)) then
+ return round(bytes, precision) .. " Bytes";
+ elseif((bytes >= kilobyte) and (bytes < megabyte)) then
+ return round(bytes / kilobyte, precision) .. ' KB';
+ elseif((bytes >= megabyte) and (bytes < gigabyte)) then
+ return round(bytes / megabyte, precision) .. ' MB';
+ elseif((bytes >= gigabyte) and (bytes < terabyte)) then
+ return round(bytes / gigabyte, precision) .. ' GB';
+ elseif(bytes >= terabyte) then
+ return round(bytes / terabyte, precision) .. ' TB';
+ else
+ return round(bytes, precision) .. ' Bytes';
+ end
+ end
+end
+
+function pairsByValues(t, f)
+ local a = {}
+ for n in pairs(t) do table.insert(a, n) end
+ table.sort(a, function(x, y) return f(t[x], t[y]) end)
+ local i = 0 -- iterator variable
+ local iter = function () -- iterator function
+ i = i + 1
+ if a[i] == nil then return nil
+ else return a[i], t[a[i]]
+ end
+ end
+ return iter
+end
+
+function asc(a,b) return (a < b) end
+function rev(a,b) return (a > b) end
+
+local function ndpi_dialog_menu()
+ local win = TextWindow.new("nDPI Protocol Statistics");
+ local label = ""
+ local i
+ local max_i = 10
+
+ if(ndpi_protos ~= {}) then
+ label = "nDPI Protocol Breakdown\n"
+ label = label .. "-----------------------\n"
+
+ i = 0
+ for k,v in pairsByValues(ndpi_protos, rev) do
+ -- label = label .. k .. "\t".. bytesToSize(v) .. "\n"
+ label = label .. string.format("%-32s\t%s\n", k, bytesToSize(v))
+ if(i == max_i) then break else i = i + 1 end
+ end
+
+ -- #######
+
+ label = label .. "\nTop nDPI Flows\n"
+ label = label .. "-----------\n"
+ i = 0
+ for k,v in pairsByValues(ndpi_flows, rev) do
+ label = label .. string.format("%-32s\t%s\n", k, bytesToSize(v))
+ if(i == max_i) then break else i = i + 1 end
+ end
+
+ win:set(label)
+ end
+end
+
+if(compute_flows_stats) then
+ register_menu("nDPI", ndpi_dialog_menu, MENU_STAT_UNSORTED)
+end