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