diff --git a/lib/watchmonkey_cli.rb b/lib/watchmonkey_cli.rb index 9fec3bb..52fc737 100644 --- a/lib/watchmonkey_cli.rb +++ b/lib/watchmonkey_cli.rb @@ -37,6 +37,7 @@ require "watchmonkey_cli/checkers/ssl_expiration" require "watchmonkey_cli/checkers/tcp_port" require "watchmonkey_cli/checkers/ts3_license" +require "watchmonkey_cli/checkers/udp_port" require "watchmonkey_cli/checkers/unix_defaults" require "watchmonkey_cli/checkers/unix_df" require "watchmonkey_cli/checkers/unix_file_exists" diff --git a/lib/watchmonkey_cli/application/configuration.tpl b/lib/watchmonkey_cli/application/configuration.tpl index dc23ce3..f2b445c 100644 --- a/lib/watchmonkey_cli/application/configuration.tpl +++ b/lib/watchmonkey_cli/application/configuration.tpl @@ -73,6 +73,24 @@ tcp_port "ftp.example.com", 21, message: "FTP offline" tcp_port :my_server, 21, message: "FTP offline" +# ----- +# UDP port +# ----- +# Attempts to establish a UDP connection to a given port. +# NOTE: We send a message and attempt to receive a response. +# If the port is closed we get an IO exception and assume the port to be unreachable. +# If the port is open we most likely don't get ANY response and when the timeout +# is reached we assume the port to be reachable. This is not an exact check. +# Host might be :local/SSH connection/String(IP/DNS) +# Available options: +# +# message Error message when connection cannot be established +# timeout Timeout in seconds to wait for a response (default = 2 seconds - false/nil = 1 hour) +# +udp_port "example.com", 9987, message: "Teamspeak offline" +udp_port :my_server, 9987, message: "Teamspeak offline" + + # ----- # FTP availability # ----- diff --git a/lib/watchmonkey_cli/checkers/udp_port.rb b/lib/watchmonkey_cli/checkers/udp_port.rb new file mode 100644 index 0000000..af8531f --- /dev/null +++ b/lib/watchmonkey_cli/checkers/udp_port.rb @@ -0,0 +1,34 @@ +module WatchmonkeyCli + module Checkers + class UdpPort < Checker + self.checker_name = "udp_port" + + def enqueue host, port, opts = {} + opts = { message: "Port #{port} (UDP) is not reachable!", timeout: 2 }.merge(opts) + host = app.fetch_connection(:loopback, :local) if !host || host == :local + host = app.fetch_connection(:ssh, host) if host.is_a?(Symbol) + app.enqueue(self, host, port, opts) + end + + def check! result, host, port, opts = {} + result.result = port_open?(host.is_a?(String) ? host : host.is_a?(WatchmonkeyCli::LoopbackConnection) ? "127.0.0.1" : host.opts[:host_name] || host.opts[:host] || host.opts[:ip], port, opts) + result.error! "#{opts[:message]}" unless result.result + end + + def port_open?(ip, port, opts = {}) + Timeout::timeout(opts[:timeout] ? opts[:timeout] : 3600) do + s = UDPSocket.new + s.connect(ip, port) + s.send "aaa", 0 + s.recv(1) + s.close + end + true + rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH + return false + rescue Timeout::Error + return true + end + end + end +end