packetgen 2.1.2 → 2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/README.md +10 -3
- data/bin/pgconsole +25 -28
- data/lib/packetgen/config.rb +47 -31
- data/lib/packetgen/header/arp.rb +1 -2
- data/lib/packetgen/header/asn1_base.rb +4 -0
- data/lib/packetgen/header/dns/question.rb +16 -30
- data/lib/packetgen/header/dot11.rb +73 -8
- data/lib/packetgen/header/dot11/control.rb +11 -1
- data/lib/packetgen/header/dot11/data.rb +14 -0
- data/lib/packetgen/header/dot11/element.rb +2 -0
- data/lib/packetgen/header/dot11/management.rb +43 -0
- data/lib/packetgen/header/dot11/sub_mngt.rb +84 -1
- data/lib/packetgen/header/dot1x.rb +8 -27
- data/lib/packetgen/header/ike.rb +10 -25
- data/lib/packetgen/header/ike/cert.rb +15 -31
- data/lib/packetgen/header/ike/notify.rb +35 -78
- data/lib/packetgen/header/ike/sa.rb +13 -25
- data/lib/packetgen/header/ike/ts.rb +4 -3
- data/lib/packetgen/inspect.rb +6 -4
- data/lib/packetgen/packet.rb +1 -1
- data/lib/packetgen/pcapng/epb.rb +1 -1
- data/lib/packetgen/pcapng/idb.rb +2 -2
- data/lib/packetgen/pcapng/shb.rb +1 -1
- data/lib/packetgen/pcapng/spb.rb +1 -1
- data/lib/packetgen/pcapng/unknown_block.rb +2 -2
- data/lib/packetgen/proto.rb +1 -1
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/enum.rb +165 -0
- data/lib/packetgen/types/fields.rb +29 -9
- data/lib/packetgen/types/int.rb +4 -0
- data/lib/packetgen/utils.rb +101 -0
- data/lib/packetgen/utils/arp_spoofer.rb +191 -0
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e306dbee54d246dd2044db6610ba27e3fb539215
|
4
|
+
data.tar.gz: 1103a3a6429fb2b4c8391750cdefa8c7d87ac323
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 592a69c18ea009c84374aa79125134ee136f0ed9050aefb8610ff484447f9cddc66685fcc3449733d2f6a1160de403d51a4465689029090815db45cdf292e12f
|
7
|
+
data.tar.gz: cf57d3f41ea4eaa30964086ec2a1127a0f2aae14a291b2fc7476819484aaa0a14a5c0681bda1f68ad7ba4aa84edc6196cb7684054ea94c22c91a5626eb2ac533
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -41,6 +41,11 @@ PacketGen.gen('Eth', src: '00:00:00:00:00:01', dst: '00:00:00:00:00:02').to_w
|
|
41
41
|
PacketGen.gen('IP', src: '192.168.1.1', dst: '192.168.1.2').to_w
|
42
42
|
# send forged IP packet over Ethernet
|
43
43
|
PacketGen.gen('Eth', src: '00:00:00:00:00:01', dst: '00:00:00:00:00:02').add('IP').to_w('eth1')
|
44
|
+
# send a IEEE 802.11 frame
|
45
|
+
PacketGen.gen('RadioTap').
|
46
|
+
add('Dot11::Management', mac1: client, mac2: bssid, mac3: bssid).
|
47
|
+
add('Dot11::DeAuth', reason: 7).
|
48
|
+
to_w('wlan0')
|
44
49
|
```
|
45
50
|
|
46
51
|
### Parse packets from binary data
|
@@ -148,9 +153,11 @@ classes. A special `config` object gives local network configuration:
|
|
148
153
|
|
149
154
|
If `pry` gem is installed, it is used as backend for `pgconsole`, else IRB is used.
|
150
155
|
|
151
|
-
##
|
156
|
+
## See also
|
152
157
|
|
153
|
-
|
158
|
+
Wiki: https://github.com/sdaubert/packetgen/wiki
|
159
|
+
|
160
|
+
API documentation: http://www.rubydoc.info/gems/packetgen
|
154
161
|
|
155
162
|
## Pull requests?
|
156
163
|
|
@@ -165,4 +172,4 @@ Copyright © 2016 Sylvain Daubert
|
|
165
172
|
All original code maintains its copyright from its original authors and licensing.
|
166
173
|
|
167
174
|
This is mainly for PcapNG (originally copied from [PacketFu](https://github.com/packetfu/packetfu),
|
168
|
-
but i am the original author
|
175
|
+
but i am the original author.
|
data/bin/pgconsole
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'packetgen'
|
4
4
|
require 'packetgen/config'
|
5
|
+
require 'packetgen/utils'
|
5
6
|
|
6
7
|
use_pry = false
|
7
8
|
begin
|
@@ -13,28 +14,25 @@ rescue LoadError
|
|
13
14
|
require 'irb/completion'
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
+
class PgConsole
|
18
|
+
include PacketGen
|
19
|
+
include Utils
|
17
20
|
|
18
|
-
def
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def capture(options={})
|
23
|
-
Packet.capture(options) { |packet| yield packet if block_given? }
|
24
|
-
end
|
25
|
-
|
26
|
-
def read(filename)
|
27
|
-
Packet.read filename
|
28
|
-
end
|
29
|
-
|
30
|
-
def write(filename, packets)
|
31
|
-
Packet.write filename, packets
|
32
|
-
end
|
21
|
+
def config
|
22
|
+
PacketGen::Config.instance
|
23
|
+
end
|
33
24
|
|
34
|
-
|
25
|
+
PacketGen.singleton_methods.each do |m|
|
26
|
+
define_method m, PacketGen.method(m).to_proc
|
27
|
+
end
|
35
28
|
|
36
|
-
|
37
|
-
|
29
|
+
Utils.singleton_methods.each do |m|
|
30
|
+
define_method m, Utils.method(m).to_proc
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_binding
|
34
|
+
binding
|
35
|
+
end
|
38
36
|
end
|
39
37
|
|
40
38
|
def start_message(use_pry)
|
@@ -47,21 +45,21 @@ if use_pry
|
|
47
45
|
Pry.config.prompt = [
|
48
46
|
proc { |target_self, nest_level, pry|
|
49
47
|
"#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}> "
|
50
|
-
},
|
51
|
-
proc { |target_self, nest_level, pry|
|
52
|
-
"#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}* "
|
48
|
+
},
|
49
|
+
proc { |target_self, nest_level, pry|
|
50
|
+
"#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}* "
|
53
51
|
}
|
54
52
|
]
|
55
53
|
Pry.config.prompt_name = 'pg'
|
56
|
-
|
54
|
+
PgConsole.new.get_binding.pry
|
57
55
|
else
|
58
56
|
IRB.setup nil
|
59
|
-
irb = IRB::Irb.new(IRB::WorkSpace.new(
|
57
|
+
irb = IRB::Irb.new(IRB::WorkSpace.new(PgConsole.new.get_binding))
|
60
58
|
IRB.conf[:MAIN_CONTEXT] = irb.context
|
61
59
|
irb.context.auto_indent_mode = true
|
62
|
-
irb.context.prompt_i = "pg
|
63
|
-
irb.context.prompt_s = "pg
|
64
|
-
irb.context.prompt_c = "pg
|
60
|
+
irb.context.prompt_i = "pg> "
|
61
|
+
irb.context.prompt_s = "pg* "
|
62
|
+
irb.context.prompt_c = "pg* "
|
65
63
|
|
66
64
|
trap("SIGINT") do
|
67
65
|
irb.signal_handle
|
@@ -75,4 +73,3 @@ else
|
|
75
73
|
IRB.irb_at_exit
|
76
74
|
end
|
77
75
|
end
|
78
|
-
|
data/lib/packetgen/config.rb
CHANGED
@@ -3,52 +3,68 @@
|
|
3
3
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
4
|
# This program is published under MIT license.
|
5
5
|
|
6
|
-
require 'network_interface'
|
7
6
|
require 'socket'
|
7
|
+
require 'singleton'
|
8
|
+
require 'network_interface'
|
8
9
|
|
9
10
|
module PacketGen
|
10
11
|
|
11
12
|
# Config class to provide +config+ object to pgconsole
|
12
13
|
# @author Sylvain Daubert
|
13
14
|
# @author Kent 'picat' Gruber
|
15
|
+
# @since 2.1.3 Config is singleton
|
14
16
|
class Config
|
17
|
+
include Singleton
|
15
18
|
|
16
19
|
# Default network interface
|
17
20
|
# @return [String]
|
18
|
-
attr_reader :
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
attr_reader :default_iface
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
begin
|
25
|
+
default_iface = Pcap.lookupdev
|
26
|
+
rescue PCAPRUB::BindingError
|
27
|
+
default_iface = NetworkInterface.interfaces.select { |i| i =~ /lo/ }.first
|
28
|
+
end
|
29
|
+
@default_iface = default_iface
|
30
|
+
@hwaddr = {}
|
31
|
+
@ipaddr = {}
|
32
|
+
@ip6addr = {}
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
NetworkInterface.interfaces.each do |iface|
|
35
|
+
addresses = NetworkInterface.addresses(iface)
|
36
|
+
@hwaddr[iface] = case RbConfig::CONFIG['target_os']
|
37
|
+
when /darwin/
|
38
|
+
addresses[Socket::AF_LINK][0]['addr'] if addresses[Socket::AF_LINK]
|
39
|
+
else
|
40
|
+
addresses[Socket::AF_PACKET][0]['addr'] if addresses[Socket::AF_PACKET]
|
41
|
+
end
|
42
|
+
@ipaddr[iface] = addresses[Socket::AF_INET][0]['addr'] if addresses[Socket::AF_INET]
|
43
|
+
if addresses[Socket::AF_INET6]
|
44
|
+
@ip6addr[iface] = addresses[Socket::AF_INET6].map { |hsh| hsh['addr'] }
|
39
45
|
end
|
40
46
|
end
|
41
|
-
|
47
|
+
end
|
42
48
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
# Get MAC address for given network interface
|
50
|
+
# @param [String,nil] iface network interface. Il +nil+, use default one.
|
51
|
+
# @return [String]
|
52
|
+
def hwaddr(iface=nil)
|
53
|
+
@hwaddr[iface || @default_iface]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get IP address for given network interface
|
57
|
+
# @param [String,nil] iface network interface. Il +nil+, use default one.
|
58
|
+
# @return [String]
|
59
|
+
def ipaddr(iface=nil)
|
60
|
+
@ipaddr[iface || @default_iface]
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get IPv6 addresses for given network interface
|
64
|
+
# @param [String,nil] iface network interface. Il +nil+, use default one.
|
65
|
+
# @return [Array<String>]
|
66
|
+
def ip6addr(iface=nil)
|
67
|
+
@ip6addr[iface || @default_iface]
|
52
68
|
end
|
53
69
|
end
|
54
70
|
end
|
data/lib/packetgen/header/arp.rb
CHANGED
@@ -48,7 +48,7 @@ module PacketGen
|
|
48
48
|
# @!attribute op
|
49
49
|
# 16-bit operation code
|
50
50
|
# # @return [Integer]
|
51
|
-
define_field :op, Types::
|
51
|
+
define_field :op, Types::Int16Enum, enum: { 'request' => 1, 'reply' => 2 }
|
52
52
|
# @!attribute sha
|
53
53
|
# source hardware address
|
54
54
|
# @return [Eth::MacAddr]
|
@@ -119,4 +119,3 @@ module PacketGen
|
|
119
119
|
Dot1q.bind_header ARP, ethertype: 0x806
|
120
120
|
end
|
121
121
|
end
|
122
|
-
|
@@ -8,6 +8,8 @@ module PacketGen
|
|
8
8
|
module Header
|
9
9
|
|
10
10
|
# @abstract Base class for ASN.1 header types.
|
11
|
+
# This class implement minimal {Base} API to mimic a {Base} object.
|
12
|
+
#
|
11
13
|
# Subclasses may define magic methods:
|
12
14
|
# * {#parse?}.
|
13
15
|
# @author Sylvain Daubert
|
@@ -56,6 +58,8 @@ module PacketGen
|
|
56
58
|
@method_name = protocol_name.downcase.sub(/::/, '_')
|
57
59
|
end
|
58
60
|
|
61
|
+
# Called by {Packet#parse} when guessing first header to check if header
|
62
|
+
# is correct
|
59
63
|
# @return [true]
|
60
64
|
def parse?
|
61
65
|
true
|
@@ -6,19 +6,6 @@ module PacketGen
|
|
6
6
|
# @author Sylvain Daubert
|
7
7
|
class Question < Base
|
8
8
|
|
9
|
-
# @!attribute name
|
10
|
-
# Question domain name
|
11
|
-
# @return [String]
|
12
|
-
define_field :name, Name, default: '.'
|
13
|
-
# @!attribute type
|
14
|
-
# 16-bit question type
|
15
|
-
# @return [Integer]
|
16
|
-
define_field :type, Types::Int16, default: 1
|
17
|
-
# @!attribute rrclass
|
18
|
-
# 16-bit question class
|
19
|
-
# @return [Integer]
|
20
|
-
define_field :rrclass, Types::Int16, default: 1
|
21
|
-
|
22
9
|
# Ressource Record types
|
23
10
|
TYPES = {
|
24
11
|
'A' => 1,
|
@@ -49,7 +36,7 @@ module PacketGen
|
|
49
36
|
'TKEY' => 249,
|
50
37
|
'TSIG' => 250,
|
51
38
|
'*' => 255
|
52
|
-
}
|
39
|
+
}.freeze
|
53
40
|
|
54
41
|
# Ressource Record classes
|
55
42
|
CLASSES = {
|
@@ -58,7 +45,20 @@ module PacketGen
|
|
58
45
|
'HS' => 4,
|
59
46
|
'NONE' => 254,
|
60
47
|
'*' => 255
|
61
|
-
}
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
# @!attribute name
|
51
|
+
# Question domain name
|
52
|
+
# @return [String]
|
53
|
+
define_field :name, Name, default: '.'
|
54
|
+
# @!attribute type
|
55
|
+
# 16-bit question type
|
56
|
+
# @return [Integer]
|
57
|
+
define_field :type, Types::Int16Enum, default: 1, enum: TYPES
|
58
|
+
# @!attribute rrclass
|
59
|
+
# 16-bit question class
|
60
|
+
# @return [Integer]
|
61
|
+
define_field :rrclass, Types::Int16Enum, default: 1, enum: CLASSES
|
62
62
|
|
63
63
|
# @param [DNS] dns
|
64
64
|
# @param [Hash] options
|
@@ -72,20 +72,6 @@ module PacketGen
|
|
72
72
|
self.rrclass = options[:rrclass] if options[:rrclass]
|
73
73
|
end
|
74
74
|
|
75
|
-
# Setter for type
|
76
|
-
# @param [Integer] val
|
77
|
-
# @return [Integer,String]
|
78
|
-
def type=(val)
|
79
|
-
v = case val
|
80
|
-
when String
|
81
|
-
self.class::TYPES[val.upcase]
|
82
|
-
else
|
83
|
-
val
|
84
|
-
end
|
85
|
-
raise ArgumentError, "unknown type #{val.inspect}" unless v
|
86
|
-
self[:type].read v
|
87
|
-
end
|
88
|
-
|
89
75
|
# Setter for class
|
90
76
|
# @param [Integer] val
|
91
77
|
# @return [Integer,String]
|
@@ -109,7 +95,7 @@ module PacketGen
|
|
109
95
|
|
110
96
|
# Get human readable type
|
111
97
|
# @return [String]
|
112
|
-
|
98
|
+
def human_type
|
113
99
|
self.class::TYPES.key(type) || "0x%04x" % type
|
114
100
|
end
|
115
101
|
|
@@ -50,7 +50,14 @@ module PacketGen
|
|
50
50
|
# Check version field
|
51
51
|
# @see [Base#parse?]
|
52
52
|
def parse?
|
53
|
-
version == 0
|
53
|
+
version == 0 and length >= 8
|
54
|
+
end
|
55
|
+
|
56
|
+
# Calculate length field
|
57
|
+
# @return [Integer] calculated length
|
58
|
+
# @since 2.1.3
|
59
|
+
def calc_length
|
60
|
+
self[:length].value = self.sz - self[:body].sz
|
54
61
|
end
|
55
62
|
|
56
63
|
# send PPI packet on wire. Dot11 FCS trailer should be set.
|
@@ -64,7 +71,7 @@ module PacketGen
|
|
64
71
|
end
|
65
72
|
self.add_class PPI
|
66
73
|
|
67
|
-
# Radiotap header
|
74
|
+
# Radiotap header (see http://www.radiotap.org/)
|
68
75
|
# @author Sylvain Daubert
|
69
76
|
class RadioTap < Base
|
70
77
|
# @!attribute version
|
@@ -75,7 +82,7 @@ module PacketGen
|
|
75
82
|
define_field :pad, Types::Int8, default: 0
|
76
83
|
# @!attribute length
|
77
84
|
# @return [Integer] 16-bit RadioTap header length
|
78
|
-
define_field :length, Types::Int16le
|
85
|
+
define_field :length, Types::Int16le, default: 8
|
79
86
|
# @!attribute present_flags
|
80
87
|
# @return [Integer] 32-bit integer
|
81
88
|
define_field :present_flags, Types::Int32le
|
@@ -103,7 +110,14 @@ module PacketGen
|
|
103
110
|
# Check version field
|
104
111
|
# @see [Base#parse?]
|
105
112
|
def parse?
|
106
|
-
version == 0
|
113
|
+
version == 0 and length >= 8
|
114
|
+
end
|
115
|
+
|
116
|
+
# Calculate length field
|
117
|
+
# @return [Integer] calculated length
|
118
|
+
# @since 2.1.3
|
119
|
+
def calc_length
|
120
|
+
self[:length].value = self.sz - self[:body].sz
|
107
121
|
end
|
108
122
|
|
109
123
|
# send RadioTap packet on wire. Dot11 FCS trailer should be set.
|
@@ -120,7 +134,7 @@ module PacketGen
|
|
120
134
|
# IEEE 802.11 header
|
121
135
|
# @abstract This is a base class to demultiplex different IEEE 802.11 frames when
|
122
136
|
# parsing.
|
123
|
-
# A IEEE 802.11 header may
|
137
|
+
# A IEEE 802.11 header may consist of at least:
|
124
138
|
# * a {#frame_ctrl} ({Types::Int16}),
|
125
139
|
# * a {#id}/duration ({Types::Int16le}),
|
126
140
|
# * and a {#mac1} ({Eth::MacAddr}).
|
@@ -134,10 +148,52 @@ module PacketGen
|
|
134
148
|
# * a {#body} (a {Types::String} or another {Base} class),
|
135
149
|
# * a Frame check sequence ({#fcs}, of type {Types::Int32le})
|
136
150
|
#
|
137
|
-
# ==
|
151
|
+
# == Header accessors
|
138
152
|
# As Dot11 header types are defined under Dot11 namespace, Dot11 header accessors
|
139
153
|
# have a specific name. By example, to access to a {Dot11::Beacon} header,
|
140
154
|
# accessor is +#dot11_beacon+.
|
155
|
+
#
|
156
|
+
# == Create Dot11 packets
|
157
|
+
# As {Dot11} is an abstract class, you have to use one of its subclasses to
|
158
|
+
# instanciate a IEEE802.11 header.
|
159
|
+
#
|
160
|
+
# === IEEE802.11 control frames
|
161
|
+
# Control frames may be created this way:
|
162
|
+
# pkt = PacketGen.gen('Dot11::Control', subtype: 13) # Ack control frame
|
163
|
+
# pkt.dot11_control # => PacketGen::Header::Dot11::Control
|
164
|
+
#
|
165
|
+
# === IEEE802.11 management frames
|
166
|
+
# Management frames may be created this way:
|
167
|
+
# pkt = PacketGen.gen('Dot11::Management')
|
168
|
+
# pkt.dot11_management # => PacketGen::Header::Dot11::Management
|
169
|
+
# Management frames are usually specialized, AssociationRequest by example:
|
170
|
+
# pkt.add('Dot11::AssoReq')
|
171
|
+
# pkt.dot11_assoreq # => PacketGen::Header::Dot11::AssoReq
|
172
|
+
# Management frames also may contain some elements (see IEEE 802.11 standard):
|
173
|
+
# pkt.dot11_assoreq.add_elements(type: 'SSID', value: "My SSID")
|
174
|
+
# pkt.dot11_assoreq.add_elements(type: 'Rates', value: supported_rates)
|
175
|
+
#
|
176
|
+
# === IEEE802.11 data frames
|
177
|
+
# Data frames may be created this way:
|
178
|
+
# pkt = PacketGen.gen('Dot11::Data')
|
179
|
+
# pkt.dot11_data # => PacketGen::Header::Dot11::Data
|
180
|
+
#
|
181
|
+
# == Parse Dot11 packets
|
182
|
+
# When parsing a Dot11 packet, Dot11 subclass is created from +type+ value.
|
183
|
+
# Dot11 header should then be accessed through +Packet#dot11_management+,
|
184
|
+
# +Packet#dot11_control+ or +Packet#dot11_data+.
|
185
|
+
#
|
186
|
+
# A +Packet#dot11+ may exist for unknown types.
|
187
|
+
#
|
188
|
+
# == Send Dot11 packets
|
189
|
+
# To send a Dot11 packet, a RadioTap header is needed:
|
190
|
+
# pkt = PacketGen.gen('RadioTap')
|
191
|
+
# pkt.add('Dot11::Management', mac1: client, mac2: bssid, mac3: bssid)
|
192
|
+
# pkt.add('Dot11::Beacon')
|
193
|
+
# pkt.dot11_beacon.add_element(type: 'SSID', value: 'My SSID')
|
194
|
+
# pkt.dot11_beacon.add_element(type: 'Rates', value: "\x85\x0c")
|
195
|
+
# pkt.calc
|
196
|
+
# pkt.to_w('wlan0')
|
141
197
|
# @author Sylvain Daubert
|
142
198
|
class Dot11 < Base
|
143
199
|
|
@@ -211,6 +267,15 @@ module PacketGen
|
|
211
267
|
define_bit_fields_on :frame_ctrl, :subtype, 4, :type, 2, :proto_version, 2,
|
212
268
|
:order, :wep, :md, :pwmngt, :retry, :mf, :from_ds, :to_ds
|
213
269
|
|
270
|
+
|
271
|
+
# @!attribute sequence_number (12-bit field from {#sequence_ctrl})
|
272
|
+
# @return [Integer]
|
273
|
+
# @since 2.1.3
|
274
|
+
# @!attribute fragment_number (4-bit field from {#sequence_ctrl})
|
275
|
+
# @return [Integer]
|
276
|
+
# @since 2.1.3
|
277
|
+
define_bit_fields_on :sequence_ctrl, :sequence_number, 12, :fragment_number, 4
|
278
|
+
|
214
279
|
alias duration id
|
215
280
|
# @private
|
216
281
|
alias old_fields fields
|
@@ -302,7 +367,7 @@ module PacketGen
|
|
302
367
|
pcap = PCAPRUB::Pcap.open_live(iface, PCAP_SNAPLEN, PCAP_PROMISC,
|
303
368
|
PCAP_TIMEOUT)
|
304
369
|
str = self.to_s
|
305
|
-
pcap.inject str
|
370
|
+
pcap.inject str
|
306
371
|
end
|
307
372
|
|
308
373
|
private
|
@@ -317,7 +382,7 @@ module PacketGen
|
|
317
382
|
unless @applicable_fields.include? :ht_ctrl
|
318
383
|
idx = @applicable_fields.index(:body)
|
319
384
|
@applicable_fields[idx, 0] = :ht_ctrl
|
320
|
-
|
385
|
+
end
|
321
386
|
else
|
322
387
|
@applicable_fields -= %i(ht_ctrl)
|
323
388
|
end
|