packetgen 2.8.7 → 3.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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -1
  3. data/README.md +5 -4
  4. data/lib/packetgen.rb +6 -12
  5. data/lib/packetgen/capture.rb +43 -39
  6. data/lib/packetgen/config.rb +0 -1
  7. data/lib/packetgen/deprecation.rb +1 -1
  8. data/lib/packetgen/header.rb +9 -9
  9. data/lib/packetgen/header/asn1_base.rb +10 -10
  10. data/lib/packetgen/header/base.rb +42 -101
  11. data/lib/packetgen/header/dhcp/option.rb +5 -11
  12. data/lib/packetgen/header/dhcpv6/duid.rb +2 -0
  13. data/lib/packetgen/header/dhcpv6/option.rb +2 -19
  14. data/lib/packetgen/header/dhcpv6/options.rb +7 -0
  15. data/lib/packetgen/header/dns.rb +5 -23
  16. data/lib/packetgen/header/dns/name.rb +1 -0
  17. data/lib/packetgen/header/dns/qdsection.rb +1 -0
  18. data/lib/packetgen/header/dns/question.rb +3 -7
  19. data/lib/packetgen/header/dns/rr.rb +3 -0
  20. data/lib/packetgen/header/dns/rrsection.rb +1 -0
  21. data/lib/packetgen/header/dot11.rb +1 -17
  22. data/lib/packetgen/header/dot1x.rb +1 -0
  23. data/lib/packetgen/header/eap.rb +4 -7
  24. data/lib/packetgen/header/eth.rb +2 -0
  25. data/lib/packetgen/header/http/headers.rb +3 -0
  26. data/lib/packetgen/header/http/request.rb +5 -4
  27. data/lib/packetgen/header/http/response.rb +5 -4
  28. data/lib/packetgen/header/icmp.rb +6 -0
  29. data/lib/packetgen/header/icmpv6.rb +6 -0
  30. data/lib/packetgen/header/igmpv3/mq.rb +2 -0
  31. data/lib/packetgen/header/ip.rb +32 -30
  32. data/lib/packetgen/header/ip/addr.rb +1 -0
  33. data/lib/packetgen/header/ip/option.rb +23 -20
  34. data/lib/packetgen/header/ip/options.rb +11 -24
  35. data/lib/packetgen/header/ipv6.rb +45 -34
  36. data/lib/packetgen/header/ipv6/addr.rb +2 -0
  37. data/lib/packetgen/header/ipv6/hop_by_hop.rb +7 -31
  38. data/lib/packetgen/header/mdns.rb +1 -0
  39. data/lib/packetgen/header/mldv2/mlq.rb +2 -0
  40. data/lib/packetgen/header/ospfv2/lsa.rb +15 -25
  41. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +1 -1
  42. data/lib/packetgen/header/ospfv3/lsa.rb +8 -25
  43. data/lib/packetgen/header/snmp.rb +2 -0
  44. data/lib/packetgen/header/tcp.rb +23 -2
  45. data/lib/packetgen/header/tcp/option.rb +51 -52
  46. data/lib/packetgen/header/tcp/options.rb +17 -52
  47. data/lib/packetgen/header/tftp.rb +3 -0
  48. data/lib/packetgen/header/udp.rb +8 -0
  49. data/lib/packetgen/packet.rb +119 -102
  50. data/lib/packetgen/pcapng/block.rb +4 -10
  51. data/lib/packetgen/pcapng/epb.rb +4 -4
  52. data/lib/packetgen/pcapng/file.rb +7 -3
  53. data/lib/packetgen/pcapng/idb.rb +2 -2
  54. data/lib/packetgen/pcapng/shb.rb +3 -3
  55. data/lib/packetgen/pcapng/spb.rb +1 -8
  56. data/lib/packetgen/pcapng/unknown_block.rb +0 -7
  57. data/lib/packetgen/types.rb +1 -0
  58. data/lib/packetgen/types/array.rb +73 -71
  59. data/lib/packetgen/types/cstring.rb +1 -1
  60. data/lib/packetgen/types/enum.rb +3 -3
  61. data/lib/packetgen/types/fields.rb +66 -106
  62. data/lib/packetgen/types/int.rb +9 -5
  63. data/lib/packetgen/types/length_from.rb +45 -0
  64. data/lib/packetgen/types/oui.rb +2 -0
  65. data/lib/packetgen/types/string.rb +10 -16
  66. data/lib/packetgen/types/tlv.rb +7 -15
  67. data/lib/packetgen/utils.rb +8 -8
  68. data/lib/packetgen/utils/arp_spoofer.rb +1 -2
  69. data/lib/packetgen/version.rb +1 -1
  70. metadata +3 -21
  71. data/lib/packetgen/header/crypto.rb +0 -62
  72. data/lib/packetgen/header/esp.rb +0 -413
  73. data/lib/packetgen/header/ike.rb +0 -243
  74. data/lib/packetgen/header/ike/auth.rb +0 -165
  75. data/lib/packetgen/header/ike/cert.rb +0 -76
  76. data/lib/packetgen/header/ike/certreq.rb +0 -66
  77. data/lib/packetgen/header/ike/id.rb +0 -99
  78. data/lib/packetgen/header/ike/ke.rb +0 -79
  79. data/lib/packetgen/header/ike/nonce.rb +0 -40
  80. data/lib/packetgen/header/ike/notify.rb +0 -176
  81. data/lib/packetgen/header/ike/payload.rb +0 -315
  82. data/lib/packetgen/header/ike/sa.rb +0 -561
  83. data/lib/packetgen/header/ike/sk.rb +0 -261
  84. data/lib/packetgen/header/ike/ts.rb +0 -270
  85. data/lib/packetgen/header/ike/vendor_id.rb +0 -39
  86. data/lib/packetgen/header/netbios.rb +0 -20
  87. data/lib/packetgen/header/netbios/datagram.rb +0 -105
  88. data/lib/packetgen/header/netbios/name.rb +0 -67
  89. data/lib/packetgen/header/netbios/session.rb +0 -64
@@ -56,9 +56,6 @@ module PacketGen
56
56
  74 => ['IRC_server', length: 4, v: IP::Addr]
57
57
  }.freeze
58
58
 
59
- # @deprecated Use {DHCP_OPTIONS} instead.
60
- DCHPOptions = DHCP_OPTIONS
61
-
62
59
  # Class to indicate DHCP options end
63
60
  class End < Types::Int8
64
61
  def initialize(value=255)
@@ -98,9 +95,10 @@ module PacketGen
98
95
  def initialize(options={})
99
96
  super
100
97
  return unless DHCP_OPTIONS.key?(self.type)
101
- h = DHCP_OPTIONS[self.type].last
102
98
 
99
+ h = DHCP_OPTIONS[self.type].last
103
100
  return unless h.is_a? Hash
101
+
104
102
  h.each do |k, v|
105
103
  self.length = v if k == :length
106
104
  if k == :v
@@ -135,13 +133,8 @@ module PacketGen
135
133
  true
136
134
  end
137
135
 
138
- # @deprecated Use {#human_types?} instead
139
- # @return [true]
140
- def has_human_types?
141
- Deprecation.deprecated(self.class, __method__, 'human_types?')
142
- human_types?
143
- end
144
-
136
+ # Get human-readable type
137
+ # @return [String]
145
138
  def human_type
146
139
  if DHCP_OPTIONS.key?(type)
147
140
  DHCP_OPTIONS[type].first.dup
@@ -150,6 +143,7 @@ module PacketGen
150
143
  end
151
144
  end
152
145
 
146
+ # @return [String]
153
147
  def to_human
154
148
  s = human_type
155
149
  if length > 0
@@ -78,6 +78,8 @@ module PacketGen
78
78
  # @return [Eth::MacAddr]
79
79
  define_field :link_addr, Eth::MacAddr
80
80
 
81
+ undef time, time=
82
+
81
83
  # @return [Time]
82
84
  def time
83
85
  BASE_TIME + self[:time].to_i
@@ -36,10 +36,12 @@ module PacketGen
36
36
  # @return [Hash]
37
37
  def subclasses
38
38
  return @klasses if defined? @klasses
39
+
39
40
  @klasses = []
40
41
  DHCPv6.constants.each do |cst|
41
42
  klass = DHCPv6.const_get(cst)
42
43
  next unless klass.is_a?(Class) && (klass < Option)
44
+
43
45
  @klasses[klass.new.type] = klass
44
46
  end
45
47
  @klasses
@@ -80,25 +82,6 @@ module PacketGen
80
82
  alias private_read read
81
83
  private :private_read
82
84
 
83
- # Populate object from binary string
84
- # @param [String] str
85
- # @return [Option]
86
- def read(str)
87
- if self.class == Option
88
- return self if str.nil?
89
- PacketGen.force_binary str
90
- type = Types::Int16.new.read(str).to_i
91
- klass = Option.subclasses[type]
92
- if klass
93
- klass.new.read(str)
94
- else
95
- private_read str
96
- end
97
- else
98
- private_read str
99
- end
100
- end
101
-
102
85
  # Get human-readable {#type}
103
86
  # @return [String]
104
87
  def human_type
@@ -23,6 +23,13 @@ module PacketGen
23
23
 
24
24
  # Separator used in {#to_human}.
25
25
  HUMAN_SEPARATOR = ';'
26
+
27
+ private
28
+
29
+ def real_type(opt)
30
+ real_klass = Option.subclasses[opt.type]
31
+ real_klass.nil? ? Option : real_klass
32
+ end
26
33
  end
27
34
  end
28
35
  end
@@ -97,12 +97,12 @@ module PacketGen
97
97
  end
98
98
  end
99
99
 
100
- require_relative 'dns/rrsection'
101
- require_relative 'dns/qdsection'
102
100
  require_relative 'dns/name'
103
101
  require_relative 'dns/question'
104
102
  require_relative 'dns/rr'
105
103
  require_relative 'dns/opt'
104
+ require_relative 'dns/rrsection'
105
+ require_relative 'dns/qdsection'
106
106
 
107
107
  module PacketGen
108
108
  module Header
@@ -184,27 +184,7 @@ module PacketGen
184
184
  define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z,
185
185
  :ad, :cd, :rcode, 4
186
186
 
187
- # Read DNS header and sections from a string
188
- # @param [String] str binary string
189
- # @return [self]
190
- def read(str)
191
- return self if str.nil?
192
- force_binary str
193
- self[:id].read str[0, 2]
194
- self[:u16].read str[2, 2]
195
- self[:qdcount].read str[4, 2]
196
- self[:ancount].read str[6, 2]
197
- self[:nscount].read str[8, 2]
198
- self[:arcount].read str[10, 2]
199
- self[:qd].read str[12..-1] if self.qdcount > 0
200
- start = 12 + self[:qd].sz
201
- self[:an].read str[start..-1] if self.ancount > 0
202
- start += self[:an].sz
203
- self[:ns].read str[start..-1] if self.nscount > 0
204
- start += self[:ns].sz
205
- self[:ar].read str[start..-1] if self.arcount > 0
206
- self
207
- end
187
+ undef opcode=, rcode=
208
188
 
209
189
  # Set opcode
210
190
  # @param [Integer,String] value
@@ -217,6 +197,7 @@ module PacketGen
217
197
  OPCODES[value.to_s]
218
198
  end
219
199
  raise ArgumentError, "unknown opcode #{value.inspect}" unless intg
200
+
220
201
  self.u16 &= 0x87ff
221
202
  self.u16 |= (intg & 0xf) << 11
222
203
  end
@@ -232,6 +213,7 @@ module PacketGen
232
213
  RCODES[value]
233
214
  end
234
215
  raise ArgumentError, "unknown rcode #{value.inspect}" unless intg
216
+
235
217
  self.u16 &= 0xfff0
236
218
  self.u16 |= intg & 0xf
237
219
  end
@@ -93,6 +93,7 @@ module PacketGen
93
93
 
94
94
  def pointer?(index)
95
95
  return false if index.nil?
96
+
96
97
  index & POINTER_MASK == POINTER_MASK
97
98
  end
98
99
 
@@ -30,6 +30,7 @@ module PacketGen
30
30
  def read(str)
31
31
  clear
32
32
  return self if str.nil?
33
+
33
34
  force_binary str
34
35
  while !str.empty? && (self.size < @counter.to_i)
35
36
  question = Question.new(@dns).read(str)
@@ -78,6 +78,8 @@ module PacketGen
78
78
  self.rrclass = options[:rrclass] if options[:rrclass]
79
79
  end
80
80
 
81
+ undef rrclass=
82
+
81
83
  # Setter for class
82
84
  # @param [Integer] val
83
85
  # @return [Integer,String]
@@ -89,6 +91,7 @@ module PacketGen
89
91
  val
90
92
  end
91
93
  raise ArgumentError, "unknown class #{val.inspect}" unless v
94
+
92
95
  self[:rrclass].read v
93
96
  end
94
97
 
@@ -100,13 +103,6 @@ module PacketGen
100
103
  self.class::TYPES[type] == self.type
101
104
  end
102
105
 
103
- # @deprecated Use {#type?} instead
104
- # @return [Boolean]
105
- def has_type?(type)
106
- Deprecation.deprecated(self.class, __method__, 'type?')
107
- type?(type)
108
- end
109
-
110
106
  # Get human readable type
111
107
  # @return [String]
112
108
  def human_type
@@ -36,9 +36,12 @@ module PacketGen
36
36
  def initialize(dns, options={})
37
37
  super
38
38
  return unless options[:rdata] && options[:rdlength].nil?
39
+
39
40
  self.rdata = options[:rdata]
40
41
  end
41
42
 
43
+ undef rdata=
44
+
42
45
  # Set rdata and rdlength from +data+
43
46
  # @param [String] data
44
47
  # @return [void]
@@ -25,6 +25,7 @@ module PacketGen
25
25
  def read(str)
26
26
  clear
27
27
  return self if str.nil?
28
+
28
29
  force_binary str
29
30
  while !str.empty? && (self.size < @counter.to_i)
30
31
  rr = RR.new(@dns).read(str)
@@ -68,8 +68,7 @@ module PacketGen
68
68
  # @param [String] iface interface name
69
69
  # @return [void]
70
70
  def to_w(iface)
71
- pcap = PCAPRUB::Pcap.open_live(iface, PCAP_SNAPLEN, PCAP_PROMISC,
72
- PCAP_TIMEOUT)
71
+ pcap = PCAPRUB::Pcap.open_live(iface, PCAP_SNAPLEN, PCAP_PROMISC, PCAP_TIMEOUT)
73
72
  pcap.inject self.to_s
74
73
  pcap.close
75
74
  end
@@ -219,21 +218,6 @@ module PacketGen
219
218
  # @return [Boolean]
220
219
  attr_accessor :fcs
221
220
  alias fcs? fcs
222
-
223
- # rubocop:disable Naming/PredicateName
224
-
225
- # @deprecated Use {.fcs?} instead.
226
- def has_fcs
227
- Deprecation.deprecated(self, __method__, 'fcs?', klass_method: true)
228
- fcs?
229
- end
230
-
231
- # @deprecated Use {.fcs=} instead.
232
- def has_fcs=(fcs)
233
- Deprecation.deprecated(self, __method__, 'fcs=', klass_method: true)
234
- self.fcs = fcs
235
- end
236
- # rubocop:enable Naming/PredicateName
237
221
  end
238
222
  Dot11.fcs = true
239
223
 
@@ -52,6 +52,7 @@ module PacketGen
52
52
  # @return [self]
53
53
  def read(str)
54
54
  return self if str.nil?
55
+
55
56
  self[:version].read(str[0, 1])
56
57
  self[:type].read(str[1, 1])
57
58
  self[:length].read(str[2, 2])
@@ -132,6 +132,7 @@ module PacketGen
132
132
  def read(str)
133
133
  super str
134
134
  return self unless self.class == EAP
135
+
135
136
  if type?
136
137
  obj = case self.type
137
138
  when 4
@@ -162,6 +163,7 @@ module PacketGen
162
163
  # @raise [ParseError] not a Request nor a Response packet
163
164
  def human_type
164
165
  raise ParseError, 'not a Request nor a Response' unless type?
166
+
165
167
  self[:type].to_human
166
168
  end
167
169
 
@@ -194,6 +196,7 @@ module PacketGen
194
196
  # @raise [ParseError] not a Nak packet
195
197
  def desired_auth_type
196
198
  raise ParseError, 'not a Nak response' if (code != 2) && (type != 3)
199
+
197
200
  body.to_s.unpack('C*')
198
201
  end
199
202
 
@@ -210,13 +213,6 @@ module PacketGen
210
213
  [1, 2].include?(self.code)
211
214
  end
212
215
 
213
- # @deprecated Use {#type?} instead.
214
- # @return [Boolean]
215
- def has_type?
216
- Deprecation.deprecated(self.class, __method__, 'type?')
217
- type?
218
- end
219
-
220
216
  # Callback called when a EAP header is added to a packet
221
217
  # Here, add +#eap+ method as a shortcut to existing
222
218
  # +#eap_(md5|tls|ttls|fast)+.
@@ -224,6 +220,7 @@ module PacketGen
224
220
  # @return [void]
225
221
  def added_to_packet(packet)
226
222
  return if packet.respond_to? :eap
223
+
227
224
  packet.instance_eval("def eap(arg=nil); header(#{self.class}, arg); end")
228
225
  end
229
226
 
@@ -57,8 +57,10 @@ module PacketGen
57
57
  # @return [self]
58
58
  def from_human(str)
59
59
  return self if str.nil?
60
+
60
61
  bytes = str.split(/:/)
61
62
  raise ArgumentError, 'not a MAC address' unless bytes.size == 6
63
+
62
64
  self[:a0].read(bytes[0].to_i(16))
63
65
  self[:a1].read(bytes[1].to_i(16))
64
66
  self[:a2].read(bytes[2].to_i(16))
@@ -29,6 +29,7 @@ module PacketGen
29
29
  when String
30
30
  @data = s_or_h.split("\n").map do |h|
31
31
  next unless h.include?(':')
32
+
32
33
  k, v = h.split(':', 2)
33
34
  [k, v.strip]
34
35
  end.reject(&:nil?).to_h
@@ -42,6 +43,7 @@ module PacketGen
42
43
  # @return [String]
43
44
  def to_s
44
45
  return "\r\n" if @data.nil? || @data.empty?
46
+
45
47
  d = []
46
48
  @data.map do |k, v|
47
49
  d << k + ': ' + v
@@ -66,6 +68,7 @@ module PacketGen
66
68
  # @return [Boolean]
67
69
  def given?
68
70
  return true unless @data.nil? || @data.empty?
71
+
69
72
  false
70
73
  end
71
74
  end
@@ -69,9 +69,9 @@ module PacketGen
69
69
  str = vrb + str.split(vrb)[-1]
70
70
  str = str.split("\n").map(&:chomp)
71
71
  first_line = str.shift.split
72
- self[:method] = first_line[0]
73
- self[:path] = first_line[1]
74
- self[:version] = first_line[2]
72
+ self[:method].read first_line[0]
73
+ self[:path].read first_line[1]
74
+ self[:version].read first_line[2]
75
75
  # requests can sometimes have a payload
76
76
  if (data_index = str.find_index(''))
77
77
  data = str[data_index + 1..-1].join("\n")
@@ -80,7 +80,7 @@ module PacketGen
80
80
  headers = str.join("\n")
81
81
  end
82
82
  self[:headers].read(headers)
83
- self[:body] = data
83
+ self[:body].read data
84
84
  self
85
85
  end
86
86
 
@@ -90,6 +90,7 @@ module PacketGen
90
90
  raise FormatError, 'Missing #method.' if self.method.empty?
91
91
  raise FormatError, 'Missing #path.' if self.path.empty?
92
92
  raise FormatError, 'Missing #version.' if self.version.empty?
93
+
93
94
  str = ''.dup # build 'dat string
94
95
  str << self[:method] << ' ' << self[:path] << ' ' << self[:version] << "\r\n" << self[:headers].to_s << self[:body]
95
96
  end
@@ -87,12 +87,12 @@ module PacketGen
87
87
  end
88
88
  unless headers.empty?
89
89
  first_line = headers.shift.split
90
- self[:version] = first_line[0]
91
- self[:status_code] = first_line[1]
92
- self[:status_mesg] = first_line[2..-1].join(' ')
90
+ self[:version].read first_line[0]
91
+ self[:status_code].read first_line[1]
92
+ self[:status_mesg].read first_line[2..-1].join(' ')
93
93
  self[:headers].read(headers.join("\n"))
94
94
  end
95
- self[:body] = data.join("\n")
95
+ self[:body].read data.join("\n")
96
96
  self
97
97
  end
98
98
 
@@ -102,6 +102,7 @@ module PacketGen
102
102
  raise FormatError, 'Missing #status_code.' if self.status_code.empty?
103
103
  raise FormatError, 'Missing #status_mesg.' if self.status_mesg.empty?
104
104
  raise FormatError, 'Missing #version.' if self.version.empty?
105
+
105
106
  str = ''.dup # build 'dat string
106
107
  str << self[:version] << ' ' << self[:status_code] << ' ' << self[:status_mesg] << "\r\n"
107
108
  str << self[:headers].to_s if self[:headers].given?
@@ -7,6 +7,12 @@
7
7
 
8
8
  module PacketGen
9
9
  module Header
10
+ # ICMP header ({https://tools.ietf.org/html/rfc792 RFC 792})
11
+ # 0 1 2 3
12
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
13
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14
+ # | Type | Code | Checksum |
15
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10
16
  # A ICMP header consists of:
11
17
  # * a {#type} field ({Types::Int8} type),
12
18
  # * a {#code} field ({Types::Int8} type),
@@ -7,6 +7,12 @@
7
7
 
8
8
  module PacketGen
9
9
  module Header
10
+ # ICMPv6 header ({https://tools.ietf.org/html/rfc4443 RFC 4443})
11
+ # 0 1 2 3
12
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
13
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14
+ # | Type | Code | Checksum |
15
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10
16
  # A ICMPv6 header consists of:
11
17
  # * a +type+ field ({Types::Int8} type),
12
18
  # * a +code+ field ({Types::Int8} type),