ether_shell 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,13 +1,14 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
- # gem "activesupport", ">= 2.3.5"
4
+ gem 'ethernet', '>= 0.1.0'
5
5
 
6
6
  # Add dependencies to develop your gem here.
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
  group :development do
9
- gem "rspec", "~> 2.5.0"
10
- gem "bundler", "~> 1.0.0"
11
- gem "jeweler", "~> 1.5.2"
12
- gem "rcov", ">= 0"
9
+ gem 'rdoc', '>= 3.6.1'
10
+ gem 'rspec', '~> 2.6.0'
11
+ gem 'bundler', '~> 1.0.0'
12
+ gem 'jeweler', '~> 1.5.2'
13
+ gem 'rcov', '>= 0'
13
14
  end
@@ -2,27 +2,33 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  diff-lcs (1.1.2)
5
+ ethernet (0.1.1)
6
+ system-getifaddrs (~> 0.1.1)
5
7
  git (1.2.5)
6
8
  jeweler (1.5.2)
7
9
  bundler (~> 1.0.0)
8
10
  git (>= 1.2.5)
9
11
  rake
10
- rake (0.8.7)
12
+ rake (0.9.0)
11
13
  rcov (0.9.9)
12
- rspec (2.5.0)
13
- rspec-core (~> 2.5.0)
14
- rspec-expectations (~> 2.5.0)
15
- rspec-mocks (~> 2.5.0)
16
- rspec-core (2.5.1)
17
- rspec-expectations (2.5.0)
14
+ rdoc (3.6.1)
15
+ rspec (2.6.0)
16
+ rspec-core (~> 2.6.0)
17
+ rspec-expectations (~> 2.6.0)
18
+ rspec-mocks (~> 2.6.0)
19
+ rspec-core (2.6.3)
20
+ rspec-expectations (2.6.0)
18
21
  diff-lcs (~> 1.1.2)
19
- rspec-mocks (2.5.0)
22
+ rspec-mocks (2.6.0)
23
+ system-getifaddrs (0.1.1)
20
24
 
21
25
  PLATFORMS
22
26
  ruby
23
27
 
24
28
  DEPENDENCIES
25
29
  bundler (~> 1.0.0)
30
+ ethernet (>= 0.1.0)
26
31
  jeweler (~> 1.5.2)
27
32
  rcov
28
- rspec (~> 2.5.0)
33
+ rdoc (>= 3.6.1)
34
+ rspec (~> 2.6.0)
@@ -48,7 +48,11 @@ documetation. You're most likely interested in the spec for ShellDsl.
48
48
  * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
49
49
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
50
50
 
51
+ == Author
52
+
53
+ Victor Costan victor@costan.us
54
+
51
55
  == Copyright
52
56
 
53
- Copyright (c) 2011 Massachusetts Institute of Technology. See LICENSE.txt for
54
- further details.
57
+ Copyright (c) 2011 Massachusetts Institute of Technology.
58
+ See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -39,7 +39,7 @@ end
39
39
 
40
40
  task :default => :spec
41
41
 
42
- require 'rake/rdoctask'
42
+ require 'rdoc/task'
43
43
  Rake::RDocTask.new do |rdoc|
44
44
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
45
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0
1
+ 0.9.1
@@ -5,15 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ether_shell}
8
- s.version = "0.9.0"
8
+ s.version = "0.9.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Victor Costan"]
12
- s.date = %q{2011-03-22}
13
- s.default_executable = %q{ether_shell}
11
+ s.authors = [%q{Victor Costan}]
12
+ s.date = %q{2011-05-27}
14
13
  s.description = %q{IRB session specialized for testing Ethernet devices}
15
14
  s.email = %q{victor@costan.us}
16
- s.executables = ["ether_shell"]
15
+ s.executables = [%q{ether_shell}]
17
16
  s.extra_rdoc_files = [
18
17
  "LICENSE.txt",
19
18
  "README.rdoc"
@@ -32,11 +31,7 @@ Gem::Specification.new do |s|
32
31
  "ether_shell.gemspec",
33
32
  "lib/ether_shell.rb",
34
33
  "lib/ether_shell/expectation_error.rb",
35
- "lib/ether_shell/high_socket.rb",
36
- "lib/ether_shell/raw_socket.rb",
37
34
  "lib/ether_shell/shell_dsl.rb",
38
- "spec/ether_shell/high_socket_spec.rb",
39
- "spec/ether_shell/raw_socket_spec.rb",
40
35
  "spec/ether_shell/shell_dsl_spec.rb",
41
36
  "spec/ether_shell_spec.rb",
42
37
  "spec/spec_helper.rb",
@@ -44,13 +39,11 @@ Gem::Specification.new do |s|
44
39
  "spec/support/shell_stub.rb"
45
40
  ]
46
41
  s.homepage = %q{http://github.com/pwnall/ether_shell}
47
- s.licenses = ["MIT"]
48
- s.require_paths = ["lib"]
49
- s.rubygems_version = %q{1.6.0}
42
+ s.licenses = [%q{MIT}]
43
+ s.require_paths = [%q{lib}]
44
+ s.rubygems_version = %q{1.8.4}
50
45
  s.summary = %q{IRB session specialized for testing Ethernet devices}
51
46
  s.test_files = [
52
- "spec/ether_shell/high_socket_spec.rb",
53
- "spec/ether_shell/raw_socket_spec.rb",
54
47
  "spec/ether_shell/shell_dsl_spec.rb",
55
48
  "spec/ether_shell_spec.rb",
56
49
  "spec/spec_helper.rb",
@@ -62,20 +55,26 @@ Gem::Specification.new do |s|
62
55
  s.specification_version = 3
63
56
 
64
57
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
- s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
58
+ s.add_runtime_dependency(%q<ethernet>, [">= 0.1.0"])
59
+ s.add_development_dependency(%q<rdoc>, [">= 3.6.1"])
60
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
66
61
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
67
62
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
68
63
  s.add_development_dependency(%q<rcov>, [">= 0"])
69
64
  s.add_development_dependency(%q<rspec>, ["> 1.2.3"])
70
65
  else
71
- s.add_dependency(%q<rspec>, ["~> 2.5.0"])
66
+ s.add_dependency(%q<ethernet>, [">= 0.1.0"])
67
+ s.add_dependency(%q<rdoc>, [">= 3.6.1"])
68
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
72
69
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
70
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
74
71
  s.add_dependency(%q<rcov>, [">= 0"])
75
72
  s.add_dependency(%q<rspec>, ["> 1.2.3"])
76
73
  end
77
74
  else
78
- s.add_dependency(%q<rspec>, ["~> 2.5.0"])
75
+ s.add_dependency(%q<ethernet>, [">= 0.1.0"])
76
+ s.add_dependency(%q<rdoc>, [">= 3.6.1"])
77
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
79
78
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
80
79
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
81
80
  s.add_dependency(%q<rcov>, [">= 0"])
@@ -3,6 +3,4 @@ module EtherShell
3
3
  end
4
4
 
5
5
  require 'ether_shell/expectation_error.rb'
6
- require 'ether_shell/high_socket.rb'
7
- require 'ether_shell/raw_socket.rb'
8
6
  require 'ether_shell/shell_dsl.rb'
@@ -1,3 +1,5 @@
1
+ require 'ethernet'
2
+
1
3
  # :nodoc: namespace
2
4
  module EtherShell
3
5
 
@@ -15,7 +17,7 @@ module ShellDsl
15
17
  def connect(eth_device, ether_type, dest_mac)
16
18
  raise "Already connected. did you forget to call disconnect?" if @_socket
17
19
  mac_bytes = EtherShell::ShellDsl.parse_mac_data dest_mac
18
- @_socket = EtherShell::HighSocket.new eth_device, ether_type
20
+ @_socket = Ethernet.socket eth_device, ether_type
19
21
  @_socket.connect mac_bytes
20
22
  if @_verbose
21
23
  print ['Connected to ', mac_bytes.unpack('H*').first, ' using ',
@@ -1,10 +1,10 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe 'ShellDsl' do
4
- let(:eth_device) { 'eth0' }
4
+ let(:eth_device) { Ethernet::Devices.all.sort.first }
5
5
  let(:eth_type) { 0x0800 }
6
6
  let(:eth_type_hex) { '0800' }
7
- let(:mac) { EtherShell::RawSocket.mac eth_device }
7
+ let(:mac) { Ethernet::Devices.mac eth_device }
8
8
  let(:dest_mac) { "\x00\x11\x22\x33\x44\x55" }
9
9
  let(:dest_mac_hex) { '001122334455' }
10
10
  let(:bcast_mac) do
@@ -38,7 +38,7 @@ describe 'ShellDsl' do
38
38
  end
39
39
 
40
40
  it 'should not accept a socket again' do
41
- raw_socket = EtherShell::HighSocket.new eth_device, eth_type
41
+ raw_socket = Ethernet.socket eth_device, eth_type
42
42
  lambda {
43
43
  shell.socket raw_socket
44
44
  }.should raise_error(RuntimeError)
@@ -55,7 +55,7 @@ describe 'ShellDsl' do
55
55
 
56
56
  describe 'connected to a live socket' do
57
57
  let(:live_socket) do
58
- socket = EtherShell::HighSocket.new eth_device, eth_type
58
+ socket = Ethernet.socket eth_device, eth_type
59
59
  socket.connect bcast_mac
60
60
  socket
61
61
  end
@@ -90,7 +90,7 @@ describe 'ShellDsl' do
90
90
  ])
91
91
  end
92
92
  let(:stubbed_shell_socket) do
93
- socket = EtherShell::HighSocket.new socket_stub, eth_type, mac
93
+ socket = Ethernet::FrameSocket.new socket_stub, eth_type, mac
94
94
  socket.connect dest_mac
95
95
  socket
96
96
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ether_shell
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 57
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 0
10
- version: 0.9.0
9
+ - 1
10
+ version: 0.9.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Victor Costan
@@ -15,28 +15,59 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-22 00:00:00 -04:00
19
- default_executable: ether_shell
18
+ date: 2011-05-27 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
- type: :development
21
+ type: :runtime
23
22
  requirement: &id001 !ruby/object:Gem::Requirement
24
23
  none: false
25
24
  requirements:
26
- - - ~>
25
+ - - ">="
27
26
  - !ruby/object:Gem::Version
28
27
  hash: 27
29
28
  segments:
30
- - 2
31
- - 5
32
29
  - 0
33
- version: 2.5.0
34
- version_requirements: *id001
35
- name: rspec
30
+ - 1
31
+ - 0
32
+ version: 0.1.0
36
33
  prerelease: false
34
+ version_requirements: *id001
35
+ name: ethernet
37
36
  - !ruby/object:Gem::Dependency
38
37
  type: :development
39
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 29
44
+ segments:
45
+ - 3
46
+ - 6
47
+ - 1
48
+ version: 3.6.1
49
+ prerelease: false
50
+ version_requirements: *id002
51
+ name: rdoc
52
+ - !ruby/object:Gem::Dependency
53
+ type: :development
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 23
60
+ segments:
61
+ - 2
62
+ - 6
63
+ - 0
64
+ version: 2.6.0
65
+ prerelease: false
66
+ version_requirements: *id003
67
+ name: rspec
68
+ - !ruby/object:Gem::Dependency
69
+ type: :development
70
+ requirement: &id004 !ruby/object:Gem::Requirement
40
71
  none: false
41
72
  requirements:
42
73
  - - ~>
@@ -47,12 +78,12 @@ dependencies:
47
78
  - 0
48
79
  - 0
49
80
  version: 1.0.0
50
- version_requirements: *id002
51
- name: bundler
52
81
  prerelease: false
82
+ version_requirements: *id004
83
+ name: bundler
53
84
  - !ruby/object:Gem::Dependency
54
85
  type: :development
55
- requirement: &id003 !ruby/object:Gem::Requirement
86
+ requirement: &id005 !ruby/object:Gem::Requirement
56
87
  none: false
57
88
  requirements:
58
89
  - - ~>
@@ -63,12 +94,12 @@ dependencies:
63
94
  - 5
64
95
  - 2
65
96
  version: 1.5.2
66
- version_requirements: *id003
67
- name: jeweler
68
97
  prerelease: false
98
+ version_requirements: *id005
99
+ name: jeweler
69
100
  - !ruby/object:Gem::Dependency
70
101
  type: :development
71
- requirement: &id004 !ruby/object:Gem::Requirement
102
+ requirement: &id006 !ruby/object:Gem::Requirement
72
103
  none: false
73
104
  requirements:
74
105
  - - ">="
@@ -77,12 +108,12 @@ dependencies:
77
108
  segments:
78
109
  - 0
79
110
  version: "0"
80
- version_requirements: *id004
81
- name: rcov
82
111
  prerelease: false
112
+ version_requirements: *id006
113
+ name: rcov
83
114
  - !ruby/object:Gem::Dependency
84
115
  type: :development
85
- requirement: &id005 !ruby/object:Gem::Requirement
116
+ requirement: &id007 !ruby/object:Gem::Requirement
86
117
  none: false
87
118
  requirements:
88
119
  - - ">"
@@ -93,9 +124,9 @@ dependencies:
93
124
  - 2
94
125
  - 3
95
126
  version: 1.2.3
96
- version_requirements: *id005
97
- name: rspec
98
127
  prerelease: false
128
+ version_requirements: *id007
129
+ name: rspec
99
130
  description: IRB session specialized for testing Ethernet devices
100
131
  email: victor@costan.us
101
132
  executables:
@@ -119,17 +150,12 @@ files:
119
150
  - ether_shell.gemspec
120
151
  - lib/ether_shell.rb
121
152
  - lib/ether_shell/expectation_error.rb
122
- - lib/ether_shell/high_socket.rb
123
- - lib/ether_shell/raw_socket.rb
124
153
  - lib/ether_shell/shell_dsl.rb
125
- - spec/ether_shell/high_socket_spec.rb
126
- - spec/ether_shell/raw_socket_spec.rb
127
154
  - spec/ether_shell/shell_dsl_spec.rb
128
155
  - spec/ether_shell_spec.rb
129
156
  - spec/spec_helper.rb
130
157
  - spec/support/raw_socket_stub.rb
131
158
  - spec/support/shell_stub.rb
132
- has_rdoc: true
133
159
  homepage: http://github.com/pwnall/ether_shell
134
160
  licenses:
135
161
  - MIT
@@ -159,13 +185,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
185
  requirements: []
160
186
 
161
187
  rubyforge_project:
162
- rubygems_version: 1.6.0
188
+ rubygems_version: 1.8.4
163
189
  signing_key:
164
190
  specification_version: 3
165
191
  summary: IRB session specialized for testing Ethernet devices
166
192
  test_files:
167
- - spec/ether_shell/high_socket_spec.rb
168
- - spec/ether_shell/raw_socket_spec.rb
169
193
  - spec/ether_shell/shell_dsl_spec.rb
170
194
  - spec/ether_shell_spec.rb
171
195
  - spec/spec_helper.rb
@@ -1,122 +0,0 @@
1
- # :nodoc: namespace
2
- module EtherShell
3
-
4
- # Wraps an Ethernet socket and abstracts away the Ethernet II frame.
5
- class HighSocket
6
- # Creates a wrapper around a raw Ethernet socket.
7
- #
8
- # Args:
9
- # raw_socket_or_device:: a raw Ethernet socket or a string containing an
10
- # Ethernet device name
11
- # ether_type:: 2-byte Ethernet packet type number
12
- # mac_address:: 6-byte MAC address for the Ethernet socket (optional if
13
- # raw_socket_or_device is an Ethernet device name)
14
- #
15
- # Raises:
16
- # RuntimeError:: if mac isn't exactly 6-bytes long
17
- def initialize(raw_socket_or_device, ether_type, mac_address = nil)
18
- check_mac mac_address if mac_address
19
-
20
- if raw_socket_or_device.respond_to? :to_str
21
- @source_mac = mac_address || RawSocket.mac(raw_socket_or_device)
22
- @socket = RawSocket.socket raw_socket_or_device, ether_type
23
- else
24
- raise 'MAC address needed with raw socket' unless mac_address
25
- @source_mac = mac_address.dup
26
- @socket = raw_socket_or_device
27
- end
28
-
29
- @dest_mac = nil
30
- @ether_type = [ether_type].pack('n')
31
- end
32
-
33
- # Sets the destination MAC address for future calls to send.
34
- #
35
- # Args:
36
- # mac:: 6-byte MAC address for the Ethernet socket
37
- #
38
- # Raises:
39
- # RuntimeError:: if mac isn't exactly 6-bytes long
40
- def connect(mac_address)
41
- check_mac mac_address
42
- @dest_mac = mac_address
43
- end
44
-
45
- # Closes the underlying socket.
46
- def close
47
- @socket.close
48
- end
49
-
50
- # Sends an Ethernet II frame.
51
- #
52
- # Args:
53
- # data:: the data bytes to be sent
54
- #
55
- # Raises:
56
- # RuntimeError:: if connect wasn' previously called
57
- def send(data, send_flags = 0)
58
- raise "Not connected" unless @dest_mac
59
- send_to @dest_mac, data, send_flags
60
- end
61
-
62
- # Sends an Ethernet II frame.
63
- #
64
- # Args:
65
- # mac_address:: the destination MAC address
66
- # data:: the data bytes to be sent
67
- #
68
- # Raises:
69
- # RuntimeError:: if connect wasn' previously called
70
- def send_to(mac_address, data, send_flags = 0)
71
- check_mac mac_address
72
-
73
- padding = (data.length < 46) ? "\0" * (46 - data.length) : ''
74
- packet = [mac_address, @source_mac, @ether_type, data, padding].join
75
- @socket.send packet, send_flags
76
- end
77
-
78
- # Receives an Ethernet II frame.
79
- #
80
- # Args:
81
- # buffer_size:: optional maximum packet size argument passed to the raw
82
- # socket's recv method
83
- #
84
- # Returns the data and the source MAC address in the frame.
85
- #
86
- # This will discard incoming frames that don't match the MAC address that the
87
- # socket is connected to, or the Ethernet packet type.
88
- def recv(buffer_size = 8192)
89
- raise "Not connected" unless @dest_mac
90
- loop do
91
- data, mac_address = recv_from buffer_size
92
- return data if @dest_mac == mac_address
93
- end
94
- end
95
-
96
- # Receives an Ethernet II frame.
97
- #
98
- # Args:
99
- # buffer_size:: optional maximum packet size argument passed to the raw
100
- # socket's recv method
101
- #
102
- # Returns the data in the frame.
103
- #
104
- # This will discard incoming frames that don't match the MAC address that the
105
- # socket is connected to, or the Ethernet packet type.
106
- def recv_from(buffer_size = 8192)
107
- loop do
108
- packet = @socket.recv buffer_size
109
- next unless packet[12, 2] == @ether_type
110
- next unless packet[0, 6] == @source_mac
111
- return packet[14..-1], packet[6, 6]
112
- end
113
- end
114
-
115
- # Raises an exception if the given MAC address is invalid.
116
- def check_mac(mac_address)
117
- raise "Invalid MAC address" unless mac_address.length == 6
118
- end
119
- private :check_mac
120
- end # class EtherShell::HighSocket
121
-
122
- end # namespace EtherShell
@@ -1,102 +0,0 @@
1
- require 'socket'
2
-
3
- # :nodoc: namespace
4
- module EtherShell
5
-
6
- # Low-level socket creation functionality.
7
- module RawSocket
8
- # A raw socket will receive all Ethernet frames, and send raw frames.
9
- #
10
- # Args:
11
- # eth_device:: device name for the Ethernet card, e.g. 'eth0'
12
- # ether_type:: Ethernet protocol number
13
- def self.socket(eth_device = nil, ether_type = nil)
14
- ether_type ||= all_ethernet_protocols
15
- socket = Socket.new raw_address_family, Socket::SOCK_RAW, htons(ether_type)
16
- socket.setsockopt Socket::SOL_SOCKET, Socket::SO_BROADCAST, true
17
- set_socket_eth_device(socket, eth_device, ether_type) if eth_device
18
- socket
19
- end
20
-
21
- # The MAC address for an Ethernet card.
22
- #
23
- # Args:
24
- # eth_device:: device name for the Ethernet card, e.g. 'eth0'
25
- def self.mac(eth_device)
26
- case RUBY_PLATFORM
27
- when /linux/
28
- # /usr/include/net/if.h, structure ifreq
29
- ifreq = [eth_device].pack 'a32'
30
- # 0x8927 is SIOCGIFHWADDR in /usr/include/bits/ioctls.h
31
- socket.ioctl 0x8927, ifreq
32
- ifreq[18, 6]
33
- else
34
- raise "Unsupported platform #{RUBY_PLATFORM}"
35
- end
36
- end
37
-
38
- class <<self
39
- # Sets the Ethernet interface and protocol type for a socket.
40
- def set_socket_eth_device(socket, eth_device, ether_type)
41
- case RUBY_PLATFORM
42
- when /linux/
43
- if_number = get_interface_number eth_device
44
- # struct sockaddr_ll in /usr/include/linux/if_packet.h
45
- socket_address = [raw_address_family, htons(ether_type), if_number,
46
- 0xFFFF, 0, 0, ""].pack 'SSISCCa8'
47
- socket.bind socket_address
48
- else
49
- raise "Unsupported platform #{RUBY_PLATFORM}"
50
- end
51
- socket
52
- end
53
- private :set_socket_eth_device
54
-
55
- # The interface number for an Ethernet interface.
56
- def get_interface_number(eth_device)
57
- case RUBY_PLATFORM
58
- when /linux/
59
- # /usr/include/net/if.h, structure ifreq
60
- ifreq = [eth_device].pack 'a32'
61
- # 0x8933 is SIOCGIFINDEX in /usr/include/bits/ioctls.h
62
- socket.ioctl 0x8933, ifreq
63
- ifreq[16, 4].unpack('I').first
64
- else
65
- raise "Unsupported platform #{RUBY_PLATFORM}"
66
- end
67
- end
68
- private :get_interface_number
69
-
70
- # The protocol number for listening to all ethernet protocols.
71
- def all_ethernet_protocols
72
- case RUBY_PLATFORM
73
- when /linux/
74
- 3
75
- else
76
- raise "Unsupported platform #{RUBY_PLATFORM}"
77
- end
78
- end
79
- private :all_ethernet_protocols
80
-
81
- # The AF / PF number for raw sockets.
82
- def raw_address_family
83
- case RUBY_PLATFORM
84
- when /linux/
85
- 17 # cat /usr/include/bits/socket.h | grep PF_PACKET
86
- when /darwin/
87
- 18 # cat /usr/include/sys/socket.h | grep AF_LINK
88
- else
89
- raise "Unsupported platform #{RUBY_PLATFORM}"
90
- end
91
- end
92
- private :raw_address_family
93
-
94
- # Converts a 16-bit integer from host-order to network-order.
95
- def htons(short_integer)
96
- [short_integer].pack('n').unpack('S').first
97
- end
98
- private :htons
99
- end
100
- end # module EtherShell::RawSocket
101
-
102
- end # namespace EtherShell
@@ -1,102 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
- describe 'HighSocket' do
4
- let(:eth_device) { 'eth0' }
5
- let(:eth_type) { 0x0800 }
6
- let(:mac) { EtherShell::RawSocket.mac eth_device }
7
- let(:dest_mac) { "\x00\x11\x22\x33\x44\x55" }
8
- let(:bcast_mac) { "\xff" * 6 }
9
-
10
- shared_examples_for 'a real socket' do
11
- it 'should output a packet' do
12
- @socket.send_to dest_mac, "\r\n"
13
- end
14
-
15
- it 'should receive some network noise' do
16
- @socket.recv_from.first.should_not be_empty
17
- end
18
- end
19
-
20
- describe 'on eth0' do
21
- before { @socket = EtherShell::HighSocket.new eth_device, eth_type }
22
- after { @socket.close }
23
-
24
- it_should_behave_like 'a real socket'
25
- end
26
-
27
- describe 'from raw socket' do
28
- before do
29
- raw_socket = EtherShell::RawSocket.socket eth_device, eth_type
30
- @socket = EtherShell::HighSocket.new raw_socket, eth_type, mac
31
- end
32
- after { @socket.close }
33
-
34
- it_should_behave_like 'a real socket'
35
- end
36
-
37
- describe 'stubbed' do
38
- let(:socket_stub) do
39
- RawSocketStub.new([
40
- [mac, dest_mac, "\x88\xB7", 'Wrong Ethernet type'].join,
41
- [bcast_mac, dest_mac, [eth_type].pack('n'), 'Wrong dest MAC'].join,
42
- [mac, bcast_mac, [eth_type].pack('n'), 'Bcast'].join,
43
- [mac, dest_mac, [eth_type].pack('n'), 'Correct'].join,
44
- ])
45
- end
46
- let(:socket) { EtherShell::HighSocket.new socket_stub, eth_type, mac }
47
-
48
- shared_examples_for 'after a small send call' do
49
- it 'should send a single packet' do
50
- socket_stub.sends.length.should == 1
51
- end
52
- it 'should pad the packet' do
53
- socket_stub.sends.first.length.should == 60
54
- end
55
- it 'should assemble packet correctly in send' do
56
- gold = [dest_mac, mac, [eth_type].pack('n'), 'Send data'].join
57
- socket_stub.sends.first[0, gold.length].should == gold
58
- end
59
- end
60
-
61
- describe 'send_to' do
62
- before { socket.send_to dest_mac, 'Send data' }
63
- it_should_behave_like 'after a small send call'
64
- end
65
-
66
- describe 'recv_from' do
67
- it 'should filter down to the correct packet' do
68
- socket.recv_from.should == ['Bcast', bcast_mac]
69
- end
70
- end
71
-
72
- describe 'unconnected' do
73
- it 'should complain in recv' do
74
- lambda { socket.recv }.should raise_error(RuntimeError)
75
- end
76
-
77
- it 'should complain in send' do
78
- lambda { socket.send 'Send data' }.should raise_error(RuntimeError)
79
- end
80
- end
81
-
82
- describe 'connected' do
83
- before { socket.connect dest_mac }
84
-
85
- describe 'send' do
86
- before { socket.send 'Send data' }
87
- it_should_behave_like 'after a small send call'
88
- end
89
-
90
- describe 'recv' do
91
- it 'should filter down to the correct packet' do
92
- socket.recv.should == 'Correct'
93
- end
94
- end
95
- end
96
-
97
- it 'should delegate close' do
98
- socket_stub.should_receive(:close).once
99
- socket.close
100
- end
101
- end
102
- end
@@ -1,41 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
- describe 'RawSocket' do
4
- let(:eth_device) { 'eth0' }
5
- let(:mac) { EtherShell::RawSocket.mac eth_device }
6
-
7
- describe 'mac' do
8
- let(:golden_mac) do
9
- hex_mac = `ifconfig #{eth_device}`[/HWaddr .*$/][7..-1]
10
- [hex_mac.gsub(':', '').strip].pack('H*')
11
- end
12
-
13
- it 'should have 6 bytes' do
14
- mac.length.should == 6
15
- end
16
-
17
- it 'should match ifconfig output' do
18
- mac.should == golden_mac
19
- end
20
- end
21
-
22
- describe 'socket' do
23
- let(:eth_type) { 0x88B7 }
24
-
25
- before { @socket = EtherShell::RawSocket.socket eth_device }
26
- after { @socket.close }
27
-
28
- it 'should be able to receive data' do
29
- @socket.should respond_to(:recv)
30
- end
31
-
32
- it 'should output a packet' do
33
- packet = [mac, mac, [eth_type].pack('n'), "\r\n" * 32].join
34
- @socket.send packet, 0
35
- end
36
-
37
- it 'should receive some network noise' do
38
- @socket.recv(8192).should_not be_empty
39
- end
40
- end
41
- end