ffi-pcap 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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