Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
*/