summaryrefslogtreecommitdiffstats
path: root/scripts/gpsd-info.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gpsd-info.nse')
-rw-r--r--scripts/gpsd-info.nse105
1 files changed, 105 insertions, 0 deletions
diff --git a/scripts/gpsd-info.nse b/scripts/gpsd-info.nse
new file mode 100644
index 0000000..b6aefaa
--- /dev/null
+++ b/scripts/gpsd-info.nse
@@ -0,0 +1,105 @@
+local datetime = require "datetime"
+local gps = require "gps"
+local match = require "match"
+local nmap = require "nmap"
+local os = require "os"
+local shortport = require "shortport"
+local stdnse = require "stdnse"
+
+description = [[
+Retrieves GPS time, coordinates and speed from the GPSD network daemon.
+]]
+
+---
+-- @usage
+-- nmap -p 2947 <ip> --script gpsd-info
+--
+-- @output
+-- PORT STATE SERVICE REASON
+-- 2947/tcp open gpsd-ng syn-ack
+-- | gpsd-info:
+-- | Time of fix: Sat Apr 14 15:54:23 2012
+-- | Coordinates: 59.321685,17.886493
+-- |_ Speed: - knots
+--
+-- @args gpsd-info.timeout timespec defining how long to wait for data (default 10s)
+
+
+author = "Patrik Karlsson"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"discovery", "safe"}
+
+
+portrule = shortport.port_or_service(2947, "gpsd-ng", "tcp")
+
+local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout"))
+arg_timeout = arg_timeout or 10
+
+local function updateData(gpsinfo, entry)
+ for k, v in pairs(gpsinfo) do
+ if ( entry[k] and 0 < #tostring(entry[k]) ) then
+ gpsinfo[k] = entry[k]
+ end
+ end
+end
+
+local function hasAllData(gpsinfo)
+ for k, v in pairs(gpsinfo) do
+ if ( k ~= "speed" and v == '-' ) then
+ return false
+ end
+ end
+ return true
+end
+
+local function fail(err) return stdnse.format_output(false, err) end
+
+action = function(host, port)
+
+ local gpsinfo = {
+ longitude = "-",
+ latitude = "-",
+ speed = "-",
+ time = "-",
+ date = "-",
+ }
+
+ local socket = nmap.new_socket()
+ socket:set_timeout(1000)
+
+ local status = socket:connect(host, port)
+
+ if ( not(status) ) then
+ return fail("Failed to connect to server")
+ end
+
+ -- get the banner
+ local status, line = socket:receive_lines(1)
+ socket:send('?WATCH={"enable":true,"nmea":true}\r\n')
+
+ local start_time = os.time()
+
+ repeat
+ local entry
+ status, line = socket:receive_buf(match.pattern_limit("\r\n", 2048), false)
+ if ( status ) then
+ status, entry = gps.NMEA.parse(line)
+ if ( status ) then
+ updateData(gpsinfo, entry)
+ end
+ end
+ until( os.time() - start_time > arg_timeout or hasAllData(gpsinfo) )
+
+ socket:send('?WATCH={"enable":false}\r\n')
+
+ if ( not(hasAllData(gpsinfo)) ) then
+ return
+ end
+
+ local output = {
+ ("Time of fix: %s"):format(datetime.format_timestamp(gps.Util.convertTime(gpsinfo.date, gpsinfo.time))),
+ ("Coordinates: %.4f,%.4f"):format(tonumber(gpsinfo.latitude), tonumber(gpsinfo.longitude)),
+ ("Speed: %s knots"):format(gpsinfo.speed)
+ }
+ return stdnse.format_output(true, output)
+end