mtik 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|