2 * Routines for Universal Computer Protocol dissection
3 * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
5 * $Id: packet-ucp.c,v 1.24 2004/03/23 01:29:45 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
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)
45 #include <epan/packet.h>
46 /* #include "packet-ucp.h" */ /* We autoregister */
49 static void dissect_ucp(tvbuff_t *, packet_info *, proto_tree *);
52 * Convert ASCII-hex character to binary equivalent. No checks, assume
53 * is valid hex character.
55 #define AHex2Bin(n) (((n) & 0x40) ? ((n) & 0x0F) + 9 : ((n) & 0x0F))
57 #define UCP_STX 0x02 /* Start of UCP PDU */
58 #define UCP_ETX 0x03 /* End of UCP PDU */
60 #define UCP_MALFORMED -1 /* Not a valid PDU */
61 #define UCP_SHORTENED -2 /* May be valid but short */
62 #define UCP_INV_CHK -3 /* Checksum doesn't add up */
64 #define UCP_O_R_OFFSET 10 /* Location of O/R field*/
65 #define UCP_OT_OFFSET 12 /* Location of OT field */
67 #define UCP_TRN_LEN 2 /* Length of TRN-field */
68 #define UCP_LEN_LEN 5 /* Length of LEN-field */
69 #define UCP_O_R_LEN 1 /* Length of O/R-field */
70 #define UCP_OT_LEN 2 /* Length of OT-field */
73 * Initialize the protocol and registered fields
75 * Header (fixed) section
77 static int proto_ucp = -1;
79 static int hf_ucp_hdr_TRN = -1;
80 static int hf_ucp_hdr_LEN = -1;
81 static int hf_ucp_hdr_O_R = -1;
82 static int hf_ucp_hdr_OT = -1;
85 * Data (variable) section
87 static int hf_ucp_oper_section = -1;
88 static int hf_ucp_parm_AdC = -1;
89 static int hf_ucp_parm_OAdC = -1;
90 static int hf_ucp_parm_DAdC = -1;
91 static int hf_ucp_parm_AC = -1;
92 static int hf_ucp_parm_OAC = -1;
93 static int hf_ucp_parm_BAS = -1;
94 static int hf_ucp_parm_LAR = -1;
95 static int hf_ucp_parm_LAC = -1;
96 static int hf_ucp_parm_L1R = -1;
97 static int hf_ucp_parm_L1P = -1;
98 static int hf_ucp_parm_L3R = -1;
99 static int hf_ucp_parm_L3P = -1;
100 static int hf_ucp_parm_LCR = -1;
101 static int hf_ucp_parm_LUR = -1;
102 static int hf_ucp_parm_LRR = -1;
103 static int hf_ucp_parm_RT = -1;
104 static int hf_ucp_parm_NoN = -1;
105 static int hf_ucp_parm_NoA = -1;
106 static int hf_ucp_parm_NoB = -1;
107 static int hf_ucp_parm_NAC = -1;
108 static int hf_ucp_parm_PNC = -1;
109 static int hf_ucp_parm_AMsg = -1;
110 static int hf_ucp_parm_LNo = -1;
111 static int hf_ucp_parm_LST = -1;
112 static int hf_ucp_parm_TNo = -1;
113 static int hf_ucp_parm_CS = -1;
114 static int hf_ucp_parm_PID = -1;
115 static int hf_ucp_parm_NPL = -1;
116 static int hf_ucp_parm_GA = -1;
117 static int hf_ucp_parm_RP = -1;
118 static int hf_ucp_parm_LRP = -1;
119 static int hf_ucp_parm_PR = -1;
120 static int hf_ucp_parm_LPR = -1;
121 static int hf_ucp_parm_UM = -1;
122 static int hf_ucp_parm_LUM = -1;
123 static int hf_ucp_parm_RC = -1;
124 static int hf_ucp_parm_LRC = -1;
125 static int hf_ucp_parm_NRq = -1;
126 static int hf_ucp_parm_GAdC = -1;
127 static int hf_ucp_parm_A_D = -1;
128 static int hf_ucp_parm_CT = -1;
129 static int hf_ucp_parm_AAC = -1;
130 static int hf_ucp_parm_MNo = -1;
131 static int hf_ucp_parm_R_T = -1;
132 static int hf_ucp_parm_IVR5x = -1;
133 static int hf_ucp_parm_REQ_OT = -1;
134 static int hf_ucp_parm_SSTAT = -1;
135 static int hf_ucp_parm_LMN = -1;
136 static int hf_ucp_parm_NMESS = -1;
137 static int hf_ucp_parm_NMESS_str= -1;
138 static int hf_ucp_parm_NAdC = -1;
139 static int hf_ucp_parm_NT = -1;
140 static int hf_ucp_parm_NPID = -1;
141 static int hf_ucp_parm_LRq = -1;
142 static int hf_ucp_parm_LRAd = -1;
143 static int hf_ucp_parm_LPID = -1;
144 static int hf_ucp_parm_DD = -1;
145 static int hf_ucp_parm_DDT = -1;
146 static int hf_ucp_parm_STx = -1;
147 static int hf_ucp_parm_ST = -1;
148 static int hf_ucp_parm_SP = -1;
149 static int hf_ucp_parm_VP = -1;
150 static int hf_ucp_parm_RPID = -1;
151 static int hf_ucp_parm_SCTS = -1;
152 static int hf_ucp_parm_Dst = -1;
153 static int hf_ucp_parm_Rsn = -1;
154 static int hf_ucp_parm_DSCTS = -1;
155 static int hf_ucp_parm_MT = -1;
156 static int hf_ucp_parm_NB = -1;
157 static int hf_ucp_data_section = -1;
158 static int hf_ucp_parm_MMS = -1;
159 static int hf_ucp_parm_DCs = -1;
160 static int hf_ucp_parm_MCLs = -1;
161 static int hf_ucp_parm_RPI = -1;
162 static int hf_ucp_parm_CPg = -1;
163 static int hf_ucp_parm_RPLy = -1;
164 static int hf_ucp_parm_OTOA = -1;
165 static int hf_ucp_parm_HPLMN = -1;
166 static int hf_ucp_parm_RES4 = -1;
167 static int hf_ucp_parm_RES5 = -1;
168 static int hf_ucp_parm_OTON = -1;
169 static int hf_ucp_parm_ONPI = -1;
170 static int hf_ucp_parm_STYP0 = -1;
171 static int hf_ucp_parm_STYP1 = -1;
172 static int hf_ucp_parm_ACK = -1;
173 static int hf_ucp_parm_PWD = -1;
174 static int hf_ucp_parm_NPWD = -1;
175 static int hf_ucp_parm_VERS = -1;
176 static int hf_ucp_parm_LAdC = -1;
177 static int hf_ucp_parm_LTON = -1;
178 static int hf_ucp_parm_LNPI = -1;
179 static int hf_ucp_parm_OPID = -1;
180 static int hf_ucp_parm_RES1 = -1;
181 static int hf_ucp_parm_RES2 = -1;
182 static int hf_ucp_parm_MVP = -1;
183 static int hf_ucp_parm_EC = -1;
184 static int hf_ucp_parm_SM = -1;
186 static int hf_ucp_parm_XSer = -1;
187 static int hf_xser_service = -1;
189 /* Initialize the subtree pointers */
190 static gint ett_ucp = -1;
191 static gint ett_sub = -1;
192 static gint ett_XSer = -1;
195 * Value-arrays for certain field-contents
197 static const value_string vals_hdr_O_R[] = {
198 { 'O', "Operation" },
203 static const value_string vals_hdr_OT[] = { /* Operation type */
206 { 2, "Call input (multiple address)" },
207 { 3, "Call input (supplementary services included)" },
208 { 4, "Address list information" },
209 { 5, "Change address list" },
210 { 6, "Advice of accumulated charges" },
211 { 7, "Password management" },
212 { 8, "Legitimisation code management" },
213 { 9, "Standard text information" },
214 { 10, "Change standard text" },
215 { 11, "Request roaming information" },
216 { 12, "Change roaming information" },
217 { 13, "Roaming reset" },
218 { 14, "Message retrieval" },
219 { 15, "Request call barring" },
220 { 16, "Cancel call barring" },
221 { 17, "Request call diversion" },
222 { 18, "Cancel call diversion" },
223 { 19, "Request deferred delivery" },
224 { 20, "Cancel deferred delivery" },
225 { 21, "All features reset" },
226 { 22, "Call input (with specific character set)" },
227 { 23, "UCP version status request" },
228 { 24, "Mobile subscriber feature status request" },
229 { 30, "SMS message transfer" },
231 { 32, "(proprietary)" },
232 { 34, "(proprietary)" },
233 { 36, "(proprietary)" },
234 { 38, "(proprietary)" },
235 { 40, "(proprietary)" },
236 { 41, "(proprietary)" },
237 { 42, "(proprietary)" },
238 { 43, "(proprietary)" },
239 { 44, "(proprietary)" },
240 { 45, "(proprietary)" },
241 { 51, "Submit short message" },
242 { 52, "Deliver short message" },
243 { 53, "Deliver notification" },
244 { 54, "Modify message" },
245 { 55, "Inquiry message" },
246 { 56, "Delete message" },
247 { 57, "Inquiry response message" },
248 { 58, "Delete response message" },
249 { 60, "Session management" },
250 { 61, "List management" },
251 { 95, "(proprietary)" },
252 { 96, "(proprietary)" },
253 { 97, "(proprietary)" },
254 { 98, "(proprietary)" },
255 { 99, "(proprietary)" },
259 static const value_string vals_parm_EC[] = { /* Error code */
260 { 1, "Checksum error" },
261 { 2, "Syntax error" },
262 { 3, "Operation not supported by system" },
263 { 4, "Operation not allowed" },
264 { 5, "Call barring active" },
265 { 6, "AdC invalid" },
266 { 7, "Authentication failure" },
267 { 8, "Legitimisation code for all calls, failure" },
268 { 9, "GA not valid" },
269 { 10, "Repetition not allowed" },
270 { 11, "Legitimisation code for repetition, failure" },
271 { 12, "Priority call not allowed" },
272 { 13, "Legitimisation code for priority call, failure" },
273 { 14, "Urgent message not allowed" },
274 { 15, "Legitimisation code for urgent message, failure" },
275 { 16, "Reverse charging not alllowed" },
276 { 17, "Legitimisation code for rev. charging, failure" },
277 { 18, "Deferred delivery not allowed" },
278 { 19, "New AC not valid" },
279 { 20, "New legitimisation code not valid" },
280 { 21, "Standard text not valid" },
281 { 22, "Time period not valid" },
282 { 23, "Message type not supported by system" },
283 { 24, "Message too long" },
284 { 25, "Requested standard text not valid" },
285 { 26, "Message type not valid for the pager type" },
286 { 27, "Message not found in SMSC" },
287 { 28, "Invalid character set" },
288 { 30, "Subscriber hang-up" },
289 { 31, "Fax group not supported" },
290 { 32, "Fax message type not supported" },
291 { 33, "Address already in list (60-series)" },
292 { 34, "Address not in list (60-series)" },
293 { 35, "List full, cannot add address to list (60-series)" },
294 { 36, "RPID already in use" },
295 { 37, "Delivery in progress" },
296 { 38, "Message forwarded" },
297 { 50, "Low network status" },
298 { 51, "Legitimisation code for standard text, failure" },
299 { 53, "Operation partially successfull" },
300 { 54, "Operation not successfull" },
301 { 55, "System error" },
302 { 57, "AdC already a member of GAdC address list" },
303 { 58, "AdC not a member of GAdC address list" },
304 { 59, "Requested standard text list invalid" },
305 { 61, "Not controller of GAdC address list" },
306 { 62, "Standard text too large" },
307 { 63, "Not owner of standard text list" },
308 { 64, "Address list full" },
309 { 65, "GAdC invalid" },
310 { 66, "Operation restricted to mobile subscribers" },
311 { 68, "Invalid AdC type" },
312 { 69, "Cannot add AdC to GAdC address list" },
313 { 90, "(proprietary error code)" },
314 { 91, "(proprietary error code)" },
315 { 92, "(proprietary error code)" },
316 { 93, "(proprietary error code)" },
317 { 94, "(proprietary error code)" },
318 { 95, "(proprietary error code)" },
319 { 96, "(proprietary error code)" },
320 { 97, "(proprietary error code)" },
321 { 98, "(proprietary error code)" },
322 { 99, "(proprietary error code)" },
326 static const value_string vals_parm_NRq[] = {
327 { '0', "NAdC not used" },
328 { '1', "NAdC used" },
332 static const value_string vals_parm_NT[] = {
333 { '0', "Default value" },
334 { '1', "Delivery notification" },
335 { '2', "Non-delivery notification" },
336 { '3', "Delivery and Non-delivery notification" },
337 { '4', "Buffered message notification" },
338 { '5', "Buffered and Delivery notification" },
339 { '6', "Buffered and Non-delivery notification" },
340 { '7', "All notifications" },
344 static const value_string vals_parm_PID[] = {
345 { 100, "Mobile station" },
346 { 122, "Fax Group 3" },
348 { 138, "Menu over PSTN" },
349 { 139, "PC appl. over PSTN (E.164)" },
350 { 339, "PC appl. over X.25 (X.121)" },
351 { 439, "PC appl. over ISDN (E.164)" },
352 { 539, "PC appl. over TCP/IP" },
356 static const value_string vals_parm_LRq[] = {
357 { '0', "LRAd not used" },
358 { '1', "LRAd used" },
362 static const value_string vals_parm_DD[] = {
363 { '0', "DDT not used" },
368 static const value_string vals_parm_Dst[] = {
369 { '0', "delivered" },
370 { '1', "buffered (see Rsn)" },
371 { '2', "not delivered (see Rsn)" },
375 static const value_string vals_parm_Rsn[] = {
376 { 0, "Unknown subscriber" },
377 { 1, "Service temporary not available" },
378 { 2, "Service temporary not available" },
379 { 3, "Service temporary not available" },
380 { 4, "Service temporary not available" },
381 { 5, "Service temporary not available" },
382 { 6, "Service temporary not available" },
383 { 7, "Service temporary not available" },
384 { 8, "Service temporary not available" },
385 { 9, "Illegal error code" },
386 { 10, "Network time-out" },
387 { 100, "Facility not supported" },
388 { 101, "Unknown subscriber" },
389 { 102, "Facility not provided" },
390 { 103, "Call barred" },
391 { 104, "Operation barred" },
392 { 105, "SC congestion" },
393 { 106, "Facility not supported" },
394 { 107, "Absent subscriber" },
395 { 108, "Delivery fail" },
396 { 109, "Sc congestion" },
397 { 110, "Protocol error" },
398 { 111, "MS not equiped" },
399 { 112, "Unknown SC" },
400 { 113, "SC congestion" },
401 { 114, "Illegal MS" },
402 { 115, "MS nota subscriber" },
403 { 116, "Error in MS" },
404 { 117, "SMS lower layer not provisioned" },
405 { 118, "System fail" },
406 { 119, "PLMN system failure" },
407 { 120, "HLR system failure" },
408 { 121, "VLR system failure" },
409 { 122, "Previous VLR system failure" },
410 { 123, "Controlling MSC system failure" },
411 { 124, "VMSC system failure" },
412 { 125, "EIR system failure" },
413 { 126, "System failure" },
414 { 127, "Unexpected data value" },
415 { 200, "Error in address service centre" },
416 { 201, "Invalid absolute validity period" },
417 { 202, "Short message exceeds maximum" },
418 { 203, "Unable to unpack GSM message" },
419 { 204, "Unable to convert to IRA alphabet" },
420 { 205, "Invalid validity period format" },
421 { 206, "Invalid destination address" },
422 { 207, "Duplicate message submit" },
423 { 208, "Invalid message type indicator" },
427 static const value_string vals_parm_MT[] = {
428 { '2', "Numeric message" },
429 { '3', "Alphanumeric message" },
430 { '4', "Transparent data" },
434 static const value_string vals_parm_DCs[] = {
435 { '0', "default alphabet" },
436 { '1', "User defined data (8 bit)" },
440 static const value_string vals_parm_MCLs[] = {
441 { '0', "message class 0" },
442 { '1', "message class 1" },
443 { '2', "message class 2" },
444 { '3', "message class 3" },
448 static const value_string vals_parm_RPI[] = {
454 static const value_string vals_parm_ACK[] = {
460 static const value_string vals_parm_RP[] = {
461 { '1', "Repetition requested" },
465 static const value_string vals_parm_UM[] = {
466 { '1', "Urgent message" },
470 static const value_string vals_parm_RC[] = {
471 { '1', "Reverse charging request" },
475 static const value_string vals_parm_OTON[] = {
476 { '1', "International number" },
477 { '2', "National number" },
478 { '6', "Abbreviated number (short number alias)" },
482 static const value_string vals_parm_ONPI[] = {
483 { '1', "E.164 address" },
484 { '3', "X.121 address" },
485 { '5', "Private -TCP/IP or abbreviated number- address" },
489 static const value_string vals_parm_STYP0[] = {
490 { '1', "open session" },
492 { '3', "change password" },
493 { '4', "open provisioning session" },
495 { '6', "change provisioning password" },
499 static const value_string vals_parm_STYP1[] = {
500 { '1', "add item to mo-list" },
501 { '2', "remove item from mo-list" },
502 { '3', "verify item mo-list" },
503 { '4', "add item to mt-list" },
504 { '5', "remove item from mt-list" },
505 { '6', "verify item mt-list" },
509 static const value_string vals_parm_OPID[] = {
510 { 0, "Mobile station" },
511 { 39, "PC application" },
515 static const value_string vals_parm_BAS[] = {
520 static const value_string vals_parm_LAR[] = {
521 { '1', "Leg. code for all calls requested" },
525 static const value_string vals_parm_L1R[] = {
526 { '1', "Leg. code for priority 1 requested" },
530 static const value_string vals_parm_L3R[] = {
531 { '1', "Leg. code for priority 3 requested" },
535 static const value_string vals_parm_LCR[] = {
536 { '1', "Leg. code for reverse charging requested" },
540 static const value_string vals_parm_LUR[] = {
541 { '1', "Leg. code for urgent message requested" },
545 static const value_string vals_parm_LRR[] = {
546 { '1', "Leg. code for repitition requested" },
550 static const value_string vals_parm_RT[] = {
551 { '1', "Tone only" },
553 { '3', "Alphanumeric" },
554 { '4', "Transparent data" },
558 static const value_string vals_parm_PNC[] = {
560 { 'I', "Input PNC" },
564 static const value_string vals_parm_A_D[] = {
570 static const value_string vals_parm_R_T[] = {
571 { 'R', "Retrieval Ok" },
572 { 'T', "Retransmit on radio channel" },
576 static const value_string vals_parm_REQ_OT[] = {
577 { 'S', "Send used operation types" },
578 { 'N', "Don't send used operation types" },
582 static const value_string vals_parm_SSTAT[] = {
583 { '0', "All services" },
584 { '1', "All in the moment active servics" },
585 { '2', "Call diversion" },
586 { '3', "Roaming information status" },
587 { '4', "Call barring status" },
588 { '5', "Deferred delivery status" },
589 { '6', "Number of stored messages" },
593 static const value_string vals_xser_service[] = {
594 { 1, "GSM UDH information" },
595 { 2, "GSM DCS information" },
596 { 3, "[Message Type] TDMA information exchange" },
597 { 4, "[Message Reference] TDMA information exchange" },
598 { 5, "[Privacy Indicator] TDMA information exchange" },
599 { 6, "[Urgency Indicator] TDMA information exchange" },
600 { 7, "[Acknowledgement Request] TDMA information exchange" },
601 { 8, "[Messsage Updating] TDMA information exchange" },
602 { 9, "[Call Back Number] TDMA information exchange" },
603 { 10, "[Response Code] TDMA information exchange" },
604 { 11, "[Teleservice ID] TDMA information exchange" },
605 { 12, "Billing identifier" },
606 { 13, "Single shot indicator" },
611 * Checks whether the PDU looks a bit like UCP and checks the checksum
613 * \param tvb The buffer with PDU-data
614 * \param endpkt Returns pointer, indicating the end of the PDU
616 * \return The state of this PDU
617 * \retval 0 Definitely UCP
618 * \retval UCP_SHORTENED Packet may be there, but not complete
619 * \retval UCP_MALFORMED Hmmmm, not UCP after all...
620 * \retval UCP_INV_CHK Nice packet, but checksum doesn't add up...
623 check_ucp(tvbuff_t *tvb, int *endpkt)
630 length = tvb_find_guint8(tvb, offset, -1, UCP_ETX);
632 /* XXX - should we have an option to request reassembly? */
633 *endpkt = tvb_reported_length_remaining(tvb, offset);
634 return UCP_SHORTENED;
636 if (length > (int) tvb_reported_length(tvb)) {
637 /* XXX - "cannot happen" */
639 return UCP_MALFORMED;
641 for (; offset < (guint) (length - 2); offset++)
642 checksum += tvb_get_guint8(tvb, offset);
644 tmp = tvb_get_guint8(tvb, offset++);
645 pkt_check = AHex2Bin(tmp);
646 tmp = tvb_get_guint8(tvb, offset++);
647 pkt_check = 16 * pkt_check + AHex2Bin(tmp);
648 *endpkt = offset + 1;
649 if (checksum == (guint) pkt_check)
656 * UCP equivalent of mktime() (3). Convert date to standard 'time_t' format
658 * \param datestr The UCP-formatted date to convert
660 * \return The date in standard 'time_t' format.
663 ucp_mktime(char *datestr)
667 r_time.tm_mday = 10 * (datestr[0] - '0') + (datestr[1] - '0');
668 r_time.tm_mon = (10 * (datestr[2] - '0') + (datestr[3] - '0')) - 1;
669 r_time.tm_year = 10 * (datestr[4] - '0') + (datestr[5] - '0');
670 if (r_time.tm_year < 90)
671 r_time.tm_year += 100;
672 r_time.tm_hour = 10 * (datestr[6] - '0') + (datestr[7] - '0');
673 r_time.tm_min = 10 * (datestr[8] - '0') + (datestr[9] - '0');
675 r_time.tm_sec = 10 * (datestr[10] - '0') + (datestr[11] - '0');
678 r_time.tm_isdst = -1;
679 return mktime(&r_time);
683 * Scanning routines to add standard types (byte, int, string, data)
684 * to the protocol-tree. Each field is seperated with a slash ('/').
686 * \param tree The protocol tree to add to
687 * \param tvb Buffer containing the data
688 * \param field The actual field, whose value needs displaying
689 * \param offset Location of field within the buffer, returns location
692 * \return For 'int'-types, the value of the field.
695 ucp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
699 idx = tvb_find_guint8(tvb, *offset, -1, '/');
701 /* Force the appropriate exception to be thrown. */
702 len = tvb_length_remaining(tvb, *offset);
703 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
707 proto_tree_add_item(tree, field, tvb, *offset, len, FALSE);
710 *offset += 1; /* skip terminating '/' */
714 ucp_handle_IRAstring(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
716 char strval[BUFSIZ + 1],
720 int tmpoff = *offset;
722 while (((byte = tvb_get_guint8(tvb, tmpoff++)) != '/') &&
725 if (byte >= '0' && byte <= '9')
727 *p_dst = (byte - '0') * 16;
731 *p_dst = (byte - 'A' + 10) * 16;
733 if ((byte = tvb_get_guint8(tvb, tmpoff++)) == '/')
737 if (byte >= '0' && byte <= '9')
739 *p_dst++ += byte - '0';
743 *p_dst++ += byte - 'A' + 10;
751 * Data clipped, eat rest of field
753 while ((tvb_get_guint8(tvb, tmpoff++)) != '/')
756 if ((tmpoff - *offset) > 1)
757 proto_tree_add_string(tree, field, tvb, *offset,
758 tmpoff - *offset - 1, strval);
763 ucp_handle_byte(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
767 if ((intval = tvb_get_guint8(tvb, (*offset)++)) != '/') {
768 proto_tree_add_uint(tree, field, tvb, *offset - 1, 1, intval);
775 ucp_handle_int(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
781 idx = tvb_find_guint8(tvb, *offset, -1, '/');
783 /* Force the appropriate exception to be thrown. */
784 len = tvb_length_remaining(tvb, *offset);
785 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
788 strval = tvb_get_string(tvb, *offset, len);
790 intval = atoi(strval);
791 proto_tree_add_uint(tree, field, tvb, *offset, idx, intval);
796 *offset += 1; /* skip terminating '/' */
801 ucp_handle_time(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
808 idx = tvb_find_guint8(tvb, *offset, -1, '/');
810 /* Force the appropriate exception to be thrown. */
811 len = tvb_length_remaining(tvb, *offset);
812 tvb_ensure_bytes_exist(tvb, *offset, len + 1);
815 strval = tvb_get_string(tvb, *offset, len);
817 tval = ucp_mktime(strval);
820 proto_tree_add_time(tree, field, tvb, *offset, idx, &tmptime);
825 *offset += 1; /* skip terminating '/' */
829 ucp_handle_data(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
831 int tmpoff = *offset;
833 while (tvb_get_guint8(tvb, tmpoff++) != '/')
835 if ((tmpoff - *offset) > 1)
836 proto_tree_add_item(tree, field, tvb, *offset,
837 tmpoff - *offset - 1, FALSE);
842 * Handle the data-field within the UCP-message, according the Message Type
844 * - 2 Numeric message
845 * - 3 Alphanumeric message
846 * - 4 Transparent (binary) data
847 * - 5 Standard text handling
848 * - 6 Alphanumeric message in specified character set
850 * \param tree The protocol tree to add to
851 * \param tvb Buffer containing the data
852 * \param field The actual field, whose value needs displaying
853 * \param offset Location of field within the buffer, returns location
857 ucp_handle_mt(proto_tree *tree, tvbuff_t *tvb, int *offset)
861 intval = ucp_handle_byte(tree, tvb, hf_ucp_parm_MT, offset);
863 case '1': /* Tone only, no data */
865 case '4': /* TMsg, no of bits */
866 ucp_handle_string(tree, tvb, hf_ucp_parm_NB, offset);
867 /* fall through here for the data piece */
869 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
872 ucp_handle_IRAstring(tree, tvb, hf_ucp_parm_AMsg, offset);
875 ucp_handle_byte(tree, tvb, hf_ucp_parm_PNC, offset);
876 ucp_handle_string(tree, tvb, hf_ucp_parm_LNo, offset);
877 ucp_handle_string(tree, tvb, hf_ucp_parm_LST, offset);
878 ucp_handle_string(tree, tvb, hf_ucp_parm_TNo, offset);
881 ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
882 ucp_handle_int(tree, tvb, hf_ucp_parm_CS, offset);
885 break; /* No data so ? */
890 * Handle the data within the 'Extended services' field. Each field having the
891 * format TTLLDD..., TT being the type of service, LL giving the length of the
892 * field, DD... containing the actual data
894 * \param tree The protocol tree to add to
895 * \param tvb Buffer containing the extended services data
898 ucp_handle_XSer(proto_tree *tree, tvbuff_t *tvb)
905 while ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
906 service = AHex2Bin(intval);
907 intval = tvb_get_guint8(tvb, offset++);
908 service = service * 16 + AHex2Bin(intval);
909 intval = tvb_get_guint8(tvb, offset++);
910 len = AHex2Bin(intval);
911 intval = tvb_get_guint8(tvb, offset++);
912 len = len * 16 + AHex2Bin(intval);
913 proto_tree_add_uint(tree, hf_xser_service, tvb, offset,
919 /* Next definitions are just a convenient shorthand to make the coding a
920 * bit more readable instead of summing up all these parameters.
922 #define UcpHandleString(field) ucp_handle_string(tree, tvb, (field), &offset)
924 #define UcpHandleIRAString(field) \
925 ucp_handle_IRAstring(tree, tvb, (field), &offset)
927 #define UcpHandleByte(field) ucp_handle_byte(tree, tvb, (field), &offset)
929 #define UcpHandleInt(field) ucp_handle_int(tree, tvb, (field), &offset)
931 #define UcpHandleTime(field) ucp_handle_time(tree, tvb, (field), &offset)
933 #define UcpHandleData(field) ucp_handle_data(tree, tvb, (field), &offset)
936 * The next set of routines handle the different operation types,
937 * associated with UCP.
940 add_00O(proto_tree *tree, tvbuff_t *tvb)
944 UcpHandleString(hf_ucp_parm_AdC);
945 UcpHandleString(hf_ucp_parm_OAdC);
946 UcpHandleString(hf_ucp_parm_OAC);
950 add_00R(proto_tree *tree, tvbuff_t *tvb)
955 intval = UcpHandleByte(hf_ucp_parm_ACK);
958 UcpHandleByte(hf_ucp_parm_BAS);
959 UcpHandleByte(hf_ucp_parm_LAR);
960 UcpHandleByte(hf_ucp_parm_L1R);
961 UcpHandleByte(hf_ucp_parm_L3R);
962 UcpHandleByte(hf_ucp_parm_LCR);
963 UcpHandleByte(hf_ucp_parm_LUR);
964 UcpHandleByte(hf_ucp_parm_LRR);
965 UcpHandleByte(hf_ucp_parm_RT);
966 UcpHandleInt(hf_ucp_parm_NoN);
967 UcpHandleInt(hf_ucp_parm_NoA);
968 UcpHandleInt(hf_ucp_parm_NoB);
970 UcpHandleInt(hf_ucp_parm_EC);
971 UcpHandleString(hf_ucp_parm_SM);
976 add_01O(proto_tree *tree, tvbuff_t *tvb)
980 UcpHandleString(hf_ucp_parm_AdC);
981 UcpHandleString(hf_ucp_parm_OAdC);
982 UcpHandleString(hf_ucp_parm_OAC);
983 ucp_handle_mt(tree, tvb, &offset);
987 add_01R(proto_tree *tree, tvbuff_t *tvb)
992 intval = UcpHandleByte(hf_ucp_parm_ACK);
994 UcpHandleInt(hf_ucp_parm_EC);
995 UcpHandleString(hf_ucp_parm_SM);
999 add_02O(proto_tree *tree, tvbuff_t *tvb)
1000 { /* Multiple address call input*/
1005 intval = UcpHandleInt(hf_ucp_parm_NPL);
1006 for (idx = 0; idx < intval; idx++)
1007 UcpHandleString(hf_ucp_parm_AdC);
1009 UcpHandleString(hf_ucp_parm_OAdC);
1010 UcpHandleString(hf_ucp_parm_OAC);
1011 ucp_handle_mt(tree, tvb, &offset);
1014 #define add_02R(a, b) add_01R(a,b)
1017 add_03O(proto_tree *tree, tvbuff_t *tvb)
1018 { /* Call input with SS */
1023 UcpHandleString(hf_ucp_parm_AdC);
1024 UcpHandleString(hf_ucp_parm_OAdC);
1025 UcpHandleString(hf_ucp_parm_OAC);
1026 intval = UcpHandleInt(hf_ucp_parm_NPL);
1027 for (idx = 0; idx < intval; idx++)
1028 UcpHandleString(hf_ucp_parm_GA);
1030 UcpHandleByte(hf_ucp_parm_RP);
1031 UcpHandleString(hf_ucp_parm_LRP);
1032 UcpHandleByte(hf_ucp_parm_PR);
1033 UcpHandleString(hf_ucp_parm_LPR);
1034 UcpHandleByte(hf_ucp_parm_UM);
1035 UcpHandleString(hf_ucp_parm_LUM);
1036 UcpHandleByte(hf_ucp_parm_RC);
1037 UcpHandleString(hf_ucp_parm_LRC);
1038 UcpHandleByte(hf_ucp_parm_DD);
1039 UcpHandleTime(hf_ucp_parm_DDT);
1040 ucp_handle_mt(tree, tvb, &offset);
1043 #define add_03R(a, b) add_01R(a,b)
1046 add_04O(proto_tree *tree, tvbuff_t *tvb)
1047 { /* Address list information */
1050 UcpHandleString(hf_ucp_parm_GAdC);
1051 UcpHandleString(hf_ucp_parm_AC);
1052 UcpHandleString(hf_ucp_parm_OAdC);
1053 UcpHandleString(hf_ucp_parm_OAC);
1057 add_04R(proto_tree *tree, tvbuff_t *tvb)
1063 intval = UcpHandleByte(hf_ucp_parm_ACK);
1064 if (intval == 'A') {
1065 intval = UcpHandleInt(hf_ucp_parm_NPL);
1066 for (idx = 0; idx < intval; idx++)
1067 UcpHandleString(hf_ucp_parm_AdC);
1068 UcpHandleString(hf_ucp_parm_GAdC);
1070 UcpHandleInt(hf_ucp_parm_EC);
1071 UcpHandleString(hf_ucp_parm_SM);
1075 add_05O(proto_tree *tree, tvbuff_t *tvb)
1076 { /* Change address list */
1081 UcpHandleString(hf_ucp_parm_GAdC);
1082 UcpHandleString(hf_ucp_parm_AC);
1083 UcpHandleString(hf_ucp_parm_OAdC);
1084 UcpHandleString(hf_ucp_parm_OAC);
1085 intval = UcpHandleInt(hf_ucp_parm_NPL);
1086 for (idx = 0; idx < intval; idx++)
1087 UcpHandleString(hf_ucp_parm_AdC);
1088 UcpHandleByte(hf_ucp_parm_A_D);
1091 #define add_05R(a, b) add_01R(a, b)
1094 add_06O(proto_tree *tree, tvbuff_t *tvb)
1095 { /* Advice of accum. charges */
1098 UcpHandleString(hf_ucp_parm_AdC);
1099 UcpHandleString(hf_ucp_parm_AC);
1103 add_06R(proto_tree *tree, tvbuff_t *tvb)
1108 intval = UcpHandleByte(hf_ucp_parm_ACK);
1109 if (intval == 'A') {
1110 UcpHandleTime(hf_ucp_parm_CT);
1111 UcpHandleString(hf_ucp_parm_AAC);
1113 UcpHandleInt(hf_ucp_parm_EC);
1114 UcpHandleString(hf_ucp_parm_SM);
1118 add_07O(proto_tree *tree, tvbuff_t *tvb)
1119 { /* Password management */
1122 UcpHandleString(hf_ucp_parm_AdC);
1123 UcpHandleString(hf_ucp_parm_AC);
1124 UcpHandleString(hf_ucp_parm_NAC);
1127 #define add_07R(a, b) add_01R(a, b)
1130 add_08O(proto_tree *tree, tvbuff_t *tvb)
1131 { /* Leg. code management */
1134 UcpHandleString(hf_ucp_parm_AdC);
1135 UcpHandleString(hf_ucp_parm_AC);
1136 UcpHandleString(hf_ucp_parm_LAC);
1137 UcpHandleString(hf_ucp_parm_L1P);
1138 UcpHandleString(hf_ucp_parm_L3P);
1139 UcpHandleString(hf_ucp_parm_LRC);
1140 UcpHandleString(hf_ucp_parm_LUM);
1141 UcpHandleString(hf_ucp_parm_LRP);
1142 UcpHandleString(hf_ucp_parm_LST);
1145 #define add_08R(a, b) add_01R(a, b)
1148 add_09O(proto_tree *tree, tvbuff_t *tvb)
1149 { /* Standard text information */
1152 UcpHandleString(hf_ucp_parm_LNo);
1153 UcpHandleString(hf_ucp_parm_LST);
1157 add_09R(proto_tree *tree, tvbuff_t *tvb)
1163 intval = UcpHandleByte(hf_ucp_parm_ACK);
1164 if (intval == 'A') {
1165 intval = UcpHandleInt(hf_ucp_parm_NPL);
1166 for (idx = 0; idx < intval; idx++)
1167 UcpHandleString(hf_ucp_parm_LST);
1169 UcpHandleInt(hf_ucp_parm_EC);
1170 UcpHandleString(hf_ucp_parm_SM);
1174 add_10O(proto_tree *tree, tvbuff_t *tvb)
1175 { /* Change standard text */
1178 UcpHandleString(hf_ucp_parm_AdC);
1179 UcpHandleString(hf_ucp_parm_AC);
1180 UcpHandleString(hf_ucp_parm_LNo);
1181 UcpHandleString(hf_ucp_parm_TNo);
1182 UcpHandleData(hf_ucp_parm_STx);
1183 UcpHandleInt(hf_ucp_parm_CS);
1186 #define add_10R(a, b) add_01R(a, b)
1188 #define add_11O(a, b) add_06O(a, b) /* Request roaming info */
1191 add_11R(proto_tree *tree, tvbuff_t *tvb)
1197 intval = UcpHandleByte(hf_ucp_parm_ACK);
1198 if (intval == 'A') {
1199 intval = UcpHandleInt(hf_ucp_parm_NPL);
1200 for (idx = 0; idx < intval; idx++)
1201 UcpHandleString(hf_ucp_parm_GA);
1203 UcpHandleInt(hf_ucp_parm_EC);
1204 UcpHandleString(hf_ucp_parm_SM);
1208 add_12O(proto_tree *tree, tvbuff_t *tvb)
1209 { /* Change roaming */
1214 UcpHandleString(hf_ucp_parm_AdC);
1215 UcpHandleString(hf_ucp_parm_AC);
1216 intval = UcpHandleInt(hf_ucp_parm_NPL);
1217 for (idx = 0; idx < intval; idx++)
1218 UcpHandleString(hf_ucp_parm_GA);
1221 #define add_12R(a, b) add_01R(a, b)
1223 #define add_13O(a, b) add_06O(a, b) /* Roaming reset */
1225 #define add_13R(a, b) add_01R(a, b)
1228 add_14O(proto_tree *tree, tvbuff_t *tvb)
1229 { /* Message retrieval */
1232 UcpHandleString(hf_ucp_parm_AdC);
1233 UcpHandleString(hf_ucp_parm_AC);
1234 UcpHandleString(hf_ucp_parm_MNo);
1235 UcpHandleByte(hf_ucp_parm_R_T);
1239 add_14R(proto_tree *tree, tvbuff_t *tvb)
1245 intval = UcpHandleByte(hf_ucp_parm_ACK);
1246 if (intval == 'A') {
1247 intval = UcpHandleInt(hf_ucp_parm_NPL);
1249 * Spec is unclear here. Is 'SM' part of the Msg:s field or not?
1250 * For now, assume it is part of it...
1252 for (idx = 0; idx < intval; idx++)
1253 UcpHandleData(hf_ucp_data_section);
1255 UcpHandleInt(hf_ucp_parm_EC);
1256 UcpHandleString(hf_ucp_parm_SM);
1261 add_15O(proto_tree *tree, tvbuff_t *tvb)
1262 { /* Request call barring */
1265 UcpHandleString(hf_ucp_parm_AdC);
1266 UcpHandleString(hf_ucp_parm_AC);
1267 UcpHandleTime(hf_ucp_parm_ST);
1268 UcpHandleTime(hf_ucp_parm_SP);
1271 #define add_15R(a, b) add_01R(a, b)
1273 #define add_16O(a, b) add_06O(a, b) /* Cancel call barring */
1275 #define add_16R(a, b) add_01R(a, b)
1278 add_17O(proto_tree *tree, tvbuff_t *tvb)
1279 { /* Request call diversion */
1282 UcpHandleString(hf_ucp_parm_AdC);
1283 UcpHandleString(hf_ucp_parm_AC);
1284 UcpHandleString(hf_ucp_parm_DAdC);
1285 UcpHandleTime(hf_ucp_parm_ST);
1286 UcpHandleTime(hf_ucp_parm_SP);
1289 #define add_17R(a, b) add_01R(a, b)
1291 #define add_18O(a, b) add_06O(a, b) /* Cancel call diversion */
1293 #define add_18R(a, b) add_01R(a, b)
1296 add_19O(proto_tree *tree, tvbuff_t *tvb)
1297 { /* Request deferred delivery*/
1300 UcpHandleString(hf_ucp_parm_AdC);
1301 UcpHandleString(hf_ucp_parm_AC);
1302 UcpHandleTime(hf_ucp_parm_ST);
1303 UcpHandleTime(hf_ucp_parm_SP);
1306 #define add_19R(a, b) add_01R(a, b)
1308 #define add_20O(a, b) add_06O(a, b) /* Cancel deferred delivery */
1310 #define add_20R(a, b) add_01R(a, b)
1312 #define add_21O(a, b) add_06O(a, b) /* All features reset */
1314 #define add_21R(a, b) add_01R(a, b)
1317 add_22O(proto_tree *tree, tvbuff_t *tvb)
1318 { /* Call input w. add. CS */
1321 UcpHandleString(hf_ucp_parm_AdC);
1322 UcpHandleString(hf_ucp_parm_OAdC);
1323 UcpHandleString(hf_ucp_parm_OAC);
1324 UcpHandleData(hf_ucp_data_section);
1325 UcpHandleInt(hf_ucp_parm_CS);
1328 #define add_22R(a, b) add_01R(a, b)
1331 add_23O(proto_tree *tree, tvbuff_t *tvb)
1332 { /* UCP version status */
1335 UcpHandleString(hf_ucp_parm_IVR5x);
1336 UcpHandleByte(hf_ucp_parm_REQ_OT);
1340 add_23R(proto_tree *tree, tvbuff_t *tvb)
1346 intval = UcpHandleByte(hf_ucp_parm_ACK);
1347 if (intval == 'A') {
1348 UcpHandleByte(hf_ucp_parm_IVR5x);
1349 intval = UcpHandleInt(hf_ucp_parm_NPL);
1350 for (idx = 0; idx < intval; idx++)
1351 UcpHandleInt(hf_ucp_hdr_OT);
1353 UcpHandleInt(hf_ucp_parm_EC);
1354 UcpHandleString(hf_ucp_parm_SM);
1358 add_24O(proto_tree *tree, tvbuff_t *tvb)
1359 { /* Mobile subs. feature stat*/
1362 UcpHandleString(hf_ucp_parm_AdC);
1363 UcpHandleString(hf_ucp_parm_AC);
1364 UcpHandleByte(hf_ucp_parm_SSTAT);
1368 add_24R(proto_tree *tree, tvbuff_t *tvb)
1374 intval = UcpHandleByte(hf_ucp_parm_ACK);
1375 if (intval == 'A') {
1376 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1377 proto_tree_add_text(tree, tvb, offset - 1, 1,
1378 "GA roaming definitions");
1379 if (intval == 'N') {
1380 proto_tree_add_text(tree, tvb, offset -1, 1,
1381 "Not subscribed/not allowed");
1385 intval = UcpHandleInt(hf_ucp_parm_NPL);
1386 for (idx = 0; idx < intval; idx++)
1387 UcpHandleData(hf_ucp_data_section);
1390 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1391 proto_tree_add_text(tree, tvb, offset - 1, 1,
1392 "Call barring definitions");
1393 if (intval == 'N') {
1394 proto_tree_add_text(tree, tvb, offset -1, 1,
1395 "Not subscribed/not allowed");
1399 intval = UcpHandleInt(hf_ucp_parm_NPL);
1400 for (idx = 0; idx < intval; idx++)
1401 UcpHandleData(hf_ucp_data_section);
1404 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1405 proto_tree_add_text(tree, tvb, offset - 1, 1,
1406 "Deferred delivery definitions");
1407 if (intval == 'N') {
1408 proto_tree_add_text(tree, tvb, offset -1, 1,
1409 "Not subscribed/not allowed");
1413 intval = UcpHandleInt(hf_ucp_parm_NPL);
1414 for (idx = 0; idx < intval; idx++)
1415 UcpHandleData(hf_ucp_data_section);
1418 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1419 proto_tree_add_text(tree, tvb, offset - 1, 1,
1420 "Diversion definitions");
1421 if (intval == 'N') {
1422 proto_tree_add_text(tree, tvb, offset -1, 1,
1423 "Not subscribed/not allowed");
1427 intval = UcpHandleInt(hf_ucp_parm_NPL);
1428 for (idx = 0; idx < intval; idx++)
1429 UcpHandleData(hf_ucp_data_section);
1432 UcpHandleInt(hf_ucp_parm_LMN);
1433 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1434 if (intval == 'N') {
1435 proto_tree_add_string(tree, hf_ucp_parm_NMESS_str, tvb,
1436 offset -1, 1, "Not subscribed/not allowed");
1440 intval = UcpHandleInt(hf_ucp_parm_NMESS);
1444 UcpHandleInt(hf_ucp_parm_EC);
1445 UcpHandleString(hf_ucp_parm_SM);
1449 add_30O(proto_tree *tree, tvbuff_t *tvb)
1450 { /* SMS message transfer */
1453 UcpHandleString(hf_ucp_parm_AdC);
1454 UcpHandleString(hf_ucp_parm_OAdC);
1455 UcpHandleString(hf_ucp_parm_AC);
1456 UcpHandleByte(hf_ucp_parm_NRq);
1457 UcpHandleString(hf_ucp_parm_NAdC);
1458 UcpHandleInt(hf_ucp_parm_NPID);
1459 UcpHandleByte(hf_ucp_parm_DD);
1460 UcpHandleTime(hf_ucp_parm_DDT);
1461 UcpHandleTime(hf_ucp_parm_VP);
1462 UcpHandleData(hf_ucp_data_section);
1466 add_30R(proto_tree *tree, tvbuff_t *tvb)
1471 intval = UcpHandleByte(hf_ucp_parm_ACK);
1473 UcpHandleTime(hf_ucp_parm_MVP);
1475 UcpHandleInt(hf_ucp_parm_EC);
1476 UcpHandleString(hf_ucp_parm_SM);
1480 add_31O(proto_tree *tree, tvbuff_t *tvb)
1484 UcpHandleString(hf_ucp_parm_AdC);
1485 UcpHandleInt(hf_ucp_parm_PID);
1488 #define add_31R(a, b) add_01R(a, b)
1491 add_5xO(proto_tree *tree, tvbuff_t *tvb)
1492 { /* 50-series operations */
1499 UcpHandleString(hf_ucp_parm_AdC);
1500 UcpHandleString(hf_ucp_parm_OAdC);
1501 UcpHandleString(hf_ucp_parm_AC);
1502 UcpHandleByte(hf_ucp_parm_NRq);
1503 UcpHandleString(hf_ucp_parm_NAdC);
1504 UcpHandleByte(hf_ucp_parm_NT);
1505 UcpHandleInt(hf_ucp_parm_NPID);
1506 UcpHandleByte(hf_ucp_parm_LRq);
1507 UcpHandleString(hf_ucp_parm_LRAd);
1508 UcpHandleInt(hf_ucp_parm_LPID);
1509 UcpHandleByte(hf_ucp_parm_DD);
1510 UcpHandleTime(hf_ucp_parm_DDT);
1511 UcpHandleTime(hf_ucp_parm_VP);
1512 UcpHandleString(hf_ucp_parm_RPID);
1513 UcpHandleTime(hf_ucp_parm_SCTS);
1514 UcpHandleByte(hf_ucp_parm_Dst);
1515 UcpHandleInt(hf_ucp_parm_Rsn);
1516 UcpHandleTime(hf_ucp_parm_DSCTS);
1517 intval = UcpHandleByte(hf_ucp_parm_MT);
1518 UcpHandleString(hf_ucp_parm_NB);
1520 UcpHandleData(hf_ucp_data_section);
1522 UcpHandleIRAString(hf_ucp_parm_AMsg);
1523 UcpHandleByte(hf_ucp_parm_MMS);
1524 UcpHandleByte(hf_ucp_parm_PR);
1525 UcpHandleByte(hf_ucp_parm_DCs);
1526 UcpHandleByte(hf_ucp_parm_MCLs);
1527 UcpHandleByte(hf_ucp_parm_RPI);
1528 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1529 proto_tree_add_string(tree, hf_ucp_parm_CPg, tvb, offset - 1,1,
1530 "(reserved for Code Page)");
1533 if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
1534 proto_tree_add_string(tree, hf_ucp_parm_RPLy, tvb, offset - 1,1,
1535 "(reserved for Reply type)");
1538 UcpHandleString(hf_ucp_parm_OTOA);
1539 UcpHandleString(hf_ucp_parm_HPLMN);
1540 tmpoff = offset; /* Extra services */
1541 while (tvb_get_guint8(tvb, tmpoff++) != '/')
1543 if ((tmpoff - offset) > 1) {
1544 int len = tmpoff - offset - 1;
1546 ti = proto_tree_add_item(tree, hf_ucp_parm_XSer,tvb,offset,len,FALSE);
1547 tmptvb = tvb_new_subset(tvb, offset, len + 1, len + 1);
1548 proto_item_add_subtree(ti, ett_XSer);
1549 ucp_handle_XSer(ti, tmptvb);
1552 UcpHandleData(hf_ucp_parm_RES4);
1553 UcpHandleData(hf_ucp_parm_RES5);
1556 #define add_5xR(a, b) add_30R(a, b)
1559 add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
1560 { /* 60-series operations */
1563 UcpHandleString(hf_ucp_parm_OAdC);
1564 UcpHandleByte(hf_ucp_parm_OTON);
1565 UcpHandleByte(hf_ucp_parm_ONPI);
1567 UcpHandleByte(hf_ucp_parm_STYP0);
1569 UcpHandleByte(hf_ucp_parm_STYP1);
1571 UcpHandleIRAString(hf_ucp_parm_PWD);
1572 UcpHandleIRAString(hf_ucp_parm_NPWD);
1573 UcpHandleString(hf_ucp_parm_VERS);
1574 UcpHandleString(hf_ucp_parm_LAdC);
1575 UcpHandleByte(hf_ucp_parm_LTON);
1576 UcpHandleByte(hf_ucp_parm_LNPI);
1577 UcpHandleInt(hf_ucp_parm_OPID);
1578 UcpHandleData(hf_ucp_parm_RES1);
1579 UcpHandleData(hf_ucp_parm_RES2);
1582 #define add_6xR(a, b) add_01R(a, b)
1585 * End of convenient shorthands
1587 #undef UcpHandleString
1588 #undef UcpHandleIRAString
1589 #undef UcpHandleByte
1591 #undef UcpHandleTime
1592 #undef UcpHandleData
1594 /* Code to actually dissect the packets */
1596 * Overlapping data for these functions
1598 static int result, endpkt;
1601 * The heuristic dissector
1604 dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1606 guint8 O_R; /* Request or response */
1608 /* This runs atop TCP, so we are guaranteed that there is at least one
1609 byte in the tvbuff. */
1610 if (tvb_get_guint8(tvb, 0) != UCP_STX)
1613 result = check_ucp(tvb, &endpkt);
1615 if (result == UCP_MALFORMED)
1617 if (endpkt < UCP_OT_OFFSET + 1)
1619 * Might be shortened packet but don't handle anyway.
1624 * Try getting the operation-type and whether it's a request/response
1626 O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
1627 if (match_strval(O_R, vals_hdr_O_R) == NULL)
1630 * Ok, looks like a valid packet, go dissect.
1632 dissect_ucp(tvb, pinfo, tree);
1637 * The actual dissector
1640 dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1642 int offset = 0; /* Offset in packet within tvbuff */
1643 int tmpoff; /* Local offset value (per field) */
1644 guint8 O_R; /* Request or response */
1645 guint8 OT; /* Operation type */
1649 /* Set up structures needed to add the protocol subtree and manage it */
1652 proto_tree *ucp_tree;
1653 proto_tree *sub_tree;
1656 O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
1658 * So do an atoi() on the operation type
1660 OT = tvb_get_guint8(tvb, UCP_OT_OFFSET) - '0';
1661 OT = 10 * OT + (tvb_get_guint8(tvb, UCP_OT_OFFSET + 1) - '0');
1663 /* Make entries in Protocol column and Info column on summary display */
1664 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1665 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
1667 if (check_col(pinfo->cinfo, COL_INFO)) {
1668 col_clear(pinfo->cinfo, COL_INFO);
1669 col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
1670 val_to_str(OT, vals_hdr_OT, "unknown operation"),
1671 match_strval(O_R, vals_hdr_O_R));
1672 if (result == UCP_SHORTENED)
1673 col_append_str(pinfo->cinfo, COL_INFO, " [short packet]");
1674 else if (result == UCP_INV_CHK)
1675 col_append_str(pinfo->cinfo, COL_INFO, " [checksum invalid]");
1678 /* In the interest of speed, if "tree" is NULL, don't do any work not
1679 necessary to generate protocol tree items. */
1682 /* create display subtree for the protocol */
1683 ti = proto_tree_add_item(tree, proto_ucp, tvb, 0, -1, FALSE);
1685 ucp_tree = proto_item_add_subtree(ti, ett_ucp);
1687 * Process the packet here.
1688 * Transaction number
1690 offset++; /* Skip <stx> */
1692 intval = tvb_get_guint8(tvb, tmpoff++) - '0';
1693 intval = 10 * intval + (tvb_get_guint8(tvb, tmpoff++) - '0');
1694 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_TRN, tvb, offset,
1695 UCP_TRN_LEN, intval);
1698 offset++; /* Skip '/' */
1701 for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
1702 intval = 10 * intval +
1703 (tvb_get_guint8(tvb, tmpoff++) - '0');
1705 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_LEN, tvb, offset,
1706 UCP_LEN_LEN, intval);
1709 offset++; /* Operation/Response */
1710 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_O_R, tvb, offset++,
1713 offset++; /* Operation type */
1714 proto_tree_add_uint(ucp_tree, hf_ucp_hdr_OT, tvb, offset,
1716 offset += UCP_OT_LEN;
1718 * Variable part starts here. Don't dissect if not complete.
1720 if (result == UCP_SHORTENED)
1722 tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
1723 sub_ti = proto_tree_add_item(ucp_tree, hf_ucp_oper_section, tvb,
1724 offset, endpkt - offset, FALSE);
1725 sub_tree = proto_item_add_subtree(sub_ti, ett_sub);
1729 O_R == 'O' ? add_00O(sub_tree,tmp_tvb) : add_00R(sub_tree,tmp_tvb);
1732 O_R == 'O' ? add_01O(sub_tree,tmp_tvb) : add_01R(sub_tree,tmp_tvb);
1735 O_R == 'O' ? add_02O(sub_tree,tmp_tvb) : add_02R(sub_tree,tmp_tvb);
1738 O_R == 'O' ? add_03O(sub_tree,tmp_tvb) : add_03R(sub_tree,tmp_tvb);
1741 O_R == 'O' ? add_04O(sub_tree,tmp_tvb) : add_04R(sub_tree,tmp_tvb);
1744 O_R == 'O' ? add_05O(sub_tree,tmp_tvb) : add_05R(sub_tree,tmp_tvb);
1747 O_R == 'O' ? add_06O(sub_tree,tmp_tvb) : add_06R(sub_tree,tmp_tvb);
1750 O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree,tmp_tvb);
1753 O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree,tmp_tvb);
1756 O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree,tmp_tvb);
1759 O_R == 'O' ? add_10O(sub_tree,tmp_tvb) : add_10R(sub_tree,tmp_tvb);
1762 O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree,tmp_tvb);
1765 O_R == 'O' ? add_12O(sub_tree,tmp_tvb) : add_12R(sub_tree,tmp_tvb);
1768 O_R == 'O' ? add_13O(sub_tree,tmp_tvb) : add_13R(sub_tree,tmp_tvb);
1771 O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree,tmp_tvb);
1774 O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree,tmp_tvb);
1777 O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree,tmp_tvb);
1780 O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree,tmp_tvb);
1783 O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree,tmp_tvb);
1786 O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree,tmp_tvb);
1789 O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree,tmp_tvb);
1792 O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree,tmp_tvb);
1795 O_R == 'O' ? add_22O(sub_tree,tmp_tvb) : add_22R(sub_tree,tmp_tvb);
1798 O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree,tmp_tvb);
1801 O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree,tmp_tvb);
1804 O_R == 'O' ? add_30O(sub_tree,tmp_tvb) : add_30R(sub_tree,tmp_tvb);
1807 O_R == 'O' ? add_31O(sub_tree,tmp_tvb) : add_31R(sub_tree,tmp_tvb);
1809 case 51: case 52: case 53: case 54: case 55: case 56: case 57:
1811 O_R == 'O' ? add_5xO(sub_tree,tmp_tvb) : add_5xR(sub_tree,tmp_tvb);
1814 O_R == 'O' ? add_6xO(sub_tree,tmp_tvb,OT) : add_6xR(sub_tree,tmp_tvb);
1823 /* Register the protocol with Ethereal */
1825 proto_register_ucp(void)
1828 /* Setup list of fields */
1829 static hf_register_info hf[] = {
1831 { "Transaction Reference Number", "ucp.hdr.TRN",
1832 FT_UINT8, BASE_DEC, NULL, 0x00,
1833 "Transaction number for this command, used in windowing.",
1838 { "Length", "ucp.hdr.LEN",
1839 FT_UINT16, BASE_DEC, NULL, 0x00,
1840 "Total number of characters between <stx>...<etx>.",
1845 { "Type", "ucp.hdr.O_R",
1846 FT_UINT8, BASE_DEC, VALS(vals_hdr_O_R), 0x00,
1847 "Your basic 'is a request or response'.",
1852 { "Operation", "ucp.hdr.OT",
1853 FT_UINT8, BASE_DEC, VALS(vals_hdr_OT), 0x00,
1854 "The operation that is requested with this message.",
1858 { &hf_ucp_oper_section,
1859 { "Data", "ucp.parm",
1860 FT_NONE, BASE_DEC, NULL, 0x00,
1861 "The actual content of the operation.",
1866 { "AdC", "ucp.parm.AdC",
1867 FT_STRING, BASE_NONE, NULL, 0x00,
1868 "Address code recipient.",
1872 { &hf_ucp_parm_OAdC,
1873 { "OAdC", "ucp.parm.OAdC",
1874 FT_STRING, BASE_NONE, NULL, 0x00,
1875 "Address code originator.",
1879 { &hf_ucp_parm_DAdC,
1880 { "DAdC", "ucp.parm.DAdC",
1881 FT_STRING, BASE_NONE, NULL, 0x00,
1882 "Diverted address code.",
1887 { "AC", "ucp.parm.AC",
1888 FT_STRING, BASE_NONE, NULL, 0x00,
1889 "Authentication code.",
1894 { "OAC", "ucp.parm.OAC",
1895 FT_STRING, BASE_NONE, NULL, 0x00,
1896 "Authentication code, originator.",
1901 { "NAC", "ucp.parm.NAC",
1902 FT_STRING, BASE_NONE, NULL, 0x00,
1903 "New authentication code.",
1908 { "BAS", "ucp.parm.BAS",
1909 FT_UINT8, BASE_DEC, VALS(vals_parm_BAS), 0x00,
1910 "Barring status flag.",
1915 { "LAR", "ucp.parm.LAR",
1916 FT_UINT8, BASE_DEC, VALS(vals_parm_LAR), 0x00,
1917 "Leg. code for all calls flag.",
1922 { "LAC", "ucp.parm.LAC",
1923 FT_STRING, BASE_NONE, NULL, 0x00,
1924 "New leg. code for all calls.",
1929 { "L1R", "ucp.parm.L1R",
1930 FT_UINT8, BASE_DEC, VALS(vals_parm_L1R), 0x00,
1931 "Leg. code for priority 1 flag.",
1936 { "L1P", "ucp.parm.L1P",
1937 FT_STRING, BASE_NONE, NULL, 0x00,
1938 "New leg. code for level 1 priority.",
1943 { "L3R", "ucp.parm.L3R",
1944 FT_UINT8, BASE_DEC, VALS(vals_parm_L3R), 0x00,
1945 "Leg. code for priority 3 flag.",
1950 { "L3P", "ucp.parm.L3P",
1951 FT_STRING, BASE_NONE, NULL, 0x00,
1952 "New leg. code for level 3 priority.",
1957 { "LCR", "ucp.parm.LCR",
1958 FT_UINT8, BASE_DEC, VALS(vals_parm_LCR), 0x00,
1959 "Leg. code for reverse charging flag.",
1964 { "LUR", "ucp.parm.LUR",
1965 FT_UINT8, BASE_DEC, VALS(vals_parm_LUR), 0x00,
1966 "Leg. code for urgent message flag.",
1971 { "LRR", "ucp.parm.LRR",
1972 FT_UINT8, BASE_DEC, VALS(vals_parm_LRR), 0x00,
1973 "Leg. code for repitition flag.",
1978 { "RT", "ucp.parm.RT",
1979 FT_UINT8, BASE_DEC, VALS(vals_parm_RT), 0x00,
1985 { "NoN", "ucp.parm.NoN",
1986 FT_UINT16, BASE_DEC, NULL, 0x00,
1987 "Maximum number of numerical characters accepted.",
1992 { "NoA", "ucp.parm.NoA",
1993 FT_UINT16, BASE_DEC, NULL, 0x00,
1994 "Maximum number of alphanumerical characters accepted.",
1999 { "NoB", "ucp.parm.NoB",
2000 FT_UINT16, BASE_DEC, NULL, 0x00,
2001 "Maximum number of data bits accepted.",
2006 { "PNC", "ucp.parm.PNC",
2007 FT_UINT8, BASE_DEC, VALS(vals_parm_PNC), 0x00,
2008 "Paging network controller.",
2012 { &hf_ucp_parm_AMsg,
2013 { "AMsg", "ucp.parm.AMsg",
2014 FT_STRING, BASE_NONE, NULL, 0x00,
2015 "The alphanumeric message that is being sent.",
2020 { "LNo", "ucp.parm.LNo",
2021 FT_STRING, BASE_NONE, NULL, 0x00,
2022 "Standard text list number requested by calling party.",
2027 { "LST", "ucp.parm.LST",
2028 FT_STRING, BASE_NONE, NULL, 0x00,
2029 "Legitimisation code for standard text.",
2034 { "TNo", "ucp.parm.TNo",
2035 FT_STRING, BASE_NONE, NULL, 0x00,
2036 "Standard text number requested by calling party.",
2041 { "CS", "ucp.parm.CS",
2042 FT_UINT8, BASE_DEC, NULL, 0x00,
2043 "Additional character set number.",
2048 { "PID", "ucp.parm.PID",
2049 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2055 { "NPL", "ucp.parm.NPL",
2056 FT_UINT16, BASE_DEC, NULL, 0x00,
2057 "Number of parameters in the following list.",
2062 { "GA", "ucp.parm.GA",
2063 FT_STRING, BASE_NONE, NULL, 0x00,
2064 "GA?? haven't got a clue.",
2069 { "RP", "ucp.parm.RP",
2070 FT_UINT8, BASE_DEC, VALS(vals_parm_RP), 0x00,
2071 "Repitition requested.",
2076 { "LRP", "ucp.parm.LRP",
2077 FT_STRING, BASE_DEC, NULL, 0x00,
2078 "Legitimisation code for repitition.",
2083 { "PR", "ucp.parm.PR",
2084 FT_UINT8, BASE_DEC, NULL, 0x00,
2085 "Priority requested.",
2090 { "LPR", "ucp.parm.LPR",
2091 FT_STRING, BASE_DEC, NULL, 0x00,
2092 "Legitimisation code for priority requested.",
2097 { "UM", "ucp.parm.UM",
2098 FT_UINT8, BASE_DEC, VALS(vals_parm_UM), 0x00,
2099 "Urgent message indicator.",
2104 { "LUM", "ucp.parm.LUM",
2105 FT_STRING, BASE_DEC, NULL, 0x00,
2106 "Legitimisation code for urgent message.",
2111 { "RC", "ucp.parm.RC",
2112 FT_UINT8, BASE_DEC, VALS(vals_parm_RC), 0x00,
2113 "Reverse charging request.",
2118 { "LRC", "ucp.parm.LRC",
2119 FT_STRING, BASE_DEC, NULL, 0x00,
2120 "Legitimisation code for reverse charging.",
2125 { "NRq", "ucp.parm.NRq",
2126 FT_UINT8, BASE_DEC, VALS(vals_parm_NRq), 0x00,
2127 "Notification request.",
2131 { &hf_ucp_parm_GAdC,
2132 { "GAdC", "ucp.parm.GAdC",
2133 FT_STRING, BASE_NONE, NULL, 0x00,
2134 "Group address code.",
2139 { "A_D", "ucp.parm.A_D",
2140 FT_UINT8, BASE_DEC, VALS(vals_parm_A_D), 0x00,
2141 "Add to/delete from fixed subscriber address list record.",
2146 { "CT", "ucp.parm.CT",
2147 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2148 "Accumulated charges timestamp.",
2153 { "AAC", "ucp.parm.AAC",
2154 FT_STRING, BASE_NONE, NULL, 0x00,
2155 "Accumulated charges.",
2160 { "MNo", "ucp.parm.MNo",
2161 FT_STRING, BASE_NONE, NULL, 0x00,
2167 { "R_T", "ucp.parm.R_T",
2168 FT_UINT8, BASE_DEC, VALS(vals_parm_R_T), 0x00,
2173 { &hf_ucp_parm_NAdC,
2174 { "NAdC", "ucp.parm.NAdC",
2175 FT_STRING, BASE_NONE, NULL, 0x00,
2176 "Notification address.",
2181 { "NT", "ucp.parm.NT",
2182 FT_UINT8, BASE_DEC, VALS(vals_parm_NT), 0x00,
2183 "Notification type.",
2187 { &hf_ucp_parm_IVR5x,
2188 { "IVR5x", "ucp.parm.IVR5x",
2189 FT_STRING, BASE_NONE, NULL, 0x00,
2190 "UCP release number supported/accepted.",
2194 { &hf_ucp_parm_REQ_OT,
2195 { "REQ_OT", "ucp.parm.REQ_OT",
2196 FT_UINT8, BASE_DEC, VALS(vals_parm_REQ_OT), 0x00,
2197 "UCP release number supported/accepted.",
2201 { &hf_ucp_parm_SSTAT,
2202 { "SSTAT", "ucp.parm.SSTAT",
2203 FT_UINT8, BASE_DEC, VALS(vals_parm_SSTAT), 0x00,
2204 "Supplementary services for which status is requested.",
2209 { "LMN", "ucp.parm.LMN",
2210 FT_UINT8, BASE_DEC, NULL, 0x00,
2211 "Last message number.",
2215 { &hf_ucp_parm_NMESS,
2216 { "NMESS", "ucp.parm.NMESS",
2217 FT_UINT8, BASE_DEC, NULL, 0x00,
2218 "Number of stored messages.",
2222 { &hf_ucp_parm_NMESS_str,
2223 { "NMESS_str", "ucp.parm.NMESS_str",
2224 FT_STRING, BASE_NONE, NULL, 0x00,
2225 "Number of stored messages.",
2229 { &hf_ucp_parm_NPID,
2230 { "NPID", "ucp.parm.NPID",
2231 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2232 "Notification PID value.",
2237 { "LRq", "ucp.parm.LRq",
2238 FT_UINT8, BASE_DEC, VALS(vals_parm_LRq), 0x00,
2239 "Last resort address request.",
2243 { &hf_ucp_parm_LRAd,
2244 { "LRAd", "ucp.parm.LRAd",
2245 FT_STRING, BASE_NONE, NULL, 0x00,
2246 "Last resort address.",
2250 { &hf_ucp_parm_LPID,
2251 { "LPID", "ucp.parm.LPID",
2252 FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
2253 "Last resort PID value.",
2258 { "DD", "ucp.parm.DD",
2259 FT_UINT8, BASE_DEC, VALS(vals_parm_DD), 0x00,
2260 "Deferred delivery requested.",
2265 { "DDT", "ucp.parm.DDT",
2266 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2267 "Deferred delivery time.",
2272 { "STx", "ucp.parm.STx",
2273 FT_NONE, BASE_NONE, NULL, 0x00,
2279 { "ST", "ucp.parm.ST",
2280 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2286 { "SP", "ucp.parm.SP",
2287 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2293 { "VP", "ucp.parm.VP",
2294 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2299 { &hf_ucp_parm_RPID,
2300 { "RPID", "ucp.parm.RPID",
2301 FT_STRING, BASE_NONE, NULL, 0x00,
2306 { &hf_ucp_parm_SCTS,
2307 { "SCTS", "ucp.parm.SCTS",
2308 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2309 "Service Centre timestamp.",
2314 { "Dst", "ucp.parm.Dst",
2315 FT_UINT8, BASE_DEC, VALS(vals_parm_Dst), 0x00,
2321 { "Rsn", "ucp.parm.Rsn",
2322 FT_UINT16, BASE_DEC, VALS(vals_parm_Rsn), 0x00,
2327 { &hf_ucp_parm_DSCTS,
2328 { "DSCTS", "ucp.parm.DSCTS",
2329 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2330 "Delivery timestamp.",
2335 { "MT", "ucp.parm.MT",
2336 FT_UINT8, BASE_DEC, VALS(vals_parm_MT), 0x00,
2342 { " NB", "ucp.parm.NB",
2343 FT_STRING, BASE_NONE, NULL, 0x00,
2344 "No. of bits in Transparent Data (TD) message.",
2348 { &hf_ucp_data_section,
2349 { " Data", "ucp.message",
2350 FT_NONE, BASE_NONE, NULL, 0x00,
2351 "The actual message or data.",
2356 { "MMS", "ucp.parm.MMS",
2357 FT_UINT8, BASE_DEC, NULL, 0x00,
2358 "More messages to send.",
2363 { "DCs", "ucp.parm.DCs",
2364 FT_UINT8, BASE_DEC, VALS(vals_parm_DCs), 0x00,
2365 "Data coding scheme (deprecated).",
2369 { &hf_ucp_parm_MCLs,
2370 { "MCLs", "ucp.parm.MCLs",
2371 FT_UINT8, BASE_DEC, VALS(vals_parm_MCLs), 0x00,
2377 { "RPI", "ucp.parm.RPI",
2378 FT_UINT8, BASE_DEC, VALS(vals_parm_RPI), 0x00,
2384 { "CPg", "ucp.parm.CPg",
2385 FT_STRING, BASE_NONE, NULL, 0x00,
2386 "Reserved for Code Page.",
2390 { &hf_ucp_parm_RPLy,
2391 { "RPLy", "ucp.parm.RPLy",
2392 FT_STRING, BASE_NONE, NULL, 0x00,
2393 "Reserved for Reply type.",
2397 { &hf_ucp_parm_OTOA,
2398 { "OTOA", "ucp.parm.OTOA",
2399 FT_STRING, BASE_NONE, NULL, 0x00,
2400 "Originator Type Of Address.",
2404 { &hf_ucp_parm_HPLMN,
2405 { "HPLMN", "ucp.parm.HPLMN",
2406 FT_STRING, BASE_NONE, NULL, 0x00,
2407 "Home PLMN address.",
2411 { &hf_ucp_parm_XSer,
2412 { "Extra services:", "ucp.parm.XSer",
2413 FT_NONE, BASE_DEC, NULL, 0x00,
2418 { &hf_ucp_parm_RES4,
2419 { "RES4", "ucp.parm.RES4",
2420 FT_STRING, BASE_NONE, NULL, 0x00,
2421 "Reserved for future use.",
2425 { &hf_ucp_parm_RES5,
2426 { "RES5", "ucp.parm.RES5",
2427 FT_STRING, BASE_NONE, NULL, 0x00,
2428 "Reserved for future use.",
2432 { &hf_ucp_parm_OTON,
2433 { "OTON", "ucp.parm.OTON",
2434 FT_UINT8, BASE_DEC, VALS(vals_parm_OTON), 0x00,
2435 "Originator type of number.",
2439 { &hf_ucp_parm_ONPI,
2440 { "ONPI", "ucp.parm.ONPI",
2441 FT_UINT8, BASE_DEC, VALS(vals_parm_ONPI), 0x00,
2442 "Originator numbering plan id.",
2446 { &hf_ucp_parm_STYP0,
2447 { "STYP0", "ucp.parm.STYP0",
2448 FT_UINT8, BASE_DEC, VALS(vals_parm_STYP0), 0x00,
2449 "Subtype of operation.",
2453 { &hf_ucp_parm_STYP1,
2454 { "STYP1", "ucp.parm.STYP1",
2455 FT_UINT8, BASE_DEC, VALS(vals_parm_STYP1), 0x00,
2456 "Subtype of operation.",
2461 { "PWD", "ucp.parm.PWD",
2462 FT_STRING, BASE_NONE, NULL, 0x00,
2463 "Current password.",
2467 { &hf_ucp_parm_NPWD,
2468 { "NPWD", "ucp.parm.NPWD",
2469 FT_STRING, BASE_NONE, NULL, 0x00,
2474 { &hf_ucp_parm_VERS,
2475 { "VERS", "ucp.parm.VERS",
2476 FT_STRING, BASE_NONE, NULL, 0x00,
2481 { &hf_ucp_parm_LAdC,
2482 { "LAdC", "ucp.parm.LAdC",
2483 FT_STRING, BASE_NONE, NULL, 0x00,
2484 "Address for VSMSC list operation.",
2488 { &hf_ucp_parm_LTON,
2489 { "LTON", "ucp.parm.LTON",
2490 FT_UINT8, BASE_DEC, NULL, 0x00,
2491 "Type of number list address.",
2495 { &hf_ucp_parm_LNPI,
2496 { "LNPI", "ucp.parm.LNPI",
2497 FT_UINT8, BASE_DEC, NULL, 0x00,
2498 "Numbering plan id. list address.",
2502 { &hf_ucp_parm_OPID,
2503 { "OPID", "ucp.parm.OPID",
2504 FT_UINT8, BASE_DEC, VALS(vals_parm_OPID), 0x00,
2505 "Originator protocol identifier.",
2509 { &hf_ucp_parm_RES1,
2510 { "RES1", "ucp.parm.RES1",
2511 FT_STRING, BASE_NONE, NULL, 0x00,
2512 "Reserved for future use.",
2516 { &hf_ucp_parm_RES2,
2517 { "RES2", "ucp.parm.RES2",
2518 FT_STRING, BASE_NONE, NULL, 0x00,
2519 "Reserved for future use.",
2524 { "(N)Ack", "ucp.parm.ACK",
2525 FT_UINT8, BASE_DEC, VALS(vals_parm_ACK), 0x00,
2526 "Positive or negative acknowledge of the operation.",
2531 { "MVP", "ucp.parm.MVP",
2532 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2533 "Mofified validity period.",
2538 { "Error code", "ucp.parm.EC",
2539 FT_UINT8, BASE_DEC, VALS(vals_parm_EC), 0x00,
2540 "The result of the requested operation.",
2545 { "SM", "ucp.parm.SM",
2546 FT_STRING, BASE_NONE, NULL, 0x00,
2552 { "Type of service", "ucp.xser.service",
2553 FT_UINT8, BASE_HEX, VALS(vals_xser_service), 0x00,
2554 "The type of service specified.",
2559 /* Setup protocol subtree array */
2560 static gint *ett[] = {
2565 /* Register the protocol name and description */
2566 proto_ucp = proto_register_protocol("Universal Computer Protocol",
2569 /* Required function calls to register header fields and subtrees used */
2570 proto_register_field_array(proto_ucp, hf, array_length(hf));
2571 proto_register_subtree_array(ett, array_length(ett));
2575 * If dissector uses sub-dissector registration add a registration routine.
2576 * This format is required because a script is used to find these routines and
2577 * create the code that calls these routines.
2580 proto_reg_handoff_ucp(void)
2582 dissector_handle_t ucp_handle;
2585 * UCP can be spoken on any port so, when not on a specific port, try this
2586 * one whenever TCP is spoken.
2588 heur_dissector_add("tcp", dissect_ucp_heur, proto_ucp);
2591 * Also register as one that can be selected by a TCP port number.
2593 ucp_handle = create_dissector_handle(dissect_ucp, proto_ucp);
2594 dissector_add_handle("tcp.port", ucp_handle);