tags:

views:

22

answers:

1

I am having difficulty setting up a struct from the pcap library in FFI.

Struct:

struct pcap_if {
struct pcap_if *next;
char *name;        
char *description;    
struct pcap_addr *addresses;
bpf_u_int32 flags;    
};

The relevant Ruby code

module Pcap
extend FFI::Library
ffi_lib 'pcap'

attach_function :pcap_findalldevs,[:pointer,:string],:int

class Pcap_if < FFI::Struct
layout :next,:pointer,
   :name,:string,
   :description,:string,
   :pcap_addr,:pointer,
   :flags,:int
end
end

Above attached function definition

int    pcap_findalldevs(pcap_if_t **, char *)

The test code(run as root)

tmp=''
ptr = FFI::MemoryPointer.new :pointer
res = Pcap.pcap_findalldevs ptr,tmp
devs = Pcap::Pcap_if.new ptr
puts res
puts devs.offsets
puts devs[:name]

The output is

0 #pcap_findalldevs return success
next
0
name
4
description
8
pcap_addr
12
flags
16
pcap.rb:29:in `[]': Memory access offset=4 size=4 is out of bounds (IndexError)

The offsets look right to me but my C is very rusty. I was expecting 2 devices: lo and eth0 as names.

A: 

I found the solution. FFI can't deal with pcap_if_t **. I wrote a C function to return just an array of structs.

pcap_if_t* find_devs()
{
   pcap_if_t *devs; 
   char errbuf[PCAP_ERRBUF_SIZE];
   int res;
   res=pcap_findalldevs(&devs, errbuf); 
   return devs;
 }

I still need to handle error cases, but this does work.