packetgen 2.7.0 → 2.8.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 +0 -1
- data/lib/packetgen/header/netbios.rb +4 -48
- data/lib/packetgen/header/netbios/datagram.rb +105 -0
- data/lib/packetgen/header/netbios/name.rb +67 -0
- data/lib/packetgen/header/netbios/session.rb +64 -0
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +1 -7
- data/lib/packetgen/types/array.rb +21 -0
- data/lib/packetgen/types/cstring.rb +3 -3
- data/lib/packetgen/types/fields.rb +19 -3
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05c4708dc2f5da405247b3dbc37d2ff96180086949587f1a7027ef65a9bc8b5d
|
4
|
+
data.tar.gz: 323d1b0810e378ac564b260ddfa182b7d7f4e3ca1504f2e03d46ac7511f4c3db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e96208217d2e909db2d2cfd5ffc4eed7180b9c9cde98f20af34e7cd7b28404c744eb6a51851b4e0ad5aba79ec91cb39ae6f21292bee2a6ec60d423fd8bbdece
|
7
|
+
data.tar.gz: 9f59f2ecc4f409b43a38c9a16e0d632182af19fa958687599db5ce719e3776b4a24e48384a432e8e2f4a6bc6312f96e2ed0c474d6ebc7db13f4ccdcbdb71666a
|
data/.travis.yml
CHANGED
@@ -11,54 +11,10 @@ module PacketGen
|
|
11
11
|
# @author Sylvain Daubert
|
12
12
|
# @since 2.5.1
|
13
13
|
module NetBIOS
|
14
|
-
# NetBIOS Session Service messages.
|
15
|
-
# @author Sylvain Daubert
|
16
|
-
class Session < Base
|
17
|
-
# Port number for NetBIOS Session Service over TCP
|
18
|
-
TCP_PORT = 139
|
19
|
-
|
20
|
-
# Session packet types
|
21
|
-
TYPES = {
|
22
|
-
'message' => 0,
|
23
|
-
'request' => 0x81,
|
24
|
-
'positive_response' => 0x82,
|
25
|
-
'negative_response' => 0x83,
|
26
|
-
'retarget_response' => 0x84,
|
27
|
-
'keep_alive' => 0x85,
|
28
|
-
}.freeze
|
29
|
-
|
30
|
-
# @!attribute type
|
31
|
-
# 8-bit session packet type
|
32
|
-
# @return [Integer]
|
33
|
-
define_field :type, Types::Int8Enum, enum: TYPES
|
34
|
-
# @!attribute length
|
35
|
-
# 17-bit session packet length
|
36
|
-
# @return [Integer]
|
37
|
-
define_field :length, Types::Int24
|
38
|
-
# @!attribute body
|
39
|
-
# @return [String]
|
40
|
-
define_field :body, Types::String
|
41
|
-
|
42
|
-
# Compute and set {#length} field
|
43
|
-
# @return [Integer] calculated length
|
44
|
-
def calc_length
|
45
|
-
Base.calculate_and_set_length(self, header_in_size: false)
|
46
|
-
end
|
47
|
-
|
48
|
-
# @api private
|
49
|
-
# @note This method is used internally by PacketGen and should not be
|
50
|
-
# directly called
|
51
|
-
# @since 2.7.0 Set TCP sport according to bindings, only if sport is 0.
|
52
|
-
# Needed by new bind API.
|
53
|
-
def added_to_packet(packet)
|
54
|
-
return unless packet.is? 'TCP'
|
55
|
-
return unless packet.tcp.sport.zero?
|
56
|
-
packet.tcp.sport = TCP_PORT
|
57
|
-
end
|
58
|
-
end
|
59
14
|
end
|
60
|
-
self.add_class NetBIOS::Session
|
61
|
-
TCP.bind NetBIOS::Session, dport: NetBIOS::Session::TCP_PORT
|
62
|
-
TCP.bind NetBIOS::Session, sport: NetBIOS::Session::TCP_PORT
|
63
15
|
end
|
64
16
|
end
|
17
|
+
|
18
|
+
require_relative 'netbios/name'
|
19
|
+
require_relative 'netbios/session'
|
20
|
+
require_relative 'netbios/datagram'
|
@@ -0,0 +1,105 @@
|
|
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
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen
|
9
|
+
module Header
|
10
|
+
# Module to group all NetBIOS headers
|
11
|
+
# @author Sylvain Daubert
|
12
|
+
# @since 2.5.1
|
13
|
+
module NetBIOS
|
14
|
+
# NetBIOS Session Service messages.
|
15
|
+
# @author Sylvain Daubert
|
16
|
+
class Datagram < Base
|
17
|
+
# Port number for NetBIOS Session Service over TCP
|
18
|
+
UDP_PORT = 138
|
19
|
+
|
20
|
+
# Datagram packet types
|
21
|
+
TYPES = {
|
22
|
+
'direct_unique' => 0x10,
|
23
|
+
'direct_group' => 0x11,
|
24
|
+
'broadcast' => 0x12,
|
25
|
+
'error' => 0x13,
|
26
|
+
'query_request' => 0x14,
|
27
|
+
'positive_query_resp' => 0x15,
|
28
|
+
'negative_query_resp' => 0x16,
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
# @!attribute type
|
32
|
+
# 8-bit session packet type
|
33
|
+
# @return [Integer]
|
34
|
+
define_field :type, Types::Int8Enum, enum: TYPES
|
35
|
+
# @!attribute flags
|
36
|
+
# 8-bit flags
|
37
|
+
# @return [Integer]
|
38
|
+
define_field :flags, Types::Int8
|
39
|
+
# @!attribute dgm_id
|
40
|
+
# 16-bit next transaction ID for datagrams
|
41
|
+
# @return [Integer]
|
42
|
+
define_field :dgm_id, Types::Int16
|
43
|
+
# @!attribute src_ip
|
44
|
+
# Source IP address
|
45
|
+
# @return [IP::Addr]
|
46
|
+
define_field :src_ip, IP::Addr
|
47
|
+
# @!attribute src_port
|
48
|
+
# Source port
|
49
|
+
# @return [IP::Addr]
|
50
|
+
define_field :src_port, Types::Int16
|
51
|
+
# @!attribute dgm_length
|
52
|
+
# Length of data + second level of encoded names. Not present in error datagram.
|
53
|
+
# @return [Integer]
|
54
|
+
define_field :dgm_length, Types::Int16, optional: ->(h) { h.type != 0x13 }
|
55
|
+
# @!attribute packet_offset
|
56
|
+
# Not present in error datagram.
|
57
|
+
# @return [Integer]
|
58
|
+
define_field :packet_offset, Types::Int16, optional: ->(h) { h.type != 0x13 }
|
59
|
+
# @!attribute error_code
|
60
|
+
# Error code. Only present in error datagrams.
|
61
|
+
# @return [Integer]
|
62
|
+
define_field :error_code, Types::Int16, optional: ->(h) { h.type == 0x13 }
|
63
|
+
# @!attribute src_name
|
64
|
+
# NetBIOS source name. Only present in direct_unique, direct_group and broadcast datagrams.
|
65
|
+
# @return []
|
66
|
+
define_field :src_name, Name, default: '', optional: ->(h) { (h.type >= 0x10) && (h.type <= 0x12) }
|
67
|
+
# @!attribute dst_name
|
68
|
+
# NetBIOS destination name. Present in all but error datagrams.
|
69
|
+
# @return []
|
70
|
+
define_field :dst_name, Name, default: '', optional: ->(h) { h.type != 0x13 }
|
71
|
+
# @!attribute body
|
72
|
+
# User data. Ony present in direct_unique, direct_group and broadcast datagrams.
|
73
|
+
# @return [String]
|
74
|
+
define_field :body, Types::String, optional: ->(h) { (h.type >= 0x10) && (h.type <= 0x12) }
|
75
|
+
|
76
|
+
# @!attribute :rsv
|
77
|
+
# 4-bit rsv field. 4 upper bits of {#flags}
|
78
|
+
# @return [Integer]
|
79
|
+
# @!attribute :snt
|
80
|
+
# 2-bit SNT (Source end-Node Type) field from {#flags}.
|
81
|
+
# @return [Integer]
|
82
|
+
# @!attribute f
|
83
|
+
# First packet flag. If set then this is first
|
84
|
+
# (and possibly only) fragment of NetBIOS datagram.
|
85
|
+
# @return [Boolean]
|
86
|
+
# @!attribute m
|
87
|
+
# More flag. If set then more NetBIOS datagram
|
88
|
+
# fragments follow.
|
89
|
+
# @return [Boolean]
|
90
|
+
define_bit_fields_on :flags, :rsv, 4, :snt, 2, :f, :m
|
91
|
+
|
92
|
+
# Compute and set {#dgm_length} field
|
93
|
+
# @return [Integer] calculated length
|
94
|
+
def calc_length
|
95
|
+
length = self[:body].sz
|
96
|
+
length += self[:src_name].sz if is_present?(:src_name)
|
97
|
+
length += self[:dst_name].sz if is_present?(:dst_name)
|
98
|
+
self.dgm_length = length
|
99
|
+
end
|
100
|
+
end
|
101
|
+
Header.add_class Datagram
|
102
|
+
UDP.bind Datagram, dport: Datagram::UDP_PORT, sport: Datagram::UDP_PORT
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,67 @@
|
|
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
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen
|
9
|
+
module Header
|
10
|
+
# Module to group all NetBIOS headers
|
11
|
+
# @author Sylvain Daubert
|
12
|
+
# @since 2.5.1
|
13
|
+
module NetBIOS
|
14
|
+
# NetBIOS Name.
|
15
|
+
# @author Sylvain Daubert
|
16
|
+
class Name < DNS::Name
|
17
|
+
# Size, in bytes, of an encoded NetBIOS name
|
18
|
+
ENCODED_NAME_SIZE = 32
|
19
|
+
|
20
|
+
# Read a NetBIOS name from a string
|
21
|
+
# @param [String] str
|
22
|
+
# @return [Name] self
|
23
|
+
def from_human(str)
|
24
|
+
clear
|
25
|
+
return self if str.nil?
|
26
|
+
encoded_name = encode_name(str)
|
27
|
+
|
28
|
+
super(encoded_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get a human readable string
|
32
|
+
# @return [String]
|
33
|
+
def to_human
|
34
|
+
encoded_name = super
|
35
|
+
decode_name(encoded_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def encode_name(name)
|
41
|
+
basename, *scope_id = name.split('.')
|
42
|
+
basename = '' if basename.nil?
|
43
|
+
scope_id = scope_id.join('.')
|
44
|
+
encoded_name = +''
|
45
|
+
basename.each_byte do |byte|
|
46
|
+
a = (byte >> 4) + 0x41
|
47
|
+
b = (byte & 0xf) + 0x41
|
48
|
+
encoded_name << [a, b].pack('C2')
|
49
|
+
end
|
50
|
+
encoded_name << 'CA' * ((ENCODED_NAME_SIZE - encoded_name.size) / 2) if encoded_name.size < ENCODED_NAME_SIZE
|
51
|
+
encoded_name << ".#{scope_id}" if scope_id
|
52
|
+
encoded_name
|
53
|
+
end
|
54
|
+
|
55
|
+
def decode_name(encoded_name)
|
56
|
+
name = +''
|
57
|
+
encoded_name.partition('.').first.scan(/../).map do |duo|
|
58
|
+
a = (duo[0].ord - 0x41) & 0xf
|
59
|
+
b = (duo[1].ord - 0x41) & 0xf
|
60
|
+
name << (a << 4 | b).chr
|
61
|
+
end
|
62
|
+
name.strip
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen
|
9
|
+
module Header
|
10
|
+
# Module to group all NetBIOS headers
|
11
|
+
# @author Sylvain Daubert
|
12
|
+
# @since 2.5.1
|
13
|
+
module NetBIOS
|
14
|
+
# NetBIOS Session Service messages.
|
15
|
+
# @author Sylvain Daubert
|
16
|
+
class Session < Base
|
17
|
+
# Port number for NetBIOS Session Service over TCP
|
18
|
+
TCP_PORT = 139
|
19
|
+
|
20
|
+
# Session packet types
|
21
|
+
TYPES = {
|
22
|
+
'message' => 0,
|
23
|
+
'request' => 0x81,
|
24
|
+
'positive_response' => 0x82,
|
25
|
+
'negative_response' => 0x83,
|
26
|
+
'retarget_response' => 0x84,
|
27
|
+
'keep_alive' => 0x85,
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
# @!attribute type
|
31
|
+
# 8-bit session packet type
|
32
|
+
# @return [Integer]
|
33
|
+
define_field :type, Types::Int8Enum, enum: TYPES
|
34
|
+
# @!attribute length
|
35
|
+
# 17-bit session packet length
|
36
|
+
# @return [Integer]
|
37
|
+
define_field :length, Types::Int24
|
38
|
+
# @!attribute body
|
39
|
+
# @return [String]
|
40
|
+
define_field :body, Types::String
|
41
|
+
|
42
|
+
# Compute and set {#length} field
|
43
|
+
# @return [Integer] calculated length
|
44
|
+
def calc_length
|
45
|
+
Base.calculate_and_set_length(self, header_in_size: false)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @api private
|
49
|
+
# @note This method is used internally by PacketGen and should not be
|
50
|
+
# directly called
|
51
|
+
# @since 2.7.0 Set TCP sport according to bindings, only if sport is 0.
|
52
|
+
# Needed by new bind API.
|
53
|
+
def added_to_packet(packet)
|
54
|
+
return unless packet.is? 'TCP'
|
55
|
+
return unless packet.tcp.sport.zero?
|
56
|
+
packet.tcp.sport = TCP_PORT
|
57
|
+
end
|
58
|
+
end
|
59
|
+
Header.add_class Session
|
60
|
+
TCP.bind Session, dport: Session::TCP_PORT
|
61
|
+
TCP.bind Session, sport: Session::TCP_PORT
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -8,12 +8,6 @@
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
10
|
class OSPFv3
|
11
|
-
# Array of 32-bit words.
|
12
|
-
# @author Sylvain Daubert
|
13
|
-
class ArrayOfInt32 < Types::Array
|
14
|
-
set_of Types::Int32
|
15
|
-
end
|
16
|
-
|
17
11
|
# This class handles IPv6 prefixes, as defined in RFC 5340 §A.4.1.
|
18
12
|
# A IPv6 prefix consists of:
|
19
13
|
# * a 8-bit {#length} field (length of the prefix, in bits),
|
@@ -39,7 +33,7 @@ module PacketGen
|
|
39
33
|
# @!attribute prefix
|
40
34
|
# IPv6 Prefix as an array of 32-bit words
|
41
35
|
# @return [Prefix]
|
42
|
-
define_field :prefix, ArrayOfInt32
|
36
|
+
define_field :prefix, Types::ArrayOfInt32
|
43
37
|
|
44
38
|
# @!attribute dn_opt
|
45
39
|
# This bit controls an inter-area-prefix-LSAs or AS-external-LSAs
|
@@ -210,5 +210,26 @@ module PacketGen
|
|
210
210
|
end
|
211
211
|
end
|
212
212
|
end
|
213
|
+
|
214
|
+
# Specialized array to handle serie of {Int8}.
|
215
|
+
class ArrayOfInt8 < Array
|
216
|
+
set_of Int8
|
217
|
+
end
|
218
|
+
# Specialized array to handle serie of {Int16}.
|
219
|
+
class ArrayOfInt16 < Array
|
220
|
+
set_of Int16
|
221
|
+
end
|
222
|
+
# Specialized array to handle serie of {Int16le}.
|
223
|
+
class ArrayOfInt16le < Array
|
224
|
+
set_of Int16le
|
225
|
+
end
|
226
|
+
# Specialized array to handle serie of {Int32}.
|
227
|
+
class ArrayOfInt32 < Types::Array
|
228
|
+
set_of Types::Int32
|
229
|
+
end
|
230
|
+
# Specialized array to handle serie of {Int32le}.
|
231
|
+
class ArrayOfInt32le < Types::Array
|
232
|
+
set_of Types::Int32le
|
233
|
+
end
|
213
234
|
end
|
214
235
|
end
|
@@ -35,13 +35,13 @@ module PacketGen
|
|
35
35
|
if @static_length.is_a? Integer
|
36
36
|
if self.size >= @static_length
|
37
37
|
s = self[0, @static_length]
|
38
|
-
s[-1] =
|
38
|
+
s[-1] = "\x00".encode(s.encoding)
|
39
39
|
PacketGen.force_binary s
|
40
40
|
else
|
41
41
|
PacketGen.force_binary(self + "\0" * (@static_length - self.length))
|
42
42
|
end
|
43
43
|
else
|
44
|
-
PacketGen.force_binary(self +
|
44
|
+
PacketGen.force_binary(self + +"\x00".encode(self.encoding))
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -56,7 +56,7 @@ module PacketGen
|
|
56
56
|
|
57
57
|
# @return [String]
|
58
58
|
def to_human
|
59
|
-
idx = self.index(
|
59
|
+
idx = self.index(+"\x00".encode(self.encoding)) || self.sz
|
60
60
|
self[0, idx]
|
61
61
|
end
|
62
62
|
end
|
@@ -70,11 +70,13 @@ module PacketGen
|
|
70
70
|
# # object will have a different value.
|
71
71
|
# define_field :id, PacketGen::Types::Int16, default: ->{ rand(65535) }
|
72
72
|
# # a size field
|
73
|
-
# define_field :body_size, PacketGen::
|
73
|
+
# define_field :body_size, PacketGen::Types::Int16
|
74
74
|
# # String field which length is taken from body_size field
|
75
|
-
# define_field :body, PacketGen::
|
75
|
+
# define_field :body, PacketGen::Types::String, builder: ->(obj, type) { type.new('', length_from: obj[:body_size]) }
|
76
76
|
# # 16-bit enumeration type. As :default not specified, default to first value of enum
|
77
|
-
# define_field :type_class, PacketGen::
|
77
|
+
# define_field :type_class, PacketGen::Types::Int16Enum, enum: { 'class1' => 1, 'class2' => 2}
|
78
|
+
# # optional field. Only present if another field has a certain value
|
79
|
+
# define_field :opt1, PacketGen::Types::Int16, optional: ->(h) { h.type == 42 }
|
78
80
|
#
|
79
81
|
# {.define_field_before} and {.define_field_after} are also defined to relatively
|
80
82
|
# create a field from anoher one (for example, when adding a field in a subclass).
|
@@ -452,6 +454,20 @@ module PacketGen
|
|
452
454
|
PacketGen.force_binary(str)
|
453
455
|
end
|
454
456
|
|
457
|
+
# Get offset of given field in {Fields} structure.
|
458
|
+
# @param [Symbol] field
|
459
|
+
# @return [Integer]
|
460
|
+
# @raise [ArgumentError] unknown field
|
461
|
+
def offset_of(field)
|
462
|
+
raise ArgumentError, "#{field} is an unknown field of #{self.class}" unless @fields.include?(field)
|
463
|
+
offset = 0
|
464
|
+
fields.each do |f|
|
465
|
+
break offset if f == field
|
466
|
+
next unless is_present?(f)
|
467
|
+
offset += self[f].sz
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
455
471
|
private
|
456
472
|
|
457
473
|
# Deeply duplicate +@fields+
|
data/lib/packetgen/version.rb
CHANGED
data/packetgen.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ['lib']
|
24
24
|
|
25
|
-
spec.required_ruby_version = '>= 2.
|
25
|
+
spec.required_ruby_version = '>= 2.3.0'
|
26
26
|
|
27
27
|
spec.add_dependency 'interfacez', '~>1.0'
|
28
28
|
spec.add_dependency 'pcaprub', '~>0.12.4'
|
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: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: interfacez
|
@@ -227,6 +227,9 @@ files:
|
|
227
227
|
- lib/packetgen/header/mldv2/mlq.rb
|
228
228
|
- lib/packetgen/header/mldv2/mlr.rb
|
229
229
|
- lib/packetgen/header/netbios.rb
|
230
|
+
- lib/packetgen/header/netbios/datagram.rb
|
231
|
+
- lib/packetgen/header/netbios/name.rb
|
232
|
+
- lib/packetgen/header/netbios/session.rb
|
230
233
|
- lib/packetgen/header/ospfv2.rb
|
231
234
|
- lib/packetgen/header/ospfv2/db_description.rb
|
232
235
|
- lib/packetgen/header/ospfv2/hello.rb
|
@@ -287,7 +290,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
287
290
|
requirements:
|
288
291
|
- - ">="
|
289
292
|
- !ruby/object:Gem::Version
|
290
|
-
version: 2.
|
293
|
+
version: 2.3.0
|
291
294
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
292
295
|
requirements:
|
293
296
|
- - ">="
|