# 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](https://github.com/dmendel/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'
dhcp_server_options =
{
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(dhcp_server_options
.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: dhcp_server_options[:ip_source_address],
requested_ip_address: dhcp_server_options[:ip_destination_address],
transaction_id: offer.transaction_id
)
request.to_binary # => DHCP Request frame in binary format
# Server side
ack = Pio::Dhcp::Ack.new(dhcp_server_options
.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](http://gembundler.com/).
Add Pio to your `Gemfile`:
gem 'pio'
and install it by running Bundler:
prompt> bundle
## Documents
- [API document generated with YARD](http://rubydoc.info/github/trema/pio/frames/file/README.md)
## Team
- [Yasuhito Takamiya](https://github.com/yasuhito) ([@yasuhito](https://twitter.com/yasuhito))
- [Eishun Kondoh](https://github.com/shun159) ([@Eishun\_Kondoh](https://twitter.com/Eishun_Kondoh))
### Contributors
## Alternatives
- PacketFu:
- Racket:
## License
Pio is released under the GNU General Public License version 3.0:
-