netsnmp 0.0.0

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,167 @@
1
+ module NETSNMP::Core
2
+ # Maps to the relevant netsnmp C library structs.
3
+ module Structures
4
+ extend FFI::Library
5
+ typedef :u_long, :oid
6
+
7
+ callback(:snmp_callback, [ :int, :pointer, :int, :pointer, :pointer ], :int)
8
+ callback(:netsnmp_callback, [ :int, :pointer, :int, :pointer, :pointer ], :int)
9
+
10
+ class SessionList < FFI::Struct
11
+ layout(
12
+ :next, :pointer,
13
+ :session, :pointer,
14
+ :transport, :pointer,
15
+ :internal, :pointer
16
+ )
17
+ end
18
+
19
+ class Transport < FFI::Struct
20
+ layout(
21
+ :domain, :pointer,
22
+ :domain_length, :int,
23
+ :local, :pointer,
24
+ :local_length, :int,
25
+ :remote, :pointer,
26
+ :remote_length, :int,
27
+ :sock, :int,
28
+ :flags, :u_int,
29
+ :data, :pointer,
30
+ :data_length, :int,
31
+ :msgMaxSize, :size_t,
32
+ :base_transport, :pointer
33
+ )
34
+ end
35
+
36
+ class Session < FFI::Struct
37
+ layout(
38
+ :version, :long,
39
+ :retries, :int,
40
+ :timeout, :long,
41
+ :flags, :u_long,
42
+ :subsession, :pointer,
43
+ :next, :pointer,
44
+ :peername, :pointer,
45
+ :remote_port, :u_short,
46
+ :localname, :pointer,
47
+ :local_port, :u_short,
48
+ :authenticator, callback([ :pointer, :pointer, :pointer, :uint ], :pointer),
49
+ :callback, :netsnmp_callback,
50
+ :callback_magic, :pointer,
51
+ :s_errno, :int,
52
+ :s_snmp_errno, :int,
53
+ :sessid, :long,
54
+ :community, :pointer,
55
+ :community_len, :size_t,
56
+ :rcvMsgMaxSize, :size_t,
57
+ :sndMsgMaxSize, :size_t,
58
+ :isAuthoritative, :u_char,
59
+ :contextEngineID, :pointer,
60
+ :contextEngineIDLen, :size_t,
61
+ :engineBoots, :u_int,
62
+ :engineTime, :u_int,
63
+ :contextName, :pointer,
64
+ :contextNameLen, :size_t,
65
+ :securityEngineID, :pointer,
66
+ :securityEngineIDLen, :size_t,
67
+ :securityName, :pointer,
68
+ :securityNameLen, :size_t,
69
+ :securityAuthProto, :pointer,
70
+ :securityAuthProtoLen, :size_t,
71
+ :securityAuthKey, [:u_char, 32],
72
+ :securityAuthKeyLen, :size_t,
73
+ :securityAuthLocalKey, :pointer,
74
+ :securityAuthLocalKeyLen, :size_t,
75
+ :securityPrivProto, :pointer,
76
+ :securityPrivProtoLen, :size_t,
77
+ :securityPrivKey, [:u_char, 32],
78
+ :securityPrivKeyLen, :size_t,
79
+ :securityPrivLocalKey, :pointer,
80
+ :securityPrivLocalKeyLen, :size_t,
81
+ :securityModel, :int,
82
+ :securityLevel, :int,
83
+ :paramName, :pointer,
84
+ :securityInfo, :pointer,
85
+ :myvoid, :pointer
86
+ )
87
+ end
88
+
89
+ class Vardata < FFI::Union
90
+ layout(
91
+ :integer, :pointer,
92
+ :string, :pointer,
93
+ :objid, :pointer,
94
+ :bitstring, :pointer,
95
+ :counter64, :pointer,
96
+ :float, :pointer,
97
+ :double, :pointer
98
+ )
99
+ end
100
+
101
+ class VariableList < FFI::Struct
102
+ layout(
103
+ :next_variable, :pointer,#VariableList.typed_pointer,
104
+ :name, :pointer,
105
+ :name_length, :size_t,
106
+ :type, :u_char,
107
+ :val, Vardata,
108
+ :val_len, :size_t,
109
+ :name_loc, [:oid, Constants::MAX_OID_LEN],
110
+ :buf, [:u_char, 40],
111
+ :data, :pointer,
112
+ :dataFreeHook, callback([ :pointer ], :void),
113
+ :index, :int
114
+ )
115
+ end
116
+
117
+
118
+ class PDU < FFI::Struct
119
+ layout(
120
+ :version, :long,
121
+ :command, :int,
122
+ :reqid, :long,
123
+ :msgid, :long,
124
+ :transid, :long,
125
+ :sessid, :long,
126
+ :errstat, :long,
127
+ :errindex, :long,
128
+ :time, :u_long,
129
+ :flags, :u_long,
130
+ :securityModel, :int,
131
+ :securityLevel, :int,
132
+ :msgParseModel, :int,
133
+ :transport_data, :pointer,
134
+ :transport_data_length, :int,
135
+ :tDomain, :pointer,
136
+ :tDomainLen, :size_t,
137
+ :variables, :pointer,
138
+ :community, :pointer,
139
+ :community_len, :size_t,
140
+ :enterprise, :pointer,
141
+ :enterprise_length, :size_t,
142
+ :trap_type, :long,
143
+ :specific_type, :long,
144
+ :agent_addr, [:uchar, 4],
145
+ :contextEngineID, :pointer,
146
+ :contextEngineIDLen, :size_t,
147
+ :contextName, :pointer,
148
+ :contextNameLen, :size_t,
149
+ :securityEngineID, :pointer,
150
+ :securityEngineIDLen, :size_t,
151
+ :securityName, :pointer,
152
+ :securityNameLen, :size_t,
153
+ :priority, :int,
154
+ :range_subid, :int,
155
+ :securityStateRef, :pointer
156
+ )
157
+ end
158
+
159
+ class Counter64 < FFI::Struct
160
+ layout(
161
+ :high, :u_long,
162
+ :low, :u_long
163
+ )
164
+ end
165
+
166
+ end
167
+ end
@@ -0,0 +1,13 @@
1
+ module NETSNMP::Core
2
+
3
+ def self.version
4
+ LibSNMP.netsnmp_get_version
5
+ end
6
+
7
+
8
+ # Do not support versions lower than 5.5, as they're mostly buggy.
9
+ if version < "5.5"
10
+ raise LoadError, "The netsnmp version #{version} is incompatible with this version of ffi-netsnmp-core"
11
+ end
12
+
13
+ end
@@ -0,0 +1,8 @@
1
+ module NETSNMP
2
+ Error = Class.new(StandardError)
3
+ ConnectionFailed = Class.new(Error)
4
+ AuthenticationFailed = Class.new(Error)
5
+
6
+ SendError = Class.new(Error)
7
+ ReceiveError = Class.new(Error)
8
+ end
@@ -0,0 +1,27 @@
1
+ require 'netsnmp'
2
+ module NETSNMP
3
+ module Celluloid
4
+ class Client < ::NETSNMP::Client
5
+
6
+ def initialize(*args)
7
+ @session = Celluloid::Session.new(*args)
8
+ super
9
+ end
10
+
11
+ end
12
+
13
+ class Session < ::NETSNMP::Session
14
+ def wait_readable
15
+ return super unless ::Celluloid::IO.evented?
16
+ ::Celluloid::IO.wait_readable(transport)
17
+ [[transport]]
18
+ end
19
+
20
+ def wait_writable
21
+ return super unless ::Celluloid::IO.evented?
22
+ ::Celluloid::IO.wait_writable(transport)
23
+ [[],[transport]]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,56 @@
1
+ require 'netsnmp'
2
+ module NETSNMP
3
+ module EM
4
+ class Client < ::NETSNMP::Client
5
+
6
+ def initialize(*args)
7
+ @session = EM::Session.new(*args)
8
+ super
9
+ end
10
+
11
+ end
12
+
13
+ class Session < ::NETSNMP::Session
14
+ module Watcher
15
+ def initialize(client, deferable)
16
+ @client = client
17
+ @deferable = deferable
18
+ @is_watching = true
19
+ end
20
+
21
+ def notify_readable
22
+ detach
23
+ begin
24
+ operation = nil
25
+ @client.__send__ :async_read
26
+ result = @client.__send__ :handle_response
27
+ rescue => e
28
+ @deferable.fail(e)
29
+ else
30
+ @deferable.succeed(result)
31
+ end
32
+ end
33
+
34
+ def watching?
35
+ @is_watching
36
+ end
37
+
38
+ def unbind
39
+ @is_watching = false
40
+ end
41
+ end
42
+
43
+ def send(pdu)
44
+ if ::EM.reactor_running?
45
+ write(pdu)
46
+ deferable = ::EM::DefaultDeferrable.new
47
+ watch = ::EM.watch(transport.fileno, Watcher, self, deferable)
48
+ watch.notify_readable = true
49
+ ::EM::Synchrony.sync deferable
50
+ else
51
+ super
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,94 @@
1
+ module NETSNMP
2
+ # Abstracts the OID structure
3
+ #
4
+ class OID
5
+ Error = Class.new(Error)
6
+ OIDREGEX = /^[\d\.]*$/
7
+
8
+ class << self
9
+
10
+ # @return [Integer] the default oid size in bytes
11
+ def default_size
12
+ @default_size ||= Core::Inline.oid_size
13
+ end
14
+
15
+ # @param [FFI::Pointer] pointer the pointer to the beginning ot the memory octet
16
+ # @param [Integer] length the length of the oid
17
+ # @return [String] the oid code (ex: "1.2.4.56.3.4.5"...)
18
+ #
19
+ def read_pointer(pointer, length)
20
+ pointer.__send__(:"read_array_of_uint#{default_size * 8}", length).join('.')
21
+ end
22
+
23
+ # @see read_pointer
24
+ # @return [OID] an OID object initialized from a code read from memory
25
+ #
26
+ def from_pointer(pointer, length)
27
+ new(read_pointer(pointer, length))
28
+ end
29
+
30
+ end
31
+
32
+ attr_reader :code
33
+
34
+ # @param [String] code the oid code
35
+ #
36
+ def initialize(code)
37
+ @struct = FFI::MemoryPointer.new(OID::default_size * Core::Constants::MAX_OID_LEN)
38
+ @length_pointer = FFI::MemoryPointer.new(:size_t)
39
+ @length_pointer.write_int(Core::Constants::MAX_OID_LEN)
40
+ existing_oid = case code
41
+ when OIDREGEX then Core::LibSNMP.read_objid(code, @struct, @length_pointer)
42
+ else Core::LibSNMP.get_node(code, @struct, @length_pointer)
43
+ end
44
+ raise Error, "unsupported oid: #{code}" if existing_oid.zero?
45
+ end
46
+
47
+ # @return [String] the oid code
48
+ #
49
+ def code ; @code ||= OID.read_pointer(pointer, length) ; end
50
+
51
+ # @return [String] the pointer to the structure
52
+ #
53
+ def pointer ; @struct ; end
54
+
55
+ # @return [Integer] length of the oid
56
+ #
57
+ def length ; @length_pointer.read_int ; end
58
+
59
+ # @return [Integer] size of the oid
60
+ #
61
+ def size ; length * NETSNMP::OID.default_size ; end
62
+
63
+ def to_s ; code ; end
64
+
65
+ # @param [OID, String] child oid another oid
66
+ # @return [true, false] whether the given OID belongs to the sub-tree
67
+ #
68
+ def parent_of?(child_oid)
69
+ child_code = child_oid.is_a?(OID) ? child_oid.code : child_oid
70
+ child_code.start_with?(code)
71
+ end
72
+ end
73
+
74
+ # SNMP v3-relevant OIDs
75
+
76
+ class MD5OID < OID
77
+ def initialize ; super("1.3.6.1.6.3.10.1.1.2") ; end
78
+ end
79
+ class SHA1OID < OID
80
+ def initialize ; super("1.3.6.1.6.3.10.1.1.3") ; end
81
+ end
82
+ class NoAuthOID < OID
83
+ def initialize ; super("1.3.6.1.6.3.10.1.1.1") ; end
84
+ end
85
+ class AESOID < OID
86
+ def initialize ; super("1.3.6.1.6.3.10.1.2.4") ; end
87
+ end
88
+ class DESOID < OID
89
+ def initialize ; super("1.3.6.1.6.3.10.1.2.2") ; end
90
+ end
91
+ class NoPrivOID < OID
92
+ def initialize ; super("1.3.6.1.6.3.10.1.2.1") ; end
93
+ end
94
+ end
@@ -0,0 +1,105 @@
1
+ require 'forwardable'
2
+ module NETSNMP
3
+ # Abstracts the PDU base structure into a ruby object. It gives access to its varbinds.
4
+ #
5
+ class PDU
6
+ extend Forwardable
7
+
8
+ Error = Class.new(Error)
9
+ class << self
10
+ # factory method that abstracts initialization of the pdu types that the library supports.
11
+ #
12
+ # @param [Symbol] type the type of pdu structure to build
13
+ # @return [RequestPDU] a fully-formed request pdu
14
+ #
15
+ def build(type, *args)
16
+ case type
17
+ when :get then RequestPDU.new(Core::Constants::SNMP_MSG_GET, *args)
18
+ when :getnext then RequestPDU.new(Core::Constants::SNMP_MSG_GETNEXT, *args)
19
+ when :getbulk then RequestPDU.new(Core::Constants::SNMP_MSG_GETBULK, *args)
20
+ when :set then RequestPDU.new(Core::Constants::SNMP_MSG_SET, *args)
21
+ when :response then ResponsePDU.new(Core::Constants::SNMP_MSG_RESPONSE, *args)
22
+ else raise Error, "#{type} is not supported as type"
23
+ end
24
+ end
25
+ end
26
+
27
+ attr_reader :struct, :varbinds
28
+
29
+ def_delegators :@struct, :[], :[]=, :pointer
30
+
31
+ # @param [FFI::Pointer] the pointer to the initialized structure
32
+ #
33
+ def initialize(pointer)
34
+ @struct = Core::Structures::PDU.new(pointer)
35
+ @varbinds = []
36
+ end
37
+
38
+
39
+ end
40
+
41
+ # Abstracts the request PDU
42
+ # Main characteristic is that it has a write-only API, in that you can add varbinds to it.
43
+ #
44
+ class RequestPDU < PDU
45
+ def initialize(type)
46
+ pointer = Core::LibSNMP.snmp_pdu_create(type)
47
+ super(pointer)
48
+ end
49
+
50
+ # Adds a request varbind to the pdu
51
+ #
52
+ # @param [OID] oid a valid oid
53
+ # @param [Hash] options additional request varbind options
54
+ # @option options [Object] :value the value for the oid
55
+ def add_varbind(oid, **options)
56
+ @varbinds << RequestVarbind.new(self, oid, options[:value], options)
57
+ end
58
+ alias_method :<<, :add_varbind
59
+ end
60
+
61
+ # Abstracts the response PDU
62
+ # Main characteristic is: it reads the values on initialization (because the response structure
63
+ # is at some point free'd). It is therefore a read-only entity
64
+ #
65
+ class ResponsePDU < PDU
66
+
67
+ # @param [FFI::Pointer] the pointer to the response pdu structure
68
+ #
69
+ # @note it loads the variable as well.
70
+ #
71
+ def initialize(pointer)
72
+ super
73
+ load_variables
74
+ end
75
+
76
+ # @return [String] the concatenation of the varbind values (usually, it's only one)
77
+ #
78
+ def value
79
+ case @varbinds.size
80
+ when 0 then nil
81
+ when 1 then @varbinds.first.value
82
+ else
83
+ # assume that they're all strings
84
+ @varbinds.map(&:value).join(' ')
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ # loads the C-level structure variables into ruby ResponseVarbind objects,
91
+ # and store them as state in {{@varbinds}}
92
+ def load_variables
93
+ variable = @struct[:variables]
94
+ unless variable.null?
95
+ @varbinds << ResponseVarbind.new(variable)
96
+ variable = Core::Structures::VariableList.new(variable)
97
+ while( !(variable = variable[:next_variable]).null? )
98
+ variable = Core::Structures::VariableList.new(variable)
99
+ @varbinds << ResponseVarbind.new(variable.pointer)
100
+ end
101
+ end
102
+ end
103
+
104
+ end
105
+ end