pcapz 1.0.0 → 1.0.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
  SHA256:
3
- metadata.gz: 6739f9dd7736d0651579bba73505cb5a60a744ed9447eff3ea412cc415b14156
4
- data.tar.gz: 63e9c4491915e9fb02ce3e9e59e90a980a473ddbd743e5b55f2a8143110a6140
3
+ metadata.gz: 8999b84015d8bea49b3d193ab221751a04a777428e88416064231792a4de501c
4
+ data.tar.gz: 43c189e57dd69a75e838833eb7e8f2d3c1d8bd3c60fb732c6deb671697472da5
5
5
  SHA512:
6
- metadata.gz: 958d14f4d1a2372dae05371f18850070857f3d73e69e83b474803a71b160a03a3b1c4f1ef0c5fe85c6060d47559e34a0d7d1eac3201ab70725645290bc4363c8
7
- data.tar.gz: 1588501e28fb5c092af8beddab8a57edf3b3313a137a84bab3a15636e697ee3742b8cf6be743888e40f0298a636332dac83a5e7a0f0d4464b9c18e9a9a87c5f2
6
+ metadata.gz: 9b0b294db2523c938be928a4150d2e78216d28ce402fb69fca9be135fe3431104737cb41e48676c3a1925b42d24b3a47cd208452f51b10d914a0454369e32bef
7
+ data.tar.gz: 0ebe1b2dce738fe8159d7d385bbe90694d35b1adffe1ecbec31a4f696397b7cc81ed3e1c807e50f2f4cfa2061b2f57017cc380f8ff78356ab022c89d778bdb40
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  /.bundle/
2
+ /.vagrant/
2
3
  /.yardoc
3
4
  /_yardoc/
4
5
  /coverage/
@@ -9,3 +10,4 @@
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
13
+ ubuntu-xenial-16.04-cloudimg-console.log
@@ -1,14 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pcapz (1.0.0)
4
+ pcapz (1.0.1)
5
5
  interfacez (~> 1.0.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
+ coderay (1.1.2)
10
11
  diff-lcs (1.3)
11
12
  interfacez (1.0.0)
13
+ method_source (0.9.0)
14
+ pry (0.11.3)
15
+ coderay (~> 1.1.0)
16
+ method_source (~> 0.9.0)
12
17
  rake (10.5.0)
13
18
  rspec (3.7.0)
14
19
  rspec-core (~> 3.7.0)
@@ -30,6 +35,7 @@ PLATFORMS
30
35
  DEPENDENCIES
31
36
  bundler (~> 1.16)
32
37
  pcapz!
38
+ pry (~> 0.11.3)
33
39
  rake (~> 10.0)
34
40
  rspec (~> 3.0)
35
41
 
data/README.md CHANGED
@@ -24,9 +24,9 @@ cap.packets do |packet|
24
24
  end
25
25
  ```
26
26
 
27
- ## Development
27
+ ## Supported Platforms
28
28
 
29
- Currently this is only implemented for macOS.
29
+ Currently this has only been implemented/tested on macOS and Linux.
30
30
 
31
31
  ## License
32
32
 
@@ -0,0 +1,76 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ # All Vagrant configuration is done below. The "2" in Vagrant.configure
5
+ # configures the configuration version (we support older styles for
6
+ # backwards compatibility). Please don't change it unless you know what
7
+ # you're doing.
8
+ Vagrant.configure("2") do |config|
9
+ # The most common configuration options are documented and commented below.
10
+ # For a complete reference, please see the online documentation at
11
+ # https://docs.vagrantup.com.
12
+
13
+ # Every Vagrant development environment requires a box. You can search for
14
+ # boxes at https://vagrantcloud.com/search.
15
+ config.vm.box = "ubuntu/xenial64"
16
+
17
+ # Disable automatic box update checking. If you disable this, then
18
+ # boxes will only be checked for updates when the user runs
19
+ # `vagrant box outdated`. This is not recommended.
20
+ # config.vm.box_check_update = false
21
+
22
+ # Create a forwarded port mapping which allows access to a specific port
23
+ # within the machine from a port on the host machine. In the example below,
24
+ # accessing "localhost:8080" will access port 80 on the guest machine.
25
+ # NOTE: This will enable public access to the opened port
26
+ # config.vm.network "forwarded_port", guest: 80, host: 8080
27
+
28
+ # Create a forwarded port mapping which allows access to a specific port
29
+ # within the machine from a port on the host machine and only allow access
30
+ # via 127.0.0.1 to disable public access
31
+ # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
32
+
33
+ # Create a private network, which allows host-only access to the machine
34
+ # using a specific IP.
35
+ # config.vm.network "private_network", ip: "192.168.33.10"
36
+
37
+ # Create a public network, which generally matched to bridged network.
38
+ # Bridged networks make the machine appear as another physical device on
39
+ # your network.
40
+ # config.vm.network "public_network"
41
+
42
+ # Share an additional folder to the guest VM. The first argument is
43
+ # the path on the host to the actual folder. The second argument is
44
+ # the path on the guest to mount the folder. And the optional third
45
+ # argument is a set of non-required options.
46
+ # config.vm.synced_folder "../data", "/vagrant_data"
47
+
48
+ # Provider-specific configuration so you can fine-tune various
49
+ # backing providers for Vagrant. These expose provider-specific options.
50
+ # Example for VirtualBox:
51
+ #
52
+ # config.vm.provider "virtualbox" do |vb|
53
+ # # Display the VirtualBox GUI when booting the machine
54
+ # vb.gui = true
55
+ #
56
+ # # Customize the amount of memory on the VM:
57
+ # vb.memory = "1024"
58
+ # end
59
+ #
60
+ # View the documentation for the provider you are using for more
61
+ # information on available options.
62
+
63
+ # Enable provisioning with a shell script. Additional provisioners such as
64
+ # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
65
+ # documentation for more information about their specific syntax and use.
66
+ config.vm.provision "shell", inline: <<-SHELL
67
+ apt-get update
68
+ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
69
+ curl -sSL https://get.rvm.io | bash -s stable
70
+ source /home/$USER/.rvm/scripts/rvm
71
+ echo "source /home/$USER/.rvm/scripts/rvm" >> ~/.bashrc
72
+ source /home/$USER/.rvm/scripts/rvm # good measure
73
+ rvm install 2.5.0
74
+ rvm use ruby-2.5.0 --default
75
+ SHELL
76
+ end
@@ -4,6 +4,12 @@ require 'pry'
4
4
 
5
5
  cap = Pcapz.capture.new
6
6
 
7
+ # CTRL+C Exit
8
+ trap "SIGINT" do
9
+ cap.stop! unless cap.stopped?
10
+ exit
11
+ end
12
+
7
13
  begin
8
14
  binding.pry
9
15
  ensure
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'pcapz'
3
+ require 'timeout'
4
+
5
+ cap = Pcapz.capture.new
6
+
7
+ # CTRL+C Exit
8
+ trap "SIGINT" do
9
+ cap.stop! unless cap.stopped?
10
+ end
11
+
12
+ begin
13
+ counter = 0
14
+ Timeout::timeout(1) {
15
+ cap.packets { |packet| counter += 1 }
16
+ }
17
+ rescue
18
+ puts "#{counter} packets per second"
19
+ retry
20
+ ensure
21
+ cap.stop! unless cap.stopped?
22
+ end
@@ -4,6 +4,12 @@ require "pcapz/capture"
4
4
 
5
5
  module Pcapz
6
6
  def self.capture
7
- Capture
7
+ if RUBY_PLATFORM =~ /linux/
8
+ return Capture::Linux
9
+ elsif RUBY_PLATFORM =~ /darwin|freebsd|netbsd/
10
+ return Capture::BSD
11
+ else
12
+ raise "This platform #{RUBY_PLATFORM} is not yet supported!"
13
+ end
8
14
  end
9
15
  end
@@ -1,83 +1,2 @@
1
- module Pcapz
2
- class Capture
3
- def initialize(interface = Interfacez.default)
4
- @interface = interface
5
- @buffer_size = 0
6
- @file = nil
7
- configure_bpf_dev
8
- end
9
-
10
- def packets
11
- return nil if @file.closed?
12
- if block_given?
13
- loop do
14
- buffer = @file.read_nonblock(@buffer_size)
15
- while buffer.size > 0
16
- datalen = buffer.slice(12,4).unpack('L')[0]
17
- hdrlen = buffer.slice(16,2).unpack('v')[0]
18
- size = (datalen+hdrlen) + 3 & ~3
19
- pkt = buffer.slice!(0,size)[hdrlen..-1]
20
- yield pkt unless pkt.nil?
21
- end
22
- end
23
- else
24
- packets = []
25
- buffer = @file.read_nonblock(@buffer_size)
26
- while buffer.size > 0
27
- size, hdrlen = header_decode(buffer)
28
- pkt = buffer.slice!(0,size)[hdrlen..-1]
29
- packets << pkt unless pkt.nil?
30
- end
31
- return packets
32
- end
33
- return true
34
- rescue EOFError, Errno::EAGAIN
35
- retry
36
- rescue IO::WaitReadable
37
- IO.select([@file])
38
- retry
39
- end
40
-
41
- def file
42
- @file
43
- end
44
-
45
- def stop!
46
- return nil if stopped?
47
- @file.close
48
- stopped?
49
- end
50
-
51
- def stopped?
52
- @file.closed?
53
- end
54
-
55
- private
56
-
57
- def configure_bpf_dev(interface: @interface)
58
- Dir.glob('/dev/bpf*') do |item|
59
- begin
60
- @file = File.open(item)
61
- rescue Errno::EBUSY
62
- next
63
- end
64
- end
65
- raise "Unable to start a packet capture on any device" if @file.nil?
66
- @file.ioctl(0x8020426c, [interface].pack("a#{interface.size+1}"))
67
- @file.ioctl(0x80044270, [1].pack('I'))
68
- @file.ioctl(0x40044274, [0].pack('N'))
69
- buf = [0].pack('i')
70
- @file.ioctl(0x40044266, buf)
71
- @buffer_size = buf.unpack('i')[0]
72
- timeout = [5,0].pack('LL')
73
- @file.ioctl(0x8008426d, timeout)
74
- return @file
75
- rescue
76
- @file.close unless @file.nil? or @file.closed?
77
- end
78
-
79
- def packet_size(n)
80
- n+3 & ~3
81
- end
82
- end
83
- end
1
+ require_relative "capture_types/linux"
2
+ require_relative "capture_types/bsd"
@@ -0,0 +1,79 @@
1
+ module Pcapz
2
+ module Capture
3
+ class BSD
4
+ def initialize(interface = Interfacez.default)
5
+ @interface = interface
6
+ @buffer_size = 0
7
+ @file = nil
8
+ @internal_buffer = nil
9
+ configure_bpf_dev
10
+ end
11
+
12
+ def packets
13
+ until @file.closed?
14
+ yield next_packet
15
+ end
16
+ end
17
+
18
+ def next_packet
19
+ @internal_buffer.resume
20
+ rescue Interrupt
21
+ exit
22
+ rescue
23
+ @internal_buffer = Fiber.new do
24
+ loop do
25
+ begin
26
+ buffer = @file.read_nonblock(@buffer_size)
27
+ while buffer.size > 0
28
+ Fiber.yield buffer.slice!(0,(((buffer.slice(12,4).unpack('L')[0])+18) + 3 & ~3))[18..-1]
29
+ end
30
+ rescue IO::WaitReadable
31
+ IO.select([@file])
32
+ retry
33
+ end
34
+ end
35
+ end
36
+ retry
37
+ end
38
+
39
+ def file
40
+ @file
41
+ end
42
+
43
+ def stop!
44
+ return nil if stopped?
45
+ @file.close
46
+ stopped?
47
+ end
48
+
49
+ def stopped?
50
+ @file.closed?
51
+ end
52
+
53
+ private
54
+
55
+ def configure_bpf_dev(interface: @interface)
56
+ Dir.glob('/dev/bpf*') do |item|
57
+ begin
58
+ @file = File.open(item)
59
+ rescue Errno::EBUSY
60
+ next
61
+ end
62
+ end
63
+ raise "Unable to start a packet capture on any device" if @file.nil?
64
+ @file.ioctl(0x8020426c, [interface].pack("a#{interface.size+1}"))
65
+ @file.ioctl(0x80044270, [1].pack('I'))
66
+ @file.ioctl(0x40044274, [0].pack('N'))
67
+ buf = [0].pack('i')
68
+ @file.ioctl(0x40044266, buf)
69
+ @buffer_size = buf.unpack('i')[0]
70
+ timeout = [5,0].pack('LL')
71
+ @file.ioctl(0x8008426d, timeout)
72
+ return @file
73
+ rescue
74
+ @file.close unless @file.nil? or @file.closed?
75
+ raise "Unable to create network listener on #{@interface}!"
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,52 @@
1
+ module Pcapz
2
+ module Capture
3
+ class Linux
4
+ def initialize(interface = Interfacez.default)
5
+ @interface = interface
6
+ @buffer_size = 0
7
+ @file = nil
8
+ configure_socket
9
+ end
10
+
11
+ def packets
12
+ until @file.closed?
13
+ yield next_packet
14
+ end
15
+ end
16
+
17
+ def next_packet
18
+ @file.recvfrom_nonblock(@buffer_size)[0]
19
+ rescue IO::WaitReadable
20
+ IO.select([@file])
21
+ retry
22
+ rescue Interrupt
23
+ exit
24
+ end
25
+
26
+ def file
27
+ @file
28
+ end
29
+
30
+ def stop!
31
+ return nil if stopped?
32
+ @file.close
33
+ stopped?
34
+ end
35
+
36
+ def stopped?
37
+ @file.closed?
38
+ end
39
+
40
+ private
41
+
42
+ def configure_socket(interface: @interface)
43
+ @file = Socket.new(Socket::PF_PACKET, Socket::SOCK_RAW, 0x03_00)
44
+ @file.setsockopt(Socket::SOL_SOCKET, Socket::SO_BINDTODEVICE, interface)
45
+ @buffer_size = 65535
46
+ rescue
47
+ @file.close unless @file.nil? or @file.closed?
48
+ raise "Unable to create network listener on #{@interface}!"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module Pcapz
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "bundler", "~> 1.16"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
27
  spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "pry", "~> 0.11.3"
28
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pcapz
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kent 'picat' Gruber
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-04-04 00:00:00.000000000 Z
11
+ date: 2018-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interfacez
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.11.3
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.11.3
69
83
  description:
70
84
  email:
71
85
  - kgruber1@emich.edu
@@ -82,12 +96,16 @@ files:
82
96
  - LICENSE.txt
83
97
  - README.md
84
98
  - Rakefile
99
+ - Vagrantfile
85
100
  - bin/console
86
101
  - bin/setup
87
102
  - examples/debug.rb
88
103
  - examples/headers.rb
104
+ - examples/pps.rb
89
105
  - lib/pcapz.rb
90
106
  - lib/pcapz/capture.rb
107
+ - lib/pcapz/capture_types/bsd.rb
108
+ - lib/pcapz/capture_types/linux.rb
91
109
  - lib/pcapz/version.rb
92
110
  - pcapz.gemspec
93
111
  homepage: https://github.com/picatz/pcapz