bugfix to a bug reported by Ian Schorr:
[obnox/wireshark/wip.git] / packet-ethertype.c
index 349d942aed69b73eebe050f720b9a38ec4d5386c..83bf5bfbc8ee58c7c99402c9fc9a00bc138890ad 100644 (file)
@@ -1,24 +1,24 @@
 /* ethertype.c
  * Routines for calling the right protocol for the ethertype.
  *
- * $Id: packet-ethertype.c,v 1.28 2002/04/24 06:03:33 guy Exp $
+ * $Id: packet-ethertype.c,v 1.46 2004/04/07 06:04:22 guy Exp $
  *
  * Gilbert Ramirez <gram@alumni.rice.edu>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 # include "config.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
 #include <glib.h>
 #include <epan/packet.h>
+#include "packet-eth.h"
+#include "packet-frame.h"
 #include "packet-ip.h"
+#include "packet-ipv6.h"
 #include "packet-ipx.h"
 #include "packet-vlan.h"
 #include "packet-vines.h"
@@ -56,14 +55,21 @@ const value_string etype_vals[] = {
     {ETHERTYPE_SNA,            "SNA-over-Ethernet"             },
     {ETHERTYPE_AARP,           "AARP"                          },
     {ETHERTYPE_IPX,            "Netware IPX/SPX"               },
-    {ETHERTYPE_VINES,          "Vines"                         },
+    {ETHERTYPE_VINES_IP,       "Vines IP"                      },
+    {ETHERTYPE_VINES_ECHO,     "Vines Echo"                    },
     {ETHERTYPE_TRAIN,          "Netmon Train"                  },
     {ETHERTYPE_LOOP,           "Loopback"                      }, /* Ethernet Loopback */
     {ETHERTYPE_WCP,            "Wellfleet Compression Protocol" },
-    {ETHERTYPE_PPPOED,         "PPPoE Discovery"               }, 
-    {ETHERTYPE_PPPOES,         "PPPoE Session"                 }, 
+    {ETHERTYPE_ISMP,           "Cabletron Interswitch Message Protocol" },
+    {ETHERTYPE_ISMP_TBFLOOD,   "Cabletron SFVLAN 1.8 Tag-Based Flood" },
+                               /* for ISMP, see RFC 2641, RFC 2642, RFC 2643 */
+    {ETHERTYPE_PPPOED,         "PPPoE Discovery"               },
+    {ETHERTYPE_PPPOES,         "PPPoE Session"                 },
+    {ETHERTYPE_INTEL_ANS,      "Intel ANS probe"               },
+    {ETHERTYPE_MS_NLB_HEARTBEAT,       "MS NLB heartbeat"      },
     {ETHERTYPE_VLAN,           "802.1Q Virtual LAN"            },
     {ETHERTYPE_EAPOL,          "802.1X Authentication"         },
+    {ETHERTYPE_RSN_PREAUTH,    "802.11i Pre-Authentication"    },
     {ETHERTYPE_MPLS,           "MPLS label switched packet"    },
     {ETHERTYPE_MPLS_MULTI,     "MPLS multicast label switched packet" },
     {ETHERTYPE_3C_NBP_DGRAM,   "3Com NBP Datagram"             },
@@ -77,6 +83,10 @@ const value_string etype_vals[] = {
     {ETHERTYPE_DEC_SCA,                "DEC LAVC/SCA"                  },
     {ETHERTYPE_ETHBRIDGE,      "Transparent Ethernet bridging" },
     {ETHERTYPE_CGMP,           "Cisco Group Management Protocol" },
+    {ETHERTYPE_SLOW_PROTOCOLS, "Slow Protocols"                },
+    {ETHERTYPE_RTNET,          "RTNET Protocol"                },
+    {ETHERTYPE_RTCFG,          "RTCFG Protocol"                },
+    {ETHERTYPE_PROFINET,       "PROFInet"                },
 
     /*
      * NDISWAN on Windows translates Ethernet frames from higher-level
@@ -99,24 +109,32 @@ const value_string etype_vals[] = {
     {PPP_CCP,                  "PPP Compression Control Protocol" },
     {0,                                NULL                            } };
 
-static void add_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
-    tvbuff_t *next_tvb, int offset_after_etype, guint length_before);
+static void add_dix_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
+    tvbuff_t *next_tvb, int offset_after_etype, guint length_before,
+    gint fcs_len);
 
 void
-capture_ethertype(guint16 etype, const u_char *pd, int offset, int len,
+capture_ethertype(guint16 etype, const guchar *pd, int offset, int len,
                  packet_counts *ld)
 {
   switch (etype) {
+    case ETHERTYPE_ARP:
+      ld->arp++;
+      break;
     case ETHERTYPE_IP:
       capture_ip(pd, offset, len, ld);
       break;
+    case ETHERTYPE_IPv6:
+      capture_ipv6(pd, offset, len, ld);
+      break;
     case ETHERTYPE_IPX:
       capture_ipx(ld);
       break;
     case ETHERTYPE_VLAN:
       capture_vlan(pd, offset, len, ld);
       break;
-    case ETHERTYPE_VINES:
+    case ETHERTYPE_VINES_IP:
+    case ETHERTYPE_VINES_ECHO:
       capture_vines(ld);
       break;
     default:
@@ -128,14 +146,15 @@ capture_ethertype(guint16 etype, const u_char *pd, int offset, int len,
 void
 ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
                packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
-               int etype_id, int trailer_id)
+               int etype_id, int trailer_id, int fcs_len)
 {
        char                    *description;
        tvbuff_t                *next_tvb;
        guint                   length_before;
        volatile gboolean       dissector_found;
-       
-       /* Add to proto_tree */
+       const char              *saved_proto;
+
+       /* Add the Ethernet type to the protocol tree */
        if (tree) {
                proto_tree_add_uint(fh_tree, etype_id, tvb,
                    offset_after_etype - 2, 2, etype);
@@ -150,31 +169,43 @@ ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
        length_before = tvb_reported_length(next_tvb);
 
        /* Look for sub-dissector, and call it if found.
-          Catch BoundsError and ReportedBoundsError, so that if the
-          reported length of "next_tvb" was reduced by some dissector
-          before an exception was thrown, we can still put in an item
-          for the trailer. */
+          Catch exceptions, so that if the reported length of "next_tvb"
+          was reduced by some dissector before an exception was thrown,
+          we can still put in an item for the trailer. */
+       saved_proto = pinfo->current_proto;
        TRY {
                dissector_found = dissector_try_port(ethertype_dissector_table,
                    etype, next_tvb, pinfo, tree);
        }
-       CATCH2(BoundsError, ReportedBoundsError) {
-               /* Well, somebody threw an exception; that means that a
-                  dissector was found, so we don't need to dissect
-                  the payload as data or update the protocol or info
-                  columns. */
+       CATCH(BoundsError) {
+               /* Somebody threw BoundsError, which means that:
+
+                    1) a dissector was found, so we don't need to
+                       dissect the payload as data or update the
+                       protocol or info columns;
+
+                    2) dissecting the payload found that the packet was
+                       cut off by a snapshot length before the end of
+                       the payload.  The trailer comes after the payload,
+                       so *all* of the trailer is cut off, and we'll
+                       just get another BoundsError if we add the trailer.
+
+                  Therefore, we just rethrow the exception so it gets
+                  reported; we don't dissect the trailer or do anything
+                  else. */
+                RETHROW;
+       }
+       CATCH_ALL {
+               /* Somebody threw an exception other than BoundsError, which
+                  means that a dissector was found, so we don't need to
+                  dissect the payload as data or update the protocol or info
+                  columns.  We just show the exception and then drive on
+                  to show the trailer, after noting that a dissector was
+                  found and restoring the protocol value that was in effect
+                  before we called the subdissector. */
+               show_exception(next_tvb, pinfo, tree, EXCEPT_CODE);
                dissector_found = TRUE;
-
-               /* Add the trailer, if appropriate. */
-               add_trailer(fh_tree, trailer_id, tvb, next_tvb,
-                   offset_after_etype, length_before);
-
-               /* Rrethrow the exception, so the "Short Frame" or "Mangled
-                  Frame" indication can be put into the tree. */
-               RETHROW;
-
-               /* XXX - RETHROW shouldn't return. */
-               g_assert_not_reached();
+               pinfo->current_proto = saved_proto;
        }
        ENDTRY;
 
@@ -208,13 +239,14 @@ ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
                }
        }
 
-       add_trailer(fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
-           length_before);
+       add_dix_trailer(fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
+           length_before, fcs_len);
 }
 
 static void
-add_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
-    tvbuff_t *next_tvb, int offset_after_etype, guint length_before)
+add_dix_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
+    tvbuff_t *next_tvb, int offset_after_etype, guint length_before,
+    gint fcs_len)
 {
        guint           length;
        tvbuff_t        *volatile trailer_tvb;
@@ -232,35 +264,27 @@ add_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
           a trailer. */
        if (length < length_before) {
                /*
-                * Create a tvbuff for the padding.
+                * Is any of the padding present in the tvbuff?
                 */
-               TRY {
+               if (tvb_offset_exists(tvb, offset_after_etype + length)) {
+                       /*
+                        * Yes - create a tvbuff for the padding.
+                        */
                        trailer_tvb = tvb_new_subset(tvb,
                            offset_after_etype + length, -1, -1);
-               }
-               CATCH2(BoundsError, ReportedBoundsError) {
-                       /* The packet doesn't have "length" bytes worth of
-                          captured data left in it.  No trailer to display. */
+               } else {
+                       /*
+                        * No - don't bother showing the trailer.
+                        * XXX - show a Short Frame indication?
+                        */
                        trailer_tvb = NULL;
                }
-               ENDTRY;
        } else
                trailer_tvb = NULL;     /* no trailer */
 
-       /* If there's some bytes left over, and we were given an item ID
-          for a trailer, mark those bytes as a trailer. */
-       if (trailer_tvb) {
-               guint   trailer_length;
-
-               trailer_length = tvb_length(trailer_tvb);
-               if (trailer_length != 0) {
-                       proto_tree_add_item(fh_tree, trailer_id, trailer_tvb, 0,
-                           trailer_length, FALSE);
-               }
-       }
+       add_ethernet_trailer(fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
 }
 
-
 void
 proto_register_ethertype(void)
 {
@@ -270,6 +294,7 @@ proto_register_ethertype(void)
 }
 
 void
-proto_reg_handoff_ethertype(void){
-  data_handle = find_dissector("data");
+proto_reg_handoff_ethertype(void)
+{
+       data_handle = find_dissector("data");
 }