fluent-plugin-sflow 0.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.
@@ -0,0 +1,10 @@
1
+ require 'bindata'
2
+ require 'eventmachine'
3
+ require 'yaml'
4
+
5
+ dir = File.expand_path(File.join(File.dirname(__FILE__), 'sflow'))
6
+ ['config','models/ipv4header', 'models/tcpheader', 'models/udpheader', 'models/protocol', 'models/binary_models','parsers/parsers','storage/storage', 'collector','snmp/iface_names'].each do |req|
7
+ require File.join(dir, req)
8
+ end
9
+
10
+ Process.daemon(true) if $daemonize == true
@@ -0,0 +1,69 @@
1
+ class SflowCollector
2
+ module Collector
3
+ Thread.abort_on_exception=true
4
+ require 'socket'
5
+ def post_init
6
+ puts "Server listening."
7
+ end
8
+
9
+ def receive_data(data)
10
+ operation = proc do
11
+ begin
12
+ if data != nil
13
+ sflow = SflowParser.parse_packet(data)
14
+ end
15
+ rescue Exception => e
16
+ puts Time.now
17
+ puts sflow.inspect
18
+ puts e.message
19
+ puts e.backtrace
20
+ end
21
+ end
22
+
23
+ callback = proc do |sflow|
24
+ begin
25
+ if sflow != nil
26
+ SflowStorage.send_udpjson(sflow)
27
+ end
28
+ rescue Exception => e
29
+ puts Time.now
30
+ puts sflow.inspect if sflow != nil
31
+ puts e.message
32
+ puts e.backtrace
33
+ end
34
+ end
35
+
36
+ EM.defer(operation,callback)
37
+
38
+ end
39
+ end
40
+
41
+ def self.start_collector(bind_ip = '0.0.0.0', bind_port = 6343)
42
+ begin
43
+ config = SflowConfig.new
44
+ if config.logstash_host and config.logstash_port
45
+ puts "Connecting to Logstash: #{config.logstash_host}:#{config.logstash_port}"
46
+ $logstash = UDPSocket.new
47
+ $logstash.connect(config.logstash_host, config.logstash_port)
48
+ else
49
+ puts "no host:port given"
50
+ exit 1
51
+ end
52
+ $switch_hash = config.switch_hash
53
+ if config.switch_hash != nil
54
+ $switchportnames = SNMPwalk.new(config.switch_hash.each_key)
55
+ end
56
+ EventMachine::run do
57
+ EventMachine::open_datagram_socket(bind_ip, bind_port, Collector)
58
+ end
59
+ rescue Exception => e
60
+ puts Time.now
61
+ puts e.message
62
+ puts e.backtrace
63
+ raise "unable to start sflow collector"
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+
@@ -0,0 +1,15 @@
1
+ class SflowConfig
2
+ attr_reader :switch_hash
3
+ attr_reader :logstash_host
4
+ attr_reader :logstash_port
5
+ attr_reader :daemonize
6
+
7
+ def initialize
8
+ config = YAML.load_file("etc/config.yaml")
9
+ @switch_hash = config['switch']
10
+ @logstash_host = config['logstash_host']
11
+ @logstash_port = config['logstash_port']
12
+ @daemonize = config['daemonize']
13
+ end
14
+ end
15
+
@@ -0,0 +1,176 @@
1
+ class Header < BinData::Record
2
+ endian :big
3
+ uint32 :version
4
+ uint32 :address_type
5
+ uint32 :agent_address
6
+ uint32 :sub_agent_id
7
+ uint32 :seq_number
8
+ uint32 :sys_uptime
9
+ uint32 :num_samples
10
+ array :flow_samples, :initial_length => :num_samples do
11
+ uint16 :enterprise_std
12
+ uint16 :sflow_sample_type
13
+ uint32 :sample_length
14
+ string :sample_data, :length => :sample_length
15
+ end
16
+ end
17
+
18
+ class Sflow5sampleheader1 < BinData::Record
19
+ endian :big
20
+ uint32 :seq_number
21
+ uint32 :source_id_type
22
+ uint32 :sampling_rate
23
+ uint32 :sample_pool
24
+ uint32 :dropped_packets
25
+ uint32 :i_iface_value
26
+ uint32 :o_iface_value
27
+ uint32 :num_records
28
+ array :records, :initial_length => :num_records do
29
+ uint16 :enterprise
30
+ uint16 :format
31
+ uint32 :flow_length
32
+ string :record_data, :length => :flow_length
33
+ end
34
+
35
+ end
36
+
37
+ class Sflow5sampleheader3 < BinData::Record
38
+ endian :big
39
+ uint32 :seq_number
40
+ uint32 :source_id_type
41
+ uint32 :source_id_index
42
+ uint32 :sampling_rate
43
+ uint32 :sample_pool
44
+ uint32 :dropped_packets
45
+ uint32 :i_iface_format
46
+ uint32 :i_iface_value
47
+ uint32 :o_iface_format
48
+ uint32 :o_iface_value
49
+ uint32 :num_records
50
+ array :records, :initial_length => :num_records do
51
+ uint16 :enterprise
52
+ uint16 :format
53
+ uint32 :flow_length
54
+ string :record_data, :length => :flow_length
55
+ end
56
+
57
+ end
58
+
59
+
60
+ class Sflow5counterheader4 < BinData::Record
61
+ endian :big
62
+ uint32 :seq_number
63
+ uint32 :source_id_type
64
+ uint32 :source_id_index
65
+ uint32 :num_records
66
+ array :records, :initial_length => :num_records do
67
+ uint16 :enterprise
68
+ uint16 :format
69
+ uint32 :record_length
70
+ string :record_data, :length => :record_length
71
+ end
72
+ end
73
+
74
+ class Sflow5counterheader2 < BinData::Record
75
+ endian :big
76
+ uint32 :seq_number
77
+ uint32 :source_id_type
78
+ uint32 :num_records
79
+ array :records, :initial_length => :num_records do
80
+ uint16 :enterprise
81
+ uint16 :format
82
+ uint32 :record_length
83
+ string :record_data, :length => :record_length
84
+ end
85
+ end
86
+
87
+
88
+ class Sflow5rawpacket < BinData::Record
89
+ endian :big
90
+ uint32 :header_protocol
91
+ uint32 :frame_length
92
+ uint32 :payload
93
+ uint32 :xy
94
+ array :rawpacket_data, :read_until => :eof do
95
+ string :data, :length => 1
96
+ end
97
+ end
98
+
99
+ class Sflow5extswitch < BinData::Record
100
+ endian :big
101
+ uint32 :src_vlan
102
+ uint32 :src_priority
103
+ uint32 :dst_vlan
104
+ uint32 :dst_priority
105
+ end
106
+
107
+ class Sflow5genericcounter < BinData::Record
108
+ endian :big
109
+ uint32 :int_index
110
+ uint32 :int_type
111
+ uint64 :int_speed
112
+ uint32 :int_direction
113
+ uint16 :int_admin_status
114
+ uint16 :int_oper_status
115
+ uint64 :input_octets
116
+ uint32 :input_packets
117
+ uint32 :input_packets_multi
118
+ uint32 :input_packets_broad
119
+ uint32 :input_packets_discard
120
+ uint32 :input_packets_error
121
+ uint32 :unknown_proto
122
+ uint64 :output_octets
123
+ uint32 :output_packets
124
+ uint32 :output_packets_multi
125
+ uint32 :output_packets_broad
126
+ uint32 :output_packets_discard
127
+ uint32 :output_packets_error
128
+ uint32 :prom_mode
129
+ end
130
+
131
+ class Sflow5ethcounter < BinData::Record
132
+ endian :big
133
+ uint32 :alignment_errors
134
+ uint32 :fcs_errors
135
+ uint32 :single_collision_frames
136
+ uint32 :multi_collision_frames
137
+ uint32 :sqe_test_errors
138
+ uint32 :deffered_transmission
139
+ uint32 :late_collision
140
+ uint32 :excessive_collision
141
+ uint32 :internal_mac_transmit_errors
142
+ uint32 :carrier_sense_errors
143
+ uint32 :frame_too_long
144
+ uint32 :internal_mac_receive_errors
145
+ uint32 :symbol_errors
146
+ end
147
+
148
+ class Sflow5rawpacketheaderEthernet < BinData::Record
149
+ endian :big
150
+ string :eth_src, :length => 6
151
+ string :eth_dst, :length => 6
152
+ uint16 :eth_type
153
+ array :ethernetdata, :read_until => :eof do
154
+ string :data, :length => 1
155
+ end
156
+ end
157
+
158
+ class Sflow5rawpacketdata < BinData::Record
159
+ endian :big
160
+ string :eth, :length => 14
161
+ string :vlan_tag, :length => 2
162
+ string :vlan_tag_p, :length => 2
163
+ string :vlana, :length => 2
164
+ string :vlanb, :length => 2
165
+ string :ip_packet, :length => 40
166
+ end
167
+
168
+ class Sflow5rawpacketdataVLAN < BinData::Record
169
+ endian :big
170
+ uint16 :prio
171
+ uint16 :type
172
+ array :vlandata, :read_until => :eof do
173
+ string :data, :length => 1
174
+ end
175
+ end
176
+
@@ -0,0 +1,69 @@
1
+ # coding: utf-8
2
+ require_relative 'protocol'
3
+
4
+ # TODO: チェックサムを確認する
5
+ class IPv4Header
6
+
7
+ attr_reader :version,:header_length,:packet_length,:identification,:frag_dont,:frag_more,:frag_offset,:ttl,:protocol,:checksum,:sndr_addr,:dest_addr,
8
+ :data_length
9
+
10
+ def initialize(packet,offset=0)
11
+ @packet = packet.force_encoding("ASCII-8BIT")
12
+ @offset = offset
13
+ header = packet.unpack("x#{offset}n10")
14
+ @version = header[0] >> 12
15
+ @header_length = ((header[0] >> 8) & 0x0f)*4
16
+ @packet_length = header[1]
17
+ @identification = header[2]
18
+ @frag_dont = (header[3] >> 14) & 0x01 != 0
19
+ @frag_more = (header[3] >> 13) & 0x01 != 0
20
+ @frag_offset = header[3] & 0x1fff
21
+ @ttl = header[4] >> 8
22
+ @protocol = header[4] & 0x00ff
23
+ @checksum = header[5]
24
+ @sndr_addr = ip_to_s(packet[12..15])
25
+ @dest_addr = ip_to_s(packet[16..19])
26
+ @data_length = @packet_length - @header_length
27
+
28
+ @virtual_header = packet[12..19] + [0,6,@data_length].pack("CCn")
29
+
30
+ end
31
+
32
+ def upper
33
+ upper_header = Protocol.to_class(@protocol)
34
+ offset = @offset+@header_length
35
+ upper_header.new(@packet,offset,@data_length,self)
36
+ end
37
+
38
+ def data
39
+ start = @offset+@header_length
40
+ @packet[start..start+@data_length]
41
+ end
42
+
43
+ def get_virtual_header
44
+ @virtual_header
45
+ end
46
+
47
+ def ip_to_s(ip)
48
+ ip = ip.unpack("n2")
49
+ sprintf("%d.%d.%d.%d",ip[0]>>8,ip[0]&0x00ff,ip[1]>>8,ip[1]&0x00ff)
50
+ end
51
+
52
+ def to_s
53
+ "IPv4 Header\n" <<
54
+ " Version : #{@version}\n" <<
55
+ " Header Length : #{@header_length}\n" <<
56
+ " Packet Length : #{@packet_length}\n" <<
57
+ " Identification : #{@identification}\n" <<
58
+ " Don't fragment : #{@frag_dont}\n" <<
59
+ " More fragments : #{@frag_more}\n" <<
60
+ " Fragment Offset : #{@frag_offset}\n" <<
61
+ " TTL : #{@ttl}\n" <<
62
+ " Protocol : #{Protocol.to_s(@protocol)}\n" <<
63
+ " Header Checksum : #{@checksum}\n" <<
64
+ " Sender Address : #{@sndr_addr}\n" <<
65
+ " Destination Address: #{@dest_addr}\n" <<
66
+ " (Data Length) : #{@data_length}"
67
+ end
68
+
69
+ end
@@ -0,0 +1,47 @@
1
+ require_relative 'ipv4header'
2
+ require_relative 'udpheader'
3
+ require_relative 'tcpheader'
4
+
5
+ class Protocol
6
+ ICMP = 0x01
7
+ IGMP = 0x02
8
+ TCP = 0x06
9
+ UDP = 0x11
10
+ IPv6 = 0x29
11
+
12
+ def self.to_class protocol
13
+ case protocol
14
+ when Protocol::ICMP
15
+ raise "ICMP is not supported"
16
+ when Protocol::IGMP
17
+ raise "IGMP is not supported"
18
+ when Protocol::TCP
19
+ TCPHeader
20
+ when Protocol::UDP
21
+ UDPHeader
22
+ when Protocol::IPv6
23
+ raise "IPv6 is not supported"
24
+ else
25
+ raise "Protocol:"+sprintf("0x%2X",protocol)+" is not supported"
26
+ end
27
+ end
28
+
29
+ def self.to_s protocol
30
+ case protocol
31
+ when Protocol::ICMP
32
+ "ICMP"
33
+ when Protocol::IGMP
34
+ "IGMP"
35
+ when Protocol::TCP
36
+ "TCP"
37
+ when Protocol::UDP
38
+ "UDP"
39
+ when Protocol::IPv6
40
+ "IPv6"
41
+ else
42
+ sprintf("0x%2X",protocol)
43
+ end
44
+ end
45
+
46
+ end
47
+
@@ -0,0 +1,82 @@
1
+ class TCPHeader
2
+
3
+ attr_reader :sndr_port,:dest_port,:seq_num,:ack_num,:header_length,
4
+ :urg,:ack,:psh,:rst,:syn,:fin,:win_size,:checksum,:emgcy_ptr,
5
+ :packet_length,:data_length,:lower
6
+
7
+ def initialize(packet,offset=0,length=nil,lower=nil)
8
+ @packet = packet.force_encoding("ASCII-8BIT")
9
+ @offset = offset
10
+ @length = length || packet.bytesize-offset
11
+ header = packet.unpack("x#{offset}n2N2n4")
12
+ @sndr_port = header[0]
13
+ @dest_port = header[1]
14
+ @seq_num = header[2]
15
+ @ack_num = header[3]
16
+ @header_length = (header[4]>>12)*4
17
+ @urg = (header[4] & 0b100000) != 0
18
+ @ack = (header[4] & 0b010000) != 0
19
+ @psh = (header[4] & 0b001000) != 0
20
+ @rst = (header[4] & 0b000100) != 0
21
+ @syn = (header[4] & 0b000010) != 0
22
+ @fin = (header[4] & 0b000001) != 0
23
+ @win_size = header[5]
24
+ @checksum = header[6]
25
+ @emgcy_ptr = header[7]
26
+
27
+ @packet_length = @length
28
+ @data_length = @packet_length-@header_length
29
+
30
+ @lower = lower
31
+
32
+ # check checksum
33
+ calc_cs = false
34
+ if calc_cs
35
+ tmp = @packet[@offset..@offset+@length]
36
+ if (tmp.length % 2) != 0
37
+ tmp += "\0"
38
+ end
39
+ data = @lower.get_virtual_header + tmp
40
+ sum = 0
41
+ list = data.unpack("n*")
42
+ list.each do |d|
43
+ sum += d
44
+ end
45
+ sum = (sum & 0xffff) + (sum >> 16)
46
+ sum = (sum & 0xffff) + (sum >> 16)
47
+ raise if sum != 65535
48
+ end
49
+
50
+
51
+
52
+
53
+ end
54
+
55
+ def data
56
+ if(@data_length>0)
57
+ @packet[@offset+@header_length..@offset+@length]
58
+ else
59
+ ""
60
+ end
61
+ end
62
+
63
+ def to_s
64
+ "TCP Header\n" <<
65
+ " Sender Port : #{@sndr_port}\n" <<
66
+ " Destination Port: #{@dest_port}\n" <<
67
+ " Sequence Number : #{@seq_num}\n" <<
68
+ " ACK Number : #{@ack_num}\n" <<
69
+ " Header Length : #{@header_length}\n" <<
70
+ " URG : #{@urg}\n" <<
71
+ " ACK : #{@ack}\n" <<
72
+ " PSH : #{@psh}\n" <<
73
+ " RST : #{@rst}\n" <<
74
+ " SYN : #{@syn}\n" <<
75
+ " FIN : #{@fin}\n" <<
76
+ " Window Size : #{@win_size}\n" <<
77
+ " Checksum : #{@checksum}\n" <<
78
+ " Emergency Ptr : #{@emgcy_ptr}\n" <<
79
+ " (Packet Length) : #{@packet_length}\n" <<
80
+ " (Data Length) : #{@data_length}"
81
+ end
82
+ end