packetgen 1.3.0 → 1.4.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/README.md +18 -41
- data/lib/packetgen.rb +1 -1
- data/lib/packetgen/header.rb +14 -9
- data/lib/packetgen/header/arp.rb +1 -0
- data/lib/packetgen/header/base.rb +50 -1
- data/lib/packetgen/header/dot11.rb +349 -0
- data/lib/packetgen/header/dot11/control.rb +59 -0
- data/lib/packetgen/header/dot11/data.rb +43 -0
- data/lib/packetgen/header/dot11/element.rb +35 -0
- data/lib/packetgen/header/dot11/management.rb +25 -0
- data/lib/packetgen/header/dot11/sub_mngt.rb +178 -0
- data/lib/packetgen/header/dot1q.rb +42 -0
- data/lib/packetgen/header/dot1x.rb +78 -0
- data/lib/packetgen/header/esp.rb +2 -2
- data/lib/packetgen/header/eth.rb +1 -8
- data/lib/packetgen/header/ip.rb +13 -2
- data/lib/packetgen/header/ipv6.rb +12 -1
- data/lib/packetgen/header/llc.rb +56 -0
- data/lib/packetgen/inspect.rb +1 -1
- data/lib/packetgen/packet.rb +12 -8
- data/lib/packetgen/pcapng.rb +11 -0
- data/lib/packetgen/pcapng/file.rb +5 -2
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/fields.rb +80 -10
- data/lib/packetgen/types/int_string.rb +1 -1
- data/lib/packetgen/types/oui.rb +48 -0
- data/lib/packetgen/types/string.rb +9 -4
- data/lib/packetgen/types/tlv.rb +83 -6
- data/lib/packetgen/version.rb +1 -1
- metadata +12 -2
@@ -0,0 +1,59 @@
|
|
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
|
+
class Dot11
|
10
|
+
|
11
|
+
# IEEE 802.11 control frame header
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
class Control < Dot11
|
14
|
+
|
15
|
+
# Control subtypes
|
16
|
+
SUBTYPES = {
|
17
|
+
7 => 'Wrapper',
|
18
|
+
8 => 'Block Ack Request',
|
19
|
+
9 => 'Block Ack',
|
20
|
+
10 => 'PS-Poll',
|
21
|
+
11 => 'RTS',
|
22
|
+
12 => 'CTS',
|
23
|
+
13 => 'Ack',
|
24
|
+
14 => 'CF-End',
|
25
|
+
15 => 'CF-End+CF-Ack'
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
# Control subtypes with mac2 field
|
29
|
+
SUBTYPES_WITH_MAC2 = [9, 10, 11, 14, 15].freeze
|
30
|
+
|
31
|
+
# @param [Hash] options
|
32
|
+
# @see Base#initialize
|
33
|
+
def initialize(options={})
|
34
|
+
super({type: 1}.merge!(options))
|
35
|
+
@applicable_fields -= %i(mac3 sequence_ctrl mac4 qos_ctrl ht_ctrl)
|
36
|
+
define_applicable_fields
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get human readable subtype
|
40
|
+
# @return [String]
|
41
|
+
def human_subtype
|
42
|
+
SUBTYPES[subtype] || subtype.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def define_applicable_fields
|
48
|
+
super
|
49
|
+
if @applicable_fields.include? :mac2
|
50
|
+
@applicable_fields -= %i(mac2) unless SUBTYPES_WITH_MAC2.include? self.subtype
|
51
|
+
elsif SUBTYPES_WITH_MAC2.include? self.subtype
|
52
|
+
sz = self.sz
|
53
|
+
@applicable_fields[3, 0] = :mac2
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,43 @@
|
|
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
|
+
class Dot11
|
10
|
+
|
11
|
+
# IEEE 802.11 data frame header
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
class Data < Dot11
|
14
|
+
|
15
|
+
# @param [Hash] options
|
16
|
+
# @see Base#initialize
|
17
|
+
def initialize(options={})
|
18
|
+
super({type: 2}.merge!(options))
|
19
|
+
@applicable_fields -= %i(mac4 qos_ctrl ht_ctrl)
|
20
|
+
define_applicable_fields
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def define_applicable_fields
|
26
|
+
super
|
27
|
+
if subtype >= 8 and !@applicable_fields.include? :qos_ctrl
|
28
|
+
# Insert after mac4, if present
|
29
|
+
# else insert after sequence_ctrl
|
30
|
+
if @applicable_fields.include? :mac4
|
31
|
+
idx = @applicable_fields.index(:mac4)
|
32
|
+
@applicable_fields[idx, 0] = :qos_ctrl
|
33
|
+
else
|
34
|
+
@applicable_fields[6, 0] = :qos_ctrl
|
35
|
+
end
|
36
|
+
elsif subtype < 8
|
37
|
+
@applicable_fields -= %i(qos_ctrl)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
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
|
+
class Dot11
|
10
|
+
|
11
|
+
# IEEE 802.11 information element
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
class Element < Types::TLV
|
14
|
+
# Known element types
|
15
|
+
TYPES = {
|
16
|
+
0 => 'SSID',
|
17
|
+
1 => 'Rates',
|
18
|
+
2 => 'FHset',
|
19
|
+
3 => 'DSset',
|
20
|
+
4 => 'CFset',
|
21
|
+
5 => 'TIM',
|
22
|
+
6 => 'IBSSset',
|
23
|
+
16 => 'challenge',
|
24
|
+
42 => 'ERPinfo',
|
25
|
+
46 => 'QoS Cap.',
|
26
|
+
47 => 'ERPinfo',
|
27
|
+
48 => 'RSNinfo',
|
28
|
+
50 => 'ESRates',
|
29
|
+
68 => 'reserved',
|
30
|
+
221 => 'vendor'
|
31
|
+
}.freeze
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
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
|
+
class Dot11
|
10
|
+
|
11
|
+
# IEEE 802.11 management frame header
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
class Management < Dot11
|
14
|
+
|
15
|
+
# @param [Hash] options
|
16
|
+
# @see Base#initialize
|
17
|
+
def initialize(options={})
|
18
|
+
super({type: 0}.merge!(options))
|
19
|
+
@applicable_fields -= %i(mac4 qos_ctrl ht_ctrl)
|
20
|
+
define_applicable_fields
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,178 @@
|
|
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
|
+
class Dot11
|
10
|
+
|
11
|
+
# @abstract Base class for all subtype management frames
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
class SubMngt < Base
|
14
|
+
# @return [Array<Element>]
|
15
|
+
attr_accessor :elements
|
16
|
+
|
17
|
+
# @param [Hash] options
|
18
|
+
# @see Base#initialize
|
19
|
+
def initialize(options={})
|
20
|
+
super
|
21
|
+
@elements = []
|
22
|
+
end
|
23
|
+
|
24
|
+
# Populate object from binary string
|
25
|
+
# @param [String] str
|
26
|
+
# @return [SubMngt] self
|
27
|
+
def read(str)
|
28
|
+
super
|
29
|
+
read_elements str[sz, str.size] || ''
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String]
|
34
|
+
def to_s
|
35
|
+
super + @elements.map(&:to_s).join
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [String]
|
39
|
+
def inspect
|
40
|
+
str = super
|
41
|
+
str << Inspect.dashed_line('Dot11 Elements', level=3)
|
42
|
+
@elements.each do |el|
|
43
|
+
str << Inspect.shift_level(4) << el.to_human << "\n"
|
44
|
+
end
|
45
|
+
str
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def read_elements(str)
|
51
|
+
start = 0
|
52
|
+
elsz = Element.new.sz
|
53
|
+
while str.size - start >= elsz do
|
54
|
+
el = Element.new.read(str[start, str.size])
|
55
|
+
@elements << el
|
56
|
+
start += el.sz
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# IEEE 802.11 Association Request frame
|
62
|
+
class AssoReq < SubMngt
|
63
|
+
# @!attribute cap
|
64
|
+
# @return [Integer] 16-bit capabillities word
|
65
|
+
define_field :cap, Types::Int16le
|
66
|
+
# @!attribute listen_interval
|
67
|
+
# @return [Integer] 16-bit listen interval value
|
68
|
+
define_field :listen_interval, Types::Int16le, default: 0x00c8
|
69
|
+
end
|
70
|
+
Header.add_class AssoReq
|
71
|
+
Management.bind_header AssoReq, op: :and, type: 0, subtype: 0
|
72
|
+
|
73
|
+
# IEEE 802.11 Association Response frame
|
74
|
+
class AssoResp < SubMngt
|
75
|
+
# @!attribute cap
|
76
|
+
# @return [Integer] 16-bit capabillities word
|
77
|
+
define_field :cap, Types::Int16le
|
78
|
+
# @!attribute status
|
79
|
+
# @return [Integer] 16-bit status word
|
80
|
+
define_field :status, Types::Int16le
|
81
|
+
# @!attribute aid
|
82
|
+
# @return [Integer] 16-bit AID word
|
83
|
+
define_field :aid, Types::Int16le
|
84
|
+
end
|
85
|
+
Header.add_class AssoResp
|
86
|
+
Management.bind_header AssoResp, op: :and, type: 0, subtype: 1
|
87
|
+
|
88
|
+
# IEEE 802.11 ReAssociation Request frame
|
89
|
+
class ReAssoReq < AssoReq
|
90
|
+
# @!attribute current_ap
|
91
|
+
# @return [Eth::MAcAddr]
|
92
|
+
define_field :current_ap, Eth::MacAddr
|
93
|
+
end
|
94
|
+
Header.add_class ReAssoReq
|
95
|
+
Management.bind_header ReAssoReq, op: :and, type: 0, subtype: 2
|
96
|
+
|
97
|
+
# IEEE 802.11 ReAssociation Response frame
|
98
|
+
class ReAssoResp < AssoResp
|
99
|
+
end
|
100
|
+
Header.add_class ReAssoResp
|
101
|
+
Management.bind_header ReAssoResp, op: :and, type: 0, subtype: 3
|
102
|
+
|
103
|
+
# IEEE 802.11 Probe Request frame
|
104
|
+
class ProbeReq < SubMngt
|
105
|
+
end
|
106
|
+
Header.add_class ProbeReq
|
107
|
+
Management.bind_header ProbeReq, op: :and, type: 0, subtype: 4
|
108
|
+
|
109
|
+
# IEEE 802.11 Probe Response frame
|
110
|
+
class ProbeResp < SubMngt
|
111
|
+
# @!attribute timestamp
|
112
|
+
# @return [Integer] 64-bit timestamp
|
113
|
+
define_field :timestamp, Types::Int64le
|
114
|
+
# @!attribute beacon_interval
|
115
|
+
# @return [Integer] 16-bit beacon interval value
|
116
|
+
define_field :beacon_interval, Types::Int16le, default: 0x0064
|
117
|
+
# @!attribute cap
|
118
|
+
# @return [Integer] 16-bit capabillities word
|
119
|
+
define_field :cap, Types::Int16le
|
120
|
+
end
|
121
|
+
Header.add_class ProbeResp
|
122
|
+
Management.bind_header ProbeResp, op: :and, type: 0, subtype: 5
|
123
|
+
|
124
|
+
# IEEE 802.11 Beacon frame
|
125
|
+
class Beacon < SubMngt
|
126
|
+
# @!attribute timestamp
|
127
|
+
# @return [Integer] 64-bit timestamp
|
128
|
+
define_field :timestamp, Types::Int64le
|
129
|
+
# @!attribute interval
|
130
|
+
# @return [Integer] 16-bit interval value
|
131
|
+
define_field :interval, Types::Int16le, default: 0x64
|
132
|
+
# @!attribute cap
|
133
|
+
# @return [Integer] 16-bit capabillities word
|
134
|
+
define_field :cap, Types::Int16le
|
135
|
+
end
|
136
|
+
Header.add_class Beacon
|
137
|
+
Management.bind_header Beacon, op: :and, type: 0, subtype: 8
|
138
|
+
|
139
|
+
# IEEE 802.11 ATIM frame
|
140
|
+
class ATIM < SubMngt; end
|
141
|
+
Header.add_class ATIM
|
142
|
+
Management.bind_header ATIM, op: :and, type: 0, subtype: 9
|
143
|
+
|
144
|
+
# IEEE 802.11 Disassociation frame
|
145
|
+
class Disas < SubMngt
|
146
|
+
# @!attribute reason
|
147
|
+
# @return [Integer] 16-bit reason value
|
148
|
+
define_field :reason, Types::Int16le
|
149
|
+
end
|
150
|
+
Header.add_class Disas
|
151
|
+
Management.bind_header Disas, op: :and, type: 0, subtype: 10
|
152
|
+
|
153
|
+
# IEEE 802.11 Authentication frame
|
154
|
+
class Auth < SubMngt
|
155
|
+
# @!attribute algo
|
156
|
+
# @return [Integer] 16-bit algo value
|
157
|
+
define_field :algo, Types::Int16le
|
158
|
+
# @!attribute seqnum
|
159
|
+
# @return [Integer] 16-bit seqnum value
|
160
|
+
define_field :seqnum, Types::Int16le
|
161
|
+
# @!attribute status
|
162
|
+
# @return [Integer] 16-bit status word
|
163
|
+
define_field :status, Types::Int16le
|
164
|
+
end
|
165
|
+
Header.add_class Auth
|
166
|
+
Management.bind_header Auth, op: :and, type: 0, subtype: 11
|
167
|
+
|
168
|
+
# IEEE 802.11 Deauthentication frame
|
169
|
+
class DeAuth < SubMngt
|
170
|
+
# @!attribute reason
|
171
|
+
# @return [Integer] 16-bit reason value
|
172
|
+
define_field :reason, Types::Int16le
|
173
|
+
end
|
174
|
+
Header.add_class DeAuth
|
175
|
+
Management.bind_header DeAuth, op: :and, type: 0, subtype: 12
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
|
9
|
+
# IEEE 802.1Q VLAN tagging
|
10
|
+
#
|
11
|
+
# A VLAN tag consists of:
|
12
|
+
# * a {#tci Tag Control Information} ({Types::Int16}),
|
13
|
+
# * a {#ethertype} ({Types::Int16}),
|
14
|
+
# * and a body (a {Types::String} or another Header class).
|
15
|
+
#
|
16
|
+
# == Create a Dot1q header
|
17
|
+
# # Create a IP packet in VLAN #43
|
18
|
+
# pkt = PacketGen.gen('Eth').add('Dot1q', vid: 43).add('IP')
|
19
|
+
# @author Sylvain Daubert
|
20
|
+
class Dot1q < Base
|
21
|
+
# @!attribute tci
|
22
|
+
# @return [Integer] 16-bit Tag Control Information
|
23
|
+
define_field :tci, Types::Int16
|
24
|
+
# @!attribute ethertype
|
25
|
+
# @return [Integer] 16-bit EtherType
|
26
|
+
define_field :ethertype, Types::Int16
|
27
|
+
# @!attribute body
|
28
|
+
# @return [Types::String,Header::Base]
|
29
|
+
define_field :body, Types::String
|
30
|
+
|
31
|
+
# @!attribute pcp
|
32
|
+
# @return [Integer] 3-bit Priority Code Point from {#tci}
|
33
|
+
# @!attribute dei
|
34
|
+
# @return [Boolean] Drop Eligible Indicator from {#tci}
|
35
|
+
# @!attribute vid
|
36
|
+
# @return [Integer] 12-bit VLAN ID from {#tci}
|
37
|
+
define_bit_fields_on :tci, :pcp, 3, :dei, :vid, 12
|
38
|
+
end
|
39
|
+
|
40
|
+
Eth.bind_header Dot1q, ethertype: 0x8100
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,78 @@
|
|
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
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
|
9
|
+
# IEEE 802.1X / EAPOL
|
10
|
+
#
|
11
|
+
# A IEEE 802.1X header consists of:
|
12
|
+
# * a {#version} ({Types::Int8}),
|
13
|
+
# * a packet {#type} ({Types::Int8}),
|
14
|
+
# * a {#length} ({Types::Int16}),
|
15
|
+
# * and a body (a {Types::String} or another Header class).
|
16
|
+
# == Create a Dot1x header
|
17
|
+
# pkt1 = PacketGen.gen('Eth').add('Dot1x', type: 1)
|
18
|
+
# pkt2 = PacketGen.gen('Eth').add('Dot1x')
|
19
|
+
# pkt2.dot1x.type = 'EAP Packet'
|
20
|
+
# pkt2.dot1x.body.read 'body'
|
21
|
+
# @author Sylvain Daubert
|
22
|
+
class Dot1x < Base
|
23
|
+
|
24
|
+
# IEEE 802.1x Ether type
|
25
|
+
ETHERTYPE = 0x888e
|
26
|
+
|
27
|
+
# IEEE 802.1X packet types
|
28
|
+
TYPES = {
|
29
|
+
0 => 'EAP Packet',
|
30
|
+
1 => 'Start',
|
31
|
+
2 => 'Logoff',
|
32
|
+
3 => 'Key',
|
33
|
+
4 => 'Encap-ASF-Alert'
|
34
|
+
}
|
35
|
+
|
36
|
+
# @!attribute version
|
37
|
+
# @return [Integer] 8-bit Protocol Version
|
38
|
+
define_field :version, Types::Int8, default: 1
|
39
|
+
# @!attribute type
|
40
|
+
# @return [Integer] 8-bit Packet Type
|
41
|
+
define_field :type, Types::Int8
|
42
|
+
# @!attribute length
|
43
|
+
# @return [Integer] 16-bit body length
|
44
|
+
define_field :length, Types::Int16
|
45
|
+
# @!attribute body
|
46
|
+
# @return [Types::String,Header::Base]
|
47
|
+
define_field :body, Types::String
|
48
|
+
|
49
|
+
# @private
|
50
|
+
alias old_type= type=
|
51
|
+
|
52
|
+
# Set type attribute
|
53
|
+
# @param [String,Integer] type
|
54
|
+
# @return [Integer]
|
55
|
+
def type=(type)
|
56
|
+
case type
|
57
|
+
when Integer
|
58
|
+
self.old_type = type
|
59
|
+
else
|
60
|
+
v = TYPES.key(type.to_s)
|
61
|
+
raise ArgumentError, "unknown type #{type}" if v.nil?
|
62
|
+
self.old_type = v
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get human readable type
|
67
|
+
# @return [String]
|
68
|
+
def human_type
|
69
|
+
v = TYPES[self.type]
|
70
|
+
v = self.type if v.nil?
|
71
|
+
v.to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
Eth.bind_header Dot1x, ethertype: Dot1x::ETHERTYPE
|
76
|
+
SNAP.bind_header Dot1x, proto_id: Dot1x::ETHERTYPE
|
77
|
+
end
|
78
|
+
end
|