/src/wireshark/epan/dissectors/packet-tpkt.c
Line | Count | Source |
1 | | /* packet-tpkt.c |
2 | | * |
3 | | * Routine to check for RFC 1006 TPKT header and to dissect TPKT header |
4 | | * Copyright 2000, Philips Electronics N.V. |
5 | | * Andreas Sikkema <h323@ramdyne.nl> |
6 | | * |
7 | | * Routine to dissect RFC 1006 TPKT packet containing OSI TP PDU |
8 | | * Copyright 2001, Martin Thomas <Martin_A_Thomas@yahoo.com> |
9 | | * |
10 | | * Wireshark - Network traffic analyzer |
11 | | * By Gerald Combs <gerald@wireshark.org> |
12 | | * Copyright 1998 Gerald Combs |
13 | | * |
14 | | * SPDX-License-Identifier: GPL-2.0-or-later |
15 | | */ |
16 | | |
17 | | #include "config.h" |
18 | | |
19 | | #include <epan/packet.h> |
20 | | #include <epan/exceptions.h> |
21 | | #include <epan/prefs.h> |
22 | | #include <epan/show_exception.h> |
23 | | #include <epan/conversation.h> |
24 | | |
25 | | #include "packet-tpkt.h" |
26 | | |
27 | | void proto_register_tpkt(void); |
28 | | void proto_reg_handoff_tpkt(void); |
29 | | |
30 | | static heur_dissector_list_t tpkt_heur_subdissector_list; |
31 | | |
32 | | /* TPKT header fields */ |
33 | | static int proto_tpkt; |
34 | | static int proto_tpkt_heur; |
35 | | static protocol_t *proto_tpkt_ptr; |
36 | | static int hf_tpkt_version; |
37 | | static int hf_tpkt_reserved; |
38 | | static int hf_tpkt_length; |
39 | | static int hf_tpkt_continuation_data; |
40 | | |
41 | | |
42 | | /* TPKT fields defining a sub tree */ |
43 | | static int ett_tpkt; |
44 | | |
45 | | /* desegmentation of OSI over TPKT over TCP */ |
46 | | static bool tpkt_desegment = true; |
47 | | |
48 | 15 | #define TCP_PORT_TPKT_RANGE "102" |
49 | | |
50 | | /* IANA registered port for RDP (as ms-wbt-server) */ |
51 | 15 | #define TCP_PORT_RDP 3389 |
52 | | |
53 | | /* find the dissector for OSI TP (aka COTP) */ |
54 | | static dissector_handle_t osi_tp_handle; |
55 | | static dissector_handle_t tpkt_handle; |
56 | | |
57 | | #define DEFAULT_TPKT_PORT_RANGE "102" |
58 | | |
59 | | /* |
60 | | * Check whether this could be a TPKT-encapsulated PDU. |
61 | | * Returns -1 if it's not, and the PDU length from the TPKT header |
62 | | * if it is. |
63 | | * |
64 | | * "min_len" is the minimum length of the PDU; the length field in the |
65 | | * TPKT header must be at least "4+min_len" in order for this to be a |
66 | | * valid TPKT PDU for the protocol in question. |
67 | | */ |
68 | | bool |
69 | | is_tpkt(tvbuff_t *tvb, unsigned min_len, unsigned *pkt_len) |
70 | 4.96k | { |
71 | 4.96k | unsigned t_pkt_len; |
72 | | |
73 | | /* |
74 | | * If TPKT is disabled, don't dissect it, just return -1, meaning |
75 | | * "this isn't TPKT". |
76 | | */ |
77 | 4.96k | if (!proto_is_protocol_enabled(proto_tpkt_ptr)) |
78 | 0 | return false; |
79 | | |
80 | | /* There should at least be 4 bytes left in the frame */ |
81 | 4.96k | if (tvb_captured_length(tvb) < 4) |
82 | 123 | return false; /* there aren't */ |
83 | | |
84 | | /* |
85 | | * The first octet should be 3 and the second one should be 0 |
86 | | * The H.323 implementers guide suggests that this might not |
87 | | * always be the case.... |
88 | | */ |
89 | 4.84k | if (!(tvb_get_uint8(tvb, 0) == 3 && tvb_get_uint8(tvb, 1) == 0)) |
90 | 4.82k | return false; /* they're not */ |
91 | | |
92 | | /* |
93 | | * Get the length from the TPKT header. Make sure it's large |
94 | | * enough. |
95 | | */ |
96 | 19 | t_pkt_len = tvb_get_ntohs(tvb, 2); |
97 | 19 | if (t_pkt_len < 4 + min_len) |
98 | 13 | return false; /* it's not */ |
99 | | |
100 | | /* |
101 | | * Return the length from the header. |
102 | | */ |
103 | 6 | if (pkt_len) { |
104 | 0 | *pkt_len = t_pkt_len; |
105 | 0 | } |
106 | 6 | return true; |
107 | 19 | } |
108 | | uint16_t |
109 | | is_asciitpkt(tvbuff_t *tvb) |
110 | 166 | { |
111 | 166 | uint16_t count; |
112 | | /* |
113 | | * If TPKT is disabled, don't dissect it, just return -1, meaning |
114 | | * "this isn't TPKT". |
115 | | */ |
116 | 166 | if (!proto_is_protocol_enabled(proto_tpkt_ptr)) |
117 | 0 | return -1; |
118 | | |
119 | | /* There should at least be 8 bytes left in the frame */ |
120 | 166 | if (!tvb_bytes_exist(tvb, 0, 8)) |
121 | 5 | return -1; /* there aren't */ |
122 | | |
123 | | /* |
124 | | * The first four octets should be alphanumeric ASCII |
125 | | */ |
126 | 767 | for (count = 0; count <=7 ; count ++) |
127 | 739 | { |
128 | 739 | if(!g_ascii_isalnum(tvb_get_uint8(tvb,count))) |
129 | 133 | { |
130 | 133 | return 0; |
131 | 133 | } |
132 | 739 | } |
133 | 28 | return 1; |
134 | | |
135 | | |
136 | 161 | } |
137 | | static int |
138 | | parseLengthText ( uint8_t* pTpktData ) |
139 | 121 | { |
140 | 121 | int value = 0; |
141 | 121 | const uint8_t * pData = pTpktData; |
142 | 121 | int bitvalue = 0, count1 = 3; |
143 | 121 | int count; |
144 | 605 | for (count = 0; count <= 3; count++) |
145 | 484 | { |
146 | 484 | if (('0' <= *(pData + count)) && (*(pData + count) <= '9')) |
147 | 261 | bitvalue = *(pData + count) - 48; |
148 | 223 | else if (('a' <= *(pData + count)) && (*(pData + count) <= 'f' )) |
149 | 5 | bitvalue = *(pData + count) - 87; |
150 | 218 | else if (('A' <= *(pData + count)) && (*(pData + count) <= 'F' )) |
151 | 4 | bitvalue = *(pData + count) - 55; |
152 | | |
153 | 484 | value += bitvalue << (4*count1); |
154 | 484 | count1--; |
155 | 484 | } |
156 | 121 | return value; |
157 | 121 | } |
158 | | static int |
159 | | parseVersionText ( uint8_t* pTpktData ) |
160 | 121 | { |
161 | 121 | int value = 0; |
162 | 121 | uint8_t * pData = pTpktData; |
163 | 121 | int bitvalue = 0, count1 = 1; |
164 | 121 | int count; |
165 | 363 | for (count = 0; count <= 1; count++) |
166 | 242 | { |
167 | 242 | if (('0' <= *(pData + count)) && (*(pData + count) <= '9')) |
168 | 229 | bitvalue = *(pData + count) - 48; |
169 | 13 | else if (('a' <= *(pData + count)) && (*(pData + count) <= 'f' )) |
170 | 0 | bitvalue = *(pData + count) - 87; |
171 | 13 | else if (('A' <= *(pData + count)) && (*(pData + count) <= 'F' )) |
172 | 1 | bitvalue = *(pData + count) - 55; |
173 | | |
174 | 242 | value += bitvalue << (4*count1); |
175 | 242 | count1--; |
176 | 242 | } |
177 | | |
178 | 121 | return value; |
179 | 121 | } |
180 | | static int |
181 | | parseReservedText ( uint8_t* pTpktData ) |
182 | 121 | { |
183 | 121 | int value = 0; |
184 | 121 | uint8_t * pData = pTpktData; |
185 | 121 | int bitvalue = 0, count1 = 1; |
186 | 121 | int count; |
187 | 363 | for (count = 0; count <= 1; count++) |
188 | 242 | { |
189 | 242 | if (('0' <= *(pData + count)) && (*(pData + count) <= '9')) |
190 | 170 | bitvalue = *(pData + count) - 48; |
191 | 72 | else if (('a' <= *(pData + count)) && (*(pData + count) <= 'f' )) |
192 | 9 | bitvalue = *(pData + count) - 87; |
193 | 63 | else if (('A' <= *(pData + count)) && (*(pData + count) <= 'F' )) |
194 | 1 | bitvalue = *(pData + count) - 55; |
195 | | |
196 | 242 | value += bitvalue << (4*count1); |
197 | 242 | count1--; |
198 | 242 | } |
199 | | |
200 | 121 | return value; |
201 | 121 | } |
202 | | |
203 | | /* |
204 | | * Length of the TPKT text-layer header. |
205 | | */ |
206 | | static const int TEXT_LAYER_LENGTH = 9; |
207 | | |
208 | | /* |
209 | | * Dissect ASCII TPKT-encapsulated data in a TCP stream. |
210 | | */ |
211 | | void |
212 | | dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
213 | | dissector_handle_t subdissector_handle) |
214 | 28 | { |
215 | 28 | proto_item *ti = NULL; |
216 | 28 | proto_tree *tpkt_tree = NULL; |
217 | 28 | volatile unsigned offset = 0; |
218 | 28 | int data_len; |
219 | 28 | volatile int mgcp_packet_len = 0; |
220 | 28 | int mgcp_version, mgcp_reserved; |
221 | 28 | tvbuff_t *volatile next_tvb; |
222 | 28 | const char *saved_proto; |
223 | 28 | uint8_t string[4]; |
224 | | |
225 | | /* |
226 | | * If we're reassembling segmented TPKT PDUs, empty the COL_INFO |
227 | | * column, so subdissectors can append information |
228 | | * without having to worry about emptying the column. |
229 | | * |
230 | | * We use "col_add_str()" because the subdissector |
231 | | * might be appending information to the column, in |
232 | | * which case we'd have to zero the buffer out explicitly |
233 | | * anyway. |
234 | | */ |
235 | 28 | if (tpkt_desegment) |
236 | 28 | col_clear(pinfo->cinfo, COL_INFO); |
237 | | |
238 | 149 | while (tvb_reported_length_remaining(tvb, offset) != 0) { |
239 | | /* |
240 | | * Is the first byte of this putative TPKT header |
241 | | * a valid TPKT version number, i.e. 3? |
242 | | */ |
243 | 135 | if (tvb_get_uint8(tvb, offset) != 48) { |
244 | | /* |
245 | | * No, so don't assume this is a TPKT header; |
246 | | * we might be in the middle of TPKT data, |
247 | | * so don't get the length and don't try to |
248 | | * do reassembly. |
249 | | */ |
250 | 14 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); |
251 | 14 | col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); |
252 | 14 | if (tree) { |
253 | 14 | ti = proto_tree_add_item(tree, proto_tpkt, tvb, |
254 | 14 | offset, -1, ENC_NA); |
255 | 14 | tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); |
256 | | |
257 | 14 | proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA); |
258 | 14 | } |
259 | 14 | return; |
260 | 14 | } |
261 | | |
262 | | /* |
263 | | * Get the length from the TPKT header. |
264 | | */ |
265 | | |
266 | 121 | tvb_memcpy(tvb, (uint8_t *)string, offset, 2); |
267 | 121 | mgcp_version = parseVersionText(string); |
268 | 121 | tvb_memcpy(tvb, (uint8_t *)string, offset +2, 2); |
269 | 121 | mgcp_reserved = parseReservedText(string); |
270 | 121 | tvb_memcpy(tvb, (uint8_t *)string, offset + 4, 4); |
271 | 121 | mgcp_packet_len = parseLengthText(string); |
272 | 121 | data_len = mgcp_packet_len; |
273 | | |
274 | | /* |
275 | | * Dissect the TPKT header. |
276 | | * Save and restore "pinfo->current_proto". |
277 | | */ |
278 | 121 | saved_proto = pinfo->current_proto; |
279 | 121 | pinfo->current_proto = "TPKT"; |
280 | | |
281 | 121 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); |
282 | | /* |
283 | | * Don't add the TPKT header information if we're |
284 | | * reassembling segmented TPKT PDUs or if this |
285 | | * PDU isn't reassembled. |
286 | | * |
287 | | * XXX - the first is so that subdissectors can append |
288 | | * information without getting TPKT stuff in the middle; |
289 | | * why the second? |
290 | | */ |
291 | 121 | if (!tpkt_desegment && !pinfo->fragmented) { |
292 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, |
293 | 0 | "TPKT Data length = %u", data_len); |
294 | 0 | } |
295 | | |
296 | 121 | if (tree) { |
297 | 121 | ti = proto_tree_add_item(tree, proto_tpkt, tvb, |
298 | 121 | offset, 8, ENC_NA); |
299 | 121 | tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); |
300 | 121 | proto_item_set_text(ti, "TPKT"); |
301 | | |
302 | | /* Version */ |
303 | 121 | proto_tree_add_uint(tpkt_tree, hf_tpkt_version, tvb, |
304 | 121 | offset, 2, mgcp_version); |
305 | | |
306 | | /* Reserved octet*/ |
307 | 121 | proto_tree_add_uint(tpkt_tree, hf_tpkt_reserved, tvb, |
308 | 121 | offset + 2, 2, mgcp_reserved); |
309 | | |
310 | | /* Length */ |
311 | 121 | proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb, |
312 | 121 | offset + 4, 4, mgcp_packet_len); |
313 | 121 | } |
314 | 121 | pinfo->current_proto = saved_proto; |
315 | | |
316 | | /* Skip the TPKT header. */ |
317 | 121 | offset += TEXT_LAYER_LENGTH; |
318 | | |
319 | 121 | next_tvb = tvb_new_subset_length(tvb, offset, data_len); |
320 | | |
321 | | /* |
322 | | * Call the subdissector. |
323 | | * |
324 | | * If it gets an error that means there's no point in |
325 | | * dissecting any more TPKT messages, rethrow the |
326 | | * exception in question. |
327 | | * |
328 | | * If it gets any other error, report it and continue, as that |
329 | | * means that TPKT message got an error, but that doesn't mean |
330 | | * we should stop dissecting TPKT messages within this frame |
331 | | * or chunk of reassembled data. |
332 | | */ |
333 | 121 | TRY { |
334 | 119 | call_dissector(subdissector_handle, next_tvb, pinfo, |
335 | 119 | tree); |
336 | 119 | } |
337 | 121 | CATCH_NONFATAL_ERRORS { |
338 | |
|
339 | 0 | show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); |
340 | 0 | } |
341 | 121 | ENDTRY; |
342 | | |
343 | | /* |
344 | | * Skip the payload. |
345 | | */ |
346 | 121 | offset += data_len; |
347 | 121 | } |
348 | 28 | } |
349 | | |
350 | | /* |
351 | | * Dissect TPKT-encapsulated data in a TCP stream. |
352 | | */ |
353 | | void |
354 | | dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
355 | | bool desegment, dissector_handle_t subdissector_handle) |
356 | 788 | { |
357 | 788 | proto_item *ti = NULL; |
358 | 788 | proto_tree *tpkt_tree = NULL; |
359 | 788 | volatile unsigned offset = 0; |
360 | 788 | unsigned length_remaining; |
361 | 788 | volatile unsigned data_len; |
362 | 788 | volatile unsigned length; |
363 | 788 | tvbuff_t *volatile next_tvb; |
364 | 788 | const char *saved_proto; |
365 | 788 | bool save_fragmented; |
366 | 788 | heur_dtbl_entry_t *hdtbl_entry; |
367 | | |
368 | | /* |
369 | | * If we're reassembling segmented TPKT PDUs, empty the COL_INFO |
370 | | * column, so subdissectors can append information |
371 | | * without having to worry about emptying the column. |
372 | | * |
373 | | * We use "col_add_str()" because the subdissector |
374 | | * might be appending information to the column, in |
375 | | * which case we'd have to zero the buffer out explicitly |
376 | | * anyway. |
377 | | */ |
378 | 788 | if (desegment) |
379 | 542 | col_clear(pinfo->cinfo, COL_INFO); |
380 | | |
381 | 1.46k | while (tvb_reported_length_remaining(tvb, offset) != 0) { |
382 | | /* |
383 | | * Is the first byte of this putative TPKT header |
384 | | * a valid TPKT version number, i.e. 3? |
385 | | */ |
386 | 818 | if (tvb_get_uint8(tvb, offset) != 3) { |
387 | | /* |
388 | | * No, so don't assume this is a TPKT header; |
389 | | * we might be in the middle of TPKT data, |
390 | | * so don't get the length and don't try to |
391 | | * do reassembly. |
392 | | */ |
393 | | |
394 | 139 | if (dissector_try_heuristic(tpkt_heur_subdissector_list, tvb, |
395 | 139 | pinfo, proto_tree_get_root(tree), |
396 | 139 | &hdtbl_entry, NULL)) { |
397 | 6 | return; |
398 | 6 | } |
399 | | |
400 | 133 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); |
401 | 133 | col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); |
402 | 133 | if (tree) { |
403 | 131 | ti = proto_tree_add_item(tree, proto_tpkt, tvb, |
404 | 131 | offset, -1, ENC_NA); |
405 | 131 | tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); |
406 | | |
407 | 131 | proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA); |
408 | 131 | } |
409 | 133 | return; |
410 | 139 | } |
411 | | |
412 | 679 | length_remaining = tvb_captured_length_remaining(tvb, offset); |
413 | | |
414 | | /* |
415 | | * Can we do reassembly? |
416 | | */ |
417 | 679 | if (desegment && pinfo->can_desegment) { |
418 | | /* |
419 | | * Yes - is the TPKT header split across segment |
420 | | * boundaries? |
421 | | */ |
422 | 0 | if (length_remaining < 4) { |
423 | | /* |
424 | | * Yes. Tell the TCP dissector where the data |
425 | | * for this message starts in the data it |
426 | | * handed us and that we need "some more data." |
427 | | * Don't tell it exactly how many bytes we need |
428 | | * because if/when we ask for even more (after |
429 | | * the header) that will break reassembly. |
430 | | */ |
431 | 0 | pinfo->desegment_offset = offset; |
432 | 0 | pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; |
433 | 0 | return; |
434 | 0 | } |
435 | 0 | } |
436 | | |
437 | | /* |
438 | | * Get the length from the TPKT header. |
439 | | */ |
440 | 679 | data_len = tvb_get_ntohs(tvb, offset + 2); |
441 | | |
442 | 679 | if (data_len < 4) { |
443 | | /* |
444 | | * The length includes the TPKT header, so this can't be a valid |
445 | | * TPKT header. We only checked one byte above, so we might be in |
446 | | * the middle of TPKT data. Call it continuation as above. |
447 | | */ |
448 | 2 | if (dissector_try_heuristic(tpkt_heur_subdissector_list, tvb, |
449 | 2 | pinfo, proto_tree_get_root(tree), |
450 | 2 | &hdtbl_entry, NULL)) { |
451 | 0 | return; |
452 | 0 | } |
453 | | |
454 | 2 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); |
455 | 2 | col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); |
456 | 2 | if (tree) { |
457 | 2 | ti = proto_tree_add_item(tree, proto_tpkt, tvb, |
458 | 2 | offset, -1, ENC_NA); |
459 | 2 | tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); |
460 | | |
461 | 2 | proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA); |
462 | 2 | } |
463 | 2 | return; |
464 | 2 | } |
465 | | |
466 | | /* |
467 | | * Can we do reassembly? |
468 | | */ |
469 | 677 | if (desegment && pinfo->can_desegment) { |
470 | | /* |
471 | | * Yes - is the payload split across segment |
472 | | * boundaries? |
473 | | */ |
474 | 0 | if (length_remaining < data_len) { |
475 | | /* |
476 | | * Yes. Tell the TCP dissector where |
477 | | * the data for this message starts in |
478 | | * the data it handed us, and how many |
479 | | * more bytes we need, and return. |
480 | | */ |
481 | 0 | pinfo->desegment_offset = offset; |
482 | 0 | pinfo->desegment_len = |
483 | 0 | data_len - length_remaining; |
484 | 0 | return; |
485 | 0 | } |
486 | 0 | } |
487 | | |
488 | | /* |
489 | | * Dissect the TPKT header. |
490 | | * Save and restore "pinfo->current_proto". |
491 | | */ |
492 | 677 | saved_proto = pinfo->current_proto; |
493 | 677 | pinfo->current_proto = "TPKT"; |
494 | | |
495 | 677 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); |
496 | | /* |
497 | | * Don't add the TPKT header information if we're |
498 | | * reassembling segmented TPKT PDUs or if this |
499 | | * PDU isn't reassembled. |
500 | | * |
501 | | * XXX - the first is so that subdissectors can append |
502 | | * information without getting TPKT stuff in the middle; |
503 | | * why the second? |
504 | | */ |
505 | 677 | if (!desegment && !pinfo->fragmented) { |
506 | 228 | col_add_fstr(pinfo->cinfo, COL_INFO, |
507 | 228 | "TPKT Data length = %u", data_len); |
508 | 228 | } |
509 | | |
510 | 677 | if (tree) { |
511 | 676 | ti = proto_tree_add_item(tree, proto_tpkt, tvb, |
512 | 676 | offset, 4, ENC_NA); |
513 | 676 | tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); |
514 | 676 | proto_item_set_text(ti, "TPKT"); |
515 | | |
516 | | /* Version */ |
517 | 676 | proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb, |
518 | 676 | offset, 1, ENC_BIG_ENDIAN); |
519 | 676 | proto_item_append_text(ti, ", Version: 3"); |
520 | | |
521 | | /* Reserved octet*/ |
522 | 676 | proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb, |
523 | 676 | offset + 1, 1, ENC_BIG_ENDIAN); |
524 | | |
525 | | /* Length */ |
526 | 676 | proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb, |
527 | 676 | offset + 2, 2, data_len); |
528 | 676 | proto_item_append_text(ti, ", Length: %u", data_len); |
529 | 676 | } |
530 | 677 | pinfo->current_proto = saved_proto; |
531 | | |
532 | | /* Skip the TPKT header. */ |
533 | 677 | offset += 4; |
534 | 677 | data_len -= 4; |
535 | | |
536 | | /* |
537 | | * Construct a tvbuff with reported length the amount |
538 | | * amount of data in this TPKT packet. |
539 | | * |
540 | | * If reassembly isn't enabled, and we don't have all the |
541 | | * payload, mark the packet as fragmented, so that |
542 | | * FragmentBoundsError is thrown instead of ReportedBoundsError. |
543 | | */ |
544 | 677 | save_fragmented = pinfo->fragmented; |
545 | 677 | length = length_remaining - 4; |
546 | 677 | if (length < data_len) { |
547 | 646 | pinfo->fragmented = true; |
548 | 646 | } |
549 | 677 | next_tvb = tvb_new_subset_length(tvb, offset, data_len); |
550 | | |
551 | | /* |
552 | | * Call the subdissector. |
553 | | * |
554 | | * If it gets an error that means there's no point in |
555 | | * dissecting any more TPKT messages, rethrow the |
556 | | * exception in question. |
557 | | * |
558 | | * If it gets any other error, report it and continue, |
559 | | * as that means that TPKT message got an error, but |
560 | | * that doesn't mean we should stop dissecting TPKT |
561 | | * messages within this frame or chunk of reassembled |
562 | | * data. |
563 | | */ |
564 | 677 | TRY { |
565 | 676 | call_dissector(subdissector_handle, next_tvb, pinfo, |
566 | 676 | tree); |
567 | 676 | } |
568 | 677 | CATCH_NONFATAL_ERRORS { |
569 | 624 | show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); |
570 | 624 | } |
571 | 677 | ENDTRY; |
572 | | |
573 | 677 | pinfo->fragmented = save_fragmented; |
574 | | |
575 | | /* |
576 | | * Skip the payload. |
577 | | */ |
578 | 677 | offset += data_len; |
579 | 677 | } |
580 | 788 | } |
581 | | |
582 | | /* |
583 | | * Dissect RFC 1006 TPKT, which wraps a TPKT header around an OSI TP |
584 | | * PDU. |
585 | | */ |
586 | | static int |
587 | | dissect_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
588 | 2 | { |
589 | 2 | dissect_tpkt_encap(tvb, pinfo, tree, tpkt_desegment, osi_tp_handle); |
590 | 2 | return tvb_captured_length(tvb); |
591 | 2 | } |
592 | | |
593 | | /* |
594 | | * Dissect ASCII TPKT, which wraps a ASCII TPKT header around an OSI TP |
595 | | * PDU. |
596 | | */ |
597 | | #if 0 |
598 | | static int |
599 | | dissect_ascii_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
600 | | { |
601 | | dissect_asciitpkt(tvb, pinfo, tree, osi_tp_handle); |
602 | | return tvb_captured_length(tvb); |
603 | | } |
604 | | #endif |
605 | | |
606 | | /* A heuristic dissector for TPKT. This is useful for RDP, where TLS may |
607 | | * or may not be present depending on the RDP security settings. |
608 | | */ |
609 | | static int |
610 | | dissect_tpkt_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
611 | 6 | { |
612 | 6 | unsigned pkt_len; |
613 | 6 | if (!is_tpkt(tvb, 0, &pkt_len)) { |
614 | | /* Doesn't look like TPKT directly. Might be over TLS, so reject |
615 | | * and let the TLS heuristic dissector take a look |
616 | | */ |
617 | 6 | return 0; |
618 | 6 | } |
619 | | |
620 | 0 | return dissect_tpkt(tvb, pinfo, tree, data); |
621 | 6 | } |
622 | | |
623 | | static bool |
624 | | dissect_tpkt_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
625 | 1 | { |
626 | 1 | return dissect_tpkt_tcp(tvb, pinfo, tree, data) > 0; |
627 | 1 | } |
628 | | |
629 | | void |
630 | | proto_register_tpkt(void) |
631 | 15 | { |
632 | 15 | static hf_register_info hf[] = { |
633 | 15 | { |
634 | 15 | &hf_tpkt_version, |
635 | 15 | { |
636 | 15 | "Version", |
637 | 15 | "tpkt.version", |
638 | 15 | FT_UINT16, |
639 | 15 | BASE_DEC, |
640 | 15 | NULL, |
641 | 15 | 0x0, |
642 | 15 | "Version, only version 3 is defined", HFILL |
643 | 15 | } |
644 | 15 | }, |
645 | 15 | { |
646 | 15 | &hf_tpkt_reserved, |
647 | 15 | { |
648 | 15 | "Reserved", |
649 | 15 | "tpkt.reserved", |
650 | 15 | FT_UINT8, |
651 | 15 | BASE_DEC, |
652 | 15 | NULL, |
653 | 15 | 0x0, |
654 | 15 | "Reserved, should be 0", HFILL |
655 | 15 | } |
656 | 15 | }, |
657 | 15 | { |
658 | 15 | &hf_tpkt_length, |
659 | 15 | { |
660 | 15 | "Length", |
661 | 15 | "tpkt.length", |
662 | 15 | FT_UINT16, |
663 | 15 | BASE_DEC, |
664 | 15 | NULL, |
665 | 15 | 0x0, |
666 | 15 | "Length of data unit, including this header", HFILL |
667 | 15 | } |
668 | 15 | }, |
669 | 15 | { |
670 | 15 | &hf_tpkt_continuation_data, |
671 | 15 | { |
672 | 15 | "Continuation data", |
673 | 15 | "tpkt.continuation_data", |
674 | 15 | FT_BYTES, |
675 | 15 | BASE_NONE, |
676 | 15 | NULL, |
677 | 15 | 0x0, |
678 | 15 | NULL, HFILL |
679 | 15 | } |
680 | 15 | }, |
681 | 15 | }; |
682 | | |
683 | 15 | static int *ett[] = |
684 | 15 | { |
685 | 15 | &ett_tpkt, |
686 | 15 | }; |
687 | 15 | module_t *tpkt_module; |
688 | | |
689 | 15 | proto_tpkt = proto_register_protocol("TPKT - ISO on TCP - RFC1006", "TPKT", "tpkt"); |
690 | 15 | proto_tpkt_ptr = find_protocol_by_id(proto_tpkt); |
691 | 15 | proto_register_field_array(proto_tpkt, hf, array_length(hf)); |
692 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
693 | 15 | tpkt_handle = register_dissector("tpkt", dissect_tpkt, proto_tpkt); |
694 | | |
695 | 15 | tpkt_module = prefs_register_protocol(proto_tpkt, NULL); |
696 | 15 | prefs_register_bool_preference(tpkt_module, "desegment", |
697 | 15 | "Reassemble TPKT messages spanning multiple TCP segments", |
698 | 15 | "Whether the TPKT dissector should reassemble messages spanning multiple TCP segments. " |
699 | 15 | "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", |
700 | 15 | &tpkt_desegment); |
701 | | |
702 | | /* heuristic dissectors for preamble CredSSP before RDP and Fast-Path RDP packets */ |
703 | 15 | tpkt_heur_subdissector_list = register_heur_dissector_list_with_description("tpkt", "TPKT fragment", proto_tpkt); |
704 | | |
705 | 15 | proto_tpkt_heur = proto_register_protocol_in_name_only("TPKT Heuristic (for RDP)", "TPKT Heuristic (for RDP)", "tpkt", proto_tpkt, FT_PROTOCOL); |
706 | 15 | } |
707 | | |
708 | | void |
709 | | proto_reg_handoff_tpkt(void) |
710 | 15 | { |
711 | 15 | osi_tp_handle = find_dissector("ositp"); |
712 | 15 | dissector_add_uint_range_with_preference("tcp.port", TCP_PORT_TPKT_RANGE, tpkt_handle); |
713 | | |
714 | | /* ssl_dissector_add registers TLS as the dissector for TCP for the |
715 | | * given port. We can't use it, since on port 3389 TPKT (for RDP) can be |
716 | | * over TLS or directly over TCP, depending on the RDP security settings. |
717 | | * TPKT heuristics are also too weak to enable in general. Instead, |
718 | | * use the heuristic dissector by default just on the RDP port, and |
719 | | * if rejected the TLS heuristic dissector will be tried. |
720 | | */ |
721 | 15 | dissector_add_uint("tcp.port", TCP_PORT_RDP, create_dissector_handle(dissect_tpkt_tcp, proto_tpkt_heur)); |
722 | 15 | heur_dissector_add("tcp", dissect_tpkt_heur, "TPKT over TCP", "tpkt_tcp", proto_tpkt, HEURISTIC_DISABLE); |
723 | 15 | heur_dissector_add("tls", dissect_tpkt_heur, "TPKT over TLS", "tpkt_tls", proto_tpkt, HEURISTIC_ENABLE); |
724 | | |
725 | | /* |
726 | | tpkt_ascii_handle = create_dissector_handle(dissect_ascii_tpkt, proto_tpkt); |
727 | | dissector_add_uint("tcp.port", TCP_PORT_TPKT, tpkt_ascii_handle); |
728 | | */ |
729 | | |
730 | 15 | } |
731 | | |
732 | | /* |
733 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
734 | | * |
735 | | * Local variables: |
736 | | * c-basic-offset: 4 |
737 | | * tab-width: 8 |
738 | | * indent-tabs-mode: nil |
739 | | * End: |
740 | | * |
741 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
742 | | * :indentSize=4:tabSize=8:noTabs=true: |
743 | | */ |