2 * Routines for the mate Facility's Pseudo-Protocol dissection
4 * Copyright 2004, Luis E. Garcia Ontanon <gopo@webflies.org>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 /**************************************************************************
15 * This is the pseudo protocol dissector for the mate module. ***
16 * It is intended for this to be just the user interface to the module. ***
17 **************************************************************************/
22 #include <epan/expert.h>
24 void proto_register_mate(void);
25 void proto_reg_handoff_mate(void);
27 static mate_config
* mc
;
29 static int proto_mate
;
31 static int hf_mate_released_time
;
32 static int hf_mate_duration
;
33 static int hf_mate_number_of_pdus
;
34 static int hf_mate_started_at
;
35 static int hf_mate_gop_key
;
37 static expert_field ei_mate_undefined_attribute
;
39 static const char* pref_mate_config_filename
= "";
40 static const char* current_mate_config_filename
;
43 static int pref_avp_debug_general
;
44 static int pref_avp_debug_avp
;
45 static int pref_avp_debug_avp_op
;
46 static int pref_avp_debug_avpl
;
47 static int pref_avp_debug_avpl_op
;
50 static dissector_handle_t mate_handle
;
53 pdu_attrs_tree(proto_tree
* tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, mate_pdu
* pdu
)
59 avpl_t
= proto_tree_add_subtree_format(tree
,tvb
,0,0,pdu
->cfg
->ett_attr
,NULL
,"%s Attributes",pdu
->cfg
->name
);
61 for ( c
= pdu
->avpl
->null
.next
; c
->avp
; c
= c
->next
) {
62 hfi_p
= (int *)g_hash_table_lookup(pdu
->cfg
->my_hfids
,(char*)c
->avp
->n
);
65 proto_tree_add_string(avpl_t
,*hfi_p
,tvb
,0,0,c
->avp
->v
);
67 proto_tree_add_expert_format(avpl_t
,pinfo
,&ei_mate_undefined_attribute
,tvb
,0,0,"Undefined attribute: %s=%s",c
->avp
->n
, c
->avp
->v
);
73 gop_attrs_tree(proto_tree
* tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, mate_gop
* gop
)
79 avpl_t
= proto_tree_add_subtree_format(tree
,tvb
,0,0,gop
->cfg
->ett_attr
,NULL
,"%s Attributes",gop
->cfg
->name
);
81 for ( c
= gop
->avpl
->null
.next
; c
->avp
; c
= c
->next
) {
82 hfi_p
= (int *)g_hash_table_lookup(gop
->cfg
->my_hfids
,(char*)c
->avp
->n
);
85 proto_tree_add_string(avpl_t
,*hfi_p
,tvb
,0,0,c
->avp
->v
);
87 proto_tree_add_expert_format(avpl_t
,pinfo
,&ei_mate_undefined_attribute
,tvb
,0,0,"Undefined attribute: %s=%s",c
->avp
->n
, c
->avp
->v
);
93 gog_attrs_tree(proto_tree
* tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, mate_gog
* gog
)
99 avpl_t
= proto_tree_add_subtree_format(tree
,tvb
,0,0,gog
->cfg
->ett_attr
,NULL
,"%s Attributes",gog
->cfg
->name
);
101 for ( c
= gog
->avpl
->null
.next
; c
->avp
; c
= c
->next
) {
102 hfi_p
= (int *)g_hash_table_lookup(gog
->cfg
->my_hfids
,(char*)c
->avp
->n
);
105 proto_tree_add_string(avpl_t
,*hfi_p
,tvb
,0,0,c
->avp
->v
);
107 proto_tree_add_expert_format(avpl_t
,pinfo
,&ei_mate_undefined_attribute
,tvb
,0,0,"Undefined attribute: %s=%s",c
->avp
->n
, c
->avp
->v
);
112 static void mate_gop_tree(proto_tree
* pdu_tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, mate_gop
* gop
);
115 mate_gog_tree(proto_tree
* tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, mate_gog
* gog
, mate_gop
* gop
)
117 proto_item
*gog_item
;
118 proto_tree
*gog_tree
;
119 proto_tree
*gog_time_tree
;
120 proto_item
*gog_gops_item
;
121 proto_tree
*gog_gops_tree
;
123 proto_item
*gog_gop_item
;
124 proto_tree
*gog_gop_tree
;
127 gog_item
= proto_tree_add_uint(tree
,gog
->cfg
->hfid
,tvb
,0,0,gog
->id
);
128 gog_tree
= proto_item_add_subtree(gog_item
,gog
->cfg
->ett
);
130 gog_attrs_tree(gog_tree
,pinfo
,tvb
,gog
);
132 if (gog
->cfg
->show_times
) {
133 gog_time_tree
= proto_tree_add_subtree_format(gog_tree
,tvb
,0,0,gog
->cfg
->ett_times
,NULL
,"%s Times",gog
->cfg
->name
);
135 proto_tree_add_double(gog_time_tree
, gog
->cfg
->hfid_start_time
, tvb
, 0, 0, gog
->start_time
);
136 proto_tree_add_double(gog_time_tree
, gog
->cfg
->hfid_last_time
, tvb
, 0, 0, gog
->last_time
- gog
->start_time
);
139 gog_gops_item
= proto_tree_add_uint(gog_tree
, gog
->cfg
->hfid_gog_num_of_gops
, tvb
, 0, 0, gog
->num_of_gops
);
141 gog_gops_tree
= proto_item_add_subtree(gog_gops_item
, gog
->cfg
->ett_children
);
143 for (gog_gops
= gog
->gops
; gog_gops
; gog_gops
= gog_gops
->next
) {
145 if (gop
!= gog_gops
) {
146 if (gog
->cfg
->gop_tree_mode
== GOP_FULL_TREE
) {
147 mate_gop_tree(gog_gops_tree
, pinfo
, tvb
, gog_gops
);
149 gog_gop_item
= proto_tree_add_uint(gog_gops_tree
,gog_gops
->cfg
->hfid
,tvb
,0,0,gog_gops
->id
);
151 if (gog
->cfg
->gop_tree_mode
== GOP_BASIC_TREE
) {
152 gog_gop_tree
= proto_item_add_subtree(gog_gop_item
, gog
->cfg
->ett_gog_gop
);
154 proto_tree_add_double(gog_gop_tree
, hf_mate_started_at
, tvb
,0,0,gog_gops
->start_time
);
156 proto_tree_add_double_format(gog_gop_tree
, hf_mate_duration
, tvb
,0,0, gog_gops
->last_time
- gog_gops
->start_time
,
157 "%s Duration: %f", gog_gops
->cfg
->name
, gog_gops
->last_time
- gog_gops
->start_time
);
159 if (gog_gops
->released
)
160 proto_tree_add_double_format(gog_gop_tree
, hf_mate_released_time
, tvb
,0,0, gog_gops
->release_time
- gog_gops
->start_time
,
161 "%s has been released, Time: %f", gog_gops
->cfg
->name
, gog_gops
->release_time
- gog_gops
->start_time
);
163 proto_tree_add_uint(gog_gop_tree
, hf_mate_number_of_pdus
, tvb
,0,0, gog_gops
->num_of_pdus
);
165 if (gop
->pdus
&& gop
->cfg
->pdu_tree_mode
!= GOP_NO_TREE
) {
166 proto_tree_add_uint(gog_gop_tree
,gog
->cfg
->hfid_gog_gopstart
,tvb
,0,0,gog_gops
->pdus
->frame
);
168 for (pdu
= gog_gops
->pdus
->next
; pdu
; pdu
= pdu
->next
) {
170 proto_tree_add_uint(gog_gop_tree
,gog
->cfg
->hfid_gog_gopstop
,tvb
,0,0,pdu
->frame
);
179 proto_tree_add_uint_format(gog_gops_tree
,gop
->cfg
->hfid
,tvb
,0,0,gop
->id
,"current %s Gop: %d",gop
->cfg
->name
,gop
->id
);
185 mate_gop_tree(proto_tree
* tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, mate_gop
* gop
)
187 proto_item
*gop_item
;
188 proto_tree
*gop_time_tree
;
189 proto_tree
*gop_tree
;
190 proto_item
*gop_pdu_item
;
191 proto_tree
*gop_pdu_tree
;
196 const char* type_str
;
199 gop_item
= proto_tree_add_uint(tree
,gop
->cfg
->hfid
,tvb
,0,0,gop
->id
);
200 gop_tree
= proto_item_add_subtree(gop_item
, gop
->cfg
->ett
);
202 if (gop
->gop_key
) proto_tree_add_string(gop_tree
,hf_mate_gop_key
,tvb
,0,0,gop
->gop_key
);
204 gop_attrs_tree(gop_tree
,pinfo
,tvb
,gop
);
206 if (gop
->cfg
->show_times
) {
207 gop_time_tree
= proto_tree_add_subtree_format(gop_tree
,tvb
,0,0,gop
->cfg
->ett_times
,NULL
,"%s Times",gop
->cfg
->name
);
209 proto_tree_add_double(gop_time_tree
, gop
->cfg
->hfid_start_time
, tvb
, 0, 0, gop
->start_time
);
212 proto_tree_add_double(gop_time_tree
, gop
->cfg
->hfid_stop_time
, tvb
, 0, 0, gop
->release_time
- gop
->start_time
);
213 proto_tree_add_double(gop_time_tree
, gop
->cfg
->hfid_last_time
, tvb
, 0, 0, gop
->last_time
- gop
->start_time
);
215 proto_tree_add_double(gop_time_tree
, gop
->cfg
->hfid_last_time
, tvb
, 0, 0, gop
->last_time
- gop
->start_time
);
219 gop_pdu_item
= proto_tree_add_uint(gop_tree
, gop
->cfg
->hfid_gop_num_pdus
, tvb
, 0, 0,gop
->num_of_pdus
);
221 if (gop
->cfg
->pdu_tree_mode
!= GOP_NO_TREE
) {
223 gop_pdu_tree
= proto_item_add_subtree(gop_pdu_item
, gop
->cfg
->ett_children
);
225 rel_time
= gop
->start_time
;
227 type_str
= (gop
->cfg
->pdu_tree_mode
== GOP_FRAME_TREE
) ? "in frame:" : "id:";
229 for (gop_pdus
= gop
->pdus
; gop_pdus
; gop_pdus
= gop_pdus
->next
) {
231 pdu_item
= (gop
->cfg
->pdu_tree_mode
== GOP_FRAME_TREE
) ? gop_pdus
->frame
: gop_pdus
->id
;
233 if (gop_pdus
->is_start
) {
235 } else if (gop_pdus
->is_stop
) {
237 } else if (gop_pdus
->after_release
) {
238 pdu_str
= "After stop ";
243 pdu_rel_time
= gop_pdus
->time_in_gop
!= 0.0 ? gop_pdus
->time_in_gop
- rel_time
: 0.0;
245 proto_tree_add_uint_format(gop_pdu_tree
,gop
->cfg
->hfid_gop_pdu
,tvb
,0,0,pdu_item
,
246 "%sPDU: %s %i (%f : %f)",pdu_str
, type_str
,
247 pdu_item
, gop_pdus
->time_in_gop
,
250 rel_time
= gop_pdus
->time_in_gop
;
258 mate_pdu_tree(mate_pdu
*pdu
, packet_info
*pinfo
, tvbuff_t
*tvb
, proto_item
*item
, proto_tree
* tree
)
260 proto_item
*pdu_item
;
261 proto_tree
*pdu_tree
;
265 if (pdu
->gop
&& pdu
->gop
->gog
) {
266 proto_item_append_text(item
," %s:%d->%s:%d->%s:%d",
267 pdu
->cfg
->name
,pdu
->id
,
268 pdu
->gop
->cfg
->name
,pdu
->gop
->id
,
269 pdu
->gop
->gog
->cfg
->name
,pdu
->gop
->gog
->id
);
270 } else if (pdu
->gop
) {
271 proto_item_append_text(item
," %s:%d->%s:%d",
272 pdu
->cfg
->name
,pdu
->id
,
273 pdu
->gop
->cfg
->name
,pdu
->gop
->id
);
275 proto_item_append_text(item
," %s:%d",pdu
->cfg
->name
,pdu
->id
);
278 pdu_item
= proto_tree_add_uint(tree
,pdu
->cfg
->hfid
,tvb
,0,0,pdu
->id
);
279 pdu_tree
= proto_item_add_subtree(pdu_item
, pdu
->cfg
->ett
);
280 proto_tree_add_double(pdu_tree
,pdu
->cfg
->hfid_pdu_rel_time
, tvb
, 0, 0, pdu
->rel_time
);
283 proto_tree_add_double(pdu_tree
,pdu
->cfg
->hfid_pdu_time_in_gop
, tvb
, 0, 0, pdu
->time_in_gop
);
284 mate_gop_tree(tree
,pinfo
,tvb
,pdu
->gop
);
287 mate_gog_tree(tree
,pinfo
,tvb
,pdu
->gop
->gog
,pdu
->gop
);
291 pdu_attrs_tree(pdu_tree
,pinfo
,tvb
,pdu
);
296 mate_tree(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
302 /* If there is no MATE configuration, don't claim the packet */
306 /* There is a MATE configuration, just no tree, so there's nothing to do */
308 return tvb_captured_length(tvb
);
310 mate_analyze_frame(mc
, pinfo
,tree
);
312 if (( pdus
= mate_get_pdus(pinfo
->num
) )) {
313 for ( ; pdus
; pdus
= pdus
->next_in_frame
) {
314 mate_i
= proto_tree_add_protocol_format(tree
,mc
->hfid_mate
,tvb
,0,0,"MATE");
315 mate_t
= proto_item_add_subtree(mate_i
, mc
->ett_root
);
316 mate_pdu_tree(pdus
,pinfo
,tvb
,mate_i
,mate_t
);
319 return tvb_captured_length(tvb
);
323 initialize_mate(void)
325 initialize_mate_runtime(mc
);
326 #ifdef _AVP_DEBUGGING
327 setup_avp_debug(mc
->dbg_facility
,
328 &pref_avp_debug_general
,
330 &pref_avp_debug_avp_op
,
331 &pref_avp_debug_avpl
,
332 &pref_avp_debug_avpl_op
);
337 flush_mate_debug(void)
339 /* Flush debug information */
340 if (mc
->dbg_facility
)
341 fflush(mc
->dbg_facility
);
346 proto_reg_handoff_mate(void)
348 if ( *pref_mate_config_filename
!= '\0' ) {
350 if (current_mate_config_filename
) {
351 report_failure("MATE cannot reconfigure itself.\n"
352 "For changes to be applied you have to restart Wireshark\n");
357 mc
= mate_make_config(pref_mate_config_filename
,proto_mate
);
360 /* XXX: alignment warnings, what do they mean? */
361 proto_register_field_array(proto_mate
, (hf_register_info
*)(void *)mc
->hfrs
->data
, mc
->hfrs
->len
);
362 proto_register_subtree_array((int**)(void*)mc
->ett
->data
, mc
->ett
->len
);
363 register_init_routine(initialize_mate
);
364 register_postseq_cleanup_routine(flush_mate_debug
);
367 * Set the list of hfids we want.
369 set_postdissector_wanted_hfids(mate_handle
,
371 /* XXX: Due to #17877, any protocol added to the tree with length -1
372 * that changes its length later (and there are many, such as TCP)
373 * doesn't actually change its length unless the tree is visible,
374 * which means that entire range checking work in MATE to split up
375 * multiple PDUs of the target protocol in the same frame doesn't
376 * work. Set the tree as visible as with Lua postdissectors that
377 * need all fields. It's overkill and bad for performance, though.
379 epan_set_always_visible(true);
381 initialize_mate_runtime(mc
);
384 current_mate_config_filename
= pref_mate_config_filename
;
392 proto_register_mate(void)
394 static hf_register_info hf
[] = {
395 { &hf_mate_started_at
, { "Started at", "mate.started_at", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
396 { &hf_mate_duration
, { "Duration", "mate.duration", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
397 { &hf_mate_released_time
, { "Release time", "mate.released_time", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
398 { &hf_mate_number_of_pdus
, { "Number of Pdus", "mate.number_of_pdus", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
399 { &hf_mate_gop_key
, { "GOP Key", "mate.gop_key", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
402 static ei_register_info ei
[] = {
403 { &ei_mate_undefined_attribute
, { "mate.undefined_attribute", PI_PROTOCOL
, PI_ERROR
, "Undefined attribute", EXPFILL
}},
406 expert_module_t
* expert_mate
;
407 module_t
*mate_module
;
409 proto_mate
= proto_register_protocol("Meta Analysis Tracing Engine", "MATE", "mate");
410 proto_register_field_array(proto_mate
, hf
, array_length(hf
));
411 expert_mate
= expert_register_protocol(proto_mate
);
412 expert_register_field_array(expert_mate
, ei
, array_length(ei
));
414 mate_handle
= register_dissector("mate",mate_tree
,proto_mate
);
415 mate_module
= prefs_register_protocol(proto_mate
, proto_reg_handoff_mate
);
416 prefs_register_filename_preference(mate_module
, "config",
417 "Configuration Filename",
418 "The name of the file containing the mate module's configuration",
419 &pref_mate_config_filename
, false);
420 #ifdef _AVP_DEBUGGING
421 prefs_register_uint_preference(mate_module
, "avp_debug_general",
423 "General debugging level (0..5)",
425 &pref_avp_debug_general
);
426 prefs_register_uint_preference(mate_module
, "avp_debug_avp",
428 "Attribute Value Pairs debugging level (0..5)",
430 &pref_avp_debug_avp
);
431 prefs_register_uint_preference(mate_module
, "avp_debug_avp_op",
432 "Debug AVP operations",
433 "Attribute Value Pairs operations debugging level (0..5)",
435 &pref_avp_debug_avp_op
);
436 prefs_register_uint_preference(mate_module
, "avp_debug_avpl",
438 "Attribute Value Pairs list debugging level (0..5)",
440 &pref_avp_debug_avpl
);
441 prefs_register_uint_preference(mate_module
, "avp_debug_avpl_op",
442 "Debug AVP list operations",
443 "Attribute Value Pairs list operations debugging level (0..5)",
445 &pref_avp_debug_avpl_op
);
448 register_postdissector(mate_handle
);
452 * Editor modelines - https://www.wireshark.org/tools/modelines.html
457 * indent-tabs-mode: t
460 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
461 * :indentSize=8:tabSize=8:noTabs=false: