2 * Collecting Expert information.
4 * Implemented as a tap named "expert".
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include "wmem/wmem.h"
39 /* proto_expert cannot be static because it's referenced in the
42 int proto_expert
= -1;
44 static int proto_malformed
= -1;
46 static int expert_tap
= -1;
47 static int highest_severity
= 0;
49 static int ett_expert
= -1;
50 static int ett_subexpert
= -1;
52 static int hf_expert_msg
= -1;
53 static int hf_expert_group
= -1;
54 static int hf_expert_severity
= -1;
58 const char* proto_name
;
59 int proto_id
; /* Cache this for registering hfs */
62 /* List which stores protocols and expert_info that have been registered */
63 typedef struct _gpa_expertinfo_t
{
65 guint32 allocated_len
;
66 expert_field_info
**ei
;
68 static gpa_expertinfo_t gpa_expertinfo
;
70 /* Possible values for a checksum evaluation */
71 const value_string expert_checksum_vals
[] = {
72 { EXPERT_CHECKSUM_DISABLED
, "Disabled" },
73 { EXPERT_CHECKSUM_UNKNOWN
, "Unknown" },
74 { EXPERT_CHECKSUM_GOOD
, "Good" },
75 { EXPERT_CHECKSUM_BAD
, "Bad" },
80 #define EXPERT_REGISTRAR_GET_NTH(eiindex, expinfo) \
81 if((guint)eiindex >= gpa_expertinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
82 g_error("Unregistered expert info! index=%d", eiindex); \
83 DISSECTOR_ASSERT_HINT((guint)eiindex < gpa_expertinfo.len, "Unregistered expert info!");\
84 expinfo = gpa_expertinfo.ei[eiindex];
87 expert_packet_init(void)
89 static hf_register_info hf
[] = {
91 { "Message", "_ws.expert.message", FT_STRING
, BASE_NONE
, NULL
, 0, "Wireshark expert information", HFILL
}
94 { "Group", "_ws.expert.group", FT_UINT32
, BASE_HEX
, VALS(expert_group_vals
), 0, "Wireshark expert group", HFILL
}
96 { &hf_expert_severity
,
97 { "Severity level", "_ws.expert.severity", FT_UINT32
, BASE_HEX
, VALS(expert_severity_vals
), 0, "Wireshark expert severity level", HFILL
}
100 static gint
*ett
[] = {
105 if (expert_tap
== -1) {
106 expert_tap
= register_tap("expert");
109 if (proto_expert
== -1) {
110 proto_expert
= proto_register_protocol("Expert Info", "Expert", "_ws.expert");
111 proto_register_field_array(proto_expert
, hf
, array_length(hf
));
112 proto_register_subtree_array(ett
, array_length(ett
));
113 proto_set_cant_toggle(proto_expert
);
116 highest_severity
= 0;
118 proto_malformed
= proto_get_id_by_filter_name("_ws.malformed");
124 gpa_expertinfo
.len
= 0;
125 gpa_expertinfo
.allocated_len
= 0;
126 gpa_expertinfo
.ei
= NULL
;
130 expert_packet_cleanup(void)
137 if (gpa_expertinfo
.allocated_len
) {
138 gpa_expertinfo
.len
= 0;
139 gpa_expertinfo
.allocated_len
= 0;
140 g_free(gpa_expertinfo
.ei
);
141 gpa_expertinfo
.ei
= NULL
;
147 expert_get_highest_severity(void)
149 return highest_severity
;
153 expert_update_comment_count(guint64 count
)
155 if (count
==0 && highest_severity
==PI_COMMENT
)
156 highest_severity
= 0;
159 expert_module_t
*expert_register_protocol(int id
)
161 expert_module_t
*module
;
162 protocol_t
*protocol
;
164 protocol
= find_protocol_by_id(id
);
166 module
= wmem_new(wmem_epan_scope(), expert_module_t
);
167 module
->proto_id
= id
;
168 module
->proto_name
= proto_get_protocol_short_name(protocol
);
174 expert_register_field_init(expert_field_info
*expinfo
, expert_module_t
* module
)
176 expinfo
->protocol
= module
->proto_name
;
178 /* if we always add and never delete, then id == len - 1 is correct */
179 if (gpa_expertinfo
.len
>= gpa_expertinfo
.allocated_len
) {
180 if (!gpa_expertinfo
.ei
) {
181 gpa_expertinfo
.allocated_len
= PRE_ALLOC_EXPERT_FIELDS_MEM
;
182 gpa_expertinfo
.ei
= (expert_field_info
**)g_malloc(sizeof(expert_field_info
*)*PRE_ALLOC_EXPERT_FIELDS_MEM
);
184 gpa_expertinfo
.allocated_len
+= 1000;
185 gpa_expertinfo
.ei
= (expert_field_info
**)g_realloc(gpa_expertinfo
.ei
,
186 sizeof(expert_field_info
*)*gpa_expertinfo
.allocated_len
);
189 gpa_expertinfo
.ei
[gpa_expertinfo
.len
] = expinfo
;
190 gpa_expertinfo
.len
++;
191 expinfo
->id
= gpa_expertinfo
.len
- 1;
197 /* for use with static arrays only, since we don't allocate our own copies
198 of the expert_field_info struct contained within the exp_register_info struct */
200 expert_register_field_array(expert_module_t
* module
, ei_register_info
*exp
, const int num_records
)
203 ei_register_info
*ptr
= exp
;
205 for (i
= 0; i
< num_records
; i
++, ptr
++) {
207 * Make sure we haven't registered this yet.
208 * Most fields have variables associated with them
209 * that are initialized to -1; some have array elements,
210 * or possibly uninitialized variables, so we also allow
211 * 0 (which is unlikely to be the field ID we get back
212 * from "expert_register_field_init()").
214 if (ptr
->ids
->ei
!= -1 && ptr
->ids
->ei
!= 0) {
216 "Duplicate field detected in call to expert_register_field_array: '%s' is already registered\n",
217 ptr
->eiinfo
.summary
);
221 /* Register the field with the experts */
222 ptr
->ids
->ei
= expert_register_field_init(&ptr
->eiinfo
, module
);
224 /* Register with the header field info, so it's display filterable */
225 ptr
->eiinfo
.hf_info
.p_id
= &ptr
->ids
->hf
;
226 ptr
->eiinfo
.hf_info
.hfinfo
.abbrev
= ptr
->eiinfo
.name
;
227 ptr
->eiinfo
.hf_info
.hfinfo
.blurb
= ptr
->eiinfo
.summary
;
229 proto_register_field_array(module
->proto_id
, &ptr
->eiinfo
.hf_info
, 1);
233 /** clear flags according to the mask and set new flag values */
234 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
235 (fi->flags = (fi)->flags & ~(mask)); \
236 (fi->flags = (fi)->flags | (flags_in)); \
239 /* set's the PI_ flags to a protocol item
240 * (and its parent items till the toplevel) */
242 expert_set_item_flags(proto_item
*pi
, const int group
, const guint severity
)
244 if (pi
!= NULL
&& PITEM_FINFO(pi
) != NULL
&& (severity
>= FI_GET_FLAG(PITEM_FINFO(pi
), PI_SEVERITY_MASK
))) {
245 FI_REPLACE_FLAGS(PITEM_FINFO(pi
), PI_GROUP_MASK
, group
);
246 FI_REPLACE_FLAGS(PITEM_FINFO(pi
), PI_SEVERITY_MASK
, severity
);
248 /* propagate till toplevel item */
249 pi
= proto_item_get_parent(pi
);
250 expert_set_item_flags(pi
, group
, severity
);
255 expert_create_tree(proto_item
*pi
, int group
, int severity
, const char *msg
)
260 tree
= proto_item_add_subtree(pi
, ett_expert
);
261 ti
= proto_tree_add_protocol_format(tree
, proto_expert
, NULL
, 0, 0, "Expert Info (%s/%s): %s",
262 val_to_str(severity
, expert_severity_vals
, "Unknown (%u)"),
263 val_to_str(group
, expert_group_vals
, "Unknown (%u)"),
265 PROTO_ITEM_SET_GENERATED(ti
);
267 if (group
== PI_MALFORMED
) {
268 /* Add hidden malformed protocol filter */
269 proto_item
*malformed_ti
= proto_tree_add_item(tree
, proto_malformed
, NULL
, 0, 0, ENC_NA
);
270 PROTO_ITEM_SET_HIDDEN(malformed_ti
);
273 return proto_item_add_subtree(ti
, ett_subexpert
);
277 expert_set_info_vformat(packet_info
*pinfo
, proto_item
*pi
, int group
, int severity
, int hf_index
, gboolean use_vaformat
,
278 const char *format
, va_list ap
)
280 char formatted
[ITEM_LABEL_LENGTH
];
286 if (pinfo
== NULL
&& pi
&& pi
->tree_data
) {
287 pinfo
= PTREE_DATA(pi
)->pinfo
;
290 /* if this packet isn't loaded because of a read filter, don't output anything */
291 if (pinfo
== NULL
|| PINFO_FD_NUM(pinfo
) == 0) {
295 if (severity
> highest_severity
) {
296 highest_severity
= severity
;
299 if (pi
!= NULL
&& PITEM_FINFO(pi
) != NULL
) {
300 expert_set_item_flags(pi
, group
, severity
);
303 if ((pi
== NULL
) || (PITEM_FINFO(pi
) == NULL
) ||
304 ((guint
)severity
>= FI_GET_FLAG(PITEM_FINFO(pi
), PI_SEVERITY_MASK
))) {
305 col_add_str(pinfo
->cinfo
, COL_EXPERT
, val_to_str(severity
, expert_severity_vals
, "Unknown (%u)"));
309 g_vsnprintf(formatted
, ITEM_LABEL_LENGTH
, format
, ap
);
311 g_strlcpy(formatted
, format
, ITEM_LABEL_LENGTH
);
314 tree
= expert_create_tree(pi
, group
, severity
, formatted
);
316 if (hf_index
== -1) {
317 /* If no filterable expert info, just add the message */
318 ti
= proto_tree_add_string(tree
, hf_expert_msg
, NULL
, 0, 0, formatted
);
319 PROTO_ITEM_SET_GENERATED(ti
);
321 /* If filterable expert info, hide the "generic" form of the message,
322 and generate the formatted filterable expert info */
323 ti
= proto_tree_add_none_format(tree
, hf_index
, NULL
, 0, 0, "%s", formatted
);
324 PROTO_ITEM_SET_GENERATED(ti
);
325 ti
= proto_tree_add_string(tree
, hf_expert_msg
, NULL
, 0, 0, formatted
);
326 PROTO_ITEM_SET_HIDDEN(ti
);
329 ti
= proto_tree_add_uint_format_value(tree
, hf_expert_severity
, NULL
, 0, 0, severity
,
330 "%s", val_to_str_const(severity
, expert_severity_vals
, "Unknown"));
331 PROTO_ITEM_SET_GENERATED(ti
);
332 ti
= proto_tree_add_uint_format_value(tree
, hf_expert_group
, NULL
, 0, 0, group
,
333 "%s", val_to_str_const(group
, expert_group_vals
, "Unknown"));
334 PROTO_ITEM_SET_GENERATED(ti
);
336 tap
= have_tap_listener(expert_tap
);
341 ei
= ep_new(expert_info_t
);
343 ei
->packet_num
= PINFO_FD_NUM(pinfo
);
345 ei
->severity
= severity
;
346 ei
->protocol
= pinfo
->current_proto
;
347 ei
->summary
= ep_strdup(formatted
);
349 /* if we have a proto_item (not a faked item), set expert attributes to it */
350 if (pi
!= NULL
&& PITEM_FINFO(pi
) != NULL
) {
356 tap_queue_packet(expert_tap
, pinfo
, ei
);
361 expert_add_info_format_internal(packet_info
*pinfo
, proto_item
*pi
, int group
, int severity
, const char *format
, ...)
365 va_start(ap
, format
);
366 expert_set_info_vformat(pinfo
, pi
, group
, severity
, -1, TRUE
, format
, ap
);
371 expert_add_info(packet_info
*pinfo
, proto_item
*pi
, expert_field
*expindex
)
373 expert_field_info
* eiinfo
;
375 /* Look up the item */
376 EXPERT_REGISTRAR_GET_NTH(expindex
->ei
, eiinfo
);
378 expert_set_info_vformat(pinfo
, pi
, eiinfo
->group
, eiinfo
->severity
, *eiinfo
->hf_info
.p_id
, FALSE
, eiinfo
->summary
, NULL
);
382 expert_add_info_format(packet_info
*pinfo
, proto_item
*pi
, expert_field
*expindex
, const char *format
, ...)
385 expert_field_info
* eiinfo
;
387 /* Look up the item */
388 EXPERT_REGISTRAR_GET_NTH(expindex
->ei
, eiinfo
);
390 va_start(ap
, format
);
391 expert_set_info_vformat(pinfo
, pi
, eiinfo
->group
, eiinfo
->severity
, *eiinfo
->hf_info
.p_id
, TRUE
, format
, ap
);
396 proto_tree_add_expert(proto_tree
*tree
, packet_info
*pinfo
, expert_field
* expindex
,
397 tvbuff_t
*tvb
, gint start
, gint length
)
399 expert_field_info
* eiinfo
;
402 /* Look up the item */
403 EXPERT_REGISTRAR_GET_NTH(expindex
->ei
, eiinfo
);
405 ti
= proto_tree_add_text(tree
, tvb
, start
, length
, "%s", eiinfo
->summary
);
406 expert_set_info_vformat(pinfo
, ti
, eiinfo
->group
, eiinfo
->severity
, *eiinfo
->hf_info
.p_id
, FALSE
, eiinfo
->summary
, NULL
);
411 proto_tree_add_expert_format(proto_tree
*tree
, packet_info
*pinfo
, expert_field
* expindex
,
412 tvbuff_t
*tvb
, gint start
, gint length
, const char *format
, ...)
415 expert_field_info
* eiinfo
;
418 /* Look up the item */
419 EXPERT_REGISTRAR_GET_NTH(expindex
->ei
, eiinfo
);
421 va_start(ap
, format
);
422 ti
= proto_tree_add_text_valist(tree
, tvb
, start
, length
, format
, ap
);
425 va_start(ap
, format
);
426 expert_set_info_vformat(pinfo
, ti
, eiinfo
->group
, eiinfo
->severity
, *eiinfo
->hf_info
.p_id
, TRUE
, format
, ap
);