# Re: libnet binding for ruby

**URL:** <https://www.ruby-forum.com/t/re-libnet-binding-for-ruby/101152>\
**Category:** Ruby\
**Created:** [February 4, 2006, 11:35pm UTC](https://www.ruby-forum.com/t/re-libnet-binding-for-ruby/101152 "2006-02-04T23:35:58Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e19b73/32.png) [@Joel\_VanderWerf](https://www.ruby-forum.com/u/Joel_VanderWerf)\
**Post date:** [February 4, 2006, 11:35pm UTC](https://www.ruby-forum.com/t/re-libnet-binding-for-ruby/101152/1 "2006-02-04T23:35:58Z")

</div>

Dave K. wrote:

> I was hoping to be able to build raw packets in ruby. I’ve found and  
> have a working pcap binding. Is there a working libnet binding out there?

I don’t know libnet (except what I just read on the website) but if you  
just want to fill in raw IP packets and send them, you can do that in  
ruby with the socket lib and with Array#pack.

I wrote an object-oriented wrapper around #pack and #unpack called  
bit-struct[1]. It lets you define packet structure and construct packets  
like so:

=== ip.rb ===  
require ‘bit-struct’

class IP \< BitStruct  
unsigned :ip\_v, 4, “Version”  
unsigned :ip\_hl, 4, “Header length”  
unsigned :ip\_tos, 8, “TOS”  
unsigned :ip\_len, 16, “Length”  
unsigned :ip\_id, 16, “ID”  
unsigned :ip\_off, 16, “Frag offset”  
unsigned :ip\_ttl, 8, “TTL”  
unsigned :ip\_p, 8, “Protocol”  
unsigned :ip\_sum, 16, “Checksum”  
octets :ip\_src, 32, “Source addr”  
octets :ip\_dst, 32, “Dest addr”  
rest :body, “Body of message”

note " rest is application defined message body"

initial\_value.ip\_v = 4  
initial\_value.ip\_hl = 5  
end

# ip = IP.new ip.ip\_tos = 0 ip.ip\_len = 0 ip.ip\_id = 0 ip.ip\_off = 0 ip.ip\_ttl = 255 ip.ip\_p = 255 ip.ip\_sum = 0 ip.ip\_src = “192.168.1.4” ip.ip\_dst = “192.168.1.255” ip.body = “This is the payload text.” ip.ip\_len = ip.length

And here is some code to receive ping (ICMP) packets using a raw IP  
socket. Sending would be similar.

=== ping-recv.rb ===  
require “socket”  
require “./ip” # the file above

# Example of using the IP class to receive ping (ICMP) messages.

begin  
rsock = Socket.open(Socket::PF\_INET, Socket::SOCK\_RAW,  
Socket::IPPROTO\_ICMP)  
rescue Errno::EPERM  
$stderr.puts “Must run #{$0} as root.”  
exit!  
end

Thread.new do  
loop do  
data, sender = rsock.recvfrom(8192)  
port, host = Socket.unpack\_sockaddr\_in(sender)  
puts “-”\*80,  
“packet received from #{host}:#{port}:”,  
IP.new(data).inspect\_detailed,  
“-”\*80  
$stdout.flush  
end  
end

# system “ping 127.0.0.1”

Sample output:

## 64 bytes from 127.0.0.1: icmp\_seq=8 ttl=64 time=0.045 ms

packet received from 127.0.0.1:62400:  
IP:  
Version = 4  
Header length = 5  
TOS = 0  
Length = 84  
ID = 41868  
Frag offset = 0  
TTL = 64  
Protocol = 1  
Checksum = 55578  
Source addr = “127.0.0.1”  
Dest addr = “127.0.0.1”  
Body of message =  
“\000\000n\030/\<\000\010\365\*\345C\2301\005\000\010\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\e\034\035\036\037  
!"#$%&'()\*+,-./01234567”  
.  
.  
.

(One could of course define more fields, based on ICMP, to make this  
body data more intelligible.)

–  
[1] [BitStruct](http://redshift.sourceforge.net/bit-struct)  
[bit-struct](http://redshift.sourceforge.net/bit-struct/doc/index.html)
