# Pio Gem Version Build Status Code Climate Coverage Status Dependency Status Inline docs pio pencil 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: -