Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-uts.c
blobbd8f5301a238d31978c1cf183f2fecc24bbf5a4b
1 /* packet-uts.c
2 * Routines for UTS WAN protocol dissection
3 * Copyright 2007, Fulko Hew, SITA INC Canada, Inc.
5 * Copied from packet-ipars.c
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 /* Use tabstops = 4 */
16 #include "config.h"
18 #include <epan/packet.h>
19 #include <wiretap/wtap.h>
20 #include <wsutil/str_util.h>
22 #define SOH (0x01)
23 #define STX (0x02)
24 #define ETX (0x03)
25 #define EOT (0x04)
26 #define ENQ (0x05)
27 #define BEL (0x07)
28 #define NAK (0x15)
29 #define DLE (0x10)
31 #define GRID (0x20)
32 #define GSID (0x50)
33 #define GDID (0x70)
35 #define MAX_POLL_TYPE_MSG_SIZE (50)
37 void proto_register_uts(void);
39 static int proto_uts;
40 static int ett_uts;
41 static int ett_header_uts;
42 static int ett_trailer_uts;
43 static int hf_rid;
44 static int hf_sid;
45 static int hf_did;
46 static int hf_retxrequest;
47 static int hf_ack;
48 static int hf_replyrequest;
49 static int hf_busy;
50 static int hf_notbusy;
51 static int hf_msgwaiting;
52 static int hf_function;
53 static int hf_data;
55 #define MATCH (1)
56 #define FETCH (2)
58 #define SRC (1)
59 #define DST (2)
61 static int testchar(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, int op, char match, char *storage)
63 char temp;
65 if (tvb_bytes_exist(tvb, offset, 1)) {
66 temp = tvb_get_uint8(tvb, offset) & 0x7f;
67 if (op == FETCH || (op == MATCH && temp == match)) {
68 if (storage != NULL)
69 *storage = temp;
70 return 1;
71 } else {
72 return 0;
74 } else {
75 col_set_str(pinfo->cinfo, COL_INFO, "Unknown Message Format");
76 return 0;
80 static void
81 set_addr(packet_info *pinfo _U_ , int field, char rid, char sid, char did)
83 if (field == SRC) {
84 col_append_fstr(pinfo->cinfo, COL_DEF_SRC, " %2.2X:%2.2X:%2.2X", rid, sid, did);
85 } else {
86 col_append_fstr(pinfo->cinfo, COL_DEF_DST, " %2.2X:%2.2X:%2.2X", rid, sid, did);
90 static int
91 dissect_uts(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree, void* data _U_)
93 proto_tree *uts_tree = NULL;
94 proto_tree *uts_header_tree = NULL;
95 proto_tree *uts_trailer_tree = NULL;
96 proto_item *ti;
97 int length;
98 char rid = 0, sid = 0, did = 0;
99 int offset = 0;
100 int header_length = -1;
101 int ack_start = 0;
102 int busy_start = 0;
103 int notbusy_start = 0;
104 int replyrequest_start = 0;
105 int function_start = 0;
106 int msgwaiting_start = 0;
107 int nak_start = 0;
108 int etx_start = 0;
109 int bcc_start = 0;
110 int stx_start = 0;
111 char function_code;
112 uint8_t *data_ptr;
114 enum { NOTRAFFIC, OTHER } msg_type = OTHER;
116 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UTS");
118 if (testchar(tvb, pinfo, 0, MATCH, EOT, NULL) &&
119 testchar(tvb, pinfo, 1, MATCH, EOT, NULL) &&
120 testchar(tvb, pinfo, 2, MATCH, ETX, NULL)) {
121 msg_type = NOTRAFFIC;
122 col_set_str(pinfo->cinfo, COL_INFO, "No Traffic");
123 } else {
124 if (testchar(tvb, pinfo, 0, MATCH, SOH, NULL) &&
125 testchar(tvb, pinfo, 1, FETCH, 0, (char *)&rid) &&
126 testchar(tvb, pinfo, 2, FETCH, 0, (char *)&sid) &&
127 testchar(tvb, pinfo, 3, FETCH, 0, (char *)&did)) {
128 offset = 4;
129 if (testchar(tvb, pinfo, offset, MATCH, ETX, NULL)) {
130 col_set_str(pinfo->cinfo, COL_INFO, "General Poll");
131 set_addr(pinfo, DST, rid, sid, did);
132 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
133 testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
134 testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
135 ack_start = offset;
136 if (sid == GSID && did == GDID) {
137 col_set_str(pinfo->cinfo, COL_INFO, "General Poll + ACK");
138 set_addr(pinfo, DST, rid, sid, did);
139 } else if (sid != GSID && did == GDID) {
140 col_set_str(pinfo->cinfo, COL_INFO, "Specific Poll + ACK");
141 set_addr(pinfo, DST, rid, sid, did);
142 } else if (sid != GSID && did != GDID) {
143 col_set_str(pinfo->cinfo, COL_INFO, "No Traffic + ACK");
144 set_addr(pinfo, SRC, rid, sid, did);
145 } else {
146 col_set_str(pinfo->cinfo, COL_INFO, "Unknown Message Format");
147 if ((pinfo->pseudo_header->sita.sita_flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
148 set_addr(pinfo, DST, rid, sid, did); /* if the ACN sent it, the address is of the destination... the terminal */
149 } else {
150 set_addr(pinfo, SRC, rid, sid, did); /* if the ACN received it, the address if of the source... the terminal */
153 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
154 testchar(tvb, pinfo, offset+1, MATCH, NAK, NULL) &&
155 testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL) &&
156 sid != GSID && did == GDID) {
157 nak_start = offset;
158 col_set_str(pinfo->cinfo, COL_INFO, "Retransmit Request");
159 set_addr(pinfo, DST, rid, sid, did);
160 } else if (testchar(tvb, pinfo, offset, MATCH, BEL, NULL) &&
161 testchar(tvb, pinfo, offset+1, MATCH, STX, NULL) &&
162 testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
163 header_length = offset+2;
164 msgwaiting_start = offset;
165 col_set_str(pinfo->cinfo, COL_INFO, "Message Waiting");
166 set_addr(pinfo, DST, rid, sid, did);
167 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
168 testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
169 testchar(tvb, pinfo, offset+2, MATCH, STX, NULL)) {
170 ack_start = offset;
171 header_length = offset+3;
172 stx_start = offset+2;
173 col_set_str(pinfo->cinfo, COL_INFO, "Text + ACK");
174 set_addr(pinfo, SRC, rid, sid, did);
175 } else if (testchar(tvb, pinfo, offset, MATCH, STX, NULL)) {
176 header_length = offset+1;
177 stx_start = offset;
178 col_set_str(pinfo->cinfo, COL_INFO, "Text");
179 if ((pinfo->pseudo_header->sita.sita_flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
180 set_addr(pinfo, DST, rid, sid, did); /* if the ACN sent it, the address is of the destination... the terminal */
181 } else {
182 set_addr(pinfo, SRC, rid, sid, did); /* if the ACN received it, the address if of the source... the terminal */
184 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
185 testchar(tvb, pinfo, offset+1, MATCH, ENQ, NULL) &&
186 testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
187 replyrequest_start = offset;
188 col_set_str(pinfo->cinfo, COL_INFO, "Reply Request");
189 set_addr(pinfo, SRC, rid, sid, did);
190 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
191 testchar(tvb, pinfo, offset+1, MATCH, '?', NULL) &&
192 testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
193 busy_start = offset;
194 col_set_str(pinfo->cinfo, COL_INFO, "Busy");
195 set_addr(pinfo, SRC, rid, sid, did);
196 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
197 testchar(tvb, pinfo, offset+1, MATCH, ';', NULL) &&
198 testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
199 notbusy_start = offset;
200 col_set_str(pinfo->cinfo, COL_INFO, "Not Busy");
201 set_addr(pinfo, SRC, rid, sid, did);
202 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
203 testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
204 testchar(tvb, pinfo, offset+2, MATCH, DLE, NULL) &&
205 testchar(tvb, pinfo, offset+3, MATCH, ';', NULL) &&
206 testchar(tvb, pinfo, offset+4, MATCH, ETX, NULL)) {
207 notbusy_start = offset+2;
208 ack_start = offset;
209 col_set_str(pinfo->cinfo, COL_INFO, "Not Busy + ACK");
210 set_addr(pinfo, SRC, rid, sid, did);
211 } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
212 testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
213 testchar(tvb, pinfo, offset+2, FETCH, 0, &function_code) &&
214 testchar(tvb, pinfo, offset+3, MATCH, ETX, NULL)) {
215 ack_start = offset;
216 function_start = offset + 2;
217 col_add_fstr(pinfo->cinfo, COL_INFO, "Function Message '%c' + ACK", function_code);
218 set_addr(pinfo, SRC, rid, sid, did);
219 } else if (testchar(tvb, pinfo, offset, FETCH, 0, &function_code) &&
220 testchar(tvb, pinfo, offset+1, MATCH, ETX, NULL)) {
221 function_start = offset;
222 col_add_fstr(pinfo->cinfo, COL_INFO, "Function Message '%c'", function_code);
223 set_addr(pinfo, SRC, rid, sid, did);
228 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* now look for the ETX */
229 if ((tvb_get_uint8(tvb, offset) & 0x7f) == ETX) {
230 if (header_length == -1)
231 header_length = offset; /* the header ends at an STX, or if not found, the ETX */
232 etx_start = offset;
233 offset++;
234 break;
236 offset++;
238 if (tvb_reported_length_remaining(tvb, offset)) /* if there is anything left, it could be the BCC and pads */
239 bcc_start = offset;
241 if (tree) {
242 ti = proto_tree_add_protocol_format(tree, proto_uts, tvb, 0, -1, "UTS");
243 uts_tree = proto_item_add_subtree(ti, ett_uts);
245 if (msg_type == NOTRAFFIC) {
246 proto_tree_add_protocol_format(uts_tree, proto_uts, tvb, 0, 2, "No Traffic");
247 proto_tree_add_protocol_format(uts_tree, proto_uts, tvb, 2, -1, "ETX + padding");
248 } else {
249 uts_header_tree = proto_tree_add_subtree(uts_tree, tvb, 0, header_length, ett_header_uts, NULL, "Header");
251 proto_tree_add_protocol_format(uts_header_tree, proto_uts, tvb, 0, 1, "SOH");
253 if (rid == GRID)
254 proto_tree_add_uint_format(uts_header_tree, hf_rid, tvb, 1, 1, rid, "RID (%02X) (General)", rid);
255 else
256 proto_tree_add_uint_format(uts_header_tree, hf_rid, tvb, 1, 1, rid, "RID (%02X)", rid);
258 if (sid == GSID)
259 proto_tree_add_uint_format(uts_header_tree, hf_sid, tvb, 2, 1, sid, "SID (%02X) (General)", sid);
260 else
261 proto_tree_add_uint_format(uts_header_tree, hf_sid, tvb, 2, 1, sid, "SID (%02X)", sid);
263 if (did == GDID)
264 proto_tree_add_uint_format(uts_header_tree, hf_did, tvb, 3, 1, did, "DID (%02X) (General)", did);
265 else
266 proto_tree_add_uint_format(uts_header_tree, hf_did, tvb, 3, 1, did, "DID (%02X)", did);
268 if (nak_start)
269 proto_tree_add_boolean_format(uts_header_tree, hf_retxrequest, tvb, nak_start, 2, 1, "Re-transmit Request");
270 if (ack_start)
271 proto_tree_add_boolean_format(uts_header_tree, hf_ack, tvb, ack_start, 2, 1, "Ack");
273 if (replyrequest_start)
274 proto_tree_add_boolean_format(uts_header_tree, hf_replyrequest, tvb, replyrequest_start, 2, 1, "Reply Request");
275 if (busy_start)
276 proto_tree_add_boolean_format(uts_header_tree, hf_busy, tvb, busy_start, 2, 1, "Busy");
278 if (notbusy_start)
279 proto_tree_add_boolean_format(uts_header_tree, hf_notbusy, tvb, notbusy_start, 2, 1, "Not Busy");
281 if (msgwaiting_start)
282 proto_tree_add_boolean_format(uts_header_tree, hf_msgwaiting, tvb, msgwaiting_start, 1, 1, "Message Waiting");
284 if (function_start)
285 proto_tree_add_uint_format(uts_header_tree, hf_function, tvb, function_start, 1, function_code, "Function '%c'", function_code );
287 if (stx_start) {
288 proto_tree_add_protocol_format(uts_header_tree, proto_uts, tvb, stx_start, 1, "Start of Text");
289 length = tvb_captured_length_remaining(tvb, stx_start+1); /* find out how much message remains */
290 if (etx_start)
291 length = (etx_start - stx_start - 1); /* and the data part is the rest... */
292 /* whatever precedes the ETX if it exists */
293 data_ptr = tvb_get_string_enc(pinfo->pool, tvb, stx_start+1, length, ENC_ASCII); /* copy the string for dissecting */
294 proto_tree_add_string_format(uts_tree, hf_data, tvb, stx_start + 1, length, data_ptr,
295 "Text (%d byte%s)", length, plurality(length, "", "s"));
298 if (etx_start) {
299 uts_trailer_tree = proto_tree_add_subtree(uts_tree, tvb, etx_start, -1, ett_trailer_uts, NULL, "Trailer");
301 if (etx_start)
302 proto_tree_add_protocol_format(uts_trailer_tree, proto_uts, tvb, etx_start, 1, "ETX");
303 if (bcc_start)
304 proto_tree_add_protocol_format(uts_trailer_tree, proto_uts, tvb, bcc_start, -1, "CCC + padding");
308 return tvb_captured_length(tvb);
311 void
312 proto_register_uts(void)
314 static hf_register_info hf[] = {
315 { &hf_rid,
316 { "RID", "uts.rid",
317 FT_UINT8, BASE_HEX, NULL, 0, "Remote Identifier address", HFILL }},
318 { &hf_sid,
319 { "SID", "uts.sid",
320 FT_UINT8, BASE_HEX, NULL, 0, "Site Identifier address", HFILL }},
321 { &hf_did,
322 { "DID", "uts.did",
323 FT_UINT8, BASE_HEX, NULL, 0, "Device Identifier address", HFILL }},
324 { &hf_retxrequest,
325 { "ReTxRequest", "uts.retxrequest",
326 FT_BOOLEAN, BASE_NONE, NULL, 0x0, "true if Re-transmit Request", HFILL }},
327 { &hf_ack,
328 { "Ack", "uts.ack",
329 FT_BOOLEAN, BASE_NONE, NULL, 0x0, "true if Ack", HFILL }},
330 { &hf_replyrequest,
331 { "ReplyRequest", "uts.replyrequest",
332 FT_BOOLEAN, BASE_NONE, NULL, 0x0, "true if Reply Request", HFILL }},
333 { &hf_busy,
334 { "Busy", "uts.busy",
335 FT_BOOLEAN, BASE_NONE, NULL, 0x0, "true if Busy", HFILL }},
336 { &hf_notbusy,
337 { "NotBusy", "uts.notbusy",
338 FT_BOOLEAN, BASE_NONE, NULL, 0x0, "true if Not Busy", HFILL }},
339 { &hf_msgwaiting,
340 { "MsgWaiting", "uts.msgwaiting",
341 FT_BOOLEAN, BASE_NONE, NULL, 0x0, "true if Message Waiting", HFILL }},
342 { &hf_function,
343 { "Function", "uts.function",
344 FT_UINT8, BASE_HEX, NULL, 0, "Function Code value", HFILL }},
345 { &hf_data,
346 { "Data", "uts.data",
347 FT_STRING, BASE_NONE, NULL, 0, "User Data Message", HFILL }},
350 static int *ett[] = {
351 &ett_uts,
352 &ett_header_uts,
353 &ett_trailer_uts,
356 proto_uts = proto_register_protocol("Unisys Transmittal System", "UTS", "uts"); /* name, short name, abbrev */
357 proto_register_field_array(proto_uts, hf, array_length(hf));
358 proto_register_subtree_array(ett, array_length(ett));
359 register_dissector("uts", dissect_uts, proto_uts);
363 * Editor modelines - https://www.wireshark.org/tools/modelines.html
365 * Local variables:
366 * c-basic-offset: 8
367 * tab-width: 8
368 * indent-tabs-mode: t
369 * End:
371 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
372 * :indentSize=8:tabSize=8:noTabs=false: