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
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
17 #include <epan/expert.h>
18 #include <wsutil/strtoi.h>
20 #define INDIGOCARE_ICALL_SOH 0x01
21 #define INDIGOCARE_ICALL_STX 0x02
22 #define INDIGOCARE_ICALL_ETX 0x03
23 #define INDIGOCARE_ICALL_EOT 0x04
24 #define INDIGOCARE_ICALL_ACK 0x06
25 #define INDIGOCARE_ICALL_US 0x1F
26 #define INDIGOCARE_ICALL_RS 0x1E
28 #define INDIGOCARE_ICALL_CALL 0x0A
30 #define INDIGOCARE_ICALL_CALL_ROOM 0x01
31 #define INDIGOCARE_ICALL_CALL_TYPE 0x02
32 #define INDIGOCARE_ICALL_CALL_ADDITION 0x03
33 #define INDIGOCARE_ICALL_CALL_ID 0x04
34 #define INDIGOCARE_ICALL_CALL_TASK 0x05
35 #define INDIGOCARE_ICALL_CALL_LOCATION 0x06
36 #define INDIGOCARE_ICALL_CALL_NAME1 0x07
37 #define INDIGOCARE_ICALL_CALL_NAME2 0x08
38 #define INDIGOCARE_ICALL_CALL_TYPE_NUMERICAL 0x09
39 #define INDIGOCARE_ICALL_CALL_NURSE 0x0A
41 void proto_reg_handoff_icall(void);
42 void proto_register_icall(void);
44 static dissector_handle_t icall_handle
;
46 static expert_field ei_icall_unexpected_header
;
47 static expert_field ei_icall_unexpected_record
;
48 static expert_field ei_icall_unexpected_end
;
50 static int proto_icall
;
51 static int hf_icall_header_type
;
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
;
64 static int hf_icall_padding_type
;
67 static int ett_icall_call
;
68 static int ett_icall_unknown
;
70 static const value_string icall_headertypenames
[] = {
71 { INDIGOCARE_ICALL_CALL
, "Call Info" },
76 dissect_icall(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, void *data _U_
)
79 proto_item
*header_item
;
80 proto_tree
*icall_tree
;
81 proto_tree
*icall_header_tree
;
82 int32_t current_offset
= 0, header_offset
, identifier_start
, identifier_offset
, data_start
, data_offset
, ett
;
84 int32_t record_identifier
;
85 const uint8_t * record_data
;
88 if ( tvb_get_uint8(tvb
, 0) != INDIGOCARE_ICALL_SOH
)
90 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "iCall");
91 col_clear(pinfo
->cinfo
,COL_INFO
);
92 ti
= proto_tree_add_item(tree
, proto_icall
, tvb
, 0, -1, ENC_NA
);
93 icall_tree
= proto_item_add_subtree(ti
, ett_icall
);
97 header_offset
= tvb_find_uint8(tvb
, current_offset
, -1, INDIGOCARE_ICALL_STX
);
98 ws_strtoi32(tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
, header_offset
- current_offset
, ENC_ASCII
|ENC_NA
), NULL
, &header
);
99 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s:", val_to_str(header
, icall_headertypenames
, "Unknown (%d)"));
101 case INDIGOCARE_ICALL_CALL
:
102 ett
= ett_icall_call
;
105 proto_tree_add_expert_format(icall_tree
, pinfo
, &ei_icall_unexpected_header
, tvb
, current_offset
, header_offset
- current_offset
, "Unexpected header %d", header
);
109 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(header
, icall_headertypenames
, "Unknown (%d)"));
110 icall_header_tree
= proto_item_add_subtree(header_item
, ett
);
111 current_offset
= header_offset
+ 1;
114 while (tvb_get_uint8(tvb
, current_offset
) != INDIGOCARE_ICALL_ETX
) {
115 identifier_start
= current_offset
;
116 identifier_offset
= tvb_find_uint8(tvb
, current_offset
, -1, INDIGOCARE_ICALL_US
);
117 ws_strtoi32(tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
, identifier_offset
- current_offset
, ENC_ASCII
|ENC_NA
), NULL
, &record_identifier
);
118 current_offset
= identifier_offset
+ 1;
120 data_start
= current_offset
;
121 data_offset
= tvb_find_uint8(tvb
, data_start
, -1, INDIGOCARE_ICALL_RS
);
122 record_data
= tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
, data_offset
- data_start
, ENC_ASCII
|ENC_NA
);
124 current_offset
= data_offset
+ 1;
127 case INDIGOCARE_ICALL_CALL
:
128 switch (record_identifier
) {
129 case INDIGOCARE_ICALL_CALL_ROOM
:
130 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 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Room=%s", record_data
);
133 case INDIGOCARE_ICALL_CALL_TYPE
:
134 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 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Type=%s", record_data
);
137 case INDIGOCARE_ICALL_CALL_ADDITION
:
138 proto_tree_add_item(icall_header_tree
, hf_icall_call_addition_type
, tvb
, data_start
, data_offset
- data_start
, ENC_ASCII
);
140 case INDIGOCARE_ICALL_CALL_ID
:
141 proto_tree_add_item(icall_header_tree
, hf_icall_call_id_type
, tvb
, data_start
, data_offset
- data_start
, ENC_ASCII
);
143 case INDIGOCARE_ICALL_CALL_TASK
:
144 proto_tree_add_item(icall_header_tree
, hf_icall_call_task_type
, tvb
, data_start
, data_offset
- data_start
, ENC_ASCII
);
146 case INDIGOCARE_ICALL_CALL_LOCATION
:
147 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 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Location=%s", record_data
);
150 case INDIGOCARE_ICALL_CALL_NAME1
:
151 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 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Name 1=%s", record_data
);
154 case INDIGOCARE_ICALL_CALL_NAME2
:
155 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 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Name 2=%s", record_data
);
158 case INDIGOCARE_ICALL_CALL_TYPE_NUMERICAL
:
159 proto_tree_add_item(icall_header_tree
, hf_icall_call_numerical_type
, tvb
, data_start
, data_offset
- data_start
, ENC_ASCII
);
161 case INDIGOCARE_ICALL_CALL_NURSE
:
162 proto_tree_add_item(icall_header_tree
, hf_icall_call_nurse_type
, tvb
, data_start
, data_offset
- data_start
, ENC_ASCII
);
165 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
);
172 if (tvb_get_uint8(tvb
, current_offset
) != INDIGOCARE_ICALL_EOT
) {
173 /* Malformed packet terminator */
174 proto_tree_add_expert(icall_header_tree
, pinfo
, &ei_icall_unexpected_end
, tvb
, current_offset
, 1);
175 return tvb_captured_length(tvb
);
178 if (tvb_captured_length_remaining(tvb
, current_offset
)) {
180 proto_tree_add_item(icall_header_tree
, hf_icall_padding_type
, tvb
, current_offset
, tvb_captured_length_remaining(tvb
, current_offset
), ENC_NA
);
182 return tvb_captured_length(tvb
);
186 proto_reg_handoff_icall(void)
188 dissector_add_for_decode_as("udp.port", icall_handle
);
189 dissector_add_for_decode_as("tcp.port", icall_handle
);
193 proto_register_icall(void)
195 static hf_register_info hf
[] = {
196 { &hf_icall_header_type
,
197 { "Header Type", "icall.header",
199 VALS(icall_headertypenames
), 0x0,
202 { &hf_icall_call_room_type
,
203 { "Room", "icall.call.room",
204 FT_STRING
, BASE_NONE
,
208 { &hf_icall_call_type_type
,
209 { "Type", "icall.call.type",
210 FT_STRING
, BASE_NONE
,
214 { &hf_icall_call_addition_type
,
215 { "Addition", "icall.call.addition",
216 FT_STRING
, BASE_NONE
,
220 { &hf_icall_call_id_type
,
221 { "ID", "icall.call.id",
222 FT_STRING
, BASE_NONE
,
226 { &hf_icall_call_task_type
,
227 { "Task", "icall.call.task",
228 FT_STRING
, BASE_NONE
,
232 { &hf_icall_call_location_type
,
233 { "Location", "icall.call.location",
234 FT_STRING
, BASE_NONE
,
238 { &hf_icall_call_name1_type
,
239 { "Name 1", "icall.call.name1",
240 FT_STRING
, BASE_NONE
,
244 { &hf_icall_call_name2_type
,
245 { "Name 2", "icall.call.name2",
246 FT_STRING
, BASE_NONE
,
250 { &hf_icall_call_numerical_type
,
251 { "Type Numerical", "icall.call.type_numerical",
252 FT_STRING
, BASE_NONE
,
256 { &hf_icall_call_nurse_type
,
257 { "Nurse", "icall.call.nurse",
258 FT_STRING
, BASE_NONE
,
262 { &hf_icall_padding_type
,
263 { "Padding", "icall.padding",
270 static ei_register_info ei
[] = {
271 { &ei_icall_unexpected_header
, { "icall.unexpected.header", PI_MALFORMED
, PI_WARN
, "Unexpected header", EXPFILL
}},
272 { &ei_icall_unexpected_record
, { "icall.unexpected.record", PI_MALFORMED
, PI_WARN
, "Unexpected record", EXPFILL
}},
273 { &ei_icall_unexpected_end
, { "icall.unexpected.end", PI_MALFORMED
, PI_WARN
, "Unexpected end of packet", EXPFILL
}}
276 expert_module_t
* expert_icall
;
278 /* Setup protocol subtree array */
279 static int *ett
[] = {
285 proto_icall
= proto_register_protocol (
286 "iCall Communication Protocol", /* name */
287 "iCall", /* short name */
291 proto_register_field_array(proto_icall
, hf
, array_length(hf
));
292 proto_register_subtree_array(ett
, array_length(ett
));
294 expert_icall
= expert_register_protocol(proto_icall
);
295 expert_register_field_array(expert_icall
, ei
, array_length(ei
));
297 icall_handle
= register_dissector("icall", dissect_icall
, proto_icall
);
301 * Editor modelines - https://www.wireshark.org/tools/modelines.html
306 * indent-tabs-mode: t
309 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
310 * :indentSize=8:tabSize=8:noTabs=false: