From: Joel VanderWerf Date: 2006-02-05T07:33:56+09:00 Subject: Re: 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] http://redshift.sourceforge.net/bit-struct http://redshift.sourceforge.net/bit-struct/doc/index.html -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407