class FFI::PCap::Live

Constants

DEFAULT_TO_MS

Attributes

device[R]
direction[R]
promisc[R]
timeout[R]

Public Class Methods

new(opts=nil) { |self| ... } click to toggle source

Creates a pcap interface for capturing from the network.

@param [Hash] opts

Options are ignored and passed to the super-class except those
below.

@option opts [String, nil] :device, :dev

The device to open. On some platforms, this can be "any".
If nil or unspecified {PCap.lookupdev} is called to obtain a
default device.

@option opts [Integer] :snaplen

The snapshot length for the pcap object.
Defaults to DEFAULT_SNAPLEN

@option opts [Boolean] :promisc

Specifies if the interface is to be put into promiscuous mode.
Defaults to false.

@option opts [Integer] :timeout

Specifies the read timeout in milliseconds.
Defaults to DEFAULT_TO_MS

@return [Live]

A live wrapper.

@raise [LibError]

On failure, an exception is raised with the relevant error 
message from libpcap.

@raise [ArgumentError]

May raise an exception if a :device cannot be autodetected using 
{PCap.lookupdev} for any reason. This should never happen on
most platforms.
Calls superclass method FFI::PCap::CaptureWrapper::new
# File lib/ffi/pcap/live.rb, line 62
def initialize(opts=nil)
  opts ||= {}

  @device = (opts[:device] || opts[:dev] || PCap.lookupdev)

  unless @device
    raise(ArgumentError,"Couldn't detect a device. One must be specified",caller)
  end

  @snaplen   = opts[:snaplen] || DEFAULT_SNAPLEN
  @promisc   = opts[:promisc] ? 1 : 0
  @timeout   = opts[:timeout] || DEFAULT_TO_MS
  @direction = (opts[:direction] || opts[:dir])

  @errbuf = ErrorBuffer.new
  @pcap   = PCap.pcap_open_live(@device, @snaplen, @promisc, @timeout, @errbuf)

  if @pcap.null?
    raise(LibError, "pcap_open_live(): #{@errbuf}",caller)
  end

  # call super to get all our ducks in a row
  super(@pcap, opts)

  set_direction(@direction) if @direction

  # Cache network and netmask from pcap_lookupdev.
  # These pointers may be used internally (and should get autoreleased)
  @netp, @maskp = nil
  begin
    PCap.lookupnet(@device) do |netp, maskp|
      @netp = netp
      @maskp = maskp
    end
  rescue LibError
    warn "Warning: #{$!}"
  end

  yield self if block_given?
end

Public Instance Methods

direction=(dir)
Alias for: set_direction
inject(pkt) click to toggle source

Transmit a packet using pcap_inject()

(not available on all platforms)

@param [Packet, String] obj

The packet to send. This can be a Packet or String object.

@return [Integer]

The number of bytes sent.

@raise [ArgumentError]

An exception is raised if the pkt object type is incorrect or
if it is a Packet and the body pointer is null.

@raise [LibError]

On failure, an exception is raised with the relevant libpcap
error message.

@raise [NotImplementedError]

If the pcap_inject() function is not available from your libpcap
library pcap_sendpacket will be tried, if both are missing, this 
exception will be raised.
# File lib/ffi/pcap/live.rb, line 255
def inject(pkt)
  if @@have_inject
    if pkt.kind_of?(Packet)
      len = pkt.caplen
      bufp = pkt.body_ptr

      if bufp.null?
        raise(ArgumentError,"packet data null pointer",caller)
      end
    elsif pkt.kind_of?(String)
      len = pkt.size
      bufp = FFI::MemoryPointer.from_string(pkt)
    else
      raise(ArgumentError,"Don't know how to inject #{pkt.class}",caller)
    end

    sent = PCap.pcap_inject(_pcap, bufp, len)

    if sent < 0
      raise(LibError,"pcap_inject(): #{geterr}",caller)
    end

    return sent
  else 
    # fake it with sendpacket on windows
    if sendpacket(pkt)
      return (Packet === pkt) ? pkt.caplen : pkt.size
    end
  end
end
netmask() click to toggle source

Returns the dotted notation string for the IPv4 netmask for the device used by this pcap interface.

# File lib/ffi/pcap/live.rb, line 117
def netmask
  if @maskp
    @netmask ||= @maskp.get_array_of_uchar(0,4).join('.')
  end
end
netmask_n32() click to toggle source

Returns the 32-bit numeric representation of the IPv4 network address for this device.

# File lib/ffi/pcap/live.rb, line 137
def netmask_n32
  if @maskp
    ::FFI::DRY::NetEndian.ntohl(@maskp.get_uint32(0))
  end
end
network() click to toggle source

Returns the dotted notation string for the IPv4 network address for the device used by this pcap interface.

# File lib/ffi/pcap/live.rb, line 107
def network
  if @netp
    @network ||= @netp.get_array_of_uchar(0,4).join('.')
  end
end
network_n32() click to toggle source

Returns the 32-bit numeric representation of the IPv4 network address for this device.

# File lib/ffi/pcap/live.rb, line 127
def network_n32
  if @netp
    ::FFI::DRY::NetEndian.ntohl(@netp.get_uint32(0))
  end
end
non_blocking() click to toggle source

get the state of non-blocking mode on a capture device

@return [Boolean]

non-blocking mode

@raise [LibError]

On failure, an exception is raised with the relevant error
message from libpcap.
# File lib/ffi/pcap/live.rb, line 198
def non_blocking
  mode = PCap.pcap_getnonblock(_pcap, @errbuf)

  if mode == -1
    raise(LibError,"pcap_getnonblock(): #{@errbuf}",caller)
  else
    return mode == 1
  end
end
Also aliased as: non_blocking?
non_blocking=(mode)
Alias for: set_non_blocking
non_blocking?()
Alias for: non_blocking
nonblocking=(mode)
Alias for: set_non_blocking
send_packet(pkt)
Alias for: sendpacket
sendpacket(pkt) click to toggle source

Transmit a packet using pcap_sendpacket()

(not available on all platforms)

@param [Packet, String] obj

The packet to send. This can be a Packet or String object.

@return [True]

True is returned on success. Otherwise an exception is raised.

@raise [ArgumentError]

An exception is raised if the pkt object type is incorrect or
if it is a Packet and the body pointer is null.

@raise [LibError]

On failure, an exception is raised with the relevant libpcap
error message.

@raise [NotImplementedError]

If the pcap_sendpacket() function is not available from your
libpcap library this exception will be raised.
# File lib/ffi/pcap/live.rb, line 311
def sendpacket(pkt)
  unless @@have_sendpacket
    raise(NotImplementedError,"packet injectors are not avaiable from your pcap library",caller)
  end

  if pkt.kind_of? Packet
    len = pkt.caplen
    bufp = pkt.body_ptr

    if bufp.null?
      raise(ArgumentError,"packet data null pointer",caller)
    end
  elsif pkt.kind_of? String
    len = pkt.size
    bufp = FFI::MemoryPointer.from_string(pkt)
  else
    raise(ArgumentError,"Don't know how to send #{pkt.class}",caller)
  end

  if PCap.pcap_sendpacket(_pcap, bufp, len) != 0
    raise(LibError,"pcap_sendpacket(): #{geterr}",caller)
  end

  return true
end
Also aliased as: send_packet
set_direction(dir) click to toggle source

Sets the direction for which packets will be captured.

(Not supported on all platforms)

# File lib/ffi/pcap/live.rb, line 150
def set_direction(dir)
  unless @@have_setdirection
    raise(NotImplementedError,"pcap_setdirection() is not avaiable from your pcap library",caller) 
  end

  dirs = PCap.enum_type(:pcap_direction_t)

  if PCap.pcap_setdirection(_pcap, dirs[:"pcap_d_#{dir}"]) == 0
    return true
  else
    raise(LibError,"pcap_setdirection(): #{geterr}",caller)
  end
end
Also aliased as: direction=
set_non_blocking(mode) click to toggle source

set the state of non-blocking mode on a capture device

@param [Boolean] mode

@raise [LibError]

On failure, an exception is raised with the relevant error
message from libpcap.
# File lib/ffi/pcap/live.rb, line 175
def set_non_blocking(mode)
  mode =  mode ? 1 : 0

  if PCap.pcap_setnonblock(_pcap, mode, @errbuf) == 0
    return (mode == 1)
  else
    raise(LibError,"pcap_setnonblock(): #{@errbuf}",caller)
  end
end
Also aliased as: non_blocking=, nonblocking=
stats() click to toggle source

Get capture statistics

@return [Stats]

@raise [LibError]

On failure, an exception is raised with the relevant error
message from libpcap.
# File lib/ffi/pcap/live.rb, line 219
def stats
  stats = Stat.new

  unless PCap.pcap_stats(_pcap, stats) == 0
    raise(LibError,"pcap_stats(): #{geterr}",caller)
  end

  return stats
end