pcapz 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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