Module: EtherShell::ShellDsl
- Defined in:
- lib/ether_shell/shell_dsl.rb
Overview
Provides the Ethernet shell DSL.
Include this in the evaluation context where you want the Ethernet shell DSL.
Defined Under Namespace
Classes: Nothing
Class Method Summary collapse
-
.nothing ⇒ Object
:nodoc: value that doesn’t show up in irb.
-
.parse_mac_data(mac_data) ⇒ Object
:nodoc: turns a packet pattern into a string of raw bytes.
-
.parse_packet_data(packet_data) ⇒ Object
:nodoc: turns a packet pattern into a string of raw bytes.
Instance Method Summary collapse
-
#connect(eth_device, ether_type, dest_mac) ⇒ Object
Creates a Ethernet socket for this shell.
-
#disconnect ⇒ Object
Disconnects this shell’s Ethernet socket.
-
#expect(packet_data) ⇒ Object
Receives a packet and matches it against an expected value.
-
#out(packet_data) ⇒ Object
Outputs a packet.
-
#socket(high_socket) ⇒ Object
Connects this shell to a pre-created socket.
-
#verbose(true_or_false = true) ⇒ Object
Enables or disables the console output in out and expect.
Class Method Details
.nothing ⇒ Object
:nodoc: value that doesn’t show up in irb
142 143 144 |
# File 'lib/ether_shell/shell_dsl.rb', line 142 def self.nothing @nothing ||= Nothing.new end |
.parse_mac_data(mac_data) ⇒ Object
:nodoc: turns a packet pattern into a string of raw bytes
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/ether_shell/shell_dsl.rb', line 129 def self.parse_mac_data(mac_data) if mac_data.length == 12 [mac_data].pack('H*') elsif mac_data.length == 14 && mac_data[0, 2] == '0x' [mac_data[2, 12]].pack('H*') elsif mac_data.kind_of? Array mac_data.pack('C*') else mac_data end end |
.parse_packet_data(packet_data) ⇒ Object
:nodoc: turns a packet pattern into a string of raw bytes
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/ether_shell/shell_dsl.rb', line 115 def self.parse_packet_data(packet_data) if packet_data.kind_of? Array # Array of integers. packet_data.pack('C*') elsif packet_data.kind_of? String if packet_data[0, 2] == '0x' [packet_data[2..-1]].pack('H*') else packet_data end end end |
Instance Method Details
#connect(eth_device, ether_type, dest_mac) ⇒ Object
Creates a Ethernet socket for this shell.
Args:
eth_device:: an Ethernet device name, e.g. 'eth0'
ether_type:: 2-byte Ethernet packet type number
dest_mac:: MAC address of the endpoint to be tested; it can be a raw
6-byte string,
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/ether_shell/shell_dsl.rb', line 17 def connect(eth_device, ether_type, dest_mac) raise "Already connected. did you forget to call disconnect?" if @_socket mac_bytes = EtherShell::ShellDsl.parse_mac_data dest_mac @_socket = Ethernet.socket eth_device, ether_type @_socket.connect mac_bytes if @_verbose print ['Connected to ', mac_bytes.unpack('H*').first, ' using ', '%04x' % ether_type, ' via ', eth_device, "\n"].join end @_nothing = '' class <<@_nothing def inspect '' end end EtherShell::ShellDsl.nothing end |
#disconnect ⇒ Object
Disconnects this shell’s Ethernet socket.
A socket should have been connected previously, using connect or socket. The shell can take further connect and socket calls.
39 40 41 42 43 44 45 |
# File 'lib/ether_shell/shell_dsl.rb', line 39 def disconnect raise "Not connected. did you forget to call connect?" unless @_socket @_socket.close @_socket = nil print "Disconnected\n" if @_verbose EtherShell::ShellDsl.nothing end |
#expect(packet_data) ⇒ Object
Receives a packet and matches it against an expected value.
Args:
packet_data:: an Array of integers (bytes), a hex string starting with 0x,
or a string of raw bytes
Raises:
RuntimeError:: if the shell was not connected to a socket by a call to
connect or socket
RuntimeError:: if the received packet doesn't match the expected value
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/ether_shell/shell_dsl.rb', line 97 def expect(packet_data) raise "Not connected. did you forget to call connect?" unless @_socket expected_bytes = EtherShell::ShellDsl.parse_packet_data packet_data print "Receiving... " if @_verbose bytes = @_socket.recv print " #{bytes.unpack('H*').first} " if @_verbose if bytes == expected_bytes print "OK\n" if @_verbose else print "!= #{expected_bytes.unpack('H*').first} ERROR\n" if @_verbose raise EtherShell::ExpectationError, "#{bytes.unpack('H*').first} != #{expected_bytes.unpack('H*').first}" end EtherShell::ShellDsl.nothing end |
#out(packet_data) ⇒ Object
Outputs a packet.
Args:
packet_data:: an Array of integers (bytes), a hex string starting with 0x,
or a string of raw bytes
Raises:
RuntimeError:: if the shell was not connected to a socket by a call to
connect or socket
76 77 78 79 80 81 82 83 84 85 |
# File 'lib/ether_shell/shell_dsl.rb', line 76 def out(packet_data) raise "Not connected. did you forget to call connect?" unless @_socket bytes = EtherShell::ShellDsl.parse_packet_data packet_data print "Sending #{bytes.unpack('H*').first}... " if @_verbose @_socket.send bytes print "OK\n" if @_verbose EtherShell::ShellDsl.nothing end |
#socket(high_socket) ⇒ Object
Connects this shell to a pre-created socket
Args:
high_socket:: socket that behaves like an EtherShell::HighSocket
51 52 53 54 55 56 |
# File 'lib/ether_shell/shell_dsl.rb', line 51 def socket(high_socket) raise "Already connected. did you forget to call disconnect?" if @_socket @_socket = high_socket print "Connected directly to socket\n" if @_verbose EtherShell::ShellDsl.nothing end |
#verbose(true_or_false = true) ⇒ Object
62 63 64 65 |
# File 'lib/ether_shell/shell_dsl.rb', line 62 def verbose(true_or_false = true) @_verbose = true_or_false EtherShell::ShellDsl.nothing end |