/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 | 186 | #define KNET_SCTP_PACKET 1000 |
26 | 184 | #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 | 88 | #define PINGREQUEST 1 /*!< Message ID definition: Ping Request */ |
35 | 132 | #define PINGREPLY 2 /*!< Message ID definition: Ping Reply */ |
36 | 2 | #define FLOWCONTROLREQUEST 3 /*!< Message ID definition: Flow Control Request */ |
37 | 21 | #define PACKETACK 4 /*!< Message ID definition: Packet Acknowledge */ |
38 | 13 | #define DISCONNECT 255 /*!< Message ID definition: Disconnect */ |
39 | 15 | #define DISCONNECTACK 254 /*!< Message ID definition: Disconnect Ack */ |
40 | 8 | #define CONNECTSYN 253 /*!< Message ID definition: Connect Syn */ |
41 | 12 | #define CONNECTSYNACK 252 /*!< Message ID definition: Connect Syn Acknowledge */ |
42 | 14 | #define CONNECTACK 251 /*!< Message ID definition: Connect Acknowledge */ |
43 | | /**@}*/ |
44 | | |
45 | 32 | #define UDP_DATAGRAM_RELIABLE_FLAG 0x40 |
46 | 68 | #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 | 580 | { |
132 | 580 | unsigned byte_count = 1; |
133 | | |
134 | 580 | if(tvb_get_uint8(tvb, offset) & 0x80) /* If the first bit of the first byte is 1 */ |
135 | 37 | byte_count = 2; /* There's at least 2 bytes of content length */ |
136 | 580 | if(tvb_get_uint8(tvb, offset+1) & 0x80) /* If the next one is also 1 */ |
137 | 29 | byte_count = 4; |
138 | | |
139 | 580 | return byte_count; |
140 | 580 | } |
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 | 18 | { |
161 | 18 | uint32_t packetid; |
162 | | |
163 | 18 | packetid = tvb_get_uint8(buffer, offset+2) << 14; |
164 | 18 | packetid += tvb_get_uint8(buffer, offset+1) << 6; |
165 | 18 | packetid += tvb_get_uint8(buffer, offset) & 63; |
166 | | |
167 | 18 | proto_tree_add_uint(tree, hf_knet_packetid, buffer, 0, 3, packetid); |
168 | 18 | return packetid; |
169 | 18 | } |
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 | 5 | { |
190 | 5 | int byte_count = 2; |
191 | | |
192 | 5 | if(tvb_get_uint8(buffer, offset+1) & 0x80) |
193 | 2 | byte_count = 4; |
194 | | |
195 | 5 | proto_tree_add_item(tree, hf_knet_rmib, buffer, offset, byte_count, ENC_LITTLE_ENDIAN); |
196 | | |
197 | 5 | return byte_count; |
198 | 5 | } |
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, unsigned *offset, proto_tree *tree) |
218 | 393 | { |
219 | 393 | unsigned byte_count; |
220 | 393 | uint32_t length; |
221 | | |
222 | 393 | length = 0; |
223 | 393 | byte_count = count_vle_bytes(buffer, *offset); |
224 | | |
225 | 393 | switch(byte_count) /*We must calculate length by hand because we use the length later */ |
226 | 393 | { |
227 | 21 | case 4: |
228 | 21 | length = tvb_get_uint8(buffer, (*offset) + 3) << 22; |
229 | 21 | length += (tvb_get_uint8(buffer, (*offset) + 2) << 14); |
230 | | /* FALLTHRU */ |
231 | 33 | case 2: |
232 | 33 | length += ((tvb_get_uint8(buffer, (*offset) + 1) & 0x7F) << 7); |
233 | | /* FALLTHRU */ |
234 | 393 | case 1: |
235 | 393 | length += (tvb_get_uint8(buffer, (*offset)) & 0x7F); |
236 | 393 | break; |
237 | 0 | default: |
238 | 0 | REPORT_DISSECTOR_BUG("Error in Content Length calculation"); |
239 | 0 | break; |
240 | 393 | } |
241 | | |
242 | 393 | proto_tree_add_uint(tree, hf_knet_content_length_vle, buffer, (*offset), byte_count, length); |
243 | 393 | (*offset) += byte_count; |
244 | | |
245 | 393 | return length; |
246 | 393 | } |
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 | 109 | { |
267 | 109 | proto_item *msgflags_ti; |
268 | 109 | proto_tree *msgflags_tree; |
269 | 109 | uint32_t length; |
270 | | |
271 | 109 | length = tvb_get_bits8(buffer, offset * 8 + 12, 4) << 8; |
272 | 109 | length += tvb_get_bits8(buffer, offset * 8, 8); |
273 | | |
274 | 109 | if(tree != NULL) |
275 | 54 | { |
276 | 54 | msgflags_ti = proto_tree_add_item(tree, hf_knet_msg_flags, buffer, offset + 1, 1, ENC_NA); |
277 | 54 | msgflags_tree = proto_item_add_subtree(msgflags_ti, ett_knet_message_flags); |
278 | | |
279 | 54 | proto_tree_add_item(msgflags_tree, hf_knet_msg_fs, buffer, offset+1, 1, ENC_NA); /* Fragment start flag */ |
280 | 54 | proto_tree_add_item(msgflags_tree, hf_knet_msg_ff, buffer, offset+1, 1, ENC_NA); /* Fragment flag */ |
281 | 54 | proto_tree_add_item(msgflags_tree, hf_knet_msg_inorder, buffer, offset+1, 1, ENC_NA); /* Inorder flag */ |
282 | 54 | proto_tree_add_item(msgflags_tree, hf_knet_msg_reliable, buffer, offset+1, 1, ENC_NA); /* Reliable flag */ |
283 | | |
284 | 54 | proto_tree_add_uint(tree, hf_knet_content_length, buffer, offset, 2, length); |
285 | 54 | } |
286 | | |
287 | 109 | return length; |
288 | 109 | } |
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 | 44 | { |
309 | 44 | int byte_count = 1; |
310 | | |
311 | 44 | if(tvb_get_uint8(buffer, offset) & 0x80) |
312 | 6 | byte_count = 2; |
313 | | |
314 | 44 | proto_tree_add_item(tree, hf_knet_msg_reliable_message_number, buffer, offset, byte_count, ENC_LITTLE_ENDIAN); |
315 | | |
316 | 44 | return byte_count; |
317 | 44 | } |
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, unsigned *offset, proto_tree *tree, packet_info *pinfo, bool separator) |
336 | 239 | { |
337 | 239 | int messageid_length; |
338 | 239 | uint8_t messageid; |
339 | | |
340 | 239 | messageid = tvb_get_uint8(buffer, (*offset)); |
341 | | |
342 | 239 | switch(messageid) |
343 | 239 | { |
344 | 7 | case DISCONNECT: |
345 | 8 | case DISCONNECTACK: |
346 | 8 | case CONNECTSYN: |
347 | 10 | case CONNECTSYNACK: |
348 | 11 | case CONNECTACK: |
349 | 11 | messageid_length = 4; |
350 | 11 | break; |
351 | 224 | default: |
352 | 224 | messageid_length = 1; |
353 | 224 | break; |
354 | 239 | } |
355 | | |
356 | 235 | proto_tree_add_uint_format_value(tree, hf_knet_messageid, buffer, *offset, messageid_length, messageid, |
357 | 235 | "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData or Malformed Message ID"), messageid); |
358 | | |
359 | 235 | if (separator) |
360 | 221 | { |
361 | 221 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); |
362 | 221 | } |
363 | 14 | else |
364 | 14 | { |
365 | 14 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); |
366 | 14 | } |
367 | | |
368 | 235 | *offset += messageid_length; |
369 | | |
370 | 235 | return messageid; |
371 | 239 | } |
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 | 235 | { |
393 | 235 | proto_item *payload_ti; |
394 | 235 | proto_tree *payload_tree; |
395 | | |
396 | 235 | payload_ti = proto_tree_add_item(tree, hf_knet_payload_tree, buffer, offset, content_length - 1, ENC_NA); |
397 | 235 | payload_tree = proto_item_add_subtree(payload_ti, ett_knet_payload); |
398 | | |
399 | 235 | switch(messageid) |
400 | 235 | { |
401 | 88 | case PINGREQUEST: |
402 | 132 | case PINGREPLY: |
403 | 132 | proto_tree_add_item(payload_tree, hf_knet_pingid, buffer, offset, 1, ENC_LITTLE_ENDIAN); |
404 | 132 | break; |
405 | 2 | case FLOWCONTROLREQUEST: |
406 | 2 | proto_tree_add_item(payload_tree, hf_knet_flowctrlreq, buffer, offset, 3, ENC_LITTLE_ENDIAN); |
407 | 2 | break; |
408 | 21 | case PACKETACK: |
409 | 21 | proto_tree_add_item(payload_tree, hf_knet_packetack, buffer, offset, 3, ENC_LITTLE_ENDIAN); |
410 | 21 | offset += 3; |
411 | 21 | proto_tree_add_item(payload_tree, hf_knet_seqnumber, buffer, offset, 4, ENC_LITTLE_ENDIAN); |
412 | 21 | break; |
413 | 6 | case DISCONNECT: /*No payload*/ |
414 | 7 | case DISCONNECTACK: /*No payload*/ |
415 | 7 | proto_tree_add_bytes_format(payload_tree, hf_knet_payload, buffer, offset, 0, NULL, "No Payload"); |
416 | 7 | break; |
417 | 0 | case CONNECTSYN: /*TODO: Not yet implemented, implement when available*/ |
418 | 2 | case CONNECTSYNACK: /*TODO: Not yet implemented, implement when available*/ |
419 | 3 | case CONNECTACK: /*TODO: Not yet implemented, implement when available*/ |
420 | 3 | proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA); |
421 | 3 | break; |
422 | 67 | default: /* Application Specific Message */ |
423 | 67 | proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA); |
424 | 67 | break; |
425 | 235 | } |
426 | | |
427 | 124 | return 0; |
428 | 235 | } |
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, unsigned offset, int messageindex) |
444 | 54 | { |
445 | 54 | int content_length, total_length, messageid; |
446 | 54 | int start_offset = offset; |
447 | | |
448 | 54 | proto_item *msgblock_ti; |
449 | 54 | proto_tree *msgblock_tree; |
450 | | |
451 | 54 | msgblock_ti = proto_tree_add_item(tree, hf_knet_message_tree, tvb, offset, -1, ENC_NA); |
452 | 54 | msgblock_tree = proto_item_add_subtree(msgblock_ti, ett_knet_message); |
453 | | |
454 | 54 | content_length = dissect_content_length(tvb, offset, msgblock_tree); /* Calculates the Content Length of this packet. */ |
455 | | |
456 | 54 | if(tvb_get_uint8(tvb, offset+1) & UDP_MSG_BLOCK_RELIABLE_FLAG) /* If the reliable flag is 1 then calculate RMN */ |
457 | 44 | offset += dissect_reliable_message_number(tvb, offset+2, msgblock_tree); |
458 | | |
459 | 54 | offset += 2; /* Move the offset the amount of contentlength and flags fields */ |
460 | | |
461 | 54 | total_length = (offset-start_offset)+content_length; |
462 | 54 | proto_item_set_len(msgblock_ti, total_length); |
463 | | |
464 | 54 | messageid = dissect_messageid(tvb, &offset, msgblock_tree, pinfo, messageindex != 0); |
465 | | |
466 | 54 | dissect_payload(tvb, offset, messageid, msgblock_tree, content_length); |
467 | | |
468 | 54 | return total_length; |
469 | 54 | } |
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 | 185 | { |
488 | 185 | proto_item *knet_ti, *message_ti; |
489 | 185 | proto_tree *knet_tree, *message_tree; |
490 | | |
491 | 185 | unsigned offset = 0, content_length, messageid; |
492 | | |
493 | | /* Attach kNet main tree to Wireshark tree */ |
494 | 185 | knet_ti = proto_tree_add_item(tree, proto_knet, tvb, 0, -1, ENC_NA); |
495 | 185 | knet_tree = proto_item_add_subtree(knet_ti, ett_knet_main); |
496 | | |
497 | | /* Attach message tree to kNet tree */ |
498 | 185 | message_ti = proto_tree_add_item(knet_tree, hf_knet_message_tree, tvb, offset, -1, ENC_NA); |
499 | 185 | message_tree = proto_item_add_subtree(message_ti, ett_knet_message); |
500 | | |
501 | 185 | content_length = dissect_content_length_vle(tvb, &offset, message_tree); /* Calculate length and add it to the tree-view */ |
502 | 185 | proto_item_set_len(message_ti, (current_protocol == KNET_SCTP_PACKET ? content_length + 1 : content_length + 2)); |
503 | | |
504 | 185 | messageid = dissect_messageid(tvb, &offset, message_tree, pinfo, true); /* Calculate messageid and add it to the tree-view */ |
505 | | |
506 | 185 | dissect_payload(tvb, offset, messageid, message_tree, content_length); /* Calculate payload and add it to the tree-view */ |
507 | | |
508 | 185 | col_set_fence(pinfo->cinfo, COL_INFO); |
509 | 185 | } |
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 | 187 | { |
524 | 187 | unsigned uoffset = offset; |
525 | 187 | return count_vle_bytes(tvb, offset) + (unsigned)dissect_content_length_vle(tvb, &uoffset, NULL); |
526 | 187 | } |
527 | | |
528 | | /** |
529 | | * dissect_knet_tcp is the dissector which is called |
530 | | * by Wireshark when kNet TCP packets are captured. |
531 | | * |
532 | | * @param tvb the buffer to the data |
533 | | * @param pinfo the packet info structure |
534 | | * @param tree the parent tree where the dissected data is going to be inserted |
535 | | * |
536 | | */ |
537 | | static int |
538 | | dissect_knet_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
539 | 184 | { |
540 | 184 | dissect_knet(tvb, pinfo, tree, KNET_TCP_PACKET); |
541 | 184 | return tvb_captured_length(tvb); |
542 | 184 | } |
543 | | |
544 | | static int |
545 | | dissect_knet_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
546 | 23 | { |
547 | | //Sanity check the length field |
548 | 23 | if (tvb_reported_length(tvb) < 2) |
549 | 1 | return 0; |
550 | | |
551 | 22 | unsigned offset = 0; |
552 | 22 | if (dissect_content_length_vle(tvb, &offset, NULL) == 0) |
553 | 1 | return 0; |
554 | | |
555 | 21 | col_clear(pinfo->cinfo, COL_INFO); |
556 | 21 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET"); |
557 | | |
558 | 21 | tcp_dissect_pdus(tvb, pinfo, tree, true, 2, get_knet_pdu_len, dissect_knet_tcp_pdu, data); |
559 | 21 | return tvb_captured_length(tvb); |
560 | 22 | } |
561 | | |
562 | | /** |
563 | | * dissect_knet_sctp is the dissector which is called |
564 | | * by Wireshark when kNet STCP packets are captured. |
565 | | * |
566 | | * @param tvb the buffer to the data |
567 | | * @param pinfo the packet info structure |
568 | | * @param tree the parent tree where the dissected data is going to be inserted |
569 | | * |
570 | | */ |
571 | | static int |
572 | | dissect_knet_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
573 | 1 | { |
574 | 1 | col_clear(pinfo->cinfo, COL_INFO); |
575 | 1 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET"); |
576 | | |
577 | 1 | dissect_knet(tvb, pinfo, tree, KNET_SCTP_PACKET); |
578 | 1 | return tvb_captured_length(tvb); |
579 | 1 | } |
580 | | |
581 | | /** |
582 | | * dissect_knet_udp is the dissector which is called |
583 | | * by Wireshark when kNet UDP packets are captured. |
584 | | * |
585 | | * @param tvb the buffer to the data |
586 | | * @param pinfo the packet info structure |
587 | | * @param tree the parent tree where the dissected data is going to be inserted |
588 | | * |
589 | | */ |
590 | | static int |
591 | | dissect_knet_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
592 | 18 | { |
593 | | /* Common subtrees */ |
594 | 18 | proto_item *knet_ti; |
595 | 18 | proto_tree *knet_tree; |
596 | | |
597 | | /* Subtrees used in kNet UDP dissector */ |
598 | 18 | proto_item *datagram_ti, *udpflags_ti; |
599 | 18 | proto_tree *datagram_tree, /* Tree containing all header related info */ |
600 | 18 | *udpflags_tree; /* Tree containing UDP Datagram Flags */ |
601 | | |
602 | 18 | unsigned offset = 0; |
603 | 18 | uint32_t packetid; /* Contains info about PacketID */ |
604 | 18 | int messageindex = 0; /*!< Index of the kNet message inside a datagram */ |
605 | | |
606 | 18 | col_clear(pinfo->cinfo, COL_INFO); |
607 | 18 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET"); |
608 | | |
609 | | /*kNet UDP Tree*/ |
610 | 18 | knet_ti = proto_tree_add_item(tree, proto_knet, tvb, 0, -1, ENC_NA); /* Attach kNet tree to wireshark main tree */ |
611 | 18 | knet_tree = proto_item_add_subtree(knet_ti, ett_knet_main); |
612 | | |
613 | | /*Datagram Header Tree*/ |
614 | 18 | datagram_ti = proto_tree_add_item(knet_ti, hf_knet_datagram_tree, tvb, 0, 3, ENC_NA); /* Attach Header tree to wireshark main tree */ |
615 | 18 | datagram_tree = proto_item_add_subtree(datagram_ti, ett_knet_datagram); |
616 | | |
617 | 18 | packetid = dissect_packetid(tvb, 0, datagram_tree); /* Lets calculate our packetid! */ |
618 | 18 | col_add_fstr(pinfo->cinfo, COL_INFO, "Packet ID %d: ", packetid); |
619 | | |
620 | | /*UDPFlags Tree*/ |
621 | 18 | udpflags_ti = proto_tree_add_item(datagram_ti, hf_knet_flags, tvb, 0, 1, ENC_NA); /* Attach UDP Flags tree to kNet tree */ |
622 | 18 | udpflags_tree = proto_item_add_subtree(udpflags_ti, ett_knet_flags); |
623 | | |
624 | 18 | proto_tree_add_item(udpflags_tree, hf_knet_inorder, tvb, 0, 1, ENC_NA); /* Add inorder flag to UDP Flags tree */ |
625 | 18 | proto_tree_add_item(udpflags_tree, hf_knet_reliable, tvb, 0, 1, ENC_NA); /* Add reliable flag to UDP Flags tree */ |
626 | | |
627 | 18 | offset += 3; |
628 | | |
629 | 18 | if(tvb_get_uint8(tvb, 0) & UDP_DATAGRAM_RELIABLE_FLAG) |
630 | 5 | offset += dissect_reliable_message_index_base(tvb, 3, datagram_tree); /* Calculate RMIB */ |
631 | | |
632 | 72 | while ((tvb_reported_length_remaining(tvb, offset) > 2) && /* If there's at least 2 bytes available in the buffer */ |
633 | 55 | (dissect_content_length(tvb, offset, NULL) > 0)) /* Empty data Abort */ |
634 | 54 | { |
635 | 54 | offset += dissect_knet_message(tvb, pinfo, knet_tree, offset, messageindex); /* Call the message subdissector */ |
636 | 54 | messageindex++; |
637 | 54 | } |
638 | | |
639 | 18 | return tvb_captured_length(tvb); |
640 | 18 | } |
641 | | /** |
642 | | * proto_register_knet registers our kNet protocol, |
643 | | * headerfield- and subtree-array to Wireshark. |
644 | | * |
645 | | */ |
646 | | void |
647 | | proto_register_knet(void) |
648 | 14 | { |
649 | | /* module_t *knet_module; */ |
650 | | |
651 | 14 | static hf_register_info hf_knet[] = |
652 | 14 | { |
653 | | /* TCP & SCTP Header */ |
654 | 14 | {&hf_knet_content_length_vle, |
655 | 14 | {"Content Length", "knet.length", |
656 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
657 | 14 | {&hf_knet_message_tree, |
658 | 14 | {"Message Block", "knet.msg", |
659 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
660 | | |
661 | | /* UDP Header */ |
662 | 14 | {&hf_knet_datagram_tree, |
663 | 14 | {"Datagram Header", "knet.datagram", |
664 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
665 | 14 | {&hf_knet_flags, |
666 | 14 | {"Flags", "knet.datagram.flags", |
667 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
668 | 14 | {&hf_knet_inorder, |
669 | 14 | {"Inorder Flag", "knet.datagram.inorder", |
670 | 14 | FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}}, |
671 | 14 | {&hf_knet_reliable, |
672 | 14 | {"Reliable Flag", "knet.datagram.reliable", |
673 | 14 | FT_BOOLEAN, 8, NULL, UDP_DATAGRAM_RELIABLE_FLAG, NULL, HFILL}}, |
674 | 14 | {&hf_knet_packetid, |
675 | 14 | {"Packet ID", "knet.datagram.packetid", |
676 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
677 | 14 | {&hf_knet_rmib, |
678 | 14 | {"Reliable Message Index Base", "knet.datagram.rmib", |
679 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
680 | 14 | {&hf_knet_msg_flags, |
681 | 14 | {"Flags", "knet.msg.flags", |
682 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
683 | 14 | {&hf_knet_msg_fs, |
684 | 14 | {"Fragment Start", "knet.msg.flags.fs", |
685 | 14 | FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}}, |
686 | 14 | {&hf_knet_msg_ff, |
687 | 14 | {"Fragment Flag", "knet.msg.flags.ff", |
688 | 14 | FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL}}, |
689 | 14 | {&hf_knet_msg_inorder, |
690 | 14 | {"Inorder Flag", "knet.msg.flags.inorder", |
691 | 14 | FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL}}, |
692 | 14 | {&hf_knet_msg_reliable, |
693 | 14 | {"Reliable Flag", "knet.msg.flags.reliable", |
694 | 14 | FT_BOOLEAN, 8, NULL, UDP_MSG_BLOCK_RELIABLE_FLAG, NULL, HFILL}}, |
695 | 14 | {&hf_knet_content_length, |
696 | 14 | {"Content Length", "knet.length", |
697 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
698 | 14 | {&hf_knet_msg_reliable_message_number, |
699 | 14 | {"Reliable Message Number", "knet.msg.reliable_number", |
700 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
701 | | |
702 | | /* Payload */ |
703 | 14 | {&hf_knet_payload_tree, |
704 | 14 | {"Payload", "knet.payload.tree", |
705 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
706 | 14 | {&hf_knet_payload, |
707 | 14 | {"Payload", "knet.payload.data", |
708 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
709 | 14 | {&hf_knet_messageid, |
710 | 14 | {"Message ID", "knet.payload.messageid", |
711 | 14 | FT_UINT32, BASE_DEC, VALS(packettypenames), 0x0, NULL, HFILL}}, |
712 | 14 | {&hf_knet_pingid, |
713 | 14 | {"Ping ID", "knet.payload.pingid", |
714 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
715 | 14 | {&hf_knet_flowctrlreq, |
716 | 14 | {"Flowcontrol Request", "knet.payload.flowctrlreq", |
717 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
718 | 14 | {&hf_knet_packetack, |
719 | 14 | {"Packet Ack", "knet.payload.packetack", |
720 | 14 | FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
721 | 14 | {&hf_knet_seqnumber, |
722 | 14 | {"Sequence Number", "knet.payload.seqnumber", |
723 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}} |
724 | 14 | }; |
725 | | |
726 | 14 | static int *ett_knet[] = |
727 | 14 | { |
728 | 14 | &ett_knet_main, |
729 | 14 | &ett_knet_datagram, |
730 | 14 | &ett_knet_flags, |
731 | 14 | &ett_knet_message, |
732 | 14 | &ett_knet_message_flags, |
733 | 14 | &ett_knet_payload |
734 | 14 | }; |
735 | | |
736 | | /* Register protocols */ |
737 | 14 | proto_knet = proto_register_protocol ("kNet Protocol", "KNET", "knet"); |
738 | | |
739 | | /* Register header field & subtree arrays */ |
740 | 14 | proto_register_field_array(proto_knet, hf_knet, array_length(hf_knet)); |
741 | 14 | proto_register_subtree_array(ett_knet, array_length(ett_knet)); |
742 | | |
743 | 14 | knet_handle_sctp = register_dissector("knetsctp", dissect_knet_sctp, proto_knet); |
744 | 14 | knet_handle_tcp = register_dissector("knettcp", dissect_knet_tcp, proto_knet); |
745 | 14 | knet_handle_udp = register_dissector("knetudp", dissect_knet_udp, proto_knet); |
746 | | |
747 | | /* Prefs module added by Decode As */ |
748 | | /* knet_module = prefs_register_protocol(proto_knet, NULL); */ |
749 | | |
750 | 14 | } |
751 | | |
752 | | /** |
753 | | * proto_reg_handoff_knet registers our kNet dissectors to Wireshark |
754 | | * |
755 | | */ |
756 | | void |
757 | | proto_reg_handoff_knet(void) |
758 | 14 | { |
759 | 14 | dissector_add_uint_with_preference("tcp.port", PORT, knet_handle_tcp); |
760 | 14 | dissector_add_uint_with_preference("udp.port", PORT, knet_handle_udp); |
761 | 14 | dissector_add_uint_with_preference("sctp.port", PORT, knet_handle_sctp); |
762 | 14 | } |
763 | | /* |
764 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
765 | | * |
766 | | * Local variables: |
767 | | * c-basic-offset: 4 |
768 | | * tab-width: 8 |
769 | | * indent-tabs-mode: nil |
770 | | * End: |
771 | | * |
772 | | * ex: set shiftwidth=4 tabstop=8 expandtab: |
773 | | * :indentSize=4:tabSize=8:noTabs=true: |
774 | | */ |