diff --git a/CHANGELOG b/CHANGELOG
index 46b48bd9e..816beed85 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
# Nmap Changelog ($Id$); -*-text-*-
+o [NSE] Added a new library dnssd with supporting functions for DNS Service
+ Discovery. Moved multicast prerule from dns-service-discovery to a new
+ script called broadcast-dns-service-discovery. [Patrik]
+
o [NSE] Added the rmi-dumpregistry script, which shows the contents of
Java RMI registry. [Martin Holst Swende]
diff --git a/nselib/dnssd.lua b/nselib/dnssd.lua
new file mode 100644
index 000000000..d06142e67
--- /dev/null
+++ b/nselib/dnssd.lua
@@ -0,0 +1,400 @@
+--- Library for supporting DNS Service Discovery
+--
+-- The library supports
+-- * Unicast and Multicast requests
+-- * Decoding responses
+-- * Running requests in parallell using Lua coroutines
+--
+-- The library contains the following classes
+-- * Comm
+-- ** A class with static functions that handle communication using the dns library
+-- * Helper
+-- ** The helper class wraps the Comm class using functions with a more descriptive name.
+-- ** The purpose of this class is to give developers easy access to some of the common DNS-SD tasks.
+-- * Util
+-- ** The Util class contains a number of static functions mainly used to convert data.
+--
+-- The following code snipplet queries all mDNS resolvers on the network for a
+-- full list of their supported services and returns the formated output:
+--
+-- local helper = dnssd.Helper:new( )
+-- helper:setMulticast(true)
+-- return stdnse.format_output(helper:queryServices())
+--
+--
+-- This next snipplet queries a specific host for the same information:
+--
+-- local helper = dnssd.Helper:new( host, port )
+-- return stdnse.format_output(helper:queryServices())
+--
+--
+-- In order to query for a specific service a string or table with service
+-- names can be passed to the Helper.queryServices method.
+--
+-- @args dnssd.services string or table containing services to query
+--
+-- @author Patrik Karlsson
+-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
+--
+
+module(... or "dnssd", package.seeall)
+
+require 'dns'
+require 'target'
+
+Util = {
+
+ --- Converts a string ip to a numeric value suitable for comparing
+ --
+ -- @param ip string containing the ip to convert
+ -- @return number containing the converted ip
+ ipToNumber = function(ip)
+ local o1, o2, o3, o4 = ip:match("^(%d*)%.(%d*)%.(%d*)%.(%d*)$")
+ return (256^3) * o1 + (256^2) * o2 + (256^1) * o3 + (256^0) * o4
+ end,
+
+ --- Compare function used for sorting IP-addresses
+ --
+ -- @param a table containing first item
+ -- @param b table containing second item
+ -- @return true if the port of a is less than the port of b
+ ipCompare = function(a, b)
+ local ip_a = Util.ipToNumber(a.name) or 0
+ local ip_b = Util.ipToNumber(b.name) or 0
+
+ if ( tonumber(ip_a) < tonumber(ip_b) ) then
+ return true
+ end
+ return false
+ end,
+
+ --- Function used to compare discovered DNS services so they can be sorted
+ --
+ -- @param a table containing first item
+ -- @param b table containing second item
+ -- @return true if the port of a is less than the port of b
+ serviceCompare = function(a, b)
+ -- if no port is found use 999999 for comparing, this way all services
+ -- without ports and device information gets printed at the end
+ local port_a = a.name:match("^(%d+)") or 999999
+ local port_b = b.name:match("^(%d+)") or 999999
+
+ if ( tonumber(port_a) < tonumber(port_b) ) then
+ return true
+ end
+ return false
+ end,
+
+ --- Creates a service host table
+ --
+ -- ['_ftp._tcp.local'] = {10.10.10.10,20.20.20.20}
+ -- ['_http._tcp.local'] = {30.30.30.30,40.40.40.40}
+ --
+ -- @param response containing multiple responses from dns.query
+ -- @return services table containing the service name as a key and all host addresses as value
+ createSvcHostTbl = function( response )
+ local services = {}
+ -- Create unique table of services
+ for _, r in ipairs( response ) do
+ -- do we really have mutliple responses?
+ if ( not(r.output) ) then return end
+ for _, svc in ipairs(r.output ) do
+ services[svc] = services[svc] or {}
+ table.insert(services[svc], r.peer)
+ end
+ end
+
+ return services
+ end,
+
+ --- Creates a unique list of services
+ --
+ -- @param response containing a single or multiple responses from
+ -- dns.query
+ -- @return array of strings containing service names
+ getUniqueServices = function( response )
+ local services = {}
+
+ for _, r in ipairs(response) do
+ if ( r.output ) then
+ for _, svc in ipairs(r.output) do services[svc] = true end
+ else
+ services[r] = true
+ end
+ end
+
+ return services
+ end,
+
+ --- Returns the amount of currenlty active threads
+ --
+ -- @param threads table containing the list of threads
+ -- @return count number containing the number of non-dead threads
+ threadCount = function( threads )
+ local count = 0
+
+ for thread in pairs(threads) do
+ if ( coroutine.status(thread) == "dead" ) then
+ threads[thread] = nil
+ else
+ count = count + 1
+ end
+ end
+ return count
+ end
+
+}
+
+Comm = {
+
+ --- Gets a record from both the Answer and Additional section
+ --
+ -- @param dtype DNS resource record type.
+ -- @param response Decoded DNS response.
+ -- @param retAll If true, return all entries, not just the first.
+ -- @return True if one or more answers of the required type were found - otherwise false.
+ -- @return Answer according to the answer fetcher for dtype or an Error message.
+ getRecordType = function( dtype, response, retAll )
+
+ local result = {}
+ local status1, answers = dns.findNiceAnswer( dtype, response, retAll )
+
+ if status1 then
+ if retAll then
+ for _, v in ipairs(answers) do
+ table.insert(result, string.format("%s", v) )
+ end
+ else
+ return true, answers
+ end
+ end
+
+ local status2, answers = dns.findNiceAdditional( dtype, response, retAll )
+
+ if status2 then
+ if retAll then
+ for _, v in ipairs(answers) do
+ table.insert(result, v)
+ end
+ else
+ return true, answers
+ end
+ end
+
+ if not status1 and not status2 then
+ return false, answers
+ end
+
+ return true, result
+
+ end,
+
+ --- Send a query for a particular service and store the response in a table
+ --
+ -- @param host string containing the ip to connect to
+ -- @param port number containing the port to connect to
+ -- @param svc the service record to retrieve
+ -- @param multiple true if responses from multiple hosts are expected
+ -- @param svcresponse table to which results are stored
+ queryService = function( host, port, svc, multiple, svcresponse )
+ local condvar = nmap.condvar(svcresponse)
+ local status, response = dns.query( svc, { port = port, host = host, dtype="PTR", retPkt=true, retAll=true, multiple=multiple, sendCount=1, timeout=2000} )
+ if not status then
+ stdnse.print_debug("Failed to query service: %s; Error: %s", svc, response)
+ return
+ end
+ svcresponse[svc] = svcresponse[svc] or {}
+ if ( multiple ) then
+ for _, r in ipairs(response) do
+ table.insert( svcresponse[svc], r )
+ end
+ else
+ svcresponse[svc] = response
+ end
+ condvar("broadcast")
+ end,
+
+ --- Decodes a record received from the queryService function
+ --
+ -- @param response as returned by queryService
+ -- @param result table into which the decoded output should be stored
+ decodeRecords = function( response, result )
+ local service, deviceinfo = {}, {}
+ local txt = {}
+ local ipv6, srv, address, port, proto
+
+ local record = ( #response.questions > 0 and response.questions[1].dname ) and response.questions[1].dname or ""
+
+ local status, ip = Comm.getRecordType( dns.types.A, response, false )
+ if status then address = ip end
+
+ status, ipv6 = Comm.getRecordType( dns.types.AAAA, response, false )
+ if status then address = address .. " " .. ipv6 end
+
+ status, txt = Comm.getRecordType( dns.types.TXT, response, true )
+ if status then
+ for _, v in ipairs(txt) do
+ if v:len() > 0 then
+ table.insert(service, v)
+ end
+ end
+ end
+
+ status, srv = Comm.getRecordType( dns.types.SRV, response, false )
+ if status then
+ local srvparams = stdnse.strsplit( ":", srv )
+
+ if #srvparams > 3 then
+ port = srvparams[3]
+ end
+ end
+
+ if address then
+ table.insert( service, ("Address=%s"):format( address ) )
+ end
+
+ if record == "_device-info._tcp.local" then
+ service.name = "Device Information"
+ deviceinfo = service
+ table.insert(result, deviceinfo)
+ else
+ local serviceparams = stdnse.strsplit("[.]", record)
+
+ if #serviceparams > 2 then
+ local servicename = serviceparams[1]:sub(2)
+ local proto = serviceparams[2]:sub(2)
+
+ if port == nil or proto == nil or servicename == nil then
+ service.name = record
+ else
+ service.name = string.format( "%s/%s %s", port, proto, servicename)
+ end
+ end
+ table.insert( result, service )
+ end
+ end,
+
+ --- Query the mDNS resolvers for a list of their services
+ --
+ -- @param host table as received by the action function
+ -- @param port number specifying the port to connect to
+ -- @param multiple receive multiple responses (multicast)
+ -- @return True if a dns response was received and contained an answer of
+ -- the requested type, or the decoded dns response was requested
+ -- (retPkt) and is being returned - or False otherwise.
+ -- @return String answer of the requested type, Table of answers or a
+ -- String error message of one of the following:
+ -- "No Such Name", "No Servers", "No Answers",
+ -- "Unable to handle response"
+ queryAllServices = function( host, port, multiple )
+ local sendCount, timeout = 1, 2000
+ if ( multiple ) then
+ sendCount, timeout = 2, 5000
+ end
+ return dns.query( "_services._dns-sd._udp.local", { port = port, host = ( host.ip or host ), dtype="PTR", retAll=true, multiple=multiple, sendCount=sendCount, timeout=timeout } )
+ end,
+
+}
+
+Helper = {
+
+ --- Creates a new helper instance
+ --
+ -- @param host string containing the host name or ip
+ -- @param port number containing the port to connect to
+ -- @return o a new instance of Helper
+ new = function( self, host, port )
+ local o = {}
+ setmetatable(o, self)
+ self.__index = self
+ o.host = host
+ o.port = port
+ o.mcast = false
+ return o
+ end,
+
+
+ --- Instructs the helper to use unconnected sockets supporting multicast
+ --
+ -- @param mcast boolean true if multicast is to be used, false otherwise
+ setMulticast = function( self, mcast )
+ assert( type(mcast)=="boolean", "mcast has to be either true or false")
+ self.mcast = mcast
+ end,
+
+ --- Performs a DNS-SD query against a host
+ --
+ -- @param host table as received by the action function
+ -- @param port number specifying the port to connect to
+ -- @param service string or table with the service(s) to query eg.
+ -- _ssh._tcp.local, _afpovertcp._tcp.local
+ -- if nil defaults to _services._dns-sd._udp.local (all)
+ -- @param mcast boolean true if a multicast query is to be done
+ -- @return status true on success, false on failure
+ -- @return response table suitable for stdnse.format_output
+ queryServices = function( self, service )
+ local result = {}
+ local status, response
+ local mcast = self.mcast
+ local port = self.port or 5353
+ local host = mcast and "224.0.0.251" or self.host
+ local service = service or stdnse.get_script_args('dnssd.services')
+
+ if ( not(service) ) then
+ status, response = Comm.queryAllServices( host, port, mcast )
+ if ( not(status) ) then return status, response end
+ else
+ if ( 'string' == type(service) ) then
+ response = { service }
+ elseif ( 'table' == type(service) ) then
+ response = service
+ end
+ end
+
+ response = Util.getUniqueServices(response)
+
+ local svcresponse = {}
+ local condvar = nmap.condvar( svcresponse )
+ local threads = {}
+
+ for svc in pairs(response) do
+ local co = stdnse.new_thread( Comm.queryService, (host.ip or host), port, svc, mcast, svcresponse )
+ threads[co] = true
+ end
+
+ -- Wait for all threads to finish running
+ while Util.threadCount(threads)>0 do condvar("wait") end
+
+ local ipsvctbl = {}
+ if ( mcast ) then
+ -- Process all records that were returned
+ for svcname, response in pairs(svcresponse) do
+ for _, r in ipairs( response ) do
+ ipsvctbl[r.peer] = ipsvctbl[r.peer] or {}
+ Comm.decodeRecords( r.output, ipsvctbl[r.peer] )
+ end
+ end
+ else
+ -- Process all records that were returned
+ for svcname, response in pairs(svcresponse) do
+ Comm.decodeRecords( response, result )
+ end
+ end
+
+ if ( mcast ) then
+ -- Restructure and build our output table
+ for ip, svctbl in pairs( ipsvctbl ) do
+ table.sort(svctbl, Util.serviceCompare)
+ svctbl.name = ip
+ if target.ALLOW_NEW_TARGETS then target.add(ip) end
+ table.insert( result, svctbl )
+ end
+ table.sort( result, Util.ipCompare )
+ else
+ -- sort the tables per port
+ table.sort( result, Util.serviceCompare )
+ end
+ return true, result
+ end,
+
+}
\ No newline at end of file
diff --git a/scripts/broadcast-dns-service-discovery.nse b/scripts/broadcast-dns-service-discovery.nse
new file mode 100644
index 000000000..ad9e66712
--- /dev/null
+++ b/scripts/broadcast-dns-service-discovery.nse
@@ -0,0 +1,58 @@
+description=[[
+Attempts to discover a hosts services using the DNS Service Discovery protocol.
+It does so by sending a multicast query and collects responses from all
+responding hosts.
+
+The script first sends a query for _services._dns-sd._udp.local to get a
+list of services. It then sends a followup query for each one to try to
+get more information.
+]]
+
+
+---
+-- @usage
+-- nmap --script=broadcast-dns-service-discovery -p 5353
+--
+-- @output
+-- | broadcast-dns-service-discovery:
+-- | 1.2.3.1
+-- | _ssh._tcp.local
+-- | _http._tcp.local
+-- | 1.2.3.50
+-- | 22/tcp ssh
+-- | org.freedesktop.Avahi.cookie=2292090182
+-- | Address=1.2.3.50
+-- | 80/tcp http
+-- | path=/admin
+-- | org.freedesktop.Avahi.cookie=2292090182
+-- | path=/
+-- | org.freedesktop.Avahi.cookie=2292090182
+-- | path=/pim
+-- | org.freedesktop.Avahi.cookie=2292090182
+-- | Address=1.2.3.50
+-- | 1.2.3.116
+-- | 80/tcp http
+-- |_ Address=1.2.3.116
+
+
+-- Version 0.1
+-- Created 10/29/2010 - v0.1 - created by Patrik Karlsson
+
+author = "Patrik Karlsson"
+license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
+categories = {"default", "discovery", "safe"}
+
+require 'shortport'
+require 'dnssd'
+
+prerule = function() return true end
+
+action = function()
+ local helper = dnssd.Helper:new( )
+ helper:setMulticast(true)
+
+ local status, result = helper:queryServices()
+ if ( status ) then
+ return stdnse.format_output(true, result)
+ end
+end
diff --git a/scripts/dns-service-discovery.nse b/scripts/dns-service-discovery.nse
index fbbc419d3..b69859c62 100644
--- a/scripts/dns-service-discovery.nse
+++ b/scripts/dns-service-discovery.nse
@@ -33,317 +33,32 @@ get more information.
-- |_ Address=192.168.0.2 fe80:0:0:0:223:6cff:1234:5678
--- Version 0.6
+-- Version 0.7
-- Created 01/06/2010 - v0.1 - created by Patrik Karlsson
-- Revised 01/13/2010 - v0.2 - modified to use existing dns library instead of mdns, changed output to be less DNS like
-- Revised 02/01/2010 - v0.3 - removed incorrect try/catch statements
-- Revised 10/04/2010 - v0.4 - added prerule and add target support
-- Revised 10/05/2010 - v0.5 - added ip sort function and
-- Revised 10/10/2010 - v0.6 - multicast queries are now used in parallel to collect service information
+-- Revised 10/29/2010 - v0.7 - factored out most of the code to dnssd library
author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
require 'shortport'
-require 'dns'
-require 'target'
+require 'dnssd'
portrule = shortport.portnumber(5353, "udp")
-prerule = function() return true end
---- Gets a record from both the Answer and Additional section
---
--- @param dtype DNS resource record type.
--- @param response Decoded DNS response.
--- @param retAll If true, return all entries, not just the first.
--- @return True if one or more answers of the required type were found - otherwise false.
--- @return Answer according to the answer fetcher for dtype or an Error message.
-function getRecordType( dtype, response, retAll )
+action = function(host, port)
+ local helper = dnssd.Helper:new( host, port )
+ local status, result = helper:queryServices()
- local result = {}
- local status1, answers = dns.findNiceAnswer( dtype, response, retAll )
-
- if status1 then
- if retAll then
- for _, v in ipairs(answers) do
- table.insert(result, string.format("%s", v) )
- end
- else
- return true, answers
- end
+ if ( status ) then
+ -- set port to open
+ nmap.set_port_state(host, port, "open")
+ return stdnse.format_output(true, result)
end
-
- local status2, answers = dns.findNiceAdditional( dtype, response, retAll )
-
- if status2 then
- if retAll then
- for _, v in ipairs(answers) do
- table.insert(result, v)
- end
- else
- return true, answers
- end
- end
-
- if not status1 and not status2 then
- return false, answers
- end
-
- return true, result
-
end
---- Function used to compare discovered DNS services so they can be sorted
---
--- @param a table containing first item
--- @param b table containing second item
--- @return true if the port of a is less than the port of b
-local function serviceCompare(a, b)
- -- if no port is found use 999999 for comparing, this way all services
- -- without ports and device information gets printed at the end
- local port_a = a.name:match("^(%d+)") or 999999
- local port_b = b.name:match("^(%d+)") or 999999
-
- if ( tonumber(port_a) < tonumber(port_b) ) then
- return true
- end
- return false
-end
-
---- Converts a string ip to a numeric value suitable for comparing
---
--- @param ip string containing the ip to convert
--- @return number containing the converted ip
-local function ipToNumber(ip)
- local o1, o2, o3, o4 = ip:match("^(%d*)%.(%d*)%.(%d*)%.(%d*)$")
- return (256^3) * o1 + (256^2) * o2 + (256^1) * o3 + (256^0) * o4
-end
-
---- Compare function used for sorting IP-addresses
---
--- @param a table containing first item
--- @param b table containing second item
--- @return true if the port of a is less than the port of b
-local function ipCompare(a, b)
- local ip_a = ipToNumber(a.name) or 0
- local ip_b = ipToNumber(b.name) or 0
-
- if ( tonumber(ip_a) < tonumber(ip_b) ) then
- return true
- end
- return false
-end
-
---- Send a query for a particular service and store the response in a table
---
--- @param host string containing the ip to connect to
--- @param port number containing the port to connect to
--- @param svc the service record to retrieve
--- @param multiple true if responses from multiple hosts are expected
--- @param svcresponse table to which results are stored
-local function queryService( host, port, svc, multiple, svcresponse )
- local condvar = nmap.condvar(svcresponse)
- local status, response = dns.query( svc, { port = port, host = host, dtype="PTR", retPkt=true, retAll=true, multiple=multiple, sendCount=1, timeout=2000} )
- if not status then
- stdnse.print_debug("Failed to query service: %s; Error: %s", svc, response)
- return
- end
- svcresponse[svc] = svcresponse[svc] or {}
- if ( multiple ) then
- for _, r in ipairs(response) do
- table.insert( svcresponse[svc], r )
- end
- else
- svcresponse[svc] = response
- end
- condvar("broadcast")
-end
-
---- Sends a unicast query for each discovered service to each host
---
--- @param host string containing the ip to connect to
--- @param record string containing the DNS record to query
--- @param result table to which the results are added
-local function processRecords( response, result )
- local service, deviceinfo = {}, {}
- local txt = {}
- local ip, ipv6, srv, address, port, proto
-
- local record = ( #response.questions > 0 and response.questions[1].dname ) and response.questions[1].dname or ""
-
- status, ip = getRecordType( dns.types.A, response, false )
- if status then address = ip end
-
- status, ipv6 = getRecordType( dns.types.AAAA, response, false )
- if status then address = address .. " " .. ipv6 end
-
- status, txt = getRecordType( dns.types.TXT, response, true )
- if status then
- for _, v in ipairs(txt) do
- if v:len() > 0 then
- table.insert(service, v)
- end
- end
- end
-
- status, srv = getRecordType( dns.types.SRV, response, false )
- if status then
- local srvparams = stdnse.strsplit( ":", srv )
-
- if #srvparams > 3 then
- port = srvparams[3]
- end
- end
-
- if address then
- table.insert( service, ("Address=%s"):format( address ) )
- end
-
- if record == "_device-info._tcp.local" then
- service.name = "Device Information"
- deviceinfo = service
- table.insert(result, deviceinfo)
- else
- local serviceparams = stdnse.strsplit("[.]", record)
-
- if #serviceparams > 2 then
- local servicename = serviceparams[1]:sub(2)
- local proto = serviceparams[2]:sub(2)
-
- if port == nil or proto == nil or servicename == nil then
- service.name = record
- else
- service.name = string.format( "%s/%s %s", port, proto, servicename)
- end
- end
- table.insert( result, service )
- end
-
-end
-
-
---- Returns the amount of currenlty active threads
---
--- @param threads table containing the list of threads
--- @return count number containing the number of non-dead threads
-threadCount = function( threads )
- local count = 0
-
- for thread in pairs(threads) do
- if ( coroutine.status(thread) == "dead" ) then
- threads[thread] = nil
- else
- count = count + 1
- end
- end
- return count
-end
-
---- Creates a service host table
---
--- ['_ftp._tcp.local'] = {10.10.10.10,20.20.20.20}
--- ['_http._tcp.local'] = {30.30.30.30,40.40.40.40}
---
--- @param response containing the response from dns.query
--- @return services table containing the service name as a key and all host addresses as value
-local function createSvcHostTbl( response )
- local services = {}
- -- Create unique table of services
- for _, r in ipairs( response ) do
- for _, svc in ipairs(r.output ) do
- services[svc] = services[svc] or {}
- table.insert(services[svc], r.peer)
- end
- end
-
- return services
-end
-
-preaction = function()
- local result = {}
- local host, port = "224.0.0.251", 5353
- local status, response = dns.query( "_services._dns-sd._udp.local", { port = port, host = host, dtype="PTR", retAll=true, multiple=true, sendCount=1, timeout=2000} )
- if not status then return end
-
- local services = createSvcHostTbl(response)
- local ipsvctbl = {}
- local svcresponse = {}
- local condvar = nmap.condvar( svcresponse )
- local threads = {}
-
- -- Start one collector thread for each service
- for svc in pairs(services) do
- local co = stdnse.new_thread( queryService, host, port, svc, true, svcresponse )
- threads[co] = true
- end
-
- -- Wait for all threads to finish running
- while threadCount(threads)>0 do
- condvar("wait")
- end
-
- -- Process all records that were returned
- for svcname, response in pairs(svcresponse) do
- for _, r in ipairs( response ) do
- ipsvctbl[r.peer] = ipsvctbl[r.peer] or {}
- processRecords( r.output, ipsvctbl[r.peer] )
- end
- end
-
- -- Restructure and build our output table
- for ip, svctbl in pairs( ipsvctbl ) do
- table.sort(svctbl, serviceCompare)
- svctbl.name = ip
- if target.ALLOW_NEW_TARGETS then target.add(ip) end
- table.insert( result, svctbl )
- end
- table.sort( result, ipCompare )
-
- return stdnse.format_output(true, result )
-end
-
-scanaction = function(host, port)
- local result = {}
- local status, response = dns.query( "_services._dns-sd._udp.local", { port = 5353, host = host.ip, dtype="PTR", retAll=true, sendCount=1, timeout=2000 } )
- if not status then return end
-
- local svcresponse = {}
- local condvar = nmap.condvar( svcresponse )
- local threads = {}
-
- -- Start one collector thread for each service
- for _, svc in ipairs(response) do
- local co = stdnse.new_thread( queryService, host.ip, port, svc, false, svcresponse )
- threads[co] = true
- end
-
- -- Wait for all threads to finish running
- while threadCount(threads)>0 do
- condvar("wait")
- end
-
- -- Process all records that were returned
- for svcname, response in pairs(svcresponse) do
- processRecords( response, result )
- end
-
- -- sort the tables per port
- table.sort( result, serviceCompare )
-
- -- set port to open
- nmap.set_port_state(host, port, "open")
-
- return stdnse.format_output(true, result )
-
-end
-
--- Function dispatch table
-local actions = {
- prerule = preaction,
- hostrule = scanaction,
- portrule = scanaction,
-}
-
-function action (...) return actions[SCRIPT_TYPE](...) end
-
diff --git a/scripts/script.db b/scripts/script.db
index 3221583a1..390b97966 100644
--- a/scripts/script.db
+++ b/scripts/script.db
@@ -6,6 +6,7 @@ Entry { filename = "asn-query.nse", categories = { "discovery", "external", "saf
Entry { filename = "auth-owners.nse", categories = { "default", "safe", } }
Entry { filename = "auth-spoof.nse", categories = { "malware", "safe", } }
Entry { filename = "banner.nse", categories = { "discovery", "safe", } }
+Entry { filename = "broadcast-dns-service-discovery.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "citrix-brute-xml.nse", categories = { "auth", "intrusive", } }
Entry { filename = "citrix-enum-apps-xml.nse", categories = { "discovery", "safe", } }
Entry { filename = "citrix-enum-apps.nse", categories = { "discovery", "safe", } }