Parent

PCAPRUB::Pcap

Constants

DLT_AIRONET_HEADER
DLT_ARCNET
DLT_ATM_RFC1483
DLT_AX25
DLT_CHAOS
DLT_EN10MB
DLT_EN3MB
DLT_FDDI
DLT_IEEE802
DLT_IEEE802_11
DLT_IEEE802_11_RADIO
DLT_IEEE802_11_RADIO_AVS
DLT_LINUX_SLL
DLT_NULL
DLT_PPP
DLT_PPP_BSDOS
DLT_PRISM_HEADER
DLT_PRONET
DLT_RAW
DLT_SLIP
DLT_SLIP_BSDOS
PCAP_ERROR

Pcap Error Codes Error codes for the pcap API. These will all be negative, so you can check for the success or failure of a call that returns these codes by checking for a negative value.

PCAP_ERROR_ACTIVATED
PCAP_ERROR_BREAK
PCAP_ERROR_IFACE_NOT_UP
PCAP_ERROR_NOT_ACTIVATED
PCAP_ERROR_NOT_RFMON
PCAP_ERROR_NO_SUCH_DEVICE
PCAP_ERROR_PERM_DENIED
PCAP_ERROR_RFMON_NOTSUP
PCAP_NETMASK_UNKNOWN

Value to pass to pcap_compile() as the netmask if you don't know what the netmask is.

PCAP_WARNING

Warning codes for the pcap API. These will all be positive and non-zero, so they won't look like errors.

PCAP_WARNING_PROMISC_NOTSUP

Public Class Methods

lookupdev() click to toggle source

Return the name of a network device on the system.

The pcap_lookupdev subroutine gets a network device suitable for use with the pcap_open_live and the pcap_lookupnet subroutines. If no interface can be found, or none are configured to be up, Null is returned. In the case of multiple network devices attached to the system, the pcap_lookupdev subroutine returns the first one it finds to be up, other than the loopback interface. (Loopback is always ignored.)

static VALUE
rbpcap_s_lookupdev(VALUE self)
{
  char *dev = NULL;
  char eb[PCAP_ERRBUF_SIZE];
  VALUE ret_dev;  /* device string to return */
#if defined(WIN32)  /* pcap_lookupdev is broken on windows */    
  pcap_if_t *alldevs;
  pcap_if_t *d;

  /* Retrieve the device list from the local machine */
  if (pcap_findalldevs(&alldevs,eb) == -1) {
      rb_raise(eBindingError,"%s",eb);
  }

  /* Find the first interface with an address and not loopback */
  for(d = alldevs; d != NULL; d= d->next)  {
      if(d->name && d->addresses && !(d->flags & PCAP_IF_LOOPBACK)) {
          dev=d->name;
          break;
      }
  }
  
  if (dev == NULL) {
      rb_raise(eBindingError,"%s","No valid interfaces found, Make sure WinPcap is installed.\n");
  }
  ret_dev = rb_str_new2(dev);
  /* We don't need any more the device list. Free it */
  pcap_freealldevs(alldevs);
#else
  dev = pcap_lookupdev(eb);
  if (dev == NULL) {
        rb_raise(eBindingError, "%s", eb);
 }
  ret_dev = rb_str_new2(dev);
#endif
  return ret_dev;
}
lookupnet(p1) click to toggle source

Returns the network address and subnet mask for a network device.

static VALUE
rbpcap_s_lookupnet(VALUE self, VALUE dev)
{
  bpf_u_int32 net, mask, m;
  struct in_addr addr;
  char eb[PCAP_ERRBUF_SIZE];
        VALUE list;
        
  Check_Type(dev, T_STRING);
  if (pcap_lookupnet(StringValuePtr(dev), &net, &mask, eb) == -1) {
          rb_raise(rb_eRuntimeError, "%s", eb);
  }

  addr.s_addr = net;
  m = ntohl(mask);
  list = rb_ary_new();
        rb_ary_push(list, rb_str_new2((char *) inet_ntoa(addr)));
        rb_ary_push(list, UINT2NUM(m));
        return(list);
}
new() click to toggle source

Creates a new Pcap instance and returns the object itself.

static VALUE
rbpcap_new_s(VALUE class)
{
  VALUE self;
  rbpcap_t *rbp;

  // need to make destructor do a pcap_close later
  self = Data_Make_Struct(class, rbpcap_t, 0, rbpcap_free, rbp);
  rb_obj_call_init(self, 0, 0);

  memset(rbp, 0, sizeof(rbpcap_t));

  return self;
}
open_dead(linktype, snaplen) → self click to toggle source
*

open a fake Pcap for compiling filters or opening a capture for output

::Pcap.open_dead() is used for creating a pcap structure to use when calling the other functions like compiling BPF code.

  • linktype specifies the link-layer type

  • snaplen specifies the snapshot length

Returns the object itself.

static VALUE
rbpcap_open_dead_s(VALUE class, VALUE linktype, VALUE snaplen)
{
  VALUE iPcap = rb_funcall(rb_cPcap, rb_intern("new"), 0);

  return rbpcap_open_dead(iPcap, linktype, snaplen);
}
open_live(iface, snaplen, promisc, timeout) → self click to toggle source
*
capture = ::Pcap.open_live(@dev, @snaplength, @promiscous_mode, @timeout)

Returns the object itself.

static VALUE
rbpcap_open_live_s(VALUE class, VALUE iface, VALUE snaplen, VALUE promisc, VALUE timeout)
{
  VALUE iPcap = rb_funcall(rb_cPcap, rb_intern("new"), 0);
  return rbpcap_open_live(iPcap, iface, snaplen, promisc, timeout);
}
open_offline(filename) → self click to toggle source
*
capture = ::Pcap.open_offline(filename)

Returns the object itself.

static VALUE
rbpcap_open_offline_s(VALUE class, VALUE filename)
{
  VALUE iPcap = rb_funcall(rb_cPcap, rb_intern("new"), 0);

  return rbpcap_open_offline(iPcap, filename);
}
version() click to toggle source
# File lib/pcaprub/version.rb, line 13
def self.version 
  return PCAPRUB::VERSION::STRING
end

Public Instance Methods

dump(caplen, pktlen, packet) click to toggle source
*

not sure if this deviates too much from the way the rest of this class works?

Writes packet capture date to a binary file assigned with dump_open().

Returns the object itself.

static VALUE
rbpcap_dump(VALUE self, VALUE caplen, VALUE pktlen, VALUE packet)
{
  rbpcap_t *rbp;
  struct pcap_pkthdr pcap_hdr;

  if(TYPE(packet) != T_STRING)
      rb_raise(rb_eArgError, "packet data must be a string");
  if(TYPE(caplen) != T_FIXNUM)
      rb_raise(rb_eArgError, "caplen must be a fixnum");
  if(TYPE(pktlen) != T_FIXNUM)
      rb_raise(rb_eArgError, "pktlen must be a fixnum");

  Data_Get_Struct(self, rbpcap_t, rbp);
  
  gettimeofday(&pcap_hdr.ts, NULL);
  pcap_hdr.caplen = NUM2UINT(caplen);
  pcap_hdr.len = NUM2UINT(pktlen);

//capture.next is yeilding an 8Bit ASCII  string 
//  ->  return rb_str_new((char *) job.pkt, job.hdr.caplen);
//Call dump such that capture.next{|pk| capture.dump(pk.length, pk.length, pk)}

  pcap_dump( 
      (u_char*)rbp->pdt,        
      &pcap_hdr,
      (unsigned char *)RSTRING_PTR(packet)
  );

  return self;
}
dump_close() click to toggle source
*

dump_close() is called to manually close a "savefile"

static VALUE
rbpcap_dump_close(VALUE self)
{
  rbpcap_t *rbp;
  
  Data_Get_Struct(self, rbpcap_t, rbp);
  
  if(! rbpcap_ready(rbp)) return self;
  
  if(!rbp->pdt)
        rb_raise(eDumperError, "Stream is already closed.");
  
  if (rbp->pdt)
          pcap_dump_close(rbp->pdt);
          
  rbp->pdt = NULL;  

  return self;
        
}
dump_open(filename) click to toggle source
*

dump_open() is called to open a "savefile" for writing

static VALUE
rbpcap_dump_open(VALUE self, VALUE filename)
{
  rbpcap_t *rbp;

  if(TYPE(filename) != T_STRING)
     rb_raise(rb_eArgError, "filename must be a string");
      
  Data_Get_Struct(self, rbpcap_t, rbp);
  
  if(! rbpcap_ready(rbp)) return self;
  
  rbp->pdt = pcap_dump_open(
      rbp->pd,
      RSTRING_PTR(filename)
  );
  
  if(!rbp->pdt)
        rb_raise(eDumperError, "Stream could not be initialized or opened.");
  
  return self;
}
each() click to toggle source

Alias of each_data

static VALUE
rbpcap_each_data(VALUE self)
{
  rbpcap_t *rbp;
        int fno = -1;
        
  Data_Get_Struct(self, rbpcap_t, rbp);

        if(! rbpcap_ready(rbp)) return self; 
        
#if !defined(WIN32)
  fno = pcap_get_selectable_fd(rbp->pd);
#else
  fno = pcap_fileno(rbp->pd);
#endif

  for(;;) {
        VALUE packet = rbpcap_next_data(self);
        if(packet == Qnil && rbp->type == OFFLINE) break;
          packet == Qnil ? rb_thread_wait_fd(fno) : rb_yield(packet);
  }

  return self;
}
each_data() { |packet| ... } click to toggle source
*

Yields each packet from the capture to the passed-in block in turn.

static VALUE
rbpcap_each_data(VALUE self)
{
  rbpcap_t *rbp;
        int fno = -1;
        
  Data_Get_Struct(self, rbpcap_t, rbp);

        if(! rbpcap_ready(rbp)) return self; 
        
#if !defined(WIN32)
  fno = pcap_get_selectable_fd(rbp->pd);
#else
  fno = pcap_fileno(rbp->pd);
#endif

  for(;;) {
        VALUE packet = rbpcap_next_data(self);
        if(packet == Qnil && rbp->type == OFFLINE) break;
          packet == Qnil ? rb_thread_wait_fd(fno) : rb_yield(packet);
  }

  return self;
}
each_packet() { |packet| ... } click to toggle source
*

Yields a PCAP::Packet from the capture to the passed-in block in turn.

static VALUE
rbpcap_each_packet(VALUE self)
{
  rbpcap_t *rbp;
        int fno = -1;
        
  Data_Get_Struct(self, rbpcap_t, rbp);

        if(! rbpcap_ready(rbp)) return self; 
        
#if !defined(WIN32)
  fno = pcap_get_selectable_fd(rbp->pd);
#else
  fno = pcap_fileno(rbp->pd);
#endif

  for(;;) {
        VALUE packet = rbpcap_next_packet(self);
        if(packet == Qnil && rbp->type == OFFLINE) break;
          packet == Qnil ? rb_thread_wait_fd(fno) : rb_yield(packet);
  }

  return self;
}
inject(payload) click to toggle source
*

inject() transmit a raw packet through the network interface

Returns the number of bytes written on success else raise failure.

static VALUE
rbpcap_inject(VALUE self, VALUE payload)
{
  rbpcap_t *rbp;

  if(TYPE(payload) != T_STRING)
        rb_raise(rb_eArgError, "payload must be a string");

  Data_Get_Struct(self, rbpcap_t, rbp);

        if(! rbpcap_ready(rbp)) return self; 
#if defined(WIN32)   
  /* WinPcap does not have a pcap_inject call we use pcap_sendpacket, if it suceedes 
   * we simply return the amount of packets request to inject, else we fail.
   */
  if(pcap_sendpacket(rbp->pd, RSTRING_PTR(payload), RSTRING_LEN(payload)) != 0) {
        rb_raise(rb_eRuntimeError, "%s", pcap_geterr(rbp->pd));
  }
  return INT2NUM(RSTRING_LEN(payload));
#else
  return INT2NUM(pcap_inject(rbp->pd, RSTRING_PTR(payload), RSTRING_LEN(payload)));
#endif
}
next() click to toggle source

Alias of next_data

static VALUE
rbpcap_next_data(VALUE self)
{
        rbpcap_t *rbp;
        rbpcapjob_t job;
        char eb[PCAP_ERRBUF_SIZE];
        int ret;       
        
        Data_Get_Struct(self, rbpcap_t, rbp);
        
        if(! rbpcap_ready(rbp)) return self; 
        pcap_setnonblock(rbp->pd, 1, eb);

#ifdef MAKE_TRAP
        TRAP_BEG;
#endif

  // ret will contain the number of packets captured during the trap (ie one) since this is an iterator.
        ret = pcap_dispatch(rbp->pd, 1, (pcap_handler) rbpcap_handler, (u_char *)&job);

#ifdef MAKE_TRAP
        TRAP_END;
#endif

        if(rbp->type == OFFLINE && ret <= 0) 
          return Qnil;

        if(ret > 0 && job.hdr.caplen > 0)
    return rb_str_new((char *) job.pkt, job.hdr.caplen);

        return Qnil;
}
next_data() click to toggle source

*

Returns the next packet from the packet capture device.

Returns a string with the packet data.

If the next_data() is unsuccessful, Null is returned.
static VALUE
rbpcap_next_data(VALUE self)
{
        rbpcap_t *rbp;
        rbpcapjob_t job;
        char eb[PCAP_ERRBUF_SIZE];
        int ret;       
        
        Data_Get_Struct(self, rbpcap_t, rbp);
        
        if(! rbpcap_ready(rbp)) return self; 
        pcap_setnonblock(rbp->pd, 1, eb);

#ifdef MAKE_TRAP
        TRAP_BEG;
#endif

  // ret will contain the number of packets captured during the trap (ie one) since this is an iterator.
        ret = pcap_dispatch(rbp->pd, 1, (pcap_handler) rbpcap_handler, (u_char *)&job);

#ifdef MAKE_TRAP
        TRAP_END;
#endif

        if(rbp->type == OFFLINE && ret <= 0) 
          return Qnil;

        if(ret > 0 && job.hdr.caplen > 0)
    return rb_str_new((char *) job.pkt, job.hdr.caplen);

        return Qnil;
}
next_packet() click to toggle source

Returns the next packet from the packet capture device.

Returns a string with the packet data.

If the next_packet() is unsuccessful, Null is returned.

static VALUE
rbpcap_next_packet(VALUE self)
{       
        rbpcap_t *rbp;
        rbpcapjob_t job;
        char eb[PCAP_ERRBUF_SIZE];
        int ret;       
        
        rbpacket_t* rbpacket;
        
        Data_Get_Struct(self, rbpcap_t, rbp);
        
        if(! rbpcap_ready(rbp)) return self; 

        pcap_setnonblock(rbp->pd, 1, eb);

#ifdef MAKE_TRAP
        TRAP_BEG;
#endif
        
        ret = pcap_dispatch(rbp->pd, 1, (pcap_handler) rbpcap_handler, (u_char *)&job);

#ifdef MAKE_TRAP
        TRAP_END;
#endif

        if(rbp->type == OFFLINE && ret <= 0) 
          return Qnil;

        if(ret > 0 && job.hdr.caplen > 0)
    {
      rbpacket = ALLOC(rbpacket_t);
      rbpacket->hdr = &job.hdr;
      rbpacket->pkt = (u_char *)&job.pkt;
      return Data_Wrap_Struct(rb_cPkt, 0, rbpacket_free, rbpacket);
    }

        return Qnil;
}
pcap_major_version() click to toggle source
*

Returns the integer PCAP MAJOR LIBRARY value unless capture

static VALUE
rbpcap_major_version(VALUE self)
{
  rbpcap_t *rbp;

  Data_Get_Struct(self, rbpcap_t, rbp);
        
        if(! rbpcap_ready(rbp)) return self;
        
  return INT2NUM(pcap_major_version(rbp->pd));
}
pcap_minor_version() click to toggle source
*

Returns the integer PCAP MINOR LIBRARY value unless capture

static VALUE
rbpcap_minor_version(VALUE self)
{
  rbpcap_t *rbp;

  Data_Get_Struct(self, rbpcap_t, rbp);
        
        if(! rbpcap_ready(rbp)) return self;
        
  return INT2NUM(pcap_minor_version(rbp->pd));
}
setfilter(filter) click to toggle source
*

Provide a valid bpf-filter to apply to the packet capture

# Show me all SYN packets:
bpf-filter = "tcp[13] & 2 != 0"
capture.setfilter(bpf-filter)

Examples:

  • "net 10.0.0.0/8"

  • "not tcp and dst host 192.168.1.1"

Returns the object itself.

static VALUE
rbpcap_setfilter(VALUE self, VALUE filter)
{
  char eb[PCAP_ERRBUF_SIZE];
  rbpcap_t *rbp;
  u_int32_t mask = 0, netid = 0;
  struct bpf_program bpf;

  Data_Get_Struct(self, rbpcap_t, rbp);

  if(TYPE(filter) != T_STRING)
        rb_raise(eBPFilterError, "filter must be a string");

        if(! rbpcap_ready(rbp)) return self; 
        
  if(rbp->type == LIVE)
        if(pcap_lookupnet(rbp->iface, &netid, &mask, eb) < 0) {
                netid = 0;
                mask = 0;
                rb_warn("unable to get IP: %s", eb);
        }

  if(pcap_compile(rbp->pd, &bpf, RSTRING_PTR(filter), 0, mask) < 0)
        rb_raise(eBPFilterError, "invalid bpf filter");

  if(pcap_setfilter(rbp->pd, &bpf) < 0)
        rb_raise(eBPFilterError, "unable to set bpf filter");

  return self;
}
snaplen() click to toggle source

Alias of snapshot

static VALUE
rbpcap_snapshot(VALUE self)
{
  rbpcap_t *rbp;

  Data_Get_Struct(self, rbpcap_t, rbp);

        if(! rbpcap_ready(rbp)) return self;
        
  return INT2NUM(pcap_snapshot(rbp->pd));
}
snapshot() click to toggle source
*

Returns the snapshot length, which is the number of bytes to save for each packet captured.

static VALUE
rbpcap_snapshot(VALUE self)
{
  rbpcap_t *rbp;

  Data_Get_Struct(self, rbpcap_t, rbp);

        if(! rbpcap_ready(rbp)) return self;
        
  return INT2NUM(pcap_snapshot(rbp->pd));
}
stats() click to toggle source
*

Returns a hash with statistics of the packet capture

  • "recv"

    # number of packets received

  • "drop"

    # number of packets dropped

  • "idrop"

    # number of packets dropped by interface

static VALUE
rbpcap_stats(VALUE self)
{
  rbpcap_t *rbp;
  struct pcap_stat stat;
  VALUE hash;
  
  Data_Get_Struct(self, rbpcap_t, rbp);

        if(! rbpcap_ready(rbp)) return self;
                
  if (pcap_stats(rbp->pd, &stat) == -1)
        return Qnil;
        
  hash = rb_hash_new();
  rb_hash_aset(hash, rb_str_new2("recv"), UINT2NUM(stat.ps_recv));
  rb_hash_aset(hash, rb_str_new2("drop"), UINT2NUM(stat.ps_drop));
  rb_hash_aset(hash, rb_str_new2("idrop"), UINT2NUM(stat.ps_ifdrop));
  // drops by interface XXX not yet supported under pcap.h 2.4

//#if defined(WIN32)
//    rb_hash_aset(hash, rb_str_new2("bs_capt"), UINT2NUM(stat.bs_capt));
//#endif    
    
  return hash;
}

[Validate]

Generated with the Darkfish Rdoc Generator 2.