From 136c7fc10e0265fba614fff6aa6ba00bb9485bda Mon Sep 17 00:00:00 2001 From: ytti Date: Thu, 14 Jun 2018 17:19:38 +0300 Subject: Fix 1385 - telnet broken Refactor to common login method to ssh/telnet was broken, as common login method made assumptions of expect and cmd API which weren't true for telnet. telnet.rb updated to resemble ssh.rb API. --- lib/oxidized/input/telnet.rb | 102 ++++++++++++------------------------------- lib/oxidized/version.rb | 2 +- 2 files changed, 30 insertions(+), 74 deletions(-) (limited to 'lib') diff --git a/lib/oxidized/input/telnet.rb b/lib/oxidized/input/telnet.rb index 102bc8c..63d811f 100644 --- a/lib/oxidized/input/telnet.rb +++ b/lib/oxidized/input/telnet.rb @@ -25,16 +25,19 @@ module Oxidized rescue Timeout::Error raise PromptUndetect, ['unable to detect prompt:', @node.prompt].join(' ') end + connected? end def connected? @telnet and not @telnet.sock.closed? end - def cmd cmd, expect = @node.prompt - Oxidized.logger.debug "Telnet: #{cmd} @#{@node.name}" - args = { 'String' => cmd } - args.merge!({ 'Match' => expect, 'Timeout' => @timeout }) if expect + def cmd cmd_str, expect = @node.prompt + return send(cmd_str + "\n") unless expect + Oxidized.logger.debug "Telnet: #{cmd_str} @#{@node.name}" + args = { 'String' => cmd_str, + 'Match' => expect, + 'Timeout' => @timeout } @telnet.cmd args end @@ -49,7 +52,7 @@ module Oxidized private def expect re - @telnet.waitfor 'Match' => re, 'Timeout' => @timeout + @telnet.oxidized_expect expect: re, timeout: @timeout end def disconnect @@ -66,75 +69,36 @@ module Oxidized end class Net::Telnet - ## FIXME: we just need 'line = model.expects line' to handle pager ## how to do this, without redefining the whole damn thing ## FIXME: we also need output (not sure I'm going to support this) attr_reader :output - def waitfor(options) # :yield: recvdata - time_out = @options["Timeout"] - waittime = @options["Waittime"] - fail_eof = @options["FailEOF"] + def oxidized_expect(options) # :yield: recvdata model = @options["Model"] @log = @options["Log"] - if options.kind_of?(Hash) - prompt = if options.has_key?("Match") - options["Match"] - elsif options.has_key?("Prompt") - options["Prompt"] - elsif options.has_key?("String") - Regexp.new(Regexp.quote(options["String"])) - end - time_out = options["Timeout"] if options.has_key?("Timeout") - waittime = options["Waittime"] if options.has_key?("Waittime") - fail_eof = options["FailEOF"] if options.has_key?("FailEOF") - else - prompt = options - end - - if time_out == false - time_out = nil - end + expects = [options[:expect]].flatten + time_out = options[:timeout] || @options["Timeout"] || Oxidized.config.timeout? - line = '' - buf = '' - rest = '' - until prompt === line and not IO::select([@sock], nil, nil, waittime) - unless IO::select([@sock], nil, nil, time_out) - raise Timeout::Error, "timed out while waiting for more data" - end - begin + Timeout::timeout(time_out) do + line = "" + rest = "" + buf = "" + loop do c = @sock.readpartial(1024 * 1024) @output = c - @dumplog.log_dump('<', c) if @options.has_key?("Dump_log") - if @options["Telnetmode"] - c = rest + c - if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) < - Integer(c.rindex(/#{IAC}#{SB}/no) || 0) - buf = preprocess(c[0...c.rindex(/#{IAC}#{SB}/no)]) - rest = c[c.rindex(/#{IAC}#{SB}/no)..-1] - elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) || - c.rindex(/\r\z/no) - buf = preprocess(c[0...pt]) - rest = c[pt..-1] - else - buf = preprocess(c) - rest = '' - end + c = rest + c + + if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) < + Integer(c.rindex(/#{IAC}#{SB}/no) || 0) + buf = preprocess(c[0...c.rindex(/#{IAC}#{SB}/no)]) + rest = c[c.rindex(/#{IAC}#{SB}/no)..-1] + elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) || + c.rindex(/\r\z/no) + buf = preprocess(c[0...pt]) + rest = c[pt..-1] else - # Not Telnetmode. - # - # We cannot use preprocess() on this data, because that - # method makes some Telnetmode-specific assumptions. - buf = rest + c + buf = preprocess(c) rest = '' - unless @options["Binmode"] - if pt = buf.rindex(/\r\z/no) - buf = buf[0...pt] - rest = buf[pt..-1] - end - buf.gsub!(/#{EOL}/no, "\n") - end end if Oxidized.config.input.debug? @log.print buf @@ -142,17 +106,9 @@ class Net::Telnet end line += buf line = model.expects line - line = yield line if block_given? - yield buf if block_given? - rescue EOFError # End of file reached - raise if fail_eof - if line == '' - line = nil - yield nil if block_given? - end - break + match = expects.find { |re| line.match re } + return match if match end end - line end end diff --git a/lib/oxidized/version.rb b/lib/oxidized/version.rb index 4b710ef..c44884a 100644 --- a/lib/oxidized/version.rb +++ b/lib/oxidized/version.rb @@ -1,6 +1,6 @@ module Oxidized VERSION = '0.23.0' - VERSION_FULL = '0.23.0' + VERSION_FULL = '0.23.0-19-g4690521' def self.version_set version_full = %x(git describe --tags).chop rescue "" version = %x(git describe --tags --abbrev=0).chop rescue "" -- cgit v1.2.1