packetgen 0.3.0 → 1.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.
- checksums.yaml +4 -4
- data/lib/packetgen/capture.rb +5 -0
- data/lib/packetgen/header/arp.rb +118 -76
- data/lib/packetgen/header/eth.rb +48 -23
- data/lib/packetgen/header/header_class_methods.rb +75 -1
- data/lib/packetgen/header/header_methods.rb +16 -0
- data/lib/packetgen/header/icmp.rb +39 -16
- data/lib/packetgen/header/icmpv6.rb +28 -5
- data/lib/packetgen/header/ip.rb +140 -58
- data/lib/packetgen/header/ipv6.rb +87 -31
- data/lib/packetgen/header/tcp/option.rb +254 -0
- data/lib/packetgen/header/tcp/options.rb +86 -0
- data/lib/packetgen/header/tcp.rb +299 -0
- data/lib/packetgen/header/udp.rb +45 -19
- data/lib/packetgen/header.rb +6 -0
- data/lib/packetgen/inspect.rb +76 -0
- data/lib/packetgen/packet.rb +12 -51
- data/lib/packetgen/pcapng/block.rb +5 -0
- data/lib/packetgen/pcapng/epb.rb +5 -0
- data/lib/packetgen/pcapng/file.rb +5 -0
- data/lib/packetgen/pcapng/idb.rb +5 -0
- data/lib/packetgen/pcapng/shb.rb +5 -0
- data/lib/packetgen/pcapng/spb.rb +5 -0
- data/lib/packetgen/pcapng/unknown_block.rb +5 -0
- data/lib/packetgen/pcapng.rb +4 -0
- data/lib/packetgen/structfu.rb +5 -3
- data/lib/packetgen/version.rb +6 -1
- data/lib/packetgen.rb +7 -1
- metadata +7 -3
data/lib/packetgen/header/udp.rb
CHANGED
@@ -1,9 +1,35 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
1
6
|
module PacketGen
|
2
7
|
module Header
|
3
8
|
|
4
|
-
# UDP header
|
9
|
+
# A UDP header consists of:
|
10
|
+
# * a source port field ({#sport}, {Int16} type),
|
11
|
+
# * a destination port field ({#dport}, +Int16+ type),
|
12
|
+
# * a UDP length field ({#length}, +Int16+ type),
|
13
|
+
# * a {#checksum} field (+Int16+ type),
|
14
|
+
# * and a {#body}.
|
15
|
+
#
|
16
|
+
# == Create a UDP header
|
17
|
+
# # standalone
|
18
|
+
# udp = PacketGen::Header::UDP.new
|
19
|
+
# # in a packet
|
20
|
+
# pkt = PAcketGen.gen('IP').eadd('UDP')
|
21
|
+
# # access to IP header
|
22
|
+
# pkt.udp # => PacketGen::Header::UDP
|
23
|
+
#
|
24
|
+
# == UDP attributes
|
25
|
+
# udp.sport = 65432
|
26
|
+
# udp.dport = 53
|
27
|
+
# udp.length = 43
|
28
|
+
# udp.checksum = 0xffff
|
29
|
+
# udp.body.read 'this is a UDP body'
|
30
|
+
#
|
5
31
|
# @author Sylvain Daubert
|
6
|
-
class UDP < Struct.new(:sport, :dport, :length, :
|
32
|
+
class UDP < Struct.new(:sport, :dport, :length, :checksum, :body)
|
7
33
|
include StructFu
|
8
34
|
include HeaderMethods
|
9
35
|
extend HeaderClassMethods
|
@@ -15,12 +41,12 @@ module PacketGen
|
|
15
41
|
# @option options [Integer] :sport source port
|
16
42
|
# @option options [Integer] :dport destination port
|
17
43
|
# @option options [Integer] :length UDP length. Default: calculated
|
18
|
-
# @option options [Integer] :
|
44
|
+
# @option options [Integer] :checksum. UDP checksum. Default: 0
|
19
45
|
def initialize(options={})
|
20
46
|
super Int16.new(options[:sport]),
|
21
47
|
Int16.new(options[:dport]),
|
22
48
|
Int16.new(options[:length]),
|
23
|
-
Int16.new(options[:
|
49
|
+
Int16.new(options[:checksum]),
|
24
50
|
StructFu::String.new.read(options[:body])
|
25
51
|
unless options[:length]
|
26
52
|
calc_length
|
@@ -32,20 +58,20 @@ module PacketGen
|
|
32
58
|
# @return [self]
|
33
59
|
def read(str)
|
34
60
|
return self if str.nil?
|
35
|
-
raise ParseError, 'string too short for
|
61
|
+
raise ParseError, 'string too short for UDP' if str.size < self.sz
|
36
62
|
force_binary str
|
37
63
|
self[:sport].read str[0, 2]
|
38
64
|
self[:dport].read str[2, 2]
|
39
65
|
self[:length].read str[4, 2]
|
40
|
-
self[:
|
66
|
+
self[:checksum].read str[6, 2]
|
41
67
|
self[:body].read str[8..-1]
|
42
68
|
end
|
43
69
|
|
44
|
-
# Compute checksum and set +
|
70
|
+
# Compute checksum and set +checksum+ field
|
45
71
|
# @return [Integer]
|
46
|
-
def
|
72
|
+
def calc_checksum
|
47
73
|
ip = ip_header(self)
|
48
|
-
sum = ip.
|
74
|
+
sum = ip.pseudo_header_checksum
|
49
75
|
sum += IP_PROTOCOL
|
50
76
|
sum += length
|
51
77
|
sum += sport
|
@@ -59,7 +85,7 @@ module PacketGen
|
|
59
85
|
sum = (sum & 0xffff) + (sum >> 16)
|
60
86
|
end
|
61
87
|
sum = ~sum & 0xffff
|
62
|
-
self[:
|
88
|
+
self[:checksum].value = (sum == 0) ? 0xffff : sum
|
63
89
|
end
|
64
90
|
|
65
91
|
# Compute length and set +length+ field
|
@@ -105,27 +131,27 @@ module PacketGen
|
|
105
131
|
end
|
106
132
|
|
107
133
|
# Setter for length attribuute
|
108
|
-
# @param [Integer]
|
134
|
+
# @param [Integer] len
|
109
135
|
# @return [Integer]
|
110
136
|
def length=(len)
|
111
137
|
self[:length].read len
|
112
138
|
end
|
113
139
|
|
114
|
-
# Getter for
|
140
|
+
# Getter for checksum attribuute
|
115
141
|
# @return [Integer]
|
116
|
-
def
|
117
|
-
self[:
|
142
|
+
def checksum
|
143
|
+
self[:checksum].to_i
|
118
144
|
end
|
119
145
|
|
120
|
-
# Setter for
|
121
|
-
# @param [Integer]
|
146
|
+
# Setter for checksum attribuute
|
147
|
+
# @param [Integer] checksum
|
122
148
|
# @return [Integer]
|
123
|
-
def
|
124
|
-
self[:
|
149
|
+
def checksum=(checksum)
|
150
|
+
self[:checksum].read checksum
|
125
151
|
end
|
126
152
|
end
|
127
153
|
|
128
|
-
IP.bind_header UDP,
|
154
|
+
IP.bind_header UDP, protocol: UDP::IP_PROTOCOL
|
129
155
|
IPv6.bind_header UDP, next: UDP::IP_PROTOCOL
|
130
156
|
end
|
131
157
|
end
|
data/lib/packetgen/header.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
1
6
|
module PacketGen
|
2
7
|
# Namespace for protocol header classes
|
3
8
|
# @author Sylvain Daubert
|
@@ -21,3 +26,4 @@ require_relative 'header/arp'
|
|
21
26
|
require_relative 'header/ipv6'
|
22
27
|
require_relative 'header/icmpv6'
|
23
28
|
require_relative 'header/udp'
|
29
|
+
require_relative 'header/tcp'
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module PacketGen
|
2
|
+
|
3
|
+
# {Inspect} module provides methods to help writing +inspect+
|
4
|
+
# @api private
|
5
|
+
# @author Sylvain Daubert
|
6
|
+
module Inspect
|
7
|
+
|
8
|
+
# Maximum number of characters on a line for INSPECT
|
9
|
+
INSPECT_MAX_WIDTH = 70
|
10
|
+
|
11
|
+
# Format to inspect attribute
|
12
|
+
INSPECT_FMT_ATTR = "%7s %12s: %s\n"
|
13
|
+
|
14
|
+
# Create a dashed line with +obj+ class writing in it
|
15
|
+
# @param [String] name
|
16
|
+
# @param [Integer] level
|
17
|
+
# @return [String]
|
18
|
+
def self.dashed_line(name, level=1)
|
19
|
+
str = '--' * level << " #{name} "
|
20
|
+
str << '-' * (INSPECT_MAX_WIDTH - str.length) << "\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [String]
|
24
|
+
def self.shift_level(level=1)
|
25
|
+
' ' + ' ' * level
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [#to_i] value
|
29
|
+
# @param [Integer] hex_size
|
30
|
+
# @return [String]
|
31
|
+
def self.int_dec_hex(value, hexsize)
|
32
|
+
"%-10s (0x%0#{hexsize}x)" % [value.to_i, value.to_i]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Format an attribute for +#inspect+.
|
36
|
+
# 3 cases are handled:
|
37
|
+
# * attribute value is a {StructFu::Int}: show value as integer and in
|
38
|
+
# hexdecimal format,
|
39
|
+
# * attribute value responds to +#to_human+: call it,
|
40
|
+
# * else, +#to_s+ is used to format attribute value.
|
41
|
+
# @param [Symbol] attr attribute name
|
42
|
+
# @param [Object] value attribute value
|
43
|
+
# @param [Integer] level
|
44
|
+
# @return [String]
|
45
|
+
def self.inspect_attribute(attr, value, level=1)
|
46
|
+
str = shift_level(level)
|
47
|
+
val = if value.is_a? StructFu::Int
|
48
|
+
int_dec_hex(value, value.to_s.size * 2)
|
49
|
+
elsif value.respond_to? :to_human
|
50
|
+
value.to_human
|
51
|
+
else
|
52
|
+
value.to_s
|
53
|
+
end
|
54
|
+
str << INSPECT_FMT_ATTR % [value.class.to_s.sub(/.*::/, ''), attr, val]
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param [#to_s] body
|
58
|
+
# @return [String]
|
59
|
+
def self.inspect_body(body)
|
60
|
+
str = dashed_line('Body', 2)
|
61
|
+
str << (0..15).to_a.map { |v| " %02d" % v}.join << "\n"
|
62
|
+
str << '-' * INSPECT_MAX_WIDTH << "\n"
|
63
|
+
if body.size > 0
|
64
|
+
(body.size / 16 + 1).times do |i|
|
65
|
+
octets = body.to_s[i*16, 16].unpack('C*')
|
66
|
+
o_str = octets.map { |v| " %02x" % v}.join
|
67
|
+
str << o_str
|
68
|
+
str << ' ' * (3*16 - o_str.size) unless o_str.size >= 3*16
|
69
|
+
str << ' ' << octets.map { |v| v < 128 && v > 13 ? v.chr : '.' }.join
|
70
|
+
str << "\n"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
str << '-' * INSPECT_MAX_WIDTH << "\n"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/packetgen/packet.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
1
5
|
require 'pcaprub'
|
2
6
|
|
3
7
|
module PacketGen
|
@@ -42,9 +46,6 @@ module PacketGen
|
|
42
46
|
# @return [Array<Header::Base]
|
43
47
|
attr_reader :headers
|
44
48
|
|
45
|
-
# @private maximum number of characters on a line for INSPECT
|
46
|
-
INSPECT_MAX_WIDTH = 70
|
47
|
-
|
48
49
|
# Create a new Packet
|
49
50
|
# @param [String] protocol base protocol for packet
|
50
51
|
# @param [Hash] options specific options for +protocol+
|
@@ -194,9 +195,9 @@ module PacketGen
|
|
194
195
|
|
195
196
|
# Recalculate all packet checksums
|
196
197
|
# @return [void]
|
197
|
-
def
|
198
|
+
def calc_checksum
|
198
199
|
@headers.reverse.each do |header|
|
199
|
-
header.
|
200
|
+
header.calc_checksum if header.respond_to? :calc_checksum
|
200
201
|
end
|
201
202
|
end
|
202
203
|
|
@@ -208,11 +209,11 @@ module PacketGen
|
|
208
209
|
end
|
209
210
|
end
|
210
211
|
|
211
|
-
# Recalculate all calculatable fields (for now: length and
|
212
|
+
# Recalculate all calculatable fields (for now: length and checksum)
|
212
213
|
# @return [void]
|
213
214
|
def calc
|
214
215
|
calc_length
|
215
|
-
|
216
|
+
calc_checksum
|
216
217
|
end
|
217
218
|
|
218
219
|
# Get packet body
|
@@ -222,7 +223,7 @@ module PacketGen
|
|
222
223
|
end
|
223
224
|
|
224
225
|
# Set packet body
|
225
|
-
# @param [String]
|
226
|
+
# @param [String] str
|
226
227
|
# @return [void]
|
227
228
|
def body=(str)
|
228
229
|
@headers.last.body = str
|
@@ -258,15 +259,11 @@ module PacketGen
|
|
258
259
|
|
259
260
|
# @return [String]
|
260
261
|
def inspect
|
261
|
-
str = dashed_line(self.class)
|
262
|
+
str = Inspect.dashed_line(self.class)
|
262
263
|
@headers.each do |header|
|
263
|
-
str <<
|
264
|
-
header.to_h.each do |attr, value|
|
265
|
-
next if attr == :body
|
266
|
-
str << inspect_line(attr, value, 2)
|
267
|
-
end
|
264
|
+
str << header.inspect
|
268
265
|
end
|
269
|
-
str << inspect_body
|
266
|
+
str << Inspect.inspect_body(body)
|
270
267
|
end
|
271
268
|
|
272
269
|
# @param [Packet] other
|
@@ -315,42 +312,6 @@ module PacketGen
|
|
315
312
|
raise ArgumentError, "unknown #{protocol} protocol" unless klass.is_a? Class
|
316
313
|
klass
|
317
314
|
end
|
318
|
-
|
319
|
-
def dashed_line(name, level=1)
|
320
|
-
str = '--' * level << " #{name} "
|
321
|
-
str << '-' * (INSPECT_MAX_WIDTH - str.length) << "\n"
|
322
|
-
end
|
323
|
-
|
324
|
-
def inspect_line(attr, value, level=1)
|
325
|
-
str = ' ' + ' ' * level
|
326
|
-
val = if value.is_a? StructFu::Int
|
327
|
-
sz = value.to_s.size
|
328
|
-
"%-10s (0x%0#{2*sz}x)" % [value.to_i, value.to_i]
|
329
|
-
elsif value.respond_to? :to_x
|
330
|
-
value.to_x
|
331
|
-
else
|
332
|
-
value.to_s
|
333
|
-
end
|
334
|
-
str << "%7s %10s: %s" % [value.class.to_s.sub(/.*::/, ''), attr, val]
|
335
|
-
str << "\n"
|
336
|
-
end
|
337
|
-
|
338
|
-
def inspect_body
|
339
|
-
str = dashed_line('Body', 2)
|
340
|
-
str << (0..15).to_a.map { |v| " %02d" % v}.join << "\n"
|
341
|
-
str << '-' * INSPECT_MAX_WIDTH << "\n"
|
342
|
-
if body.size > 0
|
343
|
-
(body.size / 16 + 1).times do |i|
|
344
|
-
octets = body.to_s[i*16, 16].unpack('C*')
|
345
|
-
o_str = octets.map { |v| " %02x" % v}.join
|
346
|
-
str << o_str
|
347
|
-
str << ' ' * (3*16 - o_str.size) unless o_str.size >= 3*16
|
348
|
-
str << ' ' << octets.map { |v| v < 128 && v > 13 ? v.chr : '.' }.join
|
349
|
-
str << "\n"
|
350
|
-
end
|
351
|
-
end
|
352
|
-
str << '-' * INSPECT_MAX_WIDTH << "\n"
|
353
|
-
end
|
354
315
|
end
|
355
316
|
end
|
356
317
|
|
data/lib/packetgen/pcapng/epb.rb
CHANGED
data/lib/packetgen/pcapng/idb.rb
CHANGED
data/lib/packetgen/pcapng/shb.rb
CHANGED
data/lib/packetgen/pcapng/spb.rb
CHANGED
data/lib/packetgen/pcapng.rb
CHANGED
data/lib/packetgen/structfu.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
# -*- coding:
|
1
|
+
# -*- coding: utf-8 -*-
|
2
2
|
module PacketGen
|
3
|
+
# Copied from PacketFu:
|
4
|
+
#
|
3
5
|
# StructFu, a nifty way to leverage Ruby's built in Struct class
|
4
6
|
# to create meaningful binary data.
|
5
7
|
#
|
6
|
-
# Copied from PacketFu:
|
7
|
-
#
|
8
8
|
# Copyright (c) 2008-2014, Tod Beardsley
|
9
9
|
# All rights reserved.
|
10
10
|
#
|
@@ -30,6 +30,7 @@ module PacketGen
|
|
30
30
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
31
31
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
32
32
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# @author Tod Beardsley
|
33
34
|
module StructFu
|
34
35
|
|
35
36
|
# Normally, self.size and self.length will refer to the Struct
|
@@ -82,6 +83,7 @@ module PacketGen
|
|
82
83
|
|
83
84
|
# Get binary string
|
84
85
|
# @return [String]
|
86
|
+
# @author Sylvain Daubert
|
85
87
|
def to_s
|
86
88
|
to_a.map { |field| field.to_s }.join
|
87
89
|
end
|
data/lib/packetgen/version.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
1
6
|
# PacketGen is a network packet generator and analyzor.
|
2
7
|
#
|
3
8
|
# @author Sylvain Daubert
|
4
9
|
module PacketGen
|
5
10
|
# PacketGen version
|
6
|
-
VERSION = "0.
|
11
|
+
VERSION = "1.0.0"
|
7
12
|
end
|
data/lib/packetgen.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
1
5
|
require 'packetgen/version'
|
2
6
|
|
7
|
+
# PacketGen is a network packet generator and analyzor.
|
3
8
|
# @author Sylvain Daubert
|
4
9
|
module PacketGen
|
5
10
|
|
@@ -28,7 +33,7 @@ module PacketGen
|
|
28
33
|
# @param [String] first_header First protocol header
|
29
34
|
# @return [Packet]
|
30
35
|
def self.parse(binary_str, first_header: nil)
|
31
|
-
Packet.parse binary_str, first_header
|
36
|
+
Packet.parse binary_str, first_header: first_header
|
32
37
|
end
|
33
38
|
|
34
39
|
# Shortcut for {Packet.capture}
|
@@ -78,6 +83,7 @@ module PacketGen
|
|
78
83
|
end
|
79
84
|
|
80
85
|
require 'packetgen/structfu'
|
86
|
+
require 'packetgen/inspect'
|
81
87
|
require 'packetgen/packet'
|
82
88
|
require 'packetgen/capture'
|
83
89
|
require 'packetgen/pcapng'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pcaprub
|
@@ -118,7 +118,11 @@ files:
|
|
118
118
|
- lib/packetgen/header/icmpv6.rb
|
119
119
|
- lib/packetgen/header/ip.rb
|
120
120
|
- lib/packetgen/header/ipv6.rb
|
121
|
+
- lib/packetgen/header/tcp.rb
|
122
|
+
- lib/packetgen/header/tcp/option.rb
|
123
|
+
- lib/packetgen/header/tcp/options.rb
|
121
124
|
- lib/packetgen/header/udp.rb
|
125
|
+
- lib/packetgen/inspect.rb
|
122
126
|
- lib/packetgen/packet.rb
|
123
127
|
- lib/packetgen/pcapng.rb
|
124
128
|
- lib/packetgen/pcapng/block.rb
|
@@ -150,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
154
|
version: '0'
|
151
155
|
requirements: []
|
152
156
|
rubyforge_project:
|
153
|
-
rubygems_version: 2.5.
|
157
|
+
rubygems_version: 2.5.2
|
154
158
|
signing_key:
|
155
159
|
specification_version: 4
|
156
160
|
summary: Network packet generator and analyzor
|