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.
- data/CHANGELOG.txt +29 -0
- data/LICENSE.txt +36 -0
- data/README.txt +64 -0
- data/VERSION.txt +1 -0
- data/examples/tikcli.rb +49 -0
- data/examples/tikcommand.rb +69 -0
- data/examples/tikfetch.rb +109 -0
- data/examples/tikjson.rb +68 -0
- data/lib/mtik.rb +244 -0
- data/lib/mtik/connection.rb +603 -0
- data/lib/mtik/error.rb +37 -0
- data/lib/mtik/fatalerror.rb +37 -0
- data/lib/mtik/reply.rb +50 -0
- data/lib/mtik/request.rb +265 -0
- data/lib/mtik/timeouterror.rb +37 -0
- metadata +67 -0
data/CHANGELOG.txt
ADDED
@@ -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
|
data/LICENSE.txt
ADDED
@@ -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
|
+
########################################################################
|
data/README.txt
ADDED
@@ -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
|
+
|
data/VERSION.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.0.2
|
data/examples/tikcli.rb
ADDED
@@ -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
|
+
|
data/examples/tikjson.rb
ADDED
@@ -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
|
+
|
data/lib/mtik.rb
ADDED
@@ -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
|
+
|