packetgen 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|