3 * Top-most dissector. Decides dissector based on Wiretap Encapsulation Type.
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 2000 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
37 #include <epan/timestamp.h>
38 #include <epan/tvbuff.h>
39 #include "packet-frame.h"
40 #include <epan/prefs.h>
42 #include <epan/expert.h>
43 #include <epan/crypt/crypt-md5.h>
46 #include "color_filters.h"
49 int hf_frame_arrival_time = -1;
50 static int hf_frame_time_invalid = -1;
51 static int hf_frame_time_delta = -1;
52 static int hf_frame_time_delta_displayed = -1;
53 static int hf_frame_time_relative = -1;
54 static int hf_frame_time_reference = -1;
55 int hf_frame_number = -1;
56 int hf_frame_len = -1;
57 int hf_frame_capture_len = -1;
58 static int hf_frame_p2p_dir = -1;
59 static int hf_frame_file_off = -1;
60 static int hf_frame_md5_hash = -1;
61 static int hf_frame_marked = -1;
62 static int hf_link_number = -1;
63 static int hf_frame_protocols = -1;
64 static int hf_frame_color_filter_name = -1;
65 static int hf_frame_color_filter_text = -1;
67 static int proto_short = -1;
68 int proto_malformed = -1;
69 static int proto_unreassembled = -1;
71 static gint ett_frame = -1;
73 static int frame_tap = -1;
75 static dissector_handle_t data_handle;
76 static dissector_handle_t docsis_handle;
79 static gboolean show_file_off = FALSE;
80 static gboolean force_docsis_encap = FALSE;
81 static gboolean generate_md5_hash = FALSE;
83 static const value_string p2p_dirs[] = {
84 { P2P_DIR_UNKNOWN, "Unknown" },
85 { P2P_DIR_SENT, "Sent" },
86 { P2P_DIR_RECV, "Received" },
90 dissector_table_t wtap_encap_dissector_table;
92 static GSList *frame_end_routines = NULL;
95 * Routine used to register frame end routine. The routine should only
96 * be registred when the dissector is used in the frame, not in the
97 * proto_register_XXX function.
100 register_frame_end_routine(void (*func)(void))
102 frame_end_routines = g_slist_append(frame_end_routines, (gpointer)func);
105 typedef void (*void_func_t)(void);
108 call_frame_end_routine(gpointer routine, gpointer dummy _U_)
110 void_func_t func = (void_func_t)routine;
115 dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
117 proto_tree *fh_tree=NULL;
118 proto_item *volatile ti = NULL;
120 int cap_len = 0, frame_len = 0;
121 proto_tree *volatile tree;
123 guint32 frame_number;
125 frame_number=pinfo->fd->num; /* dummy so that the buildbot crashdumps
126 will show the packetnumber where the
131 pinfo->current_proto = "Frame";
133 if (pinfo->pseudo_header != NULL) {
134 switch (pinfo->fd->lnk_t) {
136 case WTAP_ENCAP_WFLEET_HDLC:
137 case WTAP_ENCAP_CHDLC_WITH_PHDR:
138 case WTAP_ENCAP_PPP_WITH_PHDR:
139 case WTAP_ENCAP_SDLC:
140 case WTAP_ENCAP_BLUETOOTH_H4:
141 case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
142 pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ?
143 P2P_DIR_SENT : P2P_DIR_RECV;
146 case WTAP_ENCAP_BLUETOOTH_HCI:
147 pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent;
150 case WTAP_ENCAP_LAPB:
151 case WTAP_ENCAP_FRELAY_WITH_PHDR:
153 (pinfo->pseudo_header->x25.flags & FROM_DCE) ?
154 P2P_DIR_RECV : P2P_DIR_SENT;
157 case WTAP_ENCAP_ISDN:
158 pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ?
159 P2P_DIR_SENT : P2P_DIR_RECV;
162 case WTAP_ENCAP_LINUX_LAPD:
163 pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 ||
164 pinfo->pseudo_header->lapd.pkttype == 4) ?
165 P2P_DIR_SENT : P2P_DIR_RECV;
168 case WTAP_ENCAP_MTP2_WITH_PHDR:
169 pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ?
170 P2P_DIR_SENT : P2P_DIR_RECV;
171 pinfo->link_number = pinfo->pseudo_header->mtp2.link_number;
172 pinfo->annex_a_used = pinfo->pseudo_header->mtp2.annex_a_used;
175 case WTAP_ENCAP_GSM_UM:
176 pinfo->p2p_dir = pinfo->pseudo_header->gsm_um.uplink ?
177 P2P_DIR_SENT : P2P_DIR_RECV;
183 /* Put in frame header information. */
185 cap_len = tvb_length(tvb);
186 frame_len = tvb_reported_length(tvb);
188 ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1,
189 "Frame %u (%u bytes on wire, %u bytes captured)", pinfo->fd->num, frame_len, cap_len);
191 fh_tree = proto_item_add_subtree(ti, ett_frame);
194 /* if FRAME is not referenced from any filters we dont need to worry about
195 generating any tree items. We must do this after we created the actual
196 protocol above so that proto hier stat still works though.
198 if(!proto_field_is_referenced(tree, proto_frame)){
205 ts = pinfo->fd->abs_ts;
207 proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
209 if(ts.nsecs < 0 || ts.nsecs >= 1000000000) {
210 item = proto_tree_add_none_format(fh_tree, hf_frame_time_invalid, tvb,
211 0, 0, "Arrival Time: Fractional second %09ld is invalid, the valid range is 0-1000000000", (long) ts.nsecs);
212 PROTO_ITEM_SET_GENERATED(item);
213 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "Arrival Time: Fractional second out of range (0-1000000000)");
216 ts = pinfo->fd->del_cap_ts;
218 item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
220 PROTO_ITEM_SET_GENERATED(item);
222 ts = pinfo->fd->del_dis_ts;
224 item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb,
226 PROTO_ITEM_SET_GENERATED(item);
228 ts = pinfo->fd->rel_ts;
230 item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
232 PROTO_ITEM_SET_GENERATED(item);
234 if(pinfo->fd->flags.ref_time){
235 ti = proto_tree_add_item(fh_tree, hf_frame_time_reference, tvb, 0, 0, FALSE);
236 PROTO_ITEM_SET_GENERATED(ti);
239 proto_tree_add_uint(fh_tree, hf_frame_number, tvb,
240 0, 0, pinfo->fd->num);
242 proto_tree_add_uint_format(fh_tree, hf_frame_len, tvb,
243 0, 0, frame_len, "Frame Length: %d byte%s", frame_len,
244 plurality(frame_len, "", "s"));
246 proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb,
247 0, 0, cap_len, "Capture Length: %d byte%s", cap_len,
248 plurality(cap_len, "", "s"));
250 if (generate_md5_hash) {
253 md5_byte_t digest[16];
254 gchar *digest_string;
256 cp = tvb_get_ptr(tvb, 0, cap_len);
259 md5_append(&md_ctx, cp, cap_len);
260 md5_finish(&md_ctx, digest);
262 digest_string = bytestring_to_str(digest, 16, '\0');
263 ti = proto_tree_add_string(fh_tree, hf_frame_md5_hash, tvb, 0, 0, digest_string);
264 PROTO_ITEM_SET_GENERATED(ti);
267 ti = proto_tree_add_boolean(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
268 PROTO_ITEM_SET_GENERATED(ti);
270 /* we are going to be using proto_item_append_string() on
271 * hf_frame_protocols, and we must therefore disable the
272 * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
273 * setting it as visible.
275 * See proto.h for details.
277 proto_tree_set_visible(fh_tree, TRUE);
279 ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb,
281 PROTO_ITEM_SET_GENERATED(ti);
282 pinfo->layer_names = g_string_new("");
284 /* Check for existences of P2P pseudo header */
285 if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) {
286 proto_tree_add_int(fh_tree, hf_frame_p2p_dir, tvb,
287 0, 0, pinfo->p2p_dir);
290 /* Check for existences of MTP2 link number */
291 if ((pinfo->pseudo_header != NULL ) && (pinfo->fd->lnk_t == WTAP_ENCAP_MTP2_WITH_PHDR)) {
292 proto_tree_add_uint(fh_tree, hf_link_number, tvb,
293 0, 0, pinfo->link_number);
297 proto_tree_add_int64_format(fh_tree, hf_frame_file_off, tvb,
298 0, 0, pinfo->fd->file_off,
299 "File Offset: %" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)",
300 pinfo->fd->file_off, pinfo->fd->file_off);
303 if(pinfo->fd->color_filter != NULL) {
304 color_filter_t *color_filter = pinfo->fd->color_filter;
305 item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb,
306 0, 0, color_filter->filter_name);
307 PROTO_ITEM_SET_GENERATED(item);
308 item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb,
309 0, 0, color_filter->filter_text);
310 PROTO_ITEM_SET_GENERATED(item);
313 if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) {
314 expert_add_info_format(pinfo, NULL, PI_MALFORMED, PI_WARN, "Arrival Time: Fractional second out of range (0-1000000000)");
318 /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */
321 /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */
322 /* (a running debugger will be called before the except part below) */
325 if ((force_docsis_encap) && (docsis_handle)) {
326 call_dissector(docsis_handle, tvb, pinfo, parent_tree);
328 if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
329 tvb, pinfo, parent_tree)) {
331 if (check_col(pinfo->cinfo, COL_PROTOCOL))
332 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
333 if (check_col(pinfo->cinfo, COL_INFO))
334 col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %u",
336 call_dissector(data_handle,tvb, pinfo, parent_tree);
340 } __except(TRUE /* handle all exceptions */) {
341 switch(GetExceptionCode()) {
342 case(STATUS_ACCESS_VIOLATION):
343 show_exception(tvb, pinfo, parent_tree, DissectorError,
344 "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
346 case(STATUS_INTEGER_DIVIDE_BY_ZERO):
347 show_exception(tvb, pinfo, parent_tree, DissectorError,
348 "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
350 case(STATUS_STACK_OVERFLOW):
351 show_exception(tvb, pinfo, parent_tree, DissectorError,
352 "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
353 /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */
355 /* XXX - add other hardware exception codes as required */
357 show_exception(tvb, pinfo, parent_tree, DissectorError,
358 g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
363 CATCH(OutOfMemoryError) {
367 show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
371 if (tree && pinfo->layer_names) {
372 proto_item_append_string(ti, pinfo->layer_names->str);
373 g_string_free(pinfo->layer_names, TRUE);
374 pinfo->layer_names = NULL;
377 /* Call postdissectors if we have any (while trying to avoid another
380 if (have_postdissector()) {
383 /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */
384 /* (a running debugger will be called before the except part below) */
387 call_all_postdissectors(tvb, pinfo, parent_tree);
389 } __except(TRUE /* handle all exceptions */) {
390 switch(GetExceptionCode()) {
391 case(STATUS_ACCESS_VIOLATION):
392 show_exception(tvb, pinfo, parent_tree, DissectorError,
393 "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
395 case(STATUS_INTEGER_DIVIDE_BY_ZERO):
396 show_exception(tvb, pinfo, parent_tree, DissectorError,
397 "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
399 case(STATUS_STACK_OVERFLOW):
400 show_exception(tvb, pinfo, parent_tree, DissectorError,
401 "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
402 /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */
404 /* XXX - add other hardware exception codes as required */
406 show_exception(tvb, pinfo, parent_tree, DissectorError,
407 g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
412 CATCH(OutOfMemoryError) {
416 show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
421 tap_queue_packet(frame_tap, pinfo, NULL);
424 if (frame_end_routines) {
425 g_slist_foreach(frame_end_routines, &call_frame_end_routine, NULL);
426 g_slist_free(frame_end_routines);
427 frame_end_routines = NULL;
432 show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
433 unsigned long exception, const char *exception_message)
435 static const char dissector_error_nomsg[] =
436 "Dissector writer didn't bother saying what the error was";
442 case ScsiBoundsError:
443 if (check_col(pinfo->cinfo, COL_INFO))
444 col_append_str(pinfo->cinfo, COL_INFO, "[SCSI transfer limited due to allocation_length too small]");
445 /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
446 "SCSI transfer limited due to allocation_length too small: %s truncated]", pinfo->current_proto);
447 /* Don't record ScsiBoundsError exceptions as expert events - they merely
448 * reflect a normal SCSI condition.
449 * (any case where it's caused by something else is a bug). */
450 /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
454 if (check_col(pinfo->cinfo, COL_INFO))
455 col_append_str(pinfo->cinfo, COL_INFO, "[Packet size limited during capture]");
456 /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
457 "[Packet size limited during capture: %s truncated]", pinfo->current_proto);
458 /* Don't record BoundsError exceptions as expert events - they merely
459 * reflect a capture done with a snapshot length too short to capture
461 * (any case where it's caused by something else is a bug). */
462 /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
465 case ReportedBoundsError:
466 show_reported_bounds_error(tvb, pinfo, tree);
470 if (check_col(pinfo->cinfo, COL_INFO))
471 col_append_fstr(pinfo->cinfo, COL_INFO,
472 "[Dissector bug, protocol %s: %s]",
473 pinfo->current_proto,
474 exception_message == NULL ?
475 dissector_error_nomsg : exception_message);
476 item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
477 "[Dissector bug, protocol %s: %s]",
478 pinfo->current_proto,
479 exception_message == NULL ?
480 dissector_error_nomsg : exception_message);
481 g_warning("Dissector bug, protocol %s, in packet %u: %s",
482 pinfo->current_proto, pinfo->fd->num,
483 exception_message == NULL ?
484 dissector_error_nomsg : exception_message);
485 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
487 exception_message == NULL ?
488 dissector_error_nomsg : exception_message);
492 /* XXX - we want to know, if an unknown exception passed until here, don't we? */
493 g_assert_not_reached();
498 show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
502 if (pinfo->fragmented) {
504 * We were dissecting an unreassembled fragmented
505 * packet when the exception was thrown, so the
506 * problem isn't that the dissector expected
507 * something but it wasn't in the packet, the
508 * problem is that the dissector expected something
509 * but it wasn't in the fragment we dissected.
511 if (check_col(pinfo->cinfo, COL_INFO))
512 col_append_fstr(pinfo->cinfo, COL_INFO,
513 "[Unreassembled Packet%s] ",
514 pinfo->noreassembly_reason);
515 item = proto_tree_add_protocol_format(tree, proto_unreassembled,
516 tvb, 0, 0, "[Unreassembled Packet%s: %s]",
517 pinfo->noreassembly_reason, pinfo->current_proto);
518 expert_add_info_format(pinfo, item, PI_REASSEMBLE, PI_WARN, "Unreassembled Packet (Exception occurred)");
520 if (check_col(pinfo->cinfo, COL_INFO))
521 col_append_str(pinfo->cinfo, COL_INFO,
522 "[Malformed Packet]");
523 item = proto_tree_add_protocol_format(tree, proto_malformed,
524 tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
525 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Malformed Packet (Exception occurred)");
530 proto_register_frame(void)
532 static hf_register_info hf[] = {
533 { &hf_frame_arrival_time,
534 { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
535 "Absolute time when this frame was captured", HFILL }},
537 { &hf_frame_time_invalid,
538 { "Arrival Timestamp invalid", "frame.time_invalid", FT_NONE, BASE_NONE, NULL, 0x0,
539 "The timestamp from the capture is out of the valid range", HFILL }},
541 { &hf_frame_time_delta,
542 { "Time delta from previous captured frame", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
546 { &hf_frame_time_delta_displayed,
547 { "Time delta from previous displayed frame", "frame.time_delta_displayed", FT_RELATIVE_TIME, BASE_NONE, NULL,
551 { &hf_frame_time_relative,
552 { "Time since reference or first frame", "frame.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL,
554 "Time relative to time reference or first frame", HFILL }},
556 { &hf_frame_time_reference,
557 { "This is a Time Reference frame", "frame.ref_time", FT_NONE, 0, NULL, 0x0,
558 "This frame is a Time Reference frame", HFILL }},
561 { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
565 { "Frame length on the wire", "frame.len", FT_UINT32, BASE_DEC, NULL, 0x0,
568 { &hf_frame_capture_len,
569 { "Frame length stored into the capture file", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
572 { &hf_frame_md5_hash,
573 { "Frame MD5 Hash", "frame.md5_hash", FT_STRING, 0, NULL, 0x0,
577 { "Point-to-Point Direction", "frame.p2p_dir", FT_INT8, BASE_DEC, VALS(p2p_dirs), 0x0,
581 { "Link Number", "frame.link_nr", FT_UINT16, BASE_DEC, NULL, 0x0,
584 { &hf_frame_file_off,
585 { "File Offset", "frame.file_off", FT_INT64, BASE_DEC, NULL, 0x0,
589 { "Frame is marked", "frame.marked", FT_BOOLEAN, 8, NULL, 0x0,
590 "Frame is marked in the GUI", HFILL }},
592 { &hf_frame_protocols,
593 { "Protocols in frame", "frame.protocols", FT_STRING, 0, NULL, 0x0,
594 "Protocols carried by this frame", HFILL }},
596 { &hf_frame_color_filter_name,
597 { "Coloring Rule Name", "frame.coloring_rule.name", FT_STRING, 0, NULL, 0x0,
598 "The frame matched the coloring rule with this name", HFILL }},
600 { &hf_frame_color_filter_text,
601 { "Coloring Rule String", "frame.coloring_rule.string", FT_STRING, 0, NULL, 0x0,
602 "The frame matched this coloring rule string", HFILL }}
604 static gint *ett[] = {
607 module_t *frame_module;
609 wtap_encap_dissector_table = register_dissector_table("wtap_encap",
610 "Wiretap encapsulation type", FT_UINT32, BASE_DEC);
612 proto_frame = proto_register_protocol("Frame", "Frame", "frame");
613 proto_register_field_array(proto_frame, hf, array_length(hf));
614 proto_register_subtree_array(ett, array_length(ett));
615 register_dissector("frame",dissect_frame,proto_frame);
617 /* You can't disable dissection of "Frame", as that would be
618 tantamount to not doing any dissection whatsoever. */
619 proto_set_cant_toggle(proto_frame);
621 proto_short = proto_register_protocol("Short Frame", "Short frame", "short");
622 proto_malformed = proto_register_protocol("Malformed Packet",
623 "Malformed packet", "malformed");
624 proto_unreassembled = proto_register_protocol(
625 "Unreassembled Fragmented Packet",
626 "Unreassembled fragmented packet", "unreassembled");
628 /* "Short Frame", "Malformed Packet", and "Unreassembled Fragmented
629 Packet" aren't really protocols, they're error indications;
630 disabling them makes no sense. */
631 proto_set_cant_toggle(proto_short);
632 proto_set_cant_toggle(proto_malformed);
633 proto_set_cant_toggle(proto_unreassembled);
635 /* Our preferences */
636 frame_module = prefs_register_protocol(proto_frame, NULL);
637 prefs_register_bool_preference(frame_module, "show_file_off",
638 "Show File Offset", "Show offset of frame in capture file", &show_file_off);
639 prefs_register_bool_preference(frame_module, "force_docsis_encap",
640 "Treat all frames as DOCSIS frames", "Treat all frames as DOCSIS Frames", &force_docsis_encap);
641 prefs_register_bool_preference(frame_module, "generate_md5_hash",
642 "Generate an MD5 hash of each frame",
643 "Whether or not MD5 hashes should be generated for each frame, useful for finding duplicate frames.",
646 frame_tap=register_tap("frame");
650 proto_reg_handoff_frame(void)
652 data_handle = find_dissector("data");
653 docsis_handle = find_dissector("docsis");