mtik 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ 2010-02-05 (05 FEB 2010) VERSION 3.0.2 Aaron D. Gifford (http://www.aarongifford.com)
2
+ * Typo fixes to example tikfetch.rb
3
+ * Multi-command functionality added to interactive client and to tikcommand.rb example
4
+ * Removed kludge path stuff for author's broken FreeBSD Ruby 1.9.1 gem system
5
+ * Removed lame JSON-ifier from example and switched to require 'json' instead
6
+
7
+ 2010-01-19 (19 JAN 2010) VERSION 3.0.1 Aaron D. Gifford (http://www.aarongifford.com/)
8
+ * Added support for '/tool/fetch' 'requesting' state
9
+ * Added auto-cancel of finished '/tool/fetch' command in MTik#command()
10
+ * Added MTik::Request#cancel() method
11
+ * Added MTik::Request#state() attr_reader (and new @state object property to replace
12
+ the @completed boolean property)
13
+ * MTik::Request objects now associate with the appropriate MTik::Connection object
14
+ upon MTik::Connection transmitting the request to a device (which facilities)
15
+ the MTik::Request@cancel() method
16
+ * Removed gem root directory mtik.rb file that was acting as a kludge for the author's
17
+ messed-up FreeBSD Ruby 1.9 installation
18
+ * Renamed examples with a 'tik' prefix
19
+
20
+ 2010-01-15 (15 JAN 2010) VERSION 3.0.0 Aaron D. Gifford (http://www.aarongifford.com/)
21
+ * Bumped the version to 3.0.0 due to modularization and gemification changes
22
+ that break any software using the older Ruby API classes.
23
+ * Split out (as separate files) and added a few more examples:
24
+ cli.rb
25
+ command.rb
26
+ json.rb
27
+ fetch.rb
28
+ * Added VERSION.txt, CHANGELOG.txt, README.txt, LICENSE.txt, and *.gemspec files, moved
29
+ the example files into the bin subdirectory
@@ -0,0 +1,36 @@
1
+ ########################################################################
2
+ #--
3
+ #
4
+ # GEM: MTik -- A Ruby gem implementing the MikroTik RouterOS API
5
+ #
6
+ #++
7
+ # Author:: Aaron D. Gifford - http://www.aarongifford.com/
8
+ # Copyright:: Copyright (c) 2009-2010, InfoWest, Inc.
9
+ # License:: BSD license
10
+ #--
11
+ # Redistribution and use in source and binary forms, with or without
12
+ # modification, are permitted provided that the following conditions
13
+ # are met:
14
+ # 1. Redistributions of source code must retain the above copyright
15
+ # notice, the above list of authors and contributors, this list of
16
+ # conditions and the following disclaimer.
17
+ # 2. Redistributions in binary form must reproduce the above copyright
18
+ # notice, this list of conditions and the following disclaimer in the
19
+ # documentation and/or other materials provided with the distribution.
20
+ # 3. Neither the name of the author(s) or copyright holder(s) nor the
21
+ # names of any contributors may be used to endorse or promote products
22
+ # derived from this software without specific prior written permission.
23
+ #
24
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S), AUTHOR(S) AND
25
+ # CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
26
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), AUTHOR(S), OR CONTRIBUTORS BE
29
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
+ # DCONSEQUENTIAL AMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35
+ # THE POSSIBILITY OF SUCH DAMAGE.
36
+ ########################################################################
@@ -0,0 +1,64 @@
1
+ = MTik -- A Ruby implementation of the MikroTik RouterOS API
2
+
3
+ The MTik gem implements the MikroTik RouterOS API for connecting to
4
+ devices running RouterOS (with the API enabled) over the network.
5
+
6
+
7
+ == Examples
8
+
9
+ Included in the examples subdirectory are four example ruby scripts
10
+ that use the Ruby API implementation:
11
+
12
+ tikcli.rb:: A command-line-like API interface
13
+ tikcommand.rb:: A tool for executing a single API command from
14
+ a unix command-line
15
+ tikfetch.rb:: A tool for instructing devices to download files
16
+ from specified URLs (unix command-line tool)
17
+ tikjson.rb:: Like 'command.rb' a tool for executing a single
18
+ API command, except the output is formatted in
19
+ JSON-style
20
+
21
+
22
+ == Download
23
+
24
+ The latest version of MTik can be found at
25
+
26
+ * http://www.aarongifford.com/computers/mtik/
27
+
28
+ Ruby RDoc documentation can be found online at
29
+
30
+ * http://www.aarongifford.com/computers/mtik/latest/doc/
31
+
32
+ Additional documentation is available at
33
+
34
+ * http://www.aarongifford.com/computers/mtik/
35
+ * http://wiki.mikrotik.com/wiki/API_Ruby_class
36
+
37
+ For documentation on the MikroTik RouterOS APi, see
38
+
39
+ * http://wiki.mikrotik.com/wiki/API
40
+
41
+
42
+ == Installation
43
+
44
+ To install MTik is through its GEM file:
45
+
46
+ % [sudo] gem install mtik-3.3.0.gem
47
+
48
+ == License
49
+
50
+ This gem and all other scripts and documentation files are licensed
51
+ under a BSD-style license. (See the LICENSE.txt file.)
52
+
53
+
54
+ == Report Bugs
55
+
56
+ Please report bugs by going to the author's web site and clicking on the
57
+ "Contact Me" link in the left-hand menu. The direct URL is:
58
+
59
+ * http://www.aarongifford.com/leaveanote.html
60
+
61
+ Thank you!
62
+
63
+ -- Aaron D. Gifford
64
+
@@ -0,0 +1 @@
1
+ 3.0.2
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ ########################################################################
3
+ #--
4
+ #
5
+ # FILE: tikcli.rb -- Example of using the Ruby MikroTik API in Ruby
6
+ #
7
+ #++
8
+ # Author:: Aaron D. Gifford - http://www.aarongifford.com/
9
+ # Copyright:: Copyright (c) 2009-2010, InfoWest, Inc.
10
+ # License:: BSD license
11
+ #--
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions
14
+ # are met:
15
+ # 1. Redistributions of source code must retain the above copyright
16
+ # notice, the above list of authors and contributors, this list of
17
+ # conditions and the following disclaimer.
18
+ # 2. Redistributions in binary form must reproduce the above copyright
19
+ # notice, this list of conditions and the following disclaimer in the
20
+ # documentation and/or other materials provided with the distribution.
21
+ # 3. Neither the name of the author(s) or copyright holder(s) nor the
22
+ # names of any contributors may be used to endorse or promote products
23
+ # derived from this software without specific prior written permission.
24
+ #
25
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S), AUTHOR(S) AND
26
+ # CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
29
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), AUTHOR(S), OR CONTRIBUTORS BE
30
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
+ # DCONSEQUENTIAL AMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36
+ # THE POSSIBILITY OF SUCH DAMAGE.
37
+ ########################################################################
38
+ $LOAD_PATH.unshift(File.dirname(__FILE__)+'/../lib')
39
+
40
+ require 'rubygems'
41
+ require 'mtik'
42
+
43
+ unless ARGV.length == 3
44
+ STDERR.print("Usage: #{$0} <host> <user> <pass>\n")
45
+ exit(-1)
46
+ end
47
+
48
+ MTik::interactive_client(ARGV[0], ARGV[1], ARGV[2])
49
+
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+ ########################################################################
3
+ #--
4
+ #
5
+ # FILE: command.rb -- Example of using the Ruby MikroTik API in Ruby
6
+ #
7
+ #++
8
+ # Author:: Aaron D. Gifford - http://www.aarongifford.com/
9
+ # Copyright:: Copyright (c) 2009-2010, InfoWest, Inc.
10
+ # License:: BSD license
11
+ #--
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions
14
+ # are met:
15
+ # 1. Redistributions of source code must retain the above copyright
16
+ # notice, the above list of authors and contributors, this list of
17
+ # conditions and the following disclaimer.
18
+ # 2. Redistributions in binary form must reproduce the above copyright
19
+ # notice, this list of conditions and the following disclaimer in the
20
+ # documentation and/or other materials provided with the distribution.
21
+ # 3. Neither the name of the author(s) or copyright holder(s) nor the
22
+ # names of any contributors may be used to endorse or promote products
23
+ # derived from this software without specific prior written permission.
24
+ #
25
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S), AUTHOR(S) AND
26
+ # CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
29
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), AUTHOR(S), OR CONTRIBUTORS BE
30
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
+ # DCONSEQUENTIAL AMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36
+ # THE POSSIBILITY OF SUCH DAMAGE.
37
+ ########################################################################
38
+ $LOAD_PATH.unshift(File.dirname(__FILE__)+'/../lib')
39
+
40
+ require 'rubygems'
41
+ require 'mtik'
42
+
43
+ unless ARGV.length > 3
44
+ STDERR.print("Usage: #{$0} <host> <user> <pass> <command> [<args>...] [<command> [<args> ...]]\n")
45
+ exit(-1)
46
+ end
47
+
48
+ MTik::verbose = true ## Set how you want
49
+
50
+ ## Detect multiple command sequences and build an array of arrays
51
+ ## where each outer array element is a command plus arguments:
52
+ command = Array.new
53
+ i = 3
54
+ while i < ARGV.length
55
+ if ARGV[i][0,1] == '/' ## Command detected...
56
+ command << [ ARGV[i] ]
57
+ else
58
+ command[command.length-1] << ARGV[i]
59
+ end
60
+ i += 1
61
+ end
62
+
63
+ p MTik::command(
64
+ :host=>ARGV[0],
65
+ :user=>ARGV[1],
66
+ :pass=>ARGV[2],
67
+ :command=>command
68
+ )
69
+
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+ ########################################################################
3
+ #--
4
+ #
5
+ # FILE: fetch.rb -- Example of using the Ruby MikroTik API in Ruby
6
+ #
7
+ #++
8
+ # Author:: Aaron D. Gifford - http://www.aarongifford.com/
9
+ # Copyright:: Copyright (c) 2009-2010, InfoWest, Inc.
10
+ # License:: BSD license
11
+ #--
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions
14
+ # are met:
15
+ # 1. Redistributions of source code must retain the above copyright
16
+ # notice, the above list of authors and contributors, this list of
17
+ # conditions and the following disclaimer.
18
+ # 2. Redistributions in binary form must reproduce the above copyright
19
+ # notice, this list of conditions and the following disclaimer in the
20
+ # documentation and/or other materials provided with the distribution.
21
+ # 3. Neither the name of the author(s) or copyright holder(s) nor the
22
+ # names of any contributors may be used to endorse or promote products
23
+ # derived from this software without specific prior written permission.
24
+ #
25
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S), AUTHOR(S) AND
26
+ # CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
29
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), AUTHOR(S), OR CONTRIBUTORS BE
30
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
+ # DCONSEQUENTIAL AMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36
+ # THE POSSIBILITY OF SUCH DAMAGE.
37
+ ########################################################################
38
+ $LOAD_PATH.unshift(File.dirname(__FILE__)+'/../lib')
39
+
40
+ require 'rubygems'
41
+ require 'mtik'
42
+
43
+ ## Uncomment this (set $VERBOSE to true) if you want crazy verbose
44
+ ## output of all API interactions:
45
+ #MTik::verbose = true
46
+
47
+ if ARGV.length < 5 || ARGV.length % 2 != 1
48
+ print "Usage: #{$0} <device> <user> <pass> <url> <localfilename> [<url> <localfilename>...]\n"
49
+ exit
50
+ end
51
+
52
+ host = ARGV.shift
53
+ user = ARGV.shift
54
+ pass = ARGV.shift
55
+ begin
56
+ mt = MTik::Connection.new(:host=>host, :user=>user, :pass=>pass)
57
+ rescue Errno::ETIMEDOUT, Errno::ENETUNREACH, Errno::EHOSTUNREACH, MTik::Error => e
58
+ print ">>> ERROR CONNECTING: #{e}"
59
+ exit
60
+ end
61
+
62
+ ## List all files:
63
+ files = Hash.new
64
+ mt.get_reply_each('/file/getall') do |req, s|
65
+ unless s.key?('!done')
66
+ files[s['name']] = true
67
+ end
68
+ end
69
+
70
+ while ARGV.length > 0
71
+ url, filename = ARGV.shift, ARGV.shift
72
+ if files.key?(filename)
73
+ print ">>> ERROR: There is a file named '#{filename}' already on the device.\n"
74
+ else
75
+ print ">>> OK: Fetching file '#{filename}' from URL '#{url}'...\n"
76
+ mt.fetch(url, filename) do |status, total, bytes|
77
+ case status
78
+ when 'failed'
79
+ print ">>> ERROR: File '#{filename}' download failed!\n"
80
+ when 'finished'
81
+ print ">>> OK: File '#{filename}' download finished.\n"
82
+ when 'connecting'
83
+ print ">>> OK: Connecting to '#{url}' to download file '#{filename}'\n"
84
+ when 'downloading'
85
+ print ">>> OK: Downloaded #{bytes} bytes of #{total} of file " +
86
+ "'#{filename}' " +
87
+ (total > 0 ? '%0.2f' % (100.0*bytes/total) : '0') +
88
+ "%\n"
89
+ else
90
+ print ">>> ERROR: The following trap error occured: #{status}\n"
91
+ end
92
+ end
93
+ end
94
+ end
95
+ mt.wait_all
96
+
97
+ print "\n"
98
+ print "SIZE CREATED FILENAME\n"
99
+ print "====================================================================\n"
100
+ mt.get_reply_each('/file/getall') do |req, s|
101
+ unless s.key?('!done')
102
+ print "#{(s['size']+' ')[0,10]} #{s['creation-time']} #{s['name']}\n"
103
+ end
104
+ end
105
+
106
+ print "\n"
107
+
108
+ mt.close
109
+
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ ########################################################################
3
+ #--
4
+ #
5
+ # FILE: json.rb -- Example of using the Ruby MikroTik API in Ruby
6
+ #
7
+ #++
8
+ # Author:: Aaron D. Gifford - http://www.aarongifford.com/
9
+ # Copyright:: Copyright (c) 2009-2010, InfoWest, Inc.
10
+ # License:: BSD license
11
+ #--
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions
14
+ # are met:
15
+ # 1. Redistributions of source code must retain the above copyright
16
+ # notice, the above list of authors and contributors, this list of
17
+ # conditions and the following disclaimer.
18
+ # 2. Redistributions in binary form must reproduce the above copyright
19
+ # notice, this list of conditions and the following disclaimer in the
20
+ # documentation and/or other materials provided with the distribution.
21
+ # 3. Neither the name of the author(s) or copyright holder(s) nor the
22
+ # names of any contributors may be used to endorse or promote products
23
+ # derived from this software without specific prior written permission.
24
+ #
25
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S), AUTHOR(S) AND
26
+ # CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
29
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), AUTHOR(S), OR CONTRIBUTORS BE
30
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
+ # DCONSEQUENTIAL AMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36
+ # THE POSSIBILITY OF SUCH DAMAGE.
37
+ ########################################################################
38
+ $LOAD_PATH.unshift(File.dirname(__FILE__)+'/../lib')
39
+
40
+ require 'rubygems'
41
+ require 'mtik'
42
+ require 'json'
43
+
44
+ unless ARGV.length > 3
45
+ STDERR.print("Usage: #{$0} <host> <user> <pass> <command> [<args>...] [<command> [<args> ...]]\n")
46
+ exit(-1)
47
+ end
48
+
49
+ ## Detect multiple command sequences and build an array of arrays
50
+ ## where each outer array element is a command plus arguments:
51
+ command = Array.new
52
+ i = 3
53
+ while i < ARGV.length
54
+ if ARGV[i][0,1] == '/' ## Command detected...
55
+ command << [ ARGV[i] ]
56
+ else
57
+ command[command.length-1] << ARGV[i]
58
+ end
59
+ i += 1
60
+ end
61
+
62
+ print MTik::command(
63
+ :host=>ARGV[0],
64
+ :user=>ARGV[1],
65
+ :pass=>ARGV[2],
66
+ :command=>command
67
+ ).to_json + "\n"
68
+
@@ -0,0 +1,244 @@
1
+ ############################################################################
2
+ ## A Ruby library implementing the Ruby MikroTik API
3
+ ############################################################################
4
+ ## Author:: Aaron D. Gifford - http://www.aarongifford.com/
5
+ ## Copyright:: Copyright (c) 2009-2010, InfoWest, Inc.
6
+ ## License:: BSD license
7
+ ##
8
+ ## Redistribution and use in source and binary forms, with or without
9
+ ## modification, are permitted provided that the following conditions
10
+ ## are met:
11
+ ## 1. Redistributions of source code must retain the above copyright
12
+ ## notice, the above list of authors and contributors, this list of
13
+ ## conditions and the following disclaimer.
14
+ ## 2. Redistributions in binary form must reproduce the above copyright
15
+ ## notice, this list of conditions and the following disclaimer in the
16
+ ## documentation and/or other materials provided with the distribution.
17
+ ## 3. Neither the name of the author(s) or copyright holder(s) nor the
18
+ ## names of any contributors may be used to endorse or promote products
19
+ ## derived from this software without specific prior written permission.
20
+ ##
21
+ ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S), AUTHOR(S) AND
22
+ ## CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
23
+ ## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
+ ## AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
25
+ ## IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), AUTHOR(S), OR CONTRIBUTORS BE
26
+ ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ ## DCONSEQUENTIAL AMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32
+ ## THE POSSIBILITY OF SUCH DAMAGE.
33
+ ############################################################################
34
+ module MTik
35
+ require 'mtik/error.rb'
36
+ require 'mtik/fatalerror.rb'
37
+ require 'mtik/timeouterror.rb'
38
+ require 'mtik/request.rb'
39
+ require 'mtik/reply.rb'
40
+ require 'mtik/connection.rb'
41
+
42
+ ## Default MikroTik RouterOS API TCP port:
43
+ PORT = 8728
44
+ ## Default username to use if none is specified:
45
+ USER = 'admin'
46
+ ## Default password to use if none is specified:
47
+ PASS = ''
48
+ ## Connection timeout default -- *NOT USED*
49
+ CONN_TIMEOUT = 60
50
+ ## Command timeout -- The maximum number of seconds to wait for more
51
+ ## API data when expecting one or more command responses.
52
+ CMD_TIMEOUT = 60
53
+
54
+ @verbose = false
55
+ @debug = false
56
+
57
+ ## Access the current verbose setting (boolean)
58
+ def self.verbose
59
+ return @verbose
60
+ end
61
+
62
+ ## Change the current verbose setting (boolean)
63
+ def self.verbose=(x)
64
+ return @verbose = x
65
+ end
66
+
67
+ ## Access the current debug setting (boolean)
68
+ def self.debug
69
+ return @debug
70
+ end
71
+
72
+ ## Change the current debug setting (boolean)
73
+ def self.debug=(x)
74
+ return @debug = x
75
+ end
76
+
77
+
78
+ ## Act as an interactive client with the device, accepting user
79
+ ## input from STDIN.
80
+ def self.interactive_client(host, user, pass)
81
+ old_verbose = MTik::verbose
82
+ MTik::verbose = true
83
+ begin
84
+ tk = MTik::Connection.new(:host => host, :user => user, :pass => pass)
85
+ rescue MTik::Error, Errno::ECONNREFUSED => e
86
+ print "=== LOGIN ERROR: #{e.message}\n"
87
+ exit
88
+ end
89
+
90
+ while true
91
+ print "\nCommand (/quit to end): "
92
+ cmd = STDIN.gets.sub(/^\s+/, '').sub(/\s*[\r\n]*$/, '')
93
+ maxreply = 0
94
+ m = /^(\d+):/.match(cmd)
95
+ unless m.nil?
96
+ maxreply = m[1].to_i
97
+ cmd.sub!(/^\d+:/, '')
98
+ end
99
+ args = cmd.split(/\s+/)
100
+ cmd = args.shift
101
+ next if cmd == ''
102
+ break if cmd == '/quit'
103
+ unless /^(?:\/[a-zA-Z0-9]+)+$/.match(cmd)
104
+ print "=== INVALID COMMAND: #{cmd}\n" if MTik::debug || MTik::verbose
105
+ break
106
+ end
107
+ print "=== COMMAND: #{cmd}\n" if MTik::debug || MTik::verbose
108
+ trap = false
109
+ count = 0
110
+ state = 0
111
+ begin
112
+ tk.send_request(false, cmd, args) do |req, sentence|
113
+ if sentence.key?('!trap')
114
+ trap = sentence
115
+ print "=== TRAP: '" + (trap.key?('message') ? trap['message'] : "UNKNOWN") + "'\n\n"
116
+ elsif sentence.key?('!re')
117
+ count += 1
118
+ ## Auto-cancel any '/tool/fetch' commands that have finished,
119
+ ## or commands that have received the specified number of
120
+ ## replies:
121
+ if req.state != 'cancelled' && (
122
+ cmd == '/tool/fetch' && sentence.key?('status') && sentence['status'] == 'finished'
123
+ ) || (maxreply > 0 && count == maxreply)
124
+ state = 2
125
+ req.cancel do |req, sentence|
126
+ state = 1
127
+ end
128
+ end
129
+ elsif !sentence.key?('!done') && !sentence.key?('!fatal')
130
+ raise MTik::Error.new("Unknown or unexpected reply sentence type.")
131
+ end
132
+ if state == 0 && req.done?
133
+ state = 1
134
+ end
135
+ end
136
+ while state != 1
137
+ tk.wait_for_reply
138
+ end
139
+ rescue MTik::Error => e
140
+ print "=== ERROR: #{e.message}\n"
141
+ end
142
+ unless tk.connected?
143
+ begin
144
+ tk.login
145
+ rescue MTik::Error => e
146
+ print "=== LOGIN ERROR: #{e.message}\n"
147
+ tk.close
148
+ exit
149
+ end
150
+ end
151
+ end
152
+
153
+ reply = tk.get_reply('/quit')
154
+ unless reply[0].key?('!fatal')
155
+ raise MTik::Error.new("Unexpected response to '/quit' command.")
156
+ end
157
+
158
+ ## Extract any device-provided message from the '!fatal' response
159
+ ## to the /quit command:
160
+ print "=== SESSION TERMINATED"
161
+ message = ''
162
+ reply[0].each_key do |key|
163
+ next if key == '!fatal'
164
+ message += "'#{key}'"
165
+ unless reply[0][key].nil?
166
+ message += " => '#{reply[0][key]}'"
167
+ end
168
+ end
169
+ if message.length > 0
170
+ print ": " + message
171
+ else
172
+ print " ==="
173
+ end
174
+ print "\n\n"
175
+
176
+ unless tk.connected?
177
+ print "=== Disconnected ===\n\n"
178
+ else
179
+ ## In theory, this should never execute:
180
+ tk.close
181
+ end
182
+
183
+ MTik::verbose = old_verbose
184
+ end
185
+
186
+
187
+ ## An all-in-one function to instantiate, connect, send one or
188
+ ## more commands, retrieve the response(s), close the connection,
189
+ ## and return the response(s).
190
+ ##
191
+ ## *WARNING* :: If you use this call with an API command like
192
+ ## +/tool/fetch+ it will forever keep reading replies, never
193
+ ## returning. So do _NOT_ use this with any API command that does
194
+ ## not complete with a "!done" with no additional interaction.
195
+ def self.command(args)
196
+ tk = MTik::Connection.new(
197
+ :host => args[:host],
198
+ :user => args[:user],
199
+ :pass => args[:pass],
200
+ :port => args[:port],
201
+ :conn_timeout => args[:conn_timeout],
202
+ :cmd_timeout => args[:cmd_timeout]
203
+ )
204
+ cmd = args[:command]
205
+ replies = Array.new
206
+ if cmd.is_a?(String)
207
+ ## Single command, no arguments
208
+ cmd = [ [ cmd ] ]
209
+ elsif cmd.is_a?(Array) && !cmd[0].is_a?(Array)
210
+ ## Single command, possibly arguments
211
+ cmd = [ cmd ]
212
+ end
213
+
214
+ cmd.each do |c|
215
+ replycount = 1
216
+ tk.send_request(false, c[0], c[1,c.length-1]) do |req, sentence|
217
+ replycount += 1
218
+ if c[0] == '/tool/fetch'
219
+ if (
220
+ sentence.key?('status') &&
221
+ sentence['status'] == 'finished' &&
222
+ req.state != 'cancelled'
223
+ )
224
+ ## Cancel 'finished' fetch commands
225
+ req.cancel
226
+ end
227
+ elsif replycount >= 1000 && req.state != 'cancelled'
228
+ ## Auto-cancel any command after 1,000 replies:
229
+ req.cancel
230
+ end
231
+ if sentence.key?('!done')
232
+ replies.push(req.reply)
233
+ end
234
+ end
235
+ end
236
+
237
+ tk.wait_all ## Event loop -- wait for all commands
238
+ tk.get_reply('/quit')
239
+ tk.close
240
+ return replies
241
+ end
242
+
243
+ end
244
+