Document the new Copy Profile button.
[obnox/wireshark/wip.git] / epan / dissectors / packet-ieee8023.c
1 /* packet-ieee8023.c
2  * Routine for dissecting 802.3 (as opposed to D/I/X Ethernet) packets.
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/expert.h>
32 #include "packet-ieee8023.h"
33 #include "packet-eth.h"
34 #include "packet-frame.h"
35
36 static dissector_handle_t ipx_handle;
37 static dissector_handle_t llc_handle;
38 static dissector_handle_t ccsds_handle;
39
40 void
41 dissect_802_3(volatile int length, gboolean is_802_2, tvbuff_t *tvb,
42               int offset_after_length, packet_info *pinfo, proto_tree *tree,
43               proto_tree *fh_tree, int length_id, int trailer_id,
44               int fcs_len)
45 {
46   proto_item            *length_it;
47   tvbuff_t              *volatile next_tvb = NULL;
48   tvbuff_t              *volatile trailer_tvb = NULL;
49   const char            *saved_proto;
50   gint                  captured_length, reported_length;
51
52   length_it = proto_tree_add_uint(fh_tree, length_id, tvb,
53                                   offset_after_length - 2, 2, length);
54
55   /* Get the length of the payload.
56      If the FCS length is positive, remove the FCS.
57      (If it's zero, there's no FCS; if it's negative, we don't know whether
58      there's an FCS, so we'll guess based on the length of the trailer.) */
59   reported_length = tvb_reported_length_remaining(tvb, offset_after_length);
60   if (fcs_len > 0) {
61     if (reported_length >= fcs_len)
62       reported_length -= fcs_len;
63   }
64
65   /* Make sure the length in the 802.3 header doesn't go past the end of
66      the payload. */
67   if (length > reported_length) {
68     length = reported_length;
69     expert_add_info_format(pinfo, length_it, PI_MALFORMED, PI_ERROR,
70         "Length field value goes past the end of the payload");
71   }
72
73   /* Give the next dissector only 'length' number of bytes. */
74   captured_length = tvb_length_remaining(tvb, offset_after_length);
75   if (captured_length > length)
76     captured_length = length;
77   next_tvb = tvb_new_subset(tvb, offset_after_length, captured_length, length);
78   TRY {
79     trailer_tvb = tvb_new_subset_remaining(tvb, offset_after_length + length);
80   }
81   CATCH2(BoundsError, ReportedBoundsError) {
82     /* The packet has exactly "length" bytes worth of captured data
83        left in it, so the "tvb_new_subset()" creating "trailer_tvb"
84        threw an exception.
85
86        This means that all the data in the frame is within the length
87        value (assuming our offset isn't past the end of the tvb), so
88        we give all the data to the next protocol and have no trailer. */
89     trailer_tvb = NULL;
90   }
91   ENDTRY;
92
93   /* Dissect the payload either as IPX or as an LLC frame.
94      Catch BoundsError and ReportedBoundsError, so that if the
95      reported length of "next_tvb" was reduced by some dissector
96      before an exception was thrown, we can still put in an item
97      for the trailer. */
98   saved_proto = pinfo->current_proto;
99   TRY {
100     if (is_802_2)
101       call_dissector(llc_handle, next_tvb, pinfo, tree);
102     else {
103       /* Check if first three bits of payload are 0x7.
104          If so, then payload is IPX.  If not, then it's CCSDS.
105          Refer to packet-eth.c for setting of is_802_2 variable. */
106       if (tvb_get_bits8(next_tvb, 0, 3) == 7)
107         call_dissector(ipx_handle, next_tvb, pinfo, tree);
108       else
109         call_dissector(ccsds_handle, next_tvb, pinfo, tree);
110     }
111   }
112   CATCH(BoundsError) {
113    /* Somebody threw BoundsError, which means that dissecting the payload
114       found that the packet was cut off by a snapshot length before the
115       end of the payload.  The trailer comes after the payload, so *all*
116       of the trailer is cut off - don't bother adding the trailer, just
117       rethrow the exception so it gets reported. */
118    RETHROW;
119   }
120   CATCH_ALL {
121     /* Well, somebody threw an exception other than BoundsError.
122        Show the exception, and then drive on to show the trailer,
123        restoring the protocol value that was in effect before we
124        called the subdissector. */
125     show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
126     pinfo->current_proto = saved_proto;
127   }
128   ENDTRY;
129
130   add_ethernet_trailer(pinfo, fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
131 }
132
133 void
134 proto_reg_handoff_ieee802_3(void)
135 {
136   /*
137    * Get handles for the subdissectors.
138    */
139   ipx_handle = find_dissector("ipx");
140   llc_handle = find_dissector("llc");
141   ccsds_handle = find_dissector("ccsds");
142 }