Pio
Pio is a ruby gem to easily parse and generate network packets. It supports the following packet formats:
- ICMP
- ARP
- LLDP
- DHCP
- OpenFlow 1.0
- Hello
- Echo
- Features
- (…currently there are just a few formats supported but I'm sure this list will grow)
Features Overview
- Pure Ruby. No additional dependency on other external tools to parse/generate packets.
- Multi-Platform. Runs on major operating systems (recent Windows, Linux, and MacOSX).
- Clean Code. Pio is built on BinData's declarative binary format DSL so that it is easy to read and debug by human beings.
Examples
Its usage is dead simple.
ICMP
To parse an ICMP frame, use the API Pio::Icmp.read
and you can
access each field of the parsed ICMP frame.
require 'pio'
icmp = Pio::Icmp.read(binary_data)
icmp.source_mac.to_s # => '00:26:82:eb:ea:d1'
Also you can use Pio::Icmp::Request#new
or Pio::Icmp::Reply#new
to
generate an Icmp Request/Reply frame like below:
require 'pio'
request = Pio::Icmp::Request.new(
source_mac: '00:16:9d:1d:9c:c4',
destination_mac: '00:26:82:eb:ea:d1',
ip_source_address: '192.168.83.3',
ip_destination_address: '192.168.83.254'
)
request.to_binary # => ICMP Request frame in binary format.
reply = Pio::Icmp::Reply.new(
source_mac: '00:26:82:eb:ea:d1',
destination_mac: '00:16:9d:1d:9c:c4',
ip_source_address: '192.168.83.254',
ip_destination_address: '192.168.83.3',
# The ICMP Identifier and the ICMP Sequence number
# should be same as those of the request.
identifier: request.icmp_identifier,
sequence_number: request.icmp_sequence_number
)
reply.to_binary # => ICMP Reply frame in binary format.
ARP
To parse an ARP frame, use the API Pio::Arp.read
and you can access
each field of the parsed ARP frame.
require 'pio'
arp = Pio::Arp.read(binary_data)
arp.source_mac.to_s # => '00:26:82:eb:ea:d1'
Also you can use Pio::Arp::Request#new
or Pio::Arp::Reply#new
to
generate an Arp Request/Reply frame like below:
require 'pio'
request = Pio::Arp::Request.new(
source_mac: '00:26:82:eb:ea:d1',
sender_protocol_address: '192.168.83.3',
target_protocol_address: '192.168.83.254'
)
request.to_binary # => Arp Request frame in binary format.
reply = Pio::Arp::Reply.new(
source_mac: '00:16:9d:1d:9c:c4',
destination_mac: '00:26:82:eb:ea:d1',
sender_protocol_address: '192.168.83.254',
target_protocol_address: '192.168.83.3'
)
reply.to_binary # => Arp Reply frame in binary format.
LLDP
To parse an LLDP frame, use the API Pio::Lldp.read
and you can
access each field of the parsed LLDP frame.
require 'pio'
lldp = Pio::Lldp.read(binary_data)
lldp.ttl # => 120
Also you can use Pio::Lldp#new
to generate an LLDP frame like below:
require 'pio'
lldp = Pio::Lldp.new(dpid: 0x123, port_number: 12)
lldp.to_binary # => LLDP frame in binary format.
DHCP
To parse a DHCP frame, use the API Pio::Dhcp.read
and you can access
each field of the parsed DHCP frame.
require 'pio'
dhcp = Pio::Dhcp.read(binary_data)
dhcp.destination_mac.to_s # => 'ff:ff:ff:ff:ff:ff'
Also you can use Pio::Dhcp::Discover#new
,
Pio::Dhcp::Offer#new
, Pio::Dhcp::Request#new
and
Pio::Dhcp::Ack#new
to generate a DHCP frame like below:
require 'pio'
dhcp_client_mac_address = '24:db:ac:41:e5:5b'
=
{
source_mac: '00:26:82:eb:ea:d1',
destination_mac: '24:db:ac:41:e5:5b',
ip_source_address: '192.168.0.100',
ip_destination_address: '192.168.0.1'
}
# Client side
discover = Pio::Dhcp::Discover.new(source_mac: dhcp_client_mac_address)
discover.to_binary # => DHCP Discover frame in binary format
# Server side
offer = Pio::Dhcp::Offer.new(
.merge(transaction_id: discover.transaction_id))
offer.to_binary # => DHCP Offer frame in binary format
# Client side
request = Pio::Dhcp::Request.new(
source_mac: dhcp_client_mac_address,
server_identifier: [:ip_source_address],
requested_ip_address: [:ip_destination_address],
transaction_id: offer.transaction_id
)
request.to_binary # => DHCP Request frame in binary format
# Server side
ack = Pio::Dhcp::Ack.new(
.merge(transaction_id: request.transaction_id))
ack.to_binary # => DHCP Ack frame in binary format
Hello
To parse an OpenFlow 1.0 Hello message, use the API Pio::Hello.read
and you can access each field of the parsed Hello message.
require 'pio'
hello = Pio::Hello.read(binary_data)
hello.transaction_id # => 123
Also you can use Pio::Hello#new
to generate a Hello message like
below:
require 'pio'
hello = Pio::Hello.new(transaction_id: 123)
hello.to_binary # => HELLO message in binary format.
Echo
To parse an OpenFlow 1.0 Echo message, use the API Pio::Echo.read
and you can access each field of the parsed Echo message.
require 'pio'
echo = Pio::Echo.read(binary_data)
echo.xid # => 123
Also you can use Pio::Echo::Request#new
or Pio::Echo::Reply#new
to
generate an Echo Request/Reply message like below:
require 'pio'
request = Pio::Echo::Request.new
request.to_binary # => ECHO Request message in binary format.
# The ECHO xid (transaction_id)
# should be same as that of the request.
reply = Pio::Echo::Reply.new(xid: request.xid)
reply.to_binary # => ECHO Reply message in binary format.
Features
To parse an OpenFlow 1.0 Features message, use the API
Pio::Features.read
and you can access each field of the parsed
Features message.
require 'pio'
features = Pio::Features.read(binary_data)
features.xid # => 123
Also you can use Pio::Features::Request#new
or Pio::Features::Reply#new
to
generate an Features Request/Reply message like below:
require 'pio'
request = Pio::Features::Request.new
request.to_binary # => Features Request message in binary format.
# The Features xid (transaction_id)
# should be same as that of the request.
reply = Pio::Features::Reply.new(xid: request.xid,
dpid: 0x123,
n_buffers: 0x100,
n_tables: 0xfe,
capabilities: 0xc7,
actions: 0xfff)
reply.to_binary # => Features Reply message in binary format.
Installation
The simplest way to install Pio is to use Bundler.
Add Pio to your Gemfile
:
gem 'pio'
and install it by running Bundler:
prompt> bundle
Documents
Team
Contributors
https://github.com/trema/pio/contributors
Alternatives
- PacketFu: https://github.com/todb/packetfu
- Racket: http://spoofed.org/files/racket/
License
Pio is released under the GNU General Public License version 3.0: