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