socialcast-net-ldap 0.1.5

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.
Files changed (47) hide show
  1. data/.gemtest +0 -0
  2. data/COPYING +272 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +29 -0
  5. data/Hacking.rdoc +16 -0
  6. data/History.txt +137 -0
  7. data/LICENSE +56 -0
  8. data/Manifest.txt +45 -0
  9. data/README.txt +70 -0
  10. data/Rakefile +124 -0
  11. data/lib/net-ldap.rb +1 -0
  12. data/lib/net/ber.rb +341 -0
  13. data/lib/net/ber/ber_parser.rb +168 -0
  14. data/lib/net/ber/core_ext.rb +72 -0
  15. data/lib/net/ber/core_ext/array.rb +79 -0
  16. data/lib/net/ber/core_ext/bignum.rb +19 -0
  17. data/lib/net/ber/core_ext/false_class.rb +7 -0
  18. data/lib/net/ber/core_ext/fixnum.rb +63 -0
  19. data/lib/net/ber/core_ext/string.rb +57 -0
  20. data/lib/net/ber/core_ext/true_class.rb +9 -0
  21. data/lib/net/ldap.rb +1539 -0
  22. data/lib/net/ldap/dataset.rb +174 -0
  23. data/lib/net/ldap/entry.rb +208 -0
  24. data/lib/net/ldap/filter.rb +781 -0
  25. data/lib/net/ldap/password.rb +52 -0
  26. data/lib/net/ldap/pdu.rb +279 -0
  27. data/lib/net/ldif.rb +34 -0
  28. data/lib/net/snmp.rb +295 -0
  29. data/spec/integration/ssl_ber_spec.rb +33 -0
  30. data/spec/spec.opts +2 -0
  31. data/spec/spec_helper.rb +5 -0
  32. data/spec/unit/ber/ber_spec.rb +109 -0
  33. data/spec/unit/ber/core_ext/string_spec.rb +51 -0
  34. data/spec/unit/ldap/entry_spec.rb +51 -0
  35. data/spec/unit/ldap/filter_spec.rb +83 -0
  36. data/spec/unit/ldap_spec.rb +48 -0
  37. data/test/common.rb +3 -0
  38. data/test/test_entry.rb +59 -0
  39. data/test/test_filter.rb +115 -0
  40. data/test/test_ldif.rb +68 -0
  41. data/test/test_password.rb +17 -0
  42. data/test/test_rename.rb +79 -0
  43. data/test/test_snmp.rb +114 -0
  44. data/test/testdata.ldif +101 -0
  45. data/testserver/ldapserver.rb +210 -0
  46. data/testserver/testdata.ldif +101 -0
  47. metadata +178 -0
@@ -0,0 +1,52 @@
1
+ #----------------------------------------------------------------------------
2
+ #
3
+ # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
4
+ #
5
+ # Gmail: garbagecat10
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
+ #
21
+ #---------------------------------------------------------------------------
22
+
23
+ require 'digest/sha1'
24
+ require 'digest/md5'
25
+
26
+ class Net::LDAP::Password
27
+ class << self
28
+ # Generate a password-hash suitable for inclusion in an LDAP attribute.
29
+ # Pass a hash type (currently supported: :md5 and :sha) and a plaintext
30
+ # password. This function will return a hashed representation.
31
+ #
32
+ #--
33
+ # STUB: This is here to fulfill the requirements of an RFC, which
34
+ # one?
35
+ #
36
+ # TODO, gotta do salted-sha and (maybe)salted-md5. Should we provide
37
+ # sha1 as a synonym for sha1? I vote no because then should you also
38
+ # provide ssha1 for symmetry?
39
+ def generate(type, str)
40
+ digest, digest_name = case type
41
+ when :md5
42
+ [Digest::MD5.new, 'MD5']
43
+ when :sha
44
+ [Digest::SHA1.new, 'SHA']
45
+ else
46
+ raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})"
47
+ end
48
+ digest << str.to_s
49
+ return "{#{digest_name}}#{[digest.digest].pack('m').chomp }"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,279 @@
1
+ # LDAP PDU support classes
2
+ #
3
+ #----------------------------------------------------------------------------
4
+ #
5
+ # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
6
+ #
7
+ # Gmail: garbagecat10
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation; either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with this program; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
+ #
23
+ #---------------------------------------------------------------------------
24
+
25
+ require 'ostruct'
26
+
27
+ ##
28
+ # Defines the Protocol Data Unit (PDU) for LDAP. An LDAP PDU always looks
29
+ # like a BER SEQUENCE with at least two elements: an INTEGER message ID
30
+ # number and an application-specific SEQUENCE. Some LDAPv3 packets also
31
+ # include an optional third element, a sequence of "controls" (see RFC 2251
32
+ # section 4.1.12 for more information).
33
+ #
34
+ # The application-specific tag in the sequence tells us what kind of packet
35
+ # it is, and each kind has its own format, defined in RFC-1777.
36
+ #
37
+ # Observe that many clients (such as ldapsearch) do not necessarily enforce
38
+ # the expected application tags on received protocol packets. This
39
+ # implementation does interpret the RFC strictly in this regard, and it
40
+ # remains to be seen whether there are servers out there that will not work
41
+ # well with our approach.
42
+ #
43
+ # Currently, we only support controls on SearchResult.
44
+ class Net::LDAP::PDU
45
+ class Error < RuntimeError; end
46
+
47
+ ##
48
+ # This message packet is a bind request.
49
+ BindRequest = 0
50
+ BindResult = 1
51
+ UnbindRequest = 2
52
+ SearchRequest = 3
53
+ SearchReturnedData = 4
54
+ SearchResult = 5
55
+ ModifyResponse = 7
56
+ AddResponse = 9
57
+ DeleteResponse = 11
58
+ ModifyRDNResponse = 13
59
+ SearchResultReferral = 19
60
+ ExtendedRequest = 23
61
+ ExtendedResponse = 24
62
+
63
+ ##
64
+ # The LDAP packet message ID.
65
+ attr_reader :message_id
66
+ alias_method :msg_id, :message_id
67
+
68
+ ##
69
+ # The application protocol format tag.
70
+ attr_reader :app_tag
71
+
72
+ attr_reader :search_entry
73
+ attr_reader :search_referrals
74
+ attr_reader :search_parameters
75
+ attr_reader :bind_parameters
76
+
77
+ ##
78
+ # Returns RFC-2251 Controls if any.
79
+ attr_reader :ldap_controls
80
+ alias_method :result_controls, :ldap_controls
81
+ # Messy. Does this functionality belong somewhere else?
82
+
83
+ def initialize(ber_object)
84
+ begin
85
+ @message_id = ber_object[0].to_i
86
+ # Grab the bottom five bits of the identifier so we know which type of
87
+ # PDU this is.
88
+ #
89
+ # This is safe enough in LDAP-land, but it is recommended that other
90
+ # approaches be taken for other protocols in the case that there's an
91
+ # app-specific tag that has both primitive and constructed forms.
92
+ @app_tag = ber_object[1].ber_identifier & 0x1f
93
+ @ldap_controls = []
94
+ rescue Exception => ex
95
+ raise Net::LDAP::PDU::Error, "LDAP PDU Format Error: #{ex.message}"
96
+ end
97
+
98
+ case @app_tag
99
+ when BindResult
100
+ parse_bind_response(ber_object[1])
101
+ when SearchReturnedData
102
+ parse_search_return(ber_object[1])
103
+ when SearchResultReferral
104
+ parse_search_referral(ber_object[1])
105
+ when SearchResult
106
+ parse_ldap_result(ber_object[1])
107
+ when ModifyResponse
108
+ parse_ldap_result(ber_object[1])
109
+ when AddResponse
110
+ parse_ldap_result(ber_object[1])
111
+ when DeleteResponse
112
+ parse_ldap_result(ber_object[1])
113
+ when ModifyRDNResponse
114
+ parse_ldap_result(ber_object[1])
115
+ when SearchRequest
116
+ parse_ldap_search_request(ber_object[1])
117
+ when BindRequest
118
+ parse_bind_request(ber_object[1])
119
+ when UnbindRequest
120
+ parse_unbind_request(ber_object[1])
121
+ when ExtendedResponse
122
+ parse_ldap_result(ber_object[1])
123
+ else
124
+ raise LdapPduError.new("unknown pdu-type: #{@app_tag}")
125
+ end
126
+
127
+ parse_controls(ber_object[2]) if ber_object[2]
128
+ end
129
+
130
+ ##
131
+ # Returns a hash which (usually) defines the members :resultCode,
132
+ # :errorMessage, and :matchedDN. These values come directly from an LDAP
133
+ # response packet returned by the remote peer. Also see #result_code.
134
+ def result
135
+ @ldap_result || {}
136
+ end
137
+
138
+ ##
139
+ # This returns an LDAP result code taken from the PDU, but it will be nil
140
+ # if there wasn't a result code. That can easily happen depending on the
141
+ # type of packet.
142
+ def result_code(code = :resultCode)
143
+ @ldap_result and @ldap_result[code]
144
+ end
145
+
146
+ ##
147
+ # Return serverSaslCreds, which are only present in BindResponse packets.
148
+ #--
149
+ # Messy. Does this functionality belong somewhere else? We ought to
150
+ # refactor the accessors of this class before they get any kludgier.
151
+ def result_server_sasl_creds
152
+ @ldap_result && @ldap_result[:serverSaslCreds]
153
+ end
154
+
155
+ def parse_ldap_result(sequence)
156
+ sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP result length."
157
+ @ldap_result = {
158
+ :resultCode => sequence[0],
159
+ :matchedDN => sequence[1],
160
+ :errorMessage => sequence[2]
161
+ }
162
+ end
163
+ private :parse_ldap_result
164
+
165
+ ##
166
+ # A Bind Response may have an additional field, ID [7], serverSaslCreds,
167
+ # per RFC 2251 pgh 4.2.3.
168
+ def parse_bind_response(sequence)
169
+ sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP Bind Response length."
170
+ parse_ldap_result(sequence)
171
+ @ldap_result[:serverSaslCreds] = sequence[3] if sequence.length >= 4
172
+ @ldap_result
173
+ end
174
+ private :parse_bind_response
175
+
176
+ # Definition from RFC 1777 (we're handling application-4 here).
177
+ #
178
+ # Search Response ::=
179
+ # CHOICE {
180
+ # entry [APPLICATION 4] SEQUENCE {
181
+ # objectName LDAPDN,
182
+ # attributes SEQUENCE OF SEQUENCE {
183
+ # AttributeType,
184
+ # SET OF AttributeValue
185
+ # }
186
+ # },
187
+ # resultCode [APPLICATION 5] LDAPResult
188
+ # }
189
+ #
190
+ # We concoct a search response that is a hash of the returned attribute
191
+ # values.
192
+ #
193
+ # NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES.
194
+ #
195
+ # This is to make them more predictable for user programs, but it may not
196
+ # be a good idea. Maybe this should be configurable.
197
+ def parse_search_return(sequence)
198
+ sequence.length >= 2 or raise Net::LDAP::PDU::Error, "Invalid Search Response length."
199
+ @search_entry = Net::LDAP::Entry.new(sequence[0])
200
+ sequence[1].each { |seq| @search_entry[seq[0]] = seq[1] }
201
+ end
202
+ private :parse_search_return
203
+
204
+ ##
205
+ # A search referral is a sequence of one or more LDAP URIs. Any number of
206
+ # search-referral replies can be returned by the server, interspersed with
207
+ # normal replies in any order.
208
+ #--
209
+ # Until I can think of a better way to do this, we'll return the referrals
210
+ # as an array. It'll be up to higher-level handlers to expose something
211
+ # reasonable to the client.
212
+ def parse_search_referral(uris)
213
+ @search_referrals = uris
214
+ end
215
+ private :parse_search_referral
216
+
217
+ ##
218
+ # Per RFC 2251, an LDAP "control" is a sequence of tuples, each consisting
219
+ # of an OID, a boolean criticality flag defaulting FALSE, and an OPTIONAL
220
+ # Octet String. If only two fields are given, the second one may be either
221
+ # criticality or data, since criticality has a default value. Someday we
222
+ # may want to come back here and add support for some of more-widely used
223
+ # controls. RFC-2696 is a good example.
224
+ def parse_controls(sequence)
225
+ @ldap_controls = sequence.map do |control|
226
+ o = OpenStruct.new
227
+ o.oid, o.criticality, o.value = control[0], control[1], control[2]
228
+ if o.criticality and o.criticality.is_a?(String)
229
+ o.value = o.criticality
230
+ o.criticality = false
231
+ end
232
+ o
233
+ end
234
+ end
235
+ private :parse_controls
236
+
237
+ # (provisional, must document)
238
+ def parse_ldap_search_request(sequence)
239
+ s = OpenStruct.new
240
+ s.base_object, s.scope, s.deref_aliases, s.size_limit, s.time_limit,
241
+ s.types_only, s.filter, s.attributes = sequence
242
+ @search_parameters = s
243
+ end
244
+ private :parse_ldap_search_request
245
+
246
+ # (provisional, must document)
247
+ def parse_bind_request sequence
248
+ s = OpenStruct.new
249
+ s.version, s.name, s.authentication = sequence
250
+ @bind_parameters = s
251
+ end
252
+ private :parse_bind_request
253
+
254
+ # (provisional, must document)
255
+ # UnbindRequest has no content so this is a no-op.
256
+ def parse_unbind_request(sequence)
257
+ nil
258
+ end
259
+ private :parse_unbind_request
260
+ end
261
+
262
+ module Net
263
+ ##
264
+ # Handle the renamed constants.
265
+ def self.const_missing(name) #:nodoc:
266
+ case name.to_s
267
+ when "LdapPdu"
268
+ warn "Net::#{name} has been deprecated. Use Net::LDAP::PDU instead."
269
+ Net::LDAP::PDU
270
+ when "LdapPduError"
271
+ warn "Net::#{name} has been deprecated. Use Net::LDAP::PDU::Error instead."
272
+ Net::LDAP::PDU::Error
273
+ when 'LDAP'
274
+ else
275
+ super
276
+ end
277
+ end
278
+ end # module Net
279
+
data/lib/net/ldif.rb ADDED
@@ -0,0 +1,34 @@
1
+ # $Id$
2
+ #
3
+ # Net::LDIF for Ruby
4
+ #
5
+ #
6
+ #
7
+ # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
8
+ #
9
+ # Gmail: garbagecat10
10
+ #
11
+ # This program is free software; you can redistribute it and/or modify
12
+ # it under the terms of the GNU General Public License as published by
13
+ # the Free Software Foundation; either version 2 of the License, or
14
+ # (at your option) any later version.
15
+ #
16
+ # This program is distributed in the hope that it will be useful,
17
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ # GNU General Public License for more details.
20
+ #
21
+ # You should have received a copy of the GNU General Public License
22
+ # along with this program; if not, write to the Free Software
23
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
+ #
25
+ #
26
+
27
+ # THIS FILE IS A STUB.
28
+
29
+ module Net
30
+ class LDIF
31
+ end
32
+ end
33
+
34
+
data/lib/net/snmp.rb ADDED
@@ -0,0 +1,295 @@
1
+ # $Id$
2
+ #
3
+ # NET::SNMP
4
+ #
5
+ #----------------------------------------------------------------------------
6
+ #
7
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
8
+ #
9
+ # Gmail: garbagecat10
10
+ #
11
+ # This program is free software; you can redistribute it and/or modify
12
+ # it under the terms of the GNU General Public License as published by
13
+ # the Free Software Foundation; either version 2 of the License, or
14
+ # (at your option) any later version.
15
+ #
16
+ # This program is distributed in the hope that it will be useful,
17
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ # GNU General Public License for more details.
20
+ #
21
+ # You should have received a copy of the GNU General Public License
22
+ # along with this program; if not, write to the Free Software
23
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
+ #
25
+ #---------------------------------------------------------------------------
26
+ #
27
+ #
28
+
29
+ module Net
30
+
31
+ class SNMP
32
+ VERSION = '0.1.0'
33
+
34
+ AsnSyntax = Net::BER.compile_syntax({
35
+ :application => {
36
+ :primitive => {
37
+ 1 => :integer, # Counter32, (RFC2578 sec 2)
38
+ 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2)
39
+ 3 => :integer # TimeTicks32, (RFC2578 sec 2)
40
+ },
41
+ :constructed => {
42
+ }
43
+ },
44
+ :context_specific => {
45
+ :primitive => {
46
+ },
47
+ :constructed => {
48
+ 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2)
49
+ 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3)
50
+ 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4)
51
+ }
52
+ }
53
+ })
54
+
55
+ # SNMP 32-bit counter.
56
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
57
+ # A 32-bit counter is an ASN.1 application [1] implicit unsigned integer
58
+ # with a range from 0 to 2^^32 - 1.
59
+ class Counter32
60
+ def initialize value
61
+ @value = value
62
+ end
63
+ def to_ber
64
+ @value.to_ber_application(1)
65
+ end
66
+ end
67
+
68
+ # SNMP 32-bit gauge.
69
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
70
+ # A 32-bit counter is an ASN.1 application [2] implicit unsigned integer.
71
+ # This is also indistinguishable from Unsigned32. (Need to alias them.)
72
+ class Gauge32
73
+ def initialize value
74
+ @value = value
75
+ end
76
+ def to_ber
77
+ @value.to_ber_application(2)
78
+ end
79
+ end
80
+
81
+ # SNMP 32-bit timer-ticks.
82
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
83
+ # A 32-bit counter is an ASN.1 application [3] implicit unsigned integer.
84
+ class TimeTicks32
85
+ def initialize value
86
+ @value = value
87
+ end
88
+ def to_ber
89
+ @value.to_ber_application(3)
90
+ end
91
+ end
92
+ end
93
+
94
+ class SnmpPdu
95
+ class Error < StandardError; end
96
+
97
+ PduTypes = [
98
+ :get_request,
99
+ :get_next_request,
100
+ :get_response,
101
+ :set_request,
102
+ :trap
103
+ ]
104
+ ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1
105
+ 0 => "noError",
106
+ 1 => "tooBig",
107
+ 2 => "noSuchName",
108
+ 3 => "badValue",
109
+ 4 => "readOnly",
110
+ 5 => "genErr"
111
+ }
112
+
113
+ class << self
114
+ def parse ber_object
115
+ n = new
116
+ n.send :parse, ber_object
117
+ n
118
+ end
119
+ end
120
+
121
+ attr_reader :version, :community, :pdu_type, :variables, :error_status
122
+ attr_accessor :request_id, :error_index
123
+
124
+
125
+ def initialize args={}
126
+ @version = args[:version] || 0
127
+ @community = args[:community] || "public"
128
+ @pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value.
129
+ @error_status = args[:error_status] || 0
130
+ @error_index = args[:error_index] || 0
131
+ @variables = args[:variables] || []
132
+ end
133
+
134
+ #--
135
+ def parse ber_object
136
+ begin
137
+ parse_ber_object ber_object
138
+ rescue Error
139
+ # Pass through any SnmpPdu::Error instances
140
+ raise $!
141
+ rescue
142
+ # Wrap any basic parsing error so it becomes a PDU-format error
143
+ raise Error.new( "snmp-pdu format error" )
144
+ end
145
+ end
146
+ private :parse
147
+
148
+ def parse_ber_object ber_object
149
+ send :version=, ber_object[0].to_i
150
+ send :community=, ber_object[1].to_s
151
+
152
+ data = ber_object[2]
153
+ case (app_tag = data.ber_identifier & 31)
154
+ when 0
155
+ send :pdu_type=, :get_request
156
+ parse_get_request data
157
+ when 1
158
+ send :pdu_type=, :get_next_request
159
+ # This PDU is identical to get-request except for the type.
160
+ parse_get_request data
161
+ when 2
162
+ send :pdu_type=, :get_response
163
+ # This PDU is identical to get-request except for the type,
164
+ # the error_status and error_index values are meaningful,
165
+ # and the fact that the variable bindings will be non-null.
166
+ parse_get_response data
167
+ else
168
+ raise Error.new( "unknown snmp-pdu type: #{app_tag}" )
169
+ end
170
+ end
171
+ private :parse_ber_object
172
+
173
+ #--
174
+ # Defined in RFC1157, pgh 4.1.2.
175
+ def parse_get_request data
176
+ send :request_id=, data[0].to_i
177
+ # data[1] is error_status, always zero.
178
+ # data[2] is error_index, always zero.
179
+ send :error_status=, 0
180
+ send :error_index=, 0
181
+ data[3].each {|n,v|
182
+ # A variable-binding, of which there may be several,
183
+ # consists of an OID and a BER null.
184
+ # We're ignoring the null, we might want to verify it instead.
185
+ unless v.is_a?(Net::BER::BerIdentifiedNull)
186
+ raise Error.new(" invalid variable-binding in get-request" )
187
+ end
188
+ add_variable_binding n, nil
189
+ }
190
+ end
191
+ private :parse_get_request
192
+
193
+ #--
194
+ # Defined in RFC1157, pgh 4.1.4
195
+ def parse_get_response data
196
+ send :request_id=, data[0].to_i
197
+ send :error_status=, data[1].to_i
198
+ send :error_index=, data[2].to_i
199
+ data[3].each {|n,v|
200
+ # A variable-binding, of which there may be several,
201
+ # consists of an OID and a BER null.
202
+ # We're ignoring the null, we might want to verify it instead.
203
+ add_variable_binding n, v
204
+ }
205
+ end
206
+ private :parse_get_response
207
+
208
+
209
+ def version= ver
210
+ unless [0,2].include?(ver)
211
+ raise Error.new("unknown snmp-version: #{ver}")
212
+ end
213
+ @version = ver
214
+ end
215
+
216
+ def pdu_type= t
217
+ unless PduTypes.include?(t)
218
+ raise Error.new("unknown pdu-type: #{t}")
219
+ end
220
+ @pdu_type = t
221
+ end
222
+
223
+ def error_status= es
224
+ unless ErrorStatusCodes.has_key?(es)
225
+ raise Error.new("unknown error-status: #{es}")
226
+ end
227
+ @error_status = es
228
+ end
229
+
230
+ def community= c
231
+ @community = c.to_s
232
+ end
233
+
234
+ #--
235
+ # Syntactic sugar
236
+ def add_variable_binding name, value=nil
237
+ @variables ||= []
238
+ @variables << [name, value]
239
+ end
240
+
241
+ def to_ber_string
242
+ [
243
+ version.to_ber,
244
+ community.to_ber,
245
+ pdu_to_ber_string
246
+ ].to_ber_sequence
247
+ end
248
+
249
+ #--
250
+ # Helper method that returns a PDU payload in BER form,
251
+ # depending on the PDU type.
252
+ def pdu_to_ber_string
253
+ case pdu_type
254
+ when :get_request
255
+ [
256
+ request_id.to_ber,
257
+ error_status.to_ber,
258
+ error_index.to_ber,
259
+ [
260
+ @variables.map {|n,v|
261
+ [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
262
+ }
263
+ ].to_ber_sequence
264
+ ].to_ber_contextspecific(0)
265
+ when :get_next_request
266
+ [
267
+ request_id.to_ber,
268
+ error_status.to_ber,
269
+ error_index.to_ber,
270
+ [
271
+ @variables.map {|n,v|
272
+ [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
273
+ }
274
+ ].to_ber_sequence
275
+ ].to_ber_contextspecific(1)
276
+ when :get_response
277
+ [
278
+ request_id.to_ber,
279
+ error_status.to_ber,
280
+ error_index.to_ber,
281
+ [
282
+ @variables.map {|n,v|
283
+ [n.to_ber_oid, v.to_ber].to_ber_sequence
284
+ }
285
+ ].to_ber_sequence
286
+ ].to_ber_contextspecific(2)
287
+ else
288
+ raise Error.new( "unknown pdu-type: #{pdu_type}" )
289
+ end
290
+ end
291
+ private :pdu_to_ber_string
292
+
293
+ end
294
+ end
295
+