/
controller.zeek
133 lines (107 loc) · 3.19 KB
/
controller.zeek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
##! This is a utility script that implements the controller interface for the
##! control framework. It's intended to be run to control a remote Zeek
##! and then shutdown.
##!
##! It's intended to be used from the command line like this::
##!
##! zeek <scripts> frameworks/control/controller Control::host=<host_addr> Control::host_port=<host_port> Control::cmd=<command> [Control::arg=<arg>]
@load base/frameworks/control
@load base/frameworks/broker
module Control;
# Do some sanity checking and rework the communication nodes.
event zeek_init() &priority=5
{
# We know that some command was given because this script wouldn't be
# loaded if there wasn't so we can feel free to throw an error here and
# shutdown.
if ( cmd !in commands )
{
Reporter::error(fmt("The '%s' control command is unknown.", cmd));
terminate();
}
Broker::subscribe(Control::topic_prefix);
Broker::peer(cat(host), host_port);
}
event Control::id_value_response(id: string, val: string) &priority=-10
{
event terminate_event();
}
event Control::peer_status_response(s: string) &priority=-10
{
event terminate_event();
}
event Control::net_stats_response(s: string) &priority=-10
{
event terminate_event();
}
event Control::configuration_update_response() &priority=-10
{
event terminate_event();
}
event Control::shutdown_response() &priority=-10
{
event terminate_event();
}
function configurable_ids(): id_table
{
local rval: id_table = table();
local globals = global_ids();
for ( id in globals )
{
if ( id in ignore_ids )
next;
local t = globals[id];
# Skip it if the variable isn't redefinable or not const.
# We don't want to update non-const globals because that's usually
# where state is stored and those values will frequently be declared
# with &redef so that attributes can be redefined.
#
# NOTE: functions are currently not fully supported for serialization and hence
# aren't sent.
if ( t$constant && t$redefinable && t$type_name != "func" )
rval[id] = t;
}
return rval;
}
function send_control_request(topic: string)
{
switch ( cmd ) {
case "id_value":
if ( arg == "" )
Reporter::fatal("The Control::id_value command requires that Control::arg also has some value.");
Broker::publish(topic, Control::id_value_request, arg);
break;
case "peer_status":
Broker::publish(topic, Control::peer_status_request);
break;
case "net_stats":
Broker::publish(topic, Control::net_stats_request);
break;
case "shutdown":
Broker::publish(topic, Control::shutdown_request);
break;
case "configuration_update":
Broker::publish(topic, Control::configuration_update_request);
break;
default:
Reporter::fatal(fmt("unhandled Control::cmd, %s", cmd));
break;
}
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string) &priority=-10
{
local topic = Control::topic_prefix + "/" + endpoint$id;
if ( cmd == "configuration_update" )
{
# Send all &redef'able consts to the peer.
local ids = configurable_ids();
local publish_count = 0;
for ( id in ids )
{
if ( Broker::publish_id(topic, id) )
++publish_count;
}
Reporter::info(fmt("Control framework sent %d IDs", publish_count));
}
send_control_request(topic);
}