Class: FFI::PCap::CaptureWrapper
- Inherits:
-
CommonWrapper
- Object
- CommonWrapper
- FFI::PCap::CaptureWrapper
- Includes:
- Enumerable
- Defined in:
- lib/ffi/pcap/capture_wrapper.rb
Overview
A superclass for both offline and live interfaces, but not dead interfaces. This class provides all the features necessary for receiving packets through libpcap.
The loop and dispatch methods default to using a CopyHandler object
when preparing values to the callback block. This is done to safely
provide references to packets outside of the callback blocks.
See CopyHandler for more information.
Note that for performance reasons, you may not need or want to incur
the extra overhead of creating a copy for every Packet. You can supply
a nil
value for the loop handler which will simply pass volatile
references to packets directly to your block. You can also write
custom handlers which implement the receive_pcap
method and
implement custom defined behaviors.
Constant Summary collapse
- DEFAULT_COUNT =
Default packet count (-1: infinite loop)
-1
Instance Attribute Summary collapse
-
#handler ⇒ Object
Returns the value of attribute handler.
Attributes inherited from CommonWrapper
Instance Method Summary collapse
- #breakloop ⇒ Object (also: #stop)
-
#dispatch(opts = {}) {|self, pkt| ... } ⇒ Integer?
Processes packets from a live capture or savefile until cnt packets are processed, the end of the current bufferful of packets is reached when doing a live capture, the end of the savefile is reached (when reading from a savefile),
pcap_breakloop()
is called, or an error occurs. - #fileno ⇒ Object
-
#initialize(pcap, opts = {}, &block) ⇒ CaptureWrapper
constructor
Adds an extra parameter :handler for specifying a capture handler when using loop or dispatch.
-
#loop(opts = {}) {|self, pkt| ... } ⇒ Integer?
(also: #each)
Processes packets from a live capture or savefile until cnt packets are processed, the end of the savefile is reached (when reading from a savefile),
pcap_breakloop()
is called, or an error occurs. -
#next ⇒ Packet?
(also: #next_extra, #next_ex)
Reads the next packet from a pcap device and returns a success/failure indication.
-
#old_next ⇒ Object
This method uses the older
pcap_next()
function which has been deprecated in favor ofpcap_next_ex()
. - #selectable_fd ⇒ Object
- #selectable_io ⇒ Object
-
#set_filter(expression, opts = {}) ⇒ Object
(also: #setfilter, #filter=)
Used to specify a pcap filter for the pcap interface.
Methods inherited from CommonWrapper
#close, #closed?, #compile, #datalink, #geterr, #open_dump, #ready?, #snaplen, #supported_datalinks, #to_ptr
Constructor Details
#initialize(pcap, opts = {}, &block) ⇒ CaptureWrapper
Adds an extra parameter :handler for specifying a capture handler when using loop or dispatch. The handler defaults to FFI::PCap::CopyHandler, which always yields a copy of each packet to a block.
Setting :handler to nil
will pass packets directly to a block
without copying them, which may be desirable if the packets are
only ever processed within the block, and code does not need to
retain a reference to them elsewhere.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 42 def initialize(pcap, opts={}, &block) @handler = opts.fetch(handler,CopyHandler) trap('INT') do stop() close() raise(SignalException,'INT',caller) end trap('TERM') do stop() close() raise(SignalException,'TERM',caller) end super(pcap, opts, &block) end |
Instance Attribute Details
#handler ⇒ Object
Returns the value of attribute handler.
30 31 32 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 30 def handler @handler end |
Instance Method Details
#breakloop ⇒ Object Also known as: stop
Sets a flag that will force #dispatch or #loop to return rather
than looping; they will return the number of packets that have been
processed so far, or nil
if no packets have been processed so far.
breakloop does not guarantee that no further packets will be processed by #dispatch or #loop after it is called. At most one more packet may be processed.
238 239 240 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 238 def breakloop PCap.pcap_breakloop(_pcap) end |
#dispatch(opts = {}) {|self, pkt| ... } ⇒ Integer?
Processes packets from a live capture or savefile until cnt packets
are processed, the end of the current bufferful of packets is
reached when doing a live capture, the end of the savefile is
reached (when reading from a savefile), pcap_breakloop()
is called,
or an error occurs.
Thus, when doing a live capture, cnt is the maximum number of packets to process before returning, but is not a minimum number; when reading a live capture, only one bufferful of packets is read at a time, so fewer than cnt packets may be processed. A value of -1 or 0 for cnt causes all the packets received in one buffer to be processed when reading a live capture, and causes all the packets in the file to be processed when reading a savefile.
Note: In older versions of libpcap, the behavior when cnt was 0 was undefined; different platforms and devices behaved differently, so code that must work with older versions of libpcap should use -1, nor 0, as the value of cnt.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 159 def dispatch(opts={}, &block) cnt = (opts[:count] || DEFAULT_COUNT) # default to infinite loop h = opts[:handler] ret = PCap.pcap_dispatch(_pcap, cnt, _wrap_callback(h, block),nil) if ret == -1 raise(ReadError,"pcap_dispatch(): #{geterr}",caller) elsif ret -2 return nil elsif ret > -1 return ret else raise(ReadError,"unexpected return from pcap_dispatch() -> #{ret}",caller) end end |
#fileno ⇒ Object
276 277 278 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 276 def fileno PCap.pcap_fileno(_pcap) end |
#loop(opts = {}) {|self, pkt| ... } ⇒ Integer? Also known as: each
Processes packets from a live capture or savefile until cnt packets
are processed, the end of the savefile is reached (when reading
from a savefile), pcap_breakloop()
is called, or an error occurs.
It does not return when live read timeouts occur. A value of -1 or 0 for cnt is equivalent to infinity, so that packets are processed until another ending condition occurs.
(In older versions of libpcap, the behavior when cnt was 0 was undefined; different platforms and devices behaved differently, so code that must work with older versions of libpcap should use -1, nor 0, as the value of cnt.)
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 101 def loop(opts={}, &block) cnt = (opts[:count] || DEFAULT_COUNT) h = opts[:handler] ret = PCap.pcap_loop(_pcap, cnt, _wrap_callback(h, block), nil) if ret == -1 raise(ReadError,"pcap_loop(): #{geterr}",caller) elsif ret -2 return nil elsif ret > -1 return ret else raise(ReadError,"unexpected return from pcap_loop(): #{ret}",caller) end end |
#next ⇒ Packet? Also known as: next_extra, next_ex
Reads the next packet from a pcap device and returns a success/failure indication.
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 209 def next hdr_p = MemoryPointer.new(:pointer) buf_p = MemoryPointer.new(:pointer) case PCap.pcap_next_ex(_pcap, hdr_p, buf_p) when -1 # error raise(ReadError,"pcap_next_ex(): #{geterr}",caller) when 0 # live capture read timeout expired return nil when -2 # savefile packets exhausted return nil when 1 hdr = PacketHeader.new(hdr_p.get_pointer(0)) return Packet.new(hdr, buf_p.get_pointer(0)) end end |
#old_next ⇒ Object
This method uses the older pcap_next()
function which has been
deprecated in favor of pcap_next_ex()
. It is included only for
backward compatability purposes.
Important Note. According to libpcap documentation:
Unfortunately, there is no way to determine whether an error
occured or not when using pcap_next().
186 187 188 189 190 191 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 186 def old_next header = PacketHeader.new bytes = PCap.pcap_next(_pcap, header) return Packet.new(header, bytes) unless bytes.null? end |
#selectable_fd ⇒ Object
280 281 282 283 284 285 286 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 280 def selectable_fd if PCap.respond_to?(:pcap_get_selectable_fd) PCap.pcap_get_selectable_fd(pcap) else raise(NotImplementedError, "selectable pcap IO is not available for your platform") end end |
#selectable_io ⇒ Object
288 289 290 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 288 def selectable_io ::IO.new(self.selectable_fd, 'r') end |
#set_filter(expression, opts = {}) ⇒ Object Also known as: setfilter, filter=
Used to specify a pcap filter for the pcap interface. This method compiles a filter expression and applies it on the wrapped pcap interface.
259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/ffi/pcap/capture_wrapper.rb', line 259 def set_filter(expression, opts={}) code = compile(expression, opts) ret = PCap.pcap_setfilter(_pcap, code) # done with this, we can free it code.free! if ret < 0 raise(LibError, "pcap_setfilter(): #{geterr}",caller) end return expression end |