Support for the new restart TLV, from Hannes Gredler.
[obnox/wireshark/wip.git] / packet-frame.c
index c77acf33f5e74b548421dbba9ab0220293ce9b8e..f11586b59dd47116d99d828e2b9eba2663c99bc7 100644 (file)
@@ -2,12 +2,11 @@
  *
  * Top-most dissector. Decides dissector based on Wiretap Encapsulation Type.
  *
- * $Id: packet-frame.c,v 1.4 2000/12/15 03:30:21 gerald Exp $
+ * $Id: packet-frame.c,v 1.21 2002/01/24 09:20:47 guy Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 2000 Gerald Combs
- *
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #endif
 
 #include <glib.h>
-#include "packet.h"
-#include "timestamp.h"
-#include "tvbuff.h"
+#include <epan/packet.h>
+#include <epan/timestamp.h>
+#include <epan/tvbuff.h>
 #include "packet-frame.h"
+#include "prefs.h"
 
 static int proto_frame = -1;
 static int hf_frame_arrival_time = -1;
@@ -42,11 +42,18 @@ static int hf_frame_number = -1;
 static int hf_frame_packet_len = -1;
 static int hf_frame_capture_len = -1;
 static int hf_frame_p2p_dir = -1;
+static int hf_frame_file_off = -1;
 static int proto_short = -1;
 int proto_malformed = -1;
+static int proto_unreassembled = -1;
 
 static gint ett_frame = -1;
 
+static dissector_handle_t data_handle;
+
+/* Preferences */
+static gboolean show_file_off = FALSE;
+
 static const value_string p2p_dirs[] = {
        { P2P_DIR_SENT, "Sent" },
        { P2P_DIR_RECV, "Received" },
@@ -60,16 +67,22 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
        proto_tree      *fh_tree;
        proto_item      *ti;
-       struct timeval  tv;
+       nstime_t        ts;
        int             cap_len, pkt_len;
 
        pinfo->current_proto = "Frame";
 
        if (pinfo->fd->lnk_t == WTAP_ENCAP_LAPD ||
+                       pinfo->fd->lnk_t == WTAP_ENCAP_CHDLC ||
                        pinfo->fd->lnk_t == WTAP_ENCAP_PPP_WITH_PHDR) {
 
                pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ? P2P_DIR_SENT : P2P_DIR_RECV;
        }
+       else if (pinfo->fd->lnk_t == WTAP_ENCAP_LAPB ||
+                       pinfo->fd->lnk_t == WTAP_ENCAP_FRELAY) {
+
+               pinfo->p2p_dir = (pinfo->pseudo_header->x25.flags & 0x80) ? P2P_DIR_RECV : P2P_DIR_SENT;
+       }
 
        /* Put in frame header information. */
        if (tree) {
@@ -77,28 +90,28 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
          cap_len = tvb_length(tvb);
          pkt_len = tvb_reported_length(tvb);
 
-         ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_length(tvb),
+         ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1,
            "Frame %u (%u on wire, %u captured)", pinfo->fd->num, pkt_len, cap_len);
 
          fh_tree = proto_item_add_subtree(ti, ett_frame);
 
-         tv.tv_sec = pinfo->fd->abs_secs;
-         tv.tv_usec = pinfo->fd->abs_usecs;
+         ts.secs = pinfo->fd->abs_secs;
+         ts.nsecs = pinfo->fd->abs_usecs*1000;
 
          proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
-               0, 0, &tv);
+               0, 0, &ts);
 
-         tv.tv_sec = pinfo->fd->del_secs;
-         tv.tv_usec = pinfo->fd->del_usecs;
+         ts.secs = pinfo->fd->del_secs;
+         ts.nsecs = pinfo->fd->del_usecs*1000;
 
          proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
-               0, 0, &tv);
+               0, 0, &ts);
 
-         tv.tv_sec = pinfo->fd->rel_secs;
-         tv.tv_usec = pinfo->fd->rel_usecs;
+         ts.secs = pinfo->fd->rel_secs;
+         ts.nsecs = pinfo->fd->rel_usecs*1000;
 
          proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
-               0, 0, &tv);
+               0, 0, &ts);
 
          proto_tree_add_uint(fh_tree, hf_frame_number, tvb,
                0, 0, pinfo->fd->num);
@@ -116,6 +129,13 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                  proto_tree_add_uint(fh_tree, hf_frame_p2p_dir, tvb,
                                  0, 0, pinfo->p2p_dir);
          }
+
+         if (show_file_off) {
+                 proto_tree_add_int_format(fh_tree, hf_frame_file_off, tvb,
+                                 0, 0, pinfo->fd->file_off,
+                                 "File Offset: %ld (0x%lx)",
+                                 pinfo->fd->file_off, pinfo->fd->file_off);
+         }
        }
 
 
@@ -123,20 +143,44 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
                                        tvb, pinfo, tree)) {
 
-                       if (check_col(pinfo->fd, COL_PROTOCOL))
-                               col_set_str(pinfo->fd, COL_PROTOCOL, "UNKNOWN");
-                       if (check_col(pinfo->fd, COL_INFO))
-                               col_add_fstr(pinfo->fd, COL_INFO, "WTAP_ENCAP = 0x%x", pinfo->fd->lnk_t);
-                       dissect_data(tvb, 0, pinfo, tree);
+                       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                               col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
+                       if (check_col(pinfo->cinfo, COL_INFO))
+                               col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %u",
+                                   pinfo->fd->lnk_t);
+                       call_dissector(data_handle,tvb, pinfo, tree);
                }
        }
        CATCH(BoundsError) {
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_str(pinfo->cinfo, COL_INFO, "[Short Frame]");
                proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
                                "[Short Frame: %s]", pinfo->current_proto );
        }
        CATCH(ReportedBoundsError) {
-               proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
-                               "[Malformed Frame: %s]", pinfo->current_proto );
+               if (pinfo->fragmented) {
+                       /*
+                        * We were dissecting an unreassembled fragmented
+                        * packet when the exception was thrown, so the
+                        * problem isn't that the dissector expected
+                        * something but it wasn't in the packet, the
+                        * problem is that the dissector expected something
+                        * but it wasn't in the fragment we dissected.
+                        */
+                       if (check_col(pinfo->cinfo, COL_INFO))
+                               col_append_str(pinfo->cinfo, COL_INFO,
+                                   "[Unreassembled Packet]");
+                       proto_tree_add_protocol_format(tree, proto_unreassembled,
+                           tvb, 0, 0, "[Unreassembled Packet: %s]",
+                           pinfo->current_proto );
+               } else {
+                       if (check_col(pinfo->cinfo, COL_INFO))
+                               col_append_str(pinfo->cinfo, COL_INFO,
+                                   "[Malformed Packet]");
+                       proto_tree_add_protocol_format(tree, proto_malformed,
+                           tvb, 0, 0, "[Malformed Packet: %s]",
+                           pinfo->current_proto );
+               }
        }
        ENDTRY;
 }
@@ -147,45 +191,78 @@ proto_register_frame(void)
        static hf_register_info hf[] = {
                { &hf_frame_arrival_time,
                { "Arrival Time",               "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
-                       ""}},
+                       "", HFILL }},
 
                { &hf_frame_time_delta,
                { "Time delta from previous packet",    "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
                        0x0,
-                       "" }},
+                       "", HFILL }},
 
                { &hf_frame_time_relative,
                { "Time relative to first packet",      "frame.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL,
                        0x0,
-                       "" }},
+                       "", HFILL }},
 
                { &hf_frame_number,
                { "Frame Number",               "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
-                       "" }},
+                       "", HFILL }},
 
                { &hf_frame_packet_len,
                { "Total Frame Length",         "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
-                       "" }},
+                       "", HFILL }},
 
                { &hf_frame_capture_len,
                { "Capture Frame Length",       "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
-                       "" }},
+                       "", HFILL }},
 
                { &hf_frame_p2p_dir,
                { "Point-to-Point Direction",   "frame.p2p_dir", FT_UINT8, BASE_DEC, VALS(p2p_dirs), 0x0,
-                       "" }},
+                       "", HFILL }},
+
+               { &hf_frame_file_off,
+               { "File Offset",        "frame.file_off", FT_INT32, BASE_DEC, NULL, 0x0,
+                       "", HFILL }},
+
        };
        static gint *ett[] = {
                &ett_frame,
        };
+       module_t *frame_module; 
 
-       wtap_encap_dissector_table = register_dissector_table("wtap_encap");
+       wtap_encap_dissector_table = register_dissector_table("wtap_encap",
+           "Wiretap encapsulation type", FT_UINT32, BASE_DEC);
 
-       proto_frame = proto_register_protocol("Frame", "frame");
+       proto_frame = proto_register_protocol("Frame", "Frame", "frame");
        proto_register_field_array(proto_frame, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
+       register_dissector("frame",dissect_frame,proto_frame);
+
+       /* You can't disable dissection of "Frame", as that would be
+          tantamount to not doing any dissection whatsoever. */
+       proto_set_cant_disable(proto_frame);
+
+       proto_short = proto_register_protocol("Short Frame", "Short frame", "short");
+       proto_malformed = proto_register_protocol("Malformed Packet",
+           "Malformed packet", "malformed");
+       proto_unreassembled = proto_register_protocol(
+           "Unreassembled Fragmented Packet",
+           "Unreassembled fragmented packet", "unreassembled");
+
+       /* "Short Frame", "Malformed Packet", and "Unreassembled Fragmented
+          Packet" aren't really protocols, they're error indications;
+          disabling them makes no sense. */
+       proto_set_cant_disable(proto_short);
+       proto_set_cant_disable(proto_malformed);
+       proto_set_cant_disable(proto_unreassembled);
+
+       /* Our preferences */
+       frame_module = prefs_register_protocol(proto_frame, NULL);
+       prefs_register_bool_preference(frame_module, "show_file_off",
+           "Show File Offset", "Show File Offset", &show_file_off);
+}
 
-       proto_short = proto_register_protocol("Short Frame", "short");
-       proto_malformed = proto_register_protocol("Malformed Frame", "malformed");
-
+void
+proto_reg_handoff_frame(void)
+{
+       data_handle = find_dissector("data");
 }