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