/src/wireshark/epan/dissectors/packet-raw.c
Line | Count | Source |
1 | | /* packet-raw.c |
2 | | * Routines for raw packet disassembly |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * |
7 | | * This file created and by Mike Hall <mlh@io.com> |
8 | | * Copyright 1998 |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | |
15 | | #include <epan/packet.h> |
16 | | #include <epan/capture_dissectors.h> |
17 | | #include "packet-ip.h" |
18 | | #include "packet-ppp.h" |
19 | | |
20 | | void proto_register_raw(void); |
21 | | void proto_reg_handoff_raw(void); |
22 | | |
23 | | static int proto_raw; |
24 | | static int ett_raw; |
25 | | |
26 | | static const unsigned char zeroes[10] = {0,0,0,0,0,0,0,0,0,0}; |
27 | | |
28 | | static dissector_handle_t raw_handle; |
29 | | static dissector_handle_t ip_handle; |
30 | | static dissector_handle_t ipv4_handle; |
31 | | static dissector_handle_t ipv6_handle; |
32 | | static dissector_handle_t ppp_hdlc_handle; |
33 | | |
34 | | static capture_dissector_handle_t ip_cap_handle; |
35 | | static capture_dissector_handle_t ipv6_cap_handle; |
36 | | static capture_dissector_handle_t ppp_hdlc_cap_handle; |
37 | | |
38 | | static bool |
39 | | capture_raw(const unsigned char *pd, int offset _U_, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_) |
40 | 0 | { |
41 | | /* So far, the only time we get raw connection types are with Linux and |
42 | | * Irix PPP connections. We can't tell what type of data is coming down |
43 | | * the line, so our safest bet is IP. - GCC |
44 | | */ |
45 | | |
46 | | /* Currently, the Linux 2.1.xxx PPP driver passes back some of the header |
47 | | * sometimes. This check should be removed when 2.2 is out. |
48 | | */ |
49 | 0 | if (BYTES_ARE_IN_FRAME(0,len,2) && pd[0] == 0xff && pd[1] == 0x03) { |
50 | 0 | return call_capture_dissector(ppp_hdlc_cap_handle, pd, 0, len, cpinfo, pseudo_header); |
51 | 0 | } |
52 | | /* The Linux ISDN driver sends a fake MAC address before the PPP header |
53 | | * on its ippp interfaces... */ |
54 | 0 | else if (BYTES_ARE_IN_FRAME(0,len,8) && pd[6] == 0xff && pd[7] == 0x03) { |
55 | 0 | return call_capture_dissector(ppp_hdlc_cap_handle, pd, 6, len, cpinfo, pseudo_header); |
56 | 0 | } |
57 | | /* ...except when it just puts out one byte before the PPP header... */ |
58 | 0 | else if (BYTES_ARE_IN_FRAME(0,len,3) && pd[1] == 0xff && pd[2] == 0x03) { |
59 | 0 | return call_capture_dissector(ppp_hdlc_cap_handle, pd, 1, len, cpinfo, pseudo_header); |
60 | 0 | } |
61 | | /* ...and if the connection is currently down, it sends 10 bytes of zeroes |
62 | | * instead of a fake MAC address and PPP header. */ |
63 | 0 | else if (BYTES_ARE_IN_FRAME(0,len,10) && memcmp(pd, zeroes, 10) == 0) { |
64 | 0 | return call_capture_dissector(ip_cap_handle, pd, 10, len, cpinfo, pseudo_header); |
65 | 0 | } |
66 | 0 | else { |
67 | | /* |
68 | | * OK, is this IPv4 or IPv6? |
69 | | */ |
70 | 0 | if (BYTES_ARE_IN_FRAME(0,len,1)) { |
71 | 0 | switch (pd[0] & 0xF0) { |
72 | | |
73 | 0 | case 0x40: |
74 | | /* IPv4 */ |
75 | 0 | return call_capture_dissector(ip_cap_handle, pd, 0, len, cpinfo, pseudo_header); |
76 | |
|
77 | | #if 0 |
78 | | case 0x60: |
79 | | /* IPv6 */ |
80 | | return call_capture_dissector(ipv6_cap_handle, pd, 0, len, cpinfo, pseudo_header); |
81 | | #endif |
82 | 0 | } |
83 | 0 | } |
84 | 0 | } |
85 | | |
86 | 0 | return false; |
87 | 0 | } |
88 | | |
89 | | static int |
90 | | dissect_raw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
91 | 2 | { |
92 | 2 | tvbuff_t *next_tvb; |
93 | | |
94 | | /* load the top pane info. This should be overwritten by |
95 | | the next protocol in the stack */ |
96 | 2 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A"); |
97 | 2 | col_set_str(pinfo->cinfo, COL_INFO, "Raw packet data"); |
98 | | |
99 | | /* populate a tree in the second pane with the status of the link |
100 | | layer (ie none) */ |
101 | 2 | proto_tree_add_item(tree, proto_raw, tvb, 0, tvb_captured_length(tvb), ENC_NA); |
102 | | |
103 | | /* So far, the only time we get raw connection types are with Linux and |
104 | | * Irix PPP connections. We can't tell what type of data is coming down |
105 | | * the line, so our safest bet is IP. - GCC |
106 | | */ |
107 | | |
108 | | /* Currently, the Linux 2.1.xxx PPP driver passes back some of the header |
109 | | * sometimes. This check should be removed when 2.2 is out. |
110 | | */ |
111 | 2 | if (tvb_get_ntohs(tvb, 0) == 0xff03) { |
112 | 0 | call_dissector(ppp_hdlc_handle, tvb, pinfo, tree); |
113 | 0 | } |
114 | | /* The Linux ISDN driver sends a fake MAC address before the PPP header |
115 | | * on its ippp interfaces... */ |
116 | 2 | else if (tvb_get_ntohs(tvb, 6) == 0xff03) { |
117 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 6); |
118 | 0 | call_dissector(ppp_hdlc_handle, next_tvb, pinfo, tree); |
119 | 0 | } |
120 | | /* ...except when it just puts out one byte before the PPP header... */ |
121 | 2 | else if (tvb_get_ntohs(tvb, 1) == 0xff03) { |
122 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 1); |
123 | 0 | call_dissector(ppp_hdlc_handle, next_tvb, pinfo, tree); |
124 | 0 | } |
125 | | /* ...and if the connection is currently down, it sends 10 bytes of zeroes |
126 | | * instead of a fake MAC address and PPP header. |
127 | | * |
128 | | * XXX - in at least one capture, I've seen 10 bytes of non-zero |
129 | | * values before the initial 0x45 of an IP packet without options. |
130 | | * However, just skipping the first 10 bytes if there's a 0x4x |
131 | | * byte after it breaks the parsing of some other captures. */ |
132 | 2 | else if (tvb_memeql(tvb, 0, zeroes,10) == 0) { |
133 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 10); |
134 | 0 | call_dissector(ip_handle, next_tvb, pinfo, tree); |
135 | 0 | } |
136 | 2 | else { |
137 | | /* |
138 | | * OK, is this IPv4 or IPv6? |
139 | | */ |
140 | 2 | switch (tvb_get_uint8(tvb, 0) & 0xF0) { |
141 | | |
142 | 1 | case 0x40: |
143 | | /* |
144 | | * IPv4. |
145 | | * |
146 | | * Create a new tvbuff, so that if the dissector sets the length |
147 | | * (e.g., because the packet has extra stuff after the datagram), |
148 | | * the top-level tvbuff isn't modified and shows all the data. |
149 | | */ |
150 | 1 | next_tvb = tvb_new_subset_remaining(tvb, 0); |
151 | 1 | call_dissector(ipv4_handle, next_tvb, pinfo, tree); |
152 | 1 | break; |
153 | | |
154 | 0 | case 0x60: |
155 | | /* |
156 | | * IPv6. |
157 | | * |
158 | | * Create a new tvbuff, so that if the dissector sets the length |
159 | | * (e.g., because the packet has extra stuff after the datagram), |
160 | | * the top-level tvbuff isn't modified and shows all the data. |
161 | | */ |
162 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 0); |
163 | 0 | call_dissector(ipv6_handle, next_tvb, pinfo, tree); |
164 | 0 | break; |
165 | | |
166 | 1 | default: |
167 | | /* None of the above. */ |
168 | 1 | call_data_dissector(tvb, pinfo, tree); |
169 | 1 | break; |
170 | 2 | } |
171 | 2 | } |
172 | 2 | return tvb_captured_length(tvb); |
173 | 2 | } |
174 | | |
175 | | static int |
176 | | dissect_raw_ip4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
177 | 0 | { |
178 | 0 | tvbuff_t *next_tvb; |
179 | | |
180 | | /* load the top pane info. This should be overwritten by |
181 | | the next protocol in the stack */ |
182 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A"); |
183 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Raw packet data"); |
184 | | |
185 | | /* populate a tree in the second pane with the status of the link |
186 | | layer (ie none) */ |
187 | 0 | proto_tree_add_item(tree, proto_raw, tvb, 0, tvb_captured_length(tvb), ENC_NA); |
188 | | /* |
189 | | * OK, hand this to the IPv4 dissector. |
190 | | * |
191 | | * Create a new tvbuff, so that if the dissector sets the length |
192 | | * (e.g., because the packet has extra stuff after the datagram), |
193 | | * the top-level tvbuff isn't modified and shows all the data. |
194 | | */ |
195 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 0); |
196 | 0 | call_dissector(ipv4_handle, next_tvb, pinfo, tree); |
197 | 0 | return tvb_captured_length(tvb); |
198 | 0 | } |
199 | | |
200 | | static int |
201 | | dissect_raw_ip6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
202 | 0 | { |
203 | 0 | tvbuff_t *next_tvb; |
204 | | |
205 | | /* load the top pane info. This should be overwritten by |
206 | | the next protocol in the stack */ |
207 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A"); |
208 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Raw packet data"); |
209 | | |
210 | | /* populate a tree in the second pane with the status of the link |
211 | | layer (ie none) */ |
212 | 0 | proto_tree_add_item(tree, proto_raw, tvb, 0, tvb_captured_length(tvb), ENC_NA); |
213 | | /* |
214 | | * OK, hand this to the IPv6 dissector. |
215 | | * |
216 | | * Create a new tvbuff, so that if the dissector sets the length |
217 | | * (e.g., because the packet has extra stuff after the datagram), |
218 | | * the top-level tvbuff isn't modified and shows all the data. |
219 | | */ |
220 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 0); |
221 | 0 | call_dissector(ipv6_handle, next_tvb, pinfo, tree); |
222 | 0 | return tvb_captured_length(tvb); |
223 | 0 | } |
224 | | |
225 | | void |
226 | | proto_register_raw(void) |
227 | 15 | { |
228 | 15 | static int *ett[] = { |
229 | 15 | &ett_raw, |
230 | 15 | }; |
231 | | |
232 | 15 | proto_raw = proto_register_protocol("Raw packet data", "Raw", "raw"); |
233 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
234 | | |
235 | 15 | raw_handle = register_dissector("raw_ip", dissect_raw, proto_raw); |
236 | 15 | } |
237 | | |
238 | | void |
239 | | proto_reg_handoff_raw(void) |
240 | 15 | { |
241 | 15 | dissector_handle_t raw_ip4_handle; |
242 | 15 | dissector_handle_t raw_ip6_handle; |
243 | 15 | capture_dissector_handle_t raw_cap_handle; |
244 | | |
245 | | /* |
246 | | * Get handles for the IPv{4,6}, IPv4, IPv6, undissected-data, and |
247 | | * PPP-in-HDLC-like-framing dissectors. |
248 | | */ |
249 | 15 | ip_handle = find_dissector_add_dependency("ip", proto_raw); |
250 | 15 | ipv4_handle = find_dissector_add_dependency("ipv4", proto_raw); |
251 | 15 | ipv6_handle = find_dissector_add_dependency("ipv6", proto_raw); |
252 | 15 | ppp_hdlc_handle = find_dissector_add_dependency("ppp_hdlc", proto_raw); |
253 | 15 | dissector_add_uint("wtap_encap", WTAP_ENCAP_RAW_IP, raw_handle); |
254 | 15 | raw_ip4_handle = create_dissector_handle(dissect_raw_ip4, proto_raw); |
255 | 15 | dissector_add_uint("wtap_encap", WTAP_ENCAP_RAW_IP4, raw_ip4_handle); |
256 | 15 | raw_ip6_handle = create_dissector_handle(dissect_raw_ip6, proto_raw); |
257 | 15 | dissector_add_uint("wtap_encap", WTAP_ENCAP_RAW_IP6, raw_ip6_handle); |
258 | 15 | raw_cap_handle = create_capture_dissector_handle(capture_raw, proto_raw); |
259 | 15 | capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_RAW_IP, raw_cap_handle); |
260 | | |
261 | 15 | ip_cap_handle = find_capture_dissector("ip"); |
262 | 15 | ipv6_cap_handle = find_capture_dissector("ipv6"); |
263 | 15 | ppp_hdlc_cap_handle = find_capture_dissector("ppp_hdlc"); |
264 | 15 | } |
265 | | |
266 | | /* |
267 | | * Editor modelines |
268 | | * |
269 | | * Local Variables: |
270 | | * c-basic-offset: 2 |
271 | | * tab-width: 8 |
272 | | * indent-tabs-mode: nil |
273 | | * End: |
274 | | * |
275 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
276 | | * :indentSize=2:tabSize=8:noTabs=true: |
277 | | */ |