/src/wireshark/epan/dissectors/packet-riemann.c
Line | Count | Source |
1 | | /** |
2 | | * packet-riemann.c |
3 | | * Routines for Riemann dissection |
4 | | * Copyright 2014, Sergey Avseyev <sergey.avseyev@gmail.com> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | /* Riemann (http://riemann.io) aggregates events from servers and |
14 | | * applications with a powerful stream processing language. |
15 | | * |
16 | | * Protobuf structures layout: |
17 | | * https://github.com/riemann/riemann-java-client/blob/master/riemann-java-client/src/main/proto/riemann/proto.proto |
18 | | * |
19 | | * message State { |
20 | | * optional int64 time = 1; |
21 | | * optional string state = 2; |
22 | | * optional string service = 3; |
23 | | * optional string host = 4; |
24 | | * optional string description = 5; |
25 | | * optional bool once = 6; |
26 | | * repeated string tags = 7; |
27 | | * optional float ttl = 8; |
28 | | * } |
29 | | * |
30 | | * message Event { |
31 | | * optional int64 time = 1; |
32 | | * optional string state = 2; |
33 | | * optional string service = 3; |
34 | | * optional string host = 4; |
35 | | * optional string description = 5; |
36 | | * repeated string tags = 7; |
37 | | * optional float ttl = 8; |
38 | | * repeated Attribute attributes = 9; |
39 | | * |
40 | | * optional int64 time_micros = 10; |
41 | | * optional sint64 metric_sint64 = 13; |
42 | | * optional double metric_d = 14; |
43 | | * optional float metric_f = 15; |
44 | | * } |
45 | | * |
46 | | * message Query { |
47 | | * optional string string = 1; |
48 | | * } |
49 | | * |
50 | | * message Msg { |
51 | | * optional bool ok = 2; |
52 | | * optional string error = 3; |
53 | | * repeated State states = 4; |
54 | | * optional Query query = 5; |
55 | | * repeated Event events = 6; |
56 | | * } |
57 | | * |
58 | | * message Attribute { |
59 | | * required string key = 1; |
60 | | * optional string value = 2; |
61 | | * } |
62 | | */ |
63 | | |
64 | | #include "config.h" |
65 | | |
66 | | #include <epan/packet.h> |
67 | | #include <epan/expert.h> |
68 | | #include "packet-tcp.h" |
69 | | |
70 | | void proto_reg_handoff_riemann(void); |
71 | | void proto_register_riemann(void); |
72 | | |
73 | | static dissector_handle_t riemann_udp_handle, riemann_tcp_handle; |
74 | | |
75 | | static int proto_riemann; |
76 | | static int hf_riemann_msg_ok; |
77 | | static int hf_riemann_msg_error; |
78 | | static int hf_riemann_attribute; |
79 | | static int hf_riemann_attribute_key; |
80 | | static int hf_riemann_attribute_value; |
81 | | static int hf_riemann_query; |
82 | | static int hf_riemann_query_string; |
83 | | static int hf_riemann_event; |
84 | | static int hf_riemann_event_state; |
85 | | static int hf_riemann_event_service; |
86 | | static int hf_riemann_event_host; |
87 | | static int hf_riemann_event_description; |
88 | | static int hf_riemann_event_tag; |
89 | | static int hf_riemann_event_ttl; |
90 | | static int hf_riemann_event_time; |
91 | | static int hf_riemann_event_metric_d; |
92 | | static int hf_riemann_event_metric_f; |
93 | | static int hf_riemann_event_time_micros; |
94 | | static int hf_riemann_event_metric_sint64; |
95 | | static int hf_riemann_state; |
96 | | static int hf_riemann_state_service; |
97 | | static int hf_riemann_state_host; |
98 | | static int hf_riemann_state_description; |
99 | | static int hf_riemann_state_tag; |
100 | | static int hf_riemann_state_ttl; |
101 | | static int hf_riemann_state_time; |
102 | | static int hf_riemann_state_state; |
103 | | static int hf_riemann_state_once; |
104 | | |
105 | | static int ett_riemann; |
106 | | static int ett_query; |
107 | | static int ett_event; |
108 | | static int ett_attribute; |
109 | | static int ett_state; |
110 | | |
111 | 0 | #define RIEMANN_MIN_LENGTH 16 |
112 | 0 | #define RIEMANN_MIN_NEEDED_FOR_HEURISTICS 10 |
113 | | |
114 | | /* field numbers. see protocol definition above */ |
115 | 0 | #define RIEMANN_FN_MSG_OK 2 |
116 | 0 | #define RIEMANN_FN_MSG_ERROR 3 |
117 | 0 | #define RIEMANN_FN_MSG_STATES 4 |
118 | 0 | #define RIEMANN_FN_MSG_QUERY 5 |
119 | 0 | #define RIEMANN_FN_MSG_EVENTS 6 |
120 | | |
121 | 0 | #define RIEMANN_FN_EVENT_TIME 1 |
122 | 0 | #define RIEMANN_FN_EVENT_STATE 2 |
123 | 0 | #define RIEMANN_FN_EVENT_SERVICE 3 |
124 | 0 | #define RIEMANN_FN_EVENT_HOST 4 |
125 | 0 | #define RIEMANN_FN_EVENT_DESCRIPTION 5 |
126 | 0 | #define RIEMANN_FN_EVENT_TAGS 7 |
127 | 0 | #define RIEMANN_FN_EVENT_TTL 8 |
128 | 0 | #define RIEMANN_FN_EVENT_ATTRIBUTES 9 |
129 | 0 | #define RIEMANN_FN_EVENT_TIME_MICROS 10 |
130 | 0 | #define RIEMANN_FN_EVENT_METRIC_SINT64 13 |
131 | 0 | #define RIEMANN_FN_EVENT_METRIC_D 14 |
132 | 0 | #define RIEMANN_FN_EVENT_METRIC_F 15 |
133 | | |
134 | 0 | #define RIEMANN_FN_ATTRIBUTE_KEY 1 |
135 | 0 | #define RIEMANN_FN_ATTRIBUTE_VALUE 2 |
136 | | |
137 | 0 | #define RIEMANN_FN_STATE_TIME 1 |
138 | 0 | #define RIEMANN_FN_STATE_STATE 2 |
139 | 0 | #define RIEMANN_FN_STATE_SERVICE 3 |
140 | 0 | #define RIEMANN_FN_STATE_HOST 4 |
141 | 0 | #define RIEMANN_FN_STATE_DESCRIPTION 5 |
142 | 0 | #define RIEMANN_FN_STATE_ONCE 6 |
143 | 0 | #define RIEMANN_FN_STATE_TAGS 7 |
144 | 0 | #define RIEMANN_FN_STATE_TTL 8 |
145 | | |
146 | 0 | #define RIEMANN_FN_QUERY_STRING 1 |
147 | | |
148 | | /* type codes. see protocol definition above */ |
149 | 0 | #define RIEMANN_WIRE_INTEGER 0 |
150 | 0 | #define RIEMANN_WIRE_DOUBLE 1 |
151 | 0 | #define RIEMANN_WIRE_BYTES 2 |
152 | 0 | #define RIEMANN_WIRE_FLOAT 5 |
153 | | |
154 | | static expert_field ei_error_unknown_wire_tag; |
155 | | static expert_field ei_error_unknown_field_number; |
156 | | static expert_field ei_error_insufficient_data; |
157 | | |
158 | | static void |
159 | | riemann_verify_wire_format(uint64_t field_number, const char *field_name, int expected, int actual, |
160 | | packet_info *pinfo, proto_item *pi) |
161 | 0 | { |
162 | 0 | if (expected != actual) { |
163 | 0 | const char *wire_name; |
164 | |
|
165 | 0 | switch (expected) { |
166 | 0 | case RIEMANN_WIRE_INTEGER: |
167 | 0 | wire_name = "integer"; |
168 | 0 | break; |
169 | 0 | case RIEMANN_WIRE_BYTES: |
170 | 0 | wire_name = "bytes/string"; |
171 | 0 | break; |
172 | 0 | case RIEMANN_WIRE_FLOAT: |
173 | 0 | wire_name = "float"; |
174 | 0 | break; |
175 | 0 | case RIEMANN_WIRE_DOUBLE: |
176 | 0 | wire_name = "double"; |
177 | 0 | break; |
178 | 0 | default: |
179 | 0 | wire_name = "unknown (check packet-riemann.c)"; |
180 | 0 | break; |
181 | 0 | } |
182 | 0 | expert_add_info_format(pinfo, pi, &ei_error_unknown_wire_tag, |
183 | 0 | "Expected %s (%d) field to be an %s (%d), but it is %d", |
184 | 0 | field_name, (int)field_number, wire_name, expected, actual); |
185 | 0 | } |
186 | 0 | } |
187 | | |
188 | | #define VERIFY_WIRE_FORMAT(field_name, expected) \ |
189 | 0 | riemann_verify_wire_format(fn, field_name, expected, wire, pinfo, pi) |
190 | | |
191 | | #define UNKNOWN_FIELD_NUMBER_FOR(message_name) \ |
192 | 0 | expert_add_info_format(pinfo, pi, &ei_error_unknown_field_number, \ |
193 | 0 | "Unknown field number %d for " message_name " (wire format %d)", \ |
194 | 0 | (int)fn, (int)wire); |
195 | | |
196 | | #define VERIFY_SIZE_FOR(message_name) \ |
197 | 0 | if (size < 0) { \ |
198 | 0 | expert_add_info_format(pinfo, pi, &ei_error_insufficient_data, \ |
199 | 0 | "Insufficient data for " message_name " (%d bytes needed)", \ |
200 | 0 | (int)size * -1); \ |
201 | 0 | } |
202 | | |
203 | | static uint64_t |
204 | | riemann_get_uint64(tvbuff_t *tvb, unsigned offset, unsigned *len) |
205 | 0 | { |
206 | 0 | uint64_t num = 0; |
207 | |
|
208 | 0 | *len = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &num, ENC_VARINT_PROTOBUF); |
209 | 0 | if (*len == 0) { |
210 | 0 | *len = FT_VARINT_MAX_LEN; |
211 | 0 | num = 0; |
212 | | // XXX - Add some failure expert info |
213 | 0 | } |
214 | 0 | return num; |
215 | 0 | } |
216 | | |
217 | | static char * |
218 | | riemann_get_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset) |
219 | 0 | { |
220 | 0 | uint64_t size; |
221 | 0 | unsigned len = 0; |
222 | |
|
223 | 0 | size = riemann_get_uint64(tvb, offset, &len); |
224 | 0 | offset += len; |
225 | 0 | return (char*)tvb_get_string_enc(scope, tvb, offset, (int)size, ENC_ASCII); |
226 | 0 | } |
227 | | |
228 | | static unsigned |
229 | | riemann_dissect_int64(proto_tree *riemann_tree, tvbuff_t *tvb, unsigned offset, int hf_index) |
230 | 0 | { |
231 | 0 | uint64_t num; |
232 | 0 | unsigned len = 0; |
233 | |
|
234 | 0 | num = riemann_get_uint64(tvb, offset, &len); |
235 | 0 | proto_tree_add_int64(riemann_tree, hf_index, tvb, offset, len, num); |
236 | 0 | return len; |
237 | 0 | } |
238 | | |
239 | | static unsigned |
240 | | riemann_dissect_sint64(proto_tree *riemann_tree, tvbuff_t *tvb, unsigned offset, int hf_index) |
241 | 0 | { |
242 | 0 | int64_t snum; |
243 | 0 | unsigned len = 0; |
244 | |
|
245 | 0 | len = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, (uint64_t*)&snum, ENC_VARINT_ZIGZAG); |
246 | 0 | if (!len) { |
247 | 0 | len = FT_VARINT_MAX_LEN; |
248 | 0 | snum = 0; |
249 | | // XXX - Add some failure expert info |
250 | 0 | } |
251 | |
|
252 | 0 | proto_tree_add_int64(riemann_tree, hf_index, tvb, offset, len, snum); |
253 | 0 | return len; |
254 | 0 | } |
255 | | |
256 | | static unsigned |
257 | | riemann_dissect_string(proto_tree *riemann_tree, tvbuff_t *tvb, unsigned offset, int hf_index) |
258 | 0 | { |
259 | 0 | uint64_t size; |
260 | 0 | unsigned len = 0, orig_offset = offset; |
261 | |
|
262 | 0 | size = riemann_get_uint64(tvb, offset, &len); |
263 | 0 | offset += len; |
264 | 0 | proto_tree_add_item(riemann_tree, hf_index, tvb, offset, (int)size, ENC_ASCII); |
265 | 0 | offset += (int)size; |
266 | |
|
267 | 0 | return offset - orig_offset; |
268 | 0 | } |
269 | | |
270 | | static unsigned |
271 | | riemann_dissect_attribute(packet_info *pinfo, proto_tree *riemann_tree, |
272 | | tvbuff_t *tvb, unsigned offset) |
273 | 0 | { |
274 | 0 | uint64_t tag, fn; |
275 | 0 | int64_t size; |
276 | 0 | uint8_t wire; |
277 | 0 | unsigned len = 0; |
278 | 0 | unsigned orig_offset = offset; |
279 | 0 | proto_item *pi; |
280 | 0 | proto_tree *attribute_tree; |
281 | |
|
282 | 0 | size = (int64_t)riemann_get_uint64(tvb, offset, &len); |
283 | 0 | pi = proto_tree_add_item(riemann_tree, hf_riemann_attribute, tvb, (int)offset, (int)(size + len), ENC_NA); |
284 | 0 | attribute_tree = proto_item_add_subtree(pi, ett_attribute); |
285 | 0 | offset += len; |
286 | |
|
287 | 0 | while (size > 0) { |
288 | 0 | tag = riemann_get_uint64(tvb, offset, &len); |
289 | 0 | fn = tag >> 3; |
290 | 0 | wire = tag & 0x7; |
291 | 0 | offset += len; |
292 | 0 | size -= len; |
293 | 0 | switch (fn) { |
294 | 0 | case RIEMANN_FN_ATTRIBUTE_KEY: |
295 | 0 | VERIFY_WIRE_FORMAT("Attribute.key", RIEMANN_WIRE_BYTES); |
296 | 0 | len = riemann_dissect_string(attribute_tree, tvb, offset, hf_riemann_attribute_key); |
297 | 0 | break; |
298 | 0 | case RIEMANN_FN_ATTRIBUTE_VALUE: |
299 | 0 | VERIFY_WIRE_FORMAT("Attribute.value", RIEMANN_WIRE_BYTES); |
300 | 0 | len = riemann_dissect_string(attribute_tree, tvb, offset, hf_riemann_attribute_value); |
301 | 0 | break; |
302 | 0 | default: |
303 | 0 | len = 0; |
304 | 0 | UNKNOWN_FIELD_NUMBER_FOR("Attribute"); |
305 | 0 | } |
306 | 0 | offset += len; |
307 | 0 | size -= len; |
308 | 0 | } |
309 | 0 | VERIFY_SIZE_FOR("Attribute"); |
310 | |
|
311 | 0 | return offset - orig_offset; |
312 | 0 | } |
313 | | |
314 | | static unsigned |
315 | | riemann_dissect_query(packet_info *pinfo, proto_tree *riemann_tree, |
316 | | tvbuff_t *tvb, unsigned offset) |
317 | 0 | { |
318 | 0 | uint64_t tag, fn; |
319 | 0 | int64_t size; |
320 | 0 | uint8_t wire; |
321 | 0 | unsigned orig_offset = offset, len = 0; |
322 | 0 | proto_item *pi; |
323 | 0 | proto_tree *query_tree; |
324 | |
|
325 | 0 | size = (int64_t)riemann_get_uint64(tvb, offset, &len); |
326 | 0 | pi = proto_tree_add_item(riemann_tree, hf_riemann_query, tvb, (int)offset, (int)(size + len), ENC_NA); |
327 | 0 | query_tree = proto_item_add_subtree(pi, ett_query); |
328 | 0 | offset += len; |
329 | |
|
330 | 0 | while (size > 0) { |
331 | 0 | tag = riemann_get_uint64(tvb, offset, &len); |
332 | 0 | fn = tag >> 3; |
333 | 0 | wire = tag & 0x7; |
334 | 0 | offset += len; |
335 | 0 | size -= len; |
336 | 0 | switch (fn) { |
337 | 0 | case RIEMANN_FN_QUERY_STRING: |
338 | 0 | VERIFY_WIRE_FORMAT("Query.string", RIEMANN_WIRE_BYTES); |
339 | 0 | col_append_str(pinfo->cinfo, COL_INFO, riemann_get_string(pinfo->pool, tvb, offset)); |
340 | 0 | len = riemann_dissect_string(query_tree, tvb, offset, hf_riemann_query_string); |
341 | 0 | break; |
342 | 0 | default: |
343 | 0 | len = 0; |
344 | 0 | UNKNOWN_FIELD_NUMBER_FOR("Query"); |
345 | 0 | } |
346 | 0 | offset += len; |
347 | 0 | size -= len; |
348 | 0 | } |
349 | 0 | VERIFY_SIZE_FOR("Query"); |
350 | |
|
351 | 0 | return offset - orig_offset; |
352 | 0 | } |
353 | | |
354 | | static unsigned |
355 | | riemann_dissect_event(packet_info *pinfo, proto_tree *riemann_tree, |
356 | | tvbuff_t *tvb, unsigned offset) |
357 | 0 | { |
358 | 0 | unsigned orig_offset = offset, len = 0; |
359 | 0 | uint64_t tag, fn; |
360 | 0 | int64_t size; |
361 | 0 | uint8_t wire; |
362 | 0 | proto_item *pi; |
363 | 0 | proto_tree *event_tree; |
364 | 0 | bool need_comma = false; |
365 | |
|
366 | 0 | size = riemann_get_uint64(tvb, offset, &len); |
367 | 0 | pi = proto_tree_add_item(riemann_tree, hf_riemann_event, tvb, (int)offset, (int)(size + len), ENC_NA); |
368 | 0 | event_tree = proto_item_add_subtree(pi, ett_event); |
369 | 0 | offset += len; |
370 | |
|
371 | 0 | while (size > 0) { |
372 | 0 | const char *comma = need_comma ? ", " : ""; |
373 | 0 | tag = riemann_get_uint64(tvb, offset, &len); |
374 | 0 | fn = tag >> 3; |
375 | 0 | wire = tag & 0x7; |
376 | 0 | offset += len; |
377 | 0 | size -= len; |
378 | 0 | switch (fn) { |
379 | 0 | case RIEMANN_FN_EVENT_TIME: |
380 | 0 | VERIFY_WIRE_FORMAT("Event.time", RIEMANN_WIRE_INTEGER); |
381 | 0 | len = riemann_dissect_int64(event_tree, tvb, offset, hf_riemann_event_time); |
382 | 0 | break; |
383 | 0 | case RIEMANN_FN_EVENT_STATE: |
384 | 0 | VERIFY_WIRE_FORMAT("Event.state", RIEMANN_WIRE_BYTES); |
385 | 0 | len = riemann_dissect_string(event_tree, tvb, offset, hf_riemann_event_state); |
386 | 0 | break; |
387 | 0 | case RIEMANN_FN_EVENT_SERVICE: |
388 | 0 | VERIFY_WIRE_FORMAT("Event.service", RIEMANN_WIRE_BYTES); |
389 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s", comma, riemann_get_string(pinfo->pool, tvb, offset)); |
390 | 0 | len = riemann_dissect_string(event_tree, tvb, offset, hf_riemann_event_service); |
391 | 0 | need_comma = true; |
392 | 0 | break; |
393 | 0 | case RIEMANN_FN_EVENT_HOST: |
394 | 0 | VERIFY_WIRE_FORMAT("Event.host", RIEMANN_WIRE_BYTES); |
395 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s", comma, riemann_get_string(pinfo->pool, tvb, offset)); |
396 | 0 | len = riemann_dissect_string(event_tree, tvb, offset, hf_riemann_event_host); |
397 | 0 | need_comma = true; |
398 | 0 | break; |
399 | 0 | case RIEMANN_FN_EVENT_DESCRIPTION: |
400 | 0 | VERIFY_WIRE_FORMAT("Event.description", RIEMANN_WIRE_BYTES); |
401 | 0 | len = riemann_dissect_string(event_tree, tvb, offset, hf_riemann_event_description); |
402 | 0 | break; |
403 | 0 | case RIEMANN_FN_EVENT_TAGS: |
404 | 0 | VERIFY_WIRE_FORMAT("Event.tags", RIEMANN_WIRE_BYTES); |
405 | 0 | len = riemann_dissect_string(event_tree, tvb, offset, hf_riemann_event_tag); |
406 | 0 | break; |
407 | 0 | case RIEMANN_FN_EVENT_TTL: |
408 | 0 | VERIFY_WIRE_FORMAT("Event.ttl", RIEMANN_WIRE_FLOAT); |
409 | 0 | proto_tree_add_item(event_tree, hf_riemann_event_ttl, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
410 | 0 | len = 4; |
411 | 0 | break; |
412 | 0 | case RIEMANN_FN_EVENT_ATTRIBUTES: |
413 | 0 | VERIFY_WIRE_FORMAT("Event.attributes", RIEMANN_WIRE_BYTES); |
414 | 0 | len = riemann_dissect_attribute(pinfo, event_tree, tvb, offset); |
415 | 0 | break; |
416 | 0 | case RIEMANN_FN_EVENT_TIME_MICROS: |
417 | 0 | VERIFY_WIRE_FORMAT("Event.time_micros", RIEMANN_WIRE_INTEGER); |
418 | 0 | len = riemann_dissect_int64(event_tree, tvb, offset, hf_riemann_event_time_micros); |
419 | 0 | break; |
420 | 0 | case RIEMANN_FN_EVENT_METRIC_SINT64: |
421 | 0 | VERIFY_WIRE_FORMAT("Event.metric_sint64", RIEMANN_WIRE_INTEGER); |
422 | 0 | len = riemann_dissect_sint64(event_tree, tvb, offset, hf_riemann_event_metric_sint64); |
423 | 0 | break; |
424 | 0 | case RIEMANN_FN_EVENT_METRIC_D: |
425 | 0 | VERIFY_WIRE_FORMAT("Event.metric_d", RIEMANN_WIRE_DOUBLE); |
426 | 0 | proto_tree_add_item(event_tree, hf_riemann_event_metric_d, tvb, offset, 8, ENC_LITTLE_ENDIAN); |
427 | 0 | len = 8; |
428 | 0 | break; |
429 | 0 | case RIEMANN_FN_EVENT_METRIC_F: |
430 | 0 | VERIFY_WIRE_FORMAT("Event.metric_f", RIEMANN_WIRE_FLOAT); |
431 | 0 | proto_tree_add_item(event_tree, hf_riemann_event_metric_f, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
432 | 0 | len = 4; |
433 | 0 | break; |
434 | 0 | default: |
435 | 0 | len = 0; |
436 | 0 | UNKNOWN_FIELD_NUMBER_FOR("Event"); |
437 | 0 | } |
438 | 0 | offset += len; |
439 | 0 | size -= len; |
440 | 0 | } |
441 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "; "); |
442 | 0 | VERIFY_SIZE_FOR("Event"); |
443 | |
|
444 | 0 | return offset - orig_offset; |
445 | 0 | } |
446 | | |
447 | | static unsigned |
448 | | riemann_dissect_state(packet_info *pinfo, proto_tree *riemann_tree, |
449 | | tvbuff_t *tvb, unsigned offset) |
450 | 0 | { |
451 | 0 | unsigned orig_offset = offset, len = 0; |
452 | 0 | uint64_t tag, fn; |
453 | 0 | int64_t size; |
454 | 0 | uint8_t wire; |
455 | 0 | proto_item *pi; |
456 | 0 | proto_tree *state_tree; |
457 | 0 | bool need_comma = false; |
458 | |
|
459 | 0 | size = riemann_get_uint64(tvb, offset, &len); |
460 | 0 | pi = proto_tree_add_item(riemann_tree, hf_riemann_state, tvb, offset, (int)(size + len), ENC_NA); |
461 | 0 | state_tree = proto_item_add_subtree(pi, ett_state); |
462 | 0 | offset += len; |
463 | |
|
464 | 0 | while (size > 0) { |
465 | 0 | const char *comma = need_comma ? ", " : ""; |
466 | 0 | tag = riemann_get_uint64(tvb, offset, &len); |
467 | 0 | fn = tag >> 3; |
468 | 0 | wire = tag & 0x7; |
469 | 0 | offset += len; |
470 | 0 | size -= len; |
471 | 0 | switch (fn) { |
472 | 0 | case RIEMANN_FN_STATE_TIME: |
473 | 0 | VERIFY_WIRE_FORMAT("State.time", RIEMANN_WIRE_INTEGER); |
474 | 0 | len = riemann_dissect_int64(state_tree, tvb, offset, hf_riemann_state_time); |
475 | 0 | break; |
476 | 0 | case RIEMANN_FN_STATE_SERVICE: |
477 | 0 | VERIFY_WIRE_FORMAT("State.service", RIEMANN_WIRE_BYTES); |
478 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s", comma, riemann_get_string(pinfo->pool, tvb, offset)); |
479 | 0 | len = riemann_dissect_string(state_tree, tvb, offset, hf_riemann_state_service); |
480 | 0 | need_comma = true; |
481 | 0 | break; |
482 | 0 | case RIEMANN_FN_STATE_HOST: |
483 | 0 | VERIFY_WIRE_FORMAT("State.host", RIEMANN_WIRE_BYTES); |
484 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s", comma, riemann_get_string(pinfo->pool, tvb, offset)); |
485 | 0 | len = riemann_dissect_string(state_tree, tvb, offset, hf_riemann_state_host); |
486 | 0 | need_comma = true; |
487 | 0 | break; |
488 | 0 | case RIEMANN_FN_STATE_DESCRIPTION: |
489 | 0 | VERIFY_WIRE_FORMAT("State.description", RIEMANN_WIRE_BYTES); |
490 | 0 | len = riemann_dissect_string(state_tree, tvb, offset, hf_riemann_state_description); |
491 | 0 | break; |
492 | 0 | case RIEMANN_FN_STATE_TAGS: |
493 | 0 | VERIFY_WIRE_FORMAT("State.tags", RIEMANN_WIRE_BYTES); |
494 | 0 | len = riemann_dissect_string(state_tree, tvb, offset, hf_riemann_state_tag); |
495 | 0 | break; |
496 | 0 | case RIEMANN_FN_STATE_TTL: |
497 | 0 | VERIFY_WIRE_FORMAT("State.ttl", RIEMANN_WIRE_FLOAT); |
498 | 0 | proto_tree_add_item(state_tree, hf_riemann_state_ttl, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
499 | 0 | len = 4; |
500 | 0 | break; |
501 | 0 | case RIEMANN_FN_STATE_STATE: |
502 | 0 | VERIFY_WIRE_FORMAT("State.state", RIEMANN_WIRE_BYTES); |
503 | 0 | len = riemann_dissect_string(state_tree, tvb, offset, hf_riemann_state_state); |
504 | 0 | break; |
505 | 0 | case RIEMANN_FN_STATE_ONCE: |
506 | 0 | VERIFY_WIRE_FORMAT("State.once", RIEMANN_WIRE_INTEGER); |
507 | 0 | proto_tree_add_item(state_tree, hf_riemann_state_once, tvb, offset, 1, ENC_NA); |
508 | 0 | len = 1; |
509 | 0 | break; |
510 | 0 | default: |
511 | 0 | len = 0; |
512 | 0 | UNKNOWN_FIELD_NUMBER_FOR("State"); |
513 | 0 | } |
514 | 0 | offset += len; |
515 | 0 | size -= len; |
516 | 0 | } |
517 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "; "); |
518 | 0 | VERIFY_SIZE_FOR("State"); |
519 | |
|
520 | 0 | return offset - orig_offset; |
521 | 0 | } |
522 | | |
523 | | static unsigned |
524 | | riemann_dissect_msg(packet_info *pinfo, proto_item *pi, proto_tree *riemann_tree, |
525 | | tvbuff_t *tvb, unsigned offset) |
526 | 0 | { |
527 | 0 | uint64_t tag, fn; |
528 | 0 | int64_t size = (int64_t)tvb_reported_length_remaining(tvb, offset); |
529 | 0 | uint8_t wire; |
530 | 0 | unsigned len, orig_offset = offset; |
531 | 0 | bool cinfo_set = false; |
532 | |
|
533 | 0 | while (size > 0) { |
534 | 0 | tag = riemann_get_uint64(tvb, offset, &len); |
535 | 0 | fn = tag >> 3; |
536 | 0 | wire = tag & 0x7; |
537 | 0 | offset += len; |
538 | 0 | size -= len; |
539 | |
|
540 | 0 | switch (fn) { |
541 | 0 | case RIEMANN_FN_MSG_OK: |
542 | 0 | VERIFY_WIRE_FORMAT("Msg.ok", RIEMANN_WIRE_INTEGER); |
543 | 0 | proto_tree_add_item(riemann_tree, hf_riemann_msg_ok, tvb, offset, 1, ENC_NA); |
544 | 0 | len = 1; |
545 | 0 | break; |
546 | 0 | case RIEMANN_FN_MSG_ERROR: |
547 | 0 | VERIFY_WIRE_FORMAT("Msg.error", RIEMANN_WIRE_BYTES); |
548 | 0 | len = riemann_dissect_string(riemann_tree, tvb, offset, hf_riemann_msg_error); |
549 | 0 | break; |
550 | 0 | case RIEMANN_FN_MSG_QUERY: |
551 | 0 | VERIFY_WIRE_FORMAT("Msg.query", RIEMANN_WIRE_BYTES); |
552 | 0 | if (!cinfo_set) { |
553 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Query: "); |
554 | 0 | cinfo_set = true; |
555 | 0 | } |
556 | 0 | len = riemann_dissect_query(pinfo, riemann_tree, tvb, offset); |
557 | 0 | break; |
558 | 0 | case RIEMANN_FN_MSG_EVENTS: |
559 | 0 | VERIFY_WIRE_FORMAT("Msg.events", RIEMANN_WIRE_BYTES); |
560 | 0 | if (!cinfo_set) { |
561 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Event: "); |
562 | 0 | cinfo_set = true; |
563 | 0 | } |
564 | 0 | len = riemann_dissect_event(pinfo, riemann_tree, tvb, offset); |
565 | 0 | break; |
566 | 0 | case RIEMANN_FN_MSG_STATES: |
567 | 0 | VERIFY_WIRE_FORMAT("Msg.states", RIEMANN_WIRE_BYTES); |
568 | 0 | if (!cinfo_set) { |
569 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "State: "); |
570 | 0 | cinfo_set = true; |
571 | 0 | } |
572 | 0 | len = riemann_dissect_state(pinfo, riemann_tree, tvb, offset); |
573 | 0 | break; |
574 | 0 | default: |
575 | 0 | len = 0; |
576 | 0 | UNKNOWN_FIELD_NUMBER_FOR("Msg"); |
577 | 0 | } |
578 | 0 | offset += len; |
579 | 0 | size -= len; |
580 | 0 | } |
581 | 0 | VERIFY_SIZE_FOR("Msg"); |
582 | |
|
583 | 0 | return offset - orig_offset; |
584 | 0 | } |
585 | | |
586 | | static bool |
587 | | is_riemann(tvbuff_t *tvb, unsigned offset) |
588 | 0 | { |
589 | 0 | uint32_t reported_length = tvb_reported_length_remaining(tvb, offset); |
590 | 0 | uint32_t captured_length = tvb_captured_length_remaining(tvb, offset); |
591 | 0 | uint64_t tag, field_number, wire_format; |
592 | 0 | unsigned len; |
593 | |
|
594 | 0 | if ((reported_length < RIEMANN_MIN_LENGTH) || |
595 | 0 | (captured_length < RIEMANN_MIN_NEEDED_FOR_HEURISTICS)) { |
596 | 0 | return false; |
597 | 0 | } |
598 | 0 | tag = riemann_get_uint64(tvb, offset, &len); |
599 | 0 | field_number = tag >> 3; |
600 | 0 | wire_format = tag & 0x7; |
601 | 0 | if ((field_number == RIEMANN_FN_MSG_OK && wire_format == RIEMANN_WIRE_INTEGER) || |
602 | 0 | (field_number == RIEMANN_FN_MSG_ERROR && wire_format == RIEMANN_WIRE_BYTES) || |
603 | 0 | (field_number == RIEMANN_FN_MSG_QUERY && wire_format == RIEMANN_WIRE_BYTES) || |
604 | 0 | (field_number == RIEMANN_FN_MSG_EVENTS && wire_format == RIEMANN_WIRE_BYTES) || |
605 | 0 | (field_number == RIEMANN_FN_MSG_STATES && wire_format == RIEMANN_WIRE_BYTES)) { |
606 | 0 | return true; |
607 | 0 | } |
608 | 0 | return false; |
609 | 0 | } |
610 | | |
611 | | static int |
612 | | dissect_riemann(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset) |
613 | 0 | { |
614 | 0 | proto_item *pi; |
615 | 0 | proto_tree *riemann_tree; |
616 | |
|
617 | 0 | if (!is_riemann(tvb, offset)) |
618 | 0 | return 0; |
619 | | |
620 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "riemann"); |
621 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
622 | |
|
623 | 0 | pi = proto_tree_add_item(tree, proto_riemann, tvb, offset, -1, ENC_NA); |
624 | 0 | riemann_tree = proto_item_add_subtree(pi, ett_riemann); |
625 | |
|
626 | 0 | return riemann_dissect_msg(pinfo, pi, riemann_tree, tvb, offset); |
627 | 0 | } |
628 | | |
629 | | static int |
630 | | dissect_riemann_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
631 | 0 | { |
632 | 0 | return dissect_riemann(tvb, pinfo, tree, 0); |
633 | 0 | } |
634 | | |
635 | | static int |
636 | | dissect_riemann_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
637 | 0 | { |
638 | 0 | return dissect_riemann(tvb, pinfo, tree, 4); |
639 | 0 | } |
640 | | |
641 | | static unsigned |
642 | | get_riemann_tcp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, |
643 | | int offset, void *data _U_) |
644 | 0 | { |
645 | 0 | return (tvb_get_ntohl(tvb, offset) + 4); |
646 | 0 | } |
647 | | |
648 | | static int |
649 | | dissect_riemann_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
650 | 0 | { |
651 | 0 | tcp_dissect_pdus(tvb, pinfo, tree, true, 4, get_riemann_tcp_pdu_len, dissect_riemann_tcp_pdu, data); |
652 | |
|
653 | 0 | return tvb_captured_length(tvb); |
654 | 0 | } |
655 | | |
656 | | void |
657 | | proto_register_riemann(void) |
658 | 15 | { |
659 | 15 | expert_module_t *riemann_expert_module; |
660 | | |
661 | 15 | static hf_register_info hf[] = { |
662 | 15 | { &hf_riemann_msg_ok, |
663 | 15 | { "ok", "riemann.msg.ok", |
664 | 15 | FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } |
665 | 15 | }, |
666 | 15 | { &hf_riemann_msg_error, |
667 | 15 | { "error", "riemann.msg.error", |
668 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
669 | 15 | }, |
670 | 15 | { &hf_riemann_attribute, |
671 | 15 | { "attribute", "riemann.attribute", |
672 | 15 | FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } |
673 | 15 | }, |
674 | 15 | { &hf_riemann_attribute_key, |
675 | 15 | { "key", "riemann.attribute.key", |
676 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
677 | 15 | }, |
678 | 15 | { &hf_riemann_attribute_value, |
679 | 15 | { "value", "riemann.attribute.value", |
680 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
681 | 15 | }, |
682 | 15 | { &hf_riemann_query, |
683 | 15 | { "query", "riemann.query", |
684 | 15 | FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } |
685 | 15 | }, |
686 | 15 | { &hf_riemann_query_string, |
687 | 15 | { "string", "riemann.query.string", |
688 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
689 | 15 | }, |
690 | 15 | { &hf_riemann_event, |
691 | 15 | { "event", "riemann.event", |
692 | 15 | FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } |
693 | 15 | }, |
694 | 15 | { &hf_riemann_event_state, |
695 | 15 | { "state", "riemann.event.state", |
696 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
697 | 15 | }, |
698 | 15 | { &hf_riemann_event_service, |
699 | 15 | { "service", "riemann.event.service", |
700 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
701 | 15 | }, |
702 | 15 | { &hf_riemann_event_host, |
703 | 15 | { "host", "riemann.event.host", |
704 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
705 | 15 | }, |
706 | 15 | { &hf_riemann_event_description, |
707 | 15 | { "description", "riemann.event.description", |
708 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
709 | 15 | }, |
710 | 15 | { &hf_riemann_event_tag, |
711 | 15 | { "tag", "riemann.event.tag", |
712 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
713 | 15 | }, |
714 | 15 | { &hf_riemann_event_time, |
715 | 15 | { "time", "riemann.event.time", |
716 | 15 | FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL } |
717 | 15 | }, |
718 | 15 | { &hf_riemann_event_ttl, |
719 | 15 | { "ttl", "riemann.event.ttl", |
720 | 15 | FT_FLOAT, BASE_NONE, NULL, 0, NULL, HFILL } |
721 | 15 | }, |
722 | 15 | { &hf_riemann_event_metric_d, |
723 | 15 | { "metric_d", "riemann.event.metric_d", |
724 | 15 | FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL } |
725 | 15 | }, |
726 | 15 | { &hf_riemann_event_metric_f, |
727 | 15 | { "metric_f", "riemann.event.metric_f", |
728 | 15 | FT_FLOAT, BASE_NONE, NULL, 0, NULL, HFILL } |
729 | 15 | }, |
730 | 15 | { &hf_riemann_event_time_micros, |
731 | 15 | { "time_micros", "riemann.event.time_micros", |
732 | 15 | FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL } |
733 | 15 | }, |
734 | 15 | { &hf_riemann_event_metric_sint64, |
735 | 15 | { "metric_sint64", "riemann.event.metric_sint64", |
736 | 15 | FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL } |
737 | 15 | }, |
738 | 15 | { &hf_riemann_state, |
739 | 15 | { "state", "riemann.state", |
740 | 15 | FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } |
741 | 15 | }, |
742 | 15 | { &hf_riemann_state_service, |
743 | 15 | { "service", "riemann.state.service", |
744 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
745 | 15 | }, |
746 | 15 | { &hf_riemann_state_host, |
747 | 15 | { "host", "riemann.state.host", |
748 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
749 | 15 | }, |
750 | 15 | { &hf_riemann_state_description, |
751 | 15 | { "description", "riemann.state.description", |
752 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
753 | 15 | }, |
754 | 15 | { &hf_riemann_state_tag, |
755 | 15 | { "tag", "riemann.state.tag", |
756 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
757 | 15 | }, |
758 | 15 | { &hf_riemann_state_time, |
759 | 15 | { "time", "riemann.state.time", |
760 | 15 | FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL } |
761 | 15 | }, |
762 | 15 | { &hf_riemann_state_ttl, |
763 | 15 | { "ttl", "riemann.state.ttl", |
764 | 15 | FT_FLOAT, BASE_NONE, NULL, 0, NULL, HFILL } |
765 | 15 | }, |
766 | 15 | { &hf_riemann_state_state, |
767 | 15 | { "state", "riemann.state.state", |
768 | 15 | FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } |
769 | 15 | }, |
770 | 15 | { &hf_riemann_state_once, |
771 | 15 | { "once", "riemann.state.once", |
772 | 15 | FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } |
773 | 15 | } |
774 | 15 | }; |
775 | | |
776 | 15 | static ei_register_info ei[] = { |
777 | 15 | { &ei_error_unknown_wire_tag, |
778 | 15 | { "riemann.unknown_wire_tag", PI_MALFORMED, PI_ERROR, |
779 | 15 | "Invalid format type", EXPFILL }}, |
780 | 15 | { &ei_error_unknown_field_number, |
781 | 15 | { "riemann.unknown_field_number", PI_MALFORMED, PI_ERROR, |
782 | 15 | "Unknown field number", EXPFILL }}, |
783 | 15 | { &ei_error_insufficient_data, |
784 | 15 | { "riemann.insufficient_data", PI_MALFORMED, PI_ERROR, |
785 | 15 | "Insufficient data", EXPFILL }} |
786 | 15 | }; |
787 | | |
788 | 15 | static int *ett[] = { |
789 | 15 | &ett_riemann, |
790 | 15 | &ett_query, |
791 | 15 | &ett_event, |
792 | 15 | &ett_attribute, |
793 | 15 | &ett_state |
794 | 15 | }; |
795 | | |
796 | 15 | proto_riemann = proto_register_protocol("Riemann", "Riemann", "riemann"); |
797 | 15 | riemann_expert_module = expert_register_protocol(proto_riemann); |
798 | 15 | expert_register_field_array(riemann_expert_module, ei, array_length(ei)); |
799 | | |
800 | 15 | proto_register_field_array(proto_riemann, hf, array_length(hf)); |
801 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
802 | | |
803 | 15 | riemann_udp_handle = register_dissector("riemann.udp", dissect_riemann_udp, proto_riemann); |
804 | 15 | riemann_tcp_handle = register_dissector("riemann.tcp", dissect_riemann_tcp, proto_riemann); |
805 | 15 | } |
806 | | |
807 | | void |
808 | | proto_reg_handoff_riemann(void) |
809 | 15 | { |
810 | 15 | dissector_add_for_decode_as_with_preference("tcp.port", riemann_tcp_handle); |
811 | 15 | dissector_add_for_decode_as_with_preference("udp.port", riemann_udp_handle); |
812 | 15 | } |
813 | | |
814 | | /* |
815 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
816 | | * |
817 | | * Local variables: |
818 | | * c-basic-offset: 4 |
819 | | * tab-width: 8 |
820 | | * indent-tabs-mode: nil |
821 | | * End: |
822 | | * |
823 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
824 | | * :indentSize=4:tabSize=8:noTabs=true: |
825 | | */ |