1 /* packet-ucp.c
2 * Routines for Universal Computer Protocol dissection
3 * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
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 * Dissector of a UCP (Universal Computer Protocol) PDU, as defined for the
13 * ERMES paging system in ETS 300 133-3 (2nd final draft, September 1997,
14 * www.etsi.org).
15 * Includes the extension of EMI-UCP interface
16 * (V4.0, May 2001, www.advox.se/download/protocols/EMI_UCP.pdf)
17 *
18 * Support for statistics using the Stats Tree API added by
19 * Abhik Sarkar <sarkar.abhik@gmail.com>
20 *
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26
27 #include <epan/packet.h>
28 #include <epan/prefs.h>
29 #include <epan/expert.h>
30 #include <epan/stats_tree.h>
31
32 #include <wsutil/strtoi.h>
33
34 #include "packet-tcp.h"
35
36 void proto_register_ucp(void);
37 void proto_reg_handoff_ucp(void);
38
39 /* Tap Record */
40 typedef struct _ucp_tap_rec_t {
41 guint message_type; /* 0 = Operation; 1 = Result */
42 guint operation; /* Operation Type */
43 guint result; /* 0 = Success; Non 0 = Error Code */
44 } ucp_tap_rec_t;
45
46 /* Preferences */
47 static gboolean ucp_desegment = TRUE;
48
49 /* STX + TRN(2 num. char.) + / + LEN(5 num. char.) + / + 'O'/'R' + / + OT(2 num. char.) + / */
50 #define UCP_HEADER_SIZE 15
51
52 /*
53 * Convert ASCII-hex character to binary equivalent. No checks, assume
54 * is valid hex character.
55 */
56 #define AHex2Bin(n) (((n) & 0x40) ? ((n) & 0x0F) + 9 : ((n) & 0x0F))
57
58 #define UCP_STX 0x02 /* Start of UCP PDU */
59 #define UCP_ETX 0x03 /* End of UCP PDU */
60
61 #define UCP_MALFORMED -1 /* Not a valid PDU */
62 #define UCP_INV_CHK -2 /* Incorrect checksum */
63
64 #define UCP_TRN_OFFSET 1
65 #define UCP_LEN_OFFSET 4
66 #define UCP_O_R_OFFSET 10 /* Location of O/R field */
67 #define UCP_OT_OFFSET 12 /* Location of OT field */
68
69 #define UCP_TRN_LEN 2 /* Length of TRN-field */
70 #define UCP_LEN_LEN 5 /* Length of LEN-field */
71 #define UCP_O_R_LEN 1 /* Length of O/R-field */
72 #define UCP_OT_LEN 2 /* Length of OT-field */
73
74
75 static dissector_handle_t ucp_handle;
76
77 /*
78 * Initialize the protocol and registered fields
79 *
80 * Header (fixed) section
81 */
82 static int proto_ucp = -1;
83
84 static int hf_ucp_hdr_TRN = -1;
85 static int hf_ucp_hdr_LEN = -1;
86 static int hf_ucp_hdr_O_R = -1;
87 static int hf_ucp_hdr_OT = -1;
88
89 /*
90 * Stats section
91 */
92 static int st_ucp_messages = -1;
93 static int st_ucp_ops = -1;
94 static int st_ucp_res = -1;
95 static int st_ucp_results = -1;
96 static int st_ucp_results_pos = -1;
97 static int st_ucp_results_neg = -1;
98
99 static const gchar st_str_ucp[] = "UCP Messages";
100 static const gchar st_str_ops[] = "Operations";
101 static const gchar st_str_res[] = "Results";
102 static const gchar st_str_ucp_res[] = "UCP Results Acks/Nacks";
103 static const gchar st_str_pos[] = "Positive";
104 static const gchar st_str_neg[] = "Negative";
105
106 /*
107 * Data (variable) section
108 */
109 static int hf_ucp_oper_section = -1;
110 static int hf_ucp_parm_AdC = -1;
111 static int hf_ucp_parm_OAdC = -1;
112 static int hf_ucp_parm_DAdC = -1;
113 static int hf_ucp_parm_AC = -1;
114 static int hf_ucp_parm_OAC = -1;
115 static int hf_ucp_parm_BAS = -1;
116 static int hf_ucp_parm_LAR = -1;
117 static int hf_ucp_parm_LAC = -1;
118 static int hf_ucp_parm_L1R = -1;
119 static int hf_ucp_parm_L1P = -1;
120 static int hf_ucp_parm_L3R = -1;
121 static int hf_ucp_parm_L3P = -1;
122 static int hf_ucp_parm_LCR = -1;
123 static int hf_ucp_parm_LUR = -1;
124 static int hf_ucp_parm_LRR = -1;
125 static int hf_ucp_parm_RT = -1;
126 static int hf_ucp_parm_NoN = -1;
127 static int hf_ucp_parm_NoA = -1;
128 static int hf_ucp_parm_NoB = -1;
129 static int hf_ucp_parm_NAC = -1;
130 static int hf_ucp_parm_PNC = -1;
131 static int hf_ucp_parm_AMsg = -1;
132 static int hf_ucp_parm_LNo = -1;
133 static int hf_ucp_parm_LST = -1;
134 static int hf_ucp_parm_TNo = -1;
135 static int hf_ucp_parm_CS = -1;
136 static int hf_ucp_parm_PID = -1;
137 static int hf_ucp_parm_NPL = -1;
138 static int hf_ucp_parm_GA = -1;
139 static int hf_ucp_parm_RP = -1;
140 static int hf_ucp_parm_LRP = -1;
141 static int hf_ucp_parm_PR = -1;
142 static int hf_ucp_parm_LPR = -1;
143 static int hf_ucp_parm_UM = -1;
144 static int hf_ucp_parm_LUM = -1;
145 static int hf_ucp_parm_RC = -1;
146 static int hf_ucp_parm_LRC = -1;
147 static int hf_ucp_parm_NRq = -1;
148 static int hf_ucp_parm_GAdC = -1;
149 static int hf_ucp_parm_A_D = -1;
150 static int hf_ucp_parm_CT = -1;
151 static int hf_ucp_parm_AAC = -1;
152 static int hf_ucp_parm_MNo = -1;
153 static int hf_ucp_parm_R_T = -1;
154 static int hf_ucp_parm_IVR5x = -1;
155 static int hf_ucp_parm_REQ_OT = -1;
156 static int hf_ucp_parm_SSTAT = -1;
157 static int hf_ucp_parm_LMN = -1;
158 static int hf_ucp_parm_NMESS = -1;
159 static int hf_ucp_parm_NAdC = -1;
160 static int hf_ucp_parm_NT = -1;
161 static int hf_ucp_parm_NPID = -1;
162 static int hf_ucp_parm_LRq = -1;
163 static int hf_ucp_parm_LRAd = -1;
164 static int hf_ucp_parm_LPID = -1;
165 static int hf_ucp_parm_DD = -1;
166 static int hf_ucp_parm_DDT = -1;
167 static int hf_ucp_parm_STx = -1;
168 static int hf_ucp_parm_ST = -1;
169 static int hf_ucp_parm_SP = -1;
170 static int hf_ucp_parm_VP = -1;
171 static int hf_ucp_parm_RPID = -1;
172 static int hf_ucp_parm_SCTS = -1;
173 static int hf_ucp_parm_Dst = -1;
174 static int hf_ucp_parm_Rsn = -1;
175 static int hf_ucp_parm_DSCTS = -1;
176 static int hf_ucp_parm_MT = -1;
177 static int hf_ucp_parm_NB = -1;
178 static int hf_ucp_data_section = -1;
179 static int hf_ucp_parm_MMS = -1;
180 static int hf_ucp_parm_DCs = -1;
181 static int hf_ucp_parm_MCLs = -1;
182 static int hf_ucp_parm_RPI = -1;
183 static int hf_ucp_parm_CPg = -1;
184 static int hf_ucp_parm_RPLy = -1;
185 static int hf_ucp_parm_OTOA = -1;
186 static int hf_ucp_parm_HPLMN = -1;
187 static int hf_ucp_parm_RES4 = -1;
188 static int hf_ucp_parm_RES5 = -1;
189 static int hf_ucp_parm_OTON = -1;
190 static int hf_ucp_parm_ONPI = -1;
191 static int hf_ucp_parm_STYP0 = -1;
192 static int hf_ucp_parm_STYP1 = -1;
193 static int hf_ucp_parm_ACK = -1;
194 static int hf_ucp_parm_PWD = -1;
195 static int hf_ucp_parm_NPWD = -1;
196 static int hf_ucp_parm_VERS = -1;
197 static int hf_ucp_parm_LAdC = -1;
198 static int hf_ucp_parm_LTON = -1;
199 static int hf_ucp_parm_LNPI = -1;
200 static int hf_ucp_parm_OPID = -1;
201 static int hf_ucp_parm_RES1 = -1;
202 static int hf_ucp_parm_RES2 = -1;
203 static int hf_ucp_parm_MVP = -1;
204 static int hf_ucp_parm_EC = -1;
205 static int hf_ucp_parm_SM = -1;
206 static int hf_ucp_not_subscribed = -1;
207 static int hf_ucp_ga_roaming = -1;
208 static int hf_ucp_call_barring = -1;
209 static int hf_ucp_deferred_delivery = -1;
210 static int hf_ucp_diversion = -1;
211
212 static int hf_ucp_parm_XSer = -1;
213 static int hf_xser_service = -1;
214 static int hf_xser_length = -1;
215 static int hf_xser_data = -1;
216
217 /* Initialize the subtree pointers */
218 static gint ett_ucp = -1;
219 static gint ett_sub = -1;
220 static gint ett_XSer = -1;
221
222 static expert_field ei_ucp_stx_missing = EI_INIT;
223 static expert_field ei_ucp_intstring_invalid = EI_INIT;
224
225 /* Tap */
226 static int ucp_tap = -1;
227
228 /*
229 * Value-arrays for certain field-contents
230 */
231 static const value_string vals_hdr_O_R[] = {
232 { 'O', "Operation" },
233 { 'R', "Result" },
234 { 0, NULL }
235 };
236
237 static const value_string vals_hdr_OT[] = { /* Operation type */
238 { 0, "Enquiry" },
239 { 1, "Call input" },
240 { 2, "Call input (multiple address)" },
241 { 3, "Call input (supplementary services included)" },
242 { 4, "Address list information" },
243 { 5, "Change address list" },
244 { 6, "Advice of accumulated charges" },
245 { 7, "Password management" },
246 { 8, "Legitimisation code management" },
247 { 9, "Standard text information" },
248 { 10, "Change standard text" },
249 { 11, "Request roaming information" },
250 { 12, "Change roaming information" },
251 { 13, "Roaming reset" },
252 { 14, "Message retrieval" },
253 { 15, "Request call barring" },
254 { 16, "Cancel call barring" },
255 { 17, "Request call diversion" },
256 { 18, "Cancel call diversion" },
257 { 19, "Request deferred delivery" },
258 { 20, "Cancel deferred delivery" },
259 { 21, "All features reset" },
260 { 22, "Call input (with specific character set)" },
261 { 23, "UCP version status request" },
262 { 24, "Mobile subscriber feature status request" },
263 { 30, "SMS message transfer" },
264 { 31, "SMT alert" },
265 { 32, "(proprietary)" },
266 { 34, "(proprietary)" },
267 { 36, "(proprietary)" },
268 { 38, "(proprietary)" },
269 { 40, "(proprietary)" },
270 { 41, "(proprietary)" },
271 { 42, "(proprietary)" },
272 { 43, "(proprietary)" },
273 { 44, "(proprietary)" },
274 { 45, "(proprietary)" },
275 { 51, "Submit short message" },
276 { 52, "Deliver short message" },
277 { 53, "Deliver notification" },
278 { 54, "Modify message" },
279 { 55, "Inquiry message" },
280 { 56, "Delete message" },
281 { 57, "Inquiry response message" },
282 { 58, "Delete response message" },
283 { 60, "Session management" },
284 { 61, "List management" },
285 { 95, "(proprietary)" },
286 { 96, "(proprietary)" },
287 { 97, "(proprietary)" },
288 { 98, "(proprietary)" },
289 { 99, "(proprietary)" },
290 { 0, NULL }
291 };
292 static value_string_ext vals_hdr_OT_ext = VALUE_STRING_EXT_INIT(vals_hdr_OT);
293
294 static const value_string vals_parm_EC[] = { /* Error code */
295 { 1, "Checksum error" },
296 { 2, "Syntax error" },
297 { 3, "Operation not supported by system" },
298 { 4, "Operation not allowed" },
299 { 5, "Call barring active" },
300 { 6, "AdC invalid" },
301 { 7, "Authentication failure" },
302 { 8, "Legitimisation code for all calls, failure" },
303 { 9, "GA not valid" },
304 { 10, "Repetition not allowed" },
305 { 11, "Legitimisation code for repetition, failure" },
306 { 12, "Priority call not allowed" },
307 { 13, "Legitimisation code for priority call, failure" },
308 { 14, "Urgent message not allowed" },
309 { 15, "Legitimisation code for urgent message, failure" },
310 { 16, "Reverse charging not allowed" },
311 { 17, "Legitimisation code for rev. charging, failure" },
312 { 18, "Deferred delivery not allowed" },
313 { 19, "New AC not valid" },
314 { 20, "New legitimisation code not valid" },
315 { 21, "Standard text not valid" },
316 { 22, "Time period not valid" },
317 { 23, "Message type not supported by system" },
318 { 24, "Message too long" },
319 { 25, "Requested standard text not valid" },
320 { 26, "Message type not valid for the pager type" },
321 { 27, "Message not found in SMSC" },
322 { 28, "Invalid character set" },
323 { 30, "Subscriber hang-up" },
324 { 31, "Fax group not supported" },
325 { 32, "Fax message type not supported" },
326 { 33, "Address already in list (60-series)" },
327 { 34, "Address not in list (60-series)" },
328 { 35, "List full, cannot add address to list (60-series)" },
329 { 36, "RPID already in use" },
330 { 37, "Delivery in progress" },
331 { 38, "Message forwarded" },
332 { 50, "Low network status" },
333 { 51, "Legitimisation code for standard text, failure" },
334 { 53, "Operation partially successful" },
335 { 54, "Operation not successful" },
336 { 55, "System error" },
337 { 57, "AdC already a member of GAdC address list" },
338 { 58, "AdC not a member of GAdC address list" },
339 { 59, "Requested standard text list invalid" },
340 { 61, "Not controller of GAdC address list" },
341 { 62, "Standard text too large" },
342 { 63, "Not owner of standard text list" },
343 { 64, "Address list full" },
344 { 65, "GAdC invalid" },
345 { 66, "Operation restricted to mobile subscribers" },
346 { 68, "Invalid AdC type" },
347 { 69, "Cannot add AdC to GAdC address list" },
348 { 90, "(proprietary error code)" },
349 { 91, "(proprietary error code)" },
350 { 92, "(proprietary error code)" },
351 { 93, "(proprietary error code)" },
352 { 94, "(proprietary error code)" },
353 { 95, "(proprietary error code)" },
354 { 96, "(proprietary error code)" },
355 { 97, "(proprietary error code)" },
356 { 98, "(proprietary error code)" },
357 { 99, "(proprietary error code)" },
358 { 0, NULL },
359 };
360 static value_string_ext vals_parm_EC_ext = VALUE_STRING_EXT_INIT(vals_parm_EC);
361
362 static const value_string vals_parm_NRq[] = {
363 { '0', "NAdC not used" },
364 { '1', "NAdC used" },
365 { 0, NULL },
366 };
367
368 static const value_string vals_parm_NT[] = {
369 { '0', "Default value" },
370 { '1', "Delivery notification" },
371 { '2', "Non-delivery notification" },
372 { '3', "Delivery and Non-delivery notification" },
373 { '4', "Buffered message notification" },
374 { '5', "Buffered and Delivery notification" },
375 { '6', "Buffered and Non-delivery notification" },
376 { '7', "All notifications" },
377 { 0, NULL },
378 };
379
380 static const value_string vals_parm_PID[] = {
381 { 100, "Mobile station" },
382 { 122, "Fax Group 3" },
383 { 131, "X.400" },
384 { 138, "Menu over PSTN" },
385 { 139, "PC appl. over PSTN (E.164)" },
386 { 339, "PC appl. over X.25 (X.121)" },
387 { 439, "PC appl. over ISDN (E.164)" },
388 { 539, "PC appl. over TCP/IP" },
389 { 639, "PC appl. via abbreviated number" },
390 { 0, NULL },
391 };
392
393 static const value_string vals_parm_LRq[] = {
394 { '0', "LRAd not used" },
395 { '1', "LRAd used" },
396 { 0, NULL },
397 };
398
399 static const value_string vals_parm_DD[] = {
400 { '0', "DDT not used" },
401 { '1', "DDT used" },
402 { 0, NULL },
403 };
404
405 static const value_string vals_parm_Dst[] = {
406 { '0', "delivered" },
407 { '1', "buffered (see Rsn)" },
408 { '2', "not delivered (see Rsn)" },
409 { 0, NULL },
410 };
411
412 static const value_string vals_parm_Rsn[] = {
413 { 0, "Unknown subscriber" },
414 { 1, "Service temporary not available" },
415 { 2, "Service temporary not available" },
416 { 3, "Service temporary not available" },
417 { 4, "Service temporary not available" },
418 { 5, "Service temporary not available" },
419 { 6, "Service temporary not available" },
420 { 7, "Service temporary not available" },
421 { 8, "Service temporary not available" },
422 { 9, "Illegal error code" },
423 { 10, "Network time-out" },
424 { 100, "Facility not supported" },
425 { 101, "Unknown subscriber" },
426 { 102, "Facility not provided" },
427 { 103, "Call barred" },
428 { 104, "Operation barred" },
429 { 105, "SC congestion" },
430 { 106, "Facility not supported" },
431 { 107, "Absent subscriber" },
432 { 108, "Delivery fail" },
433 { 109, "Sc congestion" },
434 { 110, "Protocol error" },
435 { 111, "MS not equipped" },
436 { 112, "Unknown SC" },
437 { 113, "SC congestion" },
438 { 114, "Illegal MS" },
439 { 115, "MS nota subscriber" },
440 { 116, "Error in MS" },
441 { 117, "SMS lower layer not provisioned" },
442 { 118, "System fail" },
443 { 119, "PLMN system failure" },
444 { 120, "HLR system failure" },
445 { 121, "VLR system failure" },
446 { 122, "Previous VLR system failure" },
447 { 123, "Controlling MSC system failure" },
448 { 124, "VMSC system failure" },
449 { 125, "EIR system failure" },
450 { 126, "System failure" },
451 { 127, "Unexpected data value" },
452 { 200, "Error in address service centre" },
453 { 201, "Invalid absolute validity period" },
454 { 202, "Short message exceeds maximum" },
455 { 203, "Unable to unpack GSM message" },
456 { 204, "Unable to convert to IRA alphabet" },
457 { 205, "Invalid validity period format" },
458 { 206, "Invalid destination address" },
459 { 207, "Duplicate message submit" },
460 { 208, "Invalid message type indicator" },
461 { 0, NULL },
462 };
463 static value_string_ext vals_parm_Rsn_ext = VALUE_STRING_EXT_INIT(vals_parm_Rsn);
464
465 static const value_string vals_parm_MT[] = {
466 { '2', "Numeric message" },
467 { '3', "Alphanumeric message" },
468 { '4', "Transparent data" },
469 { 0, NULL },
470 };
471
472 static const value_string vals_parm_DCs[] = {
473 { '0', "default alphabet" },
474 { '1', "User defined data (8 bit)" },
475 { 0, NULL },
476 };
477
478 static const value_string vals_parm_MCLs[] = {
479 { '0', "message class 0" },
480 { '1', "message class 1" },
481 { '2', "message class 2" },
482 { '3', "message class 3" },
483 { 0, NULL },
484 };
485
486 static const value_string vals_parm_RPI[] = {
487 { '1', "Request" },
488 { '2', "Response" },
489 { 0, NULL },
490 };
491
492 static const value_string vals_parm_ACK[] = {
493 { 'A', "Ack" },
494 { 'N', "Nack" },
495 { 0, NULL },
496 };
497
498 static const value_string vals_parm_RP[] = {
499 { '1', "Repetition requested" },
500 { 0, NULL },
501 };
502
503 static const value_string vals_parm_UM[] = {
504 { '1', "Urgent message" },
505 { 0, NULL },
506 };
507
508 static const value_string vals_parm_RC[] = {
509 { '1', "Reverse charging request" },
510 { 0, NULL },
511 };
512
513 static const value_string vals_parm_OTON[] = {
514 { '1', "International number" },
515 { '2', "National number" },
516 { '6', "Abbreviated number (short number alias)" },
517 { 0, NULL },
518 };
519
520 static const value_string vals_parm_ONPI[] = {
521 { '1', "E.164 address" },
522 { '3', "X.121 address" },
523 { '5', "Private -TCP/IP or abbreviated number- address" },
524 { 0, NULL },
525 };
526
527 static const value_string vals_parm_STYP0[] = {
528 { '1', "open session" },
529 { '2', "reserved" },
530 { '3', "change password" },
531 { '4', "open provisioning session" },
532 { '5', "reserved" },
533 { '6', "change provisioning password" },
534 { 0, NULL },
535 };
536
537 static const value_string vals_parm_STYP1[] = {
538 { '1', "add item to mo-list" },
539 { '2', "remove item from mo-list" },
540 { '3', "verify item mo-list" },
541 { '4', "add item to mt-list" },
542 { '5', "remove item from mt-list" },
543 { '6', "verify item mt-list" },
544 { 0, NULL },
545 };
546
547 static const value_string vals_parm_OPID[] = {
548 { 0, "Mobile station" },
549 { 39, "PC application" },
550 { 0, NULL },
551 };
552
553 static const value_string vals_parm_BAS[] = {
554 { '1', "Barred" },
555 { 0, NULL },
556 };
557
558 static const value_string vals_parm_LAR[] = {
559 { '1', "Leg. code for all calls requested" },
560 { 0, NULL },
561 };
562
563 static const value_string vals_parm_L1R[] = {
564 { '1', "Leg. code for priority 1 requested" },
565 { 0, NULL },
566 };
567
568 static const value_string vals_parm_L3R[] = {
569 { '1', "Leg. code for priority 3 requested" },
570 { 0, NULL },
571 };
572
573 static const value_string vals_parm_LCR[] = {
574 { '1', "Leg. code for reverse charging requested" },
575 { 0, NULL },
576 };
577
578 static const value_string vals_parm_LUR[] = {
579 { '1', "Leg. code for urgent message requested" },
580 { 0, NULL },
581 };
582
583 static const value_string vals_parm_LRR[] = {
584 { '1', "Leg. code for repetition requested" },
585 { 0, NULL },
586 };
587
588 static const value_string vals_parm_RT[] = {
589 { '1', "Tone only" },
590 { '2', "Numeric" },
591 { '3', "Alphanumeric" },
592 { '4', "Transparent data" },
593 { 0, NULL },
594 };
595
596 static const value_string vals_parm_PNC[] = {
597 { 'H', "Home PNC" },
598 { 'I', "Input PNC" },
599 { 0, NULL },
600 };
601
602 static const value_string vals_parm_A_D[] = {
603 { 'A', "Add" },
604 { 'D', "Delete" },
605 { 0, NULL },
606 };
607
608 static const value_string vals_parm_R_T[] = {
609 { 'R', "Retrieval Ok" },
610 { 'T', "Retransmit on radio channel" },
611 { 0, NULL },
612 };
613
614 static const value_string vals_parm_REQ_OT[] = {
615 { 'S', "Send used operation types" },
616 { 'N', "Don't send used operation types" },
617 { 0, NULL },
618 };
619
620 static const value_string vals_parm_SSTAT[] = {
621 { '0', "All services" },
622 { '1', "All in the moment active services" },
623 { '2', "Call diversion" },
624 { '3', "Roaming information status" },
625 { '4', "Call barring status" },
626 { '5', "Deferred delivery status" },
627 { '6', "Number of stored messages" },
628 { 0, NULL },
629 };
630
631 static const value_string vals_xser_service[] = {
632 { 0, "Not Used" },
633 { 1, "GSM UDH information" },
634 { 2, "GSM DCS information" },
635 { 3, "[Message Type] TDMA information exchange" },
636 { 4, "[Message Reference] TDMA information exchange" },
637 { 5, "[Privacy Indicator] TDMA information exchange" },
638 { 6, "[Urgency Indicator] TDMA information exchange" },
639 { 7, "[Acknowledgement Request] TDMA information exchange" },
640 { 8, "[Message Updating] TDMA information exchange" },
641 { 9, "[Call Back Number] TDMA information exchange" },
642 { 10, "[Response Code] TDMA information exchange" },
643 { 11, "[Teleservice ID] TDMA information exchange" },
644 { 12, "Billing identifier" },
645 { 13, "Single shot indicator" },
646 { 14, "Originator TON" },
647 { 15, "Originator NPI" },
648 { 16, "Recipient TON" },
649 { 17, "Recipient NPI" },
650 { 18, "Message Original Submission Time" },
651 { 19, "Destination Network Type" },
652 { 0, NULL },
653 };
654 static value_string_ext vals_xser_service_ext = VALUE_STRING_EXT_INIT(vals_xser_service);
655
656 /* For statistics */
657 static void
ucp_stats_tree_init(stats_tree * st)658 ucp_stats_tree_init(stats_tree* st)
659 {
660 st_ucp_messages = stats_tree_create_node(st, st_str_ucp, 0, STAT_DT_INT, TRUE);
661 st_ucp_ops = stats_tree_create_node(st, st_str_ops, st_ucp_messages, STAT_DT_INT, TRUE);
662 st_ucp_res = stats_tree_create_node(st, st_str_res, st_ucp_messages, STAT_DT_INT, TRUE);
663 st_ucp_results = stats_tree_create_node(st, st_str_ucp_res, 0, STAT_DT_INT, TRUE);
664 st_ucp_results_pos = stats_tree_create_node(st, st_str_pos, st_ucp_results, STAT_DT_INT, TRUE);
665 st_ucp_results_neg = stats_tree_create_node(st, st_str_neg, st_ucp_results, STAT_DT_INT, TRUE);
666 }
667
668 static tap_packet_status
ucp_stats_tree_per_packet(stats_tree * st,packet_info * pinfo _U_,epan_dissect_t * edt _U_,const void * p)669 ucp_stats_tree_per_packet(stats_tree *st, /* st as it was passed to us */
670 packet_info *pinfo _U_,
671 epan_dissect_t *edt _U_,
672 const void *p) /* Used for getting UCP stats */
673 {
674 const ucp_tap_rec_t *tap_rec = (const ucp_tap_rec_t*)p;
675
676 tick_stat_node(st, st_str_ucp, 0, TRUE);
677
678 if (tap_rec->message_type == 0) /* Operation */
679 {
680 tick_stat_node(st, st_str_ops, st_ucp_messages, TRUE);
681 tick_stat_node(st, val_to_str_ext(tap_rec->operation, &vals_hdr_OT_ext,
682 "Unknown OT: %d"), st_ucp_ops, FALSE);
683 }
684 else /* Result */
685 {
686 tick_stat_node(st, st_str_res, st_ucp_messages, TRUE);
687 tick_stat_node(st, val_to_str_ext(tap_rec->operation, &vals_hdr_OT_ext,
688 "Unknown OT: %d"), st_ucp_res, FALSE);
689
690 tick_stat_node(st, st_str_ucp_res, 0, TRUE);
691
692 if (tap_rec->result == 0) /* Positive Result */
693 {
694 tick_stat_node(st, st_str_pos, st_ucp_results, FALSE);
695 }
696 else /* Negative Result */
697 {
698 tick_stat_node(st, st_str_neg, st_ucp_results, TRUE);
699 tick_stat_node(st, val_to_str_ext(tap_rec->result, &vals_parm_EC_ext,
700 "Unknown EC: %d"), st_ucp_results_neg, FALSE);
701 }
702 }
703
704 return TAP_PACKET_REDRAW;
705 }
706
707 /*!
708 * Checks whether the PDU looks a bit like UCP and checks the checksum
709 *
710 * Note: check_ucp is called only with a buffer of at least LEN+2 bytes.
711 * IOW: The buffer should contain a complete UCP PDU [STX ... ETX]
712 *
713 * \param tvb The buffer with PDU-data
714 * \param endpkt Returns pointer, indicating the end of the PDU
715 *
716 * \return The state of this PDU
717 * 0 Definitely UCP
718 * UCP_MALFORMED ???
719 * UCP_INV_CHK Nice packet, but checksum doesn't add up...
720 */
721 static int
check_ucp(tvbuff_t * tvb,int * endpkt)722 check_ucp(tvbuff_t *tvb, int *endpkt)
723 {
724 guint offset = 1;
725 guint checksum = 0;
726 int pkt_check, tmp;
727 int length;
728
729 length = tvb_find_guint8(tvb, offset, -1, UCP_ETX);
730 if (length == -1) {
731 *endpkt = tvb_reported_length_remaining(tvb, offset);
732 return UCP_MALFORMED;
733 }
734 for (; offset < (guint) (length - 2); offset++)
735 checksum += tvb_get_guint8(tvb, offset);
736 checksum &= 0xFF;
737 tmp = tvb_get_guint8(tvb, offset++);
738 pkt_check = AHex2Bin(tmp);
739 tmp = tvb_get_guint8(tvb, offset++);
740 pkt_check = 16 * pkt_check + AHex2Bin(tmp);
741 *endpkt = offset + 1;
742 if (checksum == (guint) pkt_check)
743 return 0;
744 else
745 return UCP_INV_CHK;
746 }
747
748 /*!
749 * UCP equivalent of mktime() (3). Convert date to standard 'time_t' format
750 *
751 * \param len The length of datestr
752 * \param datestr The UCP-formatted date to convert
753 *
754 * \return The date in standard 'time_t' format.
755 */
756 static time_t
ucp_mktime(const gint len,const char * datestr)757 ucp_mktime(const gint len, const char *datestr)
758 {
759 struct tm r_time;
760
761 r_time.tm_mday = (10 * (datestr[0] - '0') + (datestr[1] - '0'));
762
763 if (len >= 4)
764 r_time.tm_mon = (10 * (datestr[2] - '0') + (datestr[3] - '0')) - 1;
765 else
766 r_time.tm_mon = 0;
767
768 if (len >= 6)
769 r_time.tm_year = (10 * (datestr[4] - '0') + (datestr[5] - '0'));
770 else
771 r_time.tm_year = 0;
772 if (r_time.tm_year < 90)
773 r_time.tm_year += 100;
774
775 if (len >= 8)
776 r_time.tm_hour = (10 * (datestr[6] - '0') + (datestr[7] - '0'));
777 else
778 r_time.tm_hour = 0;
779
780 if (len >= 10)
781 r_time.tm_min = (10 * (datestr[8] - '0') + (datestr[9] - '0'));
782 else
783 r_time.tm_min = 0;
784
785 if (len >= 12)
786 r_time.tm_sec = (10 * (datestr[10] - '0') + (datestr[11] - '0'));
787 else
788 r_time.tm_sec = 0;
789
790 r_time.tm_isdst = -1;
791
792 return mktime(&r_time);
793 }
794
795 /*!
796 * Scanning routines to add standard types (byte, int, string, data)
797 * to the protocol-tree. Each field is seperated with a slash ('/').
798 *
799 * \param tree The protocol tree to add to
800 * \param tvb Buffer containing the data
801 * \param field The actual field, whose value needs displaying
802 * \param offset Location of field within the buffer, returns location
803 * of next field.
804 *
805 */
806 static void
ucp_handle_string(proto_tree * tree,tvbuff_t * tvb,int field,int * offset)807 ucp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
808 {
809 gint idx, len;
810
811 idx = tvb_find_guint8(tvb, *offset, -1, '/');
812 if (idx == -1) {
813 /* Force the appropriate exception to be thrown. */
814 len = tvb_captured_length_remaining(tvb, *offset);
815 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
816 } else
817 len = idx - *offset;
818 if (len > 0)
819 proto_tree_add_item(tree, field, tvb, *offset, len, ENC_ASCII|ENC_NA);
820 *offset += len;
821 if (idx != -1)
822 *offset += 1; /* skip terminating '/' */
823 }
824
825 #define UCP_BUFSIZ 512
826
827 static void
ucp_handle_IRAstring(proto_tree * tree,tvbuff_t * tvb,int field,int * offset)828 ucp_handle_IRAstring(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
829 {
830 char strval[UCP_BUFSIZ + 1],
831 *p_dst = strval;
832 guint8 byte;
833 int idx = 0;
834 int tmpoff = *offset;
835
836 while (((byte = tvb_get_guint8(tvb, tmpoff++)) != '/') &&
837 (idx < UCP_BUFSIZ))
838 {
839 if (byte >= '0' && byte <= '9')
840 {
841 *p_dst = (byte - '0') * 16;
842 }
843 else
844 {
845 *p_dst = (byte - 'A' + 10) * 16;
846 }
847 if ((byte = tvb_get_guint8(tvb, tmpoff++)) == '/')
848 {
849 break;
850 }
851 if (byte >= '0' && byte <= '9')
852 {
853 *p_dst++ += byte - '0';
854 }
855 else
856 {
857 *p_dst++ += byte - 'A' + 10;
858 }
859 idx++;
860 }
861 strval[idx] = '\0';
862 if (idx == UCP_BUFSIZ)
863 {
864 /*
865 * Data clipped, eat rest of field
866 */
867 while ((tvb_get_guint8(tvb, tmpoff++)) != '/')
868 ;
869 }
870 if ((tmpoff - *offset) > 1)
871 proto_tree_add_string(tree, field, tvb, *offset,
872 tmpoff - *offset - 1, strval);
873 *offset = tmpoff;
874 }
875
876 static guint
ucp_handle_byte(proto_tree * tree,tvbuff_t * tvb,int field,int * offset)877 ucp_handle_byte(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
878 {
879 guint intval = 0;
880
881 if ((intval = tvb_get_guint8(tvb, (*offset)++)) != '/') {
882 proto_tree_add_uint(tree, field, tvb, *offset - 1, 1, intval);
883 (*offset)++;
884 }
885 return intval;
886 }
887
888 static guint
ucp_handle_int(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,int field,int * offset)889 ucp_handle_int(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, int field, int *offset)
890 {
891 gint idx, len;
892 const char *strval;
893 guint intval = 0;
894 gboolean intval_valid;
895 proto_item *pi;
896
897 idx = tvb_find_guint8(tvb, *offset, -1, '/');
898 if (idx == -1) {
899 /* Force the appropriate exception to be thrown. */
900 len = tvb_captured_length_remaining(tvb, *offset);
901 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
902 } else
903 len = idx - *offset;
904 strval = tvb_get_string_enc(wmem_packet_scope(), tvb, *offset, len, ENC_ASCII);
905 if (len > 0) {
906 intval_valid = ws_strtou32(strval, NULL, &intval);
907 pi = proto_tree_add_uint(tree, field, tvb, *offset, len, intval);
908 if (!intval_valid)
909 expert_add_info_format(pinfo, pi, &ei_ucp_intstring_invalid,
910 "Invalid integer string: %s", strval);
911 }
912 *offset += len;
913 if (idx != -1)
914 *offset += 1; /* skip terminating '/' */
915 return intval;
916 }
917
918 static void
ucp_handle_time(proto_tree * tree,tvbuff_t * tvb,int field,int * offset)919 ucp_handle_time(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
920 {
921 gint idx, len;
922 const char *strval;
923 time_t tval;
924 nstime_t tmptime;
925
926 idx = tvb_find_guint8(tvb, *offset, -1, '/');
927 if (idx == -1) {
928 /* Force the appropriate exception to be thrown. */
929 len = tvb_captured_length_remaining(tvb, *offset);
930 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
931 } else
932 len = idx - *offset;
933 strval = tvb_get_string_enc(wmem_packet_scope(), tvb, *offset, len, ENC_ASCII);
934 if (len > 0) {
935 tval = ucp_mktime(len, strval);
936 tmptime.secs = tval;
937 tmptime.nsecs = 0;
938 proto_tree_add_time(tree, field, tvb, *offset, len, &tmptime);
939 }
940 *offset += len;
941 if (idx != -1)
942 *offset += 1; /* skip terminating '/' */
943 }
944
945 static void
ucp_handle_data(proto_tree * tree,tvbuff_t * tvb,int field,int * offset)946 ucp_handle_data(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
947 {
948 int tmpoff = *offset;
949
950 while (tvb_get_guint8(tvb, tmpoff++) != '/')
951 ;
952 if ((tmpoff - *offset) > 1)
953 proto_tree_add_item(tree, field, tvb, *offset,
954 tmpoff - *offset - 1, ENC_NA);
955 *offset = tmpoff;
956 }
957
958 static void
ucp_handle_data_string(proto_tree * tree,tvbuff_t * tvb,int field,int * offset)959 ucp_handle_data_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
960 {
961 int tmpoff = *offset;
962
963 while (tvb_get_guint8(tvb, tmpoff++) != '/')
964 ;
965 if ((tmpoff - *offset) > 1)
966 proto_tree_add_item(tree, field, tvb, *offset,
967 tmpoff - *offset - 1, ENC_ASCII|ENC_NA);
968 *offset = tmpoff;
969 }
970
971 /*!
972 * Handle the data-field within the UCP-message, according the Message Type
973 * - 1 Tone only
974 * - 2 Numeric message
975 * - 3 Alphanumeric message
976 * - 4 Transparent (binary) data
977 * - 5 Standard text handling
978 * - 6 Alphanumeric message in specified character set
979 *
980 * \param tree The protocol tree to add to
981 * \param tvb Buffer containing the data
982 * \param offset Location of field within the buffer, returns location
983 * of next field.
984 */
985 static void
ucp_handle_mt(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,int * offset)986 ucp_handle_mt(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, int *offset)
987 {
988 guint intval;
989
990 intval = ucp_handle_byte(tree, tvb, hf_ucp_parm_MT, offset);
991 switch (intval) {
992 case '1': /* Tone only, no data */
993 break;
994 case '4': /* TMsg, no of bits */
995 ucp_handle_string(tree, tvb, hf_ucp_parm_NB, offset);
996 /* fall through here for the data piece */
997 /* FALLTHROUGH */
998 case '2':
999 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
1000 break;
1001 case '3':
1002 ucp_handle_IRAstring(tree, tvb, hf_ucp_parm_AMsg, offset);
1003 break;
1004 case '5':
1005 ucp_handle_byte(tree, tvb, hf_ucp_parm_PNC, offset);
1006 ucp_handle_string(tree, tvb, hf_ucp_parm_LNo, offset);
1007 ucp_handle_string(tree, tvb, hf_ucp_parm_LST, offset);
1008 ucp_handle_string(tree, tvb, hf_ucp_parm_TNo, offset);
1009 break;
1010 case '6':
1011 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
1012 ucp_handle_int(tree, pinfo, tvb, hf_ucp_parm_CS, offset);
1013 break;
1014 default:
1015 break; /* No data so ? */
1016 }
1017 }
1018
1019 /*!
1020 * Handle the data within the 'Extended services' field. Each field having the
1021 * format TTLLDD..., TT being the type of service, LL giving the length of the
1022 * field, DD... containing the actual data
1023 *
1024 * \param tree The protocol tree to add to
1025 * \param tvb Buffer containing the extended services data
1026 */
1027 static void
ucp_handle_XSer(proto_tree * tree,tvbuff_t * tvb)1028 ucp_handle_XSer(proto_tree *tree, tvbuff_t *tvb)
1029 {
1030 int offset = 0;
1031 guint intval;
1032 int service;
1033 int len;
1034
1035 while ((intval = tvb_get_guint8(tvb, offset)) != '/') {
1036 service = AHex2Bin(intval);
1037 intval = tvb_get_guint8(tvb, offset+1);
1038 service = service * 16 + AHex2Bin(intval);
1039 intval = tvb_get_guint8(tvb, offset+2);
1040 len = AHex2Bin(intval);
1041 intval = tvb_get_guint8(tvb, offset+3);
1042 len = len * 16 + AHex2Bin(intval);
1043 proto_tree_add_uint(tree, hf_xser_service, tvb, offset, 2, service);
1044 proto_tree_add_uint(tree, hf_xser_length, tvb, offset+2, 2, len);
1045 proto_tree_add_item(tree, hf_xser_data, tvb, offset+4, len*2, ENC_ASCII|ENC_NA);
1046 offset += 4 + (2 * len);
1047 }
1048 }
1049
1050 /* Next definitions are just a convenient shorthand to make the coding a
1051 * bit more readable instead of summing up all these parameters.
1052 */
1053 #define UcpHandleString(field) ucp_handle_string(tree, tvb, (field), &offset)
1054
1055 #define UcpHandleIRAString(field) \
1056 ucp_handle_IRAstring(tree, tvb, (field), &offset)
1057
1058 #define UcpHandleByte(field) ucp_handle_byte(tree, tvb, (field), &offset)
1059
1060 #define UcpHandleInt(field) ucp_handle_int(tree, pinfo, tvb, (field), &offset)
1061
1062 #define UcpHandleTime(field) ucp_handle_time(tree, tvb, (field), &offset)
1063
1064 #define UcpHandleData(field) ucp_handle_data(tree, tvb, (field), &offset)
1065
1066 #define UcpHandleDataString(field)\
1067 ucp_handle_data_string(tree, tvb, (field), &offset)
1068
1069 /*!
1070 * The next set of routines handle the different operation types,
1071 * associated with UCP.
1072 */
1073 static void
add_00O(proto_tree * tree,tvbuff_t * tvb)1074 add_00O(proto_tree *tree, tvbuff_t *tvb)
1075 { /* Enquiry */
1076 int offset = 1;
1077
1078 UcpHandleString(hf_ucp_parm_AdC);
1079 UcpHandleString(hf_ucp_parm_OAdC);
1080 UcpHandleString(hf_ucp_parm_OAC);
1081 }
1082
1083 static void
add_00R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1084 add_00R(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1085 {
1086 int offset = 1;
1087 guint intval;
1088
1089 intval = UcpHandleByte(hf_ucp_parm_ACK);
1090 if (intval == 'A')
1091 {
1092 UcpHandleByte(hf_ucp_parm_BAS);
1093 UcpHandleByte(hf_ucp_parm_LAR);
1094 UcpHandleByte(hf_ucp_parm_L1R);
1095 UcpHandleByte(hf_ucp_parm_L3R);
1096 UcpHandleByte(hf_ucp_parm_LCR);
1097 UcpHandleByte(hf_ucp_parm_LUR);
1098 UcpHandleByte(hf_ucp_parm_LRR);
1099 UcpHandleByte(hf_ucp_parm_RT);
1100 UcpHandleInt(hf_ucp_parm_NoN);
1101 UcpHandleInt(hf_ucp_parm_NoA);
1102 UcpHandleInt(hf_ucp_parm_NoB);
1103
1104 tap_rec->result = 0;
1105 } else {
1106 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1107 UcpHandleString(hf_ucp_parm_SM);
1108 }
1109 }
1110
1111 static void
add_01O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1112 add_01O(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb)
1113 { /* Call input */
1114 int offset = 1;
1115
1116 UcpHandleString(hf_ucp_parm_AdC);
1117 UcpHandleString(hf_ucp_parm_OAdC);
1118 UcpHandleString(hf_ucp_parm_OAC);
1119 ucp_handle_mt(tree, pinfo, tvb, &offset);
1120 }
1121
1122 static void
add_01R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1123 add_01R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1124 {
1125 int offset = 1;
1126 guint intval;
1127
1128 intval = UcpHandleByte(hf_ucp_parm_ACK);
1129 if (intval == 'N')
1130 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1131 else
1132 tap_rec->result = 0;
1133 UcpHandleString(hf_ucp_parm_SM);
1134 }
1135
1136 static void
add_02O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1137 add_02O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1138 { /* Multiple address call input*/
1139 int offset = 1;
1140 guint intval;
1141 guint idx;
1142
1143 intval = UcpHandleInt(hf_ucp_parm_NPL);
1144 for (idx = 0; idx < intval; idx++)
1145 UcpHandleString(hf_ucp_parm_AdC);
1146
1147 UcpHandleString(hf_ucp_parm_OAdC);
1148 UcpHandleString(hf_ucp_parm_OAC);
1149 ucp_handle_mt(tree, pinfo, tvb, &offset);
1150 }
1151
1152 #define add_02R(a, b, c, d) add_01R(a, b, c, d)
1153
1154 static void
add_03O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1155 add_03O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1156 { /* Call input with SS */
1157 int offset = 1;
1158 guint intval;
1159 guint idx;
1160
1161 UcpHandleString(hf_ucp_parm_AdC);
1162 UcpHandleString(hf_ucp_parm_OAdC);
1163 UcpHandleString(hf_ucp_parm_OAC);
1164 intval = UcpHandleInt(hf_ucp_parm_NPL);
1165 for (idx = 0; idx < intval; idx++)
1166 UcpHandleString(hf_ucp_parm_GA);
1167
1168 UcpHandleByte(hf_ucp_parm_RP);
1169 UcpHandleString(hf_ucp_parm_LRP);
1170 UcpHandleByte(hf_ucp_parm_PR);
1171 UcpHandleString(hf_ucp_parm_LPR);
1172 UcpHandleByte(hf_ucp_parm_UM);
1173 UcpHandleString(hf_ucp_parm_LUM);
1174 UcpHandleByte(hf_ucp_parm_RC);
1175 UcpHandleString(hf_ucp_parm_LRC);
1176 UcpHandleByte(hf_ucp_parm_DD);
1177 UcpHandleTime(hf_ucp_parm_DDT); /* DDMMYYHHmm */
1178 ucp_handle_mt(tree, pinfo, tvb, &offset);
1179 }
1180
1181 #define add_03R(a, b, c, d) add_01R(a, b, c, d)
1182
1183 static void
add_04O(proto_tree * tree,tvbuff_t * tvb)1184 add_04O(proto_tree *tree, tvbuff_t *tvb)
1185 { /* Address list information */
1186 int offset = 1;
1187
1188 UcpHandleString(hf_ucp_parm_GAdC);
1189 UcpHandleString(hf_ucp_parm_AC);
1190 UcpHandleString(hf_ucp_parm_OAdC);
1191 UcpHandleString(hf_ucp_parm_OAC);
1192 }
1193
1194 static void
add_04R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1195 add_04R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1196 {
1197 int offset = 1;
1198 guint intval;
1199 guint idx;
1200
1201 intval = UcpHandleByte(hf_ucp_parm_ACK);
1202 if (intval == 'A') {
1203 intval = UcpHandleInt(hf_ucp_parm_NPL);
1204 for (idx = 0; idx < intval; idx++)
1205 UcpHandleString(hf_ucp_parm_AdC);
1206 UcpHandleString(hf_ucp_parm_GAdC);
1207 tap_rec->result = 0;
1208 } else
1209 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1210 UcpHandleString(hf_ucp_parm_SM);
1211 }
1212
1213 static void
add_05O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1214 add_05O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1215 { /* Change address list */
1216 int offset = 1;
1217 guint intval;
1218 guint idx;
1219
1220 UcpHandleString(hf_ucp_parm_GAdC);
1221 UcpHandleString(hf_ucp_parm_AC);
1222 UcpHandleString(hf_ucp_parm_OAdC);
1223 UcpHandleString(hf_ucp_parm_OAC);
1224 intval = UcpHandleInt(hf_ucp_parm_NPL);
1225 for (idx = 0; idx < intval; idx++)
1226 UcpHandleString(hf_ucp_parm_AdC);
1227 UcpHandleByte(hf_ucp_parm_A_D);
1228 }
1229
1230 #define add_05R(a, b, c, d) add_01R(a, b, c, d)
1231
1232 static void
add_06O(proto_tree * tree,tvbuff_t * tvb)1233 add_06O(proto_tree *tree, tvbuff_t *tvb)
1234 { /* Advice of accum. charges */
1235 int offset = 1;
1236
1237 UcpHandleString(hf_ucp_parm_AdC);
1238 UcpHandleString(hf_ucp_parm_AC);
1239 }
1240
1241 static void
add_06R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1242 add_06R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1243 {
1244 int offset = 1;
1245 guint intval;
1246
1247 intval = UcpHandleByte(hf_ucp_parm_ACK);
1248 if (intval == 'A') {
1249 UcpHandleTime(hf_ucp_parm_CT);
1250 UcpHandleString(hf_ucp_parm_AAC);
1251 tap_rec->result = 0;
1252 } else
1253 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1254 UcpHandleString(hf_ucp_parm_SM);
1255 }
1256
1257 static void
add_07O(proto_tree * tree,tvbuff_t * tvb)1258 add_07O(proto_tree *tree, tvbuff_t *tvb)
1259 { /* Password management */
1260 int offset = 1;
1261
1262 UcpHandleString(hf_ucp_parm_AdC);
1263 UcpHandleString(hf_ucp_parm_AC);
1264 UcpHandleString(hf_ucp_parm_NAC);
1265 }
1266
1267 #define add_07R(a, b, c, d) add_01R(a, b, c, d)
1268
1269 static void
add_08O(proto_tree * tree,tvbuff_t * tvb)1270 add_08O(proto_tree *tree, tvbuff_t *tvb)
1271 { /* Leg. code management */
1272 int offset = 1;
1273
1274 UcpHandleString(hf_ucp_parm_AdC);
1275 UcpHandleString(hf_ucp_parm_AC);
1276 UcpHandleString(hf_ucp_parm_LAC);
1277 UcpHandleString(hf_ucp_parm_L1P);
1278 UcpHandleString(hf_ucp_parm_L3P);
1279 UcpHandleString(hf_ucp_parm_LRC);
1280 UcpHandleString(hf_ucp_parm_LUM);
1281 UcpHandleString(hf_ucp_parm_LRP);
1282 UcpHandleString(hf_ucp_parm_LST);
1283 }
1284
1285 #define add_08R(a, b, c, d) add_01R(a, b, c, d)
1286
1287 static void
add_09O(proto_tree * tree,tvbuff_t * tvb)1288 add_09O(proto_tree *tree, tvbuff_t *tvb)
1289 { /* Standard text information */
1290 int offset = 1;
1291
1292 UcpHandleString(hf_ucp_parm_LNo);
1293 UcpHandleString(hf_ucp_parm_LST);
1294 }
1295
1296 static void
add_09R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1297 add_09R(proto_tree *tree, packet_info *pinfo,tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1298 {
1299 int offset = 1;
1300 guint intval;
1301 guint idx;
1302
1303 intval = UcpHandleByte(hf_ucp_parm_ACK);
1304 if (intval == 'A') {
1305 intval = UcpHandleInt(hf_ucp_parm_NPL);
1306 for (idx = 0; idx < intval; idx++)
1307 UcpHandleString(hf_ucp_parm_LST);
1308 tap_rec->result = 0;
1309 } else
1310 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1311 UcpHandleString(hf_ucp_parm_SM);
1312 }
1313
1314 static void
add_10O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1315 add_10O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1316 { /* Change standard text */
1317 int offset = 1;
1318
1319 UcpHandleString(hf_ucp_parm_AdC);
1320 UcpHandleString(hf_ucp_parm_AC);
1321 UcpHandleString(hf_ucp_parm_LNo);
1322 UcpHandleString(hf_ucp_parm_TNo);
1323 UcpHandleData(hf_ucp_parm_STx);
1324 UcpHandleInt(hf_ucp_parm_CS);
1325 }
1326
1327 #define add_10R(a, b, c, d) add_01R(a, b, c, d)
1328
1329 #define add_11O(a, b) add_06O(a, b) /* Request roaming info */
1330
1331 static void
add_11R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1332 add_11R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1333 {
1334 int offset = 1;
1335 guint intval;
1336 guint idx;
1337
1338 intval = UcpHandleByte(hf_ucp_parm_ACK);
1339 if (intval == 'A') {
1340 intval = UcpHandleInt(hf_ucp_parm_NPL);
1341 for (idx = 0; idx < intval; idx++)
1342 UcpHandleString(hf_ucp_parm_GA);
1343 tap_rec->result = 0;
1344 } else
1345 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1346 UcpHandleString(hf_ucp_parm_SM);
1347 }
1348
1349 static void
add_12O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1350 add_12O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1351 { /* Change roaming */
1352 int offset = 1;
1353 guint intval;
1354 guint idx;
1355
1356 UcpHandleString(hf_ucp_parm_AdC);
1357 UcpHandleString(hf_ucp_parm_AC);
1358 intval = UcpHandleInt(hf_ucp_parm_NPL);
1359 for (idx = 0; idx < intval; idx++)
1360 UcpHandleString(hf_ucp_parm_GA);
1361 }
1362
1363 #define add_12R(a, b, c, d) add_01R(a, b, c, d)
1364
1365 #define add_13O(a, c) add_06O(a, c) /* Roaming reset */
1366
1367 #define add_13R(a, b, c, d) add_01R(a, b, c, d)
1368
1369 static void
add_14O(proto_tree * tree,tvbuff_t * tvb)1370 add_14O(proto_tree *tree, tvbuff_t *tvb)
1371 { /* Message retrieval */
1372 int offset = 1;
1373
1374 UcpHandleString(hf_ucp_parm_AdC);
1375 UcpHandleString(hf_ucp_parm_AC);
1376 UcpHandleString(hf_ucp_parm_MNo);
1377 UcpHandleByte(hf_ucp_parm_R_T);
1378 }
1379
1380 static void
add_14R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1381 add_14R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1382 {
1383 int offset = 1;
1384 guint intval;
1385 guint idx;
1386
1387 intval = UcpHandleByte(hf_ucp_parm_ACK);
1388 if (intval == 'A') {
1389 intval = UcpHandleInt(hf_ucp_parm_NPL);
1390 /*
1391 * Spec is unclear here. Is 'SM' part of the Msg:s field or not?
1392 * For now, assume it is part of it...
1393 */
1394 for (idx = 0; idx < intval; idx++)
1395 UcpHandleData(hf_ucp_data_section);
1396 tap_rec->result = 0;
1397 } else {
1398 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1399 UcpHandleString(hf_ucp_parm_SM);
1400 }
1401 }
1402
1403 static void
add_15O(proto_tree * tree,tvbuff_t * tvb)1404 add_15O(proto_tree *tree, tvbuff_t *tvb)
1405 { /* Request call barring */
1406 int offset = 1;
1407
1408 UcpHandleString(hf_ucp_parm_AdC);
1409 UcpHandleString(hf_ucp_parm_AC);
1410 UcpHandleTime(hf_ucp_parm_ST);
1411 UcpHandleTime(hf_ucp_parm_SP);
1412 }
1413
1414 #define add_15R(a, b, c, d) add_01R(a, b, c, d)
1415
1416 #define add_16O(a, b) add_06O(a, b) /* Cancel call barring */
1417
1418 #define add_16R(a, b, c, d) add_01R(a, b, c, d)
1419
1420 static void
add_17O(proto_tree * tree,tvbuff_t * tvb)1421 add_17O(proto_tree *tree, tvbuff_t *tvb)
1422 { /* Request call diversion */
1423 int offset = 1;
1424
1425 UcpHandleString(hf_ucp_parm_AdC);
1426 UcpHandleString(hf_ucp_parm_AC);
1427 UcpHandleString(hf_ucp_parm_DAdC);
1428 UcpHandleTime(hf_ucp_parm_ST);
1429 UcpHandleTime(hf_ucp_parm_SP);
1430 }
1431
1432 #define add_17R(a, b, c, d) add_01R(a, b, c, d)
1433
1434 #define add_18O(a, b) add_06O(a, b) /* Cancel call diversion */
1435
1436 #define add_18R(a, b, c, d) add_01R(a, b, c, d)
1437
1438 static void
add_19O(proto_tree * tree,tvbuff_t * tvb)1439 add_19O(proto_tree *tree, tvbuff_t *tvb)
1440 { /* Request deferred delivery*/
1441 int offset = 1;
1442
1443 UcpHandleString(hf_ucp_parm_AdC);
1444 UcpHandleString(hf_ucp_parm_AC);
1445 UcpHandleTime(hf_ucp_parm_ST);
1446 UcpHandleTime(hf_ucp_parm_SP);
1447 }
1448
1449 #define add_19R(a, b, c, d) add_01R(a, b, c, d)
1450
1451 #define add_20O(a, b) add_06O(a, b) /* Cancel deferred delivery */
1452
1453 #define add_20R(a, b, c, d) add_01R(a, b, c, d)
1454
1455 #define add_21O(a, b) add_06O(a, b) /* All features reset */
1456
1457 #define add_21R(a, b, c, d) add_01R(a, b, c, d)
1458
1459 static void
add_22O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1460 add_22O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1461 { /* Call input w. add. CS */
1462 int offset = 1;
1463
1464 UcpHandleString(hf_ucp_parm_AdC);
1465 UcpHandleString(hf_ucp_parm_OAdC);
1466 UcpHandleString(hf_ucp_parm_OAC);
1467 UcpHandleData(hf_ucp_data_section);
1468 UcpHandleInt(hf_ucp_parm_CS);
1469 }
1470
1471 #define add_22R(a, b, c, d) add_01R(a, b, c, d)
1472
1473 static void
add_23O(proto_tree * tree,tvbuff_t * tvb)1474 add_23O(proto_tree *tree, tvbuff_t *tvb)
1475 { /* UCP version status */
1476 int offset = 1;
1477
1478 UcpHandleString(hf_ucp_parm_IVR5x);
1479 UcpHandleByte(hf_ucp_parm_REQ_OT);
1480 }
1481
1482 static void
add_23R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1483 add_23R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1484 {
1485 int offset = 1;
1486 guint intval;
1487 guint idx;
1488
1489 intval = UcpHandleByte(hf_ucp_parm_ACK);
1490 if (intval == 'A') {
1491 UcpHandleByte(hf_ucp_parm_IVR5x);
1492 intval = UcpHandleInt(hf_ucp_parm_NPL);
1493 for (idx = 0; idx < intval; idx++)
1494 UcpHandleInt(hf_ucp_hdr_OT);
1495 tap_rec->result = 0;
1496 } else
1497 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1498 UcpHandleString(hf_ucp_parm_SM);
1499 }
1500
1501 static void
add_24O(proto_tree * tree,tvbuff_t * tvb)1502 add_24O(proto_tree *tree, tvbuff_t *tvb)
1503 { /* Mobile subs. feature stat*/
1504 int offset = 1;
1505
1506 UcpHandleString(hf_ucp_parm_AdC);
1507 UcpHandleString(hf_ucp_parm_AC);
1508 UcpHandleByte(hf_ucp_parm_SSTAT);
1509 }
1510
1511 static void
add_24R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1512 add_24R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1513 {
1514 int offset = 1;
1515 guint intval;
1516 guint idx;
1517
1518 intval = UcpHandleByte(hf_ucp_parm_ACK);
1519 if (intval == 'A') {
1520 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1521 proto_tree_add_item(tree, hf_ucp_ga_roaming, tvb, offset - 1, 1, ENC_NA);
1522 if (intval == 'N') {
1523 proto_tree_add_item(tree, hf_ucp_not_subscribed, tvb, offset -1, 1, ENC_NA);
1524 offset++;
1525 } else {
1526 --offset;
1527 intval = UcpHandleInt(hf_ucp_parm_NPL);
1528 for (idx = 0; idx < intval; idx++)
1529 UcpHandleData(hf_ucp_data_section);
1530 }
1531 }
1532 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1533 proto_tree_add_item(tree, hf_ucp_call_barring, tvb, offset - 1, 1, ENC_NA);
1534 if (intval == 'N') {
1535 proto_tree_add_item(tree, hf_ucp_not_subscribed, tvb, offset -1, 1, ENC_NA);
1536 offset++;
1537 } else {
1538 --offset;
1539 intval = UcpHandleInt(hf_ucp_parm_NPL);
1540 for (idx = 0; idx < intval; idx++)
1541 UcpHandleData(hf_ucp_data_section);
1542 }
1543 }
1544 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1545 proto_tree_add_item(tree, hf_ucp_deferred_delivery, tvb, offset - 1, 1, ENC_NA);
1546 if (intval == 'N') {
1547 proto_tree_add_item(tree, hf_ucp_not_subscribed, tvb, offset -1, 1, ENC_NA);
1548 offset++;
1549 } else {
1550 --offset;
1551 intval = UcpHandleInt(hf_ucp_parm_NPL);
1552 for (idx = 0; idx < intval; idx++)
1553 UcpHandleData(hf_ucp_data_section);
1554 }
1555 }
1556 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1557 proto_tree_add_item(tree, hf_ucp_diversion, tvb, offset - 1, 1, ENC_NA);
1558 if (intval == 'N') {
1559 proto_tree_add_item(tree, hf_ucp_not_subscribed, tvb, offset -1, 1, ENC_NA);
1560 offset++;
1561 } else {
1562 --offset;
1563 intval = UcpHandleInt(hf_ucp_parm_NPL);
1564 for (idx = 0; idx < intval; idx++)
1565 UcpHandleData(hf_ucp_data_section);
1566 }
1567 }
1568 UcpHandleInt(hf_ucp_parm_LMN);
1569 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1570 if (intval == 'N') {
1571 proto_tree_add_item(tree, hf_ucp_not_subscribed, tvb, offset -1, 1, ENC_NA);
1572 offset++;
1573 } else {
1574 --offset;
1575 UcpHandleInt(hf_ucp_parm_NMESS);
1576 }
1577 }
1578 tap_rec->result = 0;
1579 } else
1580 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1581 UcpHandleString(hf_ucp_parm_SM);
1582 }
1583
1584 static void
add_30O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1585 add_30O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1586 { /* SMS message transfer */
1587 int offset = 1;
1588
1589 UcpHandleString(hf_ucp_parm_AdC);
1590 UcpHandleString(hf_ucp_parm_OAdC);
1591 UcpHandleString(hf_ucp_parm_AC);
1592 UcpHandleByte(hf_ucp_parm_NRq);
1593 UcpHandleString(hf_ucp_parm_NAdC);
1594 UcpHandleInt(hf_ucp_parm_NPID);
1595 UcpHandleByte(hf_ucp_parm_DD);
1596 UcpHandleTime(hf_ucp_parm_DDT); /* DDMMYYHHmm */
1597 UcpHandleTime(hf_ucp_parm_VP); /* DDMMYYHHmm */
1598 UcpHandleIRAString(hf_ucp_parm_AMsg);
1599 }
1600
1601 static void
add_30R(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,ucp_tap_rec_t * tap_rec)1602 add_30R(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1603 {
1604 int offset = 1;
1605 guint intval;
1606
1607 intval = UcpHandleByte(hf_ucp_parm_ACK);
1608 if (intval == 'A') {
1609 UcpHandleTime(hf_ucp_parm_MVP); /* DDMMYYHHmm */
1610 tap_rec->result = 0;
1611 } else {
1612 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1613 }
1614 UcpHandleString(hf_ucp_parm_SM);
1615 }
1616
1617 static void
add_31O(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1618 add_31O(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1619 { /* SMT alert */
1620 int offset = 1;
1621
1622 UcpHandleString(hf_ucp_parm_AdC);
1623 UcpHandleInt(hf_ucp_parm_PID);
1624 }
1625
1626 #define add_31R(a, b, c, d) add_01R(a, b, c, d)
1627
1628 static void
add_5xO(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb)1629 add_5xO(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
1630 { /* 50-series operations */
1631 guint intval;
1632 int offset = 1;
1633 int tmpoff;
1634 proto_item *ti;
1635 tvbuff_t *tmptvb;
1636
1637 UcpHandleString(hf_ucp_parm_AdC);
1638 UcpHandleString(hf_ucp_parm_OAdC);
1639 UcpHandleString(hf_ucp_parm_AC);
1640 UcpHandleByte(hf_ucp_parm_NRq);
1641 UcpHandleString(hf_ucp_parm_NAdC);
1642 UcpHandleByte(hf_ucp_parm_NT);
1643 UcpHandleInt(hf_ucp_parm_NPID);
1644 UcpHandleByte(hf_ucp_parm_LRq);
1645 UcpHandleString(hf_ucp_parm_LRAd);
1646 UcpHandleInt(hf_ucp_parm_LPID);
1647 UcpHandleByte(hf_ucp_parm_DD);
1648 UcpHandleTime(hf_ucp_parm_DDT); /* DDMMYYHHmm */
1649 UcpHandleTime(hf_ucp_parm_VP); /* DDMMYYHHmm */
1650 UcpHandleString(hf_ucp_parm_RPID);
1651 UcpHandleTime(hf_ucp_parm_SCTS); /* DDMMYYhhmmss */
1652 UcpHandleByte(hf_ucp_parm_Dst);
1653 UcpHandleInt(hf_ucp_parm_Rsn);
1654 UcpHandleTime(hf_ucp_parm_DSCTS); /* DDMMYYhhmmss */
1655 intval = UcpHandleByte(hf_ucp_parm_MT);
1656 UcpHandleString(hf_ucp_parm_NB);
1657 if (intval != '3')
1658 UcpHandleData(hf_ucp_data_section);
1659 else
1660 UcpHandleIRAString(hf_ucp_parm_AMsg);
1661 UcpHandleByte(hf_ucp_parm_MMS);
1662 UcpHandleByte(hf_ucp_parm_PR);
1663 UcpHandleByte(hf_ucp_parm_DCs);
1664 UcpHandleByte(hf_ucp_parm_MCLs);
1665 UcpHandleByte(hf_ucp_parm_RPI);
1666 if (tvb_get_guint8(tvb, offset++) != '/') {
1667 proto_tree_add_string(tree, hf_ucp_parm_CPg, tvb, offset - 1,1,
1668 "(reserved for Code Page)");
1669 offset++;
1670 }
1671 if (tvb_get_guint8(tvb, offset++) != '/') {
1672 proto_tree_add_string(tree, hf_ucp_parm_RPLy, tvb, offset - 1,1,
1673 "(reserved for Reply type)");
1674 offset++;
1675 }
1676 UcpHandleString(hf_ucp_parm_OTOA);
1677 UcpHandleString(hf_ucp_parm_HPLMN);
1678 tmpoff = offset; /* Extra services */
1679 while (tvb_get_guint8(tvb, tmpoff++) != '/')
1680 ;
1681 if ((tmpoff - offset) > 1) {
1682 int len = tmpoff - offset - 1;
1683 proto_tree *subtree;
1684
1685 ti = proto_tree_add_item(tree, hf_ucp_parm_XSer, tvb, offset, len, ENC_NA);
1686 tmptvb = tvb_new_subset_length(tvb, offset, len + 1);
1687 subtree = proto_item_add_subtree(ti, ett_XSer);
1688 ucp_handle_XSer(subtree, tmptvb);
1689 }
1690 offset = tmpoff;
1691 UcpHandleDataString(hf_ucp_parm_RES4);
1692 UcpHandleDataString(hf_ucp_parm_RES5);
1693 }
1694
1695 #define add_5xR(a, b, c, d) add_30R(a, b, c, d)
1696
1697 static void
add_6xO(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,guint8 OT)1698 add_6xO(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint8 OT)
1699 { /* 60-series operations */
1700 int offset = 1;
1701
1702 UcpHandleString(hf_ucp_parm_OAdC);
1703 UcpHandleByte(hf_ucp_parm_OTON);
1704 UcpHandleByte(hf_ucp_parm_ONPI);
1705 if (OT == 60) {
1706 UcpHandleByte(hf_ucp_parm_STYP0);
1707 } else {
1708 UcpHandleByte(hf_ucp_parm_STYP1);
1709 }
1710 UcpHandleIRAString(hf_ucp_parm_PWD);
1711 UcpHandleIRAString(hf_ucp_parm_NPWD);
1712 UcpHandleString(hf_ucp_parm_VERS);
1713 UcpHandleString(hf_ucp_parm_LAdC);
1714 UcpHandleByte(hf_ucp_parm_LTON);
1715 UcpHandleByte(hf_ucp_parm_LNPI);
1716 if (OT == 60) {
1717 UcpHandleInt(hf_ucp_parm_OPID);
1718 }
1719 UcpHandleDataString(hf_ucp_parm_RES1);
1720 if (OT == 61) {
1721 UcpHandleDataString(hf_ucp_parm_RES2);
1722 }
1723 }
1724
1725 #define add_6xR(a, b, c, d) add_01R(a, b, c, d)
1726
1727 /*
1728 * End of convenient shorthands
1729 */
1730 #undef UcpHandleString
1731 #undef UcpHandleIRAString
1732 #undef UcpHandleByte
1733 #undef UcpHandleInt
1734 #undef UcpHandleTime
1735 #undef UcpHandleData
1736
1737 static guint
get_ucp_pdu_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)1738 get_ucp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1739 {
1740 guint intval=0;
1741 int i;
1742
1743 offset = offset + 4;
1744 for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
1745 intval = 10 * intval +
1746 (tvb_get_guint8(tvb, offset) - '0');
1747 offset++;
1748 }
1749
1750 return intval + 2;
1751 }
1752
1753 /*
1754 * The actual dissector
1755 */
1756
1757 /* We get here only with at least LEN+2 bytes in the buffer */
1758
1759 static int
dissect_ucp_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1760 dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1761 {
1762 int offset = 0; /* Offset in packet within tvbuff */
1763 guint8 O_R; /* Request or response */
1764 guint8 OT; /* Operation type */
1765 guint intval;
1766 int i;
1767 int result;
1768 int endpkt;
1769 ucp_tap_rec_t *tap_rec; /* Tap record */
1770
1771 /* Set up structures needed to add the protocol subtree and manage it */
1772 proto_item *ti;
1773 proto_item *sub_ti;
1774 proto_tree *ucp_tree;
1775 proto_tree *sub_tree;
1776 tvbuff_t *tmp_tvb;
1777
1778 /* Make entries in Protocol column */
1779 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
1780 col_clear(pinfo->cinfo, COL_INFO);
1781
1782 if (tvb_get_guint8(tvb, 0) != UCP_STX){
1783 proto_tree_add_expert(tree, pinfo, &ei_ucp_stx_missing, tvb, 0, -1);
1784 return tvb_captured_length(tvb);
1785 }
1786
1787 /* Get data needed for dissect_ucp_common */
1788 result = check_ucp(tvb, &endpkt);
1789
1790 O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
1791 OT = tvb_get_guint8(tvb, UCP_OT_OFFSET) - '0';
1792 OT = 10 * OT + (tvb_get_guint8(tvb, UCP_OT_OFFSET + 1) - '0');
1793
1794 /* Create Tap record */
1795 tap_rec = wmem_new0(wmem_packet_scope(), ucp_tap_rec_t);
1796 tap_rec->message_type = (O_R == 'O' ? 0 : 1);
1797 tap_rec->operation = OT;
1798
1799 /* Make entries in Info column on summary display */
1800 col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
1801 val_to_str_ext_const(OT, &vals_hdr_OT_ext, "unknown operation"),
1802 val_to_str(O_R, vals_hdr_O_R, "Unknown (%d)"));
1803 if (result == UCP_INV_CHK)
1804 col_append_str(pinfo->cinfo, COL_INFO, " [checksum invalid]");
1805
1806 /* In the interest of speed, if "tree" is NULL, don't do any work not
1807 necessary to generate protocol tree items. */
1808 if (tree) {
1809
1810 /* create display subtree for the protocol */
1811 ti = proto_tree_add_item(tree, proto_ucp, tvb, 0, -1, ENC_NA);
1812
1813 ucp_tree = proto_item_add_subtree(ti, ett_ucp);
1814 /*
1815 * Process the packet here.
1816 * Transaction number
1817 */
1818 offset++; /* Skip <stx> */
1819 intval = tvb_get_guint8(tvb, offset+0) - '0';
1820 intval = 10 * intval + (tvb_get_guint8(tvb, offset+1) - '0');
1821 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_TRN, tvb, offset,
1822 UCP_TRN_LEN, intval);
1823 offset += UCP_TRN_LEN + 1; /* Skip TN/ */
1824
1825 intval = 0;
1826 for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
1827 intval = 10 * intval +
1828 (tvb_get_guint8(tvb, offset+i) - '0');
1829 }
1830 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_LEN, tvb, offset,
1831 UCP_LEN_LEN, intval);
1832 offset += UCP_LEN_LEN + 1; /* skip LEN/ */
1833
1834 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_O_R, tvb, offset,
1835 UCP_O_R_LEN, O_R);
1836
1837 offset += UCP_O_R_LEN + 1; /* skip Operation_type/ */
1838
1839 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_OT, tvb, offset,
1840 UCP_OT_LEN, OT);
1841 offset += UCP_OT_LEN;
1842
1843 /*
1844 * Variable part starts here.
1845 */
1846
1847 tmp_tvb = tvb_new_subset_remaining(tvb, offset);
1848 sub_ti = proto_tree_add_item(ucp_tree, hf_ucp_oper_section, tvb,
1849 offset, endpkt - offset, ENC_NA);
1850 sub_tree = proto_item_add_subtree(sub_ti, ett_sub);
1851
1852 switch (OT) {
1853 case 0:
1854 O_R == 'O' ? add_00O(sub_tree, tmp_tvb) : add_00R(sub_tree, pinfo, tmp_tvb, tap_rec);
1855 break;
1856 case 1:
1857 O_R == 'O' ? add_01O(sub_tree, pinfo, tmp_tvb) : add_01R(sub_tree, pinfo, tmp_tvb, tap_rec);
1858 break;
1859 case 2:
1860 O_R == 'O' ? add_02O(sub_tree, pinfo, tmp_tvb) : add_02R(sub_tree, pinfo, tmp_tvb, tap_rec);
1861 break;
1862 case 3:
1863 O_R == 'O' ? add_03O(sub_tree, pinfo, tmp_tvb) : add_03R(sub_tree, pinfo, tmp_tvb, tap_rec);
1864 break;
1865 case 4:
1866 O_R == 'O' ? add_04O(sub_tree, tmp_tvb) : add_04R(sub_tree, pinfo, tmp_tvb, tap_rec);
1867 break;
1868 case 5:
1869 O_R == 'O' ? add_05O(sub_tree, pinfo, tmp_tvb) : add_05R(sub_tree, pinfo, tmp_tvb, tap_rec);
1870 break;
1871 case 6:
1872 O_R == 'O' ? add_06O(sub_tree, tmp_tvb) : add_06R(sub_tree, pinfo, tmp_tvb, tap_rec);
1873 break;
1874 case 7:
1875 O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree, pinfo, tmp_tvb, tap_rec);
1876 break;
1877 case 8:
1878 O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree, pinfo, tmp_tvb, tap_rec);
1879 break;
1880 case 9:
1881 O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree, pinfo, tmp_tvb, tap_rec);
1882 break;
1883 case 10:
1884 O_R == 'O' ? add_10O(sub_tree, pinfo, tmp_tvb) : add_10R(sub_tree, pinfo, tmp_tvb, tap_rec);
1885 break;
1886 case 11:
1887 O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree, pinfo, tmp_tvb, tap_rec);
1888 break;
1889 case 12:
1890 O_R == 'O' ? add_12O(sub_tree, pinfo, tmp_tvb) : add_12R(sub_tree, pinfo, tmp_tvb, tap_rec);
1891 break;
1892 case 13:
1893 O_R == 'O' ? add_13O(sub_tree, tmp_tvb) : add_13R(sub_tree, pinfo, tmp_tvb, tap_rec);
1894 break;
1895 case 14:
1896 O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree, pinfo, tmp_tvb, tap_rec);
1897 break;
1898 case 15:
1899 O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree, pinfo, tmp_tvb, tap_rec);
1900 break;
1901 case 16:
1902 O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree, pinfo, tmp_tvb, tap_rec);
1903 break;
1904 case 17:
1905 O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree, pinfo, tmp_tvb, tap_rec);
1906 break;
1907 case 18:
1908 O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree, pinfo, tmp_tvb, tap_rec);
1909 break;
1910 case 19:
1911 O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree, pinfo, tmp_tvb, tap_rec);
1912 break;
1913 case 20:
1914 O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree, pinfo, tmp_tvb, tap_rec);
1915 break;
1916 case 21:
1917 O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree, pinfo, tmp_tvb, tap_rec);
1918 break;
1919 case 22:
1920 O_R == 'O' ? add_22O(sub_tree, pinfo, tmp_tvb) : add_22R(sub_tree, pinfo, tmp_tvb, tap_rec);
1921 break;
1922 case 23:
1923 O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree, pinfo, tmp_tvb, tap_rec);
1924 break;
1925 case 24:
1926 O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree, pinfo, tmp_tvb, tap_rec);
1927 break;
1928 case 30:
1929 O_R == 'O' ? add_30O(sub_tree, pinfo, tmp_tvb) : add_30R(sub_tree, pinfo, tmp_tvb, tap_rec);
1930 break;
1931 case 31:
1932 O_R == 'O' ? add_31O(sub_tree, pinfo, tmp_tvb) : add_31R(sub_tree, pinfo, tmp_tvb, tap_rec);
1933 break;
1934 case 51: case 52: case 53: case 54: case 55: case 56: case 57:
1935 case 58:
1936 O_R == 'O' ? add_5xO(sub_tree, pinfo, tmp_tvb) : add_5xR(sub_tree, pinfo, tmp_tvb, tap_rec);
1937 break;
1938 case 60: case 61:
1939 O_R == 'O' ? add_6xO(sub_tree, pinfo, tmp_tvb,OT) : add_6xR(sub_tree, pinfo, tmp_tvb, tap_rec);
1940 break;
1941 default:
1942 break;
1943 }
1944 }
1945
1946 /* Queue packet for Tap */
1947 tap_queue_packet(ucp_tap, pinfo, tap_rec);
1948
1949 return tvb_captured_length(tvb);
1950 }
1951
1952 static int
dissect_ucp_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1953 dissect_ucp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1954 {
1955 tcp_dissect_pdus(tvb, pinfo, tree, ucp_desegment, UCP_HEADER_SIZE,
1956 get_ucp_pdu_len, dissect_ucp_common, data);
1957 return tvb_captured_length(tvb);
1958 }
1959
1960 /*
1961 * The heuristic dissector
1962 */
1963
1964 static gboolean
dissect_ucp_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1965 dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1966 {
1967 conversation_t *conversation;
1968
1969 /* Heuristic */
1970
1971 if (tvb_captured_length(tvb) < UCP_HEADER_SIZE)
1972 return FALSE;
1973
1974 if ((tvb_get_guint8(tvb, 0) != UCP_STX) ||
1975 (tvb_get_guint8(tvb, UCP_TRN_OFFSET + UCP_TRN_LEN) != '/') ||
1976 (tvb_get_guint8(tvb, UCP_LEN_OFFSET + UCP_LEN_LEN) != '/') ||
1977 (tvb_get_guint8(tvb, UCP_O_R_OFFSET + UCP_O_R_LEN) != '/') ||
1978 (tvb_get_guint8(tvb, UCP_OT_OFFSET + UCP_OT_LEN) != '/'))
1979 return FALSE;
1980
1981 if (try_val_to_str(tvb_get_guint8(tvb, UCP_O_R_OFFSET), vals_hdr_O_R) == NULL)
1982 return FALSE;
1983
1984 /*
1985 * Ok, looks like a valid packet
1986 */
1987
1988 /* Set up a conversation with attached dissector so dissect_ucp_heur
1989 * won't be called any more for this TCP connection.
1990 */
1991
1992 conversation = find_or_create_conversation(pinfo);
1993 conversation_set_dissector(conversation, ucp_handle);
1994
1995 dissect_ucp_tcp(tvb, pinfo, tree, data);
1996
1997 return TRUE;
1998 }
1999
2000 /* Register the protocol with Wireshark */
2001 void
proto_register_ucp(void)2002 proto_register_ucp(void)
2003 {
2004
2005 /* Setup list of fields */
2006 static hf_register_info hf[] = {
2007 { &hf_ucp_hdr_TRN,
2008 { "Transaction Reference Number", "ucp.hdr.TRN",
2009 FT_UINT8, BASE_DEC, NULL, 0x00,
2010 "Transaction number for this command, used in windowing.",
2011 HFILL
2012 }
2013 },
2014 { &hf_ucp_hdr_LEN,
2015 { "Length", "ucp.hdr.LEN",
2016 FT_UINT16, BASE_DEC, NULL, 0x00,
2017 "Total number of characters between <stx>...<etx>.",
2018 HFILL
2019 }
2020 },
2021 { &hf_ucp_hdr_O_R,
2022 { "Type", "ucp.hdr.O_R",
2023 FT_CHAR, BASE_HEX, VALS(vals_hdr_O_R), 0x00,
2024 "Your basic 'is a request or response'.",
2025 HFILL
2026 }
2027 },
2028 { &hf_ucp_hdr_OT,
2029 { "Operation", "ucp.hdr.OT",
2030 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &vals_hdr_OT_ext, 0x00,
2031 "The operation that is requested with this message.",
2032 HFILL
2033 }
2034 },
2035 { &hf_ucp_oper_section,
2036 { "Data", "ucp.parm",
2037 FT_NONE, BASE_NONE, NULL, 0x00,
2038 "The actual content of the operation.",
2039 HFILL
2040 }
2041 },
2042 { &hf_ucp_parm_AdC,
2043 { "AdC", "ucp.parm.AdC",
2044 FT_STRING, BASE_NONE, NULL, 0x00,
2045 "Address code recipient.",
2046 HFILL
2047 }
2048 },
2049 { &hf_ucp_parm_OAdC,
2050 { "OAdC", "ucp.parm.OAdC",
2051 FT_STRING, BASE_NONE, NULL, 0x00,
2052 "Address code originator.",
2053 HFILL
2054 }
2055 },
2056 { &hf_ucp_parm_DAdC,
2057 { "DAdC", "ucp.parm.DAdC",
2058 FT_STRING, BASE_NONE, NULL, 0x00,
2059 "Diverted address code.",
2060 HFILL
2061 }
2062 },
2063 { &hf_ucp_parm_AC,
2064 { "AC", "ucp.parm.AC",
2065 FT_STRING, BASE_NONE, NULL, 0x00,
2066 "Authentication code.",
2067 HFILL
2068 }
2069 },
2070 { &hf_ucp_parm_OAC,
2071 { "OAC", "ucp.parm.OAC",
2072 FT_STRING, BASE_NONE, NULL, 0x00,
2073 "Authentication code, originator.",
2074 HFILL
2075 }
2076 },
2077 { &hf_ucp_parm_NAC,
2078 { "NAC", "ucp.parm.NAC",
2079 FT_STRING, BASE_NONE, NULL, 0x00,
2080 "New authentication code.",
2081 HFILL
2082 }
2083 },
2084 { &hf_ucp_parm_BAS,
2085 { "BAS", "ucp.parm.BAS",
2086 FT_CHAR, BASE_HEX, VALS(vals_parm_BAS), 0x00,
2087 "Barring status flag.",
2088 HFILL
2089 }
2090 },
2091 { &hf_ucp_parm_LAR,
2092 { "LAR", "ucp.parm.LAR",
2093 FT_CHAR, BASE_HEX, VALS(vals_parm_LAR), 0x00,
2094 "Leg. code for all calls flag.",
2095 HFILL
2096 }
2097 },
2098 { &hf_ucp_parm_LAC,
2099 { "LAC", "ucp.parm.LAC",
2100 FT_STRING, BASE_NONE, NULL, 0x00,
2101 "New leg. code for all calls.",
2102 HFILL
2103 }
2104 },
2105 { &hf_ucp_parm_L1R,
2106 { "L1R", "ucp.parm.L1R",
2107 FT_CHAR, BASE_HEX, VALS(vals_parm_L1R), 0x00,
2108 "Leg. code for priority 1 flag.",
2109 HFILL
2110 }
2111 },
2112 { &hf_ucp_parm_L1P,
2113 { "L1P", "ucp.parm.L1P",
2114 FT_STRING, BASE_NONE, NULL, 0x00,
2115 "New leg. code for level 1 priority.",
2116 HFILL
2117 }
2118 },
2119 { &hf_ucp_parm_L3R,
2120 { "L3R", "ucp.parm.L3R",
2121 FT_CHAR, BASE_HEX, VALS(vals_parm_L3R), 0x00,
2122 "Leg. code for priority 3 flag.",
2123 HFILL
2124 }
2125 },
2126 { &hf_ucp_parm_L3P,
2127 { "L3P", "ucp.parm.L3P",
2128 FT_STRING, BASE_NONE, NULL, 0x00,
2129 "New leg. code for level 3 priority.",
2130 HFILL
2131 }
2132 },
2133 { &hf_ucp_parm_LCR,
2134 { "LCR", "ucp.parm.LCR",
2135 FT_CHAR, BASE_HEX, VALS(vals_parm_LCR), 0x00,
2136 "Leg. code for reverse charging flag.",
2137 HFILL
2138 }
2139 },
2140 { &hf_ucp_parm_LUR,
2141 { "LUR", "ucp.parm.LUR",
2142 FT_CHAR, BASE_HEX, VALS(vals_parm_LUR), 0x00,
2143 "Leg. code for urgent message flag.",
2144 HFILL
2145 }
2146 },
2147 { &hf_ucp_parm_LRR,
2148 { "LRR", "ucp.parm.LRR",
2149 FT_CHAR, BASE_HEX, VALS(vals_parm_LRR), 0x00,
2150 "Leg. code for repetition flag.",
2151 HFILL
2152 }
2153 },
2154 { &hf_ucp_parm_RT,
2155 { "RT", "ucp.parm.RT",
2156 FT_CHAR, BASE_HEX, VALS(vals_parm_RT), 0x00,
2157 "Receiver type.",
2158 HFILL
2159 }
2160 },
2161 { &hf_ucp_parm_NoN,
2162 { "NoN", "ucp.parm.NoN",
2163 FT_UINT16, BASE_DEC, NULL, 0x00,
2164 "Maximum number of numerical characters accepted.",
2165 HFILL
2166 }
2167 },
2168 { &hf_ucp_parm_NoA,
2169 { "NoA", "ucp.parm.NoA",
2170 FT_UINT16, BASE_DEC, NULL, 0x00,
2171 "Maximum number of alphanumerical characters accepted.",
2172 HFILL
2173 }
2174 },
2175 { &hf_ucp_parm_NoB,
2176 { "NoB", "ucp.parm.NoB",
2177 FT_UINT16, BASE_DEC, NULL, 0x00,
2178 "Maximum number of data bits accepted.",
2179 HFILL
2180 }
2181 },
2182 { &hf_ucp_parm_PNC,
2183 { "PNC", "ucp.parm.PNC",
2184 FT_CHAR, BASE_HEX, VALS(vals_parm_PNC), 0x00,
2185 "Paging network controller.",
2186 HFILL
2187 }
2188 },
2189 { &hf_ucp_parm_AMsg,
2190 { "AMsg", "ucp.parm.AMsg",
2191 FT_STRING, BASE_NONE, NULL, 0x00,
2192 "The alphanumeric message that is being sent.",
2193 HFILL
2194 }
2195 },
2196 { &hf_ucp_parm_LNo,
2197 { "LNo", "ucp.parm.LNo",
2198 FT_STRING, BASE_NONE, NULL, 0x00,
2199 "Standard text list number requested by calling party.",
2200 HFILL
2201 }
2202 },
2203 { &hf_ucp_parm_LST,
2204 { "LST", "ucp.parm.LST",
2205 FT_STRING, BASE_NONE, NULL, 0x00,
2206 "Legitimisation code for standard text.",
2207 HFILL
2208 }
2209 },
2210 { &hf_ucp_parm_TNo,
2211 { "TNo", "ucp.parm.TNo",
2212 FT_STRING, BASE_NONE, NULL, 0x00,
2213 "Standard text number requested by calling party.",
2214 HFILL
2215 }
2216 },
2217 { &hf_ucp_parm_CS,
2218 { "CS", "ucp.parm.CS",
2219 FT_UINT8, BASE_DEC, NULL, 0x00,
2220 "Additional character set number.",
2221 HFILL
2222 }
2223 },
2224 { &hf_ucp_parm_PID,
2225 { "PID", "ucp.parm.PID",
2226 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2227 "SMT PID value.",
2228 HFILL
2229 }
2230 },
2231 { &hf_ucp_parm_NPL,
2232 { "NPL", "ucp.parm.NPL",
2233 FT_UINT16, BASE_DEC, NULL, 0x00,
2234 "Number of parameters in the following list.",
2235 HFILL
2236 }
2237 },
2238 { &hf_ucp_parm_GA,
2239 { "GA", "ucp.parm.GA",
2240 FT_STRING, BASE_NONE, NULL, 0x00,
2241 "GA?? haven't got a clue.",
2242 HFILL
2243 }
2244 },
2245 { &hf_ucp_parm_RP,
2246 { "RP", "ucp.parm.RP",
2247 FT_CHAR, BASE_HEX, VALS(vals_parm_RP), 0x00,
2248 "Repetition requested.",
2249 HFILL
2250 }
2251 },
2252 { &hf_ucp_parm_LRP,
2253 { "LRP", "ucp.parm.LRP",
2254 FT_STRING, BASE_NONE, NULL, 0x00,
2255 "Legitimisation code for repetition.",
2256 HFILL
2257 }
2258 },
2259 { &hf_ucp_parm_PR,
2260 { "PR", "ucp.parm.PR",
2261 FT_UINT8, BASE_DEC, NULL, 0x00,
2262 "Priority requested.",
2263 HFILL
2264 }
2265 },
2266 { &hf_ucp_parm_LPR,
2267 { "LPR", "ucp.parm.LPR",
2268 FT_STRING, BASE_NONE, NULL, 0x00,
2269 "Legitimisation code for priority requested.",
2270 HFILL
2271 }
2272 },
2273 { &hf_ucp_parm_UM,
2274 { "UM", "ucp.parm.UM",
2275 FT_CHAR, BASE_HEX, VALS(vals_parm_UM), 0x00,
2276 "Urgent message indicator.",
2277 HFILL
2278 }
2279 },
2280 { &hf_ucp_parm_LUM,
2281 { "LUM", "ucp.parm.LUM",
2282 FT_STRING, BASE_NONE, NULL, 0x00,
2283 "Legitimisation code for urgent message.",
2284 HFILL
2285 }
2286 },
2287 { &hf_ucp_parm_RC,
2288 { "RC", "ucp.parm.RC",
2289 FT_CHAR, BASE_HEX, VALS(vals_parm_RC), 0x00,
2290 "Reverse charging request.",
2291 HFILL
2292 }
2293 },
2294 { &hf_ucp_parm_LRC,
2295 { "LRC", "ucp.parm.LRC",
2296 FT_STRING, BASE_NONE, NULL, 0x00,
2297 "Legitimisation code for reverse charging.",
2298 HFILL
2299 }
2300 },
2301 { &hf_ucp_parm_NRq,
2302 { "NRq", "ucp.parm.NRq",
2303 FT_CHAR, BASE_HEX, VALS(vals_parm_NRq), 0x00,
2304 "Notification request.",
2305 HFILL
2306 }
2307 },
2308 { &hf_ucp_parm_GAdC,
2309 { "GAdC", "ucp.parm.GAdC",
2310 FT_STRING, BASE_NONE, NULL, 0x00,
2311 "Group address code.",
2312 HFILL
2313 }
2314 },
2315 { &hf_ucp_parm_A_D,
2316 { "A_D", "ucp.parm.A_D",
2317 FT_CHAR, BASE_HEX, VALS(vals_parm_A_D), 0x00,
2318 "Add to/delete from fixed subscriber address list record.",
2319 HFILL
2320 }
2321 },
2322 { &hf_ucp_parm_CT,
2323 { "CT", "ucp.parm.CT",
2324 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2325 "Accumulated charges timestamp.",
2326 HFILL
2327 }
2328 },
2329 { &hf_ucp_parm_AAC,
2330 { "AAC", "ucp.parm.AAC",
2331 FT_STRING, BASE_NONE, NULL, 0x00,
2332 "Accumulated charges.",
2333 HFILL
2334 }
2335 },
2336 { &hf_ucp_parm_MNo,
2337 { "MNo", "ucp.parm.MNo",
2338 FT_STRING, BASE_NONE, NULL, 0x00,
2339 "Message number.",
2340 HFILL
2341 }
2342 },
2343 { &hf_ucp_parm_R_T,
2344 { "R_T", "ucp.parm.R_T",
2345 FT_CHAR, BASE_HEX, VALS(vals_parm_R_T), 0x00,
2346 "Message number.",
2347 HFILL
2348 }
2349 },
2350 { &hf_ucp_parm_NAdC,
2351 { "NAdC", "ucp.parm.NAdC",
2352 FT_STRING, BASE_NONE, NULL, 0x00,
2353 "Notification address.",
2354 HFILL
2355 }
2356 },
2357 { &hf_ucp_parm_NT,
2358 { "NT", "ucp.parm.NT",
2359 FT_CHAR, BASE_HEX, VALS(vals_parm_NT), 0x00,
2360 "Notification type.",
2361 HFILL
2362 }
2363 },
2364 { &hf_ucp_parm_IVR5x,
2365 { "IVR5x", "ucp.parm.IVR5x",
2366 FT_STRING, BASE_NONE, NULL, 0x00,
2367 "UCP release number supported/accepted.",
2368 HFILL
2369 }
2370 },
2371 { &hf_ucp_parm_REQ_OT,
2372 { "REQ_OT", "ucp.parm.REQ_OT",
2373 FT_CHAR, BASE_HEX, VALS(vals_parm_REQ_OT), 0x00,
2374 "UCP release number supported/accepted.",
2375 HFILL
2376 }
2377 },
2378 { &hf_ucp_parm_SSTAT,
2379 { "SSTAT", "ucp.parm.SSTAT",
2380 FT_CHAR, BASE_HEX, VALS(vals_parm_SSTAT), 0x00,
2381 "Supplementary services for which status is requested.",
2382 HFILL
2383 }
2384 },
2385 { &hf_ucp_parm_LMN,
2386 { "LMN", "ucp.parm.LMN",
2387 FT_UINT8, BASE_DEC, NULL, 0x00,
2388 "Last message number.",
2389 HFILL
2390 }
2391 },
2392 { &hf_ucp_parm_NMESS,
2393 { "NMESS", "ucp.parm.NMESS",
2394 FT_UINT8, BASE_DEC, NULL, 0x00,
2395 "Number of stored messages.",
2396 HFILL
2397 }
2398 },
2399 { &hf_ucp_parm_NPID,
2400 { "NPID", "ucp.parm.NPID",
2401 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2402 "Notification PID value.",
2403 HFILL
2404 }
2405 },
2406 { &hf_ucp_parm_LRq,
2407 { "LRq", "ucp.parm.LRq",
2408 FT_CHAR, BASE_HEX, VALS(vals_parm_LRq), 0x00,
2409 "Last resort address request.",
2410 HFILL
2411 }
2412 },
2413 { &hf_ucp_parm_LRAd,
2414 { "LRAd", "ucp.parm.LRAd",
2415 FT_STRING, BASE_NONE, NULL, 0x00,
2416 "Last resort address.",
2417 HFILL
2418 }
2419 },
2420 { &hf_ucp_parm_LPID,
2421 { "LPID", "ucp.parm.LPID",
2422 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2423 "Last resort PID value.",
2424 HFILL
2425 }
2426 },
2427 { &hf_ucp_parm_DD,
2428 { "DD", "ucp.parm.DD",
2429 FT_CHAR, BASE_HEX, VALS(vals_parm_DD), 0x00,
2430 "Deferred delivery requested.",
2431 HFILL
2432 }
2433 },
2434 { &hf_ucp_parm_DDT,
2435 { "DDT", "ucp.parm.DDT",
2436 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2437 "Deferred delivery time.",
2438 HFILL
2439 }
2440 },
2441 { &hf_ucp_parm_STx,
2442 { "STx", "ucp.parm.STx",
2443 FT_NONE, BASE_NONE, NULL, 0x00,
2444 "Standard text.",
2445 HFILL
2446 }
2447 },
2448 { &hf_ucp_parm_ST,
2449 { "ST", "ucp.parm.ST",
2450 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2451 "Start time.",
2452 HFILL
2453 }
2454 },
2455 { &hf_ucp_parm_SP,
2456 { "SP", "ucp.parm.SP",
2457 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2458 "Stop time.",
2459 HFILL
2460 }
2461 },
2462 { &hf_ucp_parm_VP,
2463 { "VP", "ucp.parm.VP",
2464 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2465 "Validity period.",
2466 HFILL
2467 }
2468 },
2469 { &hf_ucp_parm_RPID,
2470 { "RPID", "ucp.parm.RPID",
2471 FT_STRING, BASE_NONE, NULL, 0x00,
2472 "Replace PID",
2473 HFILL
2474 }
2475 },
2476 { &hf_ucp_parm_SCTS,
2477 { "SCTS", "ucp.parm.SCTS",
2478 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2479 "Service Centre timestamp.",
2480 HFILL
2481 }
2482 },
2483 { &hf_ucp_parm_Dst,
2484 { "Dst", "ucp.parm.Dst",
2485 FT_CHAR, BASE_HEX, VALS(vals_parm_Dst), 0x00,
2486 "Delivery status.",
2487 HFILL
2488 }
2489 },
2490 { &hf_ucp_parm_Rsn,
2491 { "Rsn", "ucp.parm.Rsn",
2492 FT_UINT16, BASE_DEC | BASE_EXT_STRING, &vals_parm_Rsn_ext, 0x00,
2493 "Reason code.",
2494 HFILL
2495 }
2496 },
2497 { &hf_ucp_parm_DSCTS,
2498 { "DSCTS", "ucp.parm.DSCTS",
2499 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2500 "Delivery timestamp.",
2501 HFILL
2502 }
2503 },
2504 { &hf_ucp_parm_MT,
2505 { "MT", "ucp.parm.MT",
2506 FT_CHAR, BASE_HEX, VALS(vals_parm_MT), 0x00,
2507 "Message type.",
2508 HFILL
2509 }
2510 },
2511 { &hf_ucp_parm_NB,
2512 { "NB", "ucp.parm.NB",
2513 FT_STRING, BASE_NONE, NULL, 0x00,
2514 "No. of bits in Transparent Data (TD) message.",
2515 HFILL
2516 }
2517 },
2518 { &hf_ucp_data_section,
2519 { "Data", "ucp.message",
2520 FT_NONE, BASE_NONE, NULL, 0x00,
2521 "The actual message or data.",
2522 HFILL
2523 }
2524 },
2525 { &hf_ucp_parm_MMS,
2526 { "MMS", "ucp.parm.MMS",
2527 FT_UINT8, BASE_DEC, NULL, 0x00,
2528 "More messages to send.",
2529 HFILL
2530 }
2531 },
2532 { &hf_ucp_parm_DCs,
2533 { "DCs", "ucp.parm.DCs",
2534 FT_CHAR, BASE_HEX, VALS(vals_parm_DCs), 0x00,
2535 "Data coding scheme (deprecated).",
2536 HFILL
2537 }
2538 },
2539 { &hf_ucp_parm_MCLs,
2540 { "MCLs", "ucp.parm.MCLs",
2541 FT_CHAR, BASE_HEX, VALS(vals_parm_MCLs), 0x00,
2542 "Message class.",
2543 HFILL
2544 }
2545 },
2546 { &hf_ucp_parm_RPI,
2547 { "RPI", "ucp.parm.RPI",
2548 FT_CHAR, BASE_HEX, VALS(vals_parm_RPI), 0x00,
2549 "Reply path.",
2550 HFILL
2551 }
2552 },
2553 { &hf_ucp_parm_CPg,
2554 { "CPg", "ucp.parm.CPg",
2555 FT_STRING, BASE_NONE, NULL, 0x00,
2556 "Reserved for Code Page.",
2557 HFILL
2558 }
2559 },
2560 { &hf_ucp_parm_RPLy,
2561 { "RPLy", "ucp.parm.RPLy",
2562 FT_STRING, BASE_NONE, NULL, 0x00,
2563 "Reserved for Reply type.",
2564 HFILL
2565 }
2566 },
2567 { &hf_ucp_parm_OTOA,
2568 { "OTOA", "ucp.parm.OTOA",
2569 FT_STRING, BASE_NONE, NULL, 0x00,
2570 "Originator Type Of Address.",
2571 HFILL
2572 }
2573 },
2574 { &hf_ucp_parm_HPLMN,
2575 { "HPLMN", "ucp.parm.HPLMN",
2576 FT_STRING, BASE_NONE, NULL, 0x00,
2577 "Home PLMN address.",
2578 HFILL
2579 }
2580 },
2581 { &hf_ucp_parm_XSer,
2582 { "Extra services:", "ucp.parm.XSer",
2583 FT_NONE, BASE_NONE, NULL, 0x00,
2584 "Extra services.",
2585 HFILL
2586 }
2587 },
2588 { &hf_ucp_parm_RES4,
2589 { "RES4", "ucp.parm.RES4",
2590 FT_STRING, BASE_NONE, NULL, 0x00,
2591 "Reserved for future use.",
2592 HFILL
2593 }
2594 },
2595 { &hf_ucp_parm_RES5,
2596 { "RES5", "ucp.parm.RES5",
2597 FT_STRING, BASE_NONE, NULL, 0x00,
2598 "Reserved for future use.",
2599 HFILL
2600 }
2601 },
2602 { &hf_ucp_parm_OTON,
2603 { "OTON", "ucp.parm.OTON",
2604 FT_CHAR, BASE_HEX, VALS(vals_parm_OTON), 0x00,
2605 "Originator type of number.",
2606 HFILL
2607 }
2608 },
2609 { &hf_ucp_parm_ONPI,
2610 { "ONPI", "ucp.parm.ONPI",
2611 FT_CHAR, BASE_HEX, VALS(vals_parm_ONPI), 0x00,
2612 "Originator numbering plan id.",
2613 HFILL
2614 }
2615 },
2616 { &hf_ucp_parm_STYP0,
2617 { "STYP0", "ucp.parm.STYP0",
2618 FT_CHAR, BASE_HEX, VALS(vals_parm_STYP0), 0x00,
2619 "Subtype of operation.",
2620 HFILL
2621 }
2622 },
2623 { &hf_ucp_parm_STYP1,
2624 { "STYP1", "ucp.parm.STYP1",
2625 FT_CHAR, BASE_HEX, VALS(vals_parm_STYP1), 0x00,
2626 "Subtype of operation.",
2627 HFILL
2628 }
2629 },
2630 { &hf_ucp_parm_PWD,
2631 { "PWD", "ucp.parm.PWD",
2632 FT_STRING, BASE_NONE, NULL, 0x00,
2633 "Current password.",
2634 HFILL
2635 }
2636 },
2637 { &hf_ucp_parm_NPWD,
2638 { "NPWD", "ucp.parm.NPWD",
2639 FT_STRING, BASE_NONE, NULL, 0x00,
2640 "New password.",
2641 HFILL
2642 }
2643 },
2644 { &hf_ucp_parm_VERS,
2645 { "VERS", "ucp.parm.VERS",
2646 FT_STRING, BASE_NONE, NULL, 0x00,
2647 "Version number.",
2648 HFILL
2649 }
2650 },
2651 { &hf_ucp_parm_LAdC,
2652 { "LAdC", "ucp.parm.LAdC",
2653 FT_STRING, BASE_NONE, NULL, 0x00,
2654 "Address for VSMSC list operation.",
2655 HFILL
2656 }
2657 },
2658 { &hf_ucp_parm_LTON,
2659 { "LTON", "ucp.parm.LTON",
2660 FT_UINT8, BASE_DEC, NULL, 0x00,
2661 "Type of number list address.",
2662 HFILL
2663 }
2664 },
2665 { &hf_ucp_parm_LNPI,
2666 { "LNPI", "ucp.parm.LNPI",
2667 FT_UINT8, BASE_DEC, NULL, 0x00,
2668 "Numbering plan id. list address.",
2669 HFILL
2670 }
2671 },
2672 { &hf_ucp_parm_OPID,
2673 { "OPID", "ucp.parm.OPID",
2674 FT_UINT8, BASE_DEC, VALS(vals_parm_OPID), 0x00,
2675 "Originator protocol identifier.",
2676 HFILL
2677 }
2678 },
2679 { &hf_ucp_parm_RES1,
2680 { "RES1", "ucp.parm.RES1",
2681 FT_STRING, BASE_NONE, NULL, 0x00,
2682 "Reserved for future use.",
2683 HFILL
2684 }
2685 },
2686 { &hf_ucp_parm_RES2,
2687 { "RES2", "ucp.parm.RES2",
2688 FT_STRING, BASE_NONE, NULL, 0x00,
2689 "Reserved for future use.",
2690 HFILL
2691 }
2692 },
2693 { &hf_ucp_parm_ACK,
2694 { "(N)Ack", "ucp.parm.ACK",
2695 FT_CHAR, BASE_HEX, VALS(vals_parm_ACK), 0x00,
2696 "Positive or negative acknowledge of the operation.",
2697 HFILL
2698 }
2699 },
2700 { &hf_ucp_parm_MVP,
2701 { "MVP", "ucp.parm.MVP",
2702 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2703 "Modified validity period.",
2704 HFILL
2705 }
2706 },
2707 { &hf_ucp_parm_EC,
2708 { "Error code", "ucp.parm.EC",
2709 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &vals_parm_EC_ext, 0x00,
2710 "The result of the requested operation.",
2711 HFILL
2712 }
2713 },
2714 { &hf_ucp_parm_SM,
2715 { "SM", "ucp.parm.SM",
2716 FT_STRING, BASE_NONE, NULL, 0x00,
2717 "System message.",
2718 HFILL
2719 }
2720 },
2721 { &hf_ucp_ga_roaming,
2722 { "GA roaming definitions", "ucp.parm.ga_roaming",
2723 FT_NONE, BASE_NONE, NULL, 0x00,
2724 NULL,
2725 HFILL
2726 }
2727 },
2728 { &hf_ucp_call_barring,
2729 { "Call barring definitions", "ucp.parm.call_barring",
2730 FT_NONE, BASE_NONE, NULL, 0x00,
2731 NULL,
2732 HFILL
2733 }
2734 },
2735 { &hf_ucp_deferred_delivery,
2736 { "Deferred delivery definitions", "ucp.parm.deferred_delivery",
2737 FT_NONE, BASE_NONE, NULL, 0x00,
2738 NULL,
2739 HFILL
2740 }
2741 },
2742 { &hf_ucp_diversion,
2743 { "Diversion definitions", "ucp.parm.diversion",
2744 FT_NONE, BASE_NONE, NULL, 0x00,
2745 NULL,
2746 HFILL
2747 }
2748 },
2749 { &hf_ucp_not_subscribed,
2750 { "Not subscribed/not allowed", "ucp.parm.not_subscribed",
2751 FT_NONE, BASE_NONE, NULL, 0x00,
2752 NULL,
2753 HFILL
2754 }
2755 },
2756 { &hf_xser_service,
2757 { "Type of service", "ucp.xser.service",
2758 FT_UINT8, BASE_HEX | BASE_EXT_STRING, &vals_xser_service_ext, 0x00,
2759 "The type of service specified.",
2760 HFILL
2761 }
2762 },
2763 { &hf_xser_length,
2764 { "Length", "ucp.xser.length",
2765 FT_UINT16, BASE_DEC, NULL, 0x00,
2766 NULL,
2767 HFILL
2768 }
2769 },
2770 { &hf_xser_data,
2771 { "Data", "ucp.xser.data",
2772 FT_STRING, BASE_NONE, NULL, 0x00,
2773 NULL,
2774 HFILL
2775 }
2776 },
2777 };
2778 /* Setup protocol subtree array */
2779 static gint *ett[] = {
2780 &ett_ucp,
2781 &ett_sub,
2782 &ett_XSer
2783 };
2784
2785 static ei_register_info ei[] = {
2786 { &ei_ucp_stx_missing, { "ucp.stx_missing", PI_MALFORMED, PI_ERROR, "UCP_STX missing, this is not a new packet", EXPFILL }},
2787 { &ei_ucp_intstring_invalid, { "ucp.intstring.invalid", PI_MALFORMED, PI_ERROR, "Invalid integer string", EXPFILL }}
2788 };
2789
2790 module_t *ucp_module;
2791 expert_module_t* expert_ucp;
2792
2793 /* Register the protocol name and description */
2794 proto_ucp = proto_register_protocol("Universal Computer Protocol",
2795 "UCP", "ucp");
2796
2797 /* Required function calls to register header fields and subtrees used */
2798 proto_register_field_array(proto_ucp, hf, array_length(hf));
2799 proto_register_subtree_array(ett, array_length(ett));
2800 expert_ucp = expert_register_protocol(proto_ucp);
2801 expert_register_field_array(expert_ucp, ei, array_length(ei));
2802
2803 /* Register for tapping */
2804 ucp_tap = register_tap("ucp");
2805
2806 /* register preferences */
2807 ucp_module = prefs_register_protocol(proto_ucp, NULL);
2808 prefs_register_bool_preference(ucp_module, "desegment_ucp_messages",
2809 "Reassemble UCP messages spanning multiple TCP segments",
2810 "Whether the UCP dissector should reassemble messages spanning"
2811 " multiple TCP segments."
2812 " To use this option, you must also enable "
2813 "\"Allow subdissectors to reassemble TCP streams\" in the "
2814 "TCP protocol settings.",
2815 &ucp_desegment);
2816 }
2817
2818 void
proto_reg_handoff_ucp(void)2819 proto_reg_handoff_ucp(void)
2820 {
2821 /*
2822 * UCP can be spoken on any port so, when not on a specific port, try heuristic
2823 * whenever TCP is spoken.
2824 */
2825 heur_dissector_add("tcp", dissect_ucp_heur, "UCP over TCP", "ucp_tcp", proto_ucp, HEURISTIC_ENABLE);
2826
2827 /*
2828 * Also register as a dissector that can be selected by a TCP port number via "decode as".
2829 */
2830 ucp_handle = create_dissector_handle(dissect_ucp_tcp, proto_ucp);
2831 dissector_add_for_decode_as_with_preference("tcp.port", ucp_handle);
2832
2833 /* Tapping setup */
2834 stats_tree_register_with_group("ucp", "ucp_messages", "_UCP Messages", 0,
2835 ucp_stats_tree_per_packet, ucp_stats_tree_init,
2836 NULL, REGISTER_STAT_GROUP_TELEPHONY);
2837 }
2838
2839 /*
2840 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2841 *
2842 * Local variables:
2843 * c-basic-offset: 4
2844 * tab-width: 8
2845 * indent-tabs-mode: nil
2846 * End:
2847 *
2848 * vi: set shiftwidth=4 tabstop=8 expandtab:
2849 * :indentSize=4:tabSize=8:noTabs=true:
2850 */
2851