1d8b4ef965e9863bb97553041052b2514ae75eac
[metze/wireshark/wip.git] / epan / dissectors / packet-frame.c
1 /* packet-frame.c
2  *
3  * Top-most dissector. Decides dissector based on Wiretap Encapsulation Type.
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 2000 Gerald Combs
10  *
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.
15  *
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.
20  *
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <glib.h>
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>
36 #include <epan/tap.h>
37 #include <epan/expert.h>
38
39 #include "color.h"
40 #include "color_filters.h"
41
42 int proto_frame = -1;
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_relative = -1;
47 int hf_frame_number = -1;
48 int hf_frame_packet_len = -1;
49 int hf_frame_capture_len = -1;
50 static int hf_frame_p2p_dir = -1;
51 static int hf_frame_file_off = -1;
52 static int hf_frame_marked = -1;
53 static int hf_frame_ref_time = -1;
54 static int hf_link_number = -1;
55 static int hf_frame_protocols = -1;
56 static int hf_frame_color_filter_name = -1;
57 static int hf_frame_color_filter_text = -1;
58
59 static int proto_short = -1;
60 int proto_malformed = -1;
61 static int proto_unreassembled = -1;
62
63 static gint ett_frame = -1;
64
65 static int frame_tap = -1;
66
67 static dissector_handle_t data_handle;
68 static dissector_handle_t docsis_handle;
69
70 /* Preferences */
71 static gboolean show_file_off = FALSE;
72 static gboolean force_docsis_encap;
73
74 static const value_string p2p_dirs[] = {
75         { P2P_DIR_SENT, "Sent" },
76         { P2P_DIR_RECV, "Received" },
77         { 0, NULL }
78 };
79
80 static dissector_table_t wtap_encap_dissector_table;
81
82 static GSList *frame_end_routines = NULL;
83
84 /* 
85  * Routine used to register frame end routine.  The routine should only
86  * be registred when the dissector is used in the frame, not in the
87  * proto_register_XXX function.
88  */
89 void
90 register_frame_end_routine(void (*func)(void))
91 {
92         frame_end_routines = g_slist_append(frame_end_routines, (gpointer)func);
93 }
94
95 typedef void (*void_func_t)(void);
96
97 static void
98 call_frame_end_routine(gpointer routine, gpointer dummy _U_)
99 {
100         void_func_t func = (void_func_t)routine;
101         (*func)();
102 }
103
104 static void
105 dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
106 {
107         proto_tree      *fh_tree=NULL;
108         proto_item      *volatile ti = NULL;
109         nstime_t        ts;
110         int             cap_len = 0, pkt_len = 0;
111         proto_tree      *tree;
112         proto_item  *item;
113         int frame_number;
114
115         frame_number=pinfo->fd->num; /* dummy so that the buildbot crashdumps
116                                         will show the packetnumber where the
117                                         crash occured.
118                                      */
119         tree=parent_tree;
120
121         pinfo->current_proto = "Frame";
122
123         if (pinfo->pseudo_header != NULL) {
124                 switch (pinfo->fd->lnk_t) {
125
126                 case WTAP_ENCAP_WFLEET_HDLC:
127                 case WTAP_ENCAP_CHDLC_WITH_PHDR:
128                 case WTAP_ENCAP_PPP_WITH_PHDR:
129                 case WTAP_ENCAP_SDLC:
130                 case WTAP_ENCAP_BLUETOOTH_H4:
131                         pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ?
132                             P2P_DIR_SENT : P2P_DIR_RECV;
133                         break;
134
135                 case WTAP_ENCAP_LAPB:
136                 case WTAP_ENCAP_FRELAY_WITH_PHDR:
137                         pinfo->p2p_dir =
138                             (pinfo->pseudo_header->x25.flags & FROM_DCE) ?
139                             P2P_DIR_RECV : P2P_DIR_SENT;
140                         break;
141
142                 case WTAP_ENCAP_ISDN:
143                         pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ?
144                             P2P_DIR_SENT : P2P_DIR_RECV;
145                         break;
146
147                 case WTAP_ENCAP_LINUX_LAPD:
148                         pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 ||
149                                 pinfo->pseudo_header->lapd.pkttype == 4) ?
150                                 P2P_DIR_SENT : P2P_DIR_RECV;
151                         break;
152
153                 case WTAP_ENCAP_MTP2_WITH_PHDR:
154                         pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ?
155                             P2P_DIR_SENT : P2P_DIR_RECV;
156                         pinfo->link_number  = pinfo->pseudo_header->mtp2.link_number;
157                         pinfo->annex_a_used = pinfo->pseudo_header->mtp2.annex_a_used ?
158                             MTP2_ANNEX_A_USED : MTP2_ANNEX_A_NOT_USED;
159                         break;
160                 
161                 }
162         }
163
164         /* Put in frame header information. */
165         if (tree) {
166           cap_len = tvb_length(tvb);
167           pkt_len = tvb_reported_length(tvb);
168
169           ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1,
170             "Frame %u (%u bytes on wire, %u bytes captured)", pinfo->fd->num, pkt_len, cap_len);
171
172           fh_tree = proto_item_add_subtree(ti, ett_frame);
173         }
174
175         /* if FRAME is not referenced from any filters we dont need to worry about
176            generating any tree items.  We must do this after we created the actual
177            protocol above so that proto hier stat still works though.
178         */
179         if(!proto_field_is_referenced(tree, proto_frame)){
180                 tree=NULL;
181                 fh_tree = NULL;
182         }
183
184        
185         if (fh_tree) {
186           ts = pinfo->fd->abs_ts;
187
188           proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
189                 0, 0, &ts);
190       if(ts.nsecs < 0 || ts.nsecs >= 1000000000) {
191             item = proto_tree_add_none_format(fh_tree, hf_frame_time_invalid, tvb,
192                   0, 0, "Arrival Time: Fractional second %09ld is invalid, the valid range is 0-1000000000", (long) ts.nsecs);
193             PROTO_ITEM_SET_GENERATED(item);
194                 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "Arrival Time: Fractional second out of range (0-1000000000)");
195       }
196
197           ts = pinfo->fd->del_ts;
198
199           item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
200                 0, 0, &ts);
201           PROTO_ITEM_SET_GENERATED(item);
202
203           ts = pinfo->fd->rel_ts;
204
205           item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
206                 0, 0, &ts);
207           PROTO_ITEM_SET_GENERATED(item);
208
209           proto_tree_add_uint(fh_tree, hf_frame_number, tvb,
210                 0, 0, pinfo->fd->num);
211
212           proto_tree_add_uint_format(fh_tree, hf_frame_packet_len, tvb,
213                 0, 0, pkt_len, "Packet Length: %d byte%s", pkt_len,
214                 plurality(pkt_len, "", "s"));
215
216           proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb,
217                 0, 0, cap_len, "Capture Length: %d byte%s", cap_len,
218                 plurality(cap_len, "", "s"));
219
220           /* we are going to be using proto_item_append_string() on
221            * hf_frame_protocols, and we must therefore disable the
222            * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
223            * setting it as visible.
224            *
225            * See proto.h for details.
226            */
227           PTREE_DATA(fh_tree)->visible=1;
228
229           if(pinfo->fd->flags.ref_time){
230                 ti = proto_tree_add_item(fh_tree, hf_frame_ref_time, tvb, 0, 0, FALSE);
231             PROTO_ITEM_SET_GENERATED(ti);
232           }
233
234           ti = proto_tree_add_boolean(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
235           PROTO_ITEM_SET_GENERATED(ti);
236
237           ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb,
238                 0, 0, "");
239           PROTO_ITEM_SET_GENERATED(ti);
240           pinfo->layer_names = g_string_new("");
241
242           /* Check for existences of P2P pseudo header */
243           if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) {
244                   proto_tree_add_uint(fh_tree, hf_frame_p2p_dir, tvb,
245                                   0, 0, pinfo->p2p_dir);
246           }
247
248           /* Check for existences of MTP2 link number */
249           if ((pinfo->pseudo_header != NULL ) && (pinfo->fd->lnk_t == WTAP_ENCAP_MTP2_WITH_PHDR)) {
250                   proto_tree_add_uint(fh_tree, hf_link_number, tvb,
251                                   0, 0, pinfo->link_number);
252           }
253
254           if (show_file_off) {
255                   proto_tree_add_int_format(fh_tree, hf_frame_file_off, tvb,
256                                   0, 0, pinfo->fd->file_off,
257                                   "File Offset: %ld (0x%lx)",
258                                   pinfo->fd->file_off, pinfo->fd->file_off);
259           }
260
261       if(pinfo->fd->color_filter != NULL) {
262           color_filter_t *color_filter = pinfo->fd->color_filter;
263               item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb,
264                     0, 0, color_filter->filter_name);
265               PROTO_ITEM_SET_GENERATED(item);
266               item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb,
267                     0, 0, color_filter->filter_text);
268               PROTO_ITEM_SET_GENERATED(item);
269       }
270     } else {
271       if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) {
272                 expert_add_info_format(pinfo, NULL, PI_MALFORMED, PI_WARN, "Arrival Time: Fractional second out of range (0-1000000000)");
273       }
274     }
275
276     /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */
277         TRY {
278 #ifdef _MSC_VER
279     /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */
280     /* (a running debugger will be called before the except part below) */
281     __try {
282 #endif
283         if ((force_docsis_encap) && (docsis_handle)) {
284             call_dissector(docsis_handle, tvb, pinfo, parent_tree);
285         } else {
286             if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
287                 tvb, pinfo, parent_tree)) {
288
289                         if (check_col(pinfo->cinfo, COL_PROTOCOL))
290                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
291                         if (check_col(pinfo->cinfo, COL_INFO))
292                                 col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %u",
293                                     pinfo->fd->lnk_t);
294                         call_dissector(data_handle,tvb, pinfo, parent_tree);
295                 }
296         }
297 #ifdef _MSC_VER
298     } __except(TRUE /* handle all exceptions */) {
299         switch(GetExceptionCode()) {
300         case(STATUS_ACCESS_VIOLATION):
301                     show_exception(tvb, pinfo, parent_tree, DissectorError, 
302                 "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
303             break;
304         case(STATUS_INTEGER_DIVIDE_BY_ZERO):
305                     show_exception(tvb, pinfo, parent_tree, DissectorError,
306                 "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
307             break;
308         /* XXX - add other hardware exception codes as required */
309         default:
310                     show_exception(tvb, pinfo, parent_tree, DissectorError, 
311                 g_strdup_printf("dissector caused an unknown exception: %u", GetExceptionCode()));
312         }
313     }
314 #endif
315         }
316         CATCH_ALL {
317                 show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
318         }
319         ENDTRY;
320
321         if (tree) {
322                 proto_item_append_string(ti, pinfo->layer_names->str);
323                 g_string_free(pinfo->layer_names, TRUE);
324                 pinfo->layer_names = NULL;
325         }
326
327     call_all_postdissectors(tvb,pinfo,parent_tree);
328
329         tap_queue_packet(frame_tap, pinfo, NULL);
330     
331
332         if (frame_end_routines) {
333                 g_slist_foreach(frame_end_routines, &call_frame_end_routine, NULL);
334                 g_slist_free(frame_end_routines);
335                 frame_end_routines = NULL;
336         }
337 }
338
339 void
340 show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
341     unsigned long exception, const char *exception_message)
342 {
343         static const char dissector_error_nomsg[] =
344             "Dissector writer didn't bother saying what the error was";
345         proto_item *item;
346
347
348         switch (exception) {
349
350         case ScsiBoundsError:
351                 if (check_col(pinfo->cinfo, COL_INFO))
352                         col_append_str(pinfo->cinfo, COL_INFO, "[SCSI transfer limited due to allocation_length too small]");
353                 /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
354                                 "SCSI transfer limited due to allocation_length too small: %s truncated]", pinfo->current_proto);
355                 /* Don't record ScsiBoundsError exceptions as expert events - they merely
356                  * reflect a normal SCSI condition.
357                  * (any case where it's caused by something else is a bug). */
358                 /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
359                 break;
360
361         case BoundsError:
362                 if (check_col(pinfo->cinfo, COL_INFO))
363                         col_append_str(pinfo->cinfo, COL_INFO, "[Packet size limited during capture]");
364                 /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
365                                 "[Packet size limited during capture: %s truncated]", pinfo->current_proto);
366                 /* Don't record BoundsError exceptions as expert events - they merely
367                  * reflect a capture done with a snapshot length too short to capture 
368                  * all of the packet 
369                  * (any case where it's caused by something else is a bug). */
370                 /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
371                 break;
372
373         case ReportedBoundsError:
374                 show_reported_bounds_error(tvb, pinfo, tree);
375                 break;
376
377         case DissectorError:
378                 if (check_col(pinfo->cinfo, COL_INFO))
379                         col_append_fstr(pinfo->cinfo, COL_INFO,
380                             "[Dissector bug, protocol %s: %s]",
381                             pinfo->current_proto,
382                             exception_message == NULL ?
383                                 dissector_error_nomsg : exception_message);
384                 item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
385                     "[Dissector bug, protocol %s: %s]",
386                     pinfo->current_proto,
387                     exception_message == NULL ?
388                         dissector_error_nomsg : exception_message);
389                 g_warning("Dissector bug, protocol %s, in packet %u: %s",
390                     pinfo->current_proto, pinfo->fd->num,
391                     exception_message == NULL ?
392                         dissector_error_nomsg : exception_message);
393                 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
394                     "%s",
395                     exception_message == NULL ?
396                         dissector_error_nomsg : exception_message);
397                 break;
398
399         default:
400                 /* XXX - we want to know, if an unknown exception passed until here, don't we? */
401                 g_assert_not_reached();
402         }
403 }
404
405 void
406 show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
407 {
408         proto_item *item;
409
410         if (pinfo->fragmented) {
411                 /*
412                  * We were dissecting an unreassembled fragmented
413                  * packet when the exception was thrown, so the
414                  * problem isn't that the dissector expected
415                  * something but it wasn't in the packet, the
416                  * problem is that the dissector expected something
417                  * but it wasn't in the fragment we dissected.
418                  */
419                 if (check_col(pinfo->cinfo, COL_INFO))
420                         col_append_fstr(pinfo->cinfo, COL_INFO,
421                             "[Unreassembled Packet%s]",
422                             pinfo->noreassembly_reason);
423                 item = proto_tree_add_protocol_format(tree, proto_unreassembled,
424                     tvb, 0, 0, "[Unreassembled Packet%s: %s]",
425                     pinfo->noreassembly_reason, pinfo->current_proto);
426                 expert_add_info_format(pinfo, item, PI_REASSEMBLE, PI_WARN, "Unreassembled Packet (Exception occured)");
427         } else {
428                 if (check_col(pinfo->cinfo, COL_INFO))
429                         col_append_str(pinfo->cinfo, COL_INFO,
430                             "[Malformed Packet]");
431                 item = proto_tree_add_protocol_format(tree, proto_malformed,
432                     tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
433                 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Malformed Packet (Exception occured)");
434         }
435 }
436
437 void
438 proto_register_frame(void)
439 {
440         static hf_register_info hf[] = {
441                 { &hf_frame_arrival_time,
442                 { "Arrival Time",               "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
443                         "Absolute time when this frame was captured", HFILL }},
444
445         { &hf_frame_time_invalid,
446                 { "Arrival Timestamp invalid",          "frame.time_invalid", FT_NONE, BASE_NONE, NULL, 0x0,
447                         "The timestamp from the capture is out of the valid range", HFILL }},
448
449                 { &hf_frame_time_delta,
450                 { "Time delta from previous packet",    "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
451                         0x0,
452                         "Time delta since previous displayed frame", HFILL }},
453
454                 { &hf_frame_time_relative,
455                 { "Time since reference or first frame",        "frame.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL,
456                         0x0,
457                         "Time relative to time reference or first frame", HFILL }},
458
459                 { &hf_frame_number,
460                 { "Frame Number",               "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
461                         "", HFILL }},
462
463                 { &hf_frame_packet_len,
464                 { "Frame length on the wire",           "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
465                         "", HFILL }},
466
467                 { &hf_frame_capture_len,
468                 { "Frame length stored into the capture file",  "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
469                         "", HFILL }},
470
471                 { &hf_frame_p2p_dir,
472                 { "Point-to-Point Direction",   "frame.p2p_dir", FT_UINT8, BASE_DEC, VALS(p2p_dirs), 0x0,
473                         "", HFILL }},
474
475                 { &hf_link_number,
476                 { "Link Number",                "frame.link_nr", FT_UINT16, BASE_DEC, NULL, 0x0,
477                         "", HFILL }},
478
479                 { &hf_frame_file_off,
480                 { "File Offset",        "frame.file_off", FT_INT32, BASE_DEC, NULL, 0x0,
481                         "", HFILL }},
482
483                 { &hf_frame_marked,
484                 { "Frame is marked",    "frame.marked", FT_BOOLEAN, 8, NULL, 0x0,
485                         "Frame is marked in the GUI", HFILL }},
486
487                 { &hf_frame_ref_time,
488                 { "This is a Time Reference frame",     "frame.ref_time", FT_NONE, 0, NULL, 0x0,
489                         "This frame is a Time Reference frame", HFILL }},
490
491                 { &hf_frame_protocols,
492                 { "Protocols in frame", "frame.protocols", FT_STRING, 0, NULL, 0x0,
493                         "Protocols carried by this frame", HFILL }},
494
495                 { &hf_frame_color_filter_name,
496                 { "Coloring Rule Name", "frame.coloring_rule.name", FT_STRING, 0, NULL, 0x0,
497                         "The frame matched the coloring rule with this name", HFILL }},
498                 { &hf_frame_color_filter_text,
499                 { "Coloring Rule String", "frame.coloring_rule.string", FT_STRING, 0, NULL, 0x0,
500                         "The frame matched this coloring rule string", HFILL }},
501     };
502         static gint *ett[] = {
503                 &ett_frame,
504         };
505         module_t *frame_module;
506
507         wtap_encap_dissector_table = register_dissector_table("wtap_encap",
508             "Wiretap encapsulation type", FT_UINT32, BASE_DEC);
509
510         proto_frame = proto_register_protocol("Frame", "Frame", "frame");
511         proto_register_field_array(proto_frame, hf, array_length(hf));
512         proto_register_subtree_array(ett, array_length(ett));
513         register_dissector("frame",dissect_frame,proto_frame);
514
515         /* You can't disable dissection of "Frame", as that would be
516            tantamount to not doing any dissection whatsoever. */
517         proto_set_cant_toggle(proto_frame);
518
519         proto_short = proto_register_protocol("Short Frame", "Short frame", "short");
520         proto_malformed = proto_register_protocol("Malformed Packet",
521             "Malformed packet", "malformed");
522         proto_unreassembled = proto_register_protocol(
523             "Unreassembled Fragmented Packet",
524             "Unreassembled fragmented packet", "unreassembled");
525
526         /* "Short Frame", "Malformed Packet", and "Unreassembled Fragmented
527            Packet" aren't really protocols, they're error indications;
528            disabling them makes no sense. */
529         proto_set_cant_toggle(proto_short);
530         proto_set_cant_toggle(proto_malformed);
531         proto_set_cant_toggle(proto_unreassembled);
532
533         /* Our preferences */
534         frame_module = prefs_register_protocol(proto_frame, NULL);
535         prefs_register_bool_preference(frame_module, "show_file_off",
536             "Show File Offset", "Show File Offset", &show_file_off);
537         prefs_register_bool_preference(frame_module, "force_docsis_encap",
538             "Treat all frames as DOCSIS frames", "Treat all frames as DOCSIS Frames", &force_docsis_encap);
539
540         frame_tap=register_tap("frame");
541 }
542
543 void
544 proto_reg_handoff_frame(void)
545 {
546         data_handle = find_dissector("data");
547         docsis_handle = find_dissector("docsis");
548 }