/src/wireshark/epan/dissectors/packet-knet.c
Line | Count | Source |
1 | | /* packet-knet.c |
2 | | * Routines for the KristalliNet (kNet) protocol. |
3 | | * Kari Vatjus-Anttila <kari.vatjus-anttila@cie.fi> |
4 | | * Ville Saarinen <ville.saarinen@cie.fi> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
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/prefs.h> |
17 | | #include "packet-tcp.h" |
18 | | |
19 | | void proto_register_knet(void); |
20 | | void proto_reg_handoff_knet(void); |
21 | | |
22 | | #define PROTO_TAG_KNET "KNET" /*!< Definition of kNet Protocol */ |
23 | 42 | #define PORT 2345 /* Not IANA registered */ |
24 | | |
25 | 388 | #define KNET_SCTP_PACKET 1000 |
26 | 380 | #define KNET_TCP_PACKET 1001 |
27 | | #define KNET_UDP_PACKET 1002 |
28 | | |
29 | | /** |
30 | | * @addtogroup messageids kNet Message ID:s |
31 | | * Message ID:s of the kNet protocol |
32 | | */ |
33 | | /**@{*/ |
34 | 54 | #define PINGREQUEST 1 /*!< Message ID definition: Ping Request */ |
35 | 285 | #define PINGREPLY 2 /*!< Message ID definition: Ping Reply */ |
36 | 12 | #define FLOWCONTROLREQUEST 3 /*!< Message ID definition: Flow Control Request */ |
37 | 11 | #define PACKETACK 4 /*!< Message ID definition: Packet Acknowledge */ |
38 | 14 | #define DISCONNECT 255 /*!< Message ID definition: Disconnect */ |
39 | 18 | #define DISCONNECTACK 254 /*!< Message ID definition: Disconnect Ack */ |
40 | 14 | #define CONNECTSYN 253 /*!< Message ID definition: Connect Syn */ |
41 | 20 | #define CONNECTSYNACK 252 /*!< Message ID definition: Connect Syn Acknowledge */ |
42 | 22 | #define CONNECTACK 251 /*!< Message ID definition: Connect Acknowledge */ |
43 | | /**@}*/ |
44 | | |
45 | 43 | #define UDP_DATAGRAM_RELIABLE_FLAG 0x40 |
46 | 94 | #define UDP_MSG_BLOCK_RELIABLE_FLAG 0x10 |
47 | | |
48 | | /** |
49 | | * @addtogroup protocols Protocol Variables |
50 | | * Protocol variables. |
51 | | */ |
52 | | /**@{*/ |
53 | | static int proto_knet; |
54 | | /**@}*/ |
55 | | |
56 | | /** |
57 | | * @addtogroup headerfields Dissector Header Fields |
58 | | * Header fields of the kNet datagram |
59 | | */ |
60 | | /* *@{*/ |
61 | | |
62 | | /* Fields used by the TCP/SCTP dissector */ |
63 | | static int hf_knet_message_tree; /*!< Message tree */ |
64 | | static int hf_knet_content_length_vle; /*!< Content Length */ |
65 | | |
66 | | /* Fields used by the UDP dissector */ |
67 | | static int hf_knet_content_length; /*!< Content Length */ |
68 | | static int hf_knet_datagram_tree; /*!< Datagram subtree */ |
69 | | static int hf_knet_flags; /*!< UDP Flags subtree */ |
70 | | static int hf_knet_inorder; /*!< Inorder Flag */ |
71 | | static int hf_knet_reliable; /*!< Reliable Flag */ |
72 | | static int hf_knet_packetid; /*!< PacketID */ |
73 | | static int hf_knet_rmib; /*!< Reliable Message Index Base */ |
74 | | static int hf_knet_msg_flags; /*!< Message Block Flags subtree */ |
75 | | static int hf_knet_msg_fs; /*!< Fragment Start */ |
76 | | static int hf_knet_msg_ff; /*!< Fragment Flag */ |
77 | | static int hf_knet_msg_inorder; /*!< Inorder Flag */ |
78 | | static int hf_knet_msg_reliable; /*!< Reliable Flag */ |
79 | | static int hf_knet_msg_reliable_message_number; /*!< Reliable Message Number */ |
80 | | |
81 | | static int hf_knet_payload_tree; /*!< Payload subtree */ |
82 | | static int hf_knet_payload; /*!< Payload subtree */ |
83 | | static int hf_knet_messageid; /*!< MessageID of the packet */ |
84 | | static int hf_knet_pingid; |
85 | | static int hf_knet_flowctrlreq; |
86 | | static int hf_knet_packetack; |
87 | | static int hf_knet_seqnumber; |
88 | | /**@}*/ |
89 | | |
90 | | /** |
91 | | * @addtogroup trees Subtrees used by the dissectors |
92 | | */ |
93 | | /* *@{*/ |
94 | | |
95 | | /*Knet Subtrees */ |
96 | | static int ett_knet_main; /*!< Main kNet tree */ |
97 | | static int ett_knet_message; /*!< Message tree */ |
98 | | static int ett_knet_payload; /*!< Payload tree */ |
99 | | static int ett_knet_message_flags; /*!< Message flags tree */ |
100 | | static int ett_knet_datagram; |
101 | | static int ett_knet_flags; |
102 | | /**@}*/ |
103 | | |
104 | | static dissector_handle_t knet_handle_sctp; |
105 | | static dissector_handle_t knet_handle_tcp; |
106 | | static dissector_handle_t knet_handle_udp; |
107 | | |
108 | | static const value_string packettypenames[] = { /*!< Messageid List */ |
109 | | { PINGREQUEST, "Ping Request" }, |
110 | | { PINGREPLY, "Ping Reply" }, |
111 | | { FLOWCONTROLREQUEST, "Flowcontrol Request" }, |
112 | | { PACKETACK, "Packet Ack" }, |
113 | | { DISCONNECT, "Disconnect" }, |
114 | | { DISCONNECTACK, "Disconnect Ack" }, |
115 | | { CONNECTSYN, "Connect Syn" }, |
116 | | { CONNECTSYNACK, "Connect Syn Ack" }, |
117 | | { CONNECTACK, "Connect Ack" }, |
118 | | { 0, NULL } |
119 | | }; |
120 | | |
121 | | /** |
122 | | * counts length of the variable length encoded field |
123 | | * |
124 | | * @param tvb the buffer to the data |
125 | | * @param offset the offset of data in the buffer |
126 | | * @return int returns number of bytes used |
127 | | * |
128 | | */ |
129 | | static unsigned |
130 | | count_vle_bytes(tvbuff_t *tvb, int offset) |
131 | 1.18k | { |
132 | 1.18k | unsigned byte_count = 1; |
133 | | |
134 | 1.18k | if(tvb_get_uint8(tvb, offset) & 0x80) /* If the first bit of the first byte is 1 */ |
135 | 66 | byte_count = 2; /* There's at least 2 bytes of content length */ |
136 | 1.18k | if(tvb_get_uint8(tvb, offset+1) & 0x80) /* If the next one is also 1 */ |
137 | 40 | byte_count = 4; |
138 | | |
139 | 1.18k | return byte_count; |
140 | 1.18k | } |
141 | | |
142 | | /** |
143 | | * dissect_packetid is a utility function which calculates |
144 | | * the packets Packet ID from the data. Packet ID is a field |
145 | | * located in the datagram header. |
146 | | * |
147 | | * @see dissect_reliable_message_index_base() |
148 | | * @see dissect_reliable_message_number() |
149 | | * @see dissect_content_length() |
150 | | * @see dissect_messageid() |
151 | | * @see dissect_payload() |
152 | | * @param buffer the buffer to the data |
153 | | * @param offset the offset where to start reading the data |
154 | | * @param tree the parent tree where the dissected data is going to be inserted |
155 | | * @return int returns the new offset |
156 | | * |
157 | | */ |
158 | | static uint32_t |
159 | | dissect_packetid(tvbuff_t *buffer, int offset, proto_tree *tree) |
160 | 29 | { |
161 | 29 | uint32_t packetid; |
162 | | |
163 | 29 | packetid = tvb_get_uint8(buffer, offset+2) << 14; |
164 | 29 | packetid += tvb_get_uint8(buffer, offset+1) << 6; |
165 | 29 | packetid += tvb_get_uint8(buffer, offset) & 63; |
166 | | |
167 | 29 | proto_tree_add_uint(tree, hf_knet_packetid, buffer, 0, 3, packetid); |
168 | 29 | return packetid; |
169 | 29 | } |
170 | | |
171 | | /** |
172 | | * dissect_reliable_message_index_base is a utility function |
173 | | * which calculates the packets RMIB if and only if the reliable |
174 | | * flag is set to 1. |
175 | | * |
176 | | * @see dissect_packetid() |
177 | | * @see dissect_content_length() |
178 | | * @see dissect_reliable_message_number() |
179 | | * @see dissect_messageid() |
180 | | * @see dissect_payload() |
181 | | * @param buffer the buffer to the data |
182 | | * @param offset the offset where to start reading the data |
183 | | * @param tree the parent tree where the dissected data is going to be inserted |
184 | | * @return int returns the new offset |
185 | | * |
186 | | */ |
187 | | static int |
188 | | dissect_reliable_message_index_base(tvbuff_t *buffer, int offset, proto_tree *tree) |
189 | 9 | { |
190 | 9 | int byte_count = 2; |
191 | | |
192 | 9 | if(tvb_get_uint8(buffer, offset+1) & 0x80) |
193 | 4 | byte_count = 4; |
194 | | |
195 | 9 | proto_tree_add_item(tree, hf_knet_rmib, buffer, offset, byte_count, ENC_LITTLE_ENDIAN); |
196 | | |
197 | 9 | return byte_count; |
198 | 9 | } |
199 | | |
200 | | /** |
201 | | * dissect_content_length_vle is a utility function which |
202 | | * calculates how long is the payload section of the message |
203 | | * in bytes which is VLE encoded. |
204 | | * |
205 | | * @see dissect_packetid() |
206 | | * @see dissect_reliable_message_index_base() |
207 | | * @see dissect_reliable_message_number() |
208 | | * @see dissect_messageid() |
209 | | * @see dissect_payload() |
210 | | * @param buffer the buffer to the data |
211 | | * @param offset the offset where to start reading the data |
212 | | * @param tree the parent tree where the dissected data is going to be inserted |
213 | | * @return int returns the content length of the packet |
214 | | * |
215 | | */ |
216 | | static int |
217 | | dissect_content_length_vle(tvbuff_t *buffer, int *offset, proto_tree *tree) |
218 | 798 | { |
219 | 798 | unsigned byte_count; |
220 | 798 | uint32_t length; |
221 | | |
222 | 798 | length = 0; |
223 | 798 | byte_count = count_vle_bytes(buffer, *offset); |
224 | | |
225 | 798 | switch(byte_count) /*We must calculate length by hand because we use the length later */ |
226 | 798 | { |
227 | 27 | case 4: |
228 | 27 | length = tvb_get_uint8(buffer, (*offset) + 3) << 23; |
229 | 27 | length += (tvb_get_uint8(buffer, (*offset) + 2) << 15); |
230 | | /* FALLTHRU */ |
231 | 51 | case 2: |
232 | 51 | length += (tvb_get_uint8(buffer, (*offset) + 1) << 7); |
233 | | /* FALLTHRU */ |
234 | 798 | case 1: |
235 | 798 | length += (tvb_get_uint8(buffer, (*offset)) & 0x7F); |
236 | 798 | break; |
237 | 0 | default: |
238 | 0 | REPORT_DISSECTOR_BUG("Error in Content Length calculation"); |
239 | 0 | break; |
240 | 798 | } |
241 | | |
242 | 798 | proto_tree_add_uint(tree, hf_knet_content_length_vle, buffer, (*offset), byte_count, length); |
243 | 798 | (*offset) += byte_count; |
244 | | |
245 | 798 | return length; |
246 | 798 | } |
247 | | |
248 | | /** |
249 | | * dissect_content_length is a utility function which |
250 | | * calculates how long is the payload section of the message |
251 | | * in bytes. Used only by the UDP dissector. |
252 | | * |
253 | | * @see dissect_packetid() |
254 | | * @see dissect_reliable_message_index_base() |
255 | | * @see dissect_reliable_message_number() |
256 | | * @see dissect_messageid() |
257 | | * @see dissect_payload() |
258 | | * @param buffer the buffer to the data |
259 | | * @param offset the offset where to start reading the data |
260 | | * @param tree the parent tree where the dissected data is going to be inserted |
261 | | * @return int returns the content length of the packet |
262 | | * |
263 | | */ |
264 | | static int |
265 | | dissect_content_length(tvbuff_t *buffer, int offset, proto_tree *tree) |
266 | 162 | { |
267 | 162 | proto_item *msgflags_ti; |
268 | 162 | proto_tree *msgflags_tree; |
269 | 162 | uint32_t length; |
270 | | |
271 | 162 | length = tvb_get_bits8(buffer, offset * 8 + 12, 4) << 8; |
272 | 162 | length += tvb_get_bits8(buffer, offset * 8, 8); |
273 | | |
274 | 162 | if(tree != NULL) |
275 | 80 | { |
276 | 80 | msgflags_ti = proto_tree_add_item(tree, hf_knet_msg_flags, buffer, offset + 1, 1, ENC_NA); |
277 | 80 | msgflags_tree = proto_item_add_subtree(msgflags_ti, ett_knet_message_flags); |
278 | | |
279 | 80 | proto_tree_add_item(msgflags_tree, hf_knet_msg_fs, buffer, offset+1, 1, ENC_NA); /* Fragment start flag */ |
280 | 80 | proto_tree_add_item(msgflags_tree, hf_knet_msg_ff, buffer, offset+1, 1, ENC_NA); /* Fragment flag */ |
281 | 80 | proto_tree_add_item(msgflags_tree, hf_knet_msg_inorder, buffer, offset+1, 1, ENC_NA); /* Inorder flag */ |
282 | 80 | proto_tree_add_item(msgflags_tree, hf_knet_msg_reliable, buffer, offset+1, 1, ENC_NA); /* Reliable flag */ |
283 | | |
284 | 80 | proto_tree_add_uint(tree, hf_knet_content_length, buffer, offset, 2, length); |
285 | 80 | } |
286 | | |
287 | 162 | return length; |
288 | 162 | } |
289 | | |
290 | | /** |
291 | | * dissect_reliable_message_number is a utility function which |
292 | | * calculates the RMN if and only if the reliable flag in the |
293 | | * message block is set to 1. |
294 | | * |
295 | | * @see dissect_packetid() |
296 | | * @see dissect_reliable_message_index_base() |
297 | | * @see dissect_content_length() |
298 | | * @see dissect_messageid() |
299 | | * @see dissect_payload() |
300 | | * @param buffer the buffer to the data |
301 | | * @param offset the offset where to start reading the data |
302 | | * @param tree the parent tree where the dissected data is going to be inserted |
303 | | * @return int returns the new offset |
304 | | * |
305 | | */ |
306 | | static int |
307 | | dissect_reliable_message_number(tvbuff_t *buffer, int offset, proto_tree *tree) |
308 | 59 | { |
309 | 59 | int byte_count = 1; |
310 | | |
311 | 59 | if(tvb_get_uint8(buffer, offset) & 0x80) |
312 | 9 | byte_count = 2; |
313 | | |
314 | 59 | proto_tree_add_item(tree, hf_knet_msg_reliable_message_number, buffer, offset, byte_count, ENC_LITTLE_ENDIAN); |
315 | | |
316 | 59 | return byte_count; |
317 | 59 | } |
318 | | |
319 | | /** |
320 | | * dissect_messageid is a utility function which |
321 | | * calculates the ID of the message. |
322 | | * |
323 | | * @see dissect_packetid() |
324 | | * @see dissect_reliable_message_index_base() |
325 | | * @see dissect_content_length() |
326 | | * @see dissect_reliable_message_number() |
327 | | * @see dissect_payload() |
328 | | * @param buffer the buffer to the data |
329 | | * @param offset the offset where to start reading the data |
330 | | * @param tree the parent tree where the dissected data is going to be inserted |
331 | | * @return int returns the messageid |
332 | | * |
333 | | */ |
334 | | static int |
335 | | dissect_messageid(tvbuff_t *buffer, int *offset, proto_tree *tree, packet_info *pinfo, bool separator) |
336 | 463 | { |
337 | 463 | int messageid_length; |
338 | 463 | uint8_t messageid; |
339 | | |
340 | 463 | messageid = tvb_get_uint8(buffer, (*offset)); |
341 | | |
342 | 463 | switch(messageid) |
343 | 463 | { |
344 | 7 | case DISCONNECT: |
345 | 9 | case DISCONNECTACK: |
346 | 12 | case CONNECTSYN: |
347 | 15 | case CONNECTSYNACK: |
348 | 16 | case CONNECTACK: |
349 | 16 | messageid_length = 4; |
350 | 16 | break; |
351 | 446 | default: |
352 | 446 | messageid_length = 1; |
353 | 446 | break; |
354 | 463 | } |
355 | | |
356 | 462 | proto_tree_add_uint_format_value(tree, hf_knet_messageid, buffer, *offset, messageid_length, messageid, |
357 | 462 | "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData or Malformed Message ID"), messageid); |
358 | | |
359 | 462 | if (separator) |
360 | 438 | { |
361 | 438 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); |
362 | 438 | } |
363 | 24 | else |
364 | 24 | { |
365 | 24 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); |
366 | 24 | } |
367 | | |
368 | 462 | *offset += messageid_length; |
369 | | |
370 | 462 | return messageid; |
371 | 463 | } |
372 | | |
373 | | /** |
374 | | * dissect_payload is a utility function which |
375 | | * calculates the actual payload of the message. |
376 | | * |
377 | | * @see dissect_packetid() |
378 | | * @see dissect_reliable_message_index_base() |
379 | | * @see dissect_content_length() |
380 | | * @see dissect_reliable_message_number() |
381 | | * @see dissect_messageid() |
382 | | * @param buffer the buffer to the data |
383 | | * @param offset the offset where to start reading the data |
384 | | * @param messageid the messageid of the received message |
385 | | * @param tree the parent tree where the dissected data is going to be inserted |
386 | | * @param content_length the content length of the payload |
387 | | * @return int returns 0 at the moment |
388 | | * |
389 | | */ |
390 | | static int |
391 | | dissect_payload(tvbuff_t *buffer, int offset, int messageid, proto_tree *tree, int content_length) |
392 | 462 | { |
393 | 462 | proto_item *payload_ti; |
394 | 462 | proto_tree *payload_tree; |
395 | | |
396 | 462 | payload_ti = proto_tree_add_item(tree, hf_knet_payload_tree, buffer, offset, content_length - 1, ENC_NA); |
397 | 462 | payload_tree = proto_item_add_subtree(payload_ti, ett_knet_payload); |
398 | | |
399 | 462 | switch(messageid) |
400 | 462 | { |
401 | 54 | case PINGREQUEST: |
402 | 285 | case PINGREPLY: |
403 | 285 | proto_tree_add_item(payload_tree, hf_knet_pingid, buffer, offset, 1, ENC_LITTLE_ENDIAN); |
404 | 285 | break; |
405 | 12 | case FLOWCONTROLREQUEST: |
406 | 12 | proto_tree_add_item(payload_tree, hf_knet_flowctrlreq, buffer, offset, 3, ENC_LITTLE_ENDIAN); |
407 | 12 | break; |
408 | 11 | case PACKETACK: |
409 | 11 | proto_tree_add_item(payload_tree, hf_knet_packetack, buffer, offset, 3, ENC_LITTLE_ENDIAN); |
410 | 11 | offset += 3; |
411 | 11 | proto_tree_add_item(payload_tree, hf_knet_seqnumber, buffer, offset, 4, ENC_LITTLE_ENDIAN); |
412 | 11 | break; |
413 | 7 | case DISCONNECT: /*No payload*/ |
414 | 9 | case DISCONNECTACK: /*No payload*/ |
415 | 9 | proto_tree_add_bytes_format(payload_tree, hf_knet_payload, buffer, offset, 0, NULL, "No Payload"); |
416 | 9 | break; |
417 | 2 | case CONNECTSYN: /*TODO: Not yet implemented, implement when available*/ |
418 | 5 | case CONNECTSYNACK: /*TODO: Not yet implemented, implement when available*/ |
419 | 6 | case CONNECTACK: /*TODO: Not yet implemented, implement when available*/ |
420 | 6 | proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA); |
421 | 6 | break; |
422 | 138 | default: /* Application Specific Message */ |
423 | 138 | proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA); |
424 | 138 | break; |
425 | 462 | } |
426 | | |
427 | 388 | return 0; |
428 | 462 | } |
429 | | |
430 | | /** |
431 | | * dissect_knet_message is the subdissector which is called |
432 | | * by dissect_knet when the dissector has dissected the |
433 | | * datagram header. This subdissector dissects all of the |
434 | | * messages which are encapsulated in the kNet datagram. |
435 | | * |
436 | | * @see dissect_knet() |
437 | | * @param tvb the buffer to the data |
438 | | * @param pinfo the packet info structure |
439 | | * @param tree the parent tree where the dissected data is going to be inserted |
440 | | * |
441 | | */ |
442 | | static int |
443 | | dissect_knet_message(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, int messageindex) |
444 | 80 | { |
445 | 80 | int content_length, total_length, messageid; |
446 | 80 | int start_offset = offset; |
447 | | |
448 | 80 | proto_item *msgblock_ti; |
449 | 80 | proto_tree *msgblock_tree; |
450 | | |
451 | 80 | msgblock_ti = proto_tree_add_item(tree, hf_knet_message_tree, tvb, offset, -1, ENC_NA); |
452 | 80 | msgblock_tree = proto_item_add_subtree(msgblock_ti, ett_knet_message); |
453 | | |
454 | 80 | content_length = dissect_content_length(tvb, offset, msgblock_tree); /* Calculates the Content Length of this packet. */ |
455 | | |
456 | 80 | if(tvb_get_uint8(tvb, offset+1) & UDP_MSG_BLOCK_RELIABLE_FLAG) /* If the reliable flag is 1 then calculate RMN */ |
457 | 59 | offset += dissect_reliable_message_number(tvb, offset+2, msgblock_tree); |
458 | | |
459 | 80 | offset += 2; /* Move the offset the amount of contentlength and flags fields */ |
460 | | |
461 | 80 | total_length = (offset-start_offset)+content_length; |
462 | 80 | proto_item_set_len(msgblock_ti, total_length); |
463 | | |
464 | 80 | messageid = dissect_messageid(tvb, &offset, msgblock_tree, pinfo, messageindex != 0); |
465 | | |
466 | 80 | dissect_payload(tvb, offset, messageid, msgblock_tree, content_length); |
467 | | |
468 | 80 | return total_length; |
469 | 80 | } |
470 | | |
471 | | /** |
472 | | * dissect_knet is the dissector which is called |
473 | | * by Wireshark when kNet packets are captured. Here |
474 | | * is dissected the SCTP and TCP packets in its own |
475 | | * section and UDP packets in its own, because UDP |
476 | | * packets differ quite a lot from SCTP and TCP. |
477 | | * SCTP and TCP in the other hand has quite the same |
478 | | * structure. |
479 | | * |
480 | | * @param tvb the buffer to the data |
481 | | * @param pinfo the packet info structure |
482 | | * @param tree the parent tree where the dissected data is going to be inserted |
483 | | * |
484 | | */ |
485 | | static void |
486 | | dissect_knet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int current_protocol) |
487 | 384 | { |
488 | 384 | proto_item *knet_ti, *message_ti; |
489 | 384 | proto_tree *knet_tree, *message_tree; |
490 | | |
491 | 384 | int offset = 0, content_length, messageid; |
492 | | |
493 | | /* Attach kNet main tree to Wireshark tree */ |
494 | 384 | knet_ti = proto_tree_add_item(tree, proto_knet, tvb, 0, -1, ENC_NA); |
495 | 384 | knet_tree = proto_item_add_subtree(knet_ti, ett_knet_main); |
496 | | |
497 | | /* Attach message tree to kNet tree */ |
498 | 384 | message_ti = proto_tree_add_item(knet_tree, hf_knet_message_tree, tvb, offset, -1, ENC_NA); |
499 | 384 | message_tree = proto_item_add_subtree(message_ti, ett_knet_message); |
500 | | |
501 | 384 | content_length = dissect_content_length_vle(tvb, &offset, message_tree); /* Calculate length and add it to the tree-view */ |
502 | 384 | proto_item_set_len(message_ti, (current_protocol == KNET_SCTP_PACKET ? content_length + 1 : content_length + 2)); |
503 | | |
504 | 384 | messageid = dissect_messageid(tvb, &offset, message_tree, pinfo, true); /* Calculate messageid and add it to the tree-view */ |
505 | | |
506 | 384 | dissect_payload(tvb, offset, messageid, message_tree, content_length); /* Calculate payload and add it to the tree-view */ |
507 | | |
508 | 384 | col_set_fence(pinfo->cinfo, COL_INFO); |
509 | 384 | } |
510 | | |
511 | | /** |
512 | | * Callback function that returns the pdu length. |
513 | | * Used by TCP dissector. |
514 | | * |
515 | | * @param pinfo the info about the packet |
516 | | * @param tvb the data buffer |
517 | | * @param offset the offset to the tvb buffer |
518 | | * @return unsigned returns pdu length |
519 | | * |
520 | | */ |
521 | | static unsigned |
522 | | get_knet_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) |
523 | 386 | { |
524 | 386 | return count_vle_bytes(tvb, offset) + (unsigned)dissect_content_length_vle(tvb, &offset, NULL); |
525 | 386 | } |
526 | | |
527 | | /** |
528 | | * dissect_knet_tcp is the dissector which is called |
529 | | * by Wireshark when kNet TCP packets are captured. |
530 | | * |
531 | | * @param tvb the buffer to the data |
532 | | * @param pinfo the packet info structure |
533 | | * @param tree the parent tree where the dissected data is going to be inserted |
534 | | * |
535 | | */ |
536 | | static int |
537 | | dissect_knet_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
538 | 380 | { |
539 | 380 | dissect_knet(tvb, pinfo, tree, KNET_TCP_PACKET); |
540 | 380 | return tvb_captured_length(tvb); |
541 | 380 | } |
542 | | |
543 | | static int |
544 | | dissect_knet_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
545 | 30 | { |
546 | | //Sanity check the length field |
547 | 30 | if (tvb_reported_length(tvb) < 2) |
548 | 0 | return 0; |
549 | | |
550 | 30 | int offset = 0; |
551 | 30 | if (dissect_content_length_vle(tvb, &offset, NULL) == 0) |
552 | 3 | return 0; |
553 | | |
554 | 27 | col_clear(pinfo->cinfo, COL_INFO); |
555 | 27 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET"); |
556 | | |
557 | 27 | tcp_dissect_pdus(tvb, pinfo, tree, true, 2, get_knet_pdu_len, dissect_knet_tcp_pdu, data); |
558 | 27 | return tvb_captured_length(tvb); |
559 | 30 | } |
560 | | |
561 | | /** |
562 | | * dissect_knet_sctp is the dissector which is called |
563 | | * by Wireshark when kNet STCP packets are captured. |
564 | | * |
565 | | * @param tvb the buffer to the data |
566 | | * @param pinfo the packet info structure |
567 | | * @param tree the parent tree where the dissected data is going to be inserted |
568 | | * |
569 | | */ |
570 | | static int |
571 | | dissect_knet_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
572 | 4 | { |
573 | 4 | col_clear(pinfo->cinfo, COL_INFO); |
574 | 4 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET"); |
575 | | |
576 | 4 | dissect_knet(tvb, pinfo, tree, KNET_SCTP_PACKET); |
577 | 4 | return tvb_captured_length(tvb); |
578 | 4 | } |
579 | | |
580 | | /** |
581 | | * dissect_knet_udp is the dissector which is called |
582 | | * by Wireshark when kNet UDP packets are captured. |
583 | | * |
584 | | * @param tvb the buffer to the data |
585 | | * @param pinfo the packet info structure |
586 | | * @param tree the parent tree where the dissected data is going to be inserted |
587 | | * |
588 | | */ |
589 | | static int |
590 | | dissect_knet_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
591 | 29 | { |
592 | | /* Common subtrees */ |
593 | 29 | proto_item *knet_ti; |
594 | 29 | proto_tree *knet_tree; |
595 | | |
596 | | /* Subtrees used in kNet UDP dissector */ |
597 | 29 | proto_item *datagram_ti, *udpflags_ti; |
598 | 29 | proto_tree *datagram_tree, /* Tree containing all header related info */ |
599 | 29 | *udpflags_tree; /* Tree containing UDP Datagram Flags */ |
600 | | |
601 | 29 | int offset = 0; |
602 | 29 | uint32_t packetid; /* Contains info about PacketID */ |
603 | 29 | int messageindex = 0; /*!< Index of the kNet message inside a datagram */ |
604 | | |
605 | 29 | col_clear(pinfo->cinfo, COL_INFO); |
606 | 29 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET"); |
607 | | |
608 | | /*kNet UDP Tree*/ |
609 | 29 | knet_ti = proto_tree_add_item(tree, proto_knet, tvb, 0, -1, ENC_NA); /* Attach kNet tree to wireshark main tree */ |
610 | 29 | knet_tree = proto_item_add_subtree(knet_ti, ett_knet_main); |
611 | | |
612 | | /*Datagram Header Tree*/ |
613 | 29 | datagram_ti = proto_tree_add_item(knet_ti, hf_knet_datagram_tree, tvb, 0, 3, ENC_NA); /* Attach Header tree to wireshark main tree */ |
614 | 29 | datagram_tree = proto_item_add_subtree(datagram_ti, ett_knet_datagram); |
615 | | |
616 | 29 | packetid = dissect_packetid(tvb, 0, datagram_tree); /* Lets calculate our packetid! */ |
617 | 29 | col_add_fstr(pinfo->cinfo, COL_INFO, "Packet ID %d: ", packetid); |
618 | | |
619 | | /*UDPFlags Tree*/ |
620 | 29 | udpflags_ti = proto_tree_add_item(datagram_ti, hf_knet_flags, tvb, 0, 1, ENC_NA); /* Attach UDP Flags tree to kNet tree */ |
621 | 29 | udpflags_tree = proto_item_add_subtree(udpflags_ti, ett_knet_flags); |
622 | | |
623 | 29 | proto_tree_add_item(udpflags_tree, hf_knet_inorder, tvb, 0, 1, ENC_NA); /* Add inorder flag to UDP Flags tree */ |
624 | 29 | proto_tree_add_item(udpflags_tree, hf_knet_reliable, tvb, 0, 1, ENC_NA); /* Add reliable flag to UDP Flags tree */ |
625 | | |
626 | 29 | offset += 3; |
627 | | |
628 | 29 | if(tvb_get_uint8(tvb, 0) & UDP_DATAGRAM_RELIABLE_FLAG) |
629 | 9 | offset += dissect_reliable_message_index_base(tvb, 3, datagram_tree); /* Calculate RMIB */ |
630 | | |
631 | 109 | while ((tvb_reported_length_remaining(tvb, offset) > 2) && /* If there's at least 2 bytes available in the buffer */ |
632 | 82 | (dissect_content_length(tvb, offset, NULL) > 0)) /* Empty data Abort */ |
633 | 80 | { |
634 | 80 | offset += dissect_knet_message(tvb, pinfo, knet_tree, offset, messageindex); /* Call the message subdissector */ |
635 | 80 | messageindex++; |
636 | 80 | } |
637 | | |
638 | 29 | return tvb_captured_length(tvb); |
639 | 29 | } |
640 | | /** |
641 | | * proto_register_knet registers our kNet protocol, |
642 | | * headerfield- and subtree-array to Wireshark. |
643 | | * |
644 | | */ |
645 | | void |
646 | | proto_register_knet(void) |
647 | 14 | { |
648 | | /* module_t *knet_module; */ |
649 | | |
650 | 14 | static hf_register_info hf_knet[] = |
651 | 14 | { |
652 | | /* TCP & SCTP Header */ |
653 | 14 | {&hf_knet_content_length_vle, |
654 | 14 | {"Content Length", "knet.length", |
655 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
656 | 14 | {&hf_knet_message_tree, |
657 | 14 | {"Message Block", "knet.msg", |
658 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
659 | | |
660 | | /* UDP Header */ |
661 | 14 | {&hf_knet_datagram_tree, |
662 | 14 | {"Datagram Header", "knet.datagram", |
663 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
664 | 14 | {&hf_knet_flags, |
665 | 14 | {"Flags", "knet.datagram.flags", |
666 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
667 | 14 | {&hf_knet_inorder, |
668 | 14 | {"Inorder Flag", "knet.datagram.inorder", |
669 | 14 | FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}}, |
670 | 14 | {&hf_knet_reliable, |
671 | 14 | {"Reliable Flag", "knet.datagram.reliable", |
672 | 14 | FT_BOOLEAN, 8, NULL, UDP_DATAGRAM_RELIABLE_FLAG, NULL, HFILL}}, |
673 | 14 | {&hf_knet_packetid, |
674 | 14 | {"Packet ID", "knet.datagram.packetid", |
675 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
676 | 14 | {&hf_knet_rmib, |
677 | 14 | {"Reliable Message Index Base", "knet.datagram.rmib", |
678 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
679 | 14 | {&hf_knet_msg_flags, |
680 | 14 | {"Flags", "knet.msg.flags", |
681 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
682 | 14 | {&hf_knet_msg_fs, |
683 | 14 | {"Fragment Start", "knet.msg.flags.fs", |
684 | 14 | FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}}, |
685 | 14 | {&hf_knet_msg_ff, |
686 | 14 | {"Fragment Flag", "knet.msg.flags.ff", |
687 | 14 | FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL}}, |
688 | 14 | {&hf_knet_msg_inorder, |
689 | 14 | {"Inorder Flag", "knet.msg.flags.inorder", |
690 | 14 | FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL}}, |
691 | 14 | {&hf_knet_msg_reliable, |
692 | 14 | {"Reliable Flag", "knet.msg.flags.reliable", |
693 | 14 | FT_BOOLEAN, 8, NULL, UDP_MSG_BLOCK_RELIABLE_FLAG, NULL, HFILL}}, |
694 | 14 | {&hf_knet_content_length, |
695 | 14 | {"Content Length", "knet.length", |
696 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
697 | 14 | {&hf_knet_msg_reliable_message_number, |
698 | 14 | {"Reliable Message Number", "knet.msg.reliable_number", |
699 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
700 | | |
701 | | /* Payload */ |
702 | 14 | {&hf_knet_payload_tree, |
703 | 14 | {"Payload", "knet.payload.tree", |
704 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
705 | 14 | {&hf_knet_payload, |
706 | 14 | {"Payload", "knet.payload.data", |
707 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
708 | 14 | {&hf_knet_messageid, |
709 | 14 | {"Message ID", "knet.payload.messageid", |
710 | 14 | FT_UINT32, BASE_DEC, VALS(packettypenames), 0x0, NULL, HFILL}}, |
711 | 14 | {&hf_knet_pingid, |
712 | 14 | {"Ping ID", "knet.payload.pingid", |
713 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
714 | 14 | {&hf_knet_flowctrlreq, |
715 | 14 | {"Flowcontrol Request", "knet.payload.flowctrlreq", |
716 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
717 | 14 | {&hf_knet_packetack, |
718 | 14 | {"Packet Ack", "knet.payload.packetack", |
719 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
720 | 14 | {&hf_knet_seqnumber, |
721 | 14 | {"Sequence Number", "knet.payload.seqnumber", |
722 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}} |
723 | 14 | }; |
724 | | |
725 | 14 | static int *ett_knet[] = |
726 | 14 | { |
727 | 14 | &ett_knet_main, |
728 | 14 | &ett_knet_datagram, |
729 | 14 | &ett_knet_flags, |
730 | 14 | &ett_knet_message, |
731 | 14 | &ett_knet_message_flags, |
732 | 14 | &ett_knet_payload |
733 | 14 | }; |
734 | | |
735 | | /* Register protocols */ |
736 | 14 | proto_knet = proto_register_protocol ("kNet Protocol", "KNET", "knet"); |
737 | | |
738 | | /* Register header field & subtree arrays */ |
739 | 14 | proto_register_field_array(proto_knet, hf_knet, array_length(hf_knet)); |
740 | 14 | proto_register_subtree_array(ett_knet, array_length(ett_knet)); |
741 | | |
742 | 14 | knet_handle_sctp = register_dissector("knetsctp", dissect_knet_sctp, proto_knet); |
743 | 14 | knet_handle_tcp = register_dissector("knettcp", dissect_knet_tcp, proto_knet); |
744 | 14 | knet_handle_udp = register_dissector("knetudp", dissect_knet_udp, proto_knet); |
745 | | |
746 | | /* Prefs module added by Decode As */ |
747 | | /* knet_module = prefs_register_protocol(proto_knet, NULL); */ |
748 | | |
749 | 14 | } |
750 | | |
751 | | /** |
752 | | * proto_reg_handoff_knet registers our kNet dissectors to Wireshark |
753 | | * |
754 | | */ |
755 | | void |
756 | | proto_reg_handoff_knet(void) |
757 | 14 | { |
758 | 14 | dissector_add_uint_with_preference("tcp.port", PORT, knet_handle_tcp); |
759 | 14 | dissector_add_uint_with_preference("udp.port", PORT, knet_handle_udp); |
760 | 14 | dissector_add_uint_with_preference("sctp.port", PORT, knet_handle_sctp); |
761 | 14 | } |
762 | | /* |
763 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
764 | | * |
765 | | * Local variables: |
766 | | * c-basic-offset: 4 |
767 | | * tab-width: 8 |
768 | | * indent-tabs-mode: nil |
769 | | * End: |
770 | | * |
771 | | * ex: set shiftwidth=4 tabstop=8 expandtab: |
772 | | * :indentSize=4:tabSize=8:noTabs=true: |
773 | | */ |