Libnet binding for ruby

Dave King 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
    bit-struct

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407