packetgen 1.4.0 → 1.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67bab87e209f3ad1ca3adecf77be2b19c1ba17a5
4
- data.tar.gz: c5bd835c57160261677a22693e297c8b27ac3cbe
3
+ metadata.gz: ba692327da7837d4de41a002ca756a778692c74b
4
+ data.tar.gz: 38fca26934167acbd7d92981f160071c7fd1387f
5
5
  SHA512:
6
- metadata.gz: 466fadd588084aedad8c7e9fbc7ac6313f8f66d47594171fc7728c2056369ffc2e24fedb4794f4a37cd8fcc66ed4dff7db5339e1f19fefc3522d4906a8667953
7
- data.tar.gz: c8bd3cb05a61ae939f152355d45fed6ff0e26b6760dd0bea98fddff4aa86263ec1eea27b24024325ae089246cb78baad3958b9df7a949771150d65c45cba7073
6
+ metadata.gz: 80d8155ad93876fcb14c5d1d85b3a374a1eb865784b914aed802dbb0ab07e97364d10e5affc2a094f4041f695774a41dd60a65e8da2fbdd92e27ca873ad60ddd
7
+ data.tar.gz: ac325e1dae38151f1f73ca05b6604a7373060aaee4a814e9d87c98b4de4e8e8aa64ba11f39930693d9cc8f9e4abb028918237d37e99f5a1becabdf93227effe9
data/.travis.yml CHANGED
@@ -12,7 +12,7 @@ install:
12
12
  - bundler install --path vendor/bundle --jobs=3 --retry=3
13
13
  before_script:
14
14
  - openssl version
15
- - gem list openssl
15
+ - ruby -ropenssl -e 'puts OpenSSL::VERSION'
16
16
  script:
17
17
  - bundler exec rake
18
18
  - rvmsudo bundle exec rake spec:sudo
data/README.md CHANGED
@@ -131,6 +131,21 @@ pkt = Packet.gen('IP').add('MyHeader', field1: 0x12345678)
131
131
  pkt.myheader.field2.read 0x01
132
132
  ```
133
133
 
134
+ ## Interactive console
135
+ PacketGen provides an interactive console, based on `pry`: `pgconsole`.
136
+
137
+ In this console, context includes PacketGen module to give direct access to PacketGen
138
+ classes. A special `config` object gives local network configuration:
139
+
140
+ $ pgconsole
141
+ pg(main)> config
142
+ => #<PacketGen::Config:0x00559f27d2afe8
143
+ @hwaddr="75:74:73:72:71:70",
144
+ @iface="eth0",
145
+ @ipaddr="192.168.0.2">
146
+ pg(main)> packets = capture(max: 5)
147
+ pg(main)> exit
148
+
134
149
  ## Pull requests?
135
150
 
136
151
  yes
data/bin/pgconsole ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'packetgen'
5
+ require 'packetgen/config'
6
+ require 'pry'
7
+
8
+ include PacketGen
9
+
10
+ def parse(binary_str, first_header: nil)
11
+ Packet.parse binary_str, first_header: first_header
12
+ end
13
+
14
+ def capture(options={})
15
+ Packet.capture(options) { |packet| yield packet if block_given? }
16
+ end
17
+
18
+ def read(filename)
19
+ Packet.read filename
20
+ end
21
+
22
+ def write(filename, packets)
23
+ Packet.write filename, packets
24
+ end
25
+
26
+ @config = Config.new
27
+
28
+ def config
29
+ @config
30
+ end
31
+
32
+ Pry.config.prompt = [
33
+ proc { |target_self, nest_level, pry|
34
+ "#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}> "
35
+ },
36
+ proc { |target_self, nest_level, pry|
37
+ "#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}* "
38
+ }
39
+ ]
40
+ Pry.config.prompt_name = 'pg'
41
+ Pry.start
@@ -7,46 +7,83 @@ module PacketGen
7
7
 
8
8
  # Capture packets from wire
9
9
  # @author Sylvain Daubert
10
+ # @author Kent 'picat' Gruber
10
11
  class Capture
11
12
 
12
- # Default snaplen to use if :snaplen option not defined
13
+ # Default snaplen to use if :snaplen option not defined.
13
14
  DEFAULT_SNAPLEN = 0xffff
14
15
 
15
- # Get captured packets
16
+ # Get captured packets.
16
17
  # @return [Array<Packets>]
17
18
  attr_reader :packets
18
19
 
19
- # Get captured packet raw data
20
+ # Get captured packet raw data.
20
21
  # @return [Array<String>]
21
22
  attr_reader :raw_packets
22
23
 
23
- # @param [String] iface interface on which capture packets
24
- # @param [Hash] options
25
- # @option options [Integer] :max maximum number of packets to capture
26
- # @option options [Integer] :timeout maximum number of seconds before end
27
- # of capture. Default: +nil+ (no timeout)
28
- # @option options [String] :filter bpf filter
29
- # @option options [Boolean] :promiscuous (default: +false+)
30
- # @option options [Boolean] :parse parse raw data to generate packets before
31
- # yielding. Default: +true+
32
- # @option options [Integer] :snaplen maximum number of bytes to capture for
33
- # each packet
34
- def initialize(iface, options={})
35
- @packets = []
24
+ # Get interface name
25
+ # @return [String]
26
+ attr_reader :iface
27
+
28
+ # @overload initialize(iface=Pcap.lookupdev, options={})
29
+ # @param [String] iface interface on which capture packets
30
+ # @param [Hash] options
31
+ # @option options [Integer] :max maximum number of packets to capture.
32
+ # @option options [Integer] :timeout maximum number of seconds before end
33
+ # of capture. Default: +nil+ (no timeout)
34
+ # @option options [String] :filter bpf filter
35
+ # @option options [Boolean] :promiscuous (default: +false+)
36
+ # @option options [Boolean] :parse parse raw data to generate packets before
37
+ # yielding. Default: +true+
38
+ # @option options [Integer] :snaplen maximum number of bytes to capture for
39
+ # each packet.
40
+ # @overload initialize(options={})
41
+ # @param [Hash] options
42
+ # @option options [String] :iface interface on which capture
43
+ # packets on. Default: Use default interface lookup. If no interface found,
44
+ # use loopback one.
45
+ # @option options [Integer] :max maximum number of packets to capture.
46
+ # @option options [Integer] :timeout maximum number of seconds before end
47
+ # of capture. Default: +nil+ (no timeout)
48
+ # @option options [String] :filter bpf filter
49
+ # @option options [Boolean] :promiscuous (default: +false+)
50
+ # @option options [Boolean] :parse parse raw data to generate packets before
51
+ # yielding. Default: +true+
52
+ # @option options [Integer] :snaplen maximum number of bytes to capture for
53
+ # each packet.
54
+ def initialize(iface_or_options={}, options={})
55
+ begin
56
+ @iface = Pcap.lookupdev
57
+ rescue PCAPRUB::BindingError
58
+ @iface = 'lo'
59
+ end
60
+
61
+ case iface_or_options
62
+ when Hash
63
+ options = iface_or_options
64
+ else
65
+ warn "[deprecation] use of PacketGen::Capture#initialize with iface name as\n" \
66
+ " first argument is deprecated. Instead, use:\n" \
67
+ ' PacketGen::Capture.new(iface: \'name\').'
68
+ @iface = iface_or_options.to_s
69
+ end
70
+
71
+ @packets = []
36
72
  @raw_packets = []
37
- @iface = iface
73
+ @promisc = false
74
+ @snaplen = DEFAULT_SNAPLEN
75
+ @parse = true
38
76
  set_options options
39
77
  end
40
78
 
41
79
  # Start capture
42
80
  # @param [Hash] options complete see {#initialize}.
43
81
  # @yieldparam [Packet,String] packet if a block is given, yield each
44
- # captured packet (Packet or raw data String, depending on +:parse+)
82
+ # captured packet (Packet or raw data String, depending on +:parse+ option)
45
83
  def start(options={})
46
84
  set_options options
47
85
  @pcap = PCAPRUB::Pcap.open_live(@iface, @snaplen, @promisc, 1)
48
86
  set_filter
49
-
50
87
  @cap_thread = Thread.new do
51
88
  @pcap.each do |packet_data|
52
89
  @raw_packets << packet_data
@@ -57,9 +94,7 @@ module PacketGen
57
94
  else
58
95
  yield packet_data if block_given?
59
96
  end
60
- if @max
61
- break if @raw_packets.size >= @max
62
- end
97
+ break if @max and @raw_packets.size >= @max
63
98
  end
64
99
  end
65
100
  @cap_thread.join(@timeout)
@@ -80,21 +115,10 @@ module PacketGen
80
115
  @max = options[:max] if options[:max]
81
116
  @filter = options[:filter] if options[:filter]
82
117
  @timeout = options[:timeout] if options[:timeout]
83
- if options[:promisc]
84
- @promisc = options[:promisc]
85
- else
86
- @promisc ||= false
87
- end
88
- if options[:snaplen]
89
- @snaplen = options[:snaplen]
90
- else
91
- @snaplen ||= DEFAULT_SNAPLEN
92
- end
93
- if options[:parse].nil?
94
- @parse = true if @parse.nil?
95
- else
96
- @parse = options[:parse]
97
- end
118
+ @promisc = options[:promisc] if options.has_key? :promisc
119
+ @snaplen = options[:snaplen] if options[:snaplen]
120
+ @parse = options[:parse] if options.has_key? :parse
121
+ @iface = options[:iface] if options[:iface]
98
122
  end
99
123
 
100
124
  def set_filter
@@ -0,0 +1,39 @@
1
+ require 'network_interface'
2
+ require 'socket'
3
+
4
+ module PacketGen
5
+
6
+ # Config class to provide +config+ object to pgconsole
7
+ # @author Sylvain Daubert
8
+ class Config
9
+
10
+ # Default network interface
11
+ # @return [String]
12
+ attr_reader :iface
13
+ # MAC address of default interface
14
+ # @return [String]
15
+ attr_reader :hwaddr
16
+ # IP address of default interface
17
+ # @return [String]
18
+ attr_reader :ipaddr
19
+ # IPv6 address of default interface
20
+ # @return [String]
21
+ attr_reader :ip6addr
22
+
23
+ # Create a configuration object. If +iface+ is not set, get first network interface.
24
+ # If non exists, use loopback one.
25
+ # @param [String,nil] iface
26
+ def initialize(iface=nil)
27
+ if iface.nil?
28
+ iface = NetworkInterface.interfaces.select { |iface| iface != 'lo' }.first
29
+ iface = NetworkInterface.interfaces.first if iface.nil?
30
+ end
31
+ @iface = iface
32
+
33
+ addresses = NetworkInterface.addresses(iface)
34
+ @hwaddr = addresses[Socket::AF_PACKET][0]['addr'] if addresses[Socket::AF_PACKET]
35
+ @ipaddr = addresses[Socket::AF_INET][0]['addr'] if addresses[Socket::AF_INET]
36
+ @ip6addr = addresses[Socket::AF_INET6][0]['addr'] if addresses[Socket::AF_INET6]
37
+ end
38
+ end
39
+ end
@@ -33,10 +33,10 @@ module PacketGen
33
33
  #
34
34
  # == Get packets
35
35
  # Packets may be captured from wire:
36
- # Packet.capture('eth0') do |packet|
36
+ # Packet.capture do |packet|
37
37
  # do_some_stuffs
38
38
  # end
39
- # packets = Packet.capture('eth0', max: 5) # get 5 packets
39
+ # packets = Packet.capture(iface: 'eth0', max: 5) # get 5 packets from eth0
40
40
  #
41
41
  # Packets may also be read from a file:
42
42
  # packets = Packet.read(file.pcapng)
@@ -68,9 +68,10 @@ module PacketGen
68
68
  new.parse binary_str, first_header: first_header
69
69
  end
70
70
 
71
- # Capture packets from +iface+
72
- # @param [String] iface interface name
71
+ # Capture packets
73
72
  # @param [Hash] options capture options
73
+ # @option options [String] :iface interface on which capture
74
+ # packets on. Default: Use default interface lookup.
74
75
  # @option options [Integer] :max maximum number of packets to capture
75
76
  # @option options [Integer] :timeout maximum number of seconds before end
76
77
  # of capture
@@ -78,8 +79,8 @@ module PacketGen
78
79
  # @option options [Boolean] :promiscuous
79
80
  # @yieldparam [Packet] packet if a block is given, yield each captured packet
80
81
  # @return [Array<Packet>] captured packet
81
- def self.capture(iface, options={})
82
- capture = Capture.new(iface, options)
82
+ def self.capture(options={})
83
+ capture = Capture.new(options)
83
84
  if block_given?
84
85
  capture.start { |packet| yield packet }
85
86
  else
@@ -8,5 +8,5 @@
8
8
  # @author Sylvain Daubert
9
9
  module PacketGen
10
10
  # PacketGen version
11
- VERSION = "1.4.0"
11
+ VERSION = "1.4.1"
12
12
  end
data/lib/packetgen.rb CHANGED
@@ -42,8 +42,8 @@ module PacketGen
42
42
  # @param [Hash] options capture options. See {Packet.capture}.
43
43
  # @yieldparam [Packet] packet
44
44
  # @return [Array<Packet>]
45
- def self.capture(iface, options={})
46
- Packet.capture(iface, options) { |packet| yield packet if block_given? }
45
+ def self.capture(options={})
46
+ Packet.capture(options) { |packet| yield packet if block_given? }
47
47
  end
48
48
 
49
49
  # Shortcut for {Packet.read}
data/packetgen.gemspec CHANGED
@@ -16,13 +16,15 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
17
  f.match(%r{^(test|spec|features)/})
18
18
  end
19
- spec.bindir = 'exe'
20
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.bindir = 'bin'
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ['lib']
22
22
 
23
23
  spec.required_ruby_version = '>= 2.1.0'
24
24
 
25
25
  spec.add_dependency 'pcaprub', '~>0.12.4'
26
+ spec.add_dependency 'pry', '~>0.10'
27
+ spec.add_dependency 'network_interface'
26
28
 
27
29
  spec.add_development_dependency 'bundler', '~> 1.7'
28
30
  spec.add_development_dependency 'rake', '~> 10.0'
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: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Daubert
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-17 00:00:00.000000000 Z
11
+ date: 2017-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pcaprub
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.12.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.10'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: network_interface
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -97,7 +125,8 @@ dependencies:
97
125
  description:
98
126
  email:
99
127
  - sylvain.daubert@laposte.net
100
- executables: []
128
+ executables:
129
+ - pgconsole
101
130
  extensions: []
102
131
  extra_rdoc_files: []
103
132
  files:
@@ -107,8 +136,10 @@ files:
107
136
  - LICENSE
108
137
  - README.md
109
138
  - Rakefile
139
+ - bin/pgconsole
110
140
  - lib/packetgen.rb
111
141
  - lib/packetgen/capture.rb
142
+ - lib/packetgen/config.rb
112
143
  - lib/packetgen/header.rb
113
144
  - lib/packetgen/header/arp.rb
114
145
  - lib/packetgen/header/base.rb