pio 0.1.1 → 0.2.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
  SHA1:
3
- metadata.gz: 42e4ddeb113721d1515042c5b21242f7f5f49f76
4
- data.tar.gz: 4d135571f99d94db9e3b0f534e8154669da4360d
3
+ metadata.gz: a99eb3c57f09bc9a82c53d916636509695770620
4
+ data.tar.gz: 5da352b9a4cbe2660ce0fc71e086f15c697f52b2
5
5
  SHA512:
6
- metadata.gz: bae38aa9d987cfd6965b4657222e8713dc4e019d655bcc4fc2b81c1bdee8fa03d5b9795324b8915290e56d78ae4b8b93584d071b0cc65ab921b64da47b7cb61c
7
- data.tar.gz: 0ff3e93fc9a7159807c3ed2bb01fb8ff045e948e34ee32a1956b6856fa9ec24c8734b2287bffd5fe77d66194e29c5e5d85f63db329495cfa480af23971e3bf9f
6
+ metadata.gz: 50e299558aea50ece6f430e007b428b9b5cc53439883043aca7128fe67ed3d08c50ec2e8ffac4f5d115735e77eb09289d25a249ee22f812edfbca2f91289aacc
7
+ data.tar.gz: b01bab2207f6556d2ca45ff72281c1475195511767d64b6b4847100961ada881b3406aeee2cd068d6998881f08d07dc026ca6c991a594a87d84aa2e722dd419e
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format Fuubar
2
+ --color
data/Gemfile CHANGED
@@ -4,14 +4,15 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
 
7
- group :development do
7
+ group :development, :test do
8
8
  gem "coveralls", "~> 0.6.7", :require => false
9
9
  gem "flay", "~> 2.4.0"
10
10
  gem "flog", "~> 4.1.1"
11
+ gem "fuubar", "~> 1.2.1"
11
12
  gem "guard", "~> 1.8.2"
12
13
  gem "guard-bundler", "~> 1.0.0"
13
14
  gem "guard-rspec", "~> 3.0.2"
14
- gem "json", "~> 1.8.0" if RUBY_VERSION < "1.9.0"
15
+ gem "json", "~> 1.8.0"
15
16
  gem "rake", "~> 10.1.0"
16
17
  gem "rb-fchange", "~> 0.0.6", :require => false
17
18
  gem "rb-fsevent", "~> 0.9.3", :require => false
data/Guardfile CHANGED
@@ -1,6 +1,9 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
+ notification :terminal_notifier
5
+ notification :tmux, :display_message => true
6
+
4
7
 
5
8
  guard 'bundler' do
6
9
  watch('Gemfile')
@@ -11,6 +14,6 @@ end
11
14
 
12
15
  guard :rspec do
13
16
  watch(%r{^spec/pio/.+_spec\.rb$})
14
- watch(%r{^lib/pio/(.+)\.rb$}) { |m| "spec/lib/pio/#{m[1]}_spec.rb" }
17
+ watch(%r{^lib/pio/(.+)\.rb$}) { |m| "spec/pio/#{m[1]}_spec.rb" }
15
18
  watch('spec/spec_helper.rb') { "spec" }
16
19
  end
data/README.md CHANGED
@@ -10,7 +10,8 @@ Pio
10
10
 
11
11
  Pio is a ruby gem to easily parse and generate network packets. It supports the following packet formats:
12
12
 
13
- * [LLDP](http://en.wikipedia.org/wiki/Link_Layer_Discovery_Protocol)
13
+ * ARP
14
+ * LLDP
14
15
  * (...currently there are just a few formats supported but I'm sure this list will grow)
15
16
 
16
17
 
@@ -25,14 +26,51 @@ Features Overview
25
26
  * Clean Code. Pio is built on
26
27
  [BinData](https://github.com/dmendel/bindata)'s declarative binary
27
28
  format DSL so that it is easy to read and debug by human beings.
28
-
29
+
29
30
 
30
31
  Example
31
32
  -------
32
33
 
33
- Its usage is dead simple: to parse an LLDP frame for example, use the
34
- API `Pio::Lldp.read` and you can access each field of the parsed LLDP
35
- frame.
34
+ Its usage is dead simple.
35
+
36
+ ### ARP
37
+
38
+ To parse an ARP frame, use the API `Pio::Arp.read` and you can access
39
+ each field of the parsed ARP frame.
40
+
41
+ ```ruby
42
+ require "pio"
43
+
44
+ arp = Pio::Arp.read( binary_data )
45
+ arp.source_mac.to_s #=> "00:26:82:eb:ea:d1"
46
+ ```
47
+
48
+ Also you can use `Pio::Arp::Request#new` or `Pio::Arp::Reply#new` to
49
+ generate an Arp Request/Reply frame like below:
50
+
51
+ ```ruby
52
+ require "pio"
53
+
54
+ request = Pio::Arp::Request.new(
55
+ source_mac: "00:26:82:eb:ea:d1",
56
+ sender_protocol_address: "192.168.83.3",
57
+ target_protocol_address: "192.168.83.254"
58
+ )
59
+ request.to_binary #=> Arp Request frame in binary format.
60
+
61
+ reply = Pio::Arp::Reply.new(
62
+ source_mac: "00:26:82:eb:ea:d1",
63
+ destination_mac: "00:26:82:eb:ea:d1",
64
+ sender_protocol_address: "192.168.83.3",
65
+ target_protocol_address: "192.168.83.254"
66
+ )
67
+ reply.to_binary #=> Arp Reply frame in binary format.
68
+ ```
69
+
70
+ ### LLDP
71
+
72
+ To parse an LLDP frame, use the API `Pio::Lldp.read` and you can
73
+ access each field of the parsed LLDP frame.
36
74
 
37
75
  ```ruby
38
76
  require "pio"
@@ -46,7 +84,7 @@ Also you can use `Pio::Lldp#new` to generate an LLDP frame like below:
46
84
  ```ruby
47
85
  require "pio"
48
86
 
49
- lldp = Pio::Lldp.new( 0x123, 12 ) # dpid and port_number
87
+ lldp = Pio::Lldp.new( dpid: 0x123, port_number: 12 )
50
88
  lldp.to_binary #=> LLDP frame in binary format.
51
89
  ```
52
90
 
data/Rakefile CHANGED
@@ -1,21 +1,3 @@
1
- #
2
- # Copyright (C) 2013 NEC Corporation
3
- #
4
- # This program is free software; you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License, version 3, as
6
- # published by the Free Software Foundation.
7
- #
8
- # This program is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- # GNU General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU General Public License along
14
- # with this program; if not, write to the Free Software Foundation, Inc.,
15
- # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
- #
17
-
18
-
19
1
  require "bundler/gem_tasks"
20
2
  require "coveralls/rake/task"
21
3
  require "flay"
@@ -34,19 +16,19 @@ $ruby_source = FileList[ "lib/**/*.rb" ]
34
16
 
35
17
  task :default => :travis
36
18
  task :travis => [ :spec, :quality, "coveralls:push" ]
19
+
20
+ desc "Check for code quality"
37
21
  task :quality => [ :reek, :flog, :flay ]
38
22
 
39
23
 
40
24
  Coveralls::RakeTask.new
41
25
 
42
26
 
43
- RSpec::Core::RakeTask.new do | task |
44
- task.rspec_opts = "--format documentation --color"
45
- end
27
+ RSpec::Core::RakeTask.new
46
28
 
47
29
 
48
30
  Reek::Rake::Task.new do | t |
49
- t.fail_on_error = true
31
+ t.fail_on_error = false
50
32
  t.verbose = false
51
33
  t.ruby_opts = [ "-rubygems" ]
52
34
  t.reek_opts = "--quiet"
@@ -69,7 +51,7 @@ task :flog do
69
51
  puts "%8.1f: %s" % [ score, name ]
70
52
  end
71
53
  unless bad_methods.empty?
72
- raise "#{ bad_methods.size } methods have a flog complexity > #{ threshold }"
54
+ $stderr.puts "#{ bad_methods.size } methods have a flog complexity > #{ threshold }"
73
55
  end
74
56
  end
75
57
 
@@ -0,0 +1,15 @@
1
+ require "pio/arp"
2
+ require "pio/lldp"
3
+
4
+
5
+ module Pio
6
+ # Raised when the packet data is in wrong format.
7
+ class ParseError < StandardError; end
8
+ end
9
+
10
+
11
+ ### Local variables:
12
+ ### mode: Ruby
13
+ ### coding: utf-8-unix
14
+ ### indent-tabs-mode: nil
15
+ ### End:
@@ -0,0 +1,31 @@
1
+ require "rubygems"
2
+ require "bindata"
3
+
4
+ require "pio/arp/request"
5
+ require "pio/arp/reply"
6
+
7
+
8
+ module Pio
9
+ # ARP parser and generator.
10
+ class Arp
11
+ ARP_MESSAGE_TYPE = { Request::OPERATION => Request, Reply::OPERATION => Reply }
12
+
13
+
14
+ def self.read( raw_data )
15
+ begin
16
+ frame = Arp::Frame.read( raw_data )
17
+ rescue
18
+ raise Pio::ParseError, $!.message
19
+ end
20
+
21
+ ARP_MESSAGE_TYPE[ frame.operation ].create_from frame
22
+ end
23
+ end
24
+ end
25
+
26
+
27
+ ### Local variables:
28
+ ### mode: Ruby
29
+ ### coding: utf-8-unix
30
+ ### indent-tabs-mode: nil
31
+ ### End:
@@ -0,0 +1,38 @@
1
+ require "pio/type/ethernet-header"
2
+ require "pio/type/ip-address"
3
+ require "pio/type/mac-address"
4
+
5
+
6
+ module Pio
7
+ class Arp
8
+ # ARP frame parser.
9
+ class Frame < BinData::Record
10
+ extend Type::EthernetHeader
11
+
12
+ endian :big
13
+
14
+ ethernet_header :ether_type => 0x0806
15
+ uint16 :hardware_type, :value => 1
16
+ uint16 :protocol_type, :value => 0x0800
17
+ uint8 :hardware_length, :value => 6
18
+ uint8 :protocol_length, :value => 4
19
+ uint16 :operation
20
+ mac_address :sender_hardware_address
21
+ ip_address :sender_protocol_address
22
+ mac_address :target_hardware_address
23
+ ip_address :target_protocol_address
24
+
25
+
26
+ def to_binary
27
+ to_binary_s + "\000" * ( 64 - num_bytes )
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+ ### Local variables:
35
+ ### mode: Ruby
36
+ ### coding: utf-8-unix
37
+ ### indent-tabs-mode: nil
38
+ ### End:
@@ -0,0 +1,66 @@
1
+ require "pio/arp/frame"
2
+ require "forwardable"
3
+
4
+
5
+ module Pio
6
+ class Arp
7
+ # Base class of ARP Request and Reply
8
+ class Message
9
+ extend Forwardable
10
+
11
+
12
+ def self.create_from frame
13
+ message = allocate
14
+ message.instance_variable_set :@frame, frame
15
+ message
16
+ end
17
+
18
+
19
+ def initialize options
20
+ @options = options
21
+ @frame = Arp::Frame.new( option_hash )
22
+ end
23
+
24
+
25
+ def_delegators :@frame, :destination_mac
26
+ def_delegators :@frame, :source_mac
27
+ def_delegators :@frame, :ether_type
28
+ def_delegators :@frame, :hardware_type
29
+ def_delegators :@frame, :protocol_type
30
+ def_delegators :@frame, :hardware_length
31
+ def_delegators :@frame, :protocol_length
32
+ def_delegators :@frame, :operation
33
+ def_delegators :@frame, :sender_hardware_address
34
+ def_delegators :@frame, :sender_protocol_address
35
+ def_delegators :@frame, :target_hardware_address
36
+ def_delegators :@frame, :target_protocol_address
37
+ def_delegators :@frame, :to_binary
38
+
39
+
40
+ ##########################################################################
41
+ private
42
+ ##########################################################################
43
+
44
+
45
+ def option_hash
46
+ mandatory_options.inject( {} ) do | opt, each |
47
+ klass = option_to_klass[ each ]
48
+ opt_pair = { each => klass.new( user_options[ each ] ).to_a }
49
+ opt.merge opt_pair
50
+ end.merge default_options
51
+ end
52
+
53
+
54
+ def option_to_klass
55
+ {
56
+ :source_mac => Mac,
57
+ :destination_mac => Mac,
58
+ :sender_hardware_address => Mac,
59
+ :target_hardware_address => Mac,
60
+ :sender_protocol_address => IP,
61
+ :target_protocol_address => IP,
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,55 @@
1
+ require "forwardable"
2
+ require "pio/arp/message"
3
+ require "pio/ip"
4
+ require "pio/mac"
5
+
6
+
7
+ module Pio
8
+ class Arp
9
+ # ARP Reply packet generator
10
+ class Reply < Message
11
+ OPERATION = 2
12
+
13
+
14
+ ##########################################################################
15
+ private
16
+ ##########################################################################
17
+
18
+
19
+ def default_options
20
+ {
21
+ :operation => OPERATION,
22
+ }
23
+ end
24
+
25
+
26
+ def user_options
27
+ @options.merge(
28
+ {
29
+ :sender_hardware_address => @options[ :source_mac ],
30
+ :target_hardware_address => @options[ :destination_mac ]
31
+ }
32
+ )
33
+ end
34
+
35
+
36
+ def mandatory_options
37
+ [
38
+ :source_mac,
39
+ :destination_mac,
40
+ :sender_hardware_address,
41
+ :target_hardware_address,
42
+ :sender_protocol_address,
43
+ :target_protocol_address,
44
+ ]
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ ### Local variables:
52
+ ### mode: Ruby
53
+ ### coding: utf-8-unix
54
+ ### indent-tabs-mode: nil
55
+ ### End:
@@ -0,0 +1,55 @@
1
+ require "pio/arp/frame"
2
+ require "pio/arp/message"
3
+ require "pio/ip"
4
+ require "pio/mac"
5
+
6
+
7
+ module Pio
8
+ class Arp
9
+ # ARP Request packet generator
10
+ class Request < Message
11
+ OPERATION = 1
12
+
13
+ BROADCAST_MAC_ADDRESS = Mac.new( 0xffffffffffff ).to_a
14
+ ALL_ZERO_MAC_ADDRESS = Mac.new( 0 ).to_a
15
+
16
+
17
+ ########################################################################
18
+ private
19
+ ########################################################################
20
+
21
+
22
+ def default_options
23
+ {
24
+ :operation => OPERATION,
25
+ :destination_mac => BROADCAST_MAC_ADDRESS,
26
+ :target_hardware_address => ALL_ZERO_MAC_ADDRESS
27
+ }
28
+ end
29
+
30
+
31
+ def user_options
32
+ @options.merge(
33
+ { :sender_hardware_address => @options[ :source_mac ] }
34
+ )
35
+ end
36
+
37
+
38
+ def mandatory_options
39
+ [
40
+ :source_mac,
41
+ :sender_hardware_address,
42
+ :sender_protocol_address,
43
+ :target_protocol_address,
44
+ ]
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ ### Local variables:
52
+ ### mode: Ruby
53
+ ### coding: utf-8-unix
54
+ ### indent-tabs-mode: nil
55
+ ### End: