mirror of
https://github.com/nmap/nmap.git
synced 2025-12-15 20:29:03 +00:00
Many scripts were documented as using timespecs (10s, 5000ms, etc) for timeout script-args, but one 1 or 2 actually did. Now all timeout script-args will accept timespecs, except those which took a number of milliseconds, which remain unchanged. Also fixed some documentation issues (missing script name in arg description, missing nsedoc for args, etc)
182 lines
4.6 KiB
Lua
182 lines
4.6 KiB
Lua
local bin = require "bin"
|
|
local ipOps = require "ipOps"
|
|
local nmap = require "nmap"
|
|
local stdnse = require "stdnse"
|
|
local tab = require "tab"
|
|
local table = require "table"
|
|
|
|
description=[[
|
|
Discovers hosts and routing information from devices running RIPv2 on the
|
|
LAN. It does so by sending a RIPv2 Request command and collects the responses
|
|
from all devices responding to the request.
|
|
]]
|
|
|
|
---
|
|
-- @usage
|
|
-- nmap --script broadcast-rip-discover
|
|
--
|
|
-- @output
|
|
-- Pre-scan script results:
|
|
-- | broadcast-rip-discover:
|
|
-- | Discovered RIPv2 devices
|
|
-- | 10.0.200.107
|
|
-- | ip netmask nexthop metric
|
|
-- | 10.46.100.0 255.255.255.0 0.0.0.0 1
|
|
-- | 10.46.110.0 255.255.255.0 0.0.0.0 1
|
|
-- | 10.46.120.0 255.255.255.0 0.0.0.0 1
|
|
-- | 10.46.123.0 255.255.255.0 10.0.200.123 1
|
|
-- | 10.46.124.0 255.255.255.0 10.0.200.124 1
|
|
-- | 10.46.125.0 255.255.255.0 10.0.200.125 1
|
|
-- | 10.0.200.101
|
|
-- | ip netmask nexthop metric
|
|
-- |_ 0.0.0.0 0.0.0.0 10.0.200.1 1
|
|
--
|
|
-- @args broadcast-rip-discover.timeout timespec defining how long to wait for
|
|
-- a response. (default 5s)
|
|
|
|
--
|
|
-- Version 0.1
|
|
-- Created 29/10/2011 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
|
--
|
|
|
|
author = "Patrik Karlsson"
|
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|
categories = {"broadcast", "safe"}
|
|
|
|
|
|
prerule = function() return not( nmap.address_family() == "inet6") end
|
|
|
|
RIPv2 = {
|
|
|
|
Command = {
|
|
Request = 1,
|
|
Response = 2,
|
|
},
|
|
|
|
AddressFamily = {
|
|
IP = 2,
|
|
},
|
|
|
|
-- The Request class contains functions to build a RIPv2 Request
|
|
Request = {
|
|
|
|
-- Creates a new Request instance
|
|
--
|
|
-- @param command number containing the RIPv2 Command to use
|
|
-- @return o instance of request
|
|
new = function(self, command)
|
|
local o = {
|
|
version = 2,
|
|
command = command,
|
|
domain = 0,
|
|
family = 0,
|
|
tag = 0,
|
|
address = 0,
|
|
subnet = 0,
|
|
nexthop = 0,
|
|
metric = 16
|
|
}
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
return o
|
|
end,
|
|
|
|
-- Converts the whole request to a string
|
|
__tostring = function(self)
|
|
assert(self.command, "No command was supplied")
|
|
assert(self.metric, "No metric was supplied")
|
|
assert(self.address, "No address was supplied")
|
|
local RESERVED = 0
|
|
-- RIPv2 stuff, should be 0 for RIPv1
|
|
local tag, subnet, nexthop = 0, 0, 0
|
|
|
|
local data = bin.pack(">CCSSSIIII",
|
|
self.command, self.version, self.domain, self.family, self.tag,
|
|
self.address, self.subnet, self.nexthop, self.metric)
|
|
|
|
return data
|
|
end,
|
|
|
|
},
|
|
|
|
-- The Response class contains code needed to parse a RIPv2 response
|
|
Response = {
|
|
|
|
-- Creates a new Response instance based on raw socket data
|
|
--
|
|
-- @param data string containing the raw socket response
|
|
-- @return o Response instance
|
|
new = function(self, data)
|
|
local o = { data = data }
|
|
|
|
if ( not(data) or #data < 3 ) then
|
|
return
|
|
end
|
|
local pos
|
|
pos, o.command, o.version = bin.unpack(">CCS", data)
|
|
if ( o.command ~= RIPv2 and o.version ~= 2 ) then
|
|
return
|
|
end
|
|
|
|
local routes = tab.new(2)
|
|
tab.addrow(routes, "ip", "netmask", "nexthop", "metric")
|
|
|
|
while( #data - pos >= 20 ) do
|
|
local family, address, metric, _, netmask, nexthop
|
|
pos, family, _, address, netmask, nexthop,
|
|
metric = bin.unpack(">SS<III>I", data, pos)
|
|
|
|
if ( family == RIPv2.AddressFamily.IP ) then
|
|
local ip = ipOps.fromdword(address)
|
|
netmask = ipOps.fromdword(netmask)
|
|
nexthop = ipOps.fromdword(nexthop)
|
|
tab.addrow(routes, ip, netmask, nexthop, metric)
|
|
end
|
|
end
|
|
|
|
if ( #routes > 1 ) then o.routes = routes end
|
|
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
return o
|
|
end,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
action = function()
|
|
local timeout = stdnse.parse_timespec(stdnse.get_script_args('broadcast-rip-discover.timeout'))
|
|
timeout = (timeout or 5) * 1000
|
|
|
|
local socket = nmap.new_socket("udp")
|
|
socket:set_timeout(timeout)
|
|
|
|
local rip = RIPv2.Request:new(RIPv2.Command.Request)
|
|
local status, err = socket:sendto("224.0.0.9",
|
|
{ number = 520, protocol = "udp" },
|
|
tostring(rip))
|
|
local result = {}
|
|
repeat
|
|
local data
|
|
status, data = socket:receive()
|
|
if ( status ) then
|
|
local status, _, _, rhost, _ = socket:get_info()
|
|
local response = RIPv2.Response:new(data)
|
|
table.insert(result, rhost)
|
|
|
|
if ( response and response.routes and #response.routes > 0 ) then
|
|
--response.routes.name = "Routes"
|
|
table.insert(result, { tab.dump(response.routes) } )
|
|
end
|
|
|
|
end
|
|
until( not(status) )
|
|
|
|
if ( #result > 0 ) then
|
|
result.name = "Discovered RIPv2 devices"
|
|
end
|
|
return stdnse.format_output(true, result)
|
|
end
|