some compilers dont like unnamed unions and structs
[obnox/wireshark/wip.git] / epan / dissectors / packet-ethertype.c
1 /* ethertype.c
2  * Routines for calling the right protocol for the ethertype.
3  *
4  * $Id$
5  *
6  * Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include "packet-eth.h"
34 #include "packet-frame.h"
35 #include "packet-ip.h"
36 #include "packet-ipv6.h"
37 #include "packet-ipx.h"
38 #include "packet-vlan.h"
39 #include "packet-vines.h"
40 #include <epan/etypes.h>
41 #include <epan/ppptypes.h>
42
43 static dissector_table_t ethertype_dissector_table;
44
45 static dissector_handle_t data_handle;
46
47 const value_string etype_vals[] = {
48     {ETHERTYPE_IP,                                      "IP"                            },
49     {ETHERTYPE_IPv6,                            "IPv6"                          },
50     {ETHERTYPE_WLCCP,                           "Cisco Wireless Lan Context Control Protocol"           },
51     {ETHERTYPE_CENTRINO_PROMISC,        "IEEE 802.11 (Centrino promiscuous)" },
52     {ETHERTYPE_XNS_IDP,                         "XNS Internet Datagram Protocol" },
53     {ETHERTYPE_X25L3,                           "X.25 Layer 3"                  },
54     {ETHERTYPE_ARP,                                     "ARP"                           },
55     {ETHERTYPE_EPL_V1,                                  "EPL_V1"                                },
56     {ETHERTYPE_REVARP,                          "RARP"                          },
57     {ETHERTYPE_DEC_LB,                          "DEC LanBridge"                 },
58     {ETHERTYPE_ATALK,                           "Appletalk"                     },
59     {ETHERTYPE_SNA,                                     "SNA-over-Ethernet"             },
60     {ETHERTYPE_AARP,                            "AARP"                          },
61     {ETHERTYPE_IPX,                                     "Netware IPX/SPX"               },
62     {ETHERTYPE_VINES_IP,                        "Vines IP"                      },
63     {ETHERTYPE_VINES_ECHO,                      "Vines Echo"                    },
64     {ETHERTYPE_TRAIN,                           "Netmon Train"                  },
65     {ETHERTYPE_LOOP,                            "Loopback"                      }, /* Ethernet Loopback */
66     {ETHERTYPE_FOUNDRY,                         "Foundry proprietary"           },
67     {ETHERTYPE_WCP,                             "Wellfleet Compression Protocol" },
68     {ETHERTYPE_STP,                             "Spanning Tree Protocol"        },
69     {ETHERTYPE_ISMP,                            "Cabletron Interswitch Message Protocol" },
70     {ETHERTYPE_ISMP_TBFLOOD,            "Cabletron SFVLAN 1.8 Tag-Based Flood" },
71                                 /* for ISMP, see RFC 2641, RFC 2642, RFC 2643 */
72     {ETHERTYPE_PPPOED,                          "PPPoE Discovery"               },
73     {ETHERTYPE_PPPOES,                          "PPPoE Session"                 },
74     {ETHERTYPE_INTEL_ANS,                       "Intel ANS probe"               },
75     {ETHERTYPE_MS_NLB_HEARTBEAT,        "MS NLB heartbeat"      },
76     {ETHERTYPE_VLAN,                            "802.1Q Virtual LAN"            },
77     {ETHERTYPE_EAPOL,                           "802.1X Authentication"         },
78     {ETHERTYPE_RSN_PREAUTH,                     "802.11i Pre-Authentication"    },
79     {ETHERTYPE_MPLS,                            "MPLS label switched packet"    },
80     {ETHERTYPE_MPLS_MULTI,                      "MPLS multicast label switched packet" },
81     {ETHERTYPE_3C_NBP_DGRAM,            "3Com NBP Datagram"             },
82     {ETHERTYPE_DEC,                                     "DEC proto"                     },
83     {ETHERTYPE_DNA_DL,                          "DEC DNA Dump/Load"             },
84     {ETHERTYPE_DNA_RC,                          "DEC DNA Remote Console"        },
85     {ETHERTYPE_DNA_RT,                          "DEC DNA Routing"               },
86     {ETHERTYPE_LAT,                                     "DEC LAT"                       },
87     {ETHERTYPE_DEC_DIAG,                        "DEC Diagnostics"               },
88     {ETHERTYPE_DEC_CUST,                        "DEC Customer use"              },
89     {ETHERTYPE_DEC_SCA,                         "DEC LAVC/SCA"                  },
90     {ETHERTYPE_DEC_LAST,                        "DEC LAST"                      },
91     {ETHERTYPE_ETHBRIDGE,                       "Transparent Ethernet bridging" },
92     {ETHERTYPE_CGMP,                            "Cisco Group Management Protocol" },
93     {ETHERTYPE_MAC_CONTROL,                     "MAC Control"                   },
94     {ETHERTYPE_SLOW_PROTOCOLS,          "Slow Protocols"                },
95     {ETHERTYPE_RTMAC,                           "Real-Time Media Access Control" },
96     {ETHERTYPE_RTCFG,                           "Real-Time Configuration Protocol" },
97     {ETHERTYPE_CDMA2000_A10_UBS,        "CDMA2000 A10 Unstructured byte stream" },
98     {ETHERTYPE_PROFINET,                        "PROFINET"                      },
99     {ETHERTYPE_AOE,                                     "ATA over Ethernet"             },
100     {ETHERTYPE_TELKONET,                                        "Telkonet powerline"    },
101     {ETHERTYPE_EPL_V2,                          "ETHERNET Powerlink v2"                 },
102     {ETHERTYPE_CSM_ENCAPS,                      "CSM_ENCAPS Protocol"             },
103     {ETHERTYPE_IEEE802_OUI_EXTENDED, "IEEE 802a OUI Extended Ethertype" },
104     {ETHERTYPE_IEC61850_GOOSE,          "IEC 61850/GOOSE" },
105     {ETHERTYPE_IEC61850_GSE,            "IEC 61850/GSE management services" },
106     {ETHERTYPE_IEC61850_SV,                     "IEC 61850/SV (Sampled Value Transmission" },
107     {ETHERTYPE_TIPC,                            "Transparent Inter Process Communication" },
108     {ETHERTYPE_LLDP,                            "802.1 Link Layer Discovery Protocol (LLDP)" },
109     {ETHERTYPE_3GPP2,                           "CDMA2000 A10 3GPP2 Packet" },
110     /*
111      * NDISWAN on Windows translates Ethernet frames from higher-level
112      * protocols into PPP frames to hand to the PPP driver, and translates
113      * PPP frames from the PPP driver to hand to the higher-level protocols.
114      *
115      * Apparently the PPP driver, on at least some versions of Windows,
116      * passes frames for internal-to-PPP protocols up through NDISWAN;
117      * the protocol type field appears to be passed through unchanged
118      * (unlike what's done with, for example, the protocol type field
119      * for IP, which is mapped from its PPP value to its Ethernet value).
120      *
121      * This means that we may see, on Ethernet captures, frames for
122      * protocols internal to PPP, so we list as "Ethernet" protocol
123      * types the PPP protocol types we've seen.
124      */
125     {PPP_IPCP,                  "PPP IP Control Protocol" },
126     {PPP_LCP,                   "PPP Link Control Protocol" },
127     {PPP_PAP,                   "PPP Password Authentication Protocol" },
128     {PPP_CCP,                   "PPP Compression Control Protocol" },
129     {ETHERTYPE_LLT,             "Veritas Low Latency Transport (not officially registered)"},
130     {0,                         NULL                            } };
131
132 static void add_dix_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
133     tvbuff_t *next_tvb, int offset_after_etype, guint length_before,
134     gint fcs_len);
135
136 void
137 capture_ethertype(guint16 etype, const guchar *pd, int offset, int len,
138                   packet_counts *ld)
139 {
140   switch (etype) {
141     case ETHERTYPE_ARP:
142       ld->arp++;
143       break;
144     case ETHERTYPE_IP:
145       capture_ip(pd, offset, len, ld);
146       break;
147     case ETHERTYPE_IPv6:
148       capture_ipv6(pd, offset, len, ld);
149       break;
150     case ETHERTYPE_IPX:
151       capture_ipx(ld);
152       break;
153     case ETHERTYPE_VLAN:
154       capture_vlan(pd, offset, len, ld);
155       break;
156     case ETHERTYPE_VINES_IP:
157     case ETHERTYPE_VINES_ECHO:
158       capture_vines(ld);
159       break;
160     default:
161       ld->other++;
162       break;
163   }
164 }
165
166 void
167 ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
168                 packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
169                 int etype_id, int trailer_id, int fcs_len)
170 {
171         const char              *description;
172         tvbuff_t                *next_tvb;
173         guint                   length_before;
174         volatile gboolean       dissector_found = FALSE;
175         const char              *saved_proto;
176
177         /* Add the Ethernet type to the protocol tree */
178         if (tree) {
179                 proto_tree_add_uint(fh_tree, etype_id, tvb,
180                     offset_after_etype - 2, 2, etype);
181         }
182
183         /* Tvbuff for the payload after the Ethernet type. */
184         next_tvb = tvb_new_subset(tvb, offset_after_etype, -1, -1);
185
186         pinfo->ethertype = etype;
187
188         /* Remember how much data there is in it. */
189         length_before = tvb_reported_length(next_tvb);
190
191         /* Look for sub-dissector, and call it if found.
192            Catch exceptions, so that if the reported length of "next_tvb"
193            was reduced by some dissector before an exception was thrown,
194            we can still put in an item for the trailer. */
195         saved_proto = pinfo->current_proto;
196         TRY {
197                 dissector_found = dissector_try_port(ethertype_dissector_table,
198                     etype, next_tvb, pinfo, tree);
199         }
200         CATCH(BoundsError) {
201                 /* Somebody threw BoundsError, which means that:
202
203                      1) a dissector was found, so we don't need to
204                         dissect the payload as data or update the
205                         protocol or info columns;
206
207                      2) dissecting the payload found that the packet was
208                         cut off by a snapshot length before the end of
209                         the payload.  The trailer comes after the payload,
210                         so *all* of the trailer is cut off, and we'll
211                         just get another BoundsError if we add the trailer.
212
213                    Therefore, we just rethrow the exception so it gets
214                    reported; we don't dissect the trailer or do anything
215                    else. */
216                  RETHROW;
217         }
218         CATCH_ALL {
219                 /* Somebody threw an exception other than BoundsError, which
220                    means that a dissector was found, so we don't need to
221                    dissect the payload as data or update the protocol or info
222                    columns.  We just show the exception and then drive on
223                    to show the trailer, after noting that a dissector was
224                    found and restoring the protocol value that was in effect
225                    before we called the subdissector. */
226                 show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
227                 dissector_found = TRUE;
228                 pinfo->current_proto = saved_proto;
229         }
230         ENDTRY;
231
232         if (!dissector_found) {
233                 /* No sub-dissector found.
234                    Label rest of packet as "Data" */
235                 call_dissector(data_handle,next_tvb, pinfo, tree);
236
237                 /* Label protocol */
238                 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
239                         col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x",
240                             etype);
241                 }
242                 if (check_col(pinfo->cinfo, COL_INFO)) {
243                         description = match_strval(etype, etype_vals);
244                         if (description) {
245                                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
246                                     description);
247                         }
248                 }
249         }
250
251         add_dix_trailer(fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
252             length_before, fcs_len);
253 }
254
255 static void
256 add_dix_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
257     tvbuff_t *next_tvb, int offset_after_etype, guint length_before,
258     gint fcs_len)
259 {
260         guint           length;
261         tvbuff_t        *volatile trailer_tvb;
262
263         if (fh_tree == NULL)
264                 return; /* we're not building a protocol tree */
265
266         if (trailer_id == -1)
267                 return; /* our caller doesn't care about trailers */
268
269         /* OK, how much is there in that tvbuff now? */
270         length = tvb_reported_length(next_tvb);
271
272         /* If there's less than there was before, what's left is
273            a trailer. */
274         if (length < length_before) {
275                 /*
276                  * Is any of the padding present in the tvbuff?
277                  */
278                 if (tvb_offset_exists(tvb, offset_after_etype + length)) {
279                         /*
280                          * Yes - create a tvbuff for the padding.
281                          */
282                         trailer_tvb = tvb_new_subset(tvb,
283                             offset_after_etype + length, -1, -1);
284                 } else {
285                         /*
286                          * No - don't bother showing the trailer.
287                          * XXX - show a Short Frame indication?
288                          */
289                         trailer_tvb = NULL;
290                 }
291         } else
292                 trailer_tvb = NULL;     /* no trailer */
293
294         add_ethernet_trailer(fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
295 }
296
297 void
298 proto_register_ethertype(void)
299 {
300         /* subdissector code */
301         ethertype_dissector_table = register_dissector_table("ethertype",
302             "Ethertype", FT_UINT16, BASE_HEX);
303 }
304
305 void
306 proto_reg_handoff_ethertype(void)
307 {
308         data_handle = find_dissector("data");
309 }