From 1de1b10c89a07c29bcb9c6f1c823a97400e9aa5f Mon Sep 17 00:00:00 2001 From: gyani Date: Sat, 8 Aug 2015 11:25:27 +0000 Subject: [PATCH] Ganglia info now uses dispatch tables and SLAXML to parse the XML response. --- scripts/ganglia-info.nse | 258 +++++++++++++++++++++++++++------------ 1 file changed, 182 insertions(+), 76 deletions(-) diff --git a/scripts/ganglia-info.nse b/scripts/ganglia-info.nse index 4e0b308cb..31db88603 100644 --- a/scripts/ganglia-info.nse +++ b/scripts/ganglia-info.nse @@ -1,6 +1,7 @@ local comm = require "comm" local nmap = require "nmap" local shortport = require "shortport" +local slaxml = require "slaxml" local stdnse = require "stdnse" local string = require "string" local table = require "table" @@ -32,62 +33,177 @@ For more information about Ganglia, see: -- About 5KB-10KB of data is returned for each host in the cluster. -- -- @output --- PORT STATE SERVICE VERSION --- 8649/tcp open ganglia Ganglia XML Grid monitor 2.5.7 (Cluster name: unspecified; Owner: unspecified; Source: gmond) +-- 8649/tcp open unknown syn-ack -- | ganglia-info: --- | Service: Ganglia Monitoring Daemon --- | Version: 2.5.7 --- | Cluster Name: unspecified --- | Owner: unspecified --- | Hostname: localhost --- | IP: 127.0.0.1 --- | cpu nice: 0.0% --- | cpu user: 2.0% --- | proc total: 182 --- | proc run: 0 --- | load fifteen: 0.13 --- | pkts in: 0.12packets/sec --- | swap total: 9928700KB --- | load five: 0.15 --- | machine type: x86_64 --- | disk total: 236.111GB --- | mem buffers: 33148KB --- | mem total: 3845028KB --- | bytes in: 6.57bytes/sec --- | load one: 0.22 --- | sys clock: 1317692483s --- | mem free: 3280956KB --- | mtu: 1280B --- | mem shared: 0KB --- | cpu aidle: 97.0% --- | cpu idle: 99.1% --- | cpu speed: 2266MHz --- | mem cached: 271924KB --- | cpu num: 4 --- | part max used: 55.9% --- | bytes out: 5.48bytes/sec --- | os release: 2.6.34 --- | gexec: OFF --- | disk free: 104.075GB --- | cpu system: 0.1% --- | boottime: 1317692167s --- | swap free: 9928700KB --- | os name: Linux --- |_ pkts out: 0.06packets/sec - --- Version 0.1 +-- | Ganglia Version: 3.1.7 +-- | Cluster 1: +-- | Name: unspecified +-- | Owner: unspecified +-- | Host 1: +-- | Name: sled9735.sd.dreamhost.com +-- | IP: 10.208.42.221 +-- | load_one: 0.53 +-- | mem_total: 24685564KB +-- | os_release: 3.1.9-vs2.3.2.5 +-- | proc_run: 0 +-- | load_five: 0.52 +-- | gexec: OFF +-- | disk_free: 305.765GB +-- | mem_cached: 18857264KB +-- | pkts_in: 821.73packets/sec +-- | bytes_in: 72686.10bytes/sec +-- | bytes_out: 5612221.50bytes/sec +-- | swap_total: 1998844KB +-- | mem_free: 187964KB +-- | load_fifteen: 0.57 +-- | os_name: Linux +-- | boottime: 1429708366s +-- | cpu_idle: 96.3% +-- | cpu_user: 2.7% +-- | cpu_nice: 0.0% +-- | cpu_aidle: 94.7% +-- | mem_buffers: 169588KB +-- | cpu_system: 0.8% +-- | part_max_used: 31.5% +-- | disk_total: 435.962GB +-- | mem_shared: 0KB +-- | cpu_wio: 0.2% +-- | machine_type: x86_64 +-- | proc_total: 1027 +-- | cpu_num: 8CPUs +-- | cpu_speed: 2400MHz +-- | pkts_out: 3977.13packets/sec +-- | swap_free: 1393392KB +-- +-- @xmloutput +-- 3.1.7 +-- +-- unspecified +-- unspecified +--
+-- sled9735.sd.dreamhost.com +-- 10.208.42.221 +-- 0.53 +-- 24685564KB +-- 3.1.9-vs2.3.2.5 +-- 0 +-- 0.52 +-- OFF +-- 305.765GB +-- 18857264KB +-- 821.73packets/sec +-- 72686.10bytes/sec +-- 5612221.50bytes/sec +-- 1998844KB +-- 187964KB +-- 0.57 +-- Linux +-- 1429708366s +-- 96.3% +-- 2.7% +-- 0.0% +-- 94.7% +-- 169588KB +-- 0.8% +-- 31.5% +-- 435.962GB +-- 0KB +-- 0.2% +-- x86_64 +-- 1027 +-- 8CPUs +-- 2400MHz +-- 3977.13packets/sec +-- 1393392KB +--
+-- +-- +-- Version 0.2 -- Created 2011-06-28 - v0.1 - created by Brendan Coles - itsecuritysolutions.org +-- Created 2015-07-30 - v0.2 - Added Support for SLAXML by Gyanendra Mishra -author = "Brendan Coles" +author = {"Brendan Coles", "Gyanendra Mishra"} license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} - portrule = shortport.port_or_service ({8649,8651}, "ganglia", {"tcp"}) +local function set_name_value(name) + return function(value, state) + state.result[name] = value + end +end + +local function set_cluster(name) + return function(value, state) + local current = state[#state] + if not current.out then + state.cc = state.cc + 1 + current.out = stdnse.output_table() + current.hc = 0 + state.result["Cluster " .. state.cc] = current.out + end + state.result["Cluster " .. state.cc][name] = value + end +end + +local function get_current_cluster(state) + for i=#state, 1, -1 do + if state[i][1] == "CLUSTER" then + return state[i] + end + end +end + +local function set_host(name) + return function(value, state) + local current = state[#state] + local current_cluster = get_current_cluster(state) + if not current.out then + current_cluster.hc = current_cluster.hc + 1 + current.out = stdnse.output_table() + state.result["Cluster " .. state.cc]["Host " .. current_cluster.hc] = current.out + end + state.result["Cluster " .. state.cc]["Host " .. current_cluster.hc][name] = value + end +end + +local function set_metric(name) + return function(value, state) + local current = state[#state] + local current_cluster = get_current_cluster(state) + current[name] = value + if current["name"] and current["value"] and current["unit"] then + state.result["Cluster " .. state.cc]["Host " .. current_cluster.hc][current["name"]] = current["value"] .. current["unit"] + end + end +end + +local P = { + GANGLIA_XML = { + VERSION = set_name_value("Ganglia Version"), + }, + GRID = { + NAME = set_name_value("Grid Name"), + }, + CLUSTER = { + NAME = set_cluster("Name"), + OWNER = set_cluster("Owner"), + }, + HOST = { + NAME = set_host("Name"), + IP = set_host("IP"), + }, + METRIC = { + NAME = set_metric("name"), + UNITS = set_metric("unit"), + VAL = set_metric("value"), + } +} + action = function( host, port ) - local result = {} + local result = stdnse.output_table() -- Set timeout local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. '.timeout')) @@ -105,37 +221,27 @@ action = function( host, port ) return end - -- Parse daemon info - if not string.match(data, "]+ OWNER="([^"]*)" ') then - table.insert(result, string.format("Cluster Name: %s\n\tOwner: %s\n", string.match(line, ']+ OWNER="([^"]*)" '))) - elseif string.match(line, ']+ UNITS="[^"]*"') then - table.insert(result, string.format("\t\t%s: %s%s", string.gsub(string.match(line, ']+ UNITS="[^"]*"'), "_", " "), string.match(line, ']+ UNITS="[^"]*"'), string.match(line, ']+ UNITS="([^"]*)"'))) - end - end + local parser = slaxml.parser:new() + parser._call = { + startElement = function(name) table.insert(state, {name}) end, + closeElement = function(name) assert(state[#state][1] == name) state[#state] = nil end, + attribute = function(name, value) + local p_elem = P[state[#state][1]] + if not (p_elem and p_elem[name]) then return end + local p_attr = p_elem[name] + if not p_attr then return end + p_attr(value, state) + end, + } - -- Return results - return stdnse.format_output(true, result) + parser:parseSAX(data, {stripWhitespace=true}) + + if #state.result then return state.result end end +