Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-hsms.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-hsms.c
2
 * Routines for High-speed SECS message service dissection
3
 * Copyright 2016, Benjamin Parzella <bparzella@gmail.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
13
 *  HSMS - High-speed SECS message service (SEMI-E37)
14
 *  SECS - SEMI equipment communications standard (SEMI-E5)
15
 *
16
 *  TCP based protocol for semiconductor factory automation
17
 *  defined by SEMI (http://www.semi.org)
18
 *
19
 *  Usual TCP port: 5000
20
 */
21
22
#include <config.h>
23
24
#include <epan/packet.h>
25
#include <epan/prefs.h>
26
#include "packet-tcp.h"
27
#include <epan/expert.h>
28
29
0
#define PTYPE_SECS      0
30
31
0
#define STYPE_SECS_DATA         0
32
0
#define STYPE_SELECT_REQ        1
33
0
#define STYPE_SELECT_RSP        2
34
0
#define STYPE_DESELECT_REQ      3
35
0
#define STYPE_DESELECT_RSP      4
36
0
#define STYPE_LINKTEST_REQ      5
37
0
#define STYPE_LINKTEST_RSP      6
38
0
#define STYPE_REJECT_REQ        7
39
0
#define STYPE_SEPARATE_REQ      9
40
41
#define FORMAT_CODE_LIST    000
42
0
#define FORMAT_CODE_BINARY  010
43
0
#define FORMAT_CODE_BOOLEAN 011
44
0
#define FORMAT_CODE_ASCII   020
45
#define FORMAT_CODE_JIS8    021
46
#define FORMAT_CODE_2BYTE   022
47
0
#define FORMAT_CODE_I8      030
48
0
#define FORMAT_CODE_I1      031
49
0
#define FORMAT_CODE_I2      032
50
0
#define FORMAT_CODE_I4      034
51
0
#define FORMAT_CODE_F8      040
52
0
#define FORMAT_CODE_F4      044
53
0
#define FORMAT_CODE_U8      050
54
0
#define FORMAT_CODE_U1      051
55
0
#define FORMAT_CODE_U2      052
56
0
#define FORMAT_CODE_U4      054
57
58
/* Prototypes */
59
void proto_reg_handoff_hsms(void);
60
void proto_register_hsms(void);
61
62
static dissector_handle_t hsms_handle;
63
64
/* Initialize the protocol and registered fields */
65
static int proto_hsms;
66
67
static int hf_hsms_packet_length;
68
static int hf_hsms_header_sessionid;
69
static int hf_hsms_header_statusbyte2;
70
static int hf_hsms_header_wbit;
71
static int hf_hsms_header_stream;
72
static int hf_hsms_header_statusbyte3;
73
static int hf_hsms_header_function;
74
static int hf_hsms_header_ptype;
75
static int hf_hsms_header_stype;
76
static int hf_hsms_header_system;
77
static int hf_hsms_data_item_format;
78
static int hf_hsms_data_item_length_bytes;
79
static int hf_hsms_data_item_length;
80
static int hf_hsms_data_item_value_binary;
81
static int hf_hsms_data_item_value_boolean;
82
static int hf_hsms_data_item_value_string;
83
static int hf_hsms_data_item_value_i8;
84
static int hf_hsms_data_item_value_i1;
85
static int hf_hsms_data_item_value_i2;
86
static int hf_hsms_data_item_value_i4;
87
static int hf_hsms_data_item_value_f8;
88
static int hf_hsms_data_item_value_f4;
89
static int hf_hsms_data_item_value_u8;
90
static int hf_hsms_data_item_value_u1;
91
static int hf_hsms_data_item_value_u2;
92
static int hf_hsms_data_item_value_u4;
93
94
static expert_field ei_hsms_ptype;
95
96
static wmem_map_t *value_lengths;
97
98
/*
99
 *  Presentation type (ptype)
100
 *
101
 *  0        =>  SECS-II Encoding
102
 *  1-127    =>  Reserved for subsidiary standards
103
 *  128-255  =>  Reserved, not used
104
 */
105
static const value_string ptype_names[] = {
106
    { PTYPE_SECS, "SECS" },
107
    { 0, NULL }
108
};
109
110
/*
111
 *  Session type (stype)
112
 *
113
 *  0        =>  SECS-II data message
114
 *  1        =>  Select request
115
 *  2        =>  Select response
116
 *  3        =>  Deselect request
117
 *  4        =>  Deselect response
118
 *  5        =>  Link test request
119
 *  6        =>  Link test response
120
 *  7        =>  Packet reject request
121
 *  8        =>  Reserved, not used
122
 *  9        =>  Separate request
123
 *  10       =>  Reserved, not used
124
 *  11-127   =>  Reserved for subsidiary standards
125
 *  128-255  =>  Reserved, not used
126
 */
127
static const value_string stype_names[] = {
128
    { STYPE_SECS_DATA, "Data message" },
129
    { STYPE_SELECT_REQ, "Select.req" },
130
    { STYPE_SELECT_RSP, "Select.rsp" },
131
    { STYPE_DESELECT_REQ, "Deselect.req" },
132
    { STYPE_DESELECT_RSP, "Deselect.rsp" },
133
    { STYPE_LINKTEST_REQ, "Linktest.req" },
134
    { STYPE_LINKTEST_RSP, "Linktest.rsp" },
135
    { STYPE_REJECT_REQ, "Reject.req" },
136
    { STYPE_SEPARATE_REQ, "Separate.req" },
137
    { 0, NULL }
138
};
139
140
static const value_string item_format_names[] = {
141
    { FORMAT_CODE_LIST, "List" },
142
    { FORMAT_CODE_BINARY, "Binary" },
143
    { FORMAT_CODE_BOOLEAN, "Boolean" },
144
    { FORMAT_CODE_ASCII, "ASCII" },
145
    { FORMAT_CODE_JIS8, "JIS-8" },
146
    { FORMAT_CODE_2BYTE, "2-Byte Char" },
147
    { FORMAT_CODE_I8, "I8" },
148
    { FORMAT_CODE_I1, "I1" },
149
    { FORMAT_CODE_I2, "I2" },
150
    { FORMAT_CODE_I4, "I4" },
151
    { FORMAT_CODE_F8, "F8" },
152
    { FORMAT_CODE_F4, "F4" },
153
    { FORMAT_CODE_U8, "U8" },
154
    { FORMAT_CODE_U1, "U1" },
155
    { FORMAT_CODE_U2, "U2" },
156
    { FORMAT_CODE_U4, "U4" },
157
    { 0, NULL }
158
};
159
160
/* Global sample port preference - real port preferences should generally
161
 * default to 0 unless there is an IANA-registered (or equivalent) port for your
162
 * protocol. */
163
#define HSMS_TCP_PORT 0
164
165
/* Initialize the subtree pointers */
166
static int ett_hsms;
167
static int ett_hsms_header;
168
static int ett_hsms_data;
169
static int ett_hsms_data_item;
170
171
/* A sample #define of the minimum length (in bytes) of the protocol data.
172
 * If data is received with fewer than this many bytes it is rejected by
173
 * the current dissector. */
174
0
#define HSMS_MIN_LENGTH 14
175
176
static int
177
// NOLINTNEXTLINE(misc-no-recursion)
178
dissect_secs_variable(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data, int *offset)
179
0
{
180
0
    proto_item *hdr_stream_item;
181
0
    proto_tree *hsms_data_item_tree, *hsms_data_item_header_tree;
182
183
0
    proto_item *hdr_item = NULL;
184
185
0
    unsigned item_format_code = -1;
186
0
    unsigned length_bytes = -1;
187
0
    unsigned length = 0;
188
189
0
    unsigned *value_length = NULL;
190
191
0
    int len = 0;
192
0
    int itemLength = 0;
193
194
    /* extract item format code and number of length bytes from byte #1 */
195
0
    item_format_code = (tvb_get_uint8(tvb, *offset) & 0xFC) >> 2;
196
0
    length_bytes = (tvb_get_uint8(tvb, *offset) & 0x3);
197
198
    /* extract item length in bytes */
199
0
    switch (length_bytes)
200
0
    {
201
0
    case 3:
202
0
        length = tvb_get_ntoh24(tvb, *offset + 1);
203
0
        break;
204
0
    case 2:
205
0
        length = tvb_get_ntohs(tvb, *offset + 1);
206
0
        break;
207
0
    case 1:
208
0
        length = tvb_get_uint8(tvb, *offset + 1);
209
0
        break;
210
0
    default:
211
0
        return -1;
212
0
    }
213
214
    /* list has no item length and length is alreaty the count of items */
215
0
    if (item_format_code != 0)
216
0
    {
217
0
        value_length = (unsigned*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
218
219
        /* length must be dividable by item length, because it must be a multiple of items */
220
0
        if (length % GPOINTER_TO_UINT(value_length) != 0)
221
0
            return -1;
222
223
        /* shorten length to actual count of items */
224
0
        length = length / GPOINTER_TO_UINT(value_length);
225
0
    }
226
227
    /* add the item tree to the parent tree */
228
0
    hsms_data_item_tree = proto_tree_add_subtree_format(tree, tvb, *offset, -1, ett_hsms_data_item, &hdr_item, "%s (%d items)", val_to_str(item_format_code, item_format_names, "Unknown (%02o)"), length);
229
230
    /* add the formatcode/length bytes to the item tree */
231
0
    hsms_data_item_header_tree = proto_tree_add_subtree_format(hsms_data_item_tree, tvb, *offset, 1, ett_hsms_header, &hdr_stream_item, "Data format: %s, Length bytes: %d", val_to_str(item_format_code, item_format_names, "Unknown (%02o)"), length_bytes);
232
0
    proto_tree_add_item(hsms_data_item_header_tree, hf_hsms_data_item_format, tvb, *offset, 1, ENC_BIG_ENDIAN);
233
0
    proto_tree_add_item(hsms_data_item_header_tree, hf_hsms_data_item_length_bytes, tvb, *offset, 1, ENC_BIG_ENDIAN);
234
0
    *offset += 1;
235
236
    /* add the length to the item tree */
237
0
    len = length_bytes;
238
0
    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_length, tvb, *offset, len, ENC_BIG_ENDIAN);
239
0
    *offset += len;
240
241
    /* add the actual item to the item tree */
242
0
    switch(item_format_code)
243
0
    {
244
0
    case FORMAT_CODE_BINARY:
245
        /* add binary value as one to item list */
246
0
        value_length = (unsigned*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
247
248
0
        len = GPOINTER_TO_UINT(value_length) * length;
249
0
        proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_binary, tvb, *offset, len, ENC_NA);
250
0
        itemLength = len;
251
0
        *offset += len;
252
0
        break;
253
0
    case FORMAT_CODE_ASCII:
254
        /* add ascii value as one to item list */
255
0
        value_length = (unsigned*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
256
257
0
        len = GPOINTER_TO_UINT(value_length) * length;
258
0
        proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_string, tvb, *offset, len, ENC_ASCII);
259
0
        itemLength = len;
260
0
        *offset += len;
261
0
        break;
262
0
    default:
263
        /* walk through the items */
264
0
        for(unsigned int counter=0; counter<length; counter++)
265
0
        {
266
0
            if (item_format_code == 0)
267
0
            {
268
                /* add sub items for list element to item tree */
269
0
                increment_dissection_depth(pinfo);
270
0
                int subItemLength = dissect_secs_variable(tvb, pinfo, hsms_data_item_tree, data, offset);
271
0
                decrement_dissection_depth(pinfo);
272
273
                /* check for parsing error in sub list */
274
0
                if (subItemLength == -1)
275
0
                {
276
0
                    return -1;
277
0
                }
278
279
0
                itemLength += subItemLength;
280
0
            }
281
0
            else
282
0
            {
283
                /* add single item of type item tree */
284
0
                value_length = (unsigned*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
285
286
0
                len = GPOINTER_TO_UINT(value_length);
287
0
                switch(item_format_code)
288
0
                {
289
0
                case FORMAT_CODE_BOOLEAN:
290
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_boolean, tvb, *offset, len, ENC_BIG_ENDIAN);
291
0
                    break;
292
0
                case FORMAT_CODE_I8:
293
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i8, tvb, *offset, len, ENC_BIG_ENDIAN);
294
0
                    break;
295
0
                case FORMAT_CODE_I1:
296
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i1, tvb, *offset, len, ENC_BIG_ENDIAN);
297
0
                    break;
298
0
                case FORMAT_CODE_I2:
299
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i2, tvb, *offset, len, ENC_BIG_ENDIAN);
300
0
                    break;
301
0
                case FORMAT_CODE_I4:
302
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i4, tvb, *offset, len, ENC_BIG_ENDIAN);
303
0
                    break;
304
0
                case FORMAT_CODE_F8:
305
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_f8, tvb, *offset, len, ENC_BIG_ENDIAN);
306
0
                    break;
307
0
                case FORMAT_CODE_F4:
308
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_f4, tvb, *offset, len, ENC_BIG_ENDIAN);
309
0
                    break;
310
0
                case FORMAT_CODE_U8:
311
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u8, tvb, *offset, len, ENC_BIG_ENDIAN);
312
0
                    break;
313
0
                case FORMAT_CODE_U1:
314
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u1, tvb, *offset, len, ENC_BIG_ENDIAN);
315
0
                    break;
316
0
                case FORMAT_CODE_U2:
317
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u2, tvb, *offset, len, ENC_BIG_ENDIAN);
318
0
                    break;
319
0
                case FORMAT_CODE_U4:
320
0
                    proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u4, tvb, *offset, len, ENC_BIG_ENDIAN);
321
0
                    break;
322
0
                default:
323
0
                    return -1;
324
0
                }
325
0
                itemLength += len;
326
0
                *offset += len;
327
0
            }
328
0
        }
329
0
    }
330
331
    /* update length of item tree */
332
0
    proto_item_set_len(hsms_data_item_tree, itemLength + length_bytes + 1);
333
334
0
    return 1 + length_bytes + itemLength;
335
0
}
336
337
static int
338
dissect_secs_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data, int *offset)
339
0
{
340
0
    return dissect_secs_variable(tvb, pinfo, tree, data, offset);
341
0
}
342
343
/* Code to actually dissect the hsms packets */
344
static int
345
dissect_hsms_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
346
0
{
347
0
    proto_item *hdr_item = NULL;
348
349
    /* Set up structures needed to add the protocol subtree and manage it */
350
0
    proto_item *ti;
351
0
    proto_tree *hsms_tree, *hsms_header_tree, *hsms_header_stream_tree;
352
353
    /* Other misc. local variables. */
354
0
    unsigned    offset = 0;
355
356
0
    unsigned sessionId = -1;
357
0
    unsigned byte2 = -1;
358
0
    unsigned byte3 = -1;
359
0
    unsigned pType = -1;
360
0
    unsigned sType = -1;
361
362
    /*** HEURISTICS ***/
363
364
    /* Check that the packet is long enough for it to belong to us. */
365
0
    if (tvb_reported_length(tvb) < HSMS_MIN_LENGTH)
366
0
        return 0;
367
368
    /* Check if first byte describes length) */
369
0
    if ((tvb_get_ntohl(tvb, 0) + 4) != tvb_reported_length(tvb))
370
0
        return 0;
371
372
0
    sessionId = tvb_get_ntohs(tvb, 4);
373
0
    byte2 = tvb_get_uint8(tvb, 6);
374
0
    byte3 = tvb_get_uint8(tvb, 7);
375
0
    pType = tvb_get_uint8(tvb, 8);
376
0
    sType = tvb_get_uint8(tvb, 9);
377
378
    /* sTypes 8, 10 and 128+ are unused, 11-127 might be used for subsidiary standards */
379
0
    if ((sType == 8) || (sType == 10) || (sType > 127))
380
0
        return 0;
381
382
    /* see definition of stype_names for details on the sType values */
383
0
    switch (sType)
384
0
    {
385
0
    case STYPE_SECS_DATA:
386
0
        if (byte2 == 0) // stream must be set
387
0
            return 0;
388
0
        break;
389
0
    case STYPE_SELECT_REQ:
390
0
    case STYPE_DESELECT_REQ:
391
0
    case STYPE_SEPARATE_REQ:
392
0
        if ((byte2 != 0) || (byte3 != 0)) // byte2&3 must be zero
393
0
            return 0;
394
0
        if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
395
0
            return 0;
396
0
        break;
397
0
    case STYPE_SELECT_RSP:
398
0
    case STYPE_DESELECT_RSP:
399
0
        if (byte2 != 0) // byte2 must be zero
400
0
            return 0;
401
0
        if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
402
0
            return 0;
403
0
        break;
404
0
    case STYPE_LINKTEST_REQ:
405
0
    case STYPE_LINKTEST_RSP:
406
0
        if (sessionId != 0xFFFF) // Session ID must be max
407
0
            return 0;
408
0
        if (byte2 != 0) // byte2 must be zero
409
0
            return 0;
410
0
        if (byte3 != 0) // byte3 must be zero
411
0
            return 0;
412
0
        if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
413
0
            return 0;
414
0
        break;
415
0
    case STYPE_REJECT_REQ:
416
0
        if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
417
0
            return 0;
418
0
        break;
419
0
    }
420
421
    /*** COLUMN DATA ***/
422
423
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSMS");
424
425
    /* Clear out stuff in the info column */
426
0
    col_clear(pinfo->cinfo,COL_INFO);
427
428
0
    if (sType == STYPE_SECS_DATA)
429
0
    {
430
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "HSMS SECS Stream/Function S%02dF%02d",
431
0
                byte2 & 0x7F, byte3);
432
0
    }
433
0
    else
434
0
    {
435
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "HSMS Message %s",
436
0
                val_to_str(sType, stype_names, "Unknown (%02d)"));
437
0
    }
438
439
440
    /*** PROTOCOL TREE ***/
441
442
    /* create display subtree for the protocol */
443
0
    ti = proto_tree_add_item(tree, proto_hsms, tvb, 0, -1, ENC_NA);
444
445
0
    hsms_tree = proto_item_add_subtree(ti, ett_hsms);
446
447
    /* packet size = 4 bytes */
448
0
    proto_tree_add_item(hsms_tree, hf_hsms_packet_length, tvb, offset, 4, ENC_BIG_ENDIAN);
449
0
    offset += 4;
450
451
    /* header = 10 bytes */
452
453
    /* see definition of stype_names for details on the sType values */
454
0
    switch (sType)
455
0
    {
456
0
    case STYPE_SECS_DATA:
457
0
        hsms_header_tree = proto_tree_add_subtree_format(hsms_tree, tvb, offset, 10, ett_hsms_header, &hdr_item, "Header (S%02dF%02d)", byte2 & 0x7F, byte3);
458
0
        break;
459
0
    default:
460
0
        hsms_header_tree = proto_tree_add_subtree_format(hsms_tree, tvb, offset, 10, ett_hsms_header, &hdr_item, "Header (%s)", val_to_str(sType, stype_names, "Unknown (%02d)"));
461
0
        break;
462
0
    }
463
464
    /* session id = 2 bytes */
465
0
    proto_tree_add_item(hsms_header_tree, hf_hsms_header_sessionid, tvb, offset, 2, ENC_BIG_ENDIAN);
466
0
    offset += 2;
467
468
    /* see definition of stype_names for details on the sType values */
469
0
    switch (sType)
470
0
    {
471
0
    case STYPE_SECS_DATA:
472
        /* wbit=1bit + stream=7bits = 1 byte */
473
0
        hsms_header_stream_tree = proto_tree_add_subtree_format(hsms_header_tree, tvb, offset, 1, ett_hsms_header, &hdr_item, "Stream %d, Response requested: %s", byte2 & 0x7F, ((byte2 & 0x80) > 0) ? "Yes" : "No");
474
0
        proto_tree_add_item(hsms_header_stream_tree, hf_hsms_header_wbit, tvb, offset, 1, ENC_BIG_ENDIAN);
475
0
        proto_tree_add_item(hsms_header_stream_tree, hf_hsms_header_stream, tvb, offset, 1, ENC_BIG_ENDIAN);
476
0
        offset += 1;
477
478
        /* function = 1 byte */
479
0
        proto_tree_add_item(hsms_header_tree, hf_hsms_header_function, tvb, offset, 1, ENC_BIG_ENDIAN);
480
0
        offset += 1;
481
0
        break;
482
0
    default:
483
        /* status byte 2 = 1 byte */
484
0
        proto_tree_add_item(hsms_header_tree, hf_hsms_header_statusbyte2, tvb, offset, 1, ENC_BIG_ENDIAN);
485
0
        offset += 1;
486
        /* status byte 3 = 1 byte */
487
0
        proto_tree_add_item(hsms_header_tree, hf_hsms_header_statusbyte3, tvb, offset, 1, ENC_BIG_ENDIAN);
488
0
        offset += 1;
489
0
        break;
490
0
    }
491
492
    /* ptype = 1 byte */
493
0
    ti = proto_tree_add_item(hsms_header_tree, hf_hsms_header_ptype, tvb, offset, 1, ENC_BIG_ENDIAN);
494
0
    offset += 1;
495
496
0
    if (pType != 0)
497
0
        expert_add_info(pinfo, ti, &ei_hsms_ptype);
498
499
    /* stype = 1 byte */
500
0
    proto_tree_add_item(hsms_header_tree, hf_hsms_header_stype, tvb, offset, 1, ENC_BIG_ENDIAN);
501
0
    offset += 1;
502
503
    /* system = 4 bytes */
504
0
    proto_tree_add_item(hsms_header_tree, hf_hsms_header_system, tvb, offset, 4, ENC_BIG_ENDIAN);
505
0
    offset += 4;
506
507
    /* decode secs data if available */
508
0
    if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH)
509
0
    {
510
0
        if (pType == PTYPE_SECS)
511
0
            dissect_secs_message(tvb, pinfo, hsms_tree, data, &offset);
512
0
    }
513
0
    return offset;
514
0
}
515
516
/* determine PDU length of protocol foo */
517
static unsigned
518
get_hsms_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
519
0
{
520
    /* first four bytes are length information */
521
0
    return (unsigned)tvb_get_ntohl(tvb, offset) + 4;
522
0
}
523
524
/* The main dissecting routine */
525
static int
526
dissect_hsms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
527
0
{
528
0
    tcp_dissect_pdus(tvb, pinfo, tree, true, 4,
529
0
                     get_hsms_message_len, dissect_hsms_message, data);
530
0
    return tvb_captured_length(tvb);
531
0
}
532
533
static void
534
hsms_init(void)
535
14
{
536
14
    value_lengths = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
537
538
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_LIST), GINT_TO_POINTER(0));
539
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_BINARY), GINT_TO_POINTER(1));
540
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_BOOLEAN), GINT_TO_POINTER(1));
541
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_ASCII), GINT_TO_POINTER(1));
542
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_JIS8), GINT_TO_POINTER(2));
543
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_2BYTE), GINT_TO_POINTER(2));
544
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I8), GINT_TO_POINTER(8));
545
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I1), GINT_TO_POINTER(1));
546
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I2), GINT_TO_POINTER(2));
547
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I4), GINT_TO_POINTER(4));
548
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_F8), GINT_TO_POINTER(8));
549
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_F4), GINT_TO_POINTER(4));
550
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U8), GINT_TO_POINTER(8));
551
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U1), GINT_TO_POINTER(1));
552
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U2), GINT_TO_POINTER(2));
553
14
    wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U4), GINT_TO_POINTER(4));
554
14
}
555
556
void
557
proto_register_hsms(void)
558
14
{
559
14
    expert_module_t* expert_hsms;
560
561
14
    static hf_register_info hf[] = {
562
14
        { &hf_hsms_packet_length,
563
14
            { "Packet length", "hsms.length",
564
14
            FT_UINT32, BASE_DEC,
565
14
            NULL, 0x0,
566
14
            NULL, HFILL }
567
14
        },
568
14
        { &hf_hsms_header_sessionid,
569
14
            { "Session ID", "hsms.header.sessionid",
570
14
            FT_UINT16, BASE_DEC,
571
14
            NULL, 0x0,
572
14
            NULL, HFILL }
573
14
        },
574
14
        { &hf_hsms_header_statusbyte2,
575
14
            { "Status byte 2", "hsms.header.statusbyte2",
576
14
            FT_UINT8, BASE_DEC,
577
14
            NULL, 0x0,
578
14
            NULL, HFILL }
579
14
        },
580
14
        { &hf_hsms_header_wbit,
581
14
            { "W-bit (Response required)", "hsms.header.wbit",
582
14
            FT_BOOLEAN, 8,
583
14
            NULL, 0x80,
584
14
            NULL, HFILL }
585
14
        },
586
14
        { &hf_hsms_header_stream,
587
14
            { "Stream", "hsms.header.stream",
588
14
            FT_UINT8, BASE_DEC,
589
14
            NULL, 0x7F,
590
14
            NULL, HFILL }
591
14
        },
592
14
        { &hf_hsms_header_statusbyte3,
593
14
            { "Status byte 3", "hsms.header.statusbyte3",
594
14
            FT_UINT8, BASE_DEC,
595
14
            NULL, 0x0,
596
14
            NULL, HFILL }
597
14
        },
598
14
        { &hf_hsms_header_function,
599
14
            { "Function", "hsms.header.function",
600
14
            FT_UINT8, BASE_DEC,
601
14
            NULL, 0x0,
602
14
            NULL, HFILL }
603
14
        },
604
14
        { &hf_hsms_header_ptype,
605
14
            { "PType (Presentation type)", "hsms.header.ptype",
606
14
            FT_UINT8, BASE_DEC,
607
14
            VALS(ptype_names), 0x0,
608
14
            NULL, HFILL }
609
14
        },
610
14
        { &hf_hsms_header_stype,
611
14
            { "SType (Session type)", "hsms.header.stype",
612
14
            FT_UINT8, BASE_DEC,
613
14
            VALS(stype_names), 0x0,
614
14
            NULL, HFILL }
615
14
        },
616
14
        { &hf_hsms_header_system,
617
14
            { "System Bytes", "hsms.header.system",
618
14
            FT_UINT32, BASE_DEC,
619
14
            NULL, 0x0,
620
14
            NULL, HFILL }
621
14
        },
622
14
        { &hf_hsms_data_item_format,
623
14
            { "Data type", "hsms.data.item.format",
624
14
            FT_UINT8, BASE_OCT,
625
14
            VALS(item_format_names), 0xFC,
626
14
            NULL, HFILL }
627
14
        },
628
14
        { &hf_hsms_data_item_length_bytes,
629
14
            { "Length bytes", "hsms.data.item.length_bytes",
630
14
            FT_UINT8, BASE_OCT,
631
14
            NULL, 0x03,
632
14
            NULL, HFILL }
633
14
        },
634
14
        { &hf_hsms_data_item_length,
635
14
            { "Length", "hsms.data.item.length",
636
14
            FT_UINT32, BASE_DEC,
637
14
            NULL, 0x00,
638
14
            NULL, HFILL }
639
14
        },
640
14
        { &hf_hsms_data_item_value_binary,
641
14
            { "Value", "hsms.data.item.value.binary",
642
14
            FT_BYTES, SEP_COLON,
643
14
            NULL, 0x00,
644
14
            NULL, HFILL }
645
14
        },
646
14
        { &hf_hsms_data_item_value_boolean,
647
14
            { "Value", "hsms.data.item.value.boolean",
648
14
            FT_BOOLEAN, 8,
649
14
            NULL, 0x01,
650
14
            NULL, HFILL }
651
14
        },
652
14
        { &hf_hsms_data_item_value_string,
653
14
            { "Value", "hsms.data.item.value.string",
654
14
            FT_STRING, BASE_NONE,
655
14
            NULL, 0x00,
656
14
            NULL, HFILL }
657
14
        },
658
14
        { &hf_hsms_data_item_value_i8,
659
14
            { "Value", "hsms.data.item.value.int64",
660
14
            FT_INT64, BASE_DEC,
661
14
            NULL, 0x00,
662
14
            NULL, HFILL }
663
14
        },
664
14
        { &hf_hsms_data_item_value_i1,
665
14
            { "Value", "hsms.data.item.value.int8",
666
14
            FT_INT8, BASE_DEC,
667
14
            NULL, 0x00,
668
14
            NULL, HFILL }
669
14
        },
670
14
        { &hf_hsms_data_item_value_i2,
671
14
            { "Value", "hsms.data.item.value.int16",
672
14
            FT_INT16, BASE_DEC,
673
14
            NULL, 0x00,
674
14
            NULL, HFILL }
675
14
        },
676
14
        { &hf_hsms_data_item_value_i4,
677
14
            { "Value", "hsms.data.item.value.int32",
678
14
            FT_INT32, BASE_DEC,
679
14
            NULL, 0x00,
680
14
            NULL, HFILL }
681
14
        },
682
14
        { &hf_hsms_data_item_value_f8,
683
14
            { "Value", "hsms.data.item.value.double",
684
14
            FT_DOUBLE, BASE_NONE,
685
14
            NULL, 0x00,
686
14
            NULL, HFILL }
687
14
        },
688
14
        { &hf_hsms_data_item_value_f4,
689
14
            { "Value", "hsms.data.item.value.float",
690
14
            FT_FLOAT, BASE_NONE,
691
14
            NULL, 0x00,
692
14
            NULL, HFILL }
693
14
        },
694
14
        { &hf_hsms_data_item_value_u8,
695
14
            { "Value", "hsms.data.item.value.uint64",
696
14
            FT_UINT64, BASE_DEC,
697
14
            NULL, 0x00,
698
14
            NULL, HFILL }
699
14
        },
700
14
        { &hf_hsms_data_item_value_u1,
701
14
            { "Value", "hsms.data.item.value.uint8",
702
14
            FT_UINT8, BASE_DEC,
703
14
            NULL, 0x00,
704
14
            NULL, HFILL }
705
14
        },
706
14
        { &hf_hsms_data_item_value_u2,
707
14
            { "Value", "hsms.data.item.value.uint16",
708
14
            FT_UINT16, BASE_DEC,
709
14
            NULL, 0x00,
710
14
            NULL, HFILL }
711
14
        },
712
14
        { &hf_hsms_data_item_value_u4,
713
14
            { "Value", "hsms.data.item.value.uint32",
714
14
            FT_UINT32, BASE_DEC,
715
14
            NULL, 0x00,
716
14
            NULL, HFILL }
717
14
        },
718
14
    };
719
720
    /* Setup protocol subtree array */
721
14
    static int *ett[] = {
722
14
        &ett_hsms,
723
14
        &ett_hsms_header,
724
14
        &ett_hsms_data,
725
14
        &ett_hsms_data_item
726
14
    };
727
728
14
    static ei_register_info ei[] = {
729
14
        { &ei_hsms_ptype,
730
14
            { "hsms.header.ptype.unknown",
731
14
            PI_RESPONSE_CODE,
732
14
            PI_NOTE,
733
14
            "Unknown presentation type (ptype)",
734
14
            EXPFILL }
735
14
        }
736
14
    };
737
738
    /* Register the protocol name and description */
739
14
    proto_hsms = proto_register_protocol ("High-speed SECS Message Service Protocol", "HSMS", "hsms");
740
741
    /* Required function calls to register the header fields and subtrees */
742
14
    proto_register_field_array(proto_hsms, hf, array_length(hf));
743
14
    proto_register_subtree_array(ett, array_length(ett));
744
745
14
    expert_hsms = expert_register_protocol(proto_hsms);
746
14
    expert_register_field_array(expert_hsms, ei, array_length(ei));
747
748
14
    hsms_handle = register_dissector("hsms", dissect_hsms, proto_hsms);
749
750
14
    hsms_init();
751
14
}
752
753
void
754
proto_reg_handoff_hsms(void)
755
14
{
756
14
    dissector_add_for_decode_as_with_preference("tcp.port", hsms_handle);
757
14
}
758
759
/*
760
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
761
 *
762
 * Local variables:
763
 * c-basic-offset: 4
764
 * tab-width: 8
765
 * indent-tabs-mode: nil
766
 * End:
767
 *
768
 * vi: set shiftwidth=4 tabstop=8 expandtab:
769
 * :indentSize=4:tabSize=8:noTabs=true:
770
 */