ffi-pcap 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. data/.gitignore +2 -1
  2. data/.pkg_ignore +25 -0
  3. data/.rspec +1 -0
  4. data/.specopts +1 -0
  5. data/.yardopts +1 -0
  6. data/{ChangeLog.rdoc → ChangeLog.md} +15 -5
  7. data/LICENSE.txt +1 -4
  8. data/README.md +92 -0
  9. data/Rakefile +30 -20
  10. data/examples/em_selectable_pcap.rb +38 -0
  11. data/examples/em_timer.rb +26 -0
  12. data/examples/ipfw_divert.rb +28 -8
  13. data/examples/print_bytes.rb +5 -1
  14. data/examples/replay.rb +11 -0
  15. data/examples/selectable_pcap.rb +29 -0
  16. data/ffi-pcap.gemspec +60 -0
  17. data/gemspec.yml +23 -0
  18. data/lib/ffi/pcap.rb +7 -13
  19. data/lib/ffi/pcap/addr.rb +16 -15
  20. data/lib/ffi/pcap/bpf_instruction.rb +25 -0
  21. data/lib/ffi/pcap/bpf_program.rb +85 -0
  22. data/lib/ffi/pcap/bsd.rb +9 -98
  23. data/lib/ffi/pcap/bsd/af.rb +18 -0
  24. data/lib/ffi/pcap/bsd/in6_addr.rb +16 -0
  25. data/lib/ffi/pcap/bsd/in_addr.rb +18 -0
  26. data/lib/ffi/pcap/bsd/sock_addr.rb +19 -0
  27. data/lib/ffi/pcap/bsd/sock_addr_dl.rb +24 -0
  28. data/lib/ffi/pcap/bsd/sock_addr_family.rb +19 -0
  29. data/lib/ffi/pcap/bsd/sock_addr_in.rb +21 -0
  30. data/lib/ffi/pcap/bsd/sock_addr_in6.rb +20 -0
  31. data/lib/ffi/pcap/bsd/typedefs.rb +7 -0
  32. data/lib/ffi/pcap/capture_wrapper.rb +296 -256
  33. data/lib/ffi/pcap/common_wrapper.rb +152 -127
  34. data/lib/ffi/pcap/copy_handler.rb +32 -32
  35. data/lib/ffi/pcap/crt.rb +7 -10
  36. data/lib/ffi/pcap/data_link.rb +178 -153
  37. data/lib/ffi/pcap/dead.rb +42 -29
  38. data/lib/ffi/pcap/dumper.rb +39 -41
  39. data/lib/ffi/pcap/error_buffer.rb +21 -36
  40. data/lib/ffi/pcap/exceptions.rb +21 -15
  41. data/lib/ffi/pcap/file_header.rb +24 -18
  42. data/lib/ffi/pcap/in_addr.rb +4 -4
  43. data/lib/ffi/pcap/interface.rb +22 -20
  44. data/lib/ffi/pcap/live.rb +296 -252
  45. data/lib/ffi/pcap/offline.rb +50 -43
  46. data/lib/ffi/pcap/packet.rb +186 -143
  47. data/lib/ffi/pcap/packet_header.rb +20 -18
  48. data/lib/ffi/pcap/pcap.rb +269 -212
  49. data/lib/ffi/pcap/stat.rb +19 -49
  50. data/lib/ffi/pcap/stat_ex.rb +42 -0
  51. data/lib/ffi/pcap/time_val.rb +52 -38
  52. data/lib/ffi/pcap/typedefs.rb +16 -20
  53. data/spec/data_link_spec.rb +39 -35
  54. data/spec/dead_spec.rb +0 -4
  55. data/spec/error_buffer_spec.rb +7 -9
  56. data/spec/file_header_spec.rb +17 -14
  57. data/spec/live_spec.rb +12 -5
  58. data/spec/offline_spec.rb +10 -11
  59. data/spec/packet_behaviors.rb +20 -6
  60. data/spec/packet_injection_spec.rb +9 -8
  61. data/spec/packet_spec.rb +22 -26
  62. data/spec/pcap_spec.rb +52 -40
  63. data/spec/spec_helper.rb +16 -5
  64. data/spec/wrapper_behaviors.rb +0 -3
  65. data/tasks/doc.rake +69 -0
  66. data/tasks/gem.rake +200 -0
  67. data/tasks/git.rake +40 -0
  68. data/tasks/post_load.rake +34 -0
  69. data/tasks/rubyforge.rake +55 -0
  70. data/tasks/setup.rb +286 -0
  71. data/tasks/spec.rake +54 -0
  72. data/tasks/svn.rake +47 -0
  73. data/tasks/test.rake +40 -0
  74. metadata +142 -92
  75. data/README.rdoc +0 -30
  76. data/VERSION +0 -1
  77. data/lib/ffi/pcap/bpf.rb +0 -106
  78. data/lib/ffi/pcap/version.rb +0 -6
  79. data/tasks/rcov.rb +0 -6
  80. data/tasks/rdoc.rb +0 -17
  81. data/tasks/spec.rb +0 -9
  82. data/tasks/yard.rb +0 -21
@@ -1,24 +1,26 @@
1
1
  module FFI
2
- module PCap
3
- # Generic per-packet information, as supplied by libpcap. This structure
4
- # is used to track only the libpcap header and just contains the timestamp
5
- # and length information used by libpcap.
6
- #
7
- # See pcap_pkthdr struct in pcap.h
8
- class PacketHeader < FFI::Struct
9
- include FFI::DRY::StructHelper
2
+ module PCap
3
+ #
4
+ # Generic per-packet information, as supplied by libpcap. This structure
5
+ # is used to track only the libpcap header and just contains the
6
+ # timestamp and length information used by libpcap.
7
+ #
8
+ # See `pcap_pkthdr` struct in `pcap.h`.
9
+ #
10
+ class PacketHeader < FFI::Struct
10
11
 
11
- dsl_layout do
12
- struct :ts, ::FFI::PCap::TimeVal, :desc => 'time stamp'
13
- field :caplen, :bpf_uint32, :desc => 'length of portion present'
14
- field :len, :bpf_uint32, :desc => 'length of packet (off wire)'
15
- end
12
+ include FFI::DRY::StructHelper
16
13
 
17
- alias timestamp ts
18
- alias captured caplen
19
- alias length len
14
+ dsl_layout do
15
+ struct :ts, ::FFI::PCap::TimeVal, :desc => 'time stamp'
16
+ field :caplen, :bpf_uint32, :desc => 'length of portion present'
17
+ field :len, :bpf_uint32, :desc => 'length of packet (off wire)'
18
+ end
20
19
 
21
- end
20
+ alias timestamp ts
21
+ alias captured caplen
22
+ alias length len
22
23
 
23
- end
24
+ end
25
+ end
24
26
  end
@@ -1,252 +1,309 @@
1
+ require 'ffi/pcap/bpf_instruction'
2
+ require 'ffi/pcap/bpf_program'
3
+
1
4
  require 'enumerator'
2
5
 
3
6
  module FFI
4
- module PCap
5
- DEFAULT_SNAPLEN = 65535 # Default snapshot length for packets
6
-
7
- attach_function :pcap_lookupdev, [:pointer], :string
8
-
9
- # Find the default device on which to capture.
10
- #
11
- # @return [String]
12
- # Name of default device
13
- #
14
- # @raise [LibError]
15
- # On failure, an exception is raised with the relevant error
16
- # message from libpcap.
17
- #
18
- def PCap.lookupdev
19
- e = ErrorBuffer.create()
20
- unless name = FFI::PCap.pcap_lookupdev(e)
21
- raise(LibError, "pcap_lookupdev(): #{e.to_s}")
22
- end
23
- return name
24
- end
7
+ module PCap
25
8
 
9
+ DEFAULT_SNAPLEN = 65535 # Default snapshot length for packets
26
10
 
27
- attach_function :pcap_lookupnet, [:string, :pointer, :pointer, :pointer], :int
28
-
29
- # Determine the IPv4 network number and mask relevant with a network
30
- # device.
31
- #
32
- # @param [String] device
33
- # The name of the device to look up.
34
- #
35
- # @yield [netp, maskp]
36
- #
37
- # @yieldparam [FFI::MemoryPointer] netp
38
- # A pointer to the network return value.
39
- #
40
- # @yieldparam [FFI::MemoryPointer] maskp
41
- # A pointer to the netmask return value.
42
- #
43
- # @return [nil, String]
44
- # The IPv4 network number and mask presented as "n.n.n.n/m.m.m.m".
45
- # nil is returned when a block is specified.
46
- #
47
- # @raise [LibError]
48
- # On failure, an exception is raised with the relevant error message
49
- # from libpcap.
50
- #
51
- def PCap.lookupnet(device)
52
- netp = FFI::MemoryPointer.new(find_type(:bpf_uint32))
53
- maskp = FFI::MemoryPointer.new(find_type(:bpf_uint32))
54
- errbuf = ErrorBuffer.create()
55
- unless FFI::PCap.pcap_lookupnet(device, netp, maskp, errbuf) == 0
56
- raise(LibError, "pcap_lookupnet(): #{errbuf.to_s}")
57
- end
58
- if block_given?
59
- yield(netp, maskp)
60
- else
61
- return( netp.get_array_of_uchar(0,4).join('.') << "/" <<
62
- maskp.get_array_of_uchar(0,4).join('.') )
11
+ attach_function :pcap_lookupdev, [:pointer], :string
12
+
13
+ #
14
+ # Find the default device on which to capture.
15
+ #
16
+ # @return [String]
17
+ # Name of default device
18
+ #
19
+ # @raise [LibError]
20
+ # On failure, an exception is raised with the relevant error
21
+ # message from libpcap.
22
+ #
23
+ def PCap.lookupdev
24
+ e = ErrorBuffer.new
25
+
26
+ unless (name = PCap.pcap_lookupdev(e))
27
+ raise(LibError,"pcap_lookupdev(): #{e}",caller)
28
+ end
29
+
30
+ return name
63
31
  end
64
- end
65
-
66
-
67
- # Opens a new Live device for capturing from the network. See Live.new()
68
- # for arguments.
69
- #
70
- # If passed a block, the block is passed to Live.new() and the Live
71
- # object is closed after completion of the block
72
- def PCap.open_live(opts={},&block)
73
- ret = Live.new(opts, &block)
74
- return block_given? ? ret.close : ret
75
- end
76
32
 
77
33
 
78
- # Opens a new Dead pcap interface for compiling filters or opening
79
- # a capture for output. See Dead.new() for arguments.
80
- def PCap.open_dead(opts={}, &block)
81
- ret = Dead.new(opts, &block)
82
- return block_given? ? ret.close : ret
83
- end
34
+ attach_function :pcap_lookupnet, [:string, :pointer, :pointer, :pointer], :int
84
35
 
36
+ #
37
+ # Determine the IPv4 network number and mask relevant with a network
38
+ # device.
39
+ #
40
+ # @param [String] device
41
+ # The name of the device to look up.
42
+ #
43
+ # @yield [netp, maskp]
44
+ #
45
+ # @yieldparam [FFI::MemoryPointer] netp
46
+ # A pointer to the network return value.
47
+ #
48
+ # @yieldparam [FFI::MemoryPointer] maskp
49
+ # A pointer to the netmask return value.
50
+ #
51
+ # @return [nil, String]
52
+ # The IPv4 network number and mask presented as `n.n.n.n/m.m.m.m`.
53
+ # `nil` is returned when a block is specified.
54
+ #
55
+ # @raise [LibError]
56
+ # On failure, an exception is raised with the relevant error message
57
+ # from libpcap.
58
+ #
59
+ def PCap.lookupnet(device)
60
+ netp = MemoryPointer.new(find_type(:bpf_uint32))
61
+ maskp = MemoryPointer.new(find_type(:bpf_uint32))
62
+ errbuf = ErrorBuffer.new
85
63
 
86
- # Opens a saved capture file for reading. See Offline.new for arguments.
87
- def PCap.open_offline(path, opts={}, &block)
88
- ret = Offline.new(path, opts={}, &block)
89
- return block_given? ? ret.close : ret
90
- end
64
+ unless PCap.pcap_lookupnet(device, netp, maskp, errbuf) == 0
65
+ raise(LibError, "pcap_lookupnet(): #{errbuf}",caller)
66
+ end
91
67
 
92
- # Same as open_offline
93
- def PCap.open_file(path, opts={}, &block)
94
- open_offline(path, opts, &block)
95
- end
68
+ if block_given?
69
+ yield netp, maskp
70
+ else
71
+ net = netp.get_array_of_uchar(0,4).join('.')
72
+ net << '/'
73
+ net << maskp.get_array_of_uchar(0,4).join('.')
96
74
 
97
- attach_function :pcap_findalldevs, [:pointer, :pointer], :int
98
- attach_function :pcap_freealldevs, [Interface], :void
99
-
100
- # List all capture devices and yield them each to a block
101
- #
102
- # @yield [dev]
103
- #
104
- # @yieldparam [Interface] dev
105
- # An Interface structure for each device.
106
- #
107
- # @return [nil]
108
- #
109
- # @raise [LibError]
110
- # On failure, an exception is raised with the relevant error
111
- # message from libpcap.
112
- #
113
- def PCap.each_device
114
- devices = ::FFI::MemoryPointer.new(:pointer)
115
- errbuf = ErrorBuffer.create()
116
-
117
- FFI::PCap.pcap_findalldevs(devices, errbuf)
118
- node = devices.get_pointer(0)
119
-
120
- if node.null?
121
- raise(LibError, "pcap_findalldevs(): #{errbuf.to_s}")
75
+ return net
76
+ end
122
77
  end
123
78
 
124
- device = Interface.new(node)
125
-
126
- while device
127
- yield(device)
128
- device = device.next
79
+ #
80
+ # Opens a new Live device for capturing from the network. See
81
+ # {Live#initialize} for arguments.
82
+ #
83
+ # If passed a block, the block is passed to {Live#initialize} and the
84
+ # {Live} object is closed after completion of the block
85
+ #
86
+ def PCap.open_live(opts={},&block)
87
+ ret = Live.new(opts, &block)
88
+ return block_given? ? ret.close : ret
129
89
  end
130
90
 
131
- FFI::PCap.pcap_freealldevs(node)
132
- return nil
133
- end
91
+ #
92
+ # Opens a new Dead pcap interface for compiling filters or opening
93
+ # a capture for output.
94
+ #
95
+ # @see Dead#initialize
96
+ #
97
+ def PCap.open_dead(opts={}, &block)
98
+ ret = Dead.new(opts, &block)
99
+ return block_given? ? ret.close : ret
100
+ end
134
101
 
102
+ #
103
+ # Opens a saved capture file for reading.
104
+ #
105
+ # @see Offline#initialize
106
+ #
107
+ def PCap.open_offline(path, opts={}, &block)
108
+ ret = Offline.new(path, opts={}, &block)
109
+ return block_given? ? ret.close : ret
110
+ end
135
111
 
136
- # Returns an array of device name and network/netmask pairs for
137
- # each interface found on the system.
138
- #
139
- # If an interface does not have an address assigned, its network/netmask
140
- # value is returned as a nil value.
141
- def PCap.dump_devices
142
- FFI::PCap.enum_for(:each_device).map do |dev|
143
- net = begin; FFI::PCap.lookupnet(dev.name); rescue LibError; end
144
- [dev.name, net]
112
+ #
113
+ # @see Pcap.open_offline
114
+ #
115
+ def PCap.open_file(path, opts={}, &block)
116
+ open_offline(path, opts, &block)
145
117
  end
146
- end
147
118
 
119
+ attach_function :pcap_findalldevs, [:pointer, :pointer], :int
120
+ attach_function :pcap_freealldevs, [Interface], :void
148
121
 
149
- # Returns an array of device names for each interface found on the system.
150
- def PCap.device_names
151
- FFI::PCap.enum_for(:each_device).map {|dev| dev.name }
152
- end
122
+ #
123
+ # List all capture devices and yield them each to a block.
124
+ #
125
+ # @yield [dev]
126
+ #
127
+ # @yieldparam [Interface] dev
128
+ # An Interface structure for each device.
129
+ #
130
+ # @return [nil]
131
+ #
132
+ # @raise [LibError]
133
+ # On failure, an exception is raised with the relevant error
134
+ # message from libpcap.
135
+ #
136
+ def PCap.each_device
137
+ devices = FFI::MemoryPointer.new(:pointer)
138
+ errbuf = ErrorBuffer.new
153
139
 
154
- attach_function :pcap_lib_version, [], :string
140
+ PCap.pcap_findalldevs(devices, errbuf)
141
+ node = devices.get_pointer(0)
155
142
 
143
+ if node.null?
144
+ raise(LibError,"pcap_findalldevs(): #{errbuf}",caller)
145
+ end
156
146
 
157
- # Get the version information for libpcap.
158
- #
159
- # @return [String]
160
- # Information about the version of the libpcap library being used;
161
- # note that it contains more information than just a version number.
162
- #
163
- def PCap.lib_version
164
- FFI::PCap.pcap_lib_version
165
- end
147
+ device = Interface.new(node)
166
148
 
149
+ while device
150
+ yield(device)
167
151
 
168
- # Extract just the version number from the lib_version string.
169
- #
170
- # @return [String]
171
- # Version number.
172
- #
173
- def PCap.lib_version_number
174
- if lib_version() =~ /libpcap version (\d+\.\d+.\d+)/
175
- return $1
176
- end
177
- end
152
+ device = device.next
153
+ end
178
154
 
155
+ PCap.pcap_freealldevs(node)
156
+ return nil
157
+ end
179
158
 
180
- # Unix Only:
181
- begin
159
+ #
160
+ # Returns an array of device name and network/netmask pairs for
161
+ # each interface found on the system.
162
+ #
163
+ # If an interface does not have an address assigned, its network/netmask
164
+ # value is returned as a nil value.
165
+ #
166
+ def PCap.dump_devices
167
+ PCap.enum_for(:each_device).map do |dev|
168
+ net = begin
169
+ PCap.lookupnet(dev.name)
170
+ rescue LibError
171
+ end
172
+
173
+ [dev.name, net]
174
+ end
175
+ end
182
176
 
183
- attach_function :pcap_get_selectable_fd, [:pcap_t], :int
177
+ #
178
+ # Returns an array of device names for each interface found on the
179
+ # system.
180
+ #
181
+ def PCap.device_names
182
+ PCap.enum_for(:each_device).map { |dev| dev.name }
183
+ end
184
184
 
185
+ attach_function :pcap_lib_version, [], :string
185
186
 
186
- # Drops privileges back to the uid of the SUDO_USER environment
187
- # variable.
188
- #
189
- # Only available on Unix.
190
187
  #
191
- # This is useful for the paranoid when sudo is used to run a
192
- # ruby pcap program as root.
188
+ # Get the version information for libpcap.
193
189
  #
194
- # This method can generally be called right after a call to
195
- # open_live() has returned a pcap handle or another privileged
196
- # call has completed. Note, however, that once privileges are
197
- # dropped, pcap functions that a require higher privilege will
198
- # no longer work.
190
+ # @return [String]
191
+ # Information about the version of the libpcap library being used;
192
+ # note that it contains more information than just a version number.
193
+ #
194
+ def PCap.lib_version
195
+ PCap.pcap_lib_version
196
+ end
197
+
199
198
  #
200
- # @raise [StandardError]
201
- # An error is raised if privileges cannot be dropped for
202
- # some reason. This may be because the SUDO_USER environment
203
- # variable is not set, because we already have a lower
204
- # privilige and the SUDO_USER id is not the current uid,
205
- # or because the SUDO_USER environment variable is not
206
- # a valid user.
199
+ # Extract just the version number from the {PCap.lib_version} string.
207
200
  #
208
- def PCap.drop_sudo_privs
209
- if ENV["SUDO_USER"] and pwent=Etc.getpwnam(ENV["SUDO_USER"])
210
- Process::Sys.setgid(pwent.gid)
211
- Process::Sys.setegid(pwent.gid)
212
- Process::Sys.setuid(pwent.uid)
213
- Process::Sys.seteuid(pwent.uid)
214
- return true if (
215
- Process::Sys.getuid == pwent.uid and
216
- Process::Sys.geteuid == pwent.uid and
217
- Process::Sys.getgid == pwent.gid and
218
- Process::Sys.getegid == pwent.gid )
201
+ # @return [String]
202
+ # Version number.
203
+ #
204
+ def PCap.lib_version_number
205
+ if (version = PCap.lib_version.match(/libpcap version (\d+\.\d+.\d+)/))
206
+ return version[1]
219
207
  end
220
- raise(StandardError, "Unable to drop privileges")
221
208
  end
222
209
 
223
- rescue FFI::NotFoundError
224
- $pcap_not_unix=true
225
- end
210
+ attach_function :pcap_compile_nopcap, [:int, :int, BPFProgram, :string, :int, :bpf_uint32], :int
211
+
212
+ attach_function :bpf_filter, [BPFInstruction, :pointer, :uint, :uint], :uint
213
+ attach_function :bpf_validate, [BPFInstruction, :int], :int
214
+ attach_function :bpf_image, [BPFInstruction, :int], :string
215
+ attach_function :bpf_dump, [BPFProgram, :int], :void
216
+ attach_function :pcap_freecode, [BPFProgram], :void
217
+
218
+
219
+ # Unix Only:
220
+ begin
221
+ attach_function :pcap_get_selectable_fd, [:pcap_t], :int
222
+
223
+ #
224
+ # Drops privileges back to the uid of the SUDO_USER environment
225
+ # variable.
226
+ #
227
+ # Only available on Unix.
228
+ #
229
+ # This is useful for the paranoid when sudo is used to run a
230
+ # ruby pcap program as root.
231
+ #
232
+ # This method can generally be called right after a call to
233
+ # open_live() has returned a pcap handle or another privileged
234
+ # call has completed. Note, however, that once privileges are
235
+ # dropped, pcap functions that a require higher privilege will
236
+ # no longer work.
237
+ #
238
+ # @raise [StandardError]
239
+ # An error is raised if privileges cannot be dropped for
240
+ # some reason. This may be because the SUDO_USER environment
241
+ # variable is not set, because we already have a lower
242
+ # privilige and the SUDO_USER id is not the current uid,
243
+ # or because the SUDO_USER environment variable is not
244
+ # a valid user.
245
+ #
246
+ def PCap.drop_sudo_privs
247
+ if ENV["SUDO_USER"]
248
+ if (pwent = Etc.getpwnam(ENV["SUDO_USER"]))
249
+ Process::Sys.setgid(pwent.gid)
250
+ Process::Sys.setegid(pwent.gid)
251
+ Process::Sys.setuid(pwent.uid)
252
+ Process::Sys.seteuid(pwent.uid)
253
+
254
+ return true if (
255
+ Process::Sys.getuid == pwent.uid and
256
+ Process::Sys.geteuid == pwent.uid and
257
+ Process::Sys.getgid == pwent.gid and
258
+ Process::Sys.getegid == pwent.gid
259
+ )
260
+ end
261
+ end
262
+
263
+ raise(StandardError,"Unable to drop privileges",caller)
264
+ end
265
+ rescue FFI::NotFoundError
266
+ $pcap_not_unix = true
267
+ end
226
268
 
227
- # Win32 only:
228
- begin
229
- attach_function :pcap_setbuff, [:pcap_t, :int], :int
230
- attach_function :pcap_setmode, [:pcap_t, :pcap_w32_modes_enum], :int
231
- attach_function :pcap_setmintocopy, [:pcap_t, :int], :int
232
- rescue FFI::NotFoundError
233
- $pcap_not_win32=true
234
- end if $pcap_not_unix
235
-
236
- # MSDOS only???:
237
- begin
238
- attach_function :pcap_stats_ex, [:pcap_t, StatEx], :int
239
- attach_function :pcap_set_wait, [:pcap_t, :pointer, :int], :void
240
- attach_function :pcap_mac_packets, [], :ulong
241
- rescue FFI::NotFoundError
242
- end if $pcap_not_win32
243
-
244
-
245
- #### XXX not sure if we even want FILE io stuff yet (or ever).
246
-
247
- #attach_function :pcap_fopen_offline, [:FILE, :pointer], :pcap_t
248
- #attach_function :pcap_file, [:pcap_t], :FILE
249
- #attach_function :pcap_dump_fopen, [:pcap_t, :FILE], :pcap_dumper_t
250
- #attach_function :pcap_fileno, [:pcap_t], :int
269
+ if $pcap_not_unix
270
+ # Win32 only:
271
+ begin
272
+ attach_function :pcap_setbuff, [:pcap_t, :int], :int
273
+ attach_function :pcap_setmode, [:pcap_t, :pcap_w32_modes_enum], :int
274
+ attach_function :pcap_setmintocopy, [:pcap_t, :int], :int
275
+ rescue FFI::NotFoundError
276
+ $pcap_not_win32 = true
277
+ end
278
+ end
279
+
280
+ if $pcap_not_win32
281
+ # MSDOS only???:
282
+ begin
283
+ attach_function :pcap_stats_ex, [:pcap_t, StatEx], :int
284
+ attach_function :pcap_set_wait, [:pcap_t, :pointer, :int], :void
285
+ attach_function :pcap_mac_packets, [], :ulong
286
+ rescue FFI::NotFoundError
287
+ end
288
+ end
289
+
290
+ attach_function :pcap_fileno, [:pcap_t], :int
291
+
292
+
293
+ ### not sure if we want FILE stuff now or ever
294
+
295
+ #attach_function :pcap_fopen_offline, [:FILE, :pointer], :pcap_t
296
+ #attach_function :pcap_file, [:pcap_t], :FILE
297
+ #attach_function :pcap_dump_fopen, [:pcap_t, :FILE], :pcap_dumper_t
298
+
299
+ # MISC functions only in 1.0.0+
300
+ # They added a very different way of creating 'live' pcap handles
301
+ attach_optional_function :pcap_create, [:string, :pointer], :pcap_t
302
+ attach_optional_function :pcap_set_snaplen, [:pcap_t, :int], :int
303
+ attach_optional_function :pcap_set_promisc, [:pcap_t, :int], :int
304
+ attach_optional_function :pcap_can_set_rfmon, [:pcap_t, :int], :int
305
+ attach_optional_function :pcap_set_timeout, [:pcap_t, :int], :int
306
+ attach_optional_function :pcap_set_buffer_size, [:pcap_t, :int], :int
307
+ attach_optional_function :activate, [:pcap_t], :int
308
+ end
251
309
  end
252
- end