/src/wireshark/epan/dissectors/packet-ieee8023.c
Line | Count | Source |
1 | | /* packet-ieee8023.c |
2 | | * Routine for dissecting Ethernet packets with a length field (as opposed |
3 | | * to a type field). |
4 | | * |
5 | | * The name "ieee8023" is historical, dating back to when IEEE Std 802.3 |
6 | | * had only a length field and expected all packets to have an 802.2 |
7 | | * header following the MAC header. Since IEEE 802.3y-1997, 802.3 |
8 | | * supports either a type field or a length field, so it's no longer |
9 | | * correct to refer to "802.3" vs. "D/I/X" or vs. "Ethernet II" frames. |
10 | | * |
11 | | * Wireshark - Network traffic analyzer |
12 | | * By Gerald Combs <gerald@wireshark.org> |
13 | | * Copyright 1998 Gerald Combs |
14 | | * |
15 | | * SPDX-License-Identifier: GPL-2.0-or-later |
16 | | */ |
17 | | |
18 | | #include "config.h" |
19 | | |
20 | | #include <epan/packet.h> |
21 | | #include <epan/exceptions.h> |
22 | | #include <epan/expert.h> |
23 | | #include <epan/show_exception.h> |
24 | | #include "packet-ieee8023.h" |
25 | | #include "packet-eth.h" |
26 | | |
27 | | void proto_reg_handoff_ieee802_3(void); |
28 | | |
29 | | static dissector_handle_t ipx_handle; |
30 | | static dissector_handle_t llc_handle; |
31 | | static dissector_handle_t ccsds_handle; |
32 | | |
33 | | void |
34 | | dissect_802_3(volatile int length, bool is_802_2, tvbuff_t *tvb, |
35 | | int offset_after_length, packet_info *pinfo, proto_tree *tree, |
36 | | proto_tree *fh_tree, int length_id, int trailer_id, expert_field* ei_len, |
37 | | int fcs_len) |
38 | 3.33k | { |
39 | 3.33k | proto_item *length_it; |
40 | 3.33k | tvbuff_t *volatile next_tvb = NULL; |
41 | 3.33k | tvbuff_t *trailer_tvb = NULL; |
42 | 3.33k | const char *saved_proto; |
43 | 3.33k | int captured_length, reported_length; |
44 | | |
45 | 3.33k | length_it = proto_tree_add_uint(fh_tree, length_id, tvb, |
46 | 3.33k | offset_after_length - 2, 2, length); |
47 | | |
48 | | /* Get the length of the payload. |
49 | | If the FCS length is positive, remove the FCS. |
50 | | (If it's zero, there's no FCS; if it's negative, we don't know whether |
51 | | there's an FCS, so we'll guess based on the length of the trailer.) */ |
52 | 3.33k | reported_length = tvb_reported_length_remaining(tvb, offset_after_length); |
53 | 3.33k | if (fcs_len > 0) { |
54 | 41 | if (reported_length >= fcs_len) |
55 | 40 | reported_length -= fcs_len; |
56 | 41 | } |
57 | | |
58 | | /* Make sure the length in the 802.3 header doesn't go past the end of |
59 | | the payload. */ |
60 | 3.33k | if (length > reported_length) { |
61 | 2.92k | length = reported_length; |
62 | 2.92k | expert_add_info(pinfo, length_it, ei_len); |
63 | 2.92k | } |
64 | | |
65 | | /* Give the next dissector only 'length' number of bytes. */ |
66 | 3.33k | captured_length = tvb_captured_length_remaining(tvb, offset_after_length); |
67 | 3.33k | if (captured_length > length) |
68 | 432 | captured_length = length; |
69 | 3.33k | next_tvb = tvb_new_subset_length_caplen(tvb, offset_after_length, captured_length, length); |
70 | | |
71 | | /* Dissect the payload either as IPX or as an LLC frame. |
72 | | Catch non-fatal exceptions, so that if the reported length |
73 | | of "next_tvb" was reduced by some dissector before an |
74 | | exception was thrown, we can still put in an item for |
75 | | the trailer. */ |
76 | 3.33k | saved_proto = pinfo->current_proto; |
77 | 3.33k | TRY { |
78 | 3.33k | if (is_802_2) |
79 | 3.14k | call_dissector(llc_handle, next_tvb, pinfo, tree); |
80 | 187 | else { |
81 | | /* Check if first three bits of payload are 0x7. |
82 | | If so, then payload is IPX. If not, then it's CCSDS. |
83 | | Refer to packet-eth.c for setting of is_802_2 variable. */ |
84 | 187 | if (tvb_get_bits8(next_tvb, 0, 3) == 7) |
85 | 186 | call_dissector(ipx_handle, next_tvb, pinfo, tree); |
86 | 1 | else |
87 | 1 | call_dissector(ccsds_handle, next_tvb, pinfo, tree); |
88 | 187 | } |
89 | 3.33k | } |
90 | 3.33k | CATCH_NONFATAL_ERRORS { |
91 | | /* Somebody threw an exception that means that there was a problem |
92 | | dissecting the payload; that means that a dissector was found, |
93 | | so we don't need to dissect the payload as data or update the |
94 | | protocol or info columns. |
95 | | |
96 | | Just show the exception and then drive on to show the trailer, |
97 | | after noting that a dissector was found and restoring the |
98 | | protocol value that was in effect before we called the subdissector. */ |
99 | 1.52k | show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); |
100 | 1.52k | } |
101 | 3.33k | ENDTRY; |
102 | | |
103 | | /* Restore the protocol value, so that any exception thrown by |
104 | | tvb_new_subset_remaining() refers to the protocol for which |
105 | | this is a trailer. */ |
106 | 3.33k | pinfo->current_proto = saved_proto; |
107 | | |
108 | | /* Construct a tvbuff for the trailer; if the trailer is past the |
109 | | end of the captured data, this will throw a BoundsError, which |
110 | | is what we want, as it'll report that the packet was cut short. */ |
111 | 3.33k | trailer_tvb = tvb_new_subset_remaining(tvb, offset_after_length + length); |
112 | | |
113 | 3.33k | add_ethernet_trailer(pinfo, tree, fh_tree, trailer_id, tvb, trailer_tvb, fcs_len, offset_after_length); |
114 | 3.33k | } |
115 | | |
116 | | void |
117 | | proto_reg_handoff_ieee802_3(void) |
118 | 14 | { |
119 | | /* |
120 | | * Get handles for the subdissectors. |
121 | | */ |
122 | 14 | ipx_handle = find_dissector("ipx"); |
123 | 14 | llc_handle = find_dissector("llc"); |
124 | 14 | ccsds_handle = find_dissector("ccsds"); |
125 | 14 | } |
126 | | |
127 | | /* |
128 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
129 | | * |
130 | | * Local Variables: |
131 | | * c-basic-offset: 2 |
132 | | * tab-width: 8 |
133 | | * indent-tabs-mode: nil |
134 | | * End: |
135 | | * |
136 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
137 | | * :indentSize=2:tabSize=8:noTabs=true: |
138 | | */ |