Raw Sockets for packet sniffing

Hello,

I am trying to use, through 100% Ruby code, Linux Raw Sockets for packet
sniffing. I am using the same syscalls that I would use in C code. I am
able to inject packets through the raw socket but not to sniff packets.

Here’s my Ruby code:

class RawSocket

PF_PACKET = 17 # linux/socket.h
AF_PACKET = PF_PACKET # linux/socket.h
ETH_P_ALL = 0x00_03 # linux/if_ether.h
ETH_P_IP = 0x08_00 # linux/if_ether.h
SIOCGIFINDEX = 0x89_33 # bits/ioctls.h
SIZEOF_INT = ([0].pack ‘I’).length

def initialize(interface)
@interface = interface

@sock = nil
begin
  @sock = Socket.new(PF_PACKET, Socket::SOCK_RAW,
                     Utils.htons(ETH_P_ALL))

  # struct ifreq in net/if.h
  ifreq = [@interface].pack 'a16'
  ifreq << ( [""].pack 'a16' )
  @sock.ioctl(SIOCGIFINDEX, ifreq)

  # struct sockaddr_ll in linux/if_packet.h
  sll = [AF_PACKET].pack 'S'                    # sll_family
  sll << ( [ETH_P_ALL].pack 'S' )               # sll_protocol
  sll << ifreq[16 .. (16 + SIZEOF_INT)]  # sll_ifindex
  sll << ( [0].pack 'S' )                       # sll_hatype
  sll << ( [0].pack 'C' )                       # sll_pkttype
  sll << ( [0].pack 'C' )                       # sll_halen
  sll << ( ([0].pack 'C') * 8 )                 # sll_addr[8]
  @sock.bind sll

rescue Exception => ex
  @sock.close if @sock
  STDERR.puts "Error creating raw socket: #{ex.message}\n"
end

def send(packet_bytes)
cnt = -1
begin
cnt = @sock.write packet_bytes
@sock.flush
rescue Exception => ex
STDERR.puts “RawSocket send failed: #{ex.message}\n”
end

sent = false
if cnt == -1
  STDERR.puts "RawSocket send returned -1.\n"
elsif cnt < bytes.length
  msg << "RawSocket sent only #{cnt} bytes out of

#{packet_bytes.length}.\n"
STDERR.puts msg
else
sent = true
end

sent

end

def receive
data = nil
begin
data = (@sock.recvfrom 2048))[0]
#data = @sock.read
rescue Exception => ex
STDERR.puts “RawSockt receive failed: #{ex.class.name} |
#{ex.message}\n”
end
data
end
end

Unfortunately the “recvfrom” method never returns. Same happens using
the “read” method from the superclass IO.
Any suggestions?

Thanks