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>
48 #include <epan/packet.h>
49 #include <epan/prefs.h>
50 #include <epan/emem.h>
51 #include <epan/stats_tree.h>
53 #include "packet-tcp.h"
56 static void dissect_ucp_common(tvbuff_t *, packet_info *, proto_tree *);
59 typedef struct _ucp_tap_rec_t {
60 guint message_type; /* 0 = Operation; 1 = Result */
61 guint operation; /* Operation Type */
62 guint result; /* 0 = Success; Non 0 = Error Code */
66 gboolean ucp_desegment = TRUE;
67 /* STX + TRN 2 num. char.+ LEN 5 num. char. + O/R Char 'O' or 'R' + OT 2 num. char. */
68 #define UCP_HEADER_SIZE 11
71 * Convert ASCII-hex character to binary equivalent. No checks, assume
72 * is valid hex character.
74 #define AHex2Bin(n) (((n) & 0x40) ? ((n) & 0x0F) + 9 : ((n) & 0x0F))
76 #define UCP_STX 0x02 /* Start of UCP PDU */
77 #define UCP_ETX 0x03 /* End of UCP PDU */
79 #define UCP_MALFORMED -1 /* Not a valid PDU */
80 #define UCP_SHORTENED -2 /* May be valid but short */
81 #define UCP_INV_CHK -3 /* Checksum doesn't add up */
83 #define UCP_O_R_OFFSET 10 /* Location of O/R field*/
84 #define UCP_OT_OFFSET 12 /* Location of OT field */
86 #define UCP_TRN_LEN 2 /* Length of TRN-field */
87 #define UCP_LEN_LEN 5 /* Length of LEN-field */
88 #define UCP_O_R_LEN 1 /* Length of O/R-field */
89 #define UCP_OT_LEN 2 /* Length of OT-field */
92 * Initialize the protocol and registered fields
94 * Header (fixed) section
96 static int proto_ucp = -1;
98 static int hf_ucp_hdr_TRN = -1;
99 static int hf_ucp_hdr_LEN = -1;
100 static int hf_ucp_hdr_O_R = -1;
101 static int hf_ucp_hdr_OT = -1;
106 static int st_ucp_messages = -1;
107 static int st_ucp_ops = -1;
108 static int st_ucp_res = -1;
109 static int st_ucp_results = -1;
110 static int st_ucp_results_pos = -1;
111 static int st_ucp_results_neg = -1;
113 static gchar* st_str_ucp = "UCP Messages";
114 static gchar* st_str_ops = "Operations";
115 static gchar* st_str_res = "Results";
116 static gchar* st_str_ucp_res = "UCP Results Acks/Nacks";
117 static gchar* st_str_pos = "Positive";
118 static gchar* st_str_neg = "Negative";
121 * Data (variable) section
123 static int hf_ucp_oper_section = -1;
124 static int hf_ucp_parm_AdC = -1;
125 static int hf_ucp_parm_OAdC = -1;
126 static int hf_ucp_parm_DAdC = -1;
127 static int hf_ucp_parm_AC = -1;
128 static int hf_ucp_parm_OAC = -1;
129 static int hf_ucp_parm_BAS = -1;
130 static int hf_ucp_parm_LAR = -1;
131 static int hf_ucp_parm_LAC = -1;
132 static int hf_ucp_parm_L1R = -1;
133 static int hf_ucp_parm_L1P = -1;
134 static int hf_ucp_parm_L3R = -1;
135 static int hf_ucp_parm_L3P = -1;
136 static int hf_ucp_parm_LCR = -1;
137 static int hf_ucp_parm_LUR = -1;
138 static int hf_ucp_parm_LRR = -1;
139 static int hf_ucp_parm_RT = -1;
140 static int hf_ucp_parm_NoN = -1;
141 static int hf_ucp_parm_NoA = -1;
142 static int hf_ucp_parm_NoB = -1;
143 static int hf_ucp_parm_NAC = -1;
144 static int hf_ucp_parm_PNC = -1;
145 static int hf_ucp_parm_AMsg = -1;
146 static int hf_ucp_parm_LNo = -1;
147 static int hf_ucp_parm_LST = -1;
148 static int hf_ucp_parm_TNo = -1;
149 static int hf_ucp_parm_CS = -1;
150 static int hf_ucp_parm_PID = -1;
151 static int hf_ucp_parm_NPL = -1;
152 static int hf_ucp_parm_GA = -1;
153 static int hf_ucp_parm_RP = -1;
154 static int hf_ucp_parm_LRP = -1;
155 static int hf_ucp_parm_PR = -1;
156 static int hf_ucp_parm_LPR = -1;
157 static int hf_ucp_parm_UM = -1;
158 static int hf_ucp_parm_LUM = -1;
159 static int hf_ucp_parm_RC = -1;
160 static int hf_ucp_parm_LRC = -1;
161 static int hf_ucp_parm_NRq = -1;
162 static int hf_ucp_parm_GAdC = -1;
163 static int hf_ucp_parm_A_D = -1;
164 static int hf_ucp_parm_CT = -1;
165 static int hf_ucp_parm_AAC = -1;
166 static int hf_ucp_parm_MNo = -1;
167 static int hf_ucp_parm_R_T = -1;
168 static int hf_ucp_parm_IVR5x = -1;
169 static int hf_ucp_parm_REQ_OT = -1;
170 static int hf_ucp_parm_SSTAT = -1;
171 static int hf_ucp_parm_LMN = -1;
172 static int hf_ucp_parm_NMESS = -1;
173 static int hf_ucp_parm_NMESS_str= -1;
174 static int hf_ucp_parm_NAdC = -1;
175 static int hf_ucp_parm_NT = -1;
176 static int hf_ucp_parm_NPID = -1;
177 static int hf_ucp_parm_LRq = -1;
178 static int hf_ucp_parm_LRAd = -1;
179 static int hf_ucp_parm_LPID = -1;
180 static int hf_ucp_parm_DD = -1;
181 static int hf_ucp_parm_DDT = -1;
182 static int hf_ucp_parm_STx = -1;
183 static int hf_ucp_parm_ST = -1;
184 static int hf_ucp_parm_SP = -1;
185 static int hf_ucp_parm_VP = -1;
186 static int hf_ucp_parm_RPID = -1;
187 static int hf_ucp_parm_SCTS = -1;
188 static int hf_ucp_parm_Dst = -1;
189 static int hf_ucp_parm_Rsn = -1;
190 static int hf_ucp_parm_DSCTS = -1;
191 static int hf_ucp_parm_MT = -1;
192 static int hf_ucp_parm_NB = -1;
193 static int hf_ucp_data_section = -1;
194 static int hf_ucp_parm_MMS = -1;
195 static int hf_ucp_parm_DCs = -1;
196 static int hf_ucp_parm_MCLs = -1;
197 static int hf_ucp_parm_RPI = -1;
198 static int hf_ucp_parm_CPg = -1;
199 static int hf_ucp_parm_RPLy = -1;
200 static int hf_ucp_parm_OTOA = -1;
201 static int hf_ucp_parm_HPLMN = -1;
202 static int hf_ucp_parm_RES4 = -1;
203 static int hf_ucp_parm_RES5 = -1;
204 static int hf_ucp_parm_OTON = -1;
205 static int hf_ucp_parm_ONPI = -1;
206 static int hf_ucp_parm_STYP0 = -1;
207 static int hf_ucp_parm_STYP1 = -1;
208 static int hf_ucp_parm_ACK = -1;
209 static int hf_ucp_parm_PWD = -1;
210 static int hf_ucp_parm_NPWD = -1;
211 static int hf_ucp_parm_VERS = -1;
212 static int hf_ucp_parm_LAdC = -1;
213 static int hf_ucp_parm_LTON = -1;
214 static int hf_ucp_parm_LNPI = -1;
215 static int hf_ucp_parm_OPID = -1;
216 static int hf_ucp_parm_RES1 = -1;
217 static int hf_ucp_parm_RES2 = -1;
218 static int hf_ucp_parm_MVP = -1;
219 static int hf_ucp_parm_EC = -1;
220 static int hf_ucp_parm_SM = -1;
222 static int hf_ucp_parm_XSer = -1;
223 static int hf_xser_service = -1;
225 /* Initialize the subtree pointers */
226 static gint ett_ucp = -1;
227 static gint ett_sub = -1;
228 static gint ett_XSer = -1;
231 static int ucp_tap = -1;
234 * Value-arrays for certain field-contents
236 static const value_string vals_hdr_O_R[] = {
237 { 'O', "Operation" },
242 static const value_string vals_hdr_OT[] = { /* Operation type */
245 { 2, "Call input (multiple address)" },
246 { 3, "Call input (supplementary services included)" },
247 { 4, "Address list information" },
248 { 5, "Change address list" },
249 { 6, "Advice of accumulated charges" },
250 { 7, "Password management" },
251 { 8, "Legitimisation code management" },
252 { 9, "Standard text information" },
253 { 10, "Change standard text" },
254 { 11, "Request roaming information" },
255 { 12, "Change roaming information" },
256 { 13, "Roaming reset" },
257 { 14, "Message retrieval" },
258 { 15, "Request call barring" },
259 { 16, "Cancel call barring" },
260 { 17, "Request call diversion" },
261 { 18, "Cancel call diversion" },
262 { 19, "Request deferred delivery" },
263 { 20, "Cancel deferred delivery" },
264 { 21, "All features reset" },
265 { 22, "Call input (with specific character set)" },
266 { 23, "UCP version status request" },
267 { 24, "Mobile subscriber feature status request" },
268 { 30, "SMS message transfer" },
270 { 32, "(proprietary)" },
271 { 34, "(proprietary)" },
272 { 36, "(proprietary)" },
273 { 38, "(proprietary)" },
274 { 40, "(proprietary)" },
275 { 41, "(proprietary)" },
276 { 42, "(proprietary)" },
277 { 43, "(proprietary)" },
278 { 44, "(proprietary)" },
279 { 45, "(proprietary)" },
280 { 51, "Submit short message" },
281 { 52, "Deliver short message" },
282 { 53, "Deliver notification" },
283 { 54, "Modify message" },
284 { 55, "Inquiry message" },
285 { 56, "Delete message" },
286 { 57, "Inquiry response message" },
287 { 58, "Delete response message" },
288 { 60, "Session management" },
289 { 61, "List management" },
290 { 95, "(proprietary)" },
291 { 96, "(proprietary)" },
292 { 97, "(proprietary)" },
293 { 98, "(proprietary)" },
294 { 99, "(proprietary)" },
298 static const value_string vals_parm_EC[] = { /* Error code */
299 { 1, "Checksum error" },
300 { 2, "Syntax error" },
301 { 3, "Operation not supported by system" },
302 { 4, "Operation not allowed" },
303 { 5, "Call barring active" },
304 { 6, "AdC invalid" },
305 { 7, "Authentication failure" },
306 { 8, "Legitimisation code for all calls, failure" },
307 { 9, "GA not valid" },
308 { 10, "Repetition not allowed" },
309 { 11, "Legitimisation code for repetition, failure" },
310 { 12, "Priority call not allowed" },
311 { 13, "Legitimisation code for priority call, failure" },
312 { 14, "Urgent message not allowed" },
313 { 15, "Legitimisation code for urgent message, failure" },
314 { 16, "Reverse charging not allowed" },
315 { 17, "Legitimisation code for rev. charging, failure" },
316 { 18, "Deferred delivery not allowed" },
317 { 19, "New AC not valid" },
318 { 20, "New legitimisation code not valid" },
319 { 21, "Standard text not valid" },
320 { 22, "Time period not valid" },
321 { 23, "Message type not supported by system" },
322 { 24, "Message too long" },
323 { 25, "Requested standard text not valid" },
324 { 26, "Message type not valid for the pager type" },
325 { 27, "Message not found in SMSC" },
326 { 28, "Invalid character set" },
327 { 30, "Subscriber hang-up" },
328 { 31, "Fax group not supported" },
329 { 32, "Fax message type not supported" },
330 { 33, "Address already in list (60-series)" },
331 { 34, "Address not in list (60-series)" },
332 { 35, "List full, cannot add address to list (60-series)" },
333 { 36, "RPID already in use" },
334 { 37, "Delivery in progress" },
335 { 38, "Message forwarded" },
336 { 50, "Low network status" },
337 { 51, "Legitimisation code for standard text, failure" },
338 { 53, "Operation partially successful" },
339 { 54, "Operation not successful" },
340 { 55, "System error" },
341 { 57, "AdC already a member of GAdC address list" },
342 { 58, "AdC not a member of GAdC address list" },
343 { 59, "Requested standard text list invalid" },
344 { 61, "Not controller of GAdC address list" },
345 { 62, "Standard text too large" },
346 { 63, "Not owner of standard text list" },
347 { 64, "Address list full" },
348 { 65, "GAdC invalid" },
349 { 66, "Operation restricted to mobile subscribers" },
350 { 68, "Invalid AdC type" },
351 { 69, "Cannot add AdC to GAdC address list" },
352 { 90, "(proprietary error code)" },
353 { 91, "(proprietary error code)" },
354 { 92, "(proprietary error code)" },
355 { 93, "(proprietary error code)" },
356 { 94, "(proprietary error code)" },
357 { 95, "(proprietary error code)" },
358 { 96, "(proprietary error code)" },
359 { 97, "(proprietary error code)" },
360 { 98, "(proprietary error code)" },
361 { 99, "(proprietary error code)" },
365 static const value_string vals_parm_NRq[] = {
366 { '0', "NAdC not used" },
367 { '1', "NAdC used" },
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" },
383 static const value_string vals_parm_PID[] = {
384 { 100, "Mobile station" },
385 { 122, "Fax Group 3" },
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" },
395 static const value_string vals_parm_LRq[] = {
396 { '0', "LRAd not used" },
397 { '1', "LRAd used" },
401 static const value_string vals_parm_DD[] = {
402 { '0', "DDT not used" },
407 static const value_string vals_parm_Dst[] = {
408 { '0', "delivered" },
409 { '1', "buffered (see Rsn)" },
410 { '2', "not delivered (see Rsn)" },
414 static const value_string vals_parm_Rsn[] = {
415 { 0, "Unknown subscriber" },
416 { 1, "Service temporary not available" },
417 { 2, "Service temporary not available" },
418 { 3, "Service temporary not available" },
419 { 4, "Service temporary not available" },
420 { 5, "Service temporary not available" },
421 { 6, "Service temporary not available" },
422 { 7, "Service temporary not available" },
423 { 8, "Service temporary not available" },
424 { 9, "Illegal error code" },
425 { 10, "Network time-out" },
426 { 100, "Facility not supported" },
427 { 101, "Unknown subscriber" },
428 { 102, "Facility not provided" },
429 { 103, "Call barred" },
430 { 104, "Operation barred" },
431 { 105, "SC congestion" },
432 { 106, "Facility not supported" },
433 { 107, "Absent subscriber" },
434 { 108, "Delivery fail" },
435 { 109, "Sc congestion" },
436 { 110, "Protocol error" },
437 { 111, "MS not equipped" },
438 { 112, "Unknown SC" },
439 { 113, "SC congestion" },
440 { 114, "Illegal MS" },
441 { 115, "MS nota subscriber" },
442 { 116, "Error in MS" },
443 { 117, "SMS lower layer not provisioned" },
444 { 118, "System fail" },
445 { 119, "PLMN system failure" },
446 { 120, "HLR system failure" },
447 { 121, "VLR system failure" },
448 { 122, "Previous VLR system failure" },
449 { 123, "Controlling MSC system failure" },
450 { 124, "VMSC system failure" },
451 { 125, "EIR system failure" },
452 { 126, "System failure" },
453 { 127, "Unexpected data value" },
454 { 200, "Error in address service centre" },
455 { 201, "Invalid absolute validity period" },
456 { 202, "Short message exceeds maximum" },
457 { 203, "Unable to unpack GSM message" },
458 { 204, "Unable to convert to IRA alphabet" },
459 { 205, "Invalid validity period format" },
460 { 206, "Invalid destination address" },
461 { 207, "Duplicate message submit" },
462 { 208, "Invalid message type indicator" },
466 static const value_string vals_parm_MT[] = {
467 { '2', "Numeric message" },
468 { '3', "Alphanumeric message" },
469 { '4', "Transparent data" },
473 static const value_string vals_parm_DCs[] = {
474 { '0', "default alphabet" },
475 { '1', "User defined data (8 bit)" },
479 static const value_string vals_parm_MCLs[] = {
480 { '0', "message class 0" },
481 { '1', "message class 1" },
482 { '2', "message class 2" },
483 { '3', "message class 3" },
487 static const value_string vals_parm_RPI[] = {
493 static const value_string vals_parm_ACK[] = {
499 static const value_string vals_parm_RP[] = {
500 { '1', "Repetition requested" },
504 static const value_string vals_parm_UM[] = {
505 { '1', "Urgent message" },
509 static const value_string vals_parm_RC[] = {
510 { '1', "Reverse charging request" },
514 static const value_string vals_parm_OTON[] = {
515 { '1', "International number" },
516 { '2', "National number" },
517 { '6', "Abbreviated number (short number alias)" },
521 static const value_string vals_parm_ONPI[] = {
522 { '1', "E.164 address" },
523 { '3', "X.121 address" },
524 { '5', "Private -TCP/IP or abbreviated number- address" },
528 static const value_string vals_parm_STYP0[] = {
529 { '1', "open session" },
531 { '3', "change password" },
532 { '4', "open provisioning session" },
534 { '6', "change provisioning password" },
538 static const value_string vals_parm_STYP1[] = {
539 { '1', "add item to mo-list" },
540 { '2', "remove item from mo-list" },
541 { '3', "verify item mo-list" },
542 { '4', "add item to mt-list" },
543 { '5', "remove item from mt-list" },
544 { '6', "verify item mt-list" },
548 static const value_string vals_parm_OPID[] = {
549 { 0, "Mobile station" },
550 { 39, "PC application" },
554 static const value_string vals_parm_BAS[] = {
559 static const value_string vals_parm_LAR[] = {
560 { '1', "Leg. code for all calls requested" },
564 static const value_string vals_parm_L1R[] = {
565 { '1', "Leg. code for priority 1 requested" },
569 static const value_string vals_parm_L3R[] = {
570 { '1', "Leg. code for priority 3 requested" },
574 static const value_string vals_parm_LCR[] = {
575 { '1', "Leg. code for reverse charging requested" },
579 static const value_string vals_parm_LUR[] = {
580 { '1', "Leg. code for urgent message requested" },
584 static const value_string vals_parm_LRR[] = {
585 { '1', "Leg. code for repetition requested" },
589 static const value_string vals_parm_RT[] = {
590 { '1', "Tone only" },
592 { '3', "Alphanumeric" },
593 { '4', "Transparent data" },
597 static const value_string vals_parm_PNC[] = {
599 { 'I', "Input PNC" },
603 static const value_string vals_parm_A_D[] = {
609 static const value_string vals_parm_R_T[] = {
610 { 'R', "Retrieval Ok" },
611 { 'T', "Retransmit on radio channel" },
615 static const value_string vals_parm_REQ_OT[] = {
616 { 'S', "Send used operation types" },
617 { 'N', "Don't send used operation types" },
621 static const value_string vals_parm_SSTAT[] = {
622 { '0', "All services" },
623 { '1', "All in the moment active services" },
624 { '2', "Call diversion" },
625 { '3', "Roaming information status" },
626 { '4', "Call barring status" },
627 { '5', "Deferred delivery status" },
628 { '6', "Number of stored messages" },
632 static const value_string vals_xser_service[] = {
633 { 1, "GSM UDH information" },
634 { 2, "GSM DCS information" },
635 { 3, "[Message Type] TDMA information exchange" },
636 { 4, "[Message Reference] TDMA information exchange" },
637 { 5, "[Privacy Indicator] TDMA information exchange" },
638 { 6, "[Urgency Indicator] TDMA information exchange" },
639 { 7, "[Acknowledgement Request] TDMA information exchange" },
640 { 8, "[Message Updating] TDMA information exchange" },
641 { 9, "[Call Back Number] TDMA information exchange" },
642 { 10, "[Response Code] TDMA information exchange" },
643 { 11, "[Teleservice ID] TDMA information exchange" },
644 { 12, "Billing identifier" },
645 { 13, "Single shot indicator" },
651 ucp_stats_tree_init(stats_tree* st)
653 st_ucp_messages = stats_tree_create_node(st, st_str_ucp, 0, TRUE);
654 st_ucp_ops = stats_tree_create_node(st, st_str_ops, st_ucp_messages, TRUE);
655 st_ucp_res = stats_tree_create_node(st, st_str_res, st_ucp_messages, TRUE);
656 st_ucp_results = stats_tree_create_node(st, st_str_ucp_res, 0, TRUE);
657 st_ucp_results_pos = stats_tree_create_node(st, st_str_pos, st_ucp_results, TRUE);
658 st_ucp_results_neg = stats_tree_create_node(st, st_str_neg, st_ucp_results, TRUE);
662 ucp_stats_tree_per_packet(stats_tree *st, /* st as it was passed to us */
663 packet_info *pinfo _U_,
664 epan_dissect_t *edt _U_,
665 const void *p) /* Used for getting UCP stats */
667 ucp_tap_rec_t* tap_rec = (ucp_tap_rec_t*)p;
669 tick_stat_node(st, st_str_ucp, 0, TRUE);
671 if (tap_rec->message_type == 0) /* Operation */
673 tick_stat_node(st, st_str_ops, st_ucp_messages, TRUE);
674 tick_stat_node(st, val_to_str(tap_rec->operation, vals_hdr_OT,
675 "Unknown OT: %d"), st_ucp_ops, FALSE);
679 tick_stat_node(st, st_str_res, st_ucp_messages, TRUE);
680 tick_stat_node(st, val_to_str(tap_rec->operation, vals_hdr_OT,
681 "Unknown OT: %d"), st_ucp_res, FALSE);
683 tick_stat_node(st, st_str_ucp_res, 0, TRUE);
685 if (tap_rec->result == 0) /* Positive Result */
687 tick_stat_node(st, st_str_pos, st_ucp_results, FALSE);
689 else /* Negative Result */
691 tick_stat_node(st, st_str_neg, st_ucp_results, TRUE);
692 tick_stat_node(st, val_to_str(tap_rec->result, vals_parm_EC,
693 "Unknown EC: %d"), st_ucp_results_neg, FALSE);
701 * Checks whether the PDU looks a bit like UCP and checks the checksum
703 * \param tvb The buffer with PDU-data
704 * \param endpkt Returns pointer, indicating the end of the PDU
706 * \return The state of this PDU
707 * \retval 0 Definitely UCP
708 * \retval UCP_SHORTENED Packet may be there, but not complete
709 * \retval UCP_MALFORMED Hmmmm, not UCP after all...
710 * \retval UCP_INV_CHK Nice packet, but checksum doesn't add up...
713 check_ucp(tvbuff_t *tvb, int *endpkt)
720 length = tvb_find_guint8(tvb, offset, -1, UCP_ETX);
722 *endpkt = tvb_reported_length_remaining(tvb, offset);
723 return UCP_SHORTENED;
725 if (length > (int) tvb_reported_length(tvb)) {
726 /* XXX - "cannot happen" */
728 return UCP_MALFORMED;
730 for (; offset < (guint) (length - 2); offset++)
731 checksum += tvb_get_guint8(tvb, offset);
733 tmp = tvb_get_guint8(tvb, offset++);
734 pkt_check = AHex2Bin(tmp);
735 tmp = tvb_get_guint8(tvb, offset++);
736 pkt_check = 16 * pkt_check + AHex2Bin(tmp);
737 *endpkt = offset + 1;
738 if (checksum == (guint) pkt_check)
745 * UCP equivalent of mktime() (3). Convert date to standard 'time_t' format
747 * \param datestr The UCP-formatted date to convert
749 * \return The date in standard 'time_t' format.
752 ucp_mktime(char *datestr)
756 r_time.tm_mday = 10 * (datestr[0] - '0') + (datestr[1] - '0');
757 r_time.tm_mon = (10 * (datestr[2] - '0') + (datestr[3] - '0')) - 1;
758 r_time.tm_year = 10 * (datestr[4] - '0') + (datestr[5] - '0');
759 if (r_time.tm_year < 90)
760 r_time.tm_year += 100;
761 r_time.tm_hour = 10 * (datestr[6] - '0') + (datestr[7] - '0');
762 r_time.tm_min = 10 * (datestr[8] - '0') + (datestr[9] - '0');
764 r_time.tm_sec = 10 * (datestr[10] - '0') + (datestr[11] - '0');
767 r_time.tm_isdst = -1;
768 return mktime(&r_time);
772 * Scanning routines to add standard types (byte, int, string, data)
773 * to the protocol-tree. Each field is seperated with a slash ('/').
775 * \param tree The protocol tree to add to
776 * \param tvb Buffer containing the data
777 * \param field The actual field, whose value needs displaying
778 * \param offset Location of field within the buffer, returns location
781 * \return For 'int'-types, the value of the field.
784 ucp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
788 idx = tvb_find_guint8(tvb, *offset, -1, '/');
790 /* Force the appropriate exception to be thrown. */
791 len = tvb_length_remaining(tvb, *offset);
792 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
796 proto_tree_add_item(tree, field, tvb, *offset, len, FALSE);
799 *offset += 1; /* skip terminating '/' */
803 ucp_handle_IRAstring(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
805 char strval[BUFSIZ + 1],
809 int tmpoff = *offset;
811 while (((byte = tvb_get_guint8(tvb, tmpoff++)) != '/') &&
814 if (byte >= '0' && byte <= '9')
816 *p_dst = (byte - '0') * 16;
820 *p_dst = (byte - 'A' + 10) * 16;
822 if ((byte = tvb_get_guint8(tvb, tmpoff++)) == '/')
826 if (byte >= '0' && byte <= '9')
828 *p_dst++ += byte - '0';
832 *p_dst++ += byte - 'A' + 10;
840 * Data clipped, eat rest of field
842 while ((tvb_get_guint8(tvb, tmpoff++)) != '/')
845 if ((tmpoff - *offset) > 1)
846 proto_tree_add_string(tree, field, tvb, *offset,
847 tmpoff - *offset - 1, strval);
852 ucp_handle_byte(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
856 if ((intval = tvb_get_guint8(tvb, (*offset)++)) != '/') {
857 proto_tree_add_uint(tree, field, tvb, *offset - 1, 1, intval);
864 ucp_handle_int(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
870 idx = tvb_find_guint8(tvb, *offset, -1, '/');
872 /* Force the appropriate exception to be thrown. */
873 len = tvb_length_remaining(tvb, *offset);
874 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
877 strval = (gchar*)tvb_get_ephemeral_string(tvb, *offset, len);
879 intval = atoi(strval);
880 proto_tree_add_uint(tree, field, tvb, *offset, idx, intval);
884 *offset += 1; /* skip terminating '/' */
889 ucp_handle_time(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
896 idx = tvb_find_guint8(tvb, *offset, -1, '/');
898 /* Force the appropriate exception to be thrown. */
899 len = tvb_length_remaining(tvb, *offset);
900 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
903 strval = (gchar*)tvb_get_ephemeral_string(tvb, *offset, len);
905 tval = ucp_mktime(strval);
908 proto_tree_add_time(tree, field, tvb, *offset, idx, &tmptime);
912 *offset += 1; /* skip terminating '/' */
916 ucp_handle_data(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
918 int tmpoff = *offset;
920 while (tvb_get_guint8(tvb, tmpoff++) != '/')
922 if ((tmpoff - *offset) > 1)
923 proto_tree_add_item(tree, field, tvb, *offset,
924 tmpoff - *offset - 1, FALSE);
929 * Handle the data-field within the UCP-message, according the Message Type
931 * - 2 Numeric message
932 * - 3 Alphanumeric message
933 * - 4 Transparent (binary) data
934 * - 5 Standard text handling
935 * - 6 Alphanumeric message in specified character set
937 * \param tree The protocol tree to add to
938 * \param tvb Buffer containing the data
939 * \param field The actual field, whose value needs displaying
940 * \param offset Location of field within the buffer, returns location
944 ucp_handle_mt(proto_tree *tree, tvbuff_t *tvb, int *offset)
948 intval = ucp_handle_byte(tree, tvb, hf_ucp_parm_MT, offset);
950 case '1': /* Tone only, no data */
952 case '4': /* TMsg, no of bits */
953 ucp_handle_string(tree, tvb, hf_ucp_parm_NB, offset);
954 /* fall through here for the data piece */
956 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
959 ucp_handle_IRAstring(tree, tvb, hf_ucp_parm_AMsg, offset);
962 ucp_handle_byte(tree, tvb, hf_ucp_parm_PNC, offset);
963 ucp_handle_string(tree, tvb, hf_ucp_parm_LNo, offset);
964 ucp_handle_string(tree, tvb, hf_ucp_parm_LST, offset);
965 ucp_handle_string(tree, tvb, hf_ucp_parm_TNo, offset);
968 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
969 ucp_handle_int(tree, tvb, hf_ucp_parm_CS, offset);
972 break; /* No data so ? */
977 * Handle the data within the 'Extended services' field. Each field having the
978 * format TTLLDD..., TT being the type of service, LL giving the length of the
979 * field, DD... containing the actual data
981 * \param tree The protocol tree to add to
982 * \param tvb Buffer containing the extended services data
985 ucp_handle_XSer(proto_tree *tree, tvbuff_t *tvb)
992 while ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
993 service = AHex2Bin(intval);
994 intval = tvb_get_guint8(tvb, offset++);
995 service = service * 16 + AHex2Bin(intval);
996 intval = tvb_get_guint8(tvb, offset++);
997 len = AHex2Bin(intval);
998 intval = tvb_get_guint8(tvb, offset++);
999 len = len * 16 + AHex2Bin(intval);
1000 proto_tree_add_uint(tree, hf_xser_service, tvb, offset,
1002 offset += (2 * len);
1006 /* Next definitions are just a convenient shorthand to make the coding a
1007 * bit more readable instead of summing up all these parameters.
1009 #define UcpHandleString(field) ucp_handle_string(tree, tvb, (field), &offset)
1011 #define UcpHandleIRAString(field) \
1012 ucp_handle_IRAstring(tree, tvb, (field), &offset)
1014 #define UcpHandleByte(field) ucp_handle_byte(tree, tvb, (field), &offset)
1016 #define UcpHandleInt(field) ucp_handle_int(tree, tvb, (field), &offset)
1018 #define UcpHandleTime(field) ucp_handle_time(tree, tvb, (field), &offset)
1020 #define UcpHandleData(field) ucp_handle_data(tree, tvb, (field), &offset)
1023 * The next set of routines handle the different operation types,
1024 * associated with UCP.
1027 add_00O(proto_tree *tree, tvbuff_t *tvb)
1031 UcpHandleString(hf_ucp_parm_AdC);
1032 UcpHandleString(hf_ucp_parm_OAdC);
1033 UcpHandleString(hf_ucp_parm_OAC);
1037 add_00R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1042 intval = UcpHandleByte(hf_ucp_parm_ACK);
1045 UcpHandleByte(hf_ucp_parm_BAS);
1046 UcpHandleByte(hf_ucp_parm_LAR);
1047 UcpHandleByte(hf_ucp_parm_L1R);
1048 UcpHandleByte(hf_ucp_parm_L3R);
1049 UcpHandleByte(hf_ucp_parm_LCR);
1050 UcpHandleByte(hf_ucp_parm_LUR);
1051 UcpHandleByte(hf_ucp_parm_LRR);
1052 UcpHandleByte(hf_ucp_parm_RT);
1053 UcpHandleInt(hf_ucp_parm_NoN);
1054 UcpHandleInt(hf_ucp_parm_NoA);
1055 UcpHandleInt(hf_ucp_parm_NoB);
1057 tap_rec->result = 0;
1059 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1060 UcpHandleString(hf_ucp_parm_SM);
1065 add_01O(proto_tree *tree, tvbuff_t *tvb)
1069 UcpHandleString(hf_ucp_parm_AdC);
1070 UcpHandleString(hf_ucp_parm_OAdC);
1071 UcpHandleString(hf_ucp_parm_OAC);
1072 ucp_handle_mt(tree, tvb, &offset);
1076 add_01R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1081 intval = UcpHandleByte(hf_ucp_parm_ACK);
1083 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1085 tap_rec->result = 0;
1086 UcpHandleString(hf_ucp_parm_SM);
1090 add_02O(proto_tree *tree, tvbuff_t *tvb)
1091 { /* Multiple address call input*/
1096 intval = UcpHandleInt(hf_ucp_parm_NPL);
1097 for (idx = 0; idx < intval; idx++)
1098 UcpHandleString(hf_ucp_parm_AdC);
1100 UcpHandleString(hf_ucp_parm_OAdC);
1101 UcpHandleString(hf_ucp_parm_OAC);
1102 ucp_handle_mt(tree, tvb, &offset);
1105 #define add_02R(a, b, c) add_01R(a, b, c)
1108 add_03O(proto_tree *tree, tvbuff_t *tvb)
1109 { /* Call input with SS */
1114 UcpHandleString(hf_ucp_parm_AdC);
1115 UcpHandleString(hf_ucp_parm_OAdC);
1116 UcpHandleString(hf_ucp_parm_OAC);
1117 intval = UcpHandleInt(hf_ucp_parm_NPL);
1118 for (idx = 0; idx < intval; idx++)
1119 UcpHandleString(hf_ucp_parm_GA);
1121 UcpHandleByte(hf_ucp_parm_RP);
1122 UcpHandleString(hf_ucp_parm_LRP);
1123 UcpHandleByte(hf_ucp_parm_PR);
1124 UcpHandleString(hf_ucp_parm_LPR);
1125 UcpHandleByte(hf_ucp_parm_UM);
1126 UcpHandleString(hf_ucp_parm_LUM);
1127 UcpHandleByte(hf_ucp_parm_RC);
1128 UcpHandleString(hf_ucp_parm_LRC);
1129 UcpHandleByte(hf_ucp_parm_DD);
1130 UcpHandleTime(hf_ucp_parm_DDT);
1131 ucp_handle_mt(tree, tvb, &offset);
1134 #define add_03R(a, b, c) add_01R(a, b, c)
1137 add_04O(proto_tree *tree, tvbuff_t *tvb)
1138 { /* Address list information */
1141 UcpHandleString(hf_ucp_parm_GAdC);
1142 UcpHandleString(hf_ucp_parm_AC);
1143 UcpHandleString(hf_ucp_parm_OAdC);
1144 UcpHandleString(hf_ucp_parm_OAC);
1148 add_04R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1154 intval = UcpHandleByte(hf_ucp_parm_ACK);
1155 if (intval == 'A') {
1156 intval = UcpHandleInt(hf_ucp_parm_NPL);
1157 for (idx = 0; idx < intval; idx++)
1158 UcpHandleString(hf_ucp_parm_AdC);
1159 UcpHandleString(hf_ucp_parm_GAdC);
1160 tap_rec->result = 0;
1162 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1163 UcpHandleString(hf_ucp_parm_SM);
1167 add_05O(proto_tree *tree, tvbuff_t *tvb)
1168 { /* Change address list */
1173 UcpHandleString(hf_ucp_parm_GAdC);
1174 UcpHandleString(hf_ucp_parm_AC);
1175 UcpHandleString(hf_ucp_parm_OAdC);
1176 UcpHandleString(hf_ucp_parm_OAC);
1177 intval = UcpHandleInt(hf_ucp_parm_NPL);
1178 for (idx = 0; idx < intval; idx++)
1179 UcpHandleString(hf_ucp_parm_AdC);
1180 UcpHandleByte(hf_ucp_parm_A_D);
1183 #define add_05R(a, b, c) add_01R(a, b, c)
1186 add_06O(proto_tree *tree, tvbuff_t *tvb)
1187 { /* Advice of accum. charges */
1190 UcpHandleString(hf_ucp_parm_AdC);
1191 UcpHandleString(hf_ucp_parm_AC);
1195 add_06R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1200 intval = UcpHandleByte(hf_ucp_parm_ACK);
1201 if (intval == 'A') {
1202 UcpHandleTime(hf_ucp_parm_CT);
1203 UcpHandleString(hf_ucp_parm_AAC);
1204 tap_rec->result = 0;
1206 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1207 UcpHandleString(hf_ucp_parm_SM);
1211 add_07O(proto_tree *tree, tvbuff_t *tvb)
1212 { /* Password management */
1215 UcpHandleString(hf_ucp_parm_AdC);
1216 UcpHandleString(hf_ucp_parm_AC);
1217 UcpHandleString(hf_ucp_parm_NAC);
1220 #define add_07R(a, b, c) add_01R(a, b, c)
1223 add_08O(proto_tree *tree, tvbuff_t *tvb)
1224 { /* Leg. code management */
1227 UcpHandleString(hf_ucp_parm_AdC);
1228 UcpHandleString(hf_ucp_parm_AC);
1229 UcpHandleString(hf_ucp_parm_LAC);
1230 UcpHandleString(hf_ucp_parm_L1P);
1231 UcpHandleString(hf_ucp_parm_L3P);
1232 UcpHandleString(hf_ucp_parm_LRC);
1233 UcpHandleString(hf_ucp_parm_LUM);
1234 UcpHandleString(hf_ucp_parm_LRP);
1235 UcpHandleString(hf_ucp_parm_LST);
1238 #define add_08R(a, b, c) add_01R(a, b, c)
1241 add_09O(proto_tree *tree, tvbuff_t *tvb)
1242 { /* Standard text information */
1245 UcpHandleString(hf_ucp_parm_LNo);
1246 UcpHandleString(hf_ucp_parm_LST);
1250 add_09R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1256 intval = UcpHandleByte(hf_ucp_parm_ACK);
1257 if (intval == 'A') {
1258 intval = UcpHandleInt(hf_ucp_parm_NPL);
1259 for (idx = 0; idx < intval; idx++)
1260 UcpHandleString(hf_ucp_parm_LST);
1261 tap_rec->result = 0;
1263 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1264 UcpHandleString(hf_ucp_parm_SM);
1268 add_10O(proto_tree *tree, tvbuff_t *tvb)
1269 { /* Change standard text */
1272 UcpHandleString(hf_ucp_parm_AdC);
1273 UcpHandleString(hf_ucp_parm_AC);
1274 UcpHandleString(hf_ucp_parm_LNo);
1275 UcpHandleString(hf_ucp_parm_TNo);
1276 UcpHandleData(hf_ucp_parm_STx);
1277 UcpHandleInt(hf_ucp_parm_CS);
1280 #define add_10R(a, b, c) add_01R(a, b, c)
1282 #define add_11O(a, b) add_06O(a, b) /* Request roaming info */
1285 add_11R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1291 intval = UcpHandleByte(hf_ucp_parm_ACK);
1292 if (intval == 'A') {
1293 intval = UcpHandleInt(hf_ucp_parm_NPL);
1294 for (idx = 0; idx < intval; idx++)
1295 UcpHandleString(hf_ucp_parm_GA);
1296 tap_rec->result = 0;
1298 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1299 UcpHandleString(hf_ucp_parm_SM);
1303 add_12O(proto_tree *tree, tvbuff_t *tvb)
1304 { /* Change roaming */
1309 UcpHandleString(hf_ucp_parm_AdC);
1310 UcpHandleString(hf_ucp_parm_AC);
1311 intval = UcpHandleInt(hf_ucp_parm_NPL);
1312 for (idx = 0; idx < intval; idx++)
1313 UcpHandleString(hf_ucp_parm_GA);
1316 #define add_12R(a, b, c) add_01R(a, b, c)
1318 #define add_13O(a, b) add_06O(a, b) /* Roaming reset */
1320 #define add_13R(a, b, c) add_01R(a, b, c)
1323 add_14O(proto_tree *tree, tvbuff_t *tvb)
1324 { /* Message retrieval */
1327 UcpHandleString(hf_ucp_parm_AdC);
1328 UcpHandleString(hf_ucp_parm_AC);
1329 UcpHandleString(hf_ucp_parm_MNo);
1330 UcpHandleByte(hf_ucp_parm_R_T);
1334 add_14R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1340 intval = UcpHandleByte(hf_ucp_parm_ACK);
1341 if (intval == 'A') {
1342 intval = UcpHandleInt(hf_ucp_parm_NPL);
1344 * Spec is unclear here. Is 'SM' part of the Msg:s field or not?
1345 * For now, assume it is part of it...
1347 for (idx = 0; idx < intval; idx++)
1348 UcpHandleData(hf_ucp_data_section);
1349 tap_rec->result = 0;
1351 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1352 UcpHandleString(hf_ucp_parm_SM);
1357 add_15O(proto_tree *tree, tvbuff_t *tvb)
1358 { /* Request call barring */
1361 UcpHandleString(hf_ucp_parm_AdC);
1362 UcpHandleString(hf_ucp_parm_AC);
1363 UcpHandleTime(hf_ucp_parm_ST);
1364 UcpHandleTime(hf_ucp_parm_SP);
1367 #define add_15R(a, b, c) add_01R(a, b, c)
1369 #define add_16O(a, b) add_06O(a, b) /* Cancel call barring */
1371 #define add_16R(a, b, c) add_01R(a, b, c)
1374 add_17O(proto_tree *tree, tvbuff_t *tvb)
1375 { /* Request call diversion */
1378 UcpHandleString(hf_ucp_parm_AdC);
1379 UcpHandleString(hf_ucp_parm_AC);
1380 UcpHandleString(hf_ucp_parm_DAdC);
1381 UcpHandleTime(hf_ucp_parm_ST);
1382 UcpHandleTime(hf_ucp_parm_SP);
1385 #define add_17R(a, b, c) add_01R(a, b, c)
1387 #define add_18O(a, b) add_06O(a, b) /* Cancel call diversion */
1389 #define add_18R(a, b, c) add_01R(a, b, c)
1392 add_19O(proto_tree *tree, tvbuff_t *tvb)
1393 { /* Request deferred delivery*/
1396 UcpHandleString(hf_ucp_parm_AdC);
1397 UcpHandleString(hf_ucp_parm_AC);
1398 UcpHandleTime(hf_ucp_parm_ST);
1399 UcpHandleTime(hf_ucp_parm_SP);
1402 #define add_19R(a, b, c) add_01R(a, b, c)
1404 #define add_20O(a, b) add_06O(a, b) /* Cancel deferred delivery */
1406 #define add_20R(a, b, c) add_01R(a, b, c)
1408 #define add_21O(a, b) add_06O(a, b) /* All features reset */
1410 #define add_21R(a, b, c) add_01R(a, b, c)
1413 add_22O(proto_tree *tree, tvbuff_t *tvb)
1414 { /* Call input w. add. CS */
1417 UcpHandleString(hf_ucp_parm_AdC);
1418 UcpHandleString(hf_ucp_parm_OAdC);
1419 UcpHandleString(hf_ucp_parm_OAC);
1420 UcpHandleData(hf_ucp_data_section);
1421 UcpHandleInt(hf_ucp_parm_CS);
1424 #define add_22R(a, b, c) add_01R(a, b, c)
1427 add_23O(proto_tree *tree, tvbuff_t *tvb)
1428 { /* UCP version status */
1431 UcpHandleString(hf_ucp_parm_IVR5x);
1432 UcpHandleByte(hf_ucp_parm_REQ_OT);
1436 add_23R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1442 intval = UcpHandleByte(hf_ucp_parm_ACK);
1443 if (intval == 'A') {
1444 UcpHandleByte(hf_ucp_parm_IVR5x);
1445 intval = UcpHandleInt(hf_ucp_parm_NPL);
1446 for (idx = 0; idx < intval; idx++)
1447 UcpHandleInt(hf_ucp_hdr_OT);
1448 tap_rec->result = 0;
1450 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1451 UcpHandleString(hf_ucp_parm_SM);
1455 add_24O(proto_tree *tree, tvbuff_t *tvb)
1456 { /* Mobile subs. feature stat*/
1459 UcpHandleString(hf_ucp_parm_AdC);
1460 UcpHandleString(hf_ucp_parm_AC);
1461 UcpHandleByte(hf_ucp_parm_SSTAT);
1465 add_24R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1471 intval = UcpHandleByte(hf_ucp_parm_ACK);
1472 if (intval == 'A') {
1473 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1474 proto_tree_add_text(tree, tvb, offset - 1, 1,
1475 "GA roaming definitions");
1476 if (intval == 'N') {
1477 proto_tree_add_text(tree, tvb, offset -1, 1,
1478 "Not subscribed/not allowed");
1482 intval = UcpHandleInt(hf_ucp_parm_NPL);
1483 for (idx = 0; idx < intval; idx++)
1484 UcpHandleData(hf_ucp_data_section);
1487 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1488 proto_tree_add_text(tree, tvb, offset - 1, 1,
1489 "Call barring definitions");
1490 if (intval == 'N') {
1491 proto_tree_add_text(tree, tvb, offset -1, 1,
1492 "Not subscribed/not allowed");
1496 intval = UcpHandleInt(hf_ucp_parm_NPL);
1497 for (idx = 0; idx < intval; idx++)
1498 UcpHandleData(hf_ucp_data_section);
1501 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1502 proto_tree_add_text(tree, tvb, offset - 1, 1,
1503 "Deferred delivery definitions");
1504 if (intval == 'N') {
1505 proto_tree_add_text(tree, tvb, offset -1, 1,
1506 "Not subscribed/not allowed");
1510 intval = UcpHandleInt(hf_ucp_parm_NPL);
1511 for (idx = 0; idx < intval; idx++)
1512 UcpHandleData(hf_ucp_data_section);
1515 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1516 proto_tree_add_text(tree, tvb, offset - 1, 1,
1517 "Diversion definitions");
1518 if (intval == 'N') {
1519 proto_tree_add_text(tree, tvb, offset -1, 1,
1520 "Not subscribed/not allowed");
1524 intval = UcpHandleInt(hf_ucp_parm_NPL);
1525 for (idx = 0; idx < intval; idx++)
1526 UcpHandleData(hf_ucp_data_section);
1529 UcpHandleInt(hf_ucp_parm_LMN);
1530 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1531 if (intval == 'N') {
1532 proto_tree_add_string(tree, hf_ucp_parm_NMESS_str, tvb,
1533 offset -1, 1, "Not subscribed/not allowed");
1537 intval = UcpHandleInt(hf_ucp_parm_NMESS);
1540 tap_rec->result = 0;
1542 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1543 UcpHandleString(hf_ucp_parm_SM);
1547 add_30O(proto_tree *tree, tvbuff_t *tvb)
1548 { /* SMS message transfer */
1551 UcpHandleString(hf_ucp_parm_AdC);
1552 UcpHandleString(hf_ucp_parm_OAdC);
1553 UcpHandleString(hf_ucp_parm_AC);
1554 UcpHandleByte(hf_ucp_parm_NRq);
1555 UcpHandleString(hf_ucp_parm_NAdC);
1556 UcpHandleInt(hf_ucp_parm_NPID);
1557 UcpHandleByte(hf_ucp_parm_DD);
1558 UcpHandleTime(hf_ucp_parm_DDT);
1559 UcpHandleTime(hf_ucp_parm_VP);
1560 UcpHandleData(hf_ucp_data_section);
1564 add_30R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
1569 intval = UcpHandleByte(hf_ucp_parm_ACK);
1570 if (intval == 'A') {
1571 UcpHandleTime(hf_ucp_parm_MVP);
1572 tap_rec->result = 0;
1574 tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
1576 UcpHandleString(hf_ucp_parm_SM);
1580 add_31O(proto_tree *tree, tvbuff_t *tvb)
1584 UcpHandleString(hf_ucp_parm_AdC);
1585 UcpHandleInt(hf_ucp_parm_PID);
1588 #define add_31R(a, b, c) add_01R(a, b, c)
1591 add_5xO(proto_tree *tree, tvbuff_t *tvb)
1592 { /* 50-series operations */
1599 UcpHandleString(hf_ucp_parm_AdC);
1600 UcpHandleString(hf_ucp_parm_OAdC);
1601 UcpHandleString(hf_ucp_parm_AC);
1602 UcpHandleByte(hf_ucp_parm_NRq);
1603 UcpHandleString(hf_ucp_parm_NAdC);
1604 UcpHandleByte(hf_ucp_parm_NT);
1605 UcpHandleInt(hf_ucp_parm_NPID);
1606 UcpHandleByte(hf_ucp_parm_LRq);
1607 UcpHandleString(hf_ucp_parm_LRAd);
1608 UcpHandleInt(hf_ucp_parm_LPID);
1609 UcpHandleByte(hf_ucp_parm_DD);
1610 UcpHandleTime(hf_ucp_parm_DDT);
1611 UcpHandleTime(hf_ucp_parm_VP);
1612 UcpHandleString(hf_ucp_parm_RPID);
1613 UcpHandleTime(hf_ucp_parm_SCTS);
1614 UcpHandleByte(hf_ucp_parm_Dst);
1615 UcpHandleInt(hf_ucp_parm_Rsn);
1616 UcpHandleTime(hf_ucp_parm_DSCTS);
1617 intval = UcpHandleByte(hf_ucp_parm_MT);
1618 UcpHandleString(hf_ucp_parm_NB);
1620 UcpHandleData(hf_ucp_data_section);
1622 UcpHandleIRAString(hf_ucp_parm_AMsg);
1623 UcpHandleByte(hf_ucp_parm_MMS);
1624 UcpHandleByte(hf_ucp_parm_PR);
1625 UcpHandleByte(hf_ucp_parm_DCs);
1626 UcpHandleByte(hf_ucp_parm_MCLs);
1627 UcpHandleByte(hf_ucp_parm_RPI);
1628 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1629 proto_tree_add_string(tree, hf_ucp_parm_CPg, tvb, offset - 1,1,
1630 "(reserved for Code Page)");
1633 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1634 proto_tree_add_string(tree, hf_ucp_parm_RPLy, tvb, offset - 1,1,
1635 "(reserved for Reply type)");
1638 UcpHandleString(hf_ucp_parm_OTOA);
1639 UcpHandleString(hf_ucp_parm_HPLMN);
1640 tmpoff = offset; /* Extra services */
1641 while (tvb_get_guint8(tvb, tmpoff++) != '/')
1643 if ((tmpoff - offset) > 1) {
1644 int len = tmpoff - offset - 1;
1646 ti = proto_tree_add_item(tree, hf_ucp_parm_XSer,tvb,offset,len,FALSE);
1647 tmptvb = tvb_new_subset(tvb, offset, len + 1, len + 1);
1648 proto_item_add_subtree(ti, ett_XSer);
1649 ucp_handle_XSer(ti, tmptvb);
1652 UcpHandleData(hf_ucp_parm_RES4);
1653 UcpHandleData(hf_ucp_parm_RES5);
1656 #define add_5xR(a, b,c ) add_30R(a, b, c)
1659 add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
1660 { /* 60-series operations */
1663 UcpHandleString(hf_ucp_parm_OAdC);
1664 UcpHandleByte(hf_ucp_parm_OTON);
1665 UcpHandleByte(hf_ucp_parm_ONPI);
1667 UcpHandleByte(hf_ucp_parm_STYP0);
1669 UcpHandleByte(hf_ucp_parm_STYP1);
1671 UcpHandleIRAString(hf_ucp_parm_PWD);
1672 UcpHandleIRAString(hf_ucp_parm_NPWD);
1673 UcpHandleString(hf_ucp_parm_VERS);
1674 UcpHandleString(hf_ucp_parm_LAdC);
1675 UcpHandleByte(hf_ucp_parm_LTON);
1676 UcpHandleByte(hf_ucp_parm_LNPI);
1677 UcpHandleInt(hf_ucp_parm_OPID);
1678 UcpHandleData(hf_ucp_parm_RES1);
1680 UcpHandleData(hf_ucp_parm_RES2);
1684 #define add_6xR(a, b, c) add_01R(a, b, c)
1687 * End of convenient shorthands
1689 #undef UcpHandleString
1690 #undef UcpHandleIRAString
1691 #undef UcpHandleByte
1693 #undef UcpHandleTime
1694 #undef UcpHandleData
1696 /* Code to actually dissect the packets */
1698 * Overlapping data for these functions
1700 static int result, endpkt;
1703 * The heuristic dissector
1706 dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1708 guint8 O_R; /* Request or response */
1710 /* This runs atop TCP, so we are guaranteed that there is at least one
1711 byte in the tvbuff. */
1712 if (tvb_get_guint8(tvb, 0) != UCP_STX)
1715 result = check_ucp(tvb, &endpkt);
1717 if (result == UCP_MALFORMED)
1719 if (endpkt < UCP_OT_OFFSET + 1)
1721 * Might be shortened packet but don't handle anyway.
1726 * Try getting the operation-type and whether it's a request/response
1728 O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
1729 if (match_strval(O_R, vals_hdr_O_R) == NULL)
1732 * Ok, looks like a valid packet, go dissect.
1735 dissect_ucp_common(tvb, pinfo, tree);
1740 get_ucp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1745 offset = offset + 4;
1746 for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
1747 intval = 10 * intval +
1748 (tvb_get_guint8(tvb, offset) - '0');
1757 dissect_ucp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1759 tcp_dissect_pdus(tvb, pinfo, tree, ucp_desegment, UCP_HEADER_SIZE,
1760 get_ucp_pdu_len, dissect_ucp_common);
1763 * The actual dissector
1766 dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1768 int offset = 0; /* Offset in packet within tvbuff */
1769 int tmpoff; /* Local offset value (per field) */
1770 guint8 O_R; /* Request or response */
1771 guint8 OT; /* Operation type */
1774 ucp_tap_rec_t* tap_rec; /* Tap record */
1776 /* Set up structures needed to add the protocol subtree and manage it */
1779 proto_tree *ucp_tree;
1780 proto_tree *sub_tree;
1783 /* Make entries in Protocol column */
1784 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1785 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
1787 /* This runs atop TCP, so we are guaranteed that there is at least one
1788 byte in the tvbuff. */
1789 if (tvb_get_guint8(tvb, 0) != UCP_STX){
1790 proto_tree_add_text(tree, tvb, 0, -1,"UCP_STX missing, this is not a new packet");
1794 /* Get data needed for dissect_ucp_common */
1795 result = check_ucp(tvb, &endpkt);
1797 O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
1799 * So do an atoi() on the operation type
1801 OT = tvb_get_guint8(tvb, UCP_OT_OFFSET) - '0';
1802 OT = 10 * OT + (tvb_get_guint8(tvb, UCP_OT_OFFSET + 1) - '0');
1804 /* Create Tap record */
1805 tap_rec = ep_alloc0(sizeof(ucp_tap_rec_t));
1806 tap_rec->message_type = (O_R == 'O' ? 0 : 1);
1807 tap_rec->operation = OT;
1809 /* Make entries in Info column on summary display */
1810 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1811 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
1812 if (check_col(pinfo->cinfo, COL_INFO)) {
1813 col_clear(pinfo->cinfo, COL_INFO);
1814 col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
1815 val_to_str(OT, vals_hdr_OT, "unknown operation"),
1816 val_to_str(O_R, vals_hdr_O_R, "Unknown (%d)"));
1817 if (result == UCP_SHORTENED)
1818 col_append_str(pinfo->cinfo, COL_INFO, " [short packet]");
1819 else if (result == UCP_INV_CHK)
1820 col_append_str(pinfo->cinfo, COL_INFO, " [checksum invalid]");
1823 /* In the interest of speed, if "tree" is NULL, don't do any work not
1824 necessary to generate protocol tree items. */
1827 /* create display subtree for the protocol */
1828 ti = proto_tree_add_item(tree, proto_ucp, tvb, 0, -1, FALSE);
1830 ucp_tree = proto_item_add_subtree(ti, ett_ucp);
1832 * Process the packet here.
1833 * Transaction number
1835 offset++; /* Skip <stx> */
1837 intval = tvb_get_guint8(tvb, tmpoff++) - '0';
1838 intval = 10 * intval + (tvb_get_guint8(tvb, tmpoff++) - '0');
1839 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_TRN, tvb, offset,
1840 UCP_TRN_LEN, intval);
1843 offset++; /* Skip '/' */
1846 for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
1847 intval = 10 * intval +
1848 (tvb_get_guint8(tvb, tmpoff++) - '0');
1850 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_LEN, tvb, offset,
1851 UCP_LEN_LEN, intval);
1854 offset++; /* Operation/Response */
1855 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_O_R, tvb, offset++,
1858 offset++; /* Operation type */
1859 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_OT, tvb, offset,
1861 offset += UCP_OT_LEN;
1863 * Variable part starts here. Don't dissect if not complete.
1865 if (result == UCP_SHORTENED)
1867 tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
1868 sub_ti = proto_tree_add_item(ucp_tree, hf_ucp_oper_section, tvb,
1869 offset, endpkt - offset, FALSE);
1870 sub_tree = proto_item_add_subtree(sub_ti, ett_sub);
1874 O_R == 'O' ? add_00O(sub_tree,tmp_tvb) : add_00R(sub_tree,tmp_tvb, tap_rec);
1877 O_R == 'O' ? add_01O(sub_tree,tmp_tvb) : add_01R(sub_tree,tmp_tvb, tap_rec);
1880 O_R == 'O' ? add_02O(sub_tree,tmp_tvb) : add_02R(sub_tree,tmp_tvb, tap_rec);
1883 O_R == 'O' ? add_03O(sub_tree,tmp_tvb) : add_03R(sub_tree,tmp_tvb, tap_rec);
1886 O_R == 'O' ? add_04O(sub_tree,tmp_tvb) : add_04R(sub_tree,tmp_tvb, tap_rec);
1889 O_R == 'O' ? add_05O(sub_tree,tmp_tvb) : add_05R(sub_tree,tmp_tvb, tap_rec);
1892 O_R == 'O' ? add_06O(sub_tree,tmp_tvb) : add_06R(sub_tree,tmp_tvb, tap_rec);
1895 O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree,tmp_tvb, tap_rec);
1898 O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree,tmp_tvb, tap_rec);
1901 O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree,tmp_tvb, tap_rec);
1904 O_R == 'O' ? add_10O(sub_tree,tmp_tvb) : add_10R(sub_tree,tmp_tvb, tap_rec);
1907 O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree,tmp_tvb, tap_rec);
1910 O_R == 'O' ? add_12O(sub_tree,tmp_tvb) : add_12R(sub_tree,tmp_tvb, tap_rec);
1913 O_R == 'O' ? add_13O(sub_tree,tmp_tvb) : add_13R(sub_tree,tmp_tvb, tap_rec);
1916 O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree,tmp_tvb, tap_rec);
1919 O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree,tmp_tvb, tap_rec);
1922 O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree,tmp_tvb, tap_rec);
1925 O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree,tmp_tvb, tap_rec);
1928 O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree,tmp_tvb, tap_rec);
1931 O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree,tmp_tvb, tap_rec);
1934 O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree,tmp_tvb, tap_rec);
1937 O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree,tmp_tvb, tap_rec);
1940 O_R == 'O' ? add_22O(sub_tree,tmp_tvb) : add_22R(sub_tree,tmp_tvb, tap_rec);
1943 O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree,tmp_tvb, tap_rec);
1946 O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree,tmp_tvb, tap_rec);
1949 O_R == 'O' ? add_30O(sub_tree,tmp_tvb) : add_30R(sub_tree,tmp_tvb, tap_rec);
1952 O_R == 'O' ? add_31O(sub_tree,tmp_tvb) : add_31R(sub_tree,tmp_tvb, tap_rec);
1954 case 51: case 52: case 53: case 54: case 55: case 56: case 57:
1956 O_R == 'O' ? add_5xO(sub_tree,tmp_tvb) : add_5xR(sub_tree,tmp_tvb, tap_rec);
1959 O_R == 'O' ? add_6xO(sub_tree,tmp_tvb,OT) : add_6xR(sub_tree,tmp_tvb, tap_rec);
1966 /* Queue packet for Tap */
1967 tap_queue_packet(ucp_tap, pinfo, tap_rec);
1972 /* Register the protocol with Wireshark */
1974 proto_register_ucp(void)
1977 /* Setup list of fields */
1978 static hf_register_info hf[] = {
1980 { "Transaction Reference Number", "ucp.hdr.TRN",
1981 FT_UINT8, BASE_DEC, NULL, 0x00,
1982 "Transaction number for this command, used in windowing.",
1987 { "Length", "ucp.hdr.LEN",
1988 FT_UINT16, BASE_DEC, NULL, 0x00,
1989 "Total number of characters between <stx>...<etx>.",
1994 { "Type", "ucp.hdr.O_R",
1995 FT_UINT8, BASE_DEC, VALS(vals_hdr_O_R), 0x00,
1996 "Your basic 'is a request or response'.",
2001 { "Operation", "ucp.hdr.OT",
2002 FT_UINT8, BASE_DEC, VALS(vals_hdr_OT), 0x00,
2003 "The operation that is requested with this message.",
2007 { &hf_ucp_oper_section,
2008 { "Data", "ucp.parm",
2009 FT_NONE, BASE_DEC, NULL, 0x00,
2010 "The actual content of the operation.",
2015 { "AdC", "ucp.parm.AdC",
2016 FT_STRING, BASE_NONE, NULL, 0x00,
2017 "Address code recipient.",
2021 { &hf_ucp_parm_OAdC,
2022 { "OAdC", "ucp.parm.OAdC",
2023 FT_STRING, BASE_NONE, NULL, 0x00,
2024 "Address code originator.",
2028 { &hf_ucp_parm_DAdC,
2029 { "DAdC", "ucp.parm.DAdC",
2030 FT_STRING, BASE_NONE, NULL, 0x00,
2031 "Diverted address code.",
2036 { "AC", "ucp.parm.AC",
2037 FT_STRING, BASE_NONE, NULL, 0x00,
2038 "Authentication code.",
2043 { "OAC", "ucp.parm.OAC",
2044 FT_STRING, BASE_NONE, NULL, 0x00,
2045 "Authentication code, originator.",
2050 { "NAC", "ucp.parm.NAC",
2051 FT_STRING, BASE_NONE, NULL, 0x00,
2052 "New authentication code.",
2057 { "BAS", "ucp.parm.BAS",
2058 FT_UINT8, BASE_DEC, VALS(vals_parm_BAS), 0x00,
2059 "Barring status flag.",
2064 { "LAR", "ucp.parm.LAR",
2065 FT_UINT8, BASE_DEC, VALS(vals_parm_LAR), 0x00,
2066 "Leg. code for all calls flag.",
2071 { "LAC", "ucp.parm.LAC",
2072 FT_STRING, BASE_NONE, NULL, 0x00,
2073 "New leg. code for all calls.",
2078 { "L1R", "ucp.parm.L1R",
2079 FT_UINT8, BASE_DEC, VALS(vals_parm_L1R), 0x00,
2080 "Leg. code for priority 1 flag.",
2085 { "L1P", "ucp.parm.L1P",
2086 FT_STRING, BASE_NONE, NULL, 0x00,
2087 "New leg. code for level 1 priority.",
2092 { "L3R", "ucp.parm.L3R",
2093 FT_UINT8, BASE_DEC, VALS(vals_parm_L3R), 0x00,
2094 "Leg. code for priority 3 flag.",
2099 { "L3P", "ucp.parm.L3P",
2100 FT_STRING, BASE_NONE, NULL, 0x00,
2101 "New leg. code for level 3 priority.",
2106 { "LCR", "ucp.parm.LCR",
2107 FT_UINT8, BASE_DEC, VALS(vals_parm_LCR), 0x00,
2108 "Leg. code for reverse charging flag.",
2113 { "LUR", "ucp.parm.LUR",
2114 FT_UINT8, BASE_DEC, VALS(vals_parm_LUR), 0x00,
2115 "Leg. code for urgent message flag.",
2120 { "LRR", "ucp.parm.LRR",
2121 FT_UINT8, BASE_DEC, VALS(vals_parm_LRR), 0x00,
2122 "Leg. code for repetition flag.",
2127 { "RT", "ucp.parm.RT",
2128 FT_UINT8, BASE_DEC, VALS(vals_parm_RT), 0x00,
2134 { "NoN", "ucp.parm.NoN",
2135 FT_UINT16, BASE_DEC, NULL, 0x00,
2136 "Maximum number of numerical characters accepted.",
2141 { "NoA", "ucp.parm.NoA",
2142 FT_UINT16, BASE_DEC, NULL, 0x00,
2143 "Maximum number of alphanumerical characters accepted.",
2148 { "NoB", "ucp.parm.NoB",
2149 FT_UINT16, BASE_DEC, NULL, 0x00,
2150 "Maximum number of data bits accepted.",
2155 { "PNC", "ucp.parm.PNC",
2156 FT_UINT8, BASE_DEC, VALS(vals_parm_PNC), 0x00,
2157 "Paging network controller.",
2161 { &hf_ucp_parm_AMsg,
2162 { "AMsg", "ucp.parm.AMsg",
2163 FT_STRING, BASE_NONE, NULL, 0x00,
2164 "The alphanumeric message that is being sent.",
2169 { "LNo", "ucp.parm.LNo",
2170 FT_STRING, BASE_NONE, NULL, 0x00,
2171 "Standard text list number requested by calling party.",
2176 { "LST", "ucp.parm.LST",
2177 FT_STRING, BASE_NONE, NULL, 0x00,
2178 "Legitimisation code for standard text.",
2183 { "TNo", "ucp.parm.TNo",
2184 FT_STRING, BASE_NONE, NULL, 0x00,
2185 "Standard text number requested by calling party.",
2190 { "CS", "ucp.parm.CS",
2191 FT_UINT8, BASE_DEC, NULL, 0x00,
2192 "Additional character set number.",
2197 { "PID", "ucp.parm.PID",
2198 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2204 { "NPL", "ucp.parm.NPL",
2205 FT_UINT16, BASE_DEC, NULL, 0x00,
2206 "Number of parameters in the following list.",
2211 { "GA", "ucp.parm.GA",
2212 FT_STRING, BASE_NONE, NULL, 0x00,
2213 "GA?? haven't got a clue.",
2218 { "RP", "ucp.parm.RP",
2219 FT_UINT8, BASE_DEC, VALS(vals_parm_RP), 0x00,
2220 "Repetition requested.",
2225 { "LRP", "ucp.parm.LRP",
2226 FT_STRING, BASE_DEC, NULL, 0x00,
2227 "Legitimisation code for repetition.",
2232 { "PR", "ucp.parm.PR",
2233 FT_UINT8, BASE_DEC, NULL, 0x00,
2234 "Priority requested.",
2239 { "LPR", "ucp.parm.LPR",
2240 FT_STRING, BASE_DEC, NULL, 0x00,
2241 "Legitimisation code for priority requested.",
2246 { "UM", "ucp.parm.UM",
2247 FT_UINT8, BASE_DEC, VALS(vals_parm_UM), 0x00,
2248 "Urgent message indicator.",
2253 { "LUM", "ucp.parm.LUM",
2254 FT_STRING, BASE_DEC, NULL, 0x00,
2255 "Legitimisation code for urgent message.",
2260 { "RC", "ucp.parm.RC",
2261 FT_UINT8, BASE_DEC, VALS(vals_parm_RC), 0x00,
2262 "Reverse charging request.",
2267 { "LRC", "ucp.parm.LRC",
2268 FT_STRING, BASE_DEC, NULL, 0x00,
2269 "Legitimisation code for reverse charging.",
2274 { "NRq", "ucp.parm.NRq",
2275 FT_UINT8, BASE_DEC, VALS(vals_parm_NRq), 0x00,
2276 "Notification request.",
2280 { &hf_ucp_parm_GAdC,
2281 { "GAdC", "ucp.parm.GAdC",
2282 FT_STRING, BASE_NONE, NULL, 0x00,
2283 "Group address code.",
2288 { "A_D", "ucp.parm.A_D",
2289 FT_UINT8, BASE_DEC, VALS(vals_parm_A_D), 0x00,
2290 "Add to/delete from fixed subscriber address list record.",
2295 { "CT", "ucp.parm.CT",
2296 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2297 "Accumulated charges timestamp.",
2302 { "AAC", "ucp.parm.AAC",
2303 FT_STRING, BASE_NONE, NULL, 0x00,
2304 "Accumulated charges.",
2309 { "MNo", "ucp.parm.MNo",
2310 FT_STRING, BASE_NONE, NULL, 0x00,
2316 { "R_T", "ucp.parm.R_T",
2317 FT_UINT8, BASE_DEC, VALS(vals_parm_R_T), 0x00,
2322 { &hf_ucp_parm_NAdC,
2323 { "NAdC", "ucp.parm.NAdC",
2324 FT_STRING, BASE_NONE, NULL, 0x00,
2325 "Notification address.",
2330 { "NT", "ucp.parm.NT",
2331 FT_UINT8, BASE_DEC, VALS(vals_parm_NT), 0x00,
2332 "Notification type.",
2336 { &hf_ucp_parm_IVR5x,
2337 { "IVR5x", "ucp.parm.IVR5x",
2338 FT_STRING, BASE_NONE, NULL, 0x00,
2339 "UCP release number supported/accepted.",
2343 { &hf_ucp_parm_REQ_OT,
2344 { "REQ_OT", "ucp.parm.REQ_OT",
2345 FT_UINT8, BASE_DEC, VALS(vals_parm_REQ_OT), 0x00,
2346 "UCP release number supported/accepted.",
2350 { &hf_ucp_parm_SSTAT,
2351 { "SSTAT", "ucp.parm.SSTAT",
2352 FT_UINT8, BASE_DEC, VALS(vals_parm_SSTAT), 0x00,
2353 "Supplementary services for which status is requested.",
2358 { "LMN", "ucp.parm.LMN",
2359 FT_UINT8, BASE_DEC, NULL, 0x00,
2360 "Last message number.",
2364 { &hf_ucp_parm_NMESS,
2365 { "NMESS", "ucp.parm.NMESS",
2366 FT_UINT8, BASE_DEC, NULL, 0x00,
2367 "Number of stored messages.",
2371 { &hf_ucp_parm_NMESS_str,
2372 { "NMESS_str", "ucp.parm.NMESS_str",
2373 FT_STRING, BASE_NONE, NULL, 0x00,
2374 "Number of stored messages.",
2378 { &hf_ucp_parm_NPID,
2379 { "NPID", "ucp.parm.NPID",
2380 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2381 "Notification PID value.",
2386 { "LRq", "ucp.parm.LRq",
2387 FT_UINT8, BASE_DEC, VALS(vals_parm_LRq), 0x00,
2388 "Last resort address request.",
2392 { &hf_ucp_parm_LRAd,
2393 { "LRAd", "ucp.parm.LRAd",
2394 FT_STRING, BASE_NONE, NULL, 0x00,
2395 "Last resort address.",
2399 { &hf_ucp_parm_LPID,
2400 { "LPID", "ucp.parm.LPID",
2401 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2402 "Last resort PID value.",
2407 { "DD", "ucp.parm.DD",
2408 FT_UINT8, BASE_DEC, VALS(vals_parm_DD), 0x00,
2409 "Deferred delivery requested.",
2414 { "DDT", "ucp.parm.DDT",
2415 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2416 "Deferred delivery time.",
2421 { "STx", "ucp.parm.STx",
2422 FT_NONE, BASE_NONE, NULL, 0x00,
2428 { "ST", "ucp.parm.ST",
2429 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2435 { "SP", "ucp.parm.SP",
2436 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2442 { "VP", "ucp.parm.VP",
2443 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2448 { &hf_ucp_parm_RPID,
2449 { "RPID", "ucp.parm.RPID",
2450 FT_STRING, BASE_NONE, NULL, 0x00,
2455 { &hf_ucp_parm_SCTS,
2456 { "SCTS", "ucp.parm.SCTS",
2457 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2458 "Service Centre timestamp.",
2463 { "Dst", "ucp.parm.Dst",
2464 FT_UINT8, BASE_DEC, VALS(vals_parm_Dst), 0x00,
2470 { "Rsn", "ucp.parm.Rsn",
2471 FT_UINT16, BASE_DEC, VALS(vals_parm_Rsn), 0x00,
2476 { &hf_ucp_parm_DSCTS,
2477 { "DSCTS", "ucp.parm.DSCTS",
2478 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2479 "Delivery timestamp.",
2484 { "MT", "ucp.parm.MT",
2485 FT_UINT8, BASE_DEC, VALS(vals_parm_MT), 0x00,
2491 { " NB", "ucp.parm.NB",
2492 FT_STRING, BASE_NONE, NULL, 0x00,
2493 "No. of bits in Transparent Data (TD) message.",
2497 { &hf_ucp_data_section,
2498 { " Data", "ucp.message",
2499 FT_NONE, BASE_NONE, NULL, 0x00,
2500 "The actual message or data.",
2505 { "MMS", "ucp.parm.MMS",
2506 FT_UINT8, BASE_DEC, NULL, 0x00,
2507 "More messages to send.",
2512 { "DCs", "ucp.parm.DCs",
2513 FT_UINT8, BASE_DEC, VALS(vals_parm_DCs), 0x00,
2514 "Data coding scheme (deprecated).",
2518 { &hf_ucp_parm_MCLs,
2519 { "MCLs", "ucp.parm.MCLs",
2520 FT_UINT8, BASE_DEC, VALS(vals_parm_MCLs), 0x00,
2526 { "RPI", "ucp.parm.RPI",
2527 FT_UINT8, BASE_DEC, VALS(vals_parm_RPI), 0x00,
2533 { "CPg", "ucp.parm.CPg",
2534 FT_STRING, BASE_NONE, NULL, 0x00,
2535 "Reserved for Code Page.",
2539 { &hf_ucp_parm_RPLy,
2540 { "RPLy", "ucp.parm.RPLy",
2541 FT_STRING, BASE_NONE, NULL, 0x00,
2542 "Reserved for Reply type.",
2546 { &hf_ucp_parm_OTOA,
2547 { "OTOA", "ucp.parm.OTOA",
2548 FT_STRING, BASE_NONE, NULL, 0x00,
2549 "Originator Type Of Address.",
2553 { &hf_ucp_parm_HPLMN,
2554 { "HPLMN", "ucp.parm.HPLMN",
2555 FT_STRING, BASE_NONE, NULL, 0x00,
2556 "Home PLMN address.",
2560 { &hf_ucp_parm_XSer,
2561 { "Extra services:", "ucp.parm.XSer",
2562 FT_NONE, BASE_DEC, NULL, 0x00,
2567 { &hf_ucp_parm_RES4,
2568 { "RES4", "ucp.parm.RES4",
2569 FT_STRING, BASE_NONE, NULL, 0x00,
2570 "Reserved for future use.",
2574 { &hf_ucp_parm_RES5,
2575 { "RES5", "ucp.parm.RES5",
2576 FT_STRING, BASE_NONE, NULL, 0x00,
2577 "Reserved for future use.",
2581 { &hf_ucp_parm_OTON,
2582 { "OTON", "ucp.parm.OTON",
2583 FT_UINT8, BASE_DEC, VALS(vals_parm_OTON), 0x00,
2584 "Originator type of number.",
2588 { &hf_ucp_parm_ONPI,
2589 { "ONPI", "ucp.parm.ONPI",
2590 FT_UINT8, BASE_DEC, VALS(vals_parm_ONPI), 0x00,
2591 "Originator numbering plan id.",
2595 { &hf_ucp_parm_STYP0,
2596 { "STYP0", "ucp.parm.STYP0",
2597 FT_UINT8, BASE_DEC, VALS(vals_parm_STYP0), 0x00,
2598 "Subtype of operation.",
2602 { &hf_ucp_parm_STYP1,
2603 { "STYP1", "ucp.parm.STYP1",
2604 FT_UINT8, BASE_DEC, VALS(vals_parm_STYP1), 0x00,
2605 "Subtype of operation.",
2610 { "PWD", "ucp.parm.PWD",
2611 FT_STRING, BASE_NONE, NULL, 0x00,
2612 "Current password.",
2616 { &hf_ucp_parm_NPWD,
2617 { "NPWD", "ucp.parm.NPWD",
2618 FT_STRING, BASE_NONE, NULL, 0x00,
2623 { &hf_ucp_parm_VERS,
2624 { "VERS", "ucp.parm.VERS",
2625 FT_STRING, BASE_NONE, NULL, 0x00,
2630 { &hf_ucp_parm_LAdC,
2631 { "LAdC", "ucp.parm.LAdC",
2632 FT_STRING, BASE_NONE, NULL, 0x00,
2633 "Address for VSMSC list operation.",
2637 { &hf_ucp_parm_LTON,
2638 { "LTON", "ucp.parm.LTON",
2639 FT_UINT8, BASE_DEC, NULL, 0x00,
2640 "Type of number list address.",
2644 { &hf_ucp_parm_LNPI,
2645 { "LNPI", "ucp.parm.LNPI",
2646 FT_UINT8, BASE_DEC, NULL, 0x00,
2647 "Numbering plan id. list address.",
2651 { &hf_ucp_parm_OPID,
2652 { "OPID", "ucp.parm.OPID",
2653 FT_UINT8, BASE_DEC, VALS(vals_parm_OPID), 0x00,
2654 "Originator protocol identifier.",
2658 { &hf_ucp_parm_RES1,
2659 { "RES1", "ucp.parm.RES1",
2660 FT_STRING, BASE_NONE, NULL, 0x00,
2661 "Reserved for future use.",
2665 { &hf_ucp_parm_RES2,
2666 { "RES2", "ucp.parm.RES2",
2667 FT_STRING, BASE_NONE, NULL, 0x00,
2668 "Reserved for future use.",
2673 { "(N)Ack", "ucp.parm.ACK",
2674 FT_UINT8, BASE_DEC, VALS(vals_parm_ACK), 0x00,
2675 "Positive or negative acknowledge of the operation.",
2680 { "MVP", "ucp.parm.MVP",
2681 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2682 "Modified validity period.",
2687 { "Error code", "ucp.parm.EC",
2688 FT_UINT8, BASE_DEC, VALS(vals_parm_EC), 0x00,
2689 "The result of the requested operation.",
2694 { "SM", "ucp.parm.SM",
2695 FT_STRING, BASE_NONE, NULL, 0x00,
2701 { "Type of service", "ucp.xser.service",
2702 FT_UINT8, BASE_HEX, VALS(vals_xser_service), 0x00,
2703 "The type of service specified.",
2708 /* Setup protocol subtree array */
2709 static gint *ett[] = {
2714 module_t *ucp_module;
2716 /* Register the protocol name and description */
2717 proto_ucp = proto_register_protocol("Universal Computer Protocol",
2720 /* Required function calls to register header fields and subtrees used */
2721 proto_register_field_array(proto_ucp, hf, array_length(hf));
2722 proto_register_subtree_array(ett, array_length(ett));
2724 /* Register for tapping */
2725 ucp_tap = register_tap("ucp");
2727 /* register preferences */
2728 ucp_module = prefs_register_protocol(proto_ucp, NULL);
2729 prefs_register_bool_preference(ucp_module, "desegment_ucp_messages",
2730 "Reassemble UCP messages spanning multiple TCP segments",
2731 "Whether the UCP dissector should reassemble messages spanning multiple TCP segments."
2732 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2738 * If dissector uses sub-dissector registration add a registration routine.
2739 * This format is required because a script is used to find these routines and
2740 * create the code that calls these routines.
2743 proto_reg_handoff_ucp(void)
2745 dissector_handle_t ucp_handle;
2748 * UCP can be spoken on any port so, when not on a specific port, try this
2749 * one whenever TCP is spoken.
2751 heur_dissector_add("tcp", dissect_ucp_heur, proto_ucp);
2754 * Also register as one that can be selected by a TCP port number.
2756 ucp_handle = create_dissector_handle(dissect_ucp_tcp, proto_ucp);
2757 dissector_add_handle("tcp.port", ucp_handle);
2760 stats_tree_register_with_group("ucp", "ucp_messages", st_str_ucp,
2761 ucp_stats_tree_per_packet, ucp_stats_tree_init,
2762 NULL, REGISTER_STAT_GROUP_TELEPHONY);