fluent-plugin-netflowipfix 1.0.2 → 1.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4d367541e96f10fe8e2a3746029b5400606addc2
4
- data.tar.gz: 2c9d9cf3e5e73b608997468f6841e593acab2bb1
3
+ metadata.gz: '069c7af312866b4319eaa05bbf3a85b21dbe7284'
4
+ data.tar.gz: 347842300a58938ced6d12a552df6df416a74765
5
5
  SHA512:
6
- metadata.gz: 2ab9ec4274282f2ffd07adba1004dc9269a628e6a1256e2e9fbc2b8e66d829b532ed6174712df58c5fc264a18bf8399159ce57ff7034c39c47ad5488367f404f
7
- data.tar.gz: c4566318627dcd6a0181175912ea91f588a0a439587c10655c83cb44db09ed7d26acab539545df34f8d04c4daedd4ff49d829684af49c29eb35fc93f86cbccd9
6
+ metadata.gz: 5319acf004e86e279528485faa5ad760acaeb4b2a970aed0551a399ff34ef5b9a9692d3efd4c88072b65a76692ad96f46b19d1e84a8ede30cdce611d261cd16d
7
+ data.tar.gz: df25aa1db4ba2990a1428d99f9072c1c8f7ddd21fa9838d314d9acb218bfcd04808c9d129cc3be140508b8cf63f21550f1bffb41c6d49626f84ad5c711f4c622
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "fluent-plugin-netflowipfix"
6
- spec.version = "1.0.2"
6
+ spec.version = "1.1.0"
7
7
  spec.authors = ["Yves Desharnaus"]
8
8
  spec.email = ["yvesbd@gmail.com"]
9
9
 
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2018 Yves Desharnais
2
+ # Copyright 2018-2019 Yves Desharnais
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -13,149 +13,291 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+
17
+ require "socket"
16
18
  require "fluent/plugin/input"
17
- require 'cool.io'
18
- require 'fluent/plugin/socket_util'
19
- # require_relative 'parser_netflowipfix'
19
+
20
20
  require_relative 'parser_netflow_v5'
21
21
  require_relative 'parser_netflow_v9'
22
22
  require_relative 'netflowipfix_records'
23
23
  require_relative 'vash'
24
24
 
25
+
25
26
  module Fluent
26
- module Plugin
27
- class NetflowipfixInput < Fluent::Plugin::Input
28
- Fluent::Plugin.register_input("netflowipfix", self)
29
-
30
- config_param :cache_ttl, :integer, default: 4000
31
- config_param :definitions, :string, default: nil
32
-
33
- config_param :debug, :bool, default: false
34
- config_param :port, :integer, default: 5140
35
- config_param :bind, :string, default: '0.0.0.0'
36
- config_param :tag, :string
37
- config_param :protocol_type, default: :udp do |val|
38
- case val.downcase
39
- when 'udp'
40
- :udp
41
- else
42
- raise ConfigError, "netflow input protocol type should be 'udp'"
43
- end
44
- end # config_param :protocol_type
45
-
46
- def configure(conf)
47
- super
48
- @nbpackets = 0
49
- @parser_v5 = ParserNetflowv5.new
50
- @parser_v9 = ParserNetflowv9.new
51
- @parser_v9.configure(@cache_ttl, @definitions)
52
- @parser_v10 = ParserIPfixv10.new
53
- @parser_v10.configure(@cache_ttl, @definitions)
54
- end # def configure
55
-
56
- def start
57
- @loop = Coolio::Loop.new
58
- @handler = listen(method(:receive_data))
59
- @loop.attach(@handler)
60
- @thread = Thread.new(&method(:run))
61
- end # def start
62
-
63
- def shutdown
64
- @loop.watchers.each { |w| w.detach }
65
- @loop.stop
66
- @handler.close
67
- @thread.join
68
- end # def shutdown
69
-
70
- def run
71
- @loop.run
72
- rescue => e
73
- log.error "unexpected error", error_class: e.class, error: e.message
74
- log.error_backtrace
75
- end # def run
76
-
77
- protected
78
-
79
- def receive_data(host, data)
80
- # if (@debug)
81
- # log.on_debug { log.debug "received logs", :host => host, :data => data }
82
- call(data, host) { |time, record|
83
- unless time && record
84
- log.warn "pattern not match: #{data.inspect}"
85
- return
27
+ module Plugin
28
+ class NetflowipfixInput < Fluent::Plugin::Input
29
+ Fluent::Plugin.register_input("netflowipfix", self)
30
+ include DetachMultiProcessMixin
31
+
32
+ class PortConnection
33
+ def initialize(bind, port, tag, cache_ttl, definitions, queuesleep)
34
+ @bind = bind
35
+ @port = port
36
+ @tag = tag
37
+ @cache_ttl = cache_ttl
38
+ @definitions = definitions
39
+ @eventQueue = Queue.new
40
+ @udpQueue = Queue.new
41
+ @queuesleep = queuesleep
42
+ end
43
+
44
+ def bind
45
+ @bind
46
+ end
47
+ def port
48
+ @port
49
+ end
50
+ def tag
51
+ @tag
52
+ end
53
+
54
+ def start
55
+ @thread_udp = UdpListenerThread.new(@bind, @port, @udpQueue, @tag)
56
+ @thread_parser = ParserThread.new(@udpQueue, @queuesleep, @eventQueue, @cache_ttl, @definitions)
57
+ @thread_udp.start
58
+ @thread_parser.start
59
+ end # def start
60
+ def stop
61
+ @thread_udp.close
62
+ @thread_udp.join
63
+ @thread_parser.close
64
+ @thread_parser.join
65
+ end # def stop
66
+
67
+ def event_pop
68
+ @eventQueue.pop
69
+ end
70
+
71
+ def event_queue_length
72
+ @eventQueue.length
73
+ end
74
+
75
+
76
+ # def udpqueue_pop
77
+ # @udpQueue.pop
78
+ # end
79
+
80
+ # def udpqueue_length
81
+ # @udpQueue.length
82
+ # end
83
+ end #class PortConnection
84
+
85
+ config_param :tag, :string
86
+ config_param :port, :integer, default: nil
87
+ config_param :bind, :string, :default => '0.0.0.0'
88
+ config_param :queuesleep, :integer, default: 10
89
+
90
+ def configure(conf)
91
+ super
92
+ $log.debug "NetflowipfixInput::configure: #{@bind}:#{@port}"
93
+ @@connections ||= {}
94
+ if @@connections.nil?
95
+ end
96
+ @@connections[@port] = PortConnection.new(@bind, @port, @tag, @cache_ttl, @definitions, @queuesleep)
97
+ log.debug "NetflowipfixInput::configure NB=#{@@connections.length}"
98
+ @total = 0
99
+ end
100
+
101
+ def start
102
+ super
103
+
104
+ $log.debug "NetflowipfixInput::start NB=#{@@connections.length}"
105
+ if @@connections.nil?
106
+ else
107
+ @@connections.each do | port, conn |
108
+ $log.debug "start listening UDP on #{conn.bind}:#{conn.port}"
109
+ conn.start
86
110
  end
111
+ end
112
+
113
+
114
+ # @eventQueue = Queue.new
115
+ # @udpQueue = Queue.new
116
+ # @thread_udp = UdpListenerThread.new(@bind, @port, @udpQueue)
117
+ # @thread_parser = ParserThread.new(@udpQueue, @queuesleep, @eventQueue, @cache_ttl, @definitions)
118
+ # @thread_udp.start
119
+ # @thread_parser.start
120
+ waitForEvents
121
+ end
87
122
 
88
- # if (@debug) log.info "ready to emit ", time:time, tag:@tag
89
-
90
- record['host'] = host
91
- router.emit(@tag, EventTime.new(time), record)
92
- } # call
93
- rescue => e
94
- log.warn "unexpected error on parsing", data: data.dump, error_class: e.class, error: e.message
95
- log.warn_backtrace
96
- end # def receive_data
97
-
98
- private
99
-
100
- def listen(callback)
101
- log.info "listening netflow socket on #{@bind}:#{@port} with #{@protocol_type}"
102
- if @protocol_type == :udp
103
- @usock = SocketUtil.create_udp_socket(@bind)
104
- @usock.bind(@bind, @port)
105
- UdpHandler.new(@usock, callback)
106
- else
107
- Coolio::TCPServer.new(@bind, @port, TcpHandler, log, callback)
123
+ def shutdown
124
+ super
125
+ $log.debug "NetflowipfixInput::shutdown NB=#{@@connections.length}"
126
+ if @@connections.nil?
127
+ else
128
+ # $log.debug "listening UDP on #{@bind}:#{@port}"
129
+ # @connections[@port].stop
130
+ @@connections.each do | port, conn |
131
+ $log.debug "shutdown listening UDP on #{conn.bind}:#{conn.port}"
132
+ conn.stop
108
133
  end
109
- end # def listen
110
-
111
- def call(payload, host=nil, &block)
134
+ @@connections = nil
135
+ end
136
+
137
+ # @thread_udp.close
138
+ # @thread_udp.join
139
+ # @thread_parser.close
140
+ # @thread_parser.join
141
+ end
142
+
143
+
144
+ def waitForEvents
145
+ # puts "Main::run begin #{@eventQueue.length}"
146
+ loop do
147
+ @@connections.each do | port, conn |
148
+ if (conn.event_queue_length > 0)
149
+ $log.debug "waitForEvents: #{conn.bind}:#{conn.port}"
150
+ ar = conn.event_pop
151
+ time = ar[0]
152
+ record = ar[1]
153
+ router.emit(conn.tag, EventTime.new(time.to_i), record)
154
+ end
155
+ end
156
+ sleep(@queuesleep)
157
+
158
+ # if @eventQueue.length > 0
159
+
160
+
161
+ # ar = @eventQueue.pop
162
+ # time = ar[0]
163
+ # record = ar[1]
164
+ # router.emit(@tag, EventTime.new(time.to_i), record)
165
+
166
+
167
+ # puts "Main::pop before #{@eventQueue.length} #{@tag} #{time}" # #{record.to_s}"
168
+ # puts "Main::pop after #{@eventQueue.length}"
169
+ # else
170
+ # end
171
+ end
172
+ # puts "Main::run end #{@eventQueue.length}"
173
+
174
+ end
175
+
176
+ private
177
+
178
+
179
+ class UdpListenerThread
180
+
181
+ def initialize(bind, port, udpQueue, tag)
182
+ @port = port
183
+ @udpQueue = udpQueue
184
+ @udp_socket = UDPSocket.new
185
+ @udp_socket.bind(bind, port)
186
+ @total = 0
187
+ @tag = tag
188
+ end
189
+
190
+ def start
191
+ @thread = Thread.new(&method(:run))
192
+ puts "UdpListenerThread::start"
193
+ end
194
+
195
+ def close
196
+ @udp_socket.close
197
+ end
198
+
199
+ def join
200
+ @thread.join
201
+ end
202
+
203
+
204
+ def run
205
+ loop do
206
+ msg, sender = @udp_socket.recvfrom(4096)
207
+ @total = @total + msg.length
208
+ # puts "UdpListenerThread::recvfrom #{msg.length} bytes for #{@total} total on UDP/#{@port}"
209
+ # log.debug "Received #{msg.length} bytes for #{@total} total"
210
+ record = {}
211
+ record["message"] = msg
212
+ record["length"] = msg.length
213
+ record["total"] = @total
214
+ record["sender"] = sender
215
+ record["port"] = @port
216
+ # time = EventTime.new()
217
+ time = Time.now.getutc
218
+ # router.emit(@tag, EventTime.new(), record)
219
+ @udpQueue << [time, record]
220
+ end
221
+ end
222
+ end # class UdpListenerThread
223
+
224
+ class ParserThread
225
+ def initialize(udpQueue, queuesleep, eventQueue, cache_ttl, definitions)
226
+ @udpQueue = udpQueue
227
+ @queuesleep = queuesleep
228
+ @eventQueue = eventQueue
229
+
230
+ @parser_v5 = NetflowipfixInput::ParserNetflowv5.new
231
+ @parser_v9 = NetflowipfixInput::ParserNetflowv9.new
232
+ @parser_v10 = NetflowipfixInput::ParserIPfixv10.new
233
+
234
+ @parser_v9.configure(cache_ttl, definitions)
235
+ @parser_v10.configure(cache_ttl, definitions)
236
+ end
237
+ def start
238
+ @thread = Thread.new(&method(:run))
239
+ puts "ParserThread::start"
240
+ end
241
+
242
+ def close
243
+ end
244
+
245
+ def join
246
+ @thread.join
247
+ end
248
+
249
+ def run
250
+ # puts "ParserThread::run start #{@udpQueue.length}"
251
+
252
+ loop do
253
+ if @udpQueue.length == 0
254
+ # puts "ParserThread::run sleep #{@queuesleep}"
255
+ sleep(@queuesleep)
256
+
257
+ else
258
+ block = method(:emit)
259
+ #block = nil
260
+ ar = @udpQueue.pop
261
+ time = ar[0]
262
+ msg = ar[1]
263
+ payload = msg["message"]
264
+ host = msg["sender"]
265
+
112
266
  version,_ = payload[0,2].unpack('n')
113
- @nbpackets += 1
114
- # nb = @nbpackets
115
- if (@debug)
116
- log.debug "Packet #{@nbpackets} with version #{version}"
117
- end
267
+ # puts "ParserThread::pop #{@udpQueue.length} v#{version}"
268
+
269
+
118
270
  case version
119
271
  when 5
120
- packet = Netflow5Packet.read(payload)
272
+ packet = NetflowipfixInput::Netflow5Packet.read(payload)
121
273
  @parser_v5.handle_v5(host, packet, block)
122
274
  when 9
123
- packet = Netflow9Packet.read(payload)
275
+ packet = NetflowipfixInput::Netflow9Packet.read(payload)
124
276
  @parser_v9.handle_v9(host, packet, block)
125
277
  when 10
126
- packet = Netflow10Packet.read(payload)
278
+ packet = NetflowipfixInput::Netflow10Packet.read(payload)
127
279
  @parser_v10.handle_v10(host, packet, block)
128
280
  else
129
- $log.warn "Unsupported Netflow version v#{version}: #{version.class}"
281
+ # $log.warn "Unsupported Netflow version v#{version}: #{version.class}"
130
282
  end # case
131
- end # def call
132
-
133
- end # class NetflowipfixInput
134
283
 
135
- class UdpHandler < Coolio::IO
136
- def initialize(io, callback)
137
- super(io)
138
- @io = io
139
- @callback = callback
140
- end # def initialize
284
+ # parent_call(time, record)
285
+ # @eventQueue << [time, record]
286
+ end
287
+ end # loop do
288
+ end # def run
289
+ def emit(time, event, host = nil)
290
+ if !host.nil?
291
+ event["host"] = host
292
+ end
293
+ @eventQueue << [time, event]
294
+ # puts "ParserThread::emit #{@eventQueue.length}"
295
+ end # def emit
141
296
 
142
- def on_readable
143
- msg, addr = @io.recvfrom_nonblock(4096)
144
- @callback.call(addr[3], msg)
145
- rescue => e
146
- log.error "unexpected error on reading from socket", error_class: e.class, error: e.message
147
- log.error_backtrace
148
- end # def on_readable
149
- end # class UdpHandler
297
+ end # class ParserThread
150
298
 
151
299
 
152
- end # module Plugin
300
+ end # class DnsCacheOuput
301
+ end # module Plugin
153
302
  end # module Fluent
154
303
 
155
-
156
-
157
-
158
-
159
-
160
- =begin
161
- =end
@@ -71,7 +71,6 @@ module Fluent
71
71
 
72
72
 
73
73
 
74
-
75
74
  def handle_v5(host, packet, block)
76
75
  packet.records.each do |flowset|
77
76
  # handle_flowset_data(host, packet, flowset, block, null, null)
@@ -111,7 +110,7 @@ module Fluent
111
110
  end # unless
112
111
 
113
112
  time = Time.at(packet.unix_sec, packet.unix_nsec / 1000).to_i # TODO: Fluent::EventTime
114
- block.call(time, record)
113
+ block.call(time, record, host)
115
114
  end # do flowset
116
115
  end # def handle_v5
117
116
 
@@ -219,7 +219,13 @@ module Fluent
219
219
  # end
220
220
  #end
221
221
 
222
- block.call(time, event)
222
+ # block.call(time, event)
223
+ # if (defined?(block)).nil?
224
+ # log.error "*** handle_flowset_data block is blank"
225
+ # else
226
+ # end
227
+ block.call(time, event, host)
228
+
223
229
  end # fields = array.read
224
230
  end # def handle_flowset_data
225
231
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-netflowipfix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yves Desharnaus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-08 00:00:00.000000000 Z
11
+ date: 2019-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake