diff --git a/scripts/mrinfo.nse b/scripts/mrinfo.nse
index 623146760..12522a2f4 100644
--- a/scripts/mrinfo.nse
+++ b/scripts/mrinfo.nse
@@ -3,52 +3,81 @@ local packet = require "packet"
local ipOps = require "ipOps"
local bin = require "bin"
local stdnse = require "stdnse"
-local string = require "string"
local target = require "target"
local table = require "table"
description = [[
-Queries a target router for multicast information.
+Queries targets for multicast routing information.
This works by sending a DVMRP Ask Neighbors 2 request to the target and
-listening for the DVMRP Neighbors 2 response that contains local addresses and
-the multicast neighbors on each one. It is similar to the mrinfo utility included with Windows (Linux/UNIX versions are also available).
+listening for DVMRP Neighbors 2 responses that are sent back and which contain
+local addresses and the multicast neighbors on each interface of the target. If
+no specific target is specified, the request will be sent to the 224.0.0.1 All
+Hosts multicast address.
+This script is similar somehow to the mrinfo utility included with Windows and
+Cisco IOS.
]]
-
---
--- @args mrinfo.timeout Time to wait for a response in seconds.
+-- @args mrinfo.target Host to which the request is sent. If not set, the
+-- request will be sent to 224.0.0.1.
+--
+-- @args mrinfo.timeout Time to wait for responses in seconds.
-- Defaults to 5 seconds.
--
--@usage
--- nmap --script mrinfo
+-- nmap --script mrinfo
+-- nmap --script mrinfo -e eth1
+-- nmap --script mrinfo --script-args 'mrinfo.target=172.16.0.4'
--
--@output
--- Host script results:
+-- Pre-scan script results:
-- | mrinfo:
--- | Version 12.4
--- | Local address: 192.168.2.2
--- | Neighbor: 192.168.2.4
--- | Neighbor: 192.168.2.3
--- | Local address: 192.168.13.1
--- | Neighbor: 192.168.13.3
--- |_ Use the newtargets script-arg to add the results as targets
+-- | Source: 224.0.0.1
+-- | Version 12.4
+-- | Local address: 172.16.0.2
+-- | Neighbor: 172.16.0.4
+-- | Neighbor: 172.16.0.3
+-- | Local address: 172.17.0.1
+-- | Neighbor: 172.17.0.2
+-- | Local address: 172.18.0.1
+-- | Neighbor: 172.18.0.2
+-- | Source: 224.0.0.1
+-- | Version 12.4
+-- | Local address: 172.16.0.4
+-- | Neighbor: 172.16.0.3
+-- | Neighbor: 172.16.0.2
+-- | Local address: 172.17.0.2
+-- | Neighbor: 172.17.0.1
+-- | Source: 224.0.0.1
+-- | Version 12.4
+-- | Local address: 172.16.0.3
+-- | Neighbor: 172.16.0.4
+-- | Neighbor: 172.16.0.2
+-- | Local address: 172.18.0.2
+-- | Neighbor: 172.18.0.1
+-- |_ Use the newtargets script-arg to add the responses as targets
+--
author = "Hani Benhabiles"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
-categories = {"discovery", "safe"}
+categories = {"discovery", "safe", "broadcast"}
-hostrule = function(host)
+prerule = function()
if nmap.address_family() ~= 'inet' then
stdnse.print_verbose("%s is IPv4 only.", SCRIPT_NAME)
return false
end
+ if not nmap.is_privileged() then
+ stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME)
+ return false
+ end
return true
end
@@ -56,11 +85,11 @@ end
-- a structured response.
-- @param data raw data.
local mrinfoParse = function(data)
- local index, interface, neighbor
+ local index, address, neighbor
local response = {}
- -- first byte should be IGMP type == 0x013 (DVMRP)
- if data:byte(1) ~= 0x013 then return end
+ -- first byte should be IGMP type == 0x13 (DVMRP)
+ if data:byte(1) ~= 0x13 then return end
-- DVMRP Code
index, response.code = bin.unpack(">C", data, 2)
@@ -71,49 +100,47 @@ local mrinfoParse = function(data)
-- Major and minor version
index, response.minver = bin.unpack(">C", data, index)
index, response.majver = bin.unpack(">C", data, index)
- response.interfaces = {}
+ response.addresses = {}
-- Iterate over target local addresses (interfaces)
while index < #data do
if data:byte(index) == 0x00 then break end
- interface = {}
+ address = {}
-- Local address
- index, interface.address = bin.unpack("C", data, index)
+ index, address.metric = bin.unpack(">C", data, index)
-- Treshold
- index, interface.treshold= bin.unpack(">C", data, index)
+ index, address.treshold= bin.unpack(">C", data, index)
-- Flags
- index, interface.flags = bin.unpack(">C", data, index)
+ index, address.flags = bin.unpack(">C", data, index)
-- Number of neighbors
- index, interface.ncount = bin.unpack(">C", data, index)
+ index, address.ncount = bin.unpack(">C", data, index)
- interface.neighbors = {}
+ address.neighbors = {}
-- Iterate over neighbors
- for i = 1, interface.ncount do
+ for i = 1, address.ncount do
index, neighbor = bin.unpack(" 0 then
+ if #responses > 0 then
local output, ifoutput = {}
- local response = results[1]
- table.insert(output, ("Version %s.%s"):format(response.majver, response.minver))
- for _, interface in pairs(response.interfaces) do
- ifoutput = {}
- ifoutput.name = "Local address: " .. interface.address
- for _, neighbor in pairs(interface.neighbors) do
- if target.ALLOW_NEW_TARGETS then target.add(neighbor) end
- table.insert(ifoutput, "Neighbor: " .. neighbor)
+ for _, response in pairs(responses) do
+ result = {}
+ result.name = "Source: " .. response.srcip
+ table.insert(result, ("Version %s.%s"):format(response.majver, response.minver))
+ for _, address in pairs(response.addresses) do
+ ifoutput = {}
+ ifoutput.name = "Local address: " .. address.ip
+ for _, neighbor in pairs(address.neighbors) do
+ if target.ALLOW_NEW_TARGETS then target.add(neighbor) end
+ table.insert(ifoutput, "Neighbor: " .. neighbor)
+ end
+ table.insert(result, ifoutput)
end
- table.insert(output, ifoutput)
+ table.insert(output, result)
end
if not target.ALLOW_NEW_TARGETS then
table.insert(output,"Use the newtargets script-arg to add the results as targets")