broccoli 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ require 'mkmf'
2
+
3
+ if ex = find_executable("broccoli-config")
4
+ $CFLAGS << " " + `#{ex} --cflags`.chomp
5
+ $LDFLAGS << " " + `#{ex} --libs`.chomp
6
+ else
7
+ raise "You need to have 'broccoli-config' in your path!"
8
+ end
9
+
10
+ if have_header("broccoli.h") and
11
+ # check the broccoli library for the existence
12
+ # of the new event registration function
13
+ have_library("broccoli", "bro_event_registry_add_compact") and
14
+ have_library("ssl")
15
+ create_makefile("broccoli")
16
+ end
@@ -0,0 +1,3 @@
1
+
2
+ File.delete 'mkmf.log' if File.exists? 'mkmf.log'
3
+ File.delete 'Makefile' if File.exists? 'Makefile'
@@ -0,0 +1,5 @@
1
+ bc = `which broccoli-config`
2
+ unless bc.length > 0
3
+ puts "You need to have broccoli-config in your path!"
4
+ exit(-1)
5
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'broccoli_ext'
4
+ include Broccoli_ext
5
+
6
+ peer = bro_conf_get_str("PeerName")
7
+ puts "Peer: #{peer}"
8
+
9
+ ret, port = bro_conf_get_int("PeerPort")
10
+ if(ret)
11
+ puts "PeerPort: #{ret}"
12
+ end
@@ -0,0 +1,174 @@
1
+ # Please don't try to read too much into this file. It's mostly my
2
+ # internal test file while I'm building the C binding.
3
+ #
4
+ # Check out the examples directory for better examples that use the ruby
5
+ # library I've built overtop the C bindings.
6
+
7
+ require './broccoli_ext'
8
+ include Broccoli_ext
9
+ Broccoli_ext::bro_debug_calltrace=false
10
+ Broccoli_ext::bro_debug_messages=false
11
+
12
+ STDOUT.sync = true
13
+
14
+ #a= Broccoli_ext::BroString.new
15
+ #a.str_val="asdf"
16
+
17
+ host_str = "127.0.0.1:12345"
18
+
19
+ bc = bro_conn_new_str(host_str, BRO_CFLAG_NONE)
20
+ puts "Connection? #{bc}"
21
+ #puts " Connected" unless bro_conn_connect(bc).zero?
22
+
23
+ ###
24
+ # Test BroString Creation
25
+ ###
26
+
27
+ module SWIG
28
+ class TYPE_p_bro_conn
29
+ def method_missing(meth, *args)
30
+ return bro_conn_data_get(self, meth.id2name)
31
+ end
32
+ end
33
+
34
+ class TYPE_p_bro_record
35
+ # I need to build a full record typemapper to deal with this correctly.
36
+
37
+ def method_missing(meth, *args)
38
+ #return bro_record_get_named_val(self, meth.id2name, BRO_TYPE_STRING)
39
+ end
40
+
41
+ def [](position)
42
+ #return bro_record_get_nth_val(self, position, BRO_TYPE_STRING)
43
+ end
44
+ end
45
+ end
46
+
47
+
48
+
49
+ ###
50
+ # Test Record Creation
51
+ ###
52
+ #rec = bro_record_new()
53
+ #puts "Ruby: Inserting data into the record"
54
+ ##time = bro_util_current_time()
55
+ ##puts "Ruby: Current time: #{time}"
56
+ #bro_record_add_val(rec, "seq", BRO_TYPE_IPADDR, 213054988)
57
+ #puts "Ruby: Getting the data back out"
58
+ ##puts bro_record_get_named_val(rec, "seq", BRO_TYPE_COUNT);
59
+ #puts " " + bro_record_get_nth_val(rec, 0, BRO_TYPE_IPADDR).to_s
60
+
61
+
62
+
63
+ ###
64
+ # Test Callback creation
65
+ ###
66
+
67
+ # Ideal :)
68
+ #bro_ruby_typemap_new("pong", [8,19,0])
69
+ #build_typemap("pong", [:conn,:record])
70
+
71
+ #while 1
72
+ # ev = bro_event_new("ping")
73
+ # bro_event_free(ev)
74
+ # #GC.start
75
+ #end
76
+
77
+ bro_pong_record = Proc.new do |conn, rec|
78
+ now = bro_util_current_time()
79
+ puts "Pong_record callback"
80
+ puts rec
81
+
82
+ seq = bro_record_get_nth_val(rec, 0, BRO_TYPE_COUNT)
83
+ src_time = bro_record_get_nth_val(rec, 1, BRO_TYPE_TIME)
84
+ dst_time = bro_record_get_nth_val(rec, 2, BRO_TYPE_TIME)
85
+
86
+ puts "pong event from #{host_str}: seq=#{seq}, time=#{dst_time-src_time}/#{now-src_time} s"
87
+ end
88
+
89
+ bro_pong = Proc.new do |conn, src_time, dst_time, seq|
90
+ puts "Pong callback!"
91
+ now = bro_util_current_time()
92
+ puts "pong event from #{host_str}: seq=#{seq}, time=#{dst_time-src_time}/#{now-src_time} s"
93
+ end
94
+
95
+ new_connection = Proc.new do |conn|
96
+ puts "Saw a connection!"
97
+ end
98
+
99
+ dns_request = Proc.new do |conn, msg, query, qtype, qclass|
100
+ #$count = $count+1
101
+ #puts "msg: #{msg}"
102
+ #puts "query: #{query}"
103
+ #puts "qtype: #{qtype}"
104
+ #puts "qclass: #{qclass}"
105
+ #puts "service: #{conn.blah}"
106
+ #puts "Query output class: #{query.class}"
107
+ #answers = bro_record_get_nth_val(msg, 11, BRO_TYPE_COUNT).to_s
108
+ #puts "Number of dns answers: #{answers}"
109
+ #puts "Query: #{query} - Query type: #{qtype} - Query class: #{qclass}"
110
+ end
111
+
112
+ #puts "Registering callback..."
113
+ #bro_event_registry_add(bc, "dns_A_reply", dns_reply)
114
+
115
+ bro_event_registry_add(bc, "dns_request", ["dns_request", [19, 19, 8, 3, 3], dns_request])
116
+
117
+ #bro_event_registry_add(bc, "pong", ["pong", {"pong", [19]}, bro_pong_record])
118
+ #bro_event_registry_add(bc, "pong", ["pong", {"pong", [6,6,3]}, bro_pong])
119
+
120
+ #bro_event_registry_add(bc, "wootback", [[8], wootback])
121
+
122
+ #bro_event_registry_add(bc, "new_connection", ["new_connection", {"new_connection", [19]}, new_connection])
123
+ #bro_event_registry_add(bc, "return_memory", return_memory)
124
+
125
+ #puts "Done Registering callback..."
126
+ puts "Connected" if bro_conn_connect(bc)
127
+
128
+ while(1)
129
+ #puts "Checking input"
130
+ $count = 0
131
+ bro_conn_process_input(bc)
132
+ puts "*" * ($count/2)
133
+
134
+ sleep 0.5
135
+
136
+ GC.start
137
+ end
138
+ exit
139
+
140
+ ###
141
+ # Testing record creation and event sending
142
+ ###
143
+ record = false
144
+ (1..100).each do |seq|
145
+ bro_conn_process_input(bc)
146
+ #puts "Creating event"
147
+ ev = bro_event_new("ping")
148
+ timestamp = bro_util_current_time()
149
+ if(record)
150
+ rec = bro_record_new()
151
+ bro_record_add_val(rec, "seq", BRO_TYPE_COUNT, seq)
152
+ bro_record_add_val(rec, "src_time", BRO_TYPE_TIME, timestamp)
153
+ bro_event_add_val(ev, BRO_TYPE_RECORD, rec)
154
+ else
155
+ bro_event_add_val(ev, BRO_TYPE_TIME, timestamp)
156
+ bro_event_add_val(ev, BRO_TYPE_COUNT, seq)
157
+ end
158
+
159
+ puts "Sending ping..."
160
+ bro_event_send(bc, ev)
161
+ # May not need to call this anymore either
162
+ #bro_event_free(ev)
163
+ sleep 1
164
+ #GC.start
165
+ end
166
+
167
+ #while(1) do
168
+ # ev = bro_event_new "show_memory"
169
+ # puts "Sending event"
170
+ # puts bro_event_send(bc, ev)
171
+ # sleep 1
172
+ # puts "Processing input..."
173
+ # puts bro_conn_process_input(bc)
174
+ #end
@@ -0,0 +1,78 @@
1
+ # This gives a nice interface for retrieving fields from connections
2
+ module SWIG
3
+ class TYPE_p_bro_conn
4
+ def method_missing(meth, *args)
5
+ return Broccoli::bro_conn_data_get(self, meth.id2name)
6
+ end
7
+ end
8
+ end
9
+
10
+ module Bro
11
+ class Connection
12
+ include Broccoli
13
+
14
+ def initialize(hp, flags=nil)
15
+ flags ||= (BRO_CFLAG_RECONNECT | BRO_CFLAG_ALWAYS_QUEUE)
16
+ @bc = bro_conn_new_str(hp, flags)
17
+ @io_object = nil
18
+ @event_blocks = []
19
+ end
20
+
21
+ def disconnect
22
+ bro_conn_delete(@bc)
23
+ end
24
+
25
+ def connect
26
+ bro_conn_connect(@bc)
27
+ end
28
+
29
+ def connected?
30
+ bro_conn_alive?(@bc)
31
+ end
32
+
33
+ def process_input
34
+ bro_conn_process_input(@bc)
35
+ end
36
+
37
+ def queue_length
38
+ bro_event_queue_length(@bc)
39
+ end
40
+
41
+ def queue_length_max
42
+ bro_event_queue_length_max(@bc)
43
+ end
44
+
45
+ def queue_flush
46
+ bro_event_queue_flush(@bc)
47
+ end
48
+
49
+ def send(event)
50
+ # .ev is the real event pointer
51
+ bro_event_send(@bc, event.ev)
52
+ end
53
+
54
+ def wait
55
+ unless @io_object
56
+ fd = bro_conn_get_fd(@bc)
57
+ return false if fd < 0
58
+ @io_object = IO.new(fd)
59
+ @io_object.sync = true # don't buffer
60
+ end
61
+ # block until there is data
62
+ if @io_object.closed?
63
+ puts "ERROR: connection lost!"
64
+ exit -1
65
+ else
66
+ IO.select([@io_object])
67
+ end
68
+ end
69
+
70
+ def event_handler(event, &callback)
71
+ bro_event_registry_add_compact(@bc, event, callback)
72
+ # Re-request all events if we're already connected.
73
+ bro_event_registry_request(@bc) if connected?
74
+ end
75
+ alias :event_handler_for :event_handler
76
+
77
+ end
78
+ end
data/lib/Bro/event.rb ADDED
@@ -0,0 +1,34 @@
1
+ module Bro
2
+
3
+ class Event
4
+ include Broccoli
5
+ attr_reader :ev
6
+
7
+ def initialize(name)
8
+ @ev = bro_event_new(name)
9
+ # Kill the BroEvent when the ruby object is garbage collected
10
+ ObjectSpace.define_finalizer(self, Event.create_finalizer(@ev))
11
+ end
12
+
13
+ # Insert a value into an event.
14
+ def insert(value, type, type_name=nil)
15
+ value = value.rec if type == :record
16
+ bro_event_add_val(@ev, [Bro::TYPES[type], type_name, value])
17
+ end
18
+
19
+ private
20
+
21
+ # Free the underlying C event data structure. User's are likely
22
+ # never going to need this call.
23
+ def free
24
+ bro_event_free(@ev)
25
+ end
26
+
27
+ # When the garbage collector comes around, make sure the C structure
28
+ # is freed.
29
+ def self.create_finalizer(event)
30
+ proc { bro_event_free(event) }
31
+ end
32
+ end
33
+
34
+ end
data/lib/Bro/record.rb ADDED
@@ -0,0 +1,71 @@
1
+ # This gives a nice interface for retrieving fields from records
2
+ module SWIG
3
+ class TYPE_p_bro_record
4
+ include Broccoli
5
+
6
+ # .id is a method for all ruby objects. Move it out of the way for records.
7
+ alias :orig_id :id
8
+ def id
9
+ return method_missing(:id)
10
+ end
11
+
12
+ # Retrieve record value by name
13
+ def method_missing(meth, *args)
14
+ bro_record_get_named_val(self, meth.id2name)
15
+ end
16
+
17
+ # Retrieve record value by position
18
+ def [](pos)
19
+ bro_record_get_nth_val(self, pos.to_i)
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ module Bro
26
+ class Record
27
+ include Broccoli
28
+ attr_accessor :rec
29
+
30
+ def initialize
31
+ @rec = bro_record_new()
32
+ # Kill the BroRecord when the ruby object is garbage collected
33
+ ObjectSpace.define_finalizer(self, Record.create_finalizer(@rec))
34
+ end
35
+
36
+ # .id is a method for all ruby objects. Move it out of the way for records.
37
+ alias :orig_id :id
38
+ def id
39
+ return method_missing(:id)
40
+ end
41
+
42
+ # Forward any missing methods on to the actual record object
43
+ def method_missing(meth)
44
+ @rec.send(meth)
45
+ end
46
+
47
+ def insert(name, value, type, type_name=nil)
48
+ value = value.rec if type == :record
49
+ bro_record_add_val(@rec, name.to_s, [Bro::TYPES[type], type_name, value])
50
+ end
51
+
52
+ def insert_at(pos, value, type, type_name=nil)
53
+ value = value.rec if type == :record
54
+ bro_record_set_nth_val(@rec, pos, [Bro::TYPES[type], type_name, value])
55
+ end
56
+ alias :insert_at_position :insert_at
57
+
58
+ private
59
+
60
+ def free
61
+ bro_record_free(@rec)
62
+ end
63
+
64
+ # When the garbage collector comes around,
65
+ # make sure the C structure is freed.
66
+ def self.create_finalizer(record)
67
+ proc { bro_record_free(record) }
68
+ end
69
+ end
70
+
71
+ end
data/lib/bro.rb ADDED
@@ -0,0 +1,87 @@
1
+ require 'broccoli'
2
+ require 'time'
3
+
4
+ require 'bro/connection'
5
+ require 'bro/event'
6
+ require 'bro/record'
7
+
8
+ module Bro
9
+ include Broccoli
10
+
11
+ TYPES = {:unknown => BRO_TYPE_UNKNOWN, # not really sure how this should be handled.
12
+ :bool => BRO_TYPE_BOOL,
13
+ :int => BRO_TYPE_INT,
14
+ :count => BRO_TYPE_COUNT,
15
+ :counter => BRO_TYPE_COUNTER,
16
+ :double => BRO_TYPE_DOUBLE,
17
+ :time => BRO_TYPE_TIME,
18
+ :interval => BRO_TYPE_INTERVAL,
19
+ :string => BRO_TYPE_STRING,
20
+ :enum => BRO_TYPE_ENUM,
21
+ :timer => BRO_TYPE_TIMER,
22
+ :port => BRO_TYPE_PORT,
23
+ :addr => BRO_TYPE_IPADDR,
24
+ :net => BRO_TYPE_NET,
25
+ :subnet => BRO_TYPE_SUBNET,
26
+ :record => BRO_TYPE_RECORD,
27
+ # These are not handled by the ruby binding.
28
+ :packet => BRO_TYPE_PACKET,
29
+ :max => BRO_TYPE_MAX,
30
+ # All types below are NOT handled by broccoli.
31
+ :pattern => BRO_TYPE_PATTERN,
32
+ :any => BRO_TYPE_ANY,
33
+ :table => BRO_TYPE_TABLE,
34
+ :union => BRO_TYPE_UNION,
35
+ :list => BRO_TYPE_LIST,
36
+ :func => BRO_TYPE_FUNC,
37
+ :file => BRO_TYPE_FILE,
38
+ :vector => BRO_TYPE_VECTOR,
39
+ :error => BRO_TYPE_ERROR
40
+ }
41
+
42
+ def Bro.current_time_f
43
+ Broccoli::bro_util_current_time
44
+ end
45
+
46
+ def Bro.current_time
47
+ Time.at( current_time_f() )
48
+ end
49
+
50
+ def Bro.debug_calltrace=(v)
51
+ Broccoli::bro_debug_calltrace=v
52
+ end
53
+
54
+ def Bro.debug_messages=(v)
55
+ Broccoli::bro_debug_messages=v
56
+ end
57
+ end
58
+
59
+ class Broccoli::BroPort
60
+ @@protocols = {0=>'ip', 1=>'icmp', 2=>'igmp', 3=>'ggp', 4=>'ipv4',
61
+ 6=>'tcp', 7=>'st', 8=>'egp', 9=>'pigp', 10=>'rccmon',
62
+ 11=>'nvpii', 12=>'pup', 13=>'argus', 14=>'emcon',
63
+ 15=>'xnet', 16=>'chaos', 17=>'udp', 18=>'mux', 19=>'meas',
64
+ 20=>'hmp', 21=>'prm', 22=>'idp', 23=>'trunk1', 24=>'trunk2',
65
+ 25=>'leaf1', 26=>'leaf2', 27=>'rdp', 28=>'irtp', 29=>'tp',
66
+ 30=>'blt', 31=>'nsp', 32=>'inp', 33=>'sep', 34=>'3pc',
67
+ 35=>'idpr', 36=>'xtp', 37=>'ddp', 38=>'cmtp', 39=>'tpxx',
68
+ 40=>'il', 41=>'ipv6', 42=>'sdrp', 43=>'routing',
69
+ 44=>'fragment', 45=>'idrp', 46=>'rsvp', 47=>'gre', 48=>'mhrp',
70
+ 49=>'bha', 50=>'esp', 51=>'ah', 52=>'inlsp', 53=>'swipe',
71
+ 54=>'nhrp', 58=>'icmpv6', 59=>'nonext', 60=>'dstopts',
72
+ 61=>'ahip', 62=>'cftp', 63=>'hello', 64=>'satexpak',
73
+ 65=>'kryptolan', 66=>'rvd', 67=>'ippc', 68=>'adfs',
74
+ 69=>'satmon', 70=>'visa', 71=>'ipcv', 72=>'cpnx', 73=>'cphb',
75
+ 74=>'wsn', 75=>'pvp', 76=>'brsatmon', 77=>'nd', 78=>'wbmon',
76
+ 79=>'wbexpak', 80=>'eon', 81=>'vmtp', 82=>'svmtp',
77
+ 83=>'vines', 84=>'ttp', 85=>'igp', 86=>'dgp', 87=>'tcf',
78
+ 88=>'igrp', 89=>'ospfigp', 90=>'srpc', 91=>'larp', 92=>'mtp',
79
+ 93=>'ax25', 94=>'ipeip', 95=>'micp', 96=>'sccsp',
80
+ 97=>'etherip', 98=>'encap', 99=>'apes', 100=>'gmtp',
81
+ 103=>'pim', 108=>'ipcomp', 113=>'pgm', 254=>'divert',
82
+ 255=>'raw'}
83
+ def to_s
84
+ #"#{port_num}/#{@@protocols[port_proto]}"
85
+ port_num.to_s
86
+ end
87
+ end