2 * Routines for Universal Computer Protocol dissection
3 * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Dissector of a UCP (Universal Computer Protocol) PDU, as defined for the
27 * ERMES paging system in ETS 300 133-3 (2nd final draft, September 1997,
29 * Includes the extension of EMI-UCP interface (V4.0, May 2001, www.cmgwds.com)
31 * Support for statistics using the Stats Tree API added by
32 * Abhik Sarkar <sarkar.abhik@gmail.com>
47 #include <epan/packet.h>
48 #include <epan/prefs.h>
49 #include <epan/emem.h>
50 #include <epan/conversation.h>
51 #include <epan/stats_tree.h>
53 #include "packet-tcp.h"
56 static void dissect_ucp_tcp(tvbuff_t *, packet_info *, proto_tree *);
57 static void dissect_ucp_common(tvbuff_t *, packet_info *, proto_tree *);
60 typedef struct _ucp_tap_rec_t {
61 guint message_type; /* 0 = Operation; 1 = Result */
62 guint operation; /* Operation Type */
63 guint result; /* 0 = Success; Non 0 = Error Code */
67 static gboolean ucp_desegment = TRUE;
69 /* STX + TRN(2 num. char.) + / + LEN(5 num. char.) + / + 'O'/'R' + / + OT(2 num. char.) + / */
70 #define UCP_HEADER_SIZE 15
73 * Convert ASCII-hex character to binary equivalent. No checks, assume
74 * is valid hex character.
76 #define AHex2Bin(n) (((n) & 0x40) ? ((n) & 0x0F) + 9 : ((n) & 0x0F))
78 #define UCP_STX 0x02 /* Start of UCP PDU */
79 #define UCP_ETX 0x03 /* End of UCP PDU */
81 #define UCP_MALFORMED -1 /* Not a valid PDU */
82 #define UCP_INV_CHK -2 /* Incorrect checksum */
84 #define UCP_TRN_OFFSET 1
85 #define UCP_LEN_OFFSET 4
86 #define UCP_O_R_OFFSET 10 /* Location of O/R field */
87 #define UCP_OT_OFFSET 12 /* Location of OT field */
89 #define UCP_TRN_LEN 2 /* Length of TRN-field */
90 #define UCP_LEN_LEN 5 /* Length of LEN-field */
91 #define UCP_O_R_LEN 1 /* Length of O/R-field */
92 #define UCP_OT_LEN 2 /* Length of OT-field */
95 static dissector_handle_t ucp_handle;
98 * Initialize the protocol and registered fields
100 * Header (fixed) section
102 static int proto_ucp = -1;
104 static int hf_ucp_hdr_TRN = -1;
105 static int hf_ucp_hdr_LEN = -1;
106 static int hf_ucp_hdr_O_R = -1;
107 static int hf_ucp_hdr_OT = -1;
112 static int st_ucp_messages = -1;
113 static int st_ucp_ops = -1;
114 static int st_ucp_res = -1;
115 static int st_ucp_results = -1;
116 static int st_ucp_results_pos = -1;
117 static int st_ucp_results_neg = -1;
119 static gchar* st_str_ucp = "UCP Messages";
120 static gchar* st_str_ops = "Operations";
121 static gchar* st_str_res = "Results";
122 static gchar* st_str_ucp_res = "UCP Results Acks/Nacks";
123 static gchar* st_str_pos = "Positive";
124 static gchar* st_str_neg = "Negative";
127 * Data (variable) section
129 static int hf_ucp_oper_section = -1;
130 static int hf_ucp_parm_AdC = -1;
131 static int hf_ucp_parm_OAdC = -1;
132 static int hf_ucp_parm_DAdC = -1;
133 static int hf_ucp_parm_AC = -1;
134 static int hf_ucp_parm_OAC = -1;
135 static int hf_ucp_parm_BAS = -1;
136 static int hf_ucp_parm_LAR = -1;
137 static int hf_ucp_parm_LAC = -1;
138 static int hf_ucp_parm_L1R = -1;
139 static int hf_ucp_parm_L1P = -1;
140 static int hf_ucp_parm_L3R = -1;
141 static int hf_ucp_parm_L3P = -1;
142 static int hf_ucp_parm_LCR = -1;
143 static int hf_ucp_parm_LUR = -1;
144 static int hf_ucp_parm_LRR = -1;
145 static int hf_ucp_parm_RT = -1;
146 static int hf_ucp_parm_NoN = -1;
147 static int hf_ucp_parm_NoA = -1;
148 static int hf_ucp_parm_NoB = -1;
149 static int hf_ucp_parm_NAC = -1;
150 static int hf_ucp_parm_PNC = -1;
151 static int hf_ucp_parm_AMsg = -1;
152 static int hf_ucp_parm_LNo = -1;
153 static int hf_ucp_parm_LST = -1;
154 static int hf_ucp_parm_TNo = -1;
155 static int hf_ucp_parm_CS = -1;
156 static int hf_ucp_parm_PID = -1;
157 static int hf_ucp_parm_NPL = -1;
158 static int hf_ucp_parm_GA = -1;
159 static int hf_ucp_parm_RP = -1;
160 static int hf_ucp_parm_LRP = -1;
161 static int hf_ucp_parm_PR = -1;
162 static int hf_ucp_parm_LPR = -1;
163 static int hf_ucp_parm_UM = -1;
164 static int hf_ucp_parm_LUM = -1;
165 static int hf_ucp_parm_RC = -1;
166 static int hf_ucp_parm_LRC = -1;
167 static int hf_ucp_parm_NRq = -1;
168 static int hf_ucp_parm_GAdC = -1;
169 static int hf_ucp_parm_A_D = -1;
170 static int hf_ucp_parm_CT = -1;
171 static int hf_ucp_parm_AAC = -1;
172 static int hf_ucp_parm_MNo = -1;
173 static int hf_ucp_parm_R_T = -1;
174 static int hf_ucp_parm_IVR5x = -1;
175 static int hf_ucp_parm_REQ_OT = -1;
176 static int hf_ucp_parm_SSTAT = -1;
177 static int hf_ucp_parm_LMN = -1;
178 static int hf_ucp_parm_NMESS = -1;
179 static int hf_ucp_parm_NMESS_str = -1;
180 static int hf_ucp_parm_NAdC = -1;
181 static int hf_ucp_parm_NT = -1;
182 static int hf_ucp_parm_NPID = -1;
183 static int hf_ucp_parm_LRq = -1;
184 static int hf_ucp_parm_LRAd = -1;
185 static int hf_ucp_parm_LPID = -1;
186 static int hf_ucp_parm_DD = -1;
187 static int hf_ucp_parm_DDT = -1;
188 static int hf_ucp_parm_STx = -1;
189 static int hf_ucp_parm_ST = -1;
190 static int hf_ucp_parm_SP = -1;
191 static int hf_ucp_parm_VP = -1;
192 static int hf_ucp_parm_RPID = -1;
193 static int hf_ucp_parm_SCTS = -1;
194 static int hf_ucp_parm_Dst = -1;
195 static int hf_ucp_parm_Rsn = -1;
196 static int hf_ucp_parm_DSCTS = -1;
197 static int hf_ucp_parm_MT = -1;
198 static int hf_ucp_parm_NB = -1;
199 static int hf_ucp_data_section = -1;
200 static int hf_ucp_parm_MMS = -1;
201 static int hf_ucp_parm_DCs = -1;
202 static int hf_ucp_parm_MCLs = -1;
203 static int hf_ucp_parm_RPI = -1;
204 static int hf_ucp_parm_CPg = -1;
205 static int hf_ucp_parm_RPLy = -1;
206 static int hf_ucp_parm_OTOA = -1;
207 static int hf_ucp_parm_HPLMN = -1;
208 static int hf_ucp_parm_RES4 = -1;
209 static int hf_ucp_parm_RES5 = -1;
210 static int hf_ucp_parm_OTON = -1;
211 static int hf_ucp_parm_ONPI = -1;
212 static int hf_ucp_parm_STYP0 = -1;
213 static int hf_ucp_parm_STYP1 = -1;
214 static int hf_ucp_parm_ACK = -1;
215 static int hf_ucp_parm_PWD = -1;
216 static int hf_ucp_parm_NPWD = -1;
217 static int hf_ucp_parm_VERS = -1;
218 static int hf_ucp_parm_LAdC = -1;
219 static int hf_ucp_parm_LTON = -1;
220 static int hf_ucp_parm_LNPI = -1;
221 static int hf_ucp_parm_OPID = -1;
222 static int hf_ucp_parm_RES1 = -1;
223 static int hf_ucp_parm_RES2 = -1;
224 static int hf_ucp_parm_MVP = -1;
225 static int hf_ucp_parm_EC = -1;
226 static int hf_ucp_parm_SM = -1;
228 static int hf_ucp_parm_XSer = -1;
229 static int hf_xser_service = -1;
230 static int hf_xser_length = -1;
231 static int hf_xser_data = -1;
233 /* Initialize the subtree pointers */
234 static gint ett_ucp = -1;
235 static gint ett_sub = -1;
236 static gint ett_XSer = -1;
239 static int ucp_tap = -1;
242 * Value-arrays for certain field-contents
244 static const value_string vals_hdr_O_R[] = {
245 { 'O', "Operation" },
250 static const value_string vals_hdr_OT[] = { /* Operation type */
253 { 2, "Call input (multiple address)" },
254 { 3, "Call input (supplementary services included)" },
255 { 4, "Address list information" },
256 { 5, "Change address list" },
257 { 6, "Advice of accumulated charges" },
258 { 7, "Password management" },
259 { 8, "Legitimisation code management" },
260 { 9, "Standard text information" },
261 { 10, "Change standard text" },
262 { 11, "Request roaming information" },
263 { 12, "Change roaming information" },
264 { 13, "Roaming reset" },
265 { 14, "Message retrieval" },
266 { 15, "Request call barring" },
267 { 16, "Cancel call barring" },
268 { 17, "Request call diversion" },
269 { 18, "Cancel call diversion" },
270 { 19, "Request deferred delivery" },
271 { 20, "Cancel deferred delivery" },
272 { 21, "All features reset" },
273 { 22, "Call input (with specific character set)" },
274 { 23, "UCP version status request" },
275 { 24, "Mobile subscriber feature status request" },
276 { 30, "SMS message transfer" },
278 { 32, "(proprietary)" },
279 { 34, "(proprietary)" },
280 { 36, "(proprietary)" },
281 { 38, "(proprietary)" },
282 { 40, "(proprietary)" },
283 { 41, "(proprietary)" },
284 { 42, "(proprietary)" },
285 { 43, "(proprietary)" },
286 { 44, "(proprietary)" },
287 { 45, "(proprietary)" },
288 { 51, "Submit short message" },
289 { 52, "Deliver short message" },
290 { 53, "Deliver notification" },
291 { 54, "Modify message" },
292 { 55, "Inquiry message" },
293 { 56, "Delete message" },
294 { 57, "Inquiry response message" },
295 { 58, "Delete response message" },
296 { 60, "Session management" },
297 { 61, "List management" },
298 { 95, "(proprietary)" },
299 { 96, "(proprietary)" },
300 { 97, "(proprietary)" },
301 { 98, "(proprietary)" },
302 { 99, "(proprietary)" },
306 static const value_string vals_parm_EC[] = { /* Error code */
307 { 1, "Checksum error" },
308 { 2, "Syntax error" },
309 { 3, "Operation not supported by system" },
310 { 4, "Operation not allowed" },
311 { 5, "Call barring active" },
312 { 6, "AdC invalid" },
313 { 7, "Authentication failure" },
314 { 8, "Legitimisation code for all calls, failure" },
315 { 9, "GA not valid" },
316 { 10, "Repetition not allowed" },
317 { 11, "Legitimisation code for repetition, failure" },
318 { 12, "Priority call not allowed" },
319 { 13, "Legitimisation code for priority call, failure" },
320 { 14, "Urgent message not allowed" },
321 { 15, "Legitimisation code for urgent message, failure" },
322 { 16, "Reverse charging not allowed" },
323 { 17, "Legitimisation code for rev. charging, failure" },
324 { 18, "Deferred delivery not allowed" },
325 { 19, "New AC not valid" },
326 { 20, "New legitimisation code not valid" },
327 { 21, "Standard text not valid" },
328 { 22, "Time period not valid" },
329 { 23, "Message type not supported by system" },
330 { 24, "Message too long" },
331 { 25, "Requested standard text not valid" },
332 { 26, "Message type not valid for the pager type" },
333 { 27, "Message not found in SMSC" },
334 { 28, "Invalid character set" },
335 { 30, "Subscriber hang-up" },
336 { 31, "Fax group not supported" },
337 { 32, "Fax message type not supported" },
338 { 33, "Address already in list (60-series)" },
339 { 34, "Address not in list (60-series)" },
340 { 35, "List full, cannot add address to list (60-series)" },
341 { 36, "RPID already in use" },
342 { 37, "Delivery in progress" },
343 { 38, "Message forwarded" },
344 { 50, "Low network status" },
345 { 51, "Legitimisation code for standard text, failure" },
346 { 53, "Operation partially successful" },
347 { 54, "Operation not successful" },
348 { 55, "System error" },
349 { 57, "AdC already a member of GAdC address list" },
350 { 58, "AdC not a member of GAdC address list" },
351 { 59, "Requested standard text list invalid" },
352 { 61, "Not controller of GAdC address list" },
353 { 62, "Standard text too large" },
354 { 63, "Not owner of standard text list" },
355 { 64, "Address list full" },
356 { 65, "GAdC invalid" },
357 { 66, "Operation restricted to mobile subscribers" },
358 { 68, "Invalid AdC type" },
359 { 69, "Cannot add AdC to GAdC address list" },
360 { 90, "(proprietary error code)" },
361 { 91, "(proprietary error code)" },
362 { 92, "(proprietary error code)" },
363 { 93, "(proprietary error code)" },
364 { 94, "(proprietary error code)" },
365 { 95, "(proprietary error code)" },
366 { 96, "(proprietary error code)" },
367 { 97, "(proprietary error code)" },
368 { 98, "(proprietary error code)" },
369 { 99, "(proprietary error code)" },
373 static const value_string vals_parm_NRq[] = {
374 { '0', "NAdC not used" },
375 { '1', "NAdC used" },
379 static const value_string vals_parm_NT[] = {
380 { '0', "Default value" },
381 { '1', "Delivery notification" },
382 { '2', "Non-delivery notification" },
383 { '3', "Delivery and Non-delivery notification" },
384 { '4', "Buffered message notification" },
385 { '5', "Buffered and Delivery notification" },
386 { '6', "Buffered and Non-delivery notification" },
387 { '7', "All notifications" },
391 static const value_string vals_parm_PID[] = {
392 { 100, "Mobile station" },
393 { 122, "Fax Group 3" },
395 { 138, "Menu over PSTN" },
396 { 139, "PC appl. over PSTN (E.164)" },
397 { 339, "PC appl. over X.25 (X.121)" },
398 { 439, "PC appl. over ISDN (E.164)" },
399 { 539, "PC appl. over TCP/IP" },
403 static const value_string vals_parm_LRq[] = {
404 { '0', "LRAd not used" },
405 { '1', "LRAd used" },
409 static const value_string vals_parm_DD[] = {
410 { '0', "DDT not used" },
415 static const value_string vals_parm_Dst[] = {
416 { '0', "delivered" },
417 { '1', "buffered (see Rsn)" },
418 { '2', "not delivered (see Rsn)" },
422 static const value_string vals_parm_Rsn[] = {
423 { 0, "Unknown subscriber" },
424 { 1, "Service temporary not available" },
425 { 2, "Service temporary not available" },
426 { 3, "Service temporary not available" },
427 { 4, "Service temporary not available" },
428 { 5, "Service temporary not available" },
429 { 6, "Service temporary not available" },
430 { 7, "Service temporary not available" },
431 { 8, "Service temporary not available" },
432 { 9, "Illegal error code" },
433 { 10, "Network time-out" },
434 { 100, "Facility not supported" },
435 { 101, "Unknown subscriber" },
436 { 102, "Facility not provided" },
437 { 103, "Call barred" },
438 { 104, "Operation barred" },
439 { 105, "SC congestion" },
440 { 106, "Facility not supported" },
441 { 107, "Absent subscriber" },
442 { 108, "Delivery fail" },
443 { 109, "Sc congestion" },
444 { 110, "Protocol error" },
445 { 111, "MS not equipped" },
446 { 112, "Unknown SC" },
447 { 113, "SC congestion" },
448 { 114, "Illegal MS" },
449 { 115, "MS nota subscriber" },
450 { 116, "Error in MS" },
451 { 117, "SMS lower layer not provisioned" },
452 { 118, "System fail" },
453 { 119, "PLMN system failure" },
454 { 120, "HLR system failure" },
455 { 121, "VLR system failure" },
456 { 122, "Previous VLR system failure" },
457 { 123, "Controlling MSC system failure" },
458 { 124, "VMSC system failure" },
459 { 125, "EIR system failure" },
460 { 126, "System failure" },
461 { 127, "Unexpected data value" },
462 { 200, "Error in address service centre" },
463 { 201, "Invalid absolute validity period" },
464 { 202, "Short message exceeds maximum" },
465 { 203, "Unable to unpack GSM message" },
466 { 204, "Unable to convert to IRA alphabet" },
467 { 205, "Invalid validity period format" },
468 { 206, "Invalid destination address" },
469 { 207, "Duplicate message submit" },
470 { 208, "Invalid message type indicator" },
474 static const value_string vals_parm_MT[] = {
475 { '2', "Numeric message" },
476 { '3', "Alphanumeric message" },
477 { '4', "Transparent data" },
481 static const value_string vals_parm_DCs[] = {
482 { '0', "default alphabet" },
483 { '1', "User defined data (8 bit)" },
487 static const value_string vals_parm_MCLs[] = {
488 { '0', "message class 0" },
489 { '1', "message class 1" },
490 { '2', "message class 2" },
491 { '3', "message class 3" },
495 static const value_string vals_parm_RPI[] = {
501 static const value_string vals_parm_ACK[] = {
507 static const value_string vals_parm_RP[] = {
508 { '1', "Repetition requested" },
512 static const value_string vals_parm_UM[] = {
513 { '1', "Urgent message" },
517 static const value_string vals_parm_RC[] = {
518 { '1', "Reverse charging request" },
522 static const value_string vals_parm_OTON[] = {
523 { '1', "International number" },
524 { '2', "National number" },
525 { '6', "Abbreviated number (short number alias)" },
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" },
536 static const value_string vals_parm_STYP0[] = {
537 { '1', "open session" },
539 { '3', "change password" },
540 { '4', "open provisioning session" },
542 { '6', "change provisioning password" },
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" },
556 static const value_string vals_parm_OPID[] = {
557 { 0, "Mobile station" },
558 { 39, "PC application" },
562 static const value_string vals_parm_BAS[] = {
567 static const value_string vals_parm_LAR[] = {
568 { '1', "Leg. code for all calls requested" },
572 static const value_string vals_parm_L1R[] = {
573 { '1', "Leg. code for priority 1 requested" },
577 static const value_string vals_parm_L3R[] = {
578 { '1', "Leg. code for priority 3 requested" },
582 static const value_string vals_parm_LCR[] = {
583 { '1', "Leg. code for reverse charging requested" },
587 static const value_string vals_parm_LUR[] = {
588 { '1', "Leg. code for urgent message requested" },
592 static const value_string vals_parm_LRR[] = {
593 { '1', "Leg. code for repetition requested" },
597 static const value_string vals_parm_RT[] = {
598 { '1', "Tone only" },
600 { '3', "Alphanumeric" },
601 { '4', "Transparent data" },
605 static const value_string vals_parm_PNC[] = {
607 { 'I', "Input PNC" },
611 static const value_string vals_parm_A_D[] = {
617 static const value_string vals_parm_R_T[] = {
618 { 'R', "Retrieval Ok" },
619 { 'T', "Retransmit on radio channel" },
623 static const value_string vals_parm_REQ_OT[] = {
624 { 'S', "Send used operation types" },
625 { 'N', "Don't send used operation types" },
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" },
640 static const value_string vals_xser_service[] = {
641 { 1, "GSM UDH information" },
642 { 2, "GSM DCS information" },
643 { 3, "[Message Type] TDMA information exchange" },
644 { 4, "[Message Reference] TDMA information exchange" },
645 { 5, "[Privacy Indicator] TDMA information exchange" },
646 { 6, "[Urgency Indicator] TDMA information exchange" },
647 { 7, "[Acknowledgement Request] TDMA information exchange" },
648 { 8, "[Message Updating] TDMA information exchange" },
649 { 9, "[Call Back Number] TDMA information exchange" },
650 { 10, "[Response Code] TDMA information exchange" },
651 { 11, "[Teleservice ID] TDMA information exchange" },
652 { 12, "Billing identifier" },
653 { 13, "Single shot indicator" },
659 ucp_stats_tree_init(stats_tree* st)
661 st_ucp_messages = stats_tree_create_node(st, st_str_ucp, 0, TRUE);
662 st_ucp_ops = stats_tree_create_node(st, st_str_ops, st_ucp_messages, TRUE);
663 st_ucp_res = stats_tree_create_node(st, st_str_res, st_ucp_messages, TRUE);
664 st_ucp_results = stats_tree_create_node(st, st_str_ucp_res, 0, TRUE);
665 st_ucp_results_pos = stats_tree_create_node(st, st_str_pos, st_ucp_results, TRUE);
666 st_ucp_results_neg = stats_tree_create_node(st, st_str_neg, st_ucp_results, TRUE);
670 ucp_stats_tree_per_packet(stats_tree *st, /* st as it was passed to us */
671 packet_info *pinfo _U_,
672 epan_dissect_t *edt _U_,
673 const void *p) /* Used for getting UCP stats */
675 ucp_tap_rec_t* tap_rec = (ucp_tap_rec_t*)p;
677 tick_stat_node(st, st_str_ucp, 0, TRUE);
679 if (tap_rec->message_type == 0) /* Operation */
681 tick_stat_node(st, st_str_ops, st_ucp_messages, TRUE);
682 tick_stat_node(st, val_to_str(tap_rec->operation, vals_hdr_OT,
683 "Unknown OT: %d"), st_ucp_ops, FALSE);
687 tick_stat_node(st, st_str_res, st_ucp_messages, TRUE);
688 tick_stat_node(st, val_to_str(tap_rec->operation, vals_hdr_OT,
689 "Unknown OT: %d"), st_ucp_res, FALSE);
691 tick_stat_node(st, st_str_ucp_res, 0, TRUE);
693 if (tap_rec->result == 0) /* Positive Result */
695 tick_stat_node(st, st_str_pos, st_ucp_results, FALSE);
697 else /* Negative Result */
699 tick_stat_node(st, st_str_neg, st_ucp_results, TRUE);
700 tick_stat_node(st, val_to_str(tap_rec->result, vals_parm_EC,
701 "Unknown EC: %d"), st_ucp_results_neg, FALSE);
709 * Checks whether the PDU looks a bit like UCP and checks the checksum
711 * Note: check_ucp is called only with a buffer of at least LEN+2 bytes.
712 * IOW: The buffer should contain a complete UCP PDU [STX ... ETX]
714 * \param tvb The buffer with PDU-data
715 * \param endpkt Returns pointer, indicating the end of the PDU
717 * \return The state of this PDU
718 * \retval 0 Definitely UCP
719 * \retval UCP_MALFORMED ???
720 * \retval UCP_INV_CHK Nice packet, but checksum doesn't add up...
723 check_ucp(tvbuff_t *tvb, int *endpkt)
730 length = tvb_find_guint8(tvb, offset, -1, UCP_ETX);
732 *endpkt = tvb_reported_length_remaining(tvb, offset);
733 return UCP_MALFORMED;
735 for (; offset < (guint) (length - 2); offset++)
736 checksum += tvb_get_guint8(tvb, offset);
738 tmp = tvb_get_guint8(tvb, offset++);
739 pkt_check = AHex2Bin(tmp);
740 tmp = tvb_get_guint8(tvb, offset++);
741 pkt_check = 16 * pkt_check + AHex2Bin(tmp);
742 *endpkt = offset + 1;
743 if (checksum == (guint) pkt_check)
750 * UCP equivalent of mktime() (3). Convert date to standard 'time_t' format
752 * \param datestr The UCP-formatted date to convert
754 * \return The date in standard 'time_t' format.
757 ucp_mktime(char *datestr)
761 r_time.tm_mday = (10 * (datestr[0] - '0') + (datestr[1] - '0'));
762 r_time.tm_mon = (10 * (datestr[2] - '0') + (datestr[3] - '0')) - 1;
763 r_time.tm_year = (10 * (datestr[4] - '0') + (datestr[5] - '0'));
764 if (r_time.tm_year < 90)
765 r_time.tm_year += 100;
766 r_time.tm_hour = (10 * (datestr[6] - '0') + (datestr[7] - '0'));
767 r_time.tm_min = (10 * (datestr[8] - '0') + (datestr[9] - '0'));
769 r_time.tm_sec = (10 * (datestr[10] - '0') + (datestr[11] - '0'));
772 r_time.tm_isdst = -1;
773 return mktime(&r_time);
777 * Scanning routines to add standard types (byte, int, string, data)
778 * to the protocol-tree. Each field is seperated with a slash ('/').
780 * \param tree The protocol tree to add to
781 * \param tvb Buffer containing the data
782 * \param field The actual field, whose value needs displaying
783 * \param offset Location of field within the buffer, returns location
786 * \return For 'int'-types, the value of the field.
789 ucp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
793 idx = tvb_find_guint8(tvb, *offset, -1, '/');
795 /* Force the appropriate exception to be thrown. */
796 len = tvb_length_remaining(tvb, *offset);
797 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
801 proto_tree_add_item(tree, field, tvb, *offset, len, FALSE);
804 *offset += 1; /* skip terminating '/' */
808 ucp_handle_IRAstring(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
810 char strval[BUFSIZ + 1],
814 int tmpoff = *offset;
816 while (((byte = tvb_get_guint8(tvb, tmpoff++)) != '/') &&
819 if (byte >= '0' && byte <= '9')
821 *p_dst = (byte - '0') * 16;
825 *p_dst = (byte - 'A' + 10) * 16;
827 if ((byte = tvb_get_guint8(tvb, tmpoff++)) == '/')
831 if (byte >= '0' && byte <= '9')
833 *p_dst++ += byte - '0';
837 *p_dst++ += byte - 'A' + 10;
845 * Data clipped, eat rest of field
847 while ((tvb_get_guint8(tvb, tmpoff++)) != '/')
850 if ((tmpoff - *offset) > 1)
851 proto_tree_add_string(tree, field, tvb, *offset,
852 tmpoff - *offset - 1, strval);
857 ucp_handle_byte(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
861 if ((intval = tvb_get_guint8(tvb, (*offset)++)) != '/') {
862 proto_tree_add_uint(tree, field, tvb, *offset - 1, 1, intval);
869 ucp_handle_int(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
875 idx = tvb_find_guint8(tvb, *offset, -1, '/');
877 /* Force the appropriate exception to be thrown. */
878 len = tvb_length_remaining(tvb, *offset);
879 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
882 strval = (gchar*)tvb_get_ephemeral_string(tvb, *offset, len);
884 intval = atoi(strval);
885 proto_tree_add_uint(tree, field, tvb, *offset, len, intval);
889 *offset += 1; /* skip terminating '/' */
894 ucp_handle_time(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
901 idx = tvb_find_guint8(tvb, *offset, -1, '/');
903 /* Force the appropriate exception to be thrown. */
904 len = tvb_length_remaining(tvb, *offset);
905 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
908 strval = (gchar*)tvb_get_ephemeral_string(tvb, *offset, len);
910 tval = ucp_mktime(strval);
913 proto_tree_add_time(tree, field, tvb, *offset, len, &tmptime);
917 *offset += 1; /* skip terminating '/' */
921 ucp_handle_data(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
923 int tmpoff = *offset;
925 while (tvb_get_guint8(tvb, tmpoff++) != '/')
927 if ((tmpoff - *offset) > 1)
928 proto_tree_add_item(tree, field, tvb, *offset,
929 tmpoff - *offset - 1, FALSE);
934 * Handle the data-field within the UCP-message, according the Message Type
936 * - 2 Numeric message
937 * - 3 Alphanumeric message
938 * - 4 Transparent (binary) data
939 * - 5 Standard text handling
940 * - 6 Alphanumeric message in specified character set
942 * \param tree The protocol tree to add to
943 * \param tvb Buffer containing the data
944 * \param field The actual field, whose value needs displaying
945 * \param offset Location of field within the buffer, returns location
949 ucp_handle_mt(proto_tree *tree, tvbuff_t *tvb, int *offset)
953 intval = ucp_handle_byte(tree, tvb, hf_ucp_parm_MT, offset);
955 case '1': /* Tone only, no data */
957 case '4': /* TMsg, no of bits */
958 ucp_handle_string(tree, tvb, hf_ucp_parm_NB, offset);
959 /* fall through here for the data piece */
961 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
964 ucp_handle_IRAstring(tree, tvb, hf_ucp_parm_AMsg, offset);
967 ucp_handle_byte(tree, tvb, hf_ucp_parm_PNC, offset);
968 ucp_handle_string(tree, tvb, hf_ucp_parm_LNo, offset);
969 ucp_handle_string(tree, tvb, hf_ucp_parm_LST, offset);
970 ucp_handle_string(tree, tvb, hf_ucp_parm_TNo, offset);
973 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
974 ucp_handle_int(tree, tvb, hf_ucp_parm_CS, offset);
977 break; /* No data so ? */
982 * Handle the data within the 'Extended services' field. Each field having the
983 * format TTLLDD..., TT being the type of service, LL giving the length of the
984 * field, DD... containing the actual data
986 * \param tree The protocol tree to add to
987 * \param tvb Buffer containing the extended services data
990 ucp_handle_XSer(proto_tree *tree, tvbuff_t *tvb)
997 while ((intval = tvb_get_guint8(tvb, offset)) != '/') {
998 service = AHex2Bin(intval);
999 intval = tvb_get_guint8(tvb, offset+1);
1000 service = service * 16 + AHex2Bin(intval);
1001 intval = tvb_get_guint8(tvb, offset+2);
1002 len = AHex2Bin(intval);
1003 intval = tvb_get_guint8(tvb, offset+3);
1004 len = len * 16 + AHex2Bin(intval);
1005 proto_tree_add_uint(tree, hf_xser_service, tvb, offset, 2, service);
1006 proto_tree_add_uint(tree, hf_xser_length, tvb, offset+2, 2, len);
1007 proto_tree_add_item(tree, hf_xser_data, tvb, offset+4, len*2, ENC_ASCII|ENC_NA);
1008 offset += 4 + (2 * len);
1012 /* Next definitions are just a convenient shorthand to make the coding a
1013 * bit more readable instead of summing up all these parameters.
1015 #define UcpHandleString(field) ucp_handle_string(tree, tvb, (field), &offset)
1017 #define UcpHandleIRAString(field) \
1018 ucp_handle_IRAstring(tree, tvb, (field), &offset)
1020 #define UcpHandleByte(field) ucp_handle_byte(tree, tvb, (field), &offset)
1022 #define UcpHandleInt(field) ucp_handle_int(tree, tvb, (field), &offset)
1024 #define UcpHandleTime(field) ucp_handle_time(tree, tvb, (field), &offset)
1026 #define UcpHandleData(field) ucp_handle_data(tree, tvb, (field), &offset)
1029 * The next set of routines handle the different operation types,
1030 * associated with UCP.
1033 add_00O(proto_tree *tree, tvbuff_t *tvb)
1037 UcpHandleString(hf_ucp_parm_AdC);
1038 UcpHandleString(hf_ucp_parm_OAdC);
1039 UcpHandleString(hf_ucp_parm_OAC);
1043 add_00R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1048 intval = UcpHandleByte(hf_ucp_parm_ACK);
1051 UcpHandleByte(hf_ucp_parm_BAS);
1052 UcpHandleByte(hf_ucp_parm_LAR);
1053 UcpHandleByte(hf_ucp_parm_L1R);
1054 UcpHandleByte(hf_ucp_parm_L3R);
1055 UcpHandleByte(hf_ucp_parm_LCR);
1056 UcpHandleByte(hf_ucp_parm_LUR);
1057 UcpHandleByte(hf_ucp_parm_LRR);
1058 UcpHandleByte(hf_ucp_parm_RT);
1059 UcpHandleInt(hf_ucp_parm_NoN);
1060 UcpHandleInt(hf_ucp_parm_NoA);
1061 UcpHandleInt(hf_ucp_parm_NoB);
1063 tap_rec->result = 0;
1065 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1066 UcpHandleString(hf_ucp_parm_SM);
1071 add_01O(proto_tree *tree, tvbuff_t *tvb)
1075 UcpHandleString(hf_ucp_parm_AdC);
1076 UcpHandleString(hf_ucp_parm_OAdC);
1077 UcpHandleString(hf_ucp_parm_OAC);
1078 ucp_handle_mt(tree, tvb, &offset);
1082 add_01R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1087 intval = UcpHandleByte(hf_ucp_parm_ACK);
1089 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1091 tap_rec->result = 0;
1092 UcpHandleString(hf_ucp_parm_SM);
1096 add_02O(proto_tree *tree, tvbuff_t *tvb)
1097 { /* Multiple address call input*/
1102 intval = UcpHandleInt(hf_ucp_parm_NPL);
1103 for (idx = 0; idx < intval; idx++)
1104 UcpHandleString(hf_ucp_parm_AdC);
1106 UcpHandleString(hf_ucp_parm_OAdC);
1107 UcpHandleString(hf_ucp_parm_OAC);
1108 ucp_handle_mt(tree, tvb, &offset);
1111 #define add_02R(a, b, c) add_01R(a, b, c)
1114 add_03O(proto_tree *tree, tvbuff_t *tvb)
1115 { /* Call input with SS */
1120 UcpHandleString(hf_ucp_parm_AdC);
1121 UcpHandleString(hf_ucp_parm_OAdC);
1122 UcpHandleString(hf_ucp_parm_OAC);
1123 intval = UcpHandleInt(hf_ucp_parm_NPL);
1124 for (idx = 0; idx < intval; idx++)
1125 UcpHandleString(hf_ucp_parm_GA);
1127 UcpHandleByte(hf_ucp_parm_RP);
1128 UcpHandleString(hf_ucp_parm_LRP);
1129 UcpHandleByte(hf_ucp_parm_PR);
1130 UcpHandleString(hf_ucp_parm_LPR);
1131 UcpHandleByte(hf_ucp_parm_UM);
1132 UcpHandleString(hf_ucp_parm_LUM);
1133 UcpHandleByte(hf_ucp_parm_RC);
1134 UcpHandleString(hf_ucp_parm_LRC);
1135 UcpHandleByte(hf_ucp_parm_DD);
1136 UcpHandleTime(hf_ucp_parm_DDT); /* DDMMYYHHmm */
1137 ucp_handle_mt(tree, tvb, &offset);
1140 #define add_03R(a, b, c) add_01R(a, b, c)
1143 add_04O(proto_tree *tree, tvbuff_t *tvb)
1144 { /* Address list information */
1147 UcpHandleString(hf_ucp_parm_GAdC);
1148 UcpHandleString(hf_ucp_parm_AC);
1149 UcpHandleString(hf_ucp_parm_OAdC);
1150 UcpHandleString(hf_ucp_parm_OAC);
1154 add_04R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1160 intval = UcpHandleByte(hf_ucp_parm_ACK);
1161 if (intval == 'A') {
1162 intval = UcpHandleInt(hf_ucp_parm_NPL);
1163 for (idx = 0; idx < intval; idx++)
1164 UcpHandleString(hf_ucp_parm_AdC);
1165 UcpHandleString(hf_ucp_parm_GAdC);
1166 tap_rec->result = 0;
1168 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1169 UcpHandleString(hf_ucp_parm_SM);
1173 add_05O(proto_tree *tree, tvbuff_t *tvb)
1174 { /* Change address list */
1179 UcpHandleString(hf_ucp_parm_GAdC);
1180 UcpHandleString(hf_ucp_parm_AC);
1181 UcpHandleString(hf_ucp_parm_OAdC);
1182 UcpHandleString(hf_ucp_parm_OAC);
1183 intval = UcpHandleInt(hf_ucp_parm_NPL);
1184 for (idx = 0; idx < intval; idx++)
1185 UcpHandleString(hf_ucp_parm_AdC);
1186 UcpHandleByte(hf_ucp_parm_A_D);
1189 #define add_05R(a, b, c) add_01R(a, b, c)
1192 add_06O(proto_tree *tree, tvbuff_t *tvb)
1193 { /* Advice of accum. charges */
1196 UcpHandleString(hf_ucp_parm_AdC);
1197 UcpHandleString(hf_ucp_parm_AC);
1201 add_06R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1206 intval = UcpHandleByte(hf_ucp_parm_ACK);
1207 if (intval == 'A') {
1208 UcpHandleTime(hf_ucp_parm_CT);
1209 UcpHandleString(hf_ucp_parm_AAC);
1210 tap_rec->result = 0;
1212 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1213 UcpHandleString(hf_ucp_parm_SM);
1217 add_07O(proto_tree *tree, tvbuff_t *tvb)
1218 { /* Password management */
1221 UcpHandleString(hf_ucp_parm_AdC);
1222 UcpHandleString(hf_ucp_parm_AC);
1223 UcpHandleString(hf_ucp_parm_NAC);
1226 #define add_07R(a, b, c) add_01R(a, b, c)
1229 add_08O(proto_tree *tree, tvbuff_t *tvb)
1230 { /* Leg. code management */
1233 UcpHandleString(hf_ucp_parm_AdC);
1234 UcpHandleString(hf_ucp_parm_AC);
1235 UcpHandleString(hf_ucp_parm_LAC);
1236 UcpHandleString(hf_ucp_parm_L1P);
1237 UcpHandleString(hf_ucp_parm_L3P);
1238 UcpHandleString(hf_ucp_parm_LRC);
1239 UcpHandleString(hf_ucp_parm_LUM);
1240 UcpHandleString(hf_ucp_parm_LRP);
1241 UcpHandleString(hf_ucp_parm_LST);
1244 #define add_08R(a, b, c) add_01R(a, b, c)
1247 add_09O(proto_tree *tree, tvbuff_t *tvb)
1248 { /* Standard text information */
1251 UcpHandleString(hf_ucp_parm_LNo);
1252 UcpHandleString(hf_ucp_parm_LST);
1256 add_09R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
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_LST);
1267 tap_rec->result = 0;
1269 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1270 UcpHandleString(hf_ucp_parm_SM);
1274 add_10O(proto_tree *tree, tvbuff_t *tvb)
1275 { /* Change standard text */
1278 UcpHandleString(hf_ucp_parm_AdC);
1279 UcpHandleString(hf_ucp_parm_AC);
1280 UcpHandleString(hf_ucp_parm_LNo);
1281 UcpHandleString(hf_ucp_parm_TNo);
1282 UcpHandleData(hf_ucp_parm_STx);
1283 UcpHandleInt(hf_ucp_parm_CS);
1286 #define add_10R(a, b, c) add_01R(a, b, c)
1288 #define add_11O(a, b) add_06O(a, b) /* Request roaming info */
1291 add_11R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1297 intval = UcpHandleByte(hf_ucp_parm_ACK);
1298 if (intval == 'A') {
1299 intval = UcpHandleInt(hf_ucp_parm_NPL);
1300 for (idx = 0; idx < intval; idx++)
1301 UcpHandleString(hf_ucp_parm_GA);
1302 tap_rec->result = 0;
1304 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1305 UcpHandleString(hf_ucp_parm_SM);
1309 add_12O(proto_tree *tree, tvbuff_t *tvb)
1310 { /* Change roaming */
1315 UcpHandleString(hf_ucp_parm_AdC);
1316 UcpHandleString(hf_ucp_parm_AC);
1317 intval = UcpHandleInt(hf_ucp_parm_NPL);
1318 for (idx = 0; idx < intval; idx++)
1319 UcpHandleString(hf_ucp_parm_GA);
1322 #define add_12R(a, b, c) add_01R(a, b, c)
1324 #define add_13O(a, b) add_06O(a, b) /* Roaming reset */
1326 #define add_13R(a, b, c) add_01R(a, b, c)
1329 add_14O(proto_tree *tree, tvbuff_t *tvb)
1330 { /* Message retrieval */
1333 UcpHandleString(hf_ucp_parm_AdC);
1334 UcpHandleString(hf_ucp_parm_AC);
1335 UcpHandleString(hf_ucp_parm_MNo);
1336 UcpHandleByte(hf_ucp_parm_R_T);
1340 add_14R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1346 intval = UcpHandleByte(hf_ucp_parm_ACK);
1347 if (intval == 'A') {
1348 intval = UcpHandleInt(hf_ucp_parm_NPL);
1350 * Spec is unclear here. Is 'SM' part of the Msg:s field or not?
1351 * For now, assume it is part of it...
1353 for (idx = 0; idx < intval; idx++)
1354 UcpHandleData(hf_ucp_data_section);
1355 tap_rec->result = 0;
1357 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1358 UcpHandleString(hf_ucp_parm_SM);
1363 add_15O(proto_tree *tree, tvbuff_t *tvb)
1364 { /* Request call barring */
1367 UcpHandleString(hf_ucp_parm_AdC);
1368 UcpHandleString(hf_ucp_parm_AC);
1369 UcpHandleTime(hf_ucp_parm_ST);
1370 UcpHandleTime(hf_ucp_parm_SP);
1373 #define add_15R(a, b, c) add_01R(a, b, c)
1375 #define add_16O(a, b) add_06O(a, b) /* Cancel call barring */
1377 #define add_16R(a, b, c) add_01R(a, b, c)
1380 add_17O(proto_tree *tree, tvbuff_t *tvb)
1381 { /* Request call diversion */
1384 UcpHandleString(hf_ucp_parm_AdC);
1385 UcpHandleString(hf_ucp_parm_AC);
1386 UcpHandleString(hf_ucp_parm_DAdC);
1387 UcpHandleTime(hf_ucp_parm_ST);
1388 UcpHandleTime(hf_ucp_parm_SP);
1391 #define add_17R(a, b, c) add_01R(a, b, c)
1393 #define add_18O(a, b) add_06O(a, b) /* Cancel call diversion */
1395 #define add_18R(a, b, c) add_01R(a, b, c)
1398 add_19O(proto_tree *tree, tvbuff_t *tvb)
1399 { /* Request deferred delivery*/
1402 UcpHandleString(hf_ucp_parm_AdC);
1403 UcpHandleString(hf_ucp_parm_AC);
1404 UcpHandleTime(hf_ucp_parm_ST);
1405 UcpHandleTime(hf_ucp_parm_SP);
1408 #define add_19R(a, b, c) add_01R(a, b, c)
1410 #define add_20O(a, b) add_06O(a, b) /* Cancel deferred delivery */
1412 #define add_20R(a, b, c) add_01R(a, b, c)
1414 #define add_21O(a, b) add_06O(a, b) /* All features reset */
1416 #define add_21R(a, b, c) add_01R(a, b, c)
1419 add_22O(proto_tree *tree, tvbuff_t *tvb)
1420 { /* Call input w. add. CS */
1423 UcpHandleString(hf_ucp_parm_AdC);
1424 UcpHandleString(hf_ucp_parm_OAdC);
1425 UcpHandleString(hf_ucp_parm_OAC);
1426 UcpHandleData(hf_ucp_data_section);
1427 UcpHandleInt(hf_ucp_parm_CS);
1430 #define add_22R(a, b, c) add_01R(a, b, c)
1433 add_23O(proto_tree *tree, tvbuff_t *tvb)
1434 { /* UCP version status */
1437 UcpHandleString(hf_ucp_parm_IVR5x);
1438 UcpHandleByte(hf_ucp_parm_REQ_OT);
1442 add_23R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1448 intval = UcpHandleByte(hf_ucp_parm_ACK);
1449 if (intval == 'A') {
1450 UcpHandleByte(hf_ucp_parm_IVR5x);
1451 intval = UcpHandleInt(hf_ucp_parm_NPL);
1452 for (idx = 0; idx < intval; idx++)
1453 UcpHandleInt(hf_ucp_hdr_OT);
1454 tap_rec->result = 0;
1456 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1457 UcpHandleString(hf_ucp_parm_SM);
1461 add_24O(proto_tree *tree, tvbuff_t *tvb)
1462 { /* Mobile subs. feature stat*/
1465 UcpHandleString(hf_ucp_parm_AdC);
1466 UcpHandleString(hf_ucp_parm_AC);
1467 UcpHandleByte(hf_ucp_parm_SSTAT);
1471 add_24R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1477 intval = UcpHandleByte(hf_ucp_parm_ACK);
1478 if (intval == 'A') {
1479 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1480 proto_tree_add_text(tree, tvb, offset - 1, 1,
1481 "GA roaming definitions");
1482 if (intval == 'N') {
1483 proto_tree_add_text(tree, tvb, offset -1, 1,
1484 "Not subscribed/not allowed");
1488 intval = UcpHandleInt(hf_ucp_parm_NPL);
1489 for (idx = 0; idx < intval; idx++)
1490 UcpHandleData(hf_ucp_data_section);
1493 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1494 proto_tree_add_text(tree, tvb, offset - 1, 1,
1495 "Call barring definitions");
1496 if (intval == 'N') {
1497 proto_tree_add_text(tree, tvb, offset -1, 1,
1498 "Not subscribed/not allowed");
1502 intval = UcpHandleInt(hf_ucp_parm_NPL);
1503 for (idx = 0; idx < intval; idx++)
1504 UcpHandleData(hf_ucp_data_section);
1507 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1508 proto_tree_add_text(tree, tvb, offset - 1, 1,
1509 "Deferred delivery definitions");
1510 if (intval == 'N') {
1511 proto_tree_add_text(tree, tvb, offset -1, 1,
1512 "Not subscribed/not allowed");
1516 intval = UcpHandleInt(hf_ucp_parm_NPL);
1517 for (idx = 0; idx < intval; idx++)
1518 UcpHandleData(hf_ucp_data_section);
1521 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1522 proto_tree_add_text(tree, tvb, offset - 1, 1,
1523 "Diversion definitions");
1524 if (intval == 'N') {
1525 proto_tree_add_text(tree, tvb, offset -1, 1,
1526 "Not subscribed/not allowed");
1530 intval = UcpHandleInt(hf_ucp_parm_NPL);
1531 for (idx = 0; idx < intval; idx++)
1532 UcpHandleData(hf_ucp_data_section);
1535 UcpHandleInt(hf_ucp_parm_LMN);
1536 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1537 if (intval == 'N') {
1538 proto_tree_add_string(tree, hf_ucp_parm_NMESS_str, tvb,
1539 offset -1, 1, "Not subscribed/not allowed");
1543 intval = UcpHandleInt(hf_ucp_parm_NMESS);
1546 tap_rec->result = 0;
1548 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1549 UcpHandleString(hf_ucp_parm_SM);
1553 add_30O(proto_tree *tree, tvbuff_t *tvb)
1554 { /* SMS message transfer */
1557 UcpHandleString(hf_ucp_parm_AdC);
1558 UcpHandleString(hf_ucp_parm_OAdC);
1559 UcpHandleString(hf_ucp_parm_AC);
1560 UcpHandleByte(hf_ucp_parm_NRq);
1561 UcpHandleString(hf_ucp_parm_NAdC);
1562 UcpHandleInt(hf_ucp_parm_NPID);
1563 UcpHandleByte(hf_ucp_parm_DD);
1564 UcpHandleTime(hf_ucp_parm_DDT); /* DDMMYYHHmm */
1565 UcpHandleTime(hf_ucp_parm_VP); /* DDMMYYHHmm */
1566 UcpHandleData(hf_ucp_data_section);
1570 add_30R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1575 intval = UcpHandleByte(hf_ucp_parm_ACK);
1576 if (intval == 'A') {
1577 UcpHandleTime(hf_ucp_parm_MVP); /* DDMMYYHHmm */
1578 tap_rec->result = 0;
1580 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1582 UcpHandleString(hf_ucp_parm_SM);
1586 add_31O(proto_tree *tree, tvbuff_t *tvb)
1590 UcpHandleString(hf_ucp_parm_AdC);
1591 UcpHandleInt(hf_ucp_parm_PID);
1594 #define add_31R(a, b, c) add_01R(a, b, c)
1597 add_5xO(proto_tree *tree, tvbuff_t *tvb)
1598 { /* 50-series operations */
1605 UcpHandleString(hf_ucp_parm_AdC);
1606 UcpHandleString(hf_ucp_parm_OAdC);
1607 UcpHandleString(hf_ucp_parm_AC);
1608 UcpHandleByte(hf_ucp_parm_NRq);
1609 UcpHandleString(hf_ucp_parm_NAdC);
1610 UcpHandleByte(hf_ucp_parm_NT);
1611 UcpHandleInt(hf_ucp_parm_NPID);
1612 UcpHandleByte(hf_ucp_parm_LRq);
1613 UcpHandleString(hf_ucp_parm_LRAd);
1614 UcpHandleInt(hf_ucp_parm_LPID);
1615 UcpHandleByte(hf_ucp_parm_DD);
1616 UcpHandleTime(hf_ucp_parm_DDT); /* DDMMYYHHmm */
1617 UcpHandleTime(hf_ucp_parm_VP); /* DDMMYYHHmm */
1618 UcpHandleString(hf_ucp_parm_RPID);
1619 UcpHandleTime(hf_ucp_parm_SCTS); /* DDMMYYhhmmss */
1620 UcpHandleByte(hf_ucp_parm_Dst);
1621 UcpHandleInt(hf_ucp_parm_Rsn);
1622 UcpHandleTime(hf_ucp_parm_DSCTS); /* DDMMYYhhmmss */
1623 intval = UcpHandleByte(hf_ucp_parm_MT);
1624 UcpHandleString(hf_ucp_parm_NB);
1626 UcpHandleData(hf_ucp_data_section);
1628 UcpHandleIRAString(hf_ucp_parm_AMsg);
1629 UcpHandleByte(hf_ucp_parm_MMS);
1630 UcpHandleByte(hf_ucp_parm_PR);
1631 UcpHandleByte(hf_ucp_parm_DCs);
1632 UcpHandleByte(hf_ucp_parm_MCLs);
1633 UcpHandleByte(hf_ucp_parm_RPI);
1634 if (tvb_get_guint8(tvb, offset++) != '/') {
1635 proto_tree_add_string(tree, hf_ucp_parm_CPg, tvb, offset - 1,1,
1636 "(reserved for Code Page)");
1639 if (tvb_get_guint8(tvb, offset++) != '/') {
1640 proto_tree_add_string(tree, hf_ucp_parm_RPLy, tvb, offset - 1,1,
1641 "(reserved for Reply type)");
1644 UcpHandleString(hf_ucp_parm_OTOA);
1645 UcpHandleString(hf_ucp_parm_HPLMN);
1646 tmpoff = offset; /* Extra services */
1647 while (tvb_get_guint8(tvb, tmpoff++) != '/')
1649 if ((tmpoff - offset) > 1) {
1650 int len = tmpoff - offset - 1;
1651 proto_tree *subtree;
1653 ti = proto_tree_add_item(tree, hf_ucp_parm_XSer, tvb, offset, len, ENC_NA);
1654 tmptvb = tvb_new_subset(tvb, offset, len + 1, len + 1);
1655 subtree = proto_item_add_subtree(ti, ett_XSer);
1656 ucp_handle_XSer(subtree, tmptvb);
1659 UcpHandleData(hf_ucp_parm_RES4);
1660 UcpHandleData(hf_ucp_parm_RES5);
1663 #define add_5xR(a, b,c ) add_30R(a, b, c)
1666 add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
1667 { /* 60-series operations */
1670 UcpHandleString(hf_ucp_parm_OAdC);
1671 UcpHandleByte(hf_ucp_parm_OTON);
1672 UcpHandleByte(hf_ucp_parm_ONPI);
1674 UcpHandleByte(hf_ucp_parm_STYP0);
1676 UcpHandleByte(hf_ucp_parm_STYP1);
1678 UcpHandleIRAString(hf_ucp_parm_PWD);
1679 UcpHandleIRAString(hf_ucp_parm_NPWD);
1680 UcpHandleString(hf_ucp_parm_VERS);
1681 UcpHandleString(hf_ucp_parm_LAdC);
1682 UcpHandleByte(hf_ucp_parm_LTON);
1683 UcpHandleByte(hf_ucp_parm_LNPI);
1684 UcpHandleInt(hf_ucp_parm_OPID);
1685 UcpHandleData(hf_ucp_parm_RES1);
1687 UcpHandleData(hf_ucp_parm_RES2);
1691 #define add_6xR(a, b, c) add_01R(a, b, c)
1694 * End of convenient shorthands
1696 #undef UcpHandleString
1697 #undef UcpHandleIRAString
1698 #undef UcpHandleByte
1700 #undef UcpHandleTime
1701 #undef UcpHandleData
1704 * The heuristic dissector
1708 dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1710 conversation_t *conversation;
1714 if (tvb_length(tvb) < UCP_HEADER_SIZE)
1717 if ((tvb_get_guint8(tvb, 0) != UCP_STX) ||
1718 (tvb_get_guint8(tvb, UCP_TRN_OFFSET + UCP_TRN_LEN) != '/') ||
1719 (tvb_get_guint8(tvb, UCP_LEN_OFFSET + UCP_LEN_LEN) != '/') ||
1720 (tvb_get_guint8(tvb, UCP_O_R_OFFSET + UCP_O_R_LEN) != '/') ||
1721 (tvb_get_guint8(tvb, UCP_OT_OFFSET + UCP_OT_LEN) != '/'))
1724 if (match_strval(tvb_get_guint8(tvb, UCP_O_R_OFFSET), vals_hdr_O_R) == NULL)
1728 * Ok, looks like a valid packet
1731 /* Set up a conversation with attached dissector so dissect_ucp_heur
1732 * won't be called any more for this TCP connection.
1735 conversation = find_or_create_conversation(pinfo);
1736 conversation_set_dissector(conversation, ucp_handle);
1738 dissect_ucp_tcp(tvb, pinfo, tree);
1744 get_ucp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1749 offset = offset + 4;
1750 for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
1751 intval = 10 * intval +
1752 (tvb_get_guint8(tvb, offset) - '0');
1761 dissect_ucp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1763 tcp_dissect_pdus(tvb, pinfo, tree, ucp_desegment, UCP_HEADER_SIZE,
1764 get_ucp_pdu_len, dissect_ucp_common);
1767 * The actual dissector
1770 /* We get here only with at least LEN+2 bytes in the buffer */
1773 dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1775 int offset = 0; /* Offset in packet within tvbuff */
1776 guint8 O_R; /* Request or response */
1777 guint8 OT; /* Operation type */
1782 ucp_tap_rec_t* tap_rec; /* Tap record */
1784 /* Set up structures needed to add the protocol subtree and manage it */
1787 proto_tree *ucp_tree;
1788 proto_tree *sub_tree;
1791 /* Make entries in Protocol column */
1792 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
1793 col_clear(pinfo->cinfo, COL_INFO);
1795 if (tvb_get_guint8(tvb, 0) != UCP_STX){
1796 proto_tree_add_text(tree, tvb, 0, -1,"UCP_STX missing, this is not a new packet");
1800 /* Get data needed for dissect_ucp_common */
1801 result = check_ucp(tvb, &endpkt);
1803 O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
1805 * So do an atoi() on the operation type
1807 OT = tvb_get_guint8(tvb, UCP_OT_OFFSET) - '0';
1808 OT = 10 * OT + (tvb_get_guint8(tvb, UCP_OT_OFFSET + 1) - '0');
1810 /* Create Tap record */
1811 tap_rec = ep_alloc0(sizeof(ucp_tap_rec_t));
1812 tap_rec->message_type = (O_R == 'O' ? 0 : 1);
1813 tap_rec->operation = OT;
1815 /* Make entries in Info column on summary display */
1816 if (check_col(pinfo->cinfo, COL_INFO)) {
1817 col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
1818 val_to_str(OT, vals_hdr_OT, "unknown operation"),
1819 val_to_str(O_R, vals_hdr_O_R, "Unknown (%d)"));
1820 if (result == UCP_INV_CHK)
1821 col_append_str(pinfo->cinfo, COL_INFO, " [checksum invalid]");
1824 /* In the interest of speed, if "tree" is NULL, don't do any work not
1825 necessary to generate protocol tree items. */
1828 /* create display subtree for the protocol */
1829 ti = proto_tree_add_item(tree, proto_ucp, tvb, 0, -1, FALSE);
1831 ucp_tree = proto_item_add_subtree(ti, ett_ucp);
1833 * Process the packet here.
1834 * Transaction number
1836 offset++; /* Skip <stx> */
1837 intval = tvb_get_guint8(tvb, offset+0) - '0';
1838 intval = 10 * intval + (tvb_get_guint8(tvb, offset+1) - '0');
1839 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_TRN, tvb, offset,
1840 UCP_TRN_LEN, intval);
1841 offset += UCP_TRN_LEN + 1; /* Skip TN/ */
1844 for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
1845 intval = 10 * intval +
1846 (tvb_get_guint8(tvb, offset+i) - '0');
1848 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_LEN, tvb, offset,
1849 UCP_LEN_LEN, intval);
1850 offset += UCP_LEN_LEN + 1; /* skip LEN/ */
1852 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_O_R, tvb, offset,
1855 offset += UCP_O_R_LEN + 1; /* skip Operation_type/ */
1857 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_OT, tvb, offset,
1859 offset += UCP_OT_LEN;
1862 * Variable part starts here.
1865 tmp_tvb = tvb_new_subset_remaining(tvb, offset);
1866 sub_ti = proto_tree_add_item(ucp_tree, hf_ucp_oper_section, tvb,
1867 offset, endpkt - offset, ENC_NA);
1868 sub_tree = proto_item_add_subtree(sub_ti, ett_sub);
1872 O_R == 'O' ? add_00O(sub_tree,tmp_tvb) : add_00R(sub_tree,tmp_tvb, tap_rec);
1875 O_R == 'O' ? add_01O(sub_tree,tmp_tvb) : add_01R(sub_tree,tmp_tvb, tap_rec);
1878 O_R == 'O' ? add_02O(sub_tree,tmp_tvb) : add_02R(sub_tree,tmp_tvb, tap_rec);
1881 O_R == 'O' ? add_03O(sub_tree,tmp_tvb) : add_03R(sub_tree,tmp_tvb, tap_rec);
1884 O_R == 'O' ? add_04O(sub_tree,tmp_tvb) : add_04R(sub_tree,tmp_tvb, tap_rec);
1887 O_R == 'O' ? add_05O(sub_tree,tmp_tvb) : add_05R(sub_tree,tmp_tvb, tap_rec);
1890 O_R == 'O' ? add_06O(sub_tree,tmp_tvb) : add_06R(sub_tree,tmp_tvb, tap_rec);
1893 O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree,tmp_tvb, tap_rec);
1896 O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree,tmp_tvb, tap_rec);
1899 O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree,tmp_tvb, tap_rec);
1902 O_R == 'O' ? add_10O(sub_tree,tmp_tvb) : add_10R(sub_tree,tmp_tvb, tap_rec);
1905 O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree,tmp_tvb, tap_rec);
1908 O_R == 'O' ? add_12O(sub_tree,tmp_tvb) : add_12R(sub_tree,tmp_tvb, tap_rec);
1911 O_R == 'O' ? add_13O(sub_tree,tmp_tvb) : add_13R(sub_tree,tmp_tvb, tap_rec);
1914 O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree,tmp_tvb, tap_rec);
1917 O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree,tmp_tvb, tap_rec);
1920 O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree,tmp_tvb, tap_rec);
1923 O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree,tmp_tvb, tap_rec);
1926 O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree,tmp_tvb, tap_rec);
1929 O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree,tmp_tvb, tap_rec);
1932 O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree,tmp_tvb, tap_rec);
1935 O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree,tmp_tvb, tap_rec);
1938 O_R == 'O' ? add_22O(sub_tree,tmp_tvb) : add_22R(sub_tree,tmp_tvb, tap_rec);
1941 O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree,tmp_tvb, tap_rec);
1944 O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree,tmp_tvb, tap_rec);
1947 O_R == 'O' ? add_30O(sub_tree,tmp_tvb) : add_30R(sub_tree,tmp_tvb, tap_rec);
1950 O_R == 'O' ? add_31O(sub_tree,tmp_tvb) : add_31R(sub_tree,tmp_tvb, tap_rec);
1952 case 51: case 52: case 53: case 54: case 55: case 56: case 57:
1954 O_R == 'O' ? add_5xO(sub_tree,tmp_tvb) : add_5xR(sub_tree,tmp_tvb, tap_rec);
1957 O_R == 'O' ? add_6xO(sub_tree,tmp_tvb,OT) : add_6xR(sub_tree,tmp_tvb, tap_rec);
1964 /* Queue packet for Tap */
1965 tap_queue_packet(ucp_tap, pinfo, tap_rec);
1970 /* Register the protocol with Wireshark */
1972 proto_register_ucp(void)
1975 /* Setup list of fields */
1976 static hf_register_info hf[] = {
1978 { "Transaction Reference Number", "ucp.hdr.TRN",
1979 FT_UINT8, BASE_DEC, NULL, 0x00,
1980 "Transaction number for this command, used in windowing.",
1985 { "Length", "ucp.hdr.LEN",
1986 FT_UINT16, BASE_DEC, NULL, 0x00,
1987 "Total number of characters between <stx>...<etx>.",
1992 { "Type", "ucp.hdr.O_R",
1993 FT_UINT8, BASE_DEC, VALS(vals_hdr_O_R), 0x00,
1994 "Your basic 'is a request or response'.",
1999 { "Operation", "ucp.hdr.OT",
2000 FT_UINT8, BASE_DEC, VALS(vals_hdr_OT), 0x00,
2001 "The operation that is requested with this message.",
2005 { &hf_ucp_oper_section,
2006 { "Data", "ucp.parm",
2007 FT_NONE, BASE_NONE, NULL, 0x00,
2008 "The actual content of the operation.",
2013 { "AdC", "ucp.parm.AdC",
2014 FT_STRING, BASE_NONE, NULL, 0x00,
2015 "Address code recipient.",
2019 { &hf_ucp_parm_OAdC,
2020 { "OAdC", "ucp.parm.OAdC",
2021 FT_STRING, BASE_NONE, NULL, 0x00,
2022 "Address code originator.",
2026 { &hf_ucp_parm_DAdC,
2027 { "DAdC", "ucp.parm.DAdC",
2028 FT_STRING, BASE_NONE, NULL, 0x00,
2029 "Diverted address code.",
2034 { "AC", "ucp.parm.AC",
2035 FT_STRING, BASE_NONE, NULL, 0x00,
2036 "Authentication code.",
2041 { "OAC", "ucp.parm.OAC",
2042 FT_STRING, BASE_NONE, NULL, 0x00,
2043 "Authentication code, originator.",
2048 { "NAC", "ucp.parm.NAC",
2049 FT_STRING, BASE_NONE, NULL, 0x00,
2050 "New authentication code.",
2055 { "BAS", "ucp.parm.BAS",
2056 FT_UINT8, BASE_DEC, VALS(vals_parm_BAS), 0x00,
2057 "Barring status flag.",
2062 { "LAR", "ucp.parm.LAR",
2063 FT_UINT8, BASE_DEC, VALS(vals_parm_LAR), 0x00,
2064 "Leg. code for all calls flag.",
2069 { "LAC", "ucp.parm.LAC",
2070 FT_STRING, BASE_NONE, NULL, 0x00,
2071 "New leg. code for all calls.",
2076 { "L1R", "ucp.parm.L1R",
2077 FT_UINT8, BASE_DEC, VALS(vals_parm_L1R), 0x00,
2078 "Leg. code for priority 1 flag.",
2083 { "L1P", "ucp.parm.L1P",
2084 FT_STRING, BASE_NONE, NULL, 0x00,
2085 "New leg. code for level 1 priority.",
2090 { "L3R", "ucp.parm.L3R",
2091 FT_UINT8, BASE_DEC, VALS(vals_parm_L3R), 0x00,
2092 "Leg. code for priority 3 flag.",
2097 { "L3P", "ucp.parm.L3P",
2098 FT_STRING, BASE_NONE, NULL, 0x00,
2099 "New leg. code for level 3 priority.",
2104 { "LCR", "ucp.parm.LCR",
2105 FT_UINT8, BASE_DEC, VALS(vals_parm_LCR), 0x00,
2106 "Leg. code for reverse charging flag.",
2111 { "LUR", "ucp.parm.LUR",
2112 FT_UINT8, BASE_DEC, VALS(vals_parm_LUR), 0x00,
2113 "Leg. code for urgent message flag.",
2118 { "LRR", "ucp.parm.LRR",
2119 FT_UINT8, BASE_DEC, VALS(vals_parm_LRR), 0x00,
2120 "Leg. code for repetition flag.",
2125 { "RT", "ucp.parm.RT",
2126 FT_UINT8, BASE_DEC, VALS(vals_parm_RT), 0x00,
2132 { "NoN", "ucp.parm.NoN",
2133 FT_UINT16, BASE_DEC, NULL, 0x00,
2134 "Maximum number of numerical characters accepted.",
2139 { "NoA", "ucp.parm.NoA",
2140 FT_UINT16, BASE_DEC, NULL, 0x00,
2141 "Maximum number of alphanumerical characters accepted.",
2146 { "NoB", "ucp.parm.NoB",
2147 FT_UINT16, BASE_DEC, NULL, 0x00,
2148 "Maximum number of data bits accepted.",
2153 { "PNC", "ucp.parm.PNC",
2154 FT_UINT8, BASE_DEC, VALS(vals_parm_PNC), 0x00,
2155 "Paging network controller.",
2159 { &hf_ucp_parm_AMsg,
2160 { "AMsg", "ucp.parm.AMsg",
2161 FT_STRING, BASE_NONE, NULL, 0x00,
2162 "The alphanumeric message that is being sent.",
2167 { "LNo", "ucp.parm.LNo",
2168 FT_STRING, BASE_NONE, NULL, 0x00,
2169 "Standard text list number requested by calling party.",
2174 { "LST", "ucp.parm.LST",
2175 FT_STRING, BASE_NONE, NULL, 0x00,
2176 "Legitimisation code for standard text.",
2181 { "TNo", "ucp.parm.TNo",
2182 FT_STRING, BASE_NONE, NULL, 0x00,
2183 "Standard text number requested by calling party.",
2188 { "CS", "ucp.parm.CS",
2189 FT_UINT8, BASE_DEC, NULL, 0x00,
2190 "Additional character set number.",
2195 { "PID", "ucp.parm.PID",
2196 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2202 { "NPL", "ucp.parm.NPL",
2203 FT_UINT16, BASE_DEC, NULL, 0x00,
2204 "Number of parameters in the following list.",
2209 { "GA", "ucp.parm.GA",
2210 FT_STRING, BASE_NONE, NULL, 0x00,
2211 "GA?? haven't got a clue.",
2216 { "RP", "ucp.parm.RP",
2217 FT_UINT8, BASE_DEC, VALS(vals_parm_RP), 0x00,
2218 "Repetition requested.",
2223 { "LRP", "ucp.parm.LRP",
2224 FT_STRING, BASE_NONE, NULL, 0x00,
2225 "Legitimisation code for repetition.",
2230 { "PR", "ucp.parm.PR",
2231 FT_UINT8, BASE_DEC, NULL, 0x00,
2232 "Priority requested.",
2237 { "LPR", "ucp.parm.LPR",
2238 FT_STRING, BASE_NONE, NULL, 0x00,
2239 "Legitimisation code for priority requested.",
2244 { "UM", "ucp.parm.UM",
2245 FT_UINT8, BASE_DEC, VALS(vals_parm_UM), 0x00,
2246 "Urgent message indicator.",
2251 { "LUM", "ucp.parm.LUM",
2252 FT_STRING, BASE_NONE, NULL, 0x00,
2253 "Legitimisation code for urgent message.",
2258 { "RC", "ucp.parm.RC",
2259 FT_UINT8, BASE_DEC, VALS(vals_parm_RC), 0x00,
2260 "Reverse charging request.",
2265 { "LRC", "ucp.parm.LRC",
2266 FT_STRING, BASE_NONE, NULL, 0x00,
2267 "Legitimisation code for reverse charging.",
2272 { "NRq", "ucp.parm.NRq",
2273 FT_UINT8, BASE_DEC, VALS(vals_parm_NRq), 0x00,
2274 "Notification request.",
2278 { &hf_ucp_parm_GAdC,
2279 { "GAdC", "ucp.parm.GAdC",
2280 FT_STRING, BASE_NONE, NULL, 0x00,
2281 "Group address code.",
2286 { "A_D", "ucp.parm.A_D",
2287 FT_UINT8, BASE_DEC, VALS(vals_parm_A_D), 0x00,
2288 "Add to/delete from fixed subscriber address list record.",
2293 { "CT", "ucp.parm.CT",
2294 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2295 "Accumulated charges timestamp.",
2300 { "AAC", "ucp.parm.AAC",
2301 FT_STRING, BASE_NONE, NULL, 0x00,
2302 "Accumulated charges.",
2307 { "MNo", "ucp.parm.MNo",
2308 FT_STRING, BASE_NONE, NULL, 0x00,
2314 { "R_T", "ucp.parm.R_T",
2315 FT_UINT8, BASE_DEC, VALS(vals_parm_R_T), 0x00,
2320 { &hf_ucp_parm_NAdC,
2321 { "NAdC", "ucp.parm.NAdC",
2322 FT_STRING, BASE_NONE, NULL, 0x00,
2323 "Notification address.",
2328 { "NT", "ucp.parm.NT",
2329 FT_UINT8, BASE_DEC, VALS(vals_parm_NT), 0x00,
2330 "Notification type.",
2334 { &hf_ucp_parm_IVR5x,
2335 { "IVR5x", "ucp.parm.IVR5x",
2336 FT_STRING, BASE_NONE, NULL, 0x00,
2337 "UCP release number supported/accepted.",
2341 { &hf_ucp_parm_REQ_OT,
2342 { "REQ_OT", "ucp.parm.REQ_OT",
2343 FT_UINT8, BASE_DEC, VALS(vals_parm_REQ_OT), 0x00,
2344 "UCP release number supported/accepted.",
2348 { &hf_ucp_parm_SSTAT,
2349 { "SSTAT", "ucp.parm.SSTAT",
2350 FT_UINT8, BASE_DEC, VALS(vals_parm_SSTAT), 0x00,
2351 "Supplementary services for which status is requested.",
2356 { "LMN", "ucp.parm.LMN",
2357 FT_UINT8, BASE_DEC, NULL, 0x00,
2358 "Last message number.",
2362 { &hf_ucp_parm_NMESS,
2363 { "NMESS", "ucp.parm.NMESS",
2364 FT_UINT8, BASE_DEC, NULL, 0x00,
2365 "Number of stored messages.",
2369 { &hf_ucp_parm_NMESS_str,
2370 { "NMESS_str", "ucp.parm.NMESS_str",
2371 FT_STRING, BASE_NONE, NULL, 0x00,
2372 "Number of stored messages.",
2376 { &hf_ucp_parm_NPID,
2377 { "NPID", "ucp.parm.NPID",
2378 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2379 "Notification PID value.",
2384 { "LRq", "ucp.parm.LRq",
2385 FT_UINT8, BASE_DEC, VALS(vals_parm_LRq), 0x00,
2386 "Last resort address request.",
2390 { &hf_ucp_parm_LRAd,
2391 { "LRAd", "ucp.parm.LRAd",
2392 FT_STRING, BASE_NONE, NULL, 0x00,
2393 "Last resort address.",
2397 { &hf_ucp_parm_LPID,
2398 { "LPID", "ucp.parm.LPID",
2399 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2400 "Last resort PID value.",
2405 { "DD", "ucp.parm.DD",
2406 FT_UINT8, BASE_DEC, VALS(vals_parm_DD), 0x00,
2407 "Deferred delivery requested.",
2412 { "DDT", "ucp.parm.DDT",
2413 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2414 "Deferred delivery time.",
2419 { "STx", "ucp.parm.STx",
2420 FT_NONE, BASE_NONE, NULL, 0x00,
2426 { "ST", "ucp.parm.ST",
2427 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2433 { "SP", "ucp.parm.SP",
2434 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2440 { "VP", "ucp.parm.VP",
2441 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2446 { &hf_ucp_parm_RPID,
2447 { "RPID", "ucp.parm.RPID",
2448 FT_STRING, BASE_NONE, NULL, 0x00,
2453 { &hf_ucp_parm_SCTS,
2454 { "SCTS", "ucp.parm.SCTS",
2455 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2456 "Service Centre timestamp.",
2461 { "Dst", "ucp.parm.Dst",
2462 FT_UINT8, BASE_DEC, VALS(vals_parm_Dst), 0x00,
2468 { "Rsn", "ucp.parm.Rsn",
2469 FT_UINT16, BASE_DEC, VALS(vals_parm_Rsn), 0x00,
2474 { &hf_ucp_parm_DSCTS,
2475 { "DSCTS", "ucp.parm.DSCTS",
2476 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2477 "Delivery timestamp.",
2482 { "MT", "ucp.parm.MT",
2483 FT_UINT8, BASE_DEC, VALS(vals_parm_MT), 0x00,
2489 { "NB", "ucp.parm.NB",
2490 FT_STRING, BASE_NONE, NULL, 0x00,
2491 "No. of bits in Transparent Data (TD) message.",
2495 { &hf_ucp_data_section,
2496 { "Data", "ucp.message",
2497 FT_NONE, BASE_NONE, NULL, 0x00,
2498 "The actual message or data.",
2503 { "MMS", "ucp.parm.MMS",
2504 FT_UINT8, BASE_DEC, NULL, 0x00,
2505 "More messages to send.",
2510 { "DCs", "ucp.parm.DCs",
2511 FT_UINT8, BASE_DEC, VALS(vals_parm_DCs), 0x00,
2512 "Data coding scheme (deprecated).",
2516 { &hf_ucp_parm_MCLs,
2517 { "MCLs", "ucp.parm.MCLs",
2518 FT_UINT8, BASE_DEC, VALS(vals_parm_MCLs), 0x00,
2524 { "RPI", "ucp.parm.RPI",
2525 FT_UINT8, BASE_DEC, VALS(vals_parm_RPI), 0x00,
2531 { "CPg", "ucp.parm.CPg",
2532 FT_STRING, BASE_NONE, NULL, 0x00,
2533 "Reserved for Code Page.",
2537 { &hf_ucp_parm_RPLy,
2538 { "RPLy", "ucp.parm.RPLy",
2539 FT_STRING, BASE_NONE, NULL, 0x00,
2540 "Reserved for Reply type.",
2544 { &hf_ucp_parm_OTOA,
2545 { "OTOA", "ucp.parm.OTOA",
2546 FT_STRING, BASE_NONE, NULL, 0x00,
2547 "Originator Type Of Address.",
2551 { &hf_ucp_parm_HPLMN,
2552 { "HPLMN", "ucp.parm.HPLMN",
2553 FT_STRING, BASE_NONE, NULL, 0x00,
2554 "Home PLMN address.",
2558 { &hf_ucp_parm_XSer,
2559 { "Extra services:", "ucp.parm.XSer",
2560 FT_NONE, BASE_NONE, NULL, 0x00,
2565 { &hf_ucp_parm_RES4,
2566 { "RES4", "ucp.parm.RES4",
2567 FT_STRING, BASE_NONE, NULL, 0x00,
2568 "Reserved for future use.",
2572 { &hf_ucp_parm_RES5,
2573 { "RES5", "ucp.parm.RES5",
2574 FT_STRING, BASE_NONE, NULL, 0x00,
2575 "Reserved for future use.",
2579 { &hf_ucp_parm_OTON,
2580 { "OTON", "ucp.parm.OTON",
2581 FT_UINT8, BASE_DEC, VALS(vals_parm_OTON), 0x00,
2582 "Originator type of number.",
2586 { &hf_ucp_parm_ONPI,
2587 { "ONPI", "ucp.parm.ONPI",
2588 FT_UINT8, BASE_DEC, VALS(vals_parm_ONPI), 0x00,
2589 "Originator numbering plan id.",
2593 { &hf_ucp_parm_STYP0,
2594 { "STYP0", "ucp.parm.STYP0",
2595 FT_UINT8, BASE_DEC, VALS(vals_parm_STYP0), 0x00,
2596 "Subtype of operation.",
2600 { &hf_ucp_parm_STYP1,
2601 { "STYP1", "ucp.parm.STYP1",
2602 FT_UINT8, BASE_DEC, VALS(vals_parm_STYP1), 0x00,
2603 "Subtype of operation.",
2608 { "PWD", "ucp.parm.PWD",
2609 FT_STRING, BASE_NONE, NULL, 0x00,
2610 "Current password.",
2614 { &hf_ucp_parm_NPWD,
2615 { "NPWD", "ucp.parm.NPWD",
2616 FT_STRING, BASE_NONE, NULL, 0x00,
2621 { &hf_ucp_parm_VERS,
2622 { "VERS", "ucp.parm.VERS",
2623 FT_STRING, BASE_NONE, NULL, 0x00,
2628 { &hf_ucp_parm_LAdC,
2629 { "LAdC", "ucp.parm.LAdC",
2630 FT_STRING, BASE_NONE, NULL, 0x00,
2631 "Address for VSMSC list operation.",
2635 { &hf_ucp_parm_LTON,
2636 { "LTON", "ucp.parm.LTON",
2637 FT_UINT8, BASE_DEC, NULL, 0x00,
2638 "Type of number list address.",
2642 { &hf_ucp_parm_LNPI,
2643 { "LNPI", "ucp.parm.LNPI",
2644 FT_UINT8, BASE_DEC, NULL, 0x00,
2645 "Numbering plan id. list address.",
2649 { &hf_ucp_parm_OPID,
2650 { "OPID", "ucp.parm.OPID",
2651 FT_UINT8, BASE_DEC, VALS(vals_parm_OPID), 0x00,
2652 "Originator protocol identifier.",
2656 { &hf_ucp_parm_RES1,
2657 { "RES1", "ucp.parm.RES1",
2658 FT_STRING, BASE_NONE, NULL, 0x00,
2659 "Reserved for future use.",
2663 { &hf_ucp_parm_RES2,
2664 { "RES2", "ucp.parm.RES2",
2665 FT_STRING, BASE_NONE, NULL, 0x00,
2666 "Reserved for future use.",
2671 { "(N)Ack", "ucp.parm.ACK",
2672 FT_UINT8, BASE_DEC, VALS(vals_parm_ACK), 0x00,
2673 "Positive or negative acknowledge of the operation.",
2678 { "MVP", "ucp.parm.MVP",
2679 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
2680 "Modified validity period.",
2685 { "Error code", "ucp.parm.EC",
2686 FT_UINT8, BASE_DEC, VALS(vals_parm_EC), 0x00,
2687 "The result of the requested operation.",
2692 { "SM", "ucp.parm.SM",
2693 FT_STRING, BASE_NONE, NULL, 0x00,
2699 { "Type of service", "ucp.xser.service",
2700 FT_UINT8, BASE_HEX, VALS(vals_xser_service), 0x00,
2701 "The type of service specified.",
2706 { "Length", "ucp.xser.length",
2707 FT_UINT16, BASE_DEC, NULL, 0x00,
2713 { "Data", "ucp.xser.data",
2714 FT_STRING, BASE_NONE, NULL, 0x00,
2720 /* Setup protocol subtree array */
2721 static gint *ett[] = {
2726 module_t *ucp_module;
2728 /* Register the protocol name and description */
2729 proto_ucp = proto_register_protocol("Universal Computer Protocol",
2732 /* Required function calls to register header fields and subtrees used */
2733 proto_register_field_array(proto_ucp, hf, array_length(hf));
2734 proto_register_subtree_array(ett, array_length(ett));
2736 /* Register for tapping */
2737 ucp_tap = register_tap("ucp");
2739 /* register preferences */
2740 ucp_module = prefs_register_protocol(proto_ucp, NULL);
2741 prefs_register_bool_preference(ucp_module, "desegment_ucp_messages",
2742 "Reassemble UCP messages spanning multiple TCP segments",
2743 "Whether the UCP dissector should reassemble messages spanning"
2744 " multiple TCP segments."
2745 " To use this option, you must also enable "
2746 "\"Allow subdissectors to reassemble TCP streams\" in the "
2747 "TCP protocol settings.",
2753 proto_reg_handoff_ucp(void)
2756 * UCP can be spoken on any port so, when not on a specific port, try heuristic
2757 * whenever TCP is spoken.
2759 heur_dissector_add("tcp", dissect_ucp_heur, proto_ucp);
2762 * Also register as a dissectoir that can be selected by a TCP port number via "decode as".
2764 ucp_handle = create_dissector_handle(dissect_ucp_tcp, proto_ucp);
2765 dissector_add_handle("tcp.port", ucp_handle);
2768 stats_tree_register_with_group("ucp", "ucp_messages", "_UCP Messages", 0,
2769 ucp_stats_tree_per_packet, ucp_stats_tree_init,
2770 NULL, REGISTER_STAT_GROUP_TELEPHONY);