packetgen 1.4.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -4
- data/README.md +6 -6
- data/lib/packetgen.rb +0 -1
- data/lib/packetgen/capture.rb +15 -37
- data/lib/packetgen/header.rb +6 -2
- data/lib/packetgen/header/asn1_base.rb +86 -0
- data/lib/packetgen/header/base.rb +68 -44
- data/lib/packetgen/header/crypto.rb +62 -0
- data/lib/packetgen/header/dns.rb +3 -3
- data/lib/packetgen/header/dot11.rb +5 -0
- data/lib/packetgen/header/esp.rb +7 -43
- data/lib/packetgen/header/ike.rb +235 -0
- data/lib/packetgen/header/ike/auth.rb +197 -0
- data/lib/packetgen/header/ike/cert.rb +105 -0
- data/lib/packetgen/header/ike/certreq.rb +69 -0
- data/lib/packetgen/header/ike/id.rb +131 -0
- data/lib/packetgen/header/ike/ke.rb +74 -0
- data/lib/packetgen/header/ike/nonce.rb +35 -0
- data/lib/packetgen/header/ike/notify.rb +220 -0
- data/lib/packetgen/header/ike/payload.rb +307 -0
- data/lib/packetgen/header/ike/sa.rb +577 -0
- data/lib/packetgen/header/ike/sk.rb +255 -0
- data/lib/packetgen/header/ike/ts.rb +287 -0
- data/lib/packetgen/header/ike/vendor_id.rb +34 -0
- data/lib/packetgen/header/ip.rb +4 -4
- data/lib/packetgen/header/ipv6.rb +3 -3
- data/lib/packetgen/header/snmp.rb +283 -0
- data/lib/packetgen/header/tcp.rb +3 -3
- data/lib/packetgen/inspect.rb +35 -9
- data/lib/packetgen/packet.rb +23 -9
- data/lib/packetgen/types/fields.rb +11 -3
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +2 -0
- metadata +52 -2
@@ -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
|
data/lib/packetgen/header/ip.rb
CHANGED
@@ -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::
|
215
|
-
str << shift + Inspect::
|
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::
|
221
|
+
str << shift + Inspect::FMT_ATTR % ['', 'flags', flags_str]
|
222
222
|
foff = Inspect.int_dec_hex(fragment_offset, 4)
|
223
|
-
str << shift + Inspect::
|
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::
|
209
|
+
str << shift + Inspect::FMT_ATTR % ['', 'version', version]
|
210
210
|
tclass = Inspect.int_dec_hex(traffic_class, 2)
|
211
|
-
str << shift + Inspect::
|
211
|
+
str << shift + Inspect::FMT_ATTR % ['', 'tclass', tclass]
|
212
212
|
fl_value = Inspect.int_dec_hex(flow_label, 5)
|
213
|
-
str << shift + Inspect::
|
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
|
data/lib/packetgen/header/tcp.rb
CHANGED
@@ -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::
|
221
|
-
str << shift + Inspect::
|
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::
|
226
|
+
str << shift + Inspect::FMT_ATTR % ['', 'flags', flags]
|
227
227
|
end
|
228
228
|
end
|
229
229
|
str
|
data/lib/packetgen/inspect.rb
CHANGED
@@ -6,10 +6,10 @@ module PacketGen
|
|
6
6
|
module Inspect
|
7
7
|
|
8
8
|
# Maximum number of characters on a line for INSPECT
|
9
|
-
|
9
|
+
MAX_WIDTH = 70
|
10
10
|
|
11
11
|
# Format to inspect attribute
|
12
|
-
|
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 << '-' * (
|
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?
|
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 <<
|
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(
|
87
|
+
str = dashed_line(name, 2)
|
62
88
|
str << (0..15).to_a.map { |v| " %02d" % v}.join << "\n"
|
63
|
-
str << '-' *
|
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 << '-' *
|
100
|
+
str << '-' * MAX_WIDTH << "\n"
|
75
101
|
end
|
76
102
|
end
|
77
103
|
end
|