Coverage Report

Created: 2026-01-02 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-indigocare-icall.c
Line
Count
Source
1
/* packet-indigocare-icall.c
2
 * Dissector routines for the IndigoCare iCall protocol
3
 * By Erik de Jong <erikdejong@gmail.com>
4
 * Copyright 2016 Erik de Jong
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 <range.h>
16
#include <epan/packet.h>
17
#include <epan/expert.h>
18
#include <wsutil/strtoi.h>
19
20
0
#define INDIGOCARE_ICALL_SOH      0x01
21
0
#define INDIGOCARE_ICALL_STX      0x02
22
0
#define INDIGOCARE_ICALL_ETX      0x03
23
0
#define INDIGOCARE_ICALL_EOT      0x04
24
#define INDIGOCARE_ICALL_ACK      0x06
25
0
#define INDIGOCARE_ICALL_US     0x1F
26
0
#define INDIGOCARE_ICALL_RS     0x1E
27
28
0
#define INDIGOCARE_ICALL_CALL     0x0A
29
30
0
#define INDIGOCARE_ICALL_CALL_ROOM    0x01
31
0
#define INDIGOCARE_ICALL_CALL_TYPE    0x02
32
0
#define INDIGOCARE_ICALL_CALL_ADDITION    0x03
33
0
#define INDIGOCARE_ICALL_CALL_ID    0x04
34
0
#define INDIGOCARE_ICALL_CALL_TASK    0x05
35
0
#define INDIGOCARE_ICALL_CALL_LOCATION    0x06
36
0
#define INDIGOCARE_ICALL_CALL_NAME1   0x07
37
0
#define INDIGOCARE_ICALL_CALL_NAME2   0x08
38
0
#define INDIGOCARE_ICALL_CALL_TYPE_NUMERICAL  0x09
39
0
#define INDIGOCARE_ICALL_CALL_NURSE   0x0A
40
41
void proto_reg_handoff_icall(void);
42
void proto_register_icall(void);
43
44
static dissector_handle_t icall_handle;
45
46
static expert_field ei_icall_unexpected_header;
47
static expert_field ei_icall_unexpected_record;
48
static expert_field ei_icall_unexpected_end;
49
50
static int proto_icall;
51
static int hf_icall_header_type;
52
53
static int hf_icall_call_room_type;
54
static int hf_icall_call_type_type;
55
static int hf_icall_call_addition_type;
56
static int hf_icall_call_id_type;
57
static int hf_icall_call_task_type;
58
static int hf_icall_call_location_type;
59
static int hf_icall_call_name1_type;
60
static int hf_icall_call_name2_type;
61
static int hf_icall_call_numerical_type;
62
static int hf_icall_call_nurse_type;
63
64
static int hf_icall_padding_type;
65
66
static int ett_icall;
67
static int ett_icall_call;
68
static int ett_icall_unknown;
69
70
static const value_string icall_headertypenames[] = {
71
  { INDIGOCARE_ICALL_CALL,    "Call Info" },
72
  { 0, NULL }
73
};
74
75
static int
76
dissect_icall(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_)
77
0
{
78
0
  proto_item *ti;
79
0
  proto_item *header_item;
80
0
  proto_tree *icall_tree;
81
0
  proto_tree *icall_header_tree;
82
0
  int32_t current_offset = 0, header_offset, identifier_start, identifier_offset, data_start, data_offset, ett;
83
0
  int32_t header;
84
0
  int32_t record_identifier;
85
0
  const uint8_t * record_data;
86
87
  /* Starts with SOH */
88
0
  if ( tvb_get_uint8(tvb, 0) != INDIGOCARE_ICALL_SOH )
89
0
    return 0;
90
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "iCall");
91
0
  col_clear(pinfo->cinfo,COL_INFO);
92
0
  ti = proto_tree_add_item(tree, proto_icall, tvb, 0, -1, ENC_NA);
93
0
  icall_tree = proto_item_add_subtree(ti, ett_icall);
94
0
  current_offset++;
95
96
  /* Read header */
97
0
  header_offset = tvb_find_uint8(tvb, current_offset, -1, INDIGOCARE_ICALL_STX);
98
0
  ws_strtoi32((char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset, header_offset - current_offset, ENC_ASCII|ENC_NA), NULL, &header);
99
0
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s:", val_to_str(pinfo->pool, header, icall_headertypenames, "Unknown (%d)"));
100
0
  switch(header) {
101
0
    case INDIGOCARE_ICALL_CALL:
102
0
      ett = ett_icall_call;
103
0
    break;
104
0
    default:
105
0
      proto_tree_add_expert_format(icall_tree, pinfo, &ei_icall_unexpected_header, tvb, current_offset, header_offset -  current_offset, "Unexpected header %d", header);
106
0
      return 0;
107
0
    break;
108
0
  }
109
0
  header_item = proto_tree_add_uint_format(icall_tree, hf_icall_header_type, tvb, current_offset, header_offset - current_offset, header, "%s", val_to_str(pinfo->pool, header, icall_headertypenames, "Unknown (%d)"));
110
0
  icall_header_tree = proto_item_add_subtree(header_item, ett);
111
0
  current_offset = header_offset + 1;
112
113
  /* Read records */
114
0
  while (tvb_get_uint8(tvb, current_offset) != INDIGOCARE_ICALL_ETX) {
115
0
    identifier_start = current_offset;
116
0
    identifier_offset = tvb_find_uint8(tvb, current_offset, -1, INDIGOCARE_ICALL_US);
117
0
    ws_strtoi32((char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset, identifier_offset - current_offset, ENC_ASCII|ENC_NA), NULL, &record_identifier);
118
0
    current_offset = identifier_offset + 1;
119
120
0
    data_start = current_offset;
121
0
    data_offset = tvb_find_uint8(tvb, data_start, -1, INDIGOCARE_ICALL_RS);
122
0
    record_data = tvb_get_string_enc(pinfo->pool, tvb, current_offset, data_offset - data_start, ENC_ASCII|ENC_NA);
123
124
0
    current_offset = data_offset + 1;
125
126
0
    switch (header) {
127
0
      case INDIGOCARE_ICALL_CALL:
128
0
        switch (record_identifier) {
129
0
          case INDIGOCARE_ICALL_CALL_ROOM:
130
0
            proto_tree_add_item_ret_string(icall_header_tree, hf_icall_call_room_type, tvb, data_start, data_offset - data_start, ENC_ASCII|ENC_NA, pinfo->pool, &record_data);
131
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " Room=%s", record_data);
132
0
          break;
133
0
          case INDIGOCARE_ICALL_CALL_TYPE:
134
0
            proto_tree_add_item_ret_string(icall_header_tree, hf_icall_call_type_type, tvb, data_start, data_offset - data_start, ENC_ASCII|ENC_NA, pinfo->pool, &record_data);
135
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " Type=%s", record_data);
136
0
          break;
137
0
          case INDIGOCARE_ICALL_CALL_ADDITION:
138
0
            proto_tree_add_item(icall_header_tree, hf_icall_call_addition_type, tvb, data_start, data_offset - data_start, ENC_ASCII);
139
0
          break;
140
0
          case INDIGOCARE_ICALL_CALL_ID:
141
0
            proto_tree_add_item(icall_header_tree, hf_icall_call_id_type, tvb, data_start, data_offset - data_start, ENC_ASCII);
142
0
          break;
143
0
          case INDIGOCARE_ICALL_CALL_TASK:
144
0
            proto_tree_add_item(icall_header_tree, hf_icall_call_task_type, tvb, data_start, data_offset - data_start, ENC_ASCII);
145
0
          break;
146
0
          case INDIGOCARE_ICALL_CALL_LOCATION:
147
0
            proto_tree_add_item_ret_string(icall_header_tree, hf_icall_call_location_type, tvb, data_start, data_offset - data_start, ENC_ASCII|ENC_NA, pinfo->pool, &record_data);
148
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " Location=%s", record_data);
149
0
          break;
150
0
          case INDIGOCARE_ICALL_CALL_NAME1:
151
0
            proto_tree_add_item_ret_string(icall_header_tree, hf_icall_call_name1_type, tvb, data_start, data_offset - data_start, ENC_ASCII|ENC_NA, pinfo->pool, &record_data);
152
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " Name 1=%s", record_data);
153
0
          break;
154
0
          case INDIGOCARE_ICALL_CALL_NAME2:
155
0
            proto_tree_add_item_ret_string(icall_header_tree, hf_icall_call_name2_type, tvb, data_start, data_offset - data_start, ENC_ASCII|ENC_NA, pinfo->pool, &record_data);
156
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " Name 2=%s", record_data);
157
0
          break;
158
0
          case INDIGOCARE_ICALL_CALL_TYPE_NUMERICAL:
159
0
            proto_tree_add_item(icall_header_tree, hf_icall_call_numerical_type, tvb, data_start, data_offset - data_start, ENC_ASCII);
160
0
          break;
161
0
          case INDIGOCARE_ICALL_CALL_NURSE:
162
0
            proto_tree_add_item(icall_header_tree, hf_icall_call_nurse_type, tvb, data_start, data_offset - data_start, ENC_ASCII);
163
0
          break;
164
0
          default:
165
0
            proto_tree_add_expert_format(icall_header_tree, pinfo, &ei_icall_unexpected_record, tvb, identifier_start, data_offset - identifier_start, "Unexpected record %d with value %s", record_identifier, record_data);
166
0
          break;
167
0
        }
168
0
      break;
169
0
    }
170
0
  }
171
0
  current_offset++;
172
0
  if (tvb_get_uint8(tvb, current_offset) != INDIGOCARE_ICALL_EOT) {
173
    /* Malformed packet terminator */
174
0
    proto_tree_add_expert(icall_header_tree, pinfo, &ei_icall_unexpected_end, tvb, current_offset, 1);
175
0
    return tvb_captured_length(tvb);
176
0
  }
177
0
  current_offset++;
178
0
  if (tvb_captured_length_remaining(tvb, current_offset)) {
179
    /* Padding */
180
0
    proto_tree_add_item(icall_header_tree, hf_icall_padding_type, tvb, current_offset, tvb_captured_length_remaining(tvb, current_offset), ENC_NA);
181
0
  }
182
0
  return tvb_captured_length(tvb);
183
0
}
184
185
void
186
proto_reg_handoff_icall(void)
187
14
{
188
14
  dissector_add_for_decode_as("udp.port", icall_handle);
189
14
  dissector_add_for_decode_as("tcp.port", icall_handle);
190
14
}
191
192
void
193
proto_register_icall(void)
194
14
{
195
14
  static hf_register_info hf[] = {
196
14
  { &hf_icall_header_type,
197
14
    { "Header Type", "icall.header",
198
14
    FT_UINT32, BASE_DEC,
199
14
    VALS(icall_headertypenames), 0x0,
200
14
    NULL, HFILL }
201
14
  },
202
14
  { &hf_icall_call_room_type,
203
14
    { "Room", "icall.call.room",
204
14
    FT_STRING, BASE_NONE,
205
14
    NULL, 0x0,
206
14
    NULL, HFILL }
207
14
  },
208
14
  { &hf_icall_call_type_type,
209
14
    { "Type", "icall.call.type",
210
14
    FT_STRING, BASE_NONE,
211
14
    NULL, 0x0,
212
14
    NULL, HFILL }
213
14
  },
214
14
  { &hf_icall_call_addition_type,
215
14
    { "Addition", "icall.call.addition",
216
14
    FT_STRING, BASE_NONE,
217
14
    NULL, 0x0,
218
14
    NULL, HFILL }
219
14
  },
220
14
  { &hf_icall_call_id_type,
221
14
    { "ID", "icall.call.id",
222
14
    FT_STRING, BASE_NONE,
223
14
    NULL, 0x0,
224
14
    NULL, HFILL }
225
14
  },
226
14
  { &hf_icall_call_task_type,
227
14
    { "Task", "icall.call.task",
228
14
    FT_STRING, BASE_NONE,
229
14
    NULL, 0x0,
230
14
    NULL, HFILL }
231
14
  },
232
14
  { &hf_icall_call_location_type,
233
14
    { "Location", "icall.call.location",
234
14
    FT_STRING, BASE_NONE,
235
14
    NULL, 0x0,
236
14
    NULL, HFILL }
237
14
  },
238
14
  { &hf_icall_call_name1_type,
239
14
    { "Name 1", "icall.call.name1",
240
14
    FT_STRING, BASE_NONE,
241
14
    NULL, 0x0,
242
14
    NULL, HFILL }
243
14
  },
244
14
  { &hf_icall_call_name2_type,
245
14
    { "Name 2", "icall.call.name2",
246
14
    FT_STRING, BASE_NONE,
247
14
    NULL, 0x0,
248
14
    NULL, HFILL }
249
14
  },
250
14
  { &hf_icall_call_numerical_type,
251
14
    { "Type Numerical", "icall.call.type_numerical",
252
14
    FT_STRING, BASE_NONE,
253
14
    NULL, 0x0,
254
14
    NULL, HFILL }
255
14
  },
256
14
  { &hf_icall_call_nurse_type,
257
14
    { "Nurse", "icall.call.nurse",
258
14
    FT_STRING, BASE_NONE,
259
14
    NULL, 0x0,
260
14
    NULL, HFILL }
261
14
  },
262
14
  { &hf_icall_padding_type,
263
14
    { "Padding", "icall.padding",
264
14
    FT_BYTES, BASE_NONE,
265
14
    NULL, 0x0,
266
14
    NULL, HFILL }
267
14
  }
268
14
  };
269
270
14
  static ei_register_info ei[] = {
271
14
    { &ei_icall_unexpected_header, { "icall.unexpected.header", PI_MALFORMED, PI_WARN, "Unexpected header", EXPFILL }},
272
14
    { &ei_icall_unexpected_record, { "icall.unexpected.record", PI_MALFORMED, PI_WARN, "Unexpected record", EXPFILL }},
273
14
    { &ei_icall_unexpected_end, { "icall.unexpected.end", PI_MALFORMED, PI_WARN, "Unexpected end of packet", EXPFILL }}
274
14
  };
275
276
14
  expert_module_t* expert_icall;
277
278
  /* Setup protocol subtree array */
279
14
  static int *ett[] = {
280
14
    &ett_icall,
281
14
    &ett_icall_call,
282
14
    &ett_icall_unknown
283
14
  };
284
285
14
  proto_icall = proto_register_protocol (
286
14
    "iCall Communication Protocol", /* name */
287
14
    "iCall",      /* short name */
288
14
    "icall"       /* abbrev */
289
14
  );
290
291
14
  proto_register_field_array(proto_icall, hf, array_length(hf));
292
14
  proto_register_subtree_array(ett, array_length(ett));
293
294
14
  expert_icall = expert_register_protocol(proto_icall);
295
14
  expert_register_field_array(expert_icall, ei, array_length(ei));
296
297
14
  icall_handle = register_dissector("icall", dissect_icall, proto_icall);
298
14
}
299
300
/*
301
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
302
 *
303
 * Local variables:
304
 * c-basic-offset: 8
305
 * tab-width: 8
306
 * indent-tabs-mode: t
307
 * End:
308
 *
309
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
310
 * :indentSize=8:tabSize=8:noTabs=false:
311
 */