packetgen 1.4.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # This class handles Vendor ID payloads, as defined in RFC 7296 §3.12.
7
+ #
8
+ # A Vendor ID payload contains a generic payload header (see {Payload})
9
+ # and data field (type {Types::String}):
10
+ # 1 2 3
11
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # | Next Payload |C| RESERVED | Payload Length |
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | |
16
+ # ~ VendorID Data ~
17
+ # | |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ #
20
+ # == Create a Vendor ID payload
21
+ # # Create a IKE packet with a Vendor ID payload
22
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE')
23
+ # pkt.add('IKE::VendorID', data: "abcdefgh")
24
+ # @author Sylvain Daubert
25
+ class VendorID < Payload
26
+
27
+ # Payload type number
28
+ PAYLOAD_TYPE = 43
29
+ end
30
+ end
31
+
32
+ self.add_class IKE::VendorID
33
+ end
34
+ end
@@ -211,16 +211,16 @@ module PacketGen
211
211
  next if attr == :body
212
212
  str << Inspect.inspect_attribute(attr, value, 2)
213
213
  if attr == :u8
214
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'version', version]
215
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'ihl', ihl]
214
+ str << shift + Inspect::FMT_ATTR % ['', 'version', version]
215
+ str << shift + Inspect::FMT_ATTR % ['', 'ihl', ihl]
216
216
  elsif attr == :frag
217
217
  flags = flag_rsv? ? %w(RSV) : []
218
218
  flags << 'DF' if flag_df?
219
219
  flags << 'MF' if flag_mf?
220
220
  flags_str = flags.empty? ? 'none' : flags.join(',')
221
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'flags', flags_str]
221
+ str << shift + Inspect::FMT_ATTR % ['', 'flags', flags_str]
222
222
  foff = Inspect.int_dec_hex(fragment_offset, 4)
223
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'frag_offset', foff]
223
+ str << shift + Inspect::FMT_ATTR % ['', 'frag_offset', foff]
224
224
  end
225
225
  end
226
226
  str
@@ -206,11 +206,11 @@ module PacketGen
206
206
  str << Inspect.inspect_attribute(attr, value, 2)
207
207
  if attr == :u32
208
208
  shift = Inspect.shift_level(2)
209
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'version', version]
209
+ str << shift + Inspect::FMT_ATTR % ['', 'version', version]
210
210
  tclass = Inspect.int_dec_hex(traffic_class, 2)
211
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'tclass', tclass]
211
+ str << shift + Inspect::FMT_ATTR % ['', 'tclass', tclass]
212
212
  fl_value = Inspect.int_dec_hex(flow_label, 5)
213
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'flow_label', fl_value]
213
+ str << shift + Inspect::FMT_ATTR % ['', 'flow_label', fl_value]
214
214
  end
215
215
  end
216
216
  str
@@ -0,0 +1,283 @@
1
+ # coding: utf-8
2
+ # This file is part of PacketGen
3
+ # See https://github.com/sdaubert/packetgen for more informations
4
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
5
+ # This program is published under MIT license.
6
+
7
+ module PacketGen
8
+ module Header
9
+
10
+ # Dissect error
11
+ class DissectError < ParseError; end
12
+
13
+ # Simple Network Management Protocol (SNMP)
14
+ # @author Sylvain Daubert
15
+ # @since 2.0.0
16
+ class SNMP < ASN1Base
17
+
18
+ # Agents listen to this port
19
+ UDP_PORT1 = 161
20
+ # Configuration sinks listen to this port
21
+ UDP_PORT2 = 162
22
+
23
+ PDU_GET = 0
24
+ PDU_NEXT = 1
25
+ PDU_RESPONSE = 2
26
+ PDU_SET = 3
27
+ PDU_TRAPv1 = 4
28
+ PDU_BULK = 5
29
+ PDU_INFORM = 6
30
+ PDU_TRAPv2 = 7
31
+ PDU_REPORT = 8
32
+
33
+ ERRORS = { 'no_error' => 0,
34
+ 'too_big' => 1,
35
+ 'no_such_name' => 2,
36
+ 'bad_value' => 3,
37
+ 'read_only' => 4,
38
+ 'generic_error' => 5,
39
+ 'no_access' => 6,
40
+ 'wrong_type' => 7,
41
+ 'wrong_length' => 8,
42
+ 'wrong_encoding' => 9,
43
+ 'wrong_value' => 10,
44
+ 'no_creation' => 11,
45
+ 'inconsistent_value' => 12,
46
+ 'ressource_unavailable' => 13,
47
+ 'commit_failed' => 14,
48
+ 'undo_failed' => 15,
49
+ 'authorization_error' => 16,
50
+ 'not_writable' => 17,
51
+ 'inconsistent_name' => 18
52
+ }
53
+
54
+ # Class to handle SNMP VarBind
55
+ # VarBind ::= SEQUENCE {
56
+ # name OBJECT IDENTIFIER,
57
+ # value ANY -- depends on name
58
+ # }
59
+ # @author Sylvain Daubert
60
+ class VarBind < RASN1::Model
61
+ sequence :varbind,
62
+ content: [objectid(:name),
63
+ any(:value)]
64
+ end
65
+
66
+ # Class to handle SNMP VariableBindingsList
67
+ # VarBindList ::= SEQUENCE (SIZE (0..max-bindings)) OF VarBind
68
+ # @author Sylvain Daubert
69
+ class VariableBindings < RASN1::Model
70
+ sequence_of :bindings, VarBind
71
+ end
72
+
73
+ # Class to handle GetRequest PDU
74
+ # GetRequest-PDU ::= [0] IMPLICIT PDU
75
+ #
76
+ # PDU ::= SEQUENCE {
77
+ # request-id INTEGER (-214783648..214783647),
78
+ #
79
+ # error-status -- sometimes ignored
80
+ # INTEGER {
81
+ # noError(0),
82
+ # tooBig(1),
83
+ # noSuchName(2), -- for proxy compatibility
84
+ # badValue(3), -- for proxy compatibility
85
+ # readOnly(4), -- for proxy compatibility
86
+ # genErr(5),
87
+ # noAccess(6),
88
+ # wrongType(7),
89
+ # wrongLength(8),
90
+ # wrongEncoding(9),
91
+ # wrongValue(10),
92
+ # noCreation(11),
93
+ # inconsistentValue(12),
94
+ # resourceUnavailable(13),
95
+ # commitFailed(14),
96
+ # undoFailed(15),
97
+ # authorizationError(16),
98
+ # notWritable(17),
99
+ # inconsistentName(18)
100
+ # },
101
+ #
102
+ # error-index -- sometimes ignored
103
+ # INTEGER (0..max-bindings),
104
+ #
105
+ # variable-bindings -- values are sometimes ignored
106
+ # VarBindList
107
+ # }
108
+ # @author Sylvain Daubert
109
+ class GetRequest < RASN1::Model
110
+ sequence :pdu,
111
+ implicit: SNMP::PDU_GET, constructed: true,
112
+ content: [integer(:id, value: 0),
113
+ enumerated(:error, enum: ERRORS),
114
+ integer(:error_index),
115
+ model(:varbindlist, VariableBindings)]
116
+
117
+ # @return [String]
118
+ def inspect
119
+ Inspect.inspect_body(to_der, self.class)
120
+ end
121
+ end
122
+
123
+ # Class to handle GetNextRequest PDU
124
+ # GetNextRequest-PDU ::= [1] IMPLICIT PDU -- PDU definition: see GetRequest
125
+ # @author Sylvain Daubert
126
+ class GetNextRequest < GetRequest
127
+ root_options implicit: SNMP::PDU_NEXT
128
+ end
129
+
130
+ # Class to handle GetResponse PDU
131
+ # GetResponse-PDU ::= [2] IMPLICIT PDU -- PDU definition: see GetRequest
132
+ # @author Sylvain Daubert
133
+ class GetResponse < GetRequest
134
+ root_options implicit: SNMP::PDU_RESPONSE
135
+ end
136
+
137
+ # Class to handle SetRequest PDU
138
+ # SetRequest-PDU ::= [3] IMPLICIT PDU -- PDU definition: see GetRequest
139
+ # @author Sylvain Daubert
140
+ class SetRequest < GetRequest
141
+ root_options implicit: SNMP::PDU_GET
142
+ end
143
+
144
+ # Class to handle Trap from SNMPv1
145
+ # Trap-PDU ::= [4] IMPLICIT SEQUENCE {
146
+ # enterprise OBJECT IDENTIFIER,
147
+ # agent-addr NetworkAddress,
148
+ # generic-trap -- generic trap type
149
+ # INTEGER {
150
+ # coldStart(0),
151
+ # warmStart(1),
152
+ # linkDown(2),
153
+ # linkUp(3),
154
+ # authenticationFailure(4),
155
+ # egpNeighborLoss(5),
156
+ # enterpriseSpecific(6)
157
+ # },
158
+ # specific-trap INTEGER,
159
+ # time-stamp TimeTicks,
160
+ # variable-bindings VarBindList
161
+ # }
162
+ class Trapv1 < RASN1::Model
163
+ sequence :trap,
164
+ implicit: SNMP::PDU_TRAPv1, constructed: true,
165
+ content: [objectid(:enterprise),
166
+ octet_string(:agent_addr),
167
+ enumerated(:generic_trap, enum: { 'cold_start' => 0,
168
+ 'warm_start' => 1,
169
+ 'link_down' => 2,
170
+ 'link_up' => 3,
171
+ 'auth_failure' => 4,
172
+ 'egp_neighbor_loss' => 5,
173
+ 'specific' => 6 }),
174
+ integer(:specific_trap),
175
+ integer(:timestamp),
176
+ model(:varbindlist, VariableBindings)]
177
+ end
178
+
179
+ # Class to handle Bulk PDU
180
+ # GetBulkRequest-PDU ::= [5] IMPLICIT BulkPDU
181
+ #
182
+ # BulkPDU ::= -- must be identical in
183
+ # SEQUENCE { -- structure to PDU
184
+ # request-id INTEGER (-214783648..214783647),
185
+ # non-repeaters INTEGER (0..max-bindings),
186
+ # max-repetitions INTEGER (0..max-bindings),
187
+ # variable-bindings -- values are ignored
188
+ # VarBindList
189
+ # }
190
+ # @author Sylvain Daubert
191
+ class Bulk < RASN1::Model
192
+ sequence :bulkpdu,
193
+ implicit: SNMP::PDU_BULK, constructed: true,
194
+ content: [integer(:id, value: 0),
195
+ integer(:non_repeaters),
196
+ integer(:max_repetitions),
197
+ model(:varbindlist, VariableBindings)]
198
+
199
+ # @return [String]
200
+ def inspect
201
+ Inspect.inspect_body(to_der, self.class)
202
+ end
203
+ end
204
+
205
+ # Class to handle InformRequest PDU
206
+ # InformRequest-PDU ::= [6] IMPLICIT PDU -- PDU definition: see GetRequest
207
+ # @author Sylvain Daubert
208
+ class InformRequest < GetRequest
209
+ root_options implicit: SNMP::PDU_INFORM
210
+ end
211
+
212
+ # Class to handle Trapv2 PDU
213
+ # SNMPv2-Trap-PDU ::= [7] IMPLICIT PDU -- PDU definition: see GetRequest
214
+ # @author Sylvain Daubert
215
+ class Trapv2 < GetRequest
216
+ root_options implicit: SNMP::PDU_TRAPv2
217
+ end
218
+
219
+ # Class to handle Report PDU
220
+ # Report-PDU ::= [8] IMPLICIT PDU -- PDU definition: see GetRequest
221
+ # @author Sylvain Daubert
222
+ class Report < GetRequest
223
+ root_options implicit: SNMP::PDU_REPORT
224
+ end
225
+
226
+ # Class to handle PDUs from SNMP packet
227
+ # PDUs ::= CHOICE {
228
+ # get-request [0] IMPLICIT PDU,
229
+ # get-next-request [1] IMPLICIT PDU,
230
+ # get-response [2] IMPLICIT PDU,
231
+ # set-request [3] IMPLICIT PDU,
232
+ # snmpV1-trap [4] IMPLICIT PDU,
233
+ # get-bulk-request [5] IMPLICIT PDU,
234
+ # inform-request [6] IMPLICIT PDU,
235
+ # snmpV2-trap [7] IMPLICIT PDU,
236
+ # report [8] IMPLICIT PDU
237
+ # }
238
+ # @author Sylvain Daubert
239
+ class PDUs < RASN1::Model
240
+ choice :pdus,
241
+ content: [model(:get_request, GetRequest),
242
+ model(:get_next_request, GetNextRequest),
243
+ model(:get_response, GetResponse),
244
+ model(:set_request, SetRequest),
245
+ #model(:trapv1, Trapv1),
246
+ model(:bulk, Bulk),
247
+ model(:inform, InformRequest),
248
+ model(:trapv2, Trapv2),
249
+ model(:report, Report)]
250
+ end
251
+
252
+ sequence :message,
253
+ content: [enumerated(:version, value: 'v2c',
254
+ enum: { 'v1' => 0, 'v2c' => 1, 'v2' => 2, 'v3' => 3 }),
255
+ octet_string(:community, value: 'public'),
256
+ model(:data, PDUs)]
257
+
258
+ define_attributes :version, :community
259
+
260
+ # accessor to data payload
261
+ # @return [GetRequest]
262
+ def data
263
+ @elements[:data]
264
+ end
265
+
266
+ def inspect
267
+ str = super
268
+ str << Inspect.shift_level(2)
269
+ if self[:data].chosen.nil?
270
+ str << Inspect::FMT_ATTR % [self[:data].type, :data, '']
271
+ else
272
+ data = self[:data]
273
+ str << Inspect::FMT_ATTR % [data.type, :data, data.chosen_value.type]
274
+ str << data.chosen_value.inspect
275
+ end
276
+ end
277
+ end
278
+
279
+ self.add_class SNMP
280
+ UDP.bind_header SNMP, dport: SNMP::UDP_PORT1, sport: SNMP::UDP_PORT1
281
+ UDP.bind_header SNMP, dport: SNMP::UDP_PORT2, sport: SNMP::UDP_PORT2
282
+ end
283
+ end
@@ -217,13 +217,13 @@ module PacketGen
217
217
  str << Inspect.inspect_attribute(attr, value, 2)
218
218
  if attr == :u16
219
219
  doff = Inspect.int_dec_hex(data_offset, 1)
220
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'data_offset', doff]
221
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'reserved', reserved]
220
+ str << shift + Inspect::FMT_ATTR % ['', 'data_offset', doff]
221
+ str << shift + Inspect::FMT_ATTR % ['', 'reserved', reserved]
222
222
  flags = ''
223
223
  %w(ns cwr ece urg ack psh rst syn fin).each do |fl|
224
224
  flags << (send("flag_#{fl}?") ? fl[0].upcase : '.')
225
225
  end
226
- str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'flags', flags]
226
+ str << shift + Inspect::FMT_ATTR % ['', 'flags', flags]
227
227
  end
228
228
  end
229
229
  str
@@ -6,10 +6,10 @@ module PacketGen
6
6
  module Inspect
7
7
 
8
8
  # Maximum number of characters on a line for INSPECT
9
- INSPECT_MAX_WIDTH = 70
9
+ MAX_WIDTH = 70
10
10
 
11
11
  # Format to inspect attribute
12
- INSPECT_FMT_ATTR = "%10s %12s: %s\n"
12
+ FMT_ATTR = "%12s %12s: %s\n"
13
13
 
14
14
  # Create a dashed line with +obj+ class writing in it
15
15
  # @param [String] name
@@ -17,7 +17,7 @@ module PacketGen
17
17
  # @return [String]
18
18
  def self.dashed_line(name, level=1)
19
19
  str = '--' * level << " #{name} "
20
- str << '-' * (INSPECT_MAX_WIDTH - str.length) << "\n"
20
+ str << '-' * (MAX_WIDTH - str.length) << "\n"
21
21
  end
22
22
 
23
23
  # @return [String]
@@ -44,23 +44,49 @@ module PacketGen
44
44
  # @return [String]
45
45
  def self.inspect_attribute(attr, value, level=1)
46
46
  str = shift_level(level)
47
- val = if value.is_a? Types::Int
47
+ val = if value.is_a?(Types::Int) or value.is_a?(Integer)
48
48
  int_dec_hex(value, value.to_s.size * 2)
49
49
  elsif value.respond_to? :to_human
50
50
  value.to_human
51
51
  else
52
52
  value.to_s.inspect
53
53
  end
54
- str << INSPECT_FMT_ATTR % [value.class.to_s.sub(/.*::/, ''), attr, val]
54
+ str << FMT_ATTR % [value.class.to_s.sub(/.*::/, ''), attr, val]
55
+ end
56
+
57
+ # Format a ASN.1 attribute for +#inspect+.
58
+ # 3 cases are handled:
59
+ # * attribute value is a {Types::Int}: show value as integer and in
60
+ # hexdecimal format,
61
+ # * attribute value responds to +#to_human+: call it,
62
+ # * else, +#to_s+ is used to format attribute value.
63
+ # @param [Symbol] name attribute name
64
+ # @param [RASN1::Types::Base,RASN1::Model] attr attribute
65
+ # @param [Integer] level
66
+ # @return [String]
67
+ def self.inspect_asn1_attribute(name, attr, level=1)
68
+ str = shift_level(level)
69
+ val = case attr
70
+ when RASN1::Types::Enumerated
71
+ hexsize = attr.value_size * 2
72
+ "%-10s (0x%0#{hexsize}x)" % [attr.value, attr.to_i]
73
+ when RASN1::Types::Integer
74
+ int_dec_hex(attr.value, attr.value_size * 2)
75
+ when RASN1::Model
76
+ attr.root.type
77
+ else
78
+ attr.value.to_s.inspect
79
+ end
80
+ str << FMT_ATTR % [attr.type, name, val]
55
81
  end
56
82
 
57
83
  # @param [#to_s] body
58
84
  # @return [String]
59
- def self.inspect_body(body)
85
+ def self.inspect_body(body, name='Body')
60
86
  return '' if body.nil? or body.empty?
61
- str = dashed_line('Body', 2)
87
+ str = dashed_line(name, 2)
62
88
  str << (0..15).to_a.map { |v| " %02d" % v}.join << "\n"
63
- str << '-' * INSPECT_MAX_WIDTH << "\n"
89
+ str << '-' * MAX_WIDTH << "\n"
64
90
  if body.size > 0
65
91
  (body.size / 16 + 1).times do |i|
66
92
  octets = body.to_s[i*16, 16].unpack('C*')
@@ -71,7 +97,7 @@ module PacketGen
71
97
  str << "\n"
72
98
  end
73
99
  end
74
- str << '-' * INSPECT_MAX_WIDTH << "\n"
100
+ str << '-' * MAX_WIDTH << "\n"
75
101
  end
76
102
  end
77
103
  end