class FFI::PCap::Live
Constants
- DEFAULT_TO_MS
Attributes
Public Class Methods
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.
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
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
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
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
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
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
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
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
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
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
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