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.
31 #include <epan/packet.h>
32 #include <epan/timestamp.h>
33 #include <epan/tvbuff.h>
34 #include "packet-frame.h"
35 #include <epan/prefs.h>
37 #include <epan/expert.h>
40 #include "color_filters.h"
43 int hf_frame_arrival_time = -1;
44 static int hf_frame_time_invalid = -1;
45 static int hf_frame_time_delta = -1;
46 static int hf_frame_time_delta_displayed = -1;
47 static int hf_frame_time_relative = -1;
48 int hf_frame_number = -1;
49 int hf_frame_packet_len = -1; /* Deprecated in favor of hf_frame_len */
50 int hf_frame_len = -1;
51 int hf_frame_capture_len = -1;
52 static int hf_frame_p2p_dir = -1;
53 static int hf_frame_file_off = -1;
54 static int hf_frame_marked = -1;
55 static int hf_frame_ref_time = -1;
56 static int hf_link_number = -1;
57 static int hf_frame_protocols = -1;
58 static int hf_frame_color_filter_name = -1;
59 static int hf_frame_color_filter_text = -1;
61 static int proto_short = -1;
62 int proto_malformed = -1;
63 static int proto_unreassembled = -1;
65 static gint ett_frame = -1;
67 static int frame_tap = -1;
69 static dissector_handle_t data_handle;
70 static dissector_handle_t docsis_handle;
73 static gboolean show_file_off = FALSE;
74 static gboolean force_docsis_encap;
76 static const value_string p2p_dirs[] = {
77 { P2P_DIR_SENT, "Sent" },
78 { P2P_DIR_RECV, "Received" },
82 dissector_table_t wtap_encap_dissector_table;
84 static GSList *frame_end_routines = NULL;
87 * Routine used to register frame end routine. The routine should only
88 * be registred when the dissector is used in the frame, not in the
89 * proto_register_XXX function.
92 register_frame_end_routine(void (*func)(void))
94 frame_end_routines = g_slist_append(frame_end_routines, (gpointer)func);
97 typedef void (*void_func_t)(void);
100 call_frame_end_routine(gpointer routine, gpointer dummy _U_)
102 void_func_t func = (void_func_t)routine;
107 dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
109 proto_tree *fh_tree=NULL;
110 proto_item *volatile ti = NULL;
112 int cap_len = 0, frame_len = 0;
113 proto_tree *volatile tree;
115 guint32 frame_number;
117 frame_number=pinfo->fd->num; /* dummy so that the buildbot crashdumps
118 will show the packetnumber where the
123 pinfo->current_proto = "Frame";
125 if (pinfo->pseudo_header != NULL) {
126 switch (pinfo->fd->lnk_t) {
128 case WTAP_ENCAP_WFLEET_HDLC:
129 case WTAP_ENCAP_CHDLC_WITH_PHDR:
130 case WTAP_ENCAP_PPP_WITH_PHDR:
131 case WTAP_ENCAP_SDLC:
132 case WTAP_ENCAP_BLUETOOTH_H4:
133 case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
134 pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ?
135 P2P_DIR_SENT : P2P_DIR_RECV;
138 case WTAP_ENCAP_BLUETOOTH_HCI:
139 pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent ?
140 P2P_DIR_SENT : P2P_DIR_RECV;
143 case WTAP_ENCAP_LAPB:
144 case WTAP_ENCAP_FRELAY_WITH_PHDR:
146 (pinfo->pseudo_header->x25.flags & FROM_DCE) ?
147 P2P_DIR_RECV : P2P_DIR_SENT;
150 case WTAP_ENCAP_ISDN:
151 pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ?
152 P2P_DIR_SENT : P2P_DIR_RECV;
155 case WTAP_ENCAP_LINUX_LAPD:
156 pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 ||
157 pinfo->pseudo_header->lapd.pkttype == 4) ?
158 P2P_DIR_SENT : P2P_DIR_RECV;
161 case WTAP_ENCAP_MTP2_WITH_PHDR:
162 pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ?
163 P2P_DIR_SENT : P2P_DIR_RECV;
164 pinfo->link_number = pinfo->pseudo_header->mtp2.link_number;
165 pinfo->annex_a_used = pinfo->pseudo_header->mtp2.annex_a_used;
171 /* Put in frame header information. */
173 cap_len = tvb_length(tvb);
174 frame_len = tvb_reported_length(tvb);
176 ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1,
177 "Frame %u (%u bytes on wire, %u bytes captured)", pinfo->fd->num, frame_len, cap_len);
179 fh_tree = proto_item_add_subtree(ti, ett_frame);
182 /* if FRAME is not referenced from any filters we dont need to worry about
183 generating any tree items. We must do this after we created the actual
184 protocol above so that proto hier stat still works though.
186 if(!proto_field_is_referenced(tree, proto_frame)){
193 ts = pinfo->fd->abs_ts;
195 proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
197 if(ts.nsecs < 0 || ts.nsecs >= 1000000000) {
198 item = proto_tree_add_none_format(fh_tree, hf_frame_time_invalid, tvb,
199 0, 0, "Arrival Time: Fractional second %09ld is invalid, the valid range is 0-1000000000", (long) ts.nsecs);
200 PROTO_ITEM_SET_GENERATED(item);
201 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "Arrival Time: Fractional second out of range (0-1000000000)");
204 ts = pinfo->fd->del_cap_ts;
206 item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
208 PROTO_ITEM_SET_GENERATED(item);
210 ts = pinfo->fd->del_dis_ts;
212 item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb,
214 PROTO_ITEM_SET_GENERATED(item);
216 ts = pinfo->fd->rel_ts;
218 item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
220 PROTO_ITEM_SET_GENERATED(item);
222 proto_tree_add_uint(fh_tree, hf_frame_number, tvb,
223 0, 0, pinfo->fd->num);
225 /* Deprecated in favor of hf_frame_len */
226 item = proto_tree_add_uint_format(fh_tree, hf_frame_packet_len, tvb,
227 0, 0, frame_len, "Packet Length: %d byte%s", frame_len,
228 plurality(frame_len, "", "s"));
229 PROTO_ITEM_SET_HIDDEN(item);
231 proto_tree_add_uint_format(fh_tree, hf_frame_len, tvb,
232 0, 0, frame_len, "Frame Length: %d byte%s", frame_len,
233 plurality(frame_len, "", "s"));
235 proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb,
236 0, 0, cap_len, "Capture Length: %d byte%s", cap_len,
237 plurality(cap_len, "", "s"));
239 /* we are going to be using proto_item_append_string() on
240 * hf_frame_protocols, and we must therefore disable the
241 * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
242 * setting it as visible.
244 * See proto.h for details.
246 proto_tree_set_visible(fh_tree, TRUE);
248 if(pinfo->fd->flags.ref_time){
249 ti = proto_tree_add_item(fh_tree, hf_frame_ref_time, tvb, 0, 0, FALSE);
250 PROTO_ITEM_SET_GENERATED(ti);
253 ti = proto_tree_add_boolean(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
254 PROTO_ITEM_SET_GENERATED(ti);
256 ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb,
258 PROTO_ITEM_SET_GENERATED(ti);
259 pinfo->layer_names = g_string_new("");
261 /* Check for existences of P2P pseudo header */
262 if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) {
263 proto_tree_add_uint(fh_tree, hf_frame_p2p_dir, tvb,
264 0, 0, pinfo->p2p_dir);
267 /* Check for existences of MTP2 link number */
268 if ((pinfo->pseudo_header != NULL ) && (pinfo->fd->lnk_t == WTAP_ENCAP_MTP2_WITH_PHDR)) {
269 proto_tree_add_uint(fh_tree, hf_link_number, tvb,
270 0, 0, pinfo->link_number);
274 proto_tree_add_int64_format(fh_tree, hf_frame_file_off, tvb,
275 0, 0, pinfo->fd->file_off,
276 "File Offset: %" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)",
277 pinfo->fd->file_off, pinfo->fd->file_off);
280 if(pinfo->fd->color_filter != NULL) {
281 color_filter_t *color_filter = pinfo->fd->color_filter;
282 item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb,
283 0, 0, color_filter->filter_name);
284 PROTO_ITEM_SET_GENERATED(item);
285 item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb,
286 0, 0, color_filter->filter_text);
287 PROTO_ITEM_SET_GENERATED(item);
290 if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) {
291 expert_add_info_format(pinfo, NULL, PI_MALFORMED, PI_WARN, "Arrival Time: Fractional second out of range (0-1000000000)");
295 /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */
298 /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */
299 /* (a running debugger will be called before the except part below) */
302 if ((force_docsis_encap) && (docsis_handle)) {
303 call_dissector(docsis_handle, tvb, pinfo, parent_tree);
305 if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
306 tvb, pinfo, parent_tree)) {
308 if (check_col(pinfo->cinfo, COL_PROTOCOL))
309 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
310 if (check_col(pinfo->cinfo, COL_INFO))
311 col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %u",
313 call_dissector(data_handle,tvb, pinfo, parent_tree);
317 } __except(TRUE /* handle all exceptions */) {
318 switch(GetExceptionCode()) {
319 case(STATUS_ACCESS_VIOLATION):
320 show_exception(tvb, pinfo, parent_tree, DissectorError,
321 "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
323 case(STATUS_INTEGER_DIVIDE_BY_ZERO):
324 show_exception(tvb, pinfo, parent_tree, DissectorError,
325 "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
327 case(STATUS_STACK_OVERFLOW):
328 show_exception(tvb, pinfo, parent_tree, DissectorError,
329 "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
330 /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */
332 /* XXX - add other hardware exception codes as required */
334 show_exception(tvb, pinfo, parent_tree, DissectorError,
335 g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
340 CATCH(OutOfMemoryError) {
344 show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
348 if (tree && pinfo->layer_names) {
349 proto_item_append_string(ti, pinfo->layer_names->str);
350 g_string_free(pinfo->layer_names, TRUE);
351 pinfo->layer_names = NULL;
354 call_all_postdissectors(tvb, pinfo, parent_tree);
356 tap_queue_packet(frame_tap, pinfo, NULL);
359 if (frame_end_routines) {
360 g_slist_foreach(frame_end_routines, &call_frame_end_routine, NULL);
361 g_slist_free(frame_end_routines);
362 frame_end_routines = NULL;
367 show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
368 unsigned long exception, const char *exception_message)
370 static const char dissector_error_nomsg[] =
371 "Dissector writer didn't bother saying what the error was";
377 case ScsiBoundsError:
378 if (check_col(pinfo->cinfo, COL_INFO))
379 col_append_str(pinfo->cinfo, COL_INFO, "[SCSI transfer limited due to allocation_length too small]");
380 /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
381 "SCSI transfer limited due to allocation_length too small: %s truncated]", pinfo->current_proto);
382 /* Don't record ScsiBoundsError exceptions as expert events - they merely
383 * reflect a normal SCSI condition.
384 * (any case where it's caused by something else is a bug). */
385 /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
389 if (check_col(pinfo->cinfo, COL_INFO))
390 col_append_str(pinfo->cinfo, COL_INFO, "[Packet size limited during capture]");
391 /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
392 "[Packet size limited during capture: %s truncated]", pinfo->current_proto);
393 /* Don't record BoundsError exceptions as expert events - they merely
394 * reflect a capture done with a snapshot length too short to capture
396 * (any case where it's caused by something else is a bug). */
397 /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
400 case ReportedBoundsError:
401 show_reported_bounds_error(tvb, pinfo, tree);
405 if (check_col(pinfo->cinfo, COL_INFO))
406 col_append_fstr(pinfo->cinfo, COL_INFO,
407 "[Dissector bug, protocol %s: %s]",
408 pinfo->current_proto,
409 exception_message == NULL ?
410 dissector_error_nomsg : exception_message);
411 item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
412 "[Dissector bug, protocol %s: %s]",
413 pinfo->current_proto,
414 exception_message == NULL ?
415 dissector_error_nomsg : exception_message);
416 g_warning("Dissector bug, protocol %s, in packet %u: %s",
417 pinfo->current_proto, pinfo->fd->num,
418 exception_message == NULL ?
419 dissector_error_nomsg : exception_message);
420 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
422 exception_message == NULL ?
423 dissector_error_nomsg : exception_message);
427 /* XXX - we want to know, if an unknown exception passed until here, don't we? */
428 g_assert_not_reached();
433 show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
437 if (pinfo->fragmented) {
439 * We were dissecting an unreassembled fragmented
440 * packet when the exception was thrown, so the
441 * problem isn't that the dissector expected
442 * something but it wasn't in the packet, the
443 * problem is that the dissector expected something
444 * but it wasn't in the fragment we dissected.
446 if (check_col(pinfo->cinfo, COL_INFO))
447 col_append_fstr(pinfo->cinfo, COL_INFO,
448 "[Unreassembled Packet%s] ",
449 pinfo->noreassembly_reason);
450 item = proto_tree_add_protocol_format(tree, proto_unreassembled,
451 tvb, 0, 0, "[Unreassembled Packet%s: %s]",
452 pinfo->noreassembly_reason, pinfo->current_proto);
453 expert_add_info_format(pinfo, item, PI_REASSEMBLE, PI_WARN, "Unreassembled Packet (Exception occured)");
455 if (check_col(pinfo->cinfo, COL_INFO))
456 col_append_str(pinfo->cinfo, COL_INFO,
457 "[Malformed Packet]");
458 item = proto_tree_add_protocol_format(tree, proto_malformed,
459 tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
460 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Malformed Packet (Exception occured)");
465 proto_register_frame(void)
467 static hf_register_info hf[] = {
468 { &hf_frame_arrival_time,
469 { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
470 "Absolute time when this frame was captured", HFILL }},
472 { &hf_frame_time_invalid,
473 { "Arrival Timestamp invalid", "frame.time_invalid", FT_NONE, BASE_NONE, NULL, 0x0,
474 "The timestamp from the capture is out of the valid range", HFILL }},
476 { &hf_frame_time_delta,
477 { "Time delta from previous captured frame", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
479 "Time delta from previous captured frame", HFILL }},
481 { &hf_frame_time_delta_displayed,
482 { "Time delta from previous displayed frame", "frame.time_delta_displayed", FT_RELATIVE_TIME, BASE_NONE, NULL,
484 "Time delta from previous displayed frame", HFILL }},
486 { &hf_frame_time_relative,
487 { "Time since reference or first frame", "frame.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL,
489 "Time relative to time reference or first frame", HFILL }},
492 { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
495 /* Deprecated and hidden in favor of hf_frame_len / frame.len */
496 { &hf_frame_packet_len,
497 { "Frame length on the wire", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
501 { "Frame length on the wire", "frame.len", FT_UINT32, BASE_DEC, NULL, 0x0,
504 { &hf_frame_capture_len,
505 { "Frame length stored into the capture file", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
509 { "Point-to-Point Direction", "frame.p2p_dir", FT_UINT8, BASE_DEC, VALS(p2p_dirs), 0x0,
513 { "Link Number", "frame.link_nr", FT_UINT16, BASE_DEC, NULL, 0x0,
516 { &hf_frame_file_off,
517 { "File Offset", "frame.file_off", FT_INT64, BASE_DEC, NULL, 0x0,
521 { "Frame is marked", "frame.marked", FT_BOOLEAN, 8, NULL, 0x0,
522 "Frame is marked in the GUI", HFILL }},
524 { &hf_frame_ref_time,
525 { "This is a Time Reference frame", "frame.ref_time", FT_NONE, 0, NULL, 0x0,
526 "This frame is a Time Reference frame", HFILL }},
528 { &hf_frame_protocols,
529 { "Protocols in frame", "frame.protocols", FT_STRING, 0, NULL, 0x0,
530 "Protocols carried by this frame", HFILL }},
532 { &hf_frame_color_filter_name,
533 { "Coloring Rule Name", "frame.coloring_rule.name", FT_STRING, 0, NULL, 0x0,
534 "The frame matched the coloring rule with this name", HFILL }},
535 { &hf_frame_color_filter_text,
536 { "Coloring Rule String", "frame.coloring_rule.string", FT_STRING, 0, NULL, 0x0,
537 "The frame matched this coloring rule string", HFILL }}
539 static gint *ett[] = {
542 module_t *frame_module;
544 wtap_encap_dissector_table = register_dissector_table("wtap_encap",
545 "Wiretap encapsulation type", FT_UINT32, BASE_DEC);
547 proto_frame = proto_register_protocol("Frame", "Frame", "frame");
548 proto_register_field_array(proto_frame, hf, array_length(hf));
549 proto_register_subtree_array(ett, array_length(ett));
550 register_dissector("frame",dissect_frame,proto_frame);
552 /* You can't disable dissection of "Frame", as that would be
553 tantamount to not doing any dissection whatsoever. */
554 proto_set_cant_toggle(proto_frame);
556 proto_short = proto_register_protocol("Short Frame", "Short frame", "short");
557 proto_malformed = proto_register_protocol("Malformed Packet",
558 "Malformed packet", "malformed");
559 proto_unreassembled = proto_register_protocol(
560 "Unreassembled Fragmented Packet",
561 "Unreassembled fragmented packet", "unreassembled");
563 /* "Short Frame", "Malformed Packet", and "Unreassembled Fragmented
564 Packet" aren't really protocols, they're error indications;
565 disabling them makes no sense. */
566 proto_set_cant_toggle(proto_short);
567 proto_set_cant_toggle(proto_malformed);
568 proto_set_cant_toggle(proto_unreassembled);
570 /* Our preferences */
571 frame_module = prefs_register_protocol(proto_frame, NULL);
572 prefs_register_bool_preference(frame_module, "show_file_off",
573 "Show File Offset", "Show File Offset", &show_file_off);
574 prefs_register_bool_preference(frame_module, "force_docsis_encap",
575 "Treat all frames as DOCSIS frames", "Treat all frames as DOCSIS Frames", &force_docsis_encap);
577 frame_tap=register_tap("frame");
581 proto_reg_handoff_frame(void)
583 data_handle = find_dissector("data");
584 docsis_handle = find_dissector("docsis");