packetgen 4.0.0 → 4.1.1

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -9
  3. data/lib/packetgen/capture.rb +3 -6
  4. data/lib/packetgen/config.rb +1 -1
  5. data/lib/packetgen/deprecation.rb +7 -1
  6. data/lib/packetgen/header/arp.rb +7 -8
  7. data/lib/packetgen/header/asn1_base.rb +3 -2
  8. data/lib/packetgen/header/base.rb +39 -27
  9. data/lib/packetgen/header/bootp.rb +15 -15
  10. data/lib/packetgen/header/dhcp/option.rb +9 -9
  11. data/lib/packetgen/header/dhcp/options.rb +3 -3
  12. data/lib/packetgen/header/dhcp.rb +7 -8
  13. data/lib/packetgen/header/dhcpv6/duid.rb +3 -5
  14. data/lib/packetgen/header/dhcpv6/option.rb +38 -16
  15. data/lib/packetgen/header/dhcpv6/options.rb +4 -4
  16. data/lib/packetgen/header/dhcpv6/relay.rb +2 -1
  17. data/lib/packetgen/header/dhcpv6.rb +14 -15
  18. data/lib/packetgen/header/dns/name.rb +10 -9
  19. data/lib/packetgen/header/dns/opt.rb +4 -1
  20. data/lib/packetgen/header/dns/option.rb +8 -8
  21. data/lib/packetgen/header/dns/qdsection.rb +3 -3
  22. data/lib/packetgen/header/dns/question.rb +2 -1
  23. data/lib/packetgen/header/dns/rr.rb +2 -4
  24. data/lib/packetgen/header/dns/rrsection.rb +3 -3
  25. data/lib/packetgen/header/dns.rb +77 -61
  26. data/lib/packetgen/header/dot11/control.rb +6 -6
  27. data/lib/packetgen/header/dot11/data.rb +12 -11
  28. data/lib/packetgen/header/dot11/element.rb +2 -2
  29. data/lib/packetgen/header/dot11/management.rb +19 -16
  30. data/lib/packetgen/header/dot11/sub_mngt.rb +23 -22
  31. data/lib/packetgen/header/dot11.rb +39 -39
  32. data/lib/packetgen/header/dot1q.rb +6 -5
  33. data/lib/packetgen/header/dot1x.rb +9 -9
  34. data/lib/packetgen/header/eap/fast.rb +4 -4
  35. data/lib/packetgen/header/eap/md5.rb +12 -4
  36. data/lib/packetgen/header/eap/tls.rb +10 -9
  37. data/lib/packetgen/header/eap/ttls.rb +14 -11
  38. data/lib/packetgen/header/eap.rb +59 -34
  39. data/lib/packetgen/header/eth.rb +27 -13
  40. data/lib/packetgen/header/gre.rb +27 -3
  41. data/lib/packetgen/header/http/headers.rb +7 -6
  42. data/lib/packetgen/header/http/request.rb +25 -17
  43. data/lib/packetgen/header/http/response.rb +23 -16
  44. data/lib/packetgen/header/http/verbs.rb +1 -1
  45. data/lib/packetgen/header/http.rb +1 -1
  46. data/lib/packetgen/header/icmp.rb +11 -11
  47. data/lib/packetgen/header/icmpv6.rb +11 -10
  48. data/lib/packetgen/header/igmp.rb +22 -11
  49. data/lib/packetgen/header/igmpv3/group_record.rb +8 -3
  50. data/lib/packetgen/header/igmpv3/mq.rb +2 -2
  51. data/lib/packetgen/header/igmpv3/mr.rb +2 -2
  52. data/lib/packetgen/header/igmpv3.rb +12 -11
  53. data/lib/packetgen/header/ip/addr.rb +7 -3
  54. data/lib/packetgen/header/ip/option.rb +19 -6
  55. data/lib/packetgen/header/ip/options.rb +1 -1
  56. data/lib/packetgen/header/ip.rb +53 -36
  57. data/lib/packetgen/header/ipv6/addr.rb +15 -14
  58. data/lib/packetgen/header/ipv6/extension.rb +10 -8
  59. data/lib/packetgen/header/ipv6/hop_by_hop.rb +27 -8
  60. data/lib/packetgen/header/ipv6.rb +32 -23
  61. data/lib/packetgen/header/llc.rb +21 -14
  62. data/lib/packetgen/header/mdns.rb +10 -3
  63. data/lib/packetgen/header/mld.rb +12 -10
  64. data/lib/packetgen/header/mldv2/mcast_address_record.rb +7 -2
  65. data/lib/packetgen/header/mldv2/mlq.rb +9 -9
  66. data/lib/packetgen/header/mldv2/mlr.rb +5 -5
  67. data/lib/packetgen/header/mldv2.rb +2 -2
  68. data/lib/packetgen/header/ospfv2/db_description.rb +11 -11
  69. data/lib/packetgen/header/ospfv2/hello.rb +12 -11
  70. data/lib/packetgen/header/ospfv2/ls_ack.rb +6 -7
  71. data/lib/packetgen/header/ospfv2/ls_request.rb +8 -7
  72. data/lib/packetgen/header/ospfv2/ls_update.rb +8 -8
  73. data/lib/packetgen/header/ospfv2/lsa.rb +34 -11
  74. data/lib/packetgen/header/ospfv2/lsa_header.rb +4 -3
  75. data/lib/packetgen/header/ospfv2.rb +32 -27
  76. data/lib/packetgen/header/ospfv3/db_description.rb +13 -14
  77. data/lib/packetgen/header/ospfv3/hello.rb +11 -10
  78. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +7 -3
  79. data/lib/packetgen/header/ospfv3/ls_ack.rb +6 -7
  80. data/lib/packetgen/header/ospfv3/ls_request.rb +11 -11
  81. data/lib/packetgen/header/ospfv3/ls_update.rb +8 -8
  82. data/lib/packetgen/header/ospfv3/lsa.rb +24 -10
  83. data/lib/packetgen/header/ospfv3/lsa_header.rb +4 -3
  84. data/lib/packetgen/header/ospfv3.rb +39 -35
  85. data/lib/packetgen/header/sctp/chunk.rb +39 -18
  86. data/lib/packetgen/header/sctp/error.rb +170 -198
  87. data/lib/packetgen/header/sctp/padded32.rb +4 -4
  88. data/lib/packetgen/header/sctp/parameter.rb +86 -133
  89. data/lib/packetgen/header/sctp.rb +15 -4
  90. data/lib/packetgen/header/snmp.rb +111 -10
  91. data/lib/packetgen/header/tcp/option.rb +8 -1
  92. data/lib/packetgen/header/tcp/options.rb +12 -4
  93. data/lib/packetgen/header/tcp.rb +34 -27
  94. data/lib/packetgen/header/tftp.rb +17 -11
  95. data/lib/packetgen/header/udp.rb +16 -14
  96. data/lib/packetgen/header.rb +20 -14
  97. data/lib/packetgen/headerable.rb +10 -4
  98. data/lib/packetgen/inject.rb +1 -1
  99. data/lib/packetgen/inspect.rb +3 -8
  100. data/lib/packetgen/packet.rb +95 -37
  101. data/lib/packetgen/pcap.rb +1 -1
  102. data/lib/packetgen/pcapng/block.rb +3 -2
  103. data/lib/packetgen/pcapng/epb.rb +1 -1
  104. data/lib/packetgen/pcapng/file.rb +42 -15
  105. data/lib/packetgen/pcapng/idb.rb +3 -2
  106. data/lib/packetgen/pcapng/shb.rb +3 -2
  107. data/lib/packetgen/pcapng/spb.rb +2 -2
  108. data/lib/packetgen/pcapng/unknown_block.rb +1 -1
  109. data/lib/packetgen/pcapng.rb +3 -1
  110. data/lib/packetgen/pcaprub_wrapper.rb +1 -1
  111. data/lib/packetgen/proto.rb +5 -1
  112. data/lib/packetgen/unknown_packet.rb +4 -4
  113. data/lib/packetgen/utils/arp_spoofer.rb +1 -1
  114. data/lib/packetgen/utils.rb +4 -5
  115. data/lib/packetgen/version.rb +2 -2
  116. data/lib/packetgen.rb +9 -3
  117. metadata +8 -9
@@ -2,55 +2,63 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # This file is part of PacketGen
5
- # See https://github.com/lemontree55/packetgen for more informations
5
+ # See https://codeberg.org/lemontree55/packetgen for more informations
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
8
8
  # This program is published under MIT license.
9
9
 
10
- # rubocop:disable Metrics/ClassLength
11
-
12
10
  module PacketGen
13
11
  # An object of type {Packet} handles a network packet. This packet may contain
14
12
  # multiple protocol headers, starting from MAC layer or from Network (OSI) layer.
15
13
  #
16
- # Creating a packet is fairly simple:
17
- # Packet.gen 'IP', src: '192.168.1.1', dst: '192.168.1.2'
14
+ # A Packet is created using {.gen} method. Headers may be added to this packet using {#add}.
15
+ # It may also be created from parsing a binary string, using {.parse} method.
16
+ #
17
+ # @example Very simple packet
18
+ # # Create a packet with a single IP header. IP source and destination addresses are set.
19
+ # pkt = PacketGen::Packet.gen('IP', src: '192.168.1.1', dst: '192.168.1.2')
18
20
  #
19
- # == Create a packet
20
- # Packets may be hand-made or parsed from a binary string:
21
- # Packet.gen('IP', src: '192.168.1.1', dst: '192.168.1.2').add('UDP', sport: 45000, dport: 23)
22
- # Packet.parse(binary_string)
21
+ # @example Parsing a binary string
22
+ # # a IP/ICMP packet, as binary string
23
+ # binary_string = "E\x00\x00\x1C\xAA`\x00\x00@\x01M-\xC0\xA8\x01\x01\xC0\xA8\x01\x02\x00\b;1abcd".b
24
+ # pkt = PacketGen::Packet.parse(binary_string)
25
+ # pkt.is?('IP') #=> true
26
+ # pkt.is?('ICMP') #=> true
23
27
  #
24
- # == Access packet information
25
- # pkt = Packet.gen('IP').add('UDP')
26
- # # read information
27
- # pkt.udp.sport
28
- # pkt.ip.ttl
29
- # # set information
30
- # pkt.udp.dport = 2323
31
- # pkt.ip.ttl = 1
32
- # pkt.ip(ttl: 1, id: 1234)
28
+ # Information for each level is accessible through the associated header. Header is accessible through a
29
+ # method defined with its name at packet level (i.e. +#ip+ for a IP header).
33
30
  #
34
- # == Save a packet to a file
35
- # pkt.write('file.pcapng')
31
+ # @example Accessing header information
32
+ # pkt = PacketGen::Packet.gen('IP').add('UDP')
33
+ # # read information
34
+ # pkt.udp.sport #=> 0
35
+ # pkt.ip.ttl #=> 64
36
+ # # set information
37
+ # pkt.udp.dport = 2323
38
+ # pkt.ip.ttl = 1
39
+ # # Set multiple attributes at once
40
+ # pkt.ip(ttl: 1, id: 1234)
36
41
  #
37
- # == Get packets
38
- # Packets may be captured from wire:
39
- # Packet.capture do |packet|
40
- # do_some_stuffs
41
- # end
42
- # packets = Packet.capture(iface: 'eth0', max: 5) # get 5 packets from eth0
42
+ # Packets may be written to files using {#write}:
43
+ # pkt = PacketGen::Packet.gen('Eth')
44
+ # pkt.write('file.pcapng')
43
45
  #
44
- # Packets may also be read from a file:
45
- # packets = Packet.read(file.pcapng)
46
+ # Packets may be captured from network interfaces:
47
+ # # Capture all packets from default interface. Never end.
48
+ # PacketGen::Packet.capture do |packet|
49
+ # do_some_stuffs
50
+ # end
46
51
  #
47
- # == Save packets to a file
48
- # Packet.write 'file.pcapng', packets
52
+ # # Get 5 packets from eth0 interface
53
+ # packets = Packet.capture(iface: 'eth0', max: 5)
49
54
  #
55
+ # Finally, packets may also be read from a file:
56
+ # packets = Packet.read(file.pcapng)
50
57
  # @author Sylvain Daubert
58
+ # @author LemonTree55
51
59
  class Packet
52
60
  # Get packet headers, ordered as they appear in the packet.
53
- # @return [Array<Header::Base>]
61
+ # @return [Array<Headerable>]
54
62
  attr_reader :headers
55
63
  # Activaye or deactivate header cache (activated by default)
56
64
  # @return [Boolean]
@@ -142,7 +150,15 @@ module PacketGen
142
150
  # @param [String] protocol
143
151
  # @param [Hash] options protocol specific options
144
152
  # @return [self]
145
- # @raise [BindingError] unknown protocol
153
+ # @raise [ArgumentError] unknown protocol
154
+ # @raise [BindingError] unknown binding
155
+ # @see #<<
156
+ # @example
157
+ # pkt = PacketGen::Packet.gen('Eth')
158
+ # # Add a IP header
159
+ # pkt.add('IP')
160
+ # # Add a TCP header, with some attributes and body set
161
+ # pkt.add('TCP', dport: 80, seqnum: 123456, body: "abcd".b)
146
162
  def add(protocol, options={})
147
163
  klass = check_protocol(protocol)
148
164
 
@@ -174,6 +190,7 @@ module PacketGen
174
190
  end
175
191
 
176
192
  # Check if a protocol header is embedded in packet.
193
+ # @example
177
194
  # pkt = PacketGen.gen('IP').add('UDP')
178
195
  # pkt.is?('IP') #=> true
179
196
  # pkt.is?('TCP') #=> false
@@ -210,16 +227,22 @@ module PacketGen
210
227
  end
211
228
  end
212
229
 
213
- # Get packet body
214
- # @return [Types]
230
+ # Get packet body. If packet (i.e. last header) has no +:body+ field, return +nil+.
231
+ # @return [Headerable,BinStruct::String,nil]
215
232
  def body
216
233
  last_header[:body] if last_header.respond_to?(:body)
217
234
  end
218
235
 
219
236
  # Set packet body
220
- # @param [String] str
237
+ # @param [String] str Binary string
221
238
  # @return [void]
239
+ # @raise [Error] Packet (i.e. last header) has no +:body+ field.
240
+ # @note To set a {Headerable} object, prefer #{<<}
241
+ # @see #<<
242
+ # @since 4.1.0 raise {Error} if no body on packet
222
243
  def body=(str)
244
+ raise Error, 'no body in last headeré' unless last_header.respond_to?(:body)
245
+
223
246
  last_header.body = str
224
247
  end
225
248
 
@@ -270,6 +293,13 @@ module PacketGen
270
293
  # @return [self] +self+ updated with new headers from +other+
271
294
  # @raise [BindingError] do not known how to encapsulate
272
295
  # @since 1.1.0
296
+ # @example
297
+ # # Create a first IP packet
298
+ # ip1 = PacketGen::Packet.gen('IP', id: 1)
299
+ # # Create second IP packet, to encapsulate in first
300
+ # ip2 = PacketGen.gen('IP', id: 2)
301
+ # ip1.encapsulate(ip2)
302
+ # ip1.ip(2) == ip2.ip
273
303
  def encapsulate(other, parsing: false)
274
304
  other.headers.each_with_index do |h, i|
275
305
  add_header(h, parsing: i.positive? || parsing)
@@ -282,6 +312,12 @@ module PacketGen
282
312
  # @raise [FormatError] any headers not in +self+
283
313
  # @raise [BindingError] removed headers result in an unknown binding
284
314
  # @since 1.1.0
315
+ # @example
316
+ # # IP/IP encapsulation
317
+ # pkt = PacketGen::Packet.gen('IP', id: 1).add('IP', id:2)
318
+ # # Remove outer IP header
319
+ # pkt.decapsulate(pkt.ip(1))
320
+ # pkt.ip.id #=> 2
285
321
  def decapsulate(*hdrs)
286
322
  hdrs.each do |hdr|
287
323
  prev_hdr = previous_header(hdr)
@@ -290,6 +326,7 @@ module PacketGen
290
326
  add_header(next_hdr, previous_header: prev_hdr) if prev_hdr && next_hdr
291
327
  end
292
328
  invalidate_header_cache
329
+ self
293
330
  rescue ArgumentError => e
294
331
  raise FormatError, e.message
295
332
  end
@@ -334,7 +371,7 @@ module PacketGen
334
371
  to_s == other.to_s
335
372
  end
336
373
 
337
- # +true+ is {#==} is +true+ with another packet, or if +other+ is a protocol name String, whose protocol is in Packet.
374
+ # +true+ if {#==} is +true+ with another packet, or if +other+ is a protocol name String, whose protocol is in Packet.
338
375
  # @param [Packet] other
339
376
  # @return [Boolean]
340
377
  # @since 3.1.2
@@ -349,8 +386,9 @@ module PacketGen
349
386
  end
350
387
  end
351
388
 
352
- # Invert all possible attributes.in packet to create a reply.
389
+ # Invert all possible attributes in packet to create a reply.
353
390
  # @return [self]
391
+ # @note Only modify headers responding to +#reply!+.
354
392
  # @since 2.7.0
355
393
  def reply!
356
394
  headers.each do |header|
@@ -362,12 +400,32 @@ module PacketGen
362
400
  # Forge a new packet from current one with all possible fields
363
401
  # inverted. The new packet may be a reply to current one.
364
402
  # @return [Packet]
403
+ # @note Only modify headers responding to +#reply!+.
365
404
  # @since 2.7.0
366
405
  def reply
367
406
  pkt = dup
368
407
  pkt.reply!
369
408
  end
370
409
 
410
+ # Append an already defined header to packet
411
+ # @param [Headerable] header
412
+ # @return [self]
413
+ # @raise [ArgumentError] unknown protocol
414
+ # @raise [BindingError] unknown binding
415
+ # @example
416
+ # pkt = PacketGen.gen('Eth')
417
+ # # Add a new header from its type
418
+ # pkt.add('IP')
419
+ # # Add a new pre-generated header
420
+ # pkt << PacketGen::Header::TCP.new
421
+ # @see #add
422
+ # @since 4.1.0
423
+ # @author LemonTree55
424
+ def <<(header)
425
+ add_header(header)
426
+ self
427
+ end
428
+
371
429
  private
372
430
 
373
431
  # Dup +@headers+ instance variable. Internally used by +#dup+ and +#clone+
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -10,6 +10,7 @@ module PacketGen
10
10
  module PcapNG
11
11
  # @abstract Base class for all block types
12
12
  # @author Sylvain Daubert
13
+ # @author LemonTree55
13
14
  class Block < BinStruct::Struct
14
15
  # @return [:little, :big]
15
16
  attr_accessor :endian
@@ -78,7 +79,7 @@ module PacketGen
78
79
  def to_io(str_or_io)
79
80
  return str_or_io if str_or_io.respond_to?(:read)
80
81
 
81
- StringIO.new(force_binary(str_or_io.to_s))
82
+ StringIO.new(str_or_io.to_s.b)
82
83
  end
83
84
 
84
85
  def remove_padding(io, data_len)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -1,16 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
8
8
 
9
9
  module PacketGen
10
10
  module PcapNG
11
- # PcapNG::File is a complete Pcap-NG file handler.
11
+ # PcapNG::File is a complete Pcap-NG file handler. It provides methods to:
12
+ # * read and write PcapNG files,
13
+ # * process packets from such files.
14
+ #
15
+ # @example Writing a file
16
+ # pkt1 = PacketGen.gen('IP', id: 1).add('TCP')
17
+ # pkt2 = PacketGen.gen('IP', id: 2).add('UDP')
18
+ # file = PacketGen::PcapNG::File.new
19
+ # file.read_array([pkt1, pkt2])
20
+ # file.write('/tmp/file.pcapng')
21
+ #
22
+ # @example Reading a file
23
+ # file = PacketGen::PcapNG::File.new
24
+ # pkts = file.read_packets('/tmp/file.pcapng')
25
+ #
12
26
  # @author Sylvain Daubert
13
- class File # rubocop:disable Metrics/ClassLength
27
+ # @author LemonTree55
28
+ class File
14
29
  # Known link types
15
30
  KNOWN_LINK_TYPES = {
16
31
  LINKTYPE_ETHERNET => 'Eth',
@@ -29,19 +44,19 @@ module PacketGen
29
44
  end.freeze
30
45
 
31
46
  # Get file sections
32
- # @return [Array]
47
+ # @return [Array<SHB>]
33
48
  attr_accessor :sections
34
49
 
35
50
  def initialize
36
51
  @sections = []
37
52
  end
38
53
 
39
- # Read a string to populate the object. Note that this appends new blocks to
54
+ # Read a binary string to populate the object. Note that this appends new blocks to
40
55
  # the Pcapng::File object.
41
56
  # @param [String] str
42
57
  # @return [self]
43
58
  def read(str)
44
- PacketGen.force_binary(str)
59
+ str = str.b unless str.encoding == Encoding::BINARY
45
60
  io = StringIO.new(str)
46
61
  parse_section(io)
47
62
  self
@@ -59,11 +74,19 @@ module PacketGen
59
74
 
60
75
  # Read a given file and analyze it.
61
76
  # If given a block, it will yield PcapNG::EPB or PcapNG::SPB objects.
62
- # This is the only way to get packet timestamps.
77
+ # This is the only way to get packet timestamps (via {EPB#timestamp}).
63
78
  # @param [String] fname pcapng file name
64
79
  # @yieldparam [EPB,SPB] block
65
80
  # @return [Integer] return number of yielded blocks (only if a block is given)
66
81
  # @raise [ArgumentError] cannot read +fname+
82
+ # @example Parse packets and get their timestamp
83
+ # hsh = {}
84
+ # file = PacketGen::PcapNG::File.new
85
+ # file.readfile('/tmp/file.pcapng') do |xpb|
86
+ # ts = xpb.is_a?(PacketGen::PcapNG::EPB) ? xpb.timestamp : nil
87
+ # pkt = PacketGen.parse(xpb.data)
88
+ # hsh[pkt] = ts
89
+ # end
67
90
  def readfile(fname, &blk)
68
91
  raise ArgumentError, "cannot read file #{fname}" unless ::File.readable?(fname)
69
92
 
@@ -168,13 +191,15 @@ module PacketGen
168
191
  end
169
192
 
170
193
  # Writes the {File} to a file.
171
- # @param [Hash] options
172
- # @option options [Boolean] :append (default: +false+) if set to +true+,
194
+ # @param [String] filename file name to write
195
+ # @param [Boolean] append if set to +true+,
173
196
  # the packets are appended to the file, rather than overwriting it
174
- # @return [Array] array of 2 elements: filename and size written
175
- # @todo for 4.0, replace +options+ by +append+ kwarg
176
- def to_file(filename, options={})
177
- mode = options[:append] && ::File.exist?(filename) ? 'ab' : 'wb'
197
+ # @return [Array(String, Integer)] array of 2 elements: filename and size written
198
+ # @since 4.1.0 Options hash with single +:append+ option is replaced by +append+ keyword argument.
199
+ # @see #append
200
+ # @see #write
201
+ def to_file(filename, append: false)
202
+ mode = append && ::File.exist?(filename) ? 'ab' : 'wb'
178
203
  ::File.open(filename, mode) { |f| f.write(self.to_s) }
179
204
  [filename, self.to_s.size]
180
205
  end
@@ -182,14 +207,16 @@ module PacketGen
182
207
 
183
208
  # Shorthand method for writing to a file.
184
209
  # @param [#to_s] filename
185
- # @return [Array] see return value from {#to_file}
210
+ # @return [Array(String, Integer)]
211
+ # @see #to_file
186
212
  def write(filename='out.pcapng')
187
213
  self.to_file(filename.to_s, append: false)
188
214
  end
189
215
 
190
216
  # Shorthand method for appending to a file.
191
217
  # @param [#to_s] filename
192
- # @return [Array] see return value from {#to_file}
218
+ # @return [Array(String, Integer)]
219
+ # @see #to_file
193
220
  def append(filename='out.pcapng')
194
221
  self.to_file(filename.to_s, append: true)
195
222
  end
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
8
8
 
9
9
  module PacketGen
10
10
  module PcapNG
11
- # {IDB} represents a Interface Description Block (IDB) of a pcapng file.
11
+ # {IDB} represents an Interface Description Block (IDB) of a pcapng file. It is associated to a network interfaces.
12
+ # It contains packet data as {EPB} and/or {SPB}.
12
13
  #
13
14
  # == IDB Definition
14
15
  # Int32 :type Default: 0x00000001
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
8
8
 
9
9
  module PacketGen
10
10
  module PcapNG
11
- # {SHB} represents a Section Header Block (SHB) of a pcapng file.
11
+ # {SHB} represents a Section Header Block (SHB) of a pcapng file. A SHB contains {IDB}, which contain
12
+ # {EPB} and/or {SPB}.
12
13
  #
13
14
  # == SHB Definition
14
15
  # Int32 :type Default: 0x0A0D0D0A
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
8
8
 
9
9
  module PacketGen
10
10
  module PcapNG
11
- # {SPB} represents a Section Simple Packet Block (SPB) of a pcapng file.
11
+ # {SPB} represents a Simple Packet Block (SPB) of a pcapng file.
12
12
  #
13
13
  # == Pcapng::SPB Definition
14
14
  # Int32 :type Default: 0x00000003
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -11,6 +11,8 @@ require 'stringio'
11
11
  module PacketGen
12
12
  # Module to handle PCAP-NG file format.
13
13
  # See http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii
14
+ #
15
+ # See {PcapNG::File} to handle Pcap-NG files.
14
16
  # @author Sylvain Daubert
15
17
  module PcapNG
16
18
  # Section Header Block type number
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # This file is part of PacketGen
5
- # See https://github.com/lemontree55/packetgen for more informations
5
+ # See https://codeberg.org/lemontree55/packetgen for more informations
6
6
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
7
7
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
8
8
  # This program is published under MIT license.
@@ -30,6 +30,8 @@ module PacketGen
30
30
  # Get protocol number from its name
31
31
  # @param [String] name
32
32
  # @return [Integer,nil] return nil for unknown protocol names
33
+ # @example
34
+ # PacketGen::Proto.getprotobyname('tcp') #=> 6
33
35
  def self.getprotobyname(name)
34
36
  @cache[name]
35
37
  end
@@ -37,6 +39,8 @@ module PacketGen
37
39
  # Get protocol name from its number
38
40
  # @param [Integer] num
39
41
  # @return [String,nil] return nil for unknown protocol numbers
42
+ # @example
43
+ # PacketGen::Proto.getprotobynumber(6) #=> 'tcp'
40
44
  def self.getprotobynumber(num)
41
45
  @cache.key(num)
42
46
  end
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # This file is part of PacketGen
5
- # See https://github.com/lemontree55/packetgen for more informations
5
+ # See https://codeberg.org/lemontree55/packetgen for more informations
6
6
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
7
7
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
8
8
  # This program is published under MIT license.
@@ -20,7 +20,7 @@ module PacketGen
20
20
 
21
21
  def initialize
22
22
  @headers = [].freeze
23
- @binary_str = PacketGen.force_binary('')
23
+ @binary_str = ::String.new # Return empty string with encoding ASCII-8BIT, so BINARY
24
24
  end
25
25
 
26
26
  # Unknown packet, so unknown protocol.
@@ -40,7 +40,7 @@ module PacketGen
40
40
  # @param [String] str
41
41
  # @return [void]
42
42
  def body=(str)
43
- @binary_str = PacketGen.force_binary(str)
43
+ @binary_str = str.b
44
44
  end
45
45
 
46
46
  # Write packet to a PCapNG file on disk.
@@ -56,7 +56,7 @@ module PacketGen
56
56
  # @param [String] binary_str
57
57
  # @return [self]
58
58
  def parse(binary_str, _first_header: nil)
59
- @binary_str = PacketGen.force_binary(binary_str)
59
+ @binary_str = binary_str.b
60
60
  self
61
61
  end
62
62
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -71,9 +71,7 @@ module PacketGen
71
71
  cache
72
72
  end
73
73
 
74
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
75
-
76
- # Get MAC address from an IP address, or nil if this IP address is unknown
74
+ # Get MAC address from an IP address, or nil if this IP address is unknown
77
75
  # on local network.
78
76
  # @param [String] ipaddr dotted-octet IP address
79
77
  # @param [Hash] options
@@ -168,7 +166,8 @@ module PacketGen
168
166
  def self.mitm(target1, target2, options={}, &block)
169
167
  options = { iface: PacketGen.default_iface }.merge(options)
170
168
 
171
- spoofer = Utils::ARPSpoofer.new(options)
169
+ spoofer_options = options.slice(:timeout, :interval, :iface)
170
+ spoofer = Utils::ARPSpoofer.new(**spoofer_options.compact)
172
171
  spoofer.add target1, target2, options
173
172
  spoofer.add target2, target1, options
174
173
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is part of PacketGen
4
- # See https://github.com/lemontree55/packetgen for more informations
4
+ # See https://codeberg.org/lemontree55/packetgen for more informations
5
5
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
6
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
7
  # This program is published under MIT license.
@@ -11,5 +11,5 @@
11
11
  # @author Sylvain Daubert
12
12
  module PacketGen
13
13
  # PacketGen version
14
- VERSION = '4.0.0'
14
+ VERSION = '4.1.1'
15
15
  end
data/lib/packetgen.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # This file is part of PacketGen
5
- # See https://github.com/lemontree55/packetgen for more informations
5
+ # See https://codeberg.org/lemontree55/packetgen for more informations
6
6
  # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
7
7
  # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
8
8
  # This program is published under MIT license.
@@ -13,6 +13,7 @@ require 'interfacez'
13
13
 
14
14
  # PacketGen is a network packet generator and analyzor.
15
15
  # @author Sylvain Daubert
16
+ # @author LemonTree
16
17
  module PacketGen
17
18
  # Base exception class for PacketGen exceptions
18
19
  class Error < StandardError; end
@@ -33,12 +34,15 @@ module PacketGen
33
34
  # @return [Headerable]
34
35
  attr_reader :hdr
35
36
 
37
+ # @param [Headerable] prev_hdr
38
+ # @param [Headerable] hdr
36
39
  def initialize(prev_hdr, hdr)
37
40
  super()
38
41
  @prev_hdr = prev_hdr
39
42
  @hdr = hdr
40
43
  end
41
44
 
45
+ # @return [String]
42
46
  def message
43
47
  "#{prev_hdr.class} knowns no layer association with #{hdr.protocol_name}. " \
44
48
  "Try #{prev_hdr.class}.bind_layer(#{hdr.class}, " \
@@ -92,8 +96,10 @@ module PacketGen
92
96
  # Force binary encoding for +str+
93
97
  # @param [String] str
94
98
  # @return [String] binary encoded string
99
+ # @deprecated Use +String#b+ instead.
95
100
  def self.force_binary(str)
96
- str.dup.force_encoding(Encoding::BINARY)
101
+ Deprecation.deprecated(self, :force_binary, 'String#b')
102
+ str.b
97
103
  end
98
104
 
99
105
  # Get default network interface (ie. first non-loopback declared interface)
@@ -120,7 +126,7 @@ module PacketGen
120
126
  # Shortcut to get a header class
121
127
  # @example builtin class
122
128
  # # same as PacketGen::Header::Dot11:Data.new(id: 0xfedc)
123
- # dot11 = PacketGen.header('Dot11::Data', id: 0xfedc) #=> PacketGen::Header::Dot11:Data
129
+ # dot11 = PacketGen.header('Dot11::Data', id: 0xfedc)
124
130
  # @example plugin class
125
131
  # require 'packet-plugin-smb'
126
132
  # # same as PacketGen::Plugin::SMB::CloseRequest.new(fid: 0x1234)