Don't do fcn calls in arg of g_?to??(); Macro may very well eval args multiple times.
[obnox/wireshark/wip.git] / epan / dissectors / packet-ansi_637.c
1 /* packet-ansi_637.c
2  * Routines for ANSI IS-637-A (SMS) dissection
3  *
4  * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
5  * In association with Telos Technology Inc.
6  *
7  * Title                3GPP2                   Other
8  *
9  *   Short Message Service
10  *                      3GPP2 C.S0015-0         TIA/EIA-637-A
11  *
12  * $Id$
13  *
14  * Wireshark - Network traffic analyzer
15  * By Gerald Combs <gerald@wireshark.org>
16  * Copyright 1998 Gerald Combs
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif
40
41 #ifdef HAVE_NETINET_IN_H
42 # include <netinet/in.h>
43 #endif
44
45 #include <epan/packet.h>
46 #include <epan/emem.h>
47 #include <epan/strutil.h>
48
49
50 static const char *ansi_proto_name_tele = "ANSI IS-637-A (SMS) Teleservice Layer";
51 static const char *ansi_proto_name_trans = "ANSI IS-637-A (SMS) Transport Layer";
52 static const char *ansi_proto_name_short = "IS-637-A";
53
54 static const value_string ansi_srvc_cat_strings[] = {
55     { 0x0000,   "Unknown or unspecified" },
56     { 0x0001,   "Emergency Broadcasts" },
57     { 0x0002,   "Administrative" },
58     { 0x0003,   "Maintenance" },
59     { 0x0004,   "General News - Local" },
60     { 0x0005,   "General News - Regional" },
61     { 0x0006,   "General News - National" },
62     { 0x0007,   "General News - International" },
63     { 0x0008,   "Business/Financial News - Local" },
64     { 0x0009,   "Business/Financial News - Regional" },
65     { 0x000A,   "Business/Financial News - National" },
66     { 0x000B,   "Business/Financial News - International" },
67     { 0x000C,   "Sports News - Local" },
68     { 0x000D,   "Sports News - Regional" },
69     { 0x000E,   "Sports News - National" },
70     { 0x000F,   "Sports News - International" },
71     { 0x0010,   "Entertainment News - Local" },
72     { 0x0011,   "Entertainment News - Regional" },
73     { 0x0012,   "Entertainment News - National" },
74     { 0x0013,   "Entertainment News - International" },
75     { 0x0014,   "Local Weather" },
76     { 0x0015,   "Area Traffic Reports" },
77     { 0x0016,   "Local Airport Flight Schedules" },
78     { 0x0017,   "Restaurants" },
79     { 0x0018,   "Lodgings" },
80     { 0x0019,   "Retail Directory" },
81     { 0x001A,   "Advertisements" },
82     { 0x001B,   "Stock Quotes" },
83     { 0x001C,   "Employment Opportunities" },
84     { 0x001D,   "Medical/Health/Hospitals" },
85     { 0x001E,   "Technology News" },
86     { 0x001F,   "Multi-category" },
87     { 0, NULL },
88 };
89
90 static const value_string ansi_tele_msg_type_strings[] = {
91     { 1,        "Deliver (mobile-terminated only)" },
92     { 2,        "Submit (mobile-originated only)" },
93     { 3,        "Cancellation (mobile-originated only)" },
94     { 4,        "Delivery Acknowledgement (mobile-terminated only)" },
95     { 5,        "User Acknowledgement (either direction)" },
96     { 0, NULL },
97     };
98
99 static const value_string ansi_tele_msg_status_strings[] = {
100     {0x00,"Message accepted"},
101     {0x01,"Message deposited to Internet"},
102     {0x02,"Message delivered"},
103     {0x03,"Message cancelled"},
104     {0x84,"Network congestion"},
105     {0x85,"Network error"},
106     {0x9f,"Unknown error"},
107     {0xc4,"Network congestion"},
108     {0xc5,"Network error"},
109     {0xc6,"Cancel failed"},
110     {0xc7,"Blocked destination"},
111     {0xc8,"Text too long"},
112     {0xc9,"Duplicate message"},
113     {0xca,"Invalid destination"},
114     {0xcd,"Message expired"},
115     {0xdf,"Unknown error"},
116     { 0, NULL }
117 };
118
119 static const value_string ansi_tele_id_strings[] = {
120     { 1,        "Reserved for maintenance" },
121     { 4096,     "AMPS Extended Protocol Enhanced Services" },
122     { 4097,     "CDMA Cellular Paging Teleservice" },
123     { 4098,     "CDMA Cellular Messaging Teleservice" },
124     { 4099,     "CDMA Voice Mail Notification" },
125     { 4100,     "CDMA Wireless Application Protocol (WAP)" },
126     { 4101,     "CDMA Wireless Enhanced Messaging Teleservice (WEMT)" },
127     { 65535,    "(Reserved) Being used for Broadcast" },
128     { 0, NULL },
129
130 };
131
132 static const value_string ansi_tele_param_strings[] = {
133     { 0x00,     "Message Identifier" },
134     { 0x01,     "User Data" },
135     { 0x02,     "User Response Code" },
136     { 0x03,     "Message Center Time Stamp" },
137     { 0x04,     "Validity Period - Absolute" },
138     { 0x05,     "Validity Period - Relative" },
139     { 0x06,     "Deferred Delivery Time - Absolute" },
140     { 0x07,     "Deferred Delivery Time - Relative" },
141     { 0x08,     "Priority Indicator" },
142     { 0x09,     "Privacy Indicator" },
143     { 0x0a,     "Reply Option" },
144     { 0x0b,     "Number of Messages" },
145     { 0x0c,     "Alert on Message Delivery" },
146     { 0x0d,     "Language Indicator" },
147     { 0x0e,     "Call-Back Number" },
148     { 0x0f,     "Message Display Mode" },
149     { 0x10,     "Multiple Encoding User Data" },
150     { 0x14,     "Message Status" },
151     { 0, NULL },
152 };
153
154 #define ANSI_TRANS_MSG_TYPE_BROADCAST   1
155
156 static const value_string ansi_trans_msg_type_strings[] = {
157     { 0,        "Point-to-Point" },
158     { 1,        "Broadcast" },
159     { 2,        "Acknowledge" },
160     { 0, NULL },
161 };
162
163 static const value_string ansi_trans_param_strings[] = {
164     { 0x00,     "Teleservice Identifier" },
165     { 0x01,     "Service Category" },
166     { 0x02,     "Originating Address" },
167     { 0x03,     "Originating Subaddress" },
168     { 0x04,     "Destination Address" },
169     { 0x05,     "Destination Subaddress" },
170     { 0x06,     "Bearer Reply Option" },
171     { 0x07,     "Cause Codes" },
172     { 0x08,     "Bearer Data" },
173     { 0, NULL },
174 };
175
176 /*
177  * from Table 2.7.1.3.2.4-4. Representation of DTMF Digits
178  * 3GPP2 C.S0005-C (IS-2000 aka cdma2000)
179  */
180 static unsigned char air_digits[] = {
181   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
182      '?','1','2','3','4','5','6','7','8','9','0','*','#','?','?'
183 };
184
185 /* Initialize the protocol and registered fields */
186 static int proto_ansi_637_tele = -1;
187 static int proto_ansi_637_trans = -1;
188 static int hf_ansi_637_tele_length = -1;
189 static int hf_ansi_637_trans_length = -1;
190 static int hf_ansi_637_trans_bin_addr = -1;
191 static int hf_ansi_637_tele_msg_type = -1;
192 static int hf_ansi_637_tele_msg_id = -1;
193 static int hf_ansi_637_tele_msg_status = -1;
194 static int hf_ansi_637_tele_msg_rsvd = -1;
195 static int hf_ansi_637_tele_subparam_id = -1;
196 static int hf_ansi_637_trans_msg_type = -1;
197 static int hf_ansi_637_trans_param_id = -1;
198
199 /* Initialize the subtree pointers */
200 static gint ett_ansi_637_tele = -1;
201 static gint ett_ansi_637_trans = -1;
202 static gint ett_params = -1;
203
204 static guint32 ansi_637_trans_tele_id;
205 static char ansi_637_bigbuf[1024];
206 static char gsm_637_bigbuf[1024];
207 static char ia5_637_bigbuf[1024];
208 /* static dissector_handle_t data_handle; */
209 static dissector_table_t tele_dissector_table;
210 static packet_info *g_pinfo;
211 static proto_tree *g_tree;
212
213 /* FUNCTIONS */
214 #define GN_CHAR_ALPHABET_SIZE 128
215
216 #define GN_CHAR_ESCAPE 0x1b
217
218 static gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
219
220     /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
221     /* Fixed to use unicode */
222     /* Characters in hex position 10, [12 to 1a] and 24 are not present on
223        latin1 charset, so we cannot reproduce on the screen, however they are
224        greek symbol not present even on my Nokia */
225
226     '@',  0xa3, '$' , 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
227     0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
228    0x394, '_', 0x3a6,0x393,0x39b,0x3a9,0x3a0,0x3a8,
229    0x3a3,0x398,0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
230     ' ',  '!',  '\"', '#',  0xa4,  '%',  '&',  '\'',
231     '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
232     '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
233     '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
234     0xa1, 'A',  'B',  'C',  'D',  'E',  'F',  'G',
235     'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
236     'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
237     'X',  'Y',  'Z',  0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
238     0xbf, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
239     'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
240     'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
241     'x',  'y',  'z',  0xe4, 0xf6, 0xf1, 0xfc, 0xe0
242 };
243
244
245
246 static gboolean
247 char_is_escape(unsigned char value)
248 {
249     return (value == GN_CHAR_ESCAPE);
250 }
251
252 static gunichar
253 char_def_alphabet_ext_decode(unsigned char value)
254 {
255     switch (value)
256     {
257     case 0x0a: return 0x0c; /* form feed */
258     case 0x14: return '^';
259     case 0x28: return '{';
260     case 0x29: return '}';
261     case 0x2f: return '\\';
262     case 0x3c: return '[';
263     case 0x3d: return '~';
264     case 0x3e: return ']';
265     case 0x40: return '|';
266     case 0x65: return 0x20ac; /* euro */
267     default: return '?'; /* invalid character */
268     }
269 }
270
271 static gunichar
272 char_def_alphabet_decode(unsigned char value)
273 {
274     if (value < GN_CHAR_ALPHABET_SIZE)
275     {
276         return gsm_default_alphabet[value];
277     }
278     else
279     {
280         return '?';
281     }
282 }
283
284 static void
285 gsm_sms_char_7bit_ascii_decode(unsigned char * dest, const unsigned char* src, int len)
286 {
287     int i, j;
288     gunichar buf;
289
290
291     for (i = 0, j = 0; j < len;  j++)
292     {
293         if (char_is_escape(src[j])) {
294             buf = char_def_alphabet_ext_decode(src[++j]);
295             i += g_unichar_to_utf8(buf,&(dest[i]));
296         }
297         else {
298             buf = char_def_alphabet_decode(src[j]);
299             i += g_unichar_to_utf8(buf,&(dest[i]));
300         }
301     }
302     dest[i]=0;
303     return;
304 }
305
306
307
308
309
310 static int
311 decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oct, guint8 *last_bit, gchar *buf)
312 {
313     guint8      oct, oct2, bit;
314     /* guint32  saved_offset; */
315     guint32     i;
316
317
318     if (num_fields == 0)
319     {
320         return 0;
321     }
322
323     /* saved_offset = *offset; */
324     oct = oct2 = *last_oct;
325     bit = *last_bit;
326
327     if (bit == 1)
328     {
329         oct2 = tvb_get_guint8(tvb, *offset);
330         (*offset)++;
331     }
332
333     for (i=0; i < num_fields; i++)
334     {
335         if (bit != 1)
336         {
337             oct = oct2;
338
339             /*
340              * cannot grab an octet if we are getting
341              * the last field and bit is 7 or 8
342              * because there may not be another octet
343              */
344             if (((i + 1) != num_fields) ||
345                 ((bit != 7) && (bit != 8)))
346             {
347                 oct2 = tvb_get_guint8(tvb, *offset);
348                 (*offset)++;
349             }
350         }
351
352         switch (bit)
353         {
354         case 1:
355             buf[i] = ((oct & 0x01) << 6) | ((oct2 & 0xfc) >> 2);
356             break;
357
358         case 2:
359             buf[i] = ((oct & 0x03) << 5) | ((oct2 & 0xf8) >> 3);
360             break;
361
362         case 3:
363             buf[i] = ((oct & 0x07) << 4) | ((oct2 & 0xf0) >> 4);
364             break;
365
366         case 4:
367             buf[i] = ((oct & 0x0f) << 3) | ((oct2 & 0xe0) >> 5);
368             break;
369
370         case 5:
371             buf[i] = ((oct & 0x1f) << 2) | ((oct2 & 0xc0) >> 6);
372             break;
373
374         case 6:
375             buf[i] = ((oct & 0x3f) << 1) | ((oct2 & 0x80) >> 7);
376             break;
377
378         case 7:
379             buf[i] = oct & 0x7f;
380             break;
381
382         case 8:
383             buf[i] = (oct & 0xfe) >> 1;
384             break;
385         }
386
387         bit = (bit % 8) + 1;
388     }
389
390     buf[i] = '\0';
391     *last_bit = bit;
392     *last_oct = (bit == 1) ? oct : oct2;
393     return i;
394 }
395
396 /* PARAM FUNCTIONS */
397
398 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
399     if ((edc_len) > (edc_max_len)) \
400     { \
401         proto_tree_add_text(tree, tvb, offset, \
402             (edc_len) - (edc_max_len), "Extraneous Data"); \
403     }
404
405 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
406     if ((sdc_len) < (sdc_min_len)) \
407     { \
408         proto_tree_add_text(tree, tvb, offset, \
409             (sdc_len), "Short Data (?)"); \
410         return; \
411     }
412
413 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
414     if ((edc_len) != (edc_eq_len)) \
415     { \
416         proto_tree_add_text(tree, tvb, offset, \
417             (edc_len), "Unexpected Data Length"); \
418         return; \
419     }
420
421 static void
422 tele_param_msg_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
423 {
424     guint32     octs;
425
426     EXACT_DATA_CHECK(len, 3);
427
428     octs = tvb_get_ntoh24(tvb, offset);
429
430     proto_tree_add_uint(tree, hf_ansi_637_tele_msg_type,
431         tvb, offset, 3, octs);
432
433     proto_tree_add_uint(tree, hf_ansi_637_tele_msg_id,
434         tvb, offset, 3, octs);
435
436     proto_tree_add_uint(tree, hf_ansi_637_tele_msg_rsvd,
437         tvb, offset, 3, octs);
438 }
439
440 /* Adamek Jan - IS637C Message status decoding procedure */
441 static void
442 tele_param_msg_status(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
443 {
444     /* Declare some variables */
445
446     guint8      oct;
447     guint8      error_class;
448     guint8      msg_status_code;
449     const gchar *str = NULL;
450
451     /* Chceck if the exact length */
452     EXACT_DATA_CHECK(len, 1);
453
454     /* get the status octet? */
455
456     oct = tvb_get_guint8(tvb, offset);
457
458
459     /* error class filter */
460     proto_tree_add_item(tree, hf_ansi_637_tele_msg_status,tvb, offset, 1, ENC_BIG_ENDIAN);
461
462     /*error class filter end */
463
464
465 /*error class */
466
467     error_class = ((oct & 0xc0) >> 6);
468     switch (error_class)
469     {
470     case 0x00: str = "No Error";break;
471     case 0x01: str = "Reserved";break;
472     case 0x02: str = "Temporary Condition";break;
473     case 0x03: str = "Permanent Condition";break;
474     default: str = "Reserved";break;
475     }
476     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
477     proto_tree_add_text(tree, tvb, offset, 1,
478                         "%s :  Erorr Class: %s",
479                         ansi_637_bigbuf,
480                         str);
481
482
483
484     msg_status_code = (oct & 0x3f);
485
486     if (error_class == 0x00){
487         switch (msg_status_code)
488         {
489         case 0x00: str = "Message accepted";break;
490         case 0x01: str = "Message deposited to internet";break;
491         case 0x02: str = "Message delivered";break;
492         case 0x03: str = "Message cancelled";break;
493         default: str = "Reserved";break;
494         }
495         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
496         proto_tree_add_text(tree, tvb, offset, 1,
497                             "%s :  Message status code: %s",
498                             ansi_637_bigbuf,
499                             str);
500     }
501
502 /*error message status */
503     if (error_class == 0x02){
504         switch (msg_status_code)
505         {
506         case 0x04: str = "Network congestion";break;
507         case 0x05: str = "Network error";break;
508         case 0x1f: str = "Unknown error";break;
509         default: str = "Reserved";break;
510         }
511         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
512         proto_tree_add_text(tree, tvb, offset, 1,
513                             "%s :  Message status code: %s",
514                             ansi_637_bigbuf,
515                             str);
516     }
517
518     if (error_class == 0x03){
519         switch (msg_status_code)
520         {
521         case 0x04: str = "Network congestion";break;
522         case 0x05: str = "Network error";break;
523         case 0x06: str = "Cancel failed";break;
524         case 0x07: str = "Blocked destination";break;
525         case 0x08: str = "Text too long";break;
526         case 0x09: str = "Duplicate message";break;
527         case 0x0a: str = "Invalid destination";break;
528         case 0x0d: str = "Message expired";break;
529         case 0x1f: str = "Unknown error";break;
530         default: str = "Reserved";break;
531         }
532         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
533         proto_tree_add_text(tree, tvb, offset, 1,
534                             "%s :  Message status code: %s",
535                             ansi_637_bigbuf,
536                             str);
537     }
538 }
539
540
541 static void
542 tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
543 {
544     guint8      oct, oct2;
545     guint8      encoding;
546     guint8      msg_type;
547     guint8      num_fields;
548     guint8      used;
549     guint8      bit;
550     guint32     required_octs;
551     guint32     saved_offset;
552     guint32     i , out_len;
553     const gchar *str = NULL;
554
555     /*add more translation UCS  , IA5 , latin ,  latin \ hebrew ,gsm 7BIT*/
556     gchar *utf8_text = NULL;
557     GIConv cd;
558     GError *l_conv_error = NULL;
559
560     SHORT_DATA_CHECK(len, 2);
561
562     /*
563      * message encoding
564      */
565     oct = tvb_get_guint8(tvb, offset);
566     oct2 = 0;
567     msg_type = 0;
568     used = 0;
569
570     encoding = ((oct & 0xf8) >> 3);
571     switch (encoding)
572     {
573     case 0x00: str = "Octet, unspecified"; break;
574     case 0x01: str = "Extended Protocol Message";
575         oct2 = tvb_get_guint8(tvb, offset+1);
576         msg_type = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
577         break;
578     case 0x02: str = "7-bit ASCII"; break;
579     case 0x03: str = "IA5"; break;
580     case 0x04: str = "UNICODE"; break;
581     case 0x05: str = "Shift-JIS"; break;
582     case 0x06: str = "Korean"; break;
583     case 0x07: str = "Latin/Hebrew"; break;
584     case 0x08: str = "Latin"; break;
585     case 0x09: str = "GSM 7-bit default alphabet"; break;
586     default: str = "Reserved"; break;
587     }
588
589     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
590     proto_tree_add_text(tree, tvb, offset, 1,
591         "%s :  Encoding: %s",
592         ansi_637_bigbuf,
593         str);
594
595     if (encoding == 0x01)
596     {
597         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
598         proto_tree_add_text(tree, tvb, offset, 1,
599             "%s :  Message type: see TIA/EIA/IS-91 (%d)",
600             ansi_637_bigbuf,
601             msg_type);
602
603         other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
604         proto_tree_add_text(tree, tvb, offset+1, 1,
605             "%s :  Message type",
606             ansi_637_bigbuf);
607
608         oct = oct2;
609         offset++;
610         used++;
611     }
612
613     offset++;
614     used++;
615
616     /*
617      * number of fields
618      */
619     oct2 = tvb_get_guint8(tvb, offset);
620     num_fields = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
621
622     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
623     proto_tree_add_text(tree, tvb, offset-1, 1,
624         "%s :  Number of fields (MSB): %d",
625         ansi_637_bigbuf,
626         num_fields);
627
628     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
629     proto_tree_add_text(tree, tvb, offset, 1,
630         "%s :  Number of fields (LSB)",
631         ansi_637_bigbuf);
632
633     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
634     proto_tree_add_text(tree, tvb, offset, 1,
635         "%s :  Most significant bits of first field",
636         ansi_637_bigbuf);
637
638     offset++;
639     used++;
640     oct = oct2;
641
642     /* NOTE: there are now 3 bits remaining in 'oct' */
643
644     if (len <= used) return;
645
646     /*
647      * decode rest if 7-bit ASCII
648      */
649     if (encoding == 0x02)
650     {
651         /*
652          * magic numbers:
653          *      3 bits remaining from last octet
654          *      7 bit encoding
655          *      8 bits per octet
656          */
657         i = (num_fields * 7) - 3;
658         required_octs = (i / 8) + ((i % 8) ? 1 : 0);
659
660         if (required_octs + used > len)
661         {
662             proto_tree_add_text(tree, tvb, offset, 1,
663                 "Missing %d octet(s) for number of fields",
664                 (required_octs + used) - len);
665
666             return;
667         }
668
669         bit = 3;
670         saved_offset = offset;
671
672         decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
673
674         proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
675             "Encoded user data: %s",
676             ansi_637_bigbuf);
677
678         switch (bit)
679         {
680         case 1: oct2 = 0x01; break;
681         case 2: oct2 = 0x03; break;
682         case 3: oct2 = 0x07; break;
683         case 4: oct2 = 0x0f; break;
684         case 5: oct2 = 0x1f; break;
685         case 6: oct2 = 0x3f; break;
686         case 7: oct2 = 0x7f; break;
687         }
688
689         if (bit != 8)
690         {
691             other_decode_bitfield_value(ansi_637_bigbuf, oct, oct2, 8);
692             proto_tree_add_text(tree, tvb, offset - 1, 1,
693                 "%s :  Reserved",
694                 ansi_637_bigbuf);
695         }
696     }
697     else if (encoding == 0x03)/* IA5 */
698     {
699         i = (num_fields * 7) - 3;
700         required_octs = (i / 8) + ((i % 8) ? 1 : 0);
701
702         if (required_octs + used > len)
703         {
704             proto_tree_add_text(tree, tvb, offset, 1,
705                                 "Missing %d octet(s) for number of fields",
706                                 (required_octs + used) - len);
707
708             return;
709         }
710
711         bit = 3;
712         saved_offset = offset;
713         out_len = decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
714         IA5_7BIT_decode(ia5_637_bigbuf, ansi_637_bigbuf, out_len);
715
716         proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
717                             "Encoded user data: %s",
718                             ia5_637_bigbuf);
719     }
720     /*TODO UCS else if (encoding == 0x04)
721       {
722       }*/
723     else if (encoding == 0x07)/* Latin/Hebrew */
724     {
725         saved_offset = offset - 1;
726         for (i=0; i < num_fields; i++)
727         {
728             oct = tvb_get_guint8(tvb, saved_offset);
729             oct2 = tvb_get_guint8(tvb, saved_offset + 1);;
730             ansi_637_bigbuf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
731             saved_offset++;
732         }
733
734         if ((cd = g_iconv_open("UTF-8","iso-8859-8")) != (GIConv)-1)
735         {
736             utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb, offset, num_fields), num_fields , cd , NULL , NULL , &l_conv_error);
737             if(!l_conv_error)
738             {
739                 proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
740             }
741             else
742             {
743                 proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-8 contact Wireshark developers");
744             }
745             if(utf8_text)
746                 g_free(utf8_text);
747             g_iconv_close(cd);
748         }
749     }
750     else if (encoding == 0x08) /* Latin */
751     {
752         saved_offset = offset - 1;
753         for (i=0; i < num_fields; i++)
754         {
755             oct = tvb_get_guint8(tvb, saved_offset);
756             oct2 = tvb_get_guint8(tvb, saved_offset + 1);;
757             ansi_637_bigbuf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
758             saved_offset++;
759         }
760
761         if ((cd = g_iconv_open("UTF-8","iso-8859-1")) != (GIConv)-1)
762         {
763             utf8_text = g_convert_with_iconv(ansi_637_bigbuf , num_fields , cd , NULL , NULL , &l_conv_error);
764             if(!l_conv_error)
765             {
766                 proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
767             }
768             else
769             {
770                 proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-1 contact Wireshark developers");
771             }
772             if(utf8_text)
773                 g_free(utf8_text);
774             g_iconv_close(cd);
775         }
776     }
777     else if (encoding == 0x09) /* GSM 7-bit default alphabet */
778     {
779         i = (num_fields * 7) - 3;
780         required_octs = (i / 8) + ((i % 8) ? 1 : 0);
781
782         if (required_octs + used > len)
783         {
784             proto_tree_add_text(tree, tvb, offset, 1,
785                                 "Missing %d octet(s) for number of fields",
786                                 (required_octs + used) - len);
787
788             return;
789         }
790
791         bit = 3;
792         saved_offset = offset;
793         out_len = decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
794         gsm_sms_char_7bit_ascii_decode(gsm_637_bigbuf, ansi_637_bigbuf, out_len);
795
796         proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
797                             "Encoded user data: %s",
798                             gsm_637_bigbuf);
799
800
801     }
802     else
803     {
804         proto_tree_add_text(tree, tvb, offset, len - used,
805                             "Encoded user data");
806     }
807 }
808
809 static void
810 tele_param_rsp_code(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
811 {
812     guint8      oct;
813
814     EXACT_DATA_CHECK(len, 1);
815
816     /*
817      * response code
818      */
819     oct = tvb_get_guint8(tvb, offset);
820
821     proto_tree_add_text(tree, tvb, offset, 1,
822         "Response code: %d",
823         oct);
824 }
825
826 static void
827 tele_param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
828 {
829     guint8      oct, oct2, oct3;
830
831     EXACT_DATA_CHECK(len, 6);
832
833     oct = tvb_get_guint8(tvb, offset);
834     oct2 = tvb_get_guint8(tvb, offset+1);
835     oct3 = tvb_get_guint8(tvb, offset+2);
836
837     proto_tree_add_text(tree, tvb, offset, 3,
838         "Year %d%d, Month %d%d, Day %d%d",
839         (oct & 0xf0) >> 4,
840         oct & 0x0f,
841         (oct2 & 0xf0) >> 4,
842         oct2 & 0x0f,
843         (oct3 & 0xf0) >> 4,
844         oct3 & 0x0f);
845
846     offset += 3;
847
848     oct = tvb_get_guint8(tvb, offset);
849     oct2 = tvb_get_guint8(tvb, offset+1);
850     oct3 = tvb_get_guint8(tvb, offset+2);
851
852     proto_tree_add_text(tree, tvb, offset, 3,
853         "Hour %d%d, Minutes %d%d, Seconds %d%d",
854         (oct & 0xf0) >> 4,
855         oct & 0x0f,
856         (oct2 & 0xf0) >> 4,
857         oct2 & 0x0f,
858         (oct3 & 0xf0) >> 4,
859         oct3 & 0x0f);
860 }
861
862 static void
863 tele_param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
864 {
865     guint8      oct;
866     guint32     value = 0;
867     const gchar *str = NULL;
868     const gchar *str2 = NULL;
869
870     EXACT_DATA_CHECK(len, 1);
871
872     oct = tvb_get_guint8(tvb, offset);
873
874     switch (oct)
875     {
876     case 245: str = "Indefinite"; break;
877     case 246: str = "Immediate"; break;
878     case 247: str = "Valid until mobile becomes inactive/Deliver when mobile next becomes active"; break;
879     case 248: str = "Valid until registration area changes, discard if not registered" ; break;
880     default:
881         if (oct <= 143) { value = (oct + 1) * 5; str2 = "Minutes"; break; }
882         else if ((oct >= 144) && (oct <= 167)) { value = (oct - 143) * 30; str2 = "Minutes + 12 Hours"; break; }
883         else if ((oct >= 168) && (oct <= 196)) { value = oct - 166; str2 = "Days"; break; }
884         else if ((oct >= 197) && (oct <= 244)) { value = oct - 192; str2 = "Weeks"; break; }
885         else { str = "Reserved"; break; }
886     }
887
888     if (str == NULL)
889     {
890         proto_tree_add_text(tree, tvb, offset, 1,
891             "%s", str2);
892     }
893     else
894     {
895         proto_tree_add_text(tree, tvb, offset, 1,
896             "%d %s",
897             value, str2);
898     }
899 }
900
901 static const value_string tele_param_pri_ind_strings[] = {
902     { 0,        "Normal" },
903     { 1,        "Interactive" },
904     { 2,        "Urgent" },
905     { 3,        "Emergency" },
906     { 0, NULL }
907 };
908
909 static void
910 tele_param_pri_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
911 {
912     guint8      oct;
913     const gchar *str = NULL;
914
915     EXACT_DATA_CHECK(len, 1);
916
917     oct = tvb_get_guint8(tvb, offset);
918
919     str=val_to_str((oct&0xc0)>>6, tele_param_pri_ind_strings, "Unknown");
920
921     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
922     proto_tree_add_text(tree, tvb, offset, 1,
923         "%s :  %s",
924         ansi_637_bigbuf,
925         str);
926
927     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
928     proto_tree_add_text(tree, tvb, offset, 1,
929         "%s :  Reserved",
930         ansi_637_bigbuf);
931 }
932
933 static void
934 tele_param_priv_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
935 {
936     guint8      oct;
937     const gchar *str = NULL;
938
939     EXACT_DATA_CHECK(len, 1);
940
941     oct = tvb_get_guint8(tvb, offset);
942
943     switch ((oct & 0xc0) >> 6)
944     {
945     case 0: str = "Not restricted (privacy level 0)"; break;
946     case 1: str = "Restricted (privacy level 1)"; break;
947     case 2: str = "Confidential (privacy level 2)"; break;
948     case 3: str = "Secret (privacy level 3)"; break;
949     }
950
951     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
952     proto_tree_add_text(tree, tvb, offset, 1,
953         "%s :  %s",
954         ansi_637_bigbuf,
955         str);
956
957     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
958     proto_tree_add_text(tree, tvb, offset, 1,
959         "%s :  Reserved",
960         ansi_637_bigbuf);
961 }
962
963 static void
964 tele_param_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
965 {
966     guint8      oct;
967
968     EXACT_DATA_CHECK(len, 1);
969
970     oct = tvb_get_guint8(tvb, offset);
971
972     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
973     proto_tree_add_text(tree, tvb, offset, 1,
974         "%s :  %s (manual) acknowledgment is requested",
975         ansi_637_bigbuf,
976         (oct & 0x80) ? "User" : "No user");
977
978     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
979     proto_tree_add_text(tree, tvb, offset, 1,
980         "%s :  %s acknowledgment requested",
981         ansi_637_bigbuf,
982         (oct & 0x40) ? "Delivery" : "No delivery");
983
984     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
985     proto_tree_add_text(tree, tvb, offset, 1,
986         "%s :  Reserved",
987         ansi_637_bigbuf);
988 }
989
990 static void
991 tele_param_num_messages(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
992 {
993     guint8      oct;
994
995     EXACT_DATA_CHECK(len, 1);
996
997     oct = tvb_get_guint8(tvb, offset);
998
999     proto_tree_add_text(tree, tvb, offset, 1,
1000         "Number of voice mail messages: %d%d",
1001         (oct & 0xf0) >> 4,
1002         oct & 0x0f);
1003 }
1004
1005 static void
1006 tele_param_alert(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1007 {
1008     guint8      oct;
1009     const gchar *str = NULL;
1010
1011     EXACT_DATA_CHECK(len, 1);
1012
1013     oct = tvb_get_guint8(tvb, offset);
1014
1015     switch ((oct & 0xc0) >> 6)
1016     {
1017     case 0: str = "Use Mobile default alert"; break;
1018     case 1: str = "Use Low-priority alert"; break;
1019     case 2: str = "Use Medium-priority alert"; break;
1020     case 3: str = "Use High-priority alert"; break;
1021     }
1022
1023     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
1024     proto_tree_add_text(tree, tvb, offset, 1,
1025         "%s :  %s",
1026         ansi_637_bigbuf,
1027         str);
1028
1029     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
1030     proto_tree_add_text(tree, tvb, offset, 1,
1031         "%s :  Reserved",
1032         ansi_637_bigbuf);
1033 }
1034
1035 static void
1036 tele_param_lang_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1037 {
1038     guint8      oct;
1039     const gchar *str = NULL;
1040
1041     EXACT_DATA_CHECK(len, 1);
1042
1043     oct = tvb_get_guint8(tvb, offset);
1044
1045     switch (oct)
1046     {
1047     case 0x00: str = "Unknown or unspecified"; break;
1048     case 0x01: str = "English"; break;
1049     case 0x02: str = "French"; break;
1050     case 0x03: str = "Spanish"; break;
1051     case 0x04: str = "Japanese"; break;
1052     case 0x05: str = "Korean"; break;
1053     case 0x06: str = "Chinese"; break;
1054     case 0x07: str = "Hebrew"; break;
1055     default: str = "Reserved"; break;
1056     }
1057
1058     proto_tree_add_text(tree, tvb, offset, 1,
1059         "%s", str);
1060 }
1061
1062 static void
1063 tele_param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1064 {
1065     guint8      oct, oct2, num_fields, odd;
1066     guint32     saved_offset;
1067     guint32     required_octs;
1068     guint32     i;
1069
1070     SHORT_DATA_CHECK(len, 2);
1071
1072     oct = tvb_get_guint8(tvb, offset);
1073
1074     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
1075     proto_tree_add_text(tree, tvb, offset, 1,
1076         "%s :  Digit mode: %s",
1077         ansi_637_bigbuf,
1078         (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
1079
1080     if (oct & 0x80)
1081     {
1082         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x70, 8);
1083         proto_tree_add_text(tree, tvb, offset, 1,
1084             "%s :  Type of number: (%d)",
1085             ansi_637_bigbuf,
1086             (oct & 0x70) >> 4);
1087
1088         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
1089         proto_tree_add_text(tree, tvb, offset, 1,
1090             "%s :  Numbering plan: (%d)",
1091             ansi_637_bigbuf,
1092             oct & 0x0f);
1093
1094         offset++;
1095         num_fields = tvb_get_guint8(tvb, offset);
1096
1097         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xff, 8);
1098         proto_tree_add_text(tree, tvb, offset, 1,
1099             "%s :  Number of fields: (%d)",
1100             ansi_637_bigbuf,
1101             num_fields);
1102
1103         if (num_fields == 0) return;
1104
1105         if (num_fields > (len - 2))
1106         {
1107             proto_tree_add_text(tree, tvb, offset, 1,
1108                 "Missing %d octet(s) for number of fields",
1109                 (num_fields + 2) - len);
1110
1111             return;
1112         }
1113
1114         offset++;
1115
1116         i = 0;
1117         while (i < num_fields)
1118         {
1119             ansi_637_bigbuf[i] = tvb_get_guint8(tvb, offset+i) & 0x7f;
1120             i++;
1121         }
1122         ansi_637_bigbuf[i] = '\0';
1123
1124         proto_tree_add_text(tree, tvb, offset, num_fields,
1125             "Number: %s",
1126             ansi_637_bigbuf);
1127     }
1128     else
1129     {
1130         offset++;
1131         num_fields = (oct & 0x7f) << 1;
1132         oct2 = tvb_get_guint8(tvb, offset);
1133         num_fields |= ((oct2 & 0x80) >> 7);
1134
1135         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
1136         proto_tree_add_text(tree, tvb, offset-1, 1,
1137             "%s :  Number of fields (MBS): (%d)",
1138             ansi_637_bigbuf,
1139             num_fields);
1140
1141         other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
1142         proto_tree_add_text(tree, tvb, offset, 1,
1143             "%s :  Number of fields (LSB)",
1144             ansi_637_bigbuf);
1145
1146         oct = oct2;
1147         odd = FALSE;
1148
1149         if (num_fields > 0)
1150         {
1151             i = (num_fields - 1) * 4;
1152             required_octs = (i / 8) + ((i % 8) ? 1 : 0);
1153
1154             if (required_octs + 2 > len)
1155             {
1156                 proto_tree_add_text(tree, tvb, offset, 1,
1157                     "Missing %d octet(s) for number of fields",
1158                     (required_octs + 2) - len);
1159
1160                 return;
1161             }
1162
1163             odd = num_fields & 0x01;
1164             memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
1165             saved_offset = offset;
1166             offset++;
1167
1168             i = 0;
1169             while (i < num_fields)
1170             {
1171                 ansi_637_bigbuf[i] =
1172                     air_digits[(oct & 0x78) >> 3];
1173
1174                 i++;
1175                 if (i >= num_fields) break;
1176
1177                 oct2 = tvb_get_guint8(tvb, offset);
1178                 offset++;
1179
1180                 ansi_637_bigbuf[i] =
1181                     air_digits[((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)];
1182
1183                 oct = oct2;
1184
1185                 i++;
1186             }
1187
1188             proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
1189                 "Number: %s",
1190                 ansi_637_bigbuf);
1191         }
1192
1193         other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x07: 0x7f, 8);
1194         proto_tree_add_text(tree, tvb, offset, 1,
1195             "%s :  Reserved",
1196             ansi_637_bigbuf);
1197     }
1198 }
1199
1200 static void
1201 tele_param_disp_mode(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1202 {
1203     guint8      oct;
1204     const gchar *str = NULL;
1205
1206     EXACT_DATA_CHECK(len, 1);
1207
1208     oct = tvb_get_guint8(tvb, offset);
1209
1210     switch ((oct & 0xc0) >> 6)
1211     {
1212     case 0: str = "Immediate Display: The mobile station is to display the received message as soon as possible."; break;
1213     case 1: str = "Mobile default setting: The mobile station is to display the received message based on a pre-defined mode in the mobile station."; break;
1214     case 2: str = "User Invoke: The mobile station is to display the received message based on the mode selected by the user."; break;
1215     case 3: str = "Reserved"; break;
1216     }
1217
1218     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
1219     proto_tree_add_text(tree, tvb, offset, 1,
1220         "%s :  %s",
1221         ansi_637_bigbuf,
1222         str);
1223
1224     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
1225     proto_tree_add_text(tree, tvb, offset, 1,
1226         "%s :  Reserved",
1227         ansi_637_bigbuf);
1228 }
1229
1230 #define NUM_TELE_PARAM (sizeof(ansi_tele_param_strings)/sizeof(value_string))
1231 static gint ett_ansi_637_tele_param[NUM_TELE_PARAM];
1232 static void (*ansi_637_tele_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
1233     tele_param_msg_id,          /* Message Identifier */
1234     tele_param_user_data,       /* User Data */
1235     tele_param_rsp_code,        /* User Response Code */
1236     tele_param_timestamp,       /* Message Center Time Stamp */
1237     tele_param_timestamp,       /* Validity Period  Absolute */
1238     tele_param_rel_timestamp,   /* Validity Period  Relative */
1239     tele_param_timestamp,       /* Deferred Delivery Time - Absolute */
1240     tele_param_rel_timestamp,   /* Deferred Delivery Time - Relative */
1241     tele_param_pri_ind,         /* Priority Indicator */
1242     tele_param_priv_ind,        /* Privacy Indicator */
1243     tele_param_reply_opt,       /* Reply Option */
1244     tele_param_num_messages,    /* Number of Messages */
1245     tele_param_alert,           /* Alert on Message Delivery */
1246     tele_param_lang_ind,        /* Language Indicator */
1247     tele_param_cb_num,          /* Call-Back Number */
1248     tele_param_disp_mode,       /* Message Display Mode */
1249     NULL,                       /* Multiple Encoding User Data */
1250     tele_param_msg_status       /* Message status */
1251 };
1252
1253 static void
1254 trans_param_tele_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len)
1255 {
1256     guint32     value;
1257     const gchar *str = NULL;
1258
1259     EXACT_DATA_CHECK(len, 2);
1260
1261     value = tvb_get_ntohs(tvb, offset);
1262
1263     ansi_637_trans_tele_id = value;
1264
1265     str = match_strval(value, ansi_tele_id_strings);
1266
1267     if (NULL == str)
1268     {
1269         switch (value)
1270         {
1271         case 1:
1272             str = "Reserved for maintenance";
1273             break;
1274         case 4102:
1275             str = "CDMA Service Category Programming Teleservice (SCPT)";
1276             break;
1277         case 4103:
1278             str = "CDMA Card Application Toolkit Protocol Teleservice (CATPT)";
1279             break;
1280         case 32513:
1281             str = "TDMA Cellular Messaging Teleservice";
1282             break;
1283         case 32514:
1284             str = "TDMA Cellular Paging Teleservice (CPT-136)";
1285             break;
1286         case 32515:
1287             str = "TDMA Over-the-Air Activation Teleservice (OATS)";
1288             break;
1289         case 32520:
1290             str = "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)";
1291             break;
1292         case 32584:
1293             str = "TDMA Segmented System Assisted Mobile Positioning Service";
1294             break;
1295         default:
1296             if ((value >= 2) && (value <= 4095))
1297             {
1298                 str = "Reserved for assignment by TIA-41";
1299             }
1300             else if ((value >= 4104) && (value <= 4113))
1301             {
1302                 str = "Reserved for GSM1x Teleservice (CDMA)";
1303             }
1304             else if ((value >= 4114) && (value <= 32512))
1305             {
1306                 str = "Reserved for assignment by TIA-41";
1307             }
1308             else if ((value >= 32521) && (value <= 32575))
1309             {
1310                 str = "Reserved for assignment by this Standard for TDMA MS-based SMEs";
1311             }
1312             else if ((value >= 49152) && (value <= 65535))
1313             {
1314                 str = "Reserved for carrier specific teleservices";
1315             }
1316             else
1317             {
1318                 str = "Unrecognized Teleservice ID";
1319             }
1320             break;
1321         }
1322     }
1323
1324     proto_tree_add_text(tree, tvb, offset, 2,
1325         "%s (%d)",
1326         str,
1327         value);
1328
1329     g_snprintf(add_string, string_len, " - %s (%d)", str, value);
1330 }
1331
1332 static void
1333 trans_param_srvc_cat(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len)
1334 {
1335     guint32     value;
1336     const gchar *str = NULL;
1337
1338     EXACT_DATA_CHECK(len, 2);
1339
1340     value = tvb_get_ntohs(tvb, offset);
1341
1342     str = val_to_str_const(value, ansi_srvc_cat_strings, "Reserved");
1343
1344     proto_tree_add_text(tree, tvb, offset, 2,
1345         "%s", str);
1346
1347     g_snprintf(add_string, string_len, " - %s (%d)", str, value);
1348 }
1349
1350 static void
1351 trans_param_address(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_)
1352 {
1353     guint8      oct, oct2, num_fields, odd;
1354     gboolean    email_addr;
1355     guint32     saved_offset;
1356     guint32     required_octs;
1357     guint32     i;
1358     const gchar *str;
1359
1360     SHORT_DATA_CHECK(len, 2);
1361
1362     email_addr = FALSE;
1363
1364     oct = tvb_get_guint8(tvb, offset);
1365
1366     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
1367     proto_tree_add_text(tree, tvb, offset, 1,
1368         "%s :  Digit mode: %s",
1369         ansi_637_bigbuf,
1370         (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
1371
1372     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
1373     proto_tree_add_text(tree, tvb, offset, 1,
1374         "%s :  Number mode: %s",
1375         ansi_637_bigbuf,
1376         (oct & 0x40) ? "Data Network Address" : "ANSI T1.607");
1377
1378     if (oct & 0x80)
1379     {
1380         if (oct & 0x40)
1381         {
1382             switch ((oct & 0x38) >> 3)
1383             {
1384             case 0: str = "Unknown"; break;
1385             case 1: str = "Internet Protocol (RFC 791)"; break;
1386             case 2: str = "Internet Email Address (RFC 822)"; email_addr = TRUE; break;
1387             default:
1388                 str = "Reserved";
1389                 break;
1390             }
1391
1392             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
1393             proto_tree_add_text(tree, tvb, offset, 1,
1394                 "%s :  Type of number: %s (%d)",
1395                 ansi_637_bigbuf,
1396                 str,
1397                 (oct & 0x38) >> 3);
1398
1399             offset++;
1400             num_fields = (oct & 0x07) << 5;
1401             oct2 = tvb_get_guint8(tvb, offset);
1402             num_fields |= ((oct2 & 0xf8) >> 3);
1403
1404             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
1405             proto_tree_add_text(tree, tvb, offset-1, 1,
1406                 "%s :  Number of fields (MSB): (%d)",
1407                 ansi_637_bigbuf,
1408                 num_fields);
1409
1410             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
1411             proto_tree_add_text(tree, tvb, offset, 1,
1412                 "%s :  Number of fields (LSB)",
1413                 ansi_637_bigbuf);
1414
1415             if (num_fields == 0) return;
1416
1417             if (num_fields > (len - 2))
1418             {
1419                 proto_tree_add_text(tree, tvb, offset, 1,
1420                     "Missing %d octet(s) for number of fields",
1421                     (num_fields + 2) - len);
1422
1423                 return;
1424             }
1425
1426             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
1427             proto_tree_add_text(tree, tvb, offset, 1,
1428                 "%s :  Most significant bits of first field",
1429                 ansi_637_bigbuf);
1430
1431             offset++;
1432             oct = oct2;
1433
1434             i = 0;
1435             while (i < num_fields)
1436             {
1437                 ansi_637_bigbuf[i] = (oct & 0x07) << 5;
1438                 ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf8) >> 3;
1439                 i++;
1440             }
1441             ansi_637_bigbuf[i] = '\0';
1442
1443             if (email_addr)
1444             {
1445                 proto_tree_add_text(tree, tvb, offset, num_fields - 1,
1446                     "Number: %s",
1447                     ansi_637_bigbuf);
1448             }
1449             else
1450             {
1451                 proto_tree_add_bytes(tree, hf_ansi_637_trans_bin_addr, tvb, offset, num_fields - 1,
1452                     (guint8*)ansi_637_bigbuf);
1453             }
1454
1455             offset += (num_fields - 1);
1456
1457             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
1458             proto_tree_add_text(tree, tvb, offset, 1,
1459                 "%s :  Least significant bits of last field",
1460                 ansi_637_bigbuf);
1461
1462             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
1463             proto_tree_add_text(tree, tvb, offset, 1,
1464                 "%s :  Reserved",
1465                 ansi_637_bigbuf);
1466         }
1467         else
1468         {
1469             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
1470             proto_tree_add_text(tree, tvb, offset, 1,
1471                 "%s :  Type of number: (%d)",
1472                 ansi_637_bigbuf,
1473                 (oct & 0x38) >> 3);
1474
1475             oct2 = tvb_get_guint8(tvb, offset + 1);
1476
1477             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
1478             proto_tree_add_text(tree, tvb, offset, 1,
1479                 "%s :  Numbering plan (MSB): (%d)",
1480                 ansi_637_bigbuf,
1481                 ((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7));
1482
1483             offset++;
1484             oct = oct2;
1485
1486             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
1487             proto_tree_add_text(tree, tvb, offset, 1,
1488                 "%s :  Numbering plan (LSB)",
1489                 ansi_637_bigbuf);
1490
1491             offset++;
1492             num_fields = (oct & 0x7f) << 1;
1493             oct2 = tvb_get_guint8(tvb, offset);
1494             num_fields |= ((oct2 & 0x80) >> 7);
1495
1496             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
1497             proto_tree_add_text(tree, tvb, offset-1, 1,
1498                 "%s :  Number of fields (MSB): (%d)",
1499                 ansi_637_bigbuf,
1500                 num_fields);
1501
1502             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
1503             proto_tree_add_text(tree, tvb, offset, 1,
1504                 "%s :  Number of fields (LSB)",
1505                 ansi_637_bigbuf);
1506
1507             if (num_fields == 0) return;
1508
1509             if (num_fields > (len - 3))
1510             {
1511                 proto_tree_add_text(tree, tvb, offset, 1,
1512                     "Missing %d octet(s) for number of fields",
1513                     (num_fields + 3) - len);
1514
1515                 return;
1516             }
1517
1518             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x7f, 8);
1519             proto_tree_add_text(tree, tvb, offset, 1,
1520                 "%s :  Most significant bits of first field",
1521                 ansi_637_bigbuf);
1522
1523             offset++;
1524             oct = oct2;
1525
1526             i = 0;
1527             while (i < num_fields)
1528             {
1529                 ansi_637_bigbuf[i] = (oct & 0x7f) << 1;
1530                 ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0x80) >> 7;
1531                 i++;
1532             }
1533             ansi_637_bigbuf[i] = '\0';
1534
1535             proto_tree_add_text(tree, tvb, offset, num_fields - 1,
1536                 "Number: %s",
1537                 ansi_637_bigbuf);
1538
1539             offset += (num_fields - 1);
1540
1541             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
1542             proto_tree_add_text(tree, tvb, offset, 1,
1543                 "%s :  Least significant bit of last field",
1544                 ansi_637_bigbuf);
1545
1546             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
1547             proto_tree_add_text(tree, tvb, offset, 1,
1548                 "%s :  Reserved",
1549                 ansi_637_bigbuf);
1550         }
1551     }
1552     else
1553     {
1554         offset++;
1555         num_fields = (oct & 0x3f) << 2;
1556         oct2 = tvb_get_guint8(tvb, offset);
1557         num_fields |= ((oct2 & 0xc0) >> 6);
1558
1559         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
1560         proto_tree_add_text(tree, tvb, offset-1, 1,
1561             "%s :  Number of fields (MSB): (%d)",
1562             ansi_637_bigbuf,
1563             num_fields);
1564
1565         other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xc0, 8);
1566         proto_tree_add_text(tree, tvb, offset, 1,
1567             "%s :  Number of fields (LSB)",
1568             ansi_637_bigbuf);
1569
1570         oct = oct2;
1571         odd = FALSE;
1572
1573         if (num_fields > 0)
1574         {
1575             i = (num_fields - 1) * 4;
1576             required_octs = (i / 8) + ((i % 8) ? 1 : 0);
1577
1578             if (required_octs + 2 > len)
1579             {
1580                 proto_tree_add_text(tree, tvb, offset, 1,
1581                     "Missing %d octet(s) for number of fields",
1582                     (required_octs + 2) - len);
1583
1584                 return;
1585             }
1586
1587             odd = num_fields & 0x01;
1588             memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
1589             saved_offset = offset;
1590             offset++;
1591
1592             i = 0;
1593             while (i < num_fields)
1594             {
1595                 ansi_637_bigbuf[i] =
1596                     air_digits[(oct & 0x3c) >> 2];
1597
1598                 i++;
1599                 if (i >= num_fields) break;
1600
1601                 oct2 = tvb_get_guint8(tvb, offset);
1602                 offset++;
1603
1604                 ansi_637_bigbuf[i] =
1605                     air_digits[((oct & 0x03) << 2) | ((oct2 & 0xc0) >> 6)];
1606
1607                 oct = oct2;
1608
1609                 i++;
1610             }
1611
1612             proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
1613                 "Number: %s",
1614                 ansi_637_bigbuf);
1615         }
1616
1617         other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x03: 0x3f, 8);
1618         proto_tree_add_text(tree, tvb, offset, 1,
1619             "%s :  Reserved",
1620             ansi_637_bigbuf);
1621     }
1622 }
1623
1624 static void
1625 trans_param_subaddress(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_)
1626 {
1627     guint8      oct, oct2, num_fields;
1628     guint32     i;
1629     const gchar *str;
1630
1631     SHORT_DATA_CHECK(len, 2);
1632
1633     oct = tvb_get_guint8(tvb, offset);
1634
1635     switch ((oct & 0xe0) >> 5)
1636     {
1637     case 0: str = "NSAP (CCITT Recommendation X.213 or ISO 8348 AD2)"; break;
1638     case 1: str = "User-specified"; break;
1639     default:
1640         str = "Reserved";
1641         break;
1642     }
1643
1644     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xe0, 8);
1645     proto_tree_add_text(tree, tvb, offset, 1,
1646         "%s :  Type: %s",
1647         ansi_637_bigbuf,
1648         str);
1649
1650     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x10, 8);
1651     proto_tree_add_text(tree, tvb, offset, 1,
1652         "%s :  Odd",
1653         ansi_637_bigbuf);
1654
1655     offset++;
1656     num_fields = (oct & 0x0f) << 4;
1657     oct2 = tvb_get_guint8(tvb, offset);
1658     num_fields |= ((oct2 & 0xf0) >> 4);
1659
1660     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
1661     proto_tree_add_text(tree, tvb, offset-1, 1,
1662         "%s :  Number of fields (MSB): (%d)",
1663         ansi_637_bigbuf,
1664         num_fields);
1665
1666     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf0, 8);
1667     proto_tree_add_text(tree, tvb, offset, 1,
1668         "%s :  Number of fields (LSB)",
1669         ansi_637_bigbuf);
1670
1671     if (num_fields == 0) return;
1672
1673     if (num_fields > (len - 2))
1674     {
1675         proto_tree_add_text(tree, tvb, offset, 1,
1676             "Missing %d octet(s) for number of fields",
1677             (num_fields + 2) - len);
1678
1679         return;
1680     }
1681
1682     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x0f, 8);
1683     proto_tree_add_text(tree, tvb, offset, 1,
1684         "%s :  Most significant bits of first field",
1685         ansi_637_bigbuf);
1686
1687     offset++;
1688     oct = oct2;
1689
1690     i = 0;
1691     while (i < num_fields)
1692     {
1693         ansi_637_bigbuf[i] = (oct & 0x0f) << 4;
1694         ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf0) >> 4;
1695         i++;
1696     }
1697     ansi_637_bigbuf[i] = '\0';
1698
1699     proto_tree_add_bytes(tree, hf_ansi_637_trans_bin_addr, tvb, offset, num_fields - 1,
1700         (guint8*)ansi_637_bigbuf);
1701
1702     offset += (num_fields - 1);
1703
1704     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf0, 8);
1705     proto_tree_add_text(tree, tvb, offset, 1,
1706         "%s :  Least significant bits of last field",
1707         ansi_637_bigbuf);
1708
1709     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
1710     proto_tree_add_text(tree, tvb, offset, 1,
1711         "%s :  Reserved",
1712         ansi_637_bigbuf);
1713 }
1714
1715 static void
1716 trans_param_bearer_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len _U_, guint32 offset, gchar *add_string, int string_len)
1717 {
1718     guint8      oct;
1719
1720     oct = tvb_get_guint8(tvb, offset);
1721
1722     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
1723     proto_tree_add_text(tree, tvb, offset, 1,
1724         "%s :  Reply Sequence Number: %d",
1725         ansi_637_bigbuf,
1726         (oct & 0xfc) >> 2);
1727
1728     g_snprintf(add_string, string_len, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
1729
1730     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
1731     proto_tree_add_text(tree, tvb, offset, 1,
1732         "%s :  Reserved",
1733         ansi_637_bigbuf);
1734 }
1735
1736 static void
1737 trans_param_cause_codes(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len)
1738 {
1739     guint8      oct;
1740     const gchar *str = NULL;
1741
1742     oct = tvb_get_guint8(tvb, offset);
1743
1744     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
1745     proto_tree_add_text(tree, tvb, offset, 1,
1746         "%s :  Reply Sequence Number: %d",
1747         ansi_637_bigbuf,
1748         (oct & 0xfc) >> 2);
1749
1750     switch (oct & 0x03)
1751     {
1752     case 0x00: str = "No error"; break;
1753     case 0x02: str = "Temporary Condition"; break;
1754     case 0x03: str = "Permanent Condition"; break;
1755     default:
1756         str = "Reserved";
1757         break;
1758     }
1759
1760     g_snprintf(add_string, string_len, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
1761
1762     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
1763     proto_tree_add_text(tree, tvb, offset, 1,
1764         "%s :  Error Class: %s",
1765         ansi_637_bigbuf,
1766         str);
1767
1768     offset++;
1769
1770     if (!(oct & 0x03)) return;
1771
1772     if (len == 1) return;
1773
1774     oct = tvb_get_guint8(tvb, offset);
1775
1776     switch (oct)
1777     {
1778     case 0: str = "Address vacant"; break;
1779     case 1: str = "Address translation failure"; break;
1780     case 2: str = "Network resource shortage"; break;
1781     case 3: str = "Network failure"; break;
1782     case 4: str = "Invalid Teleservice ID"; break;
1783     case 5: str = "Other network problem"; break;
1784     case 6: str = "Unsupported network interface"; break;
1785     case 32: str = "No page response"; break;
1786     case 33: str = "Destination busy"; break;
1787     case 34: str = "No acknowledgement"; break;
1788     case 35: str = "Destination resource shortage"; break;
1789     case 36: str = "SMS delivery postponed"; break;
1790     case 37: str = "Destination out of service"; break;
1791     case 38: str = "Destination no longer at this address"; break;
1792     case 39: str = "Other terminal problem"; break;
1793     case 64: str = "Radio interface resource shortage"; break;
1794     case 65: str = "Radio interface incompatibility"; break;
1795     case 66: str = "Other radio interface problem"; break;
1796     case 67: str = "Unsupported Base Station Capability"; break;
1797     case 96: str = "Encoding problem"; break;
1798     case 97: str = "Service origination denied"; break;
1799     case 98: str = "Service termination denied"; break;
1800     case 99: str = "Supplementary service not supported"; break;
1801     case 100: str = "Service not supported"; break;
1802     case 101: str = "Reserved"; break;
1803     case 102: str = "Missing expected parameter"; break;
1804     case 103: str = "Missing mandatory parameter"; break;
1805     case 104: str = "Unrecognized parameter value"; break;
1806     case 105: str = "Unexpected parameter value"; break;
1807     case 106: str = "User Data size error"; break;
1808     case 107: str = "Other general problems"; break;
1809     case 108: str = "Session not active"; break;
1810     default:
1811         if ((oct >= 7) && (oct <= 31)) { str = "Reserved, treat as Other network problem"; }
1812         else if ((oct >= 40) && (oct <= 47)) { str = "Reserved, treat as Other terminal problem"; }
1813         else if ((oct >= 48) && (oct <= 63)) { str = "Reserved, treat as SMS delivery postponed"; }
1814         else if ((oct >= 68) && (oct <= 95)) { str = "Reserved, treat as Other radio interface problem"; }
1815         else if ((oct >= 109) && (oct <= 223)) { str = "Reserved, treat as Other general problems"; }
1816         else { str = "Reserved for protocol extension, treat as Other general problems"; }
1817         break;
1818     }
1819
1820     proto_tree_add_text(tree, tvb, offset, 1,
1821         "%s", str);
1822 }
1823
1824 static void
1825 trans_param_bearer_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_)
1826 {
1827     tvbuff_t    *tele_tvb;
1828
1829     proto_tree_add_text(tree, tvb, offset, len,
1830         "Bearer Data");
1831
1832     /*
1833      * dissect the embedded teleservice data
1834      */
1835     tele_tvb = tvb_new_subset(tvb, offset, len, len);
1836
1837     dissector_try_uint(tele_dissector_table, ansi_637_trans_tele_id,
1838         tele_tvb, g_pinfo, g_tree);
1839 }
1840
1841 #define NUM_TRANS_PARAM (sizeof(ansi_trans_param_strings)/sizeof(value_string))
1842 static gint ett_ansi_637_trans_param[NUM_TRANS_PARAM];
1843 static void (*ansi_637_trans_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len) = {
1844     trans_param_tele_id,        /* Teleservice Identifier */
1845     trans_param_srvc_cat,       /* Service Category */
1846     trans_param_address,        /* Originating Address */
1847     trans_param_subaddress,     /* Originating Subaddress */
1848     trans_param_address,        /* Destination Address */
1849     trans_param_subaddress,     /* Destination Subaddress */
1850     trans_param_bearer_reply_opt,       /* Bearer Reply Option */
1851     trans_param_cause_codes,    /* Cause Codes */
1852     trans_param_bearer_data,    /* Bearer Data */
1853     NULL,       /* NONE */
1854 };
1855
1856 #define NUM_TRANS_MSG_TYPE (sizeof(ansi_trans_msg_type_strings)/sizeof(value_string))
1857 static gint ett_ansi_637_trans_msg[NUM_TRANS_MSG_TYPE];
1858
1859 /* GENERIC IS-637 DISSECTOR FUNCTIONS */
1860
1861 static gboolean
1862 dissect_ansi_637_tele_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
1863 {
1864     void (*param_fcn)(tvbuff_t *, proto_tree *, guint, guint32) = NULL;
1865     guint8      oct;
1866     guint8      len;
1867     guint32     curr_offset;
1868     gint        ett_param_idx, idx;
1869     proto_tree  *subtree;
1870     proto_item  *item;
1871     const gchar *str = NULL;
1872
1873
1874     curr_offset = *offset;
1875
1876     oct = tvb_get_guint8(tvb, curr_offset);
1877     str = match_strval_idx((guint32) oct, ansi_tele_param_strings, &idx);
1878
1879     if (NULL == str)
1880     {
1881         return(FALSE);
1882     }
1883
1884     ett_param_idx = ett_ansi_637_tele_param[idx];
1885     param_fcn = ansi_637_tele_param_fcn[idx];
1886
1887     item =
1888         proto_tree_add_text(tree, tvb, curr_offset, -1, "%s", str);
1889
1890     subtree = proto_item_add_subtree(item, ett_param_idx);
1891
1892     proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id,
1893         tvb, curr_offset, 1, oct);
1894
1895     curr_offset++;
1896
1897     len = tvb_get_guint8(tvb, curr_offset);
1898
1899     proto_item_set_len(item, (curr_offset - *offset) + len + 1);
1900
1901     proto_tree_add_uint(subtree, hf_ansi_637_tele_length,
1902         tvb, curr_offset, 1, len);
1903
1904     curr_offset++;
1905
1906     if (len > 0)
1907     {
1908         if (param_fcn == NULL)
1909         {
1910             proto_tree_add_text(subtree, tvb, curr_offset,
1911                 len, "Parameter Data");
1912         }
1913         else
1914         {
1915             (*param_fcn)(tvb, subtree, len, curr_offset);
1916         }
1917
1918         curr_offset += len;
1919     }
1920
1921     *offset = curr_offset;
1922
1923     return(TRUE);
1924 }
1925
1926 static void
1927 dissect_ansi_637_tele_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
1928 {
1929     guint8      len;
1930     guint32     curr_offset;
1931
1932     curr_offset = 0;
1933     len = tvb_length(tvb);
1934
1935     while ((len - curr_offset) > 0)
1936     {
1937         if (!dissect_ansi_637_tele_param(tvb, ansi_637_tree, &curr_offset))
1938         {
1939             proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
1940                 "Unknown Parameter Data");
1941             break;
1942         }
1943     }
1944 }
1945
1946 static void
1947 dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1948 {
1949     proto_item  *ansi_637_item;
1950     proto_tree  *ansi_637_tree = NULL;
1951     const gchar *str = NULL;
1952     guint32     value;
1953
1954     col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
1955
1956     /* In the interest of speed, if "tree" is NULL, don't do any work not
1957      * necessary to generate protocol tree items.
1958      */
1959     if (tree)
1960     {
1961         value = pinfo->match_uint;
1962
1963         /*
1964          * create the ansi_637 protocol tree
1965          */
1966         str = match_strval(value, ansi_tele_id_strings);
1967
1968         if (NULL == str)
1969         {
1970             switch (value)
1971             {
1972             case 1:
1973                 str = "Reserved for maintenance";
1974                 break;
1975             case 4102:
1976                 str = "CDMA Service Category Programming Teleservice (SCPT)";
1977                 break;
1978             case 4103:
1979                 str = "CDMA Card Application Toolkit Protocol Teleservice (CATPT)";
1980                 break;
1981             case 32513:
1982                 str = "TDMA Cellular Messaging Teleservice";
1983                 break;
1984             case 32514:
1985                 str = "TDMA Cellular Paging Teleservice (CPT-136)";
1986                 break;
1987             case 32515:
1988                 str = "TDMA Over-the-Air Activation Teleservice (OATS)";
1989                 break;
1990             case 32520:
1991                 str = "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)";
1992                 break;
1993             case 32584:
1994                 str = "TDMA Segmented System Assisted Mobile Positioning Service";
1995                 break;
1996             default:
1997                 if ((value >= 2) && (value <= 4095))
1998                 {
1999                     str = "Reserved for assignment by TIA-41";
2000                 }
2001                 else if ((value >= 4104) && (value <= 4113))
2002                 {
2003                     str = "Reserved for GSM1x Teleservice (CDMA)";
2004                 }
2005                 else if ((value >= 4114) && (value <= 32512))
2006                 {
2007                     str = "Reserved for assignment by TIA-41";
2008                 }
2009                 else if ((value >= 32521) && (value <= 32575))
2010                 {
2011                     str = "Reserved for assignment by this Standard for TDMA MS-based SMEs";
2012                 }
2013                 else if ((value >= 49152) && (value < 65535))
2014                 {
2015                     str = "Reserved for carrier specific teleservices";
2016                 }
2017                 else if (value == 65535)
2018                 {
2019                     /*
2020                      * supposed to be "Reserved for carrier specific teleservices"
2021                      * but we are using it to key SMS Broadcast dissection where
2022                      * there is no teleservice ID
2023                      */
2024                     str = "(Reserved) Being used for Broadcast";
2025                 }
2026                 else
2027                 {
2028                     str = "Unrecognized Teleservice ID";
2029                 }
2030                 break;
2031             }
2032         }
2033
2034         ansi_637_item =
2035             proto_tree_add_protocol_format(tree, proto_ansi_637_tele, tvb, 0, -1,
2036                 "%s - %s (%d)",
2037                 ansi_proto_name_tele,
2038                 str,
2039                 pinfo->match_uint);
2040
2041         ansi_637_tree =
2042             proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele);
2043
2044         dissect_ansi_637_tele_message(tvb, ansi_637_tree);
2045     }
2046 }
2047
2048 static gboolean
2049 dissect_ansi_637_trans_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
2050 {
2051     void (*param_fcn)(tvbuff_t *, proto_tree *, guint, guint32, gchar *, int) = NULL;
2052     guint8      oct;
2053     guint8      len;
2054     guint32     curr_offset;
2055     gint        ett_param_idx, idx;
2056     proto_tree  *subtree;
2057     proto_item  *item;
2058     const gchar *str = NULL;
2059
2060     curr_offset = *offset;
2061
2062     oct = tvb_get_guint8(tvb, curr_offset);
2063     str = match_strval_idx((guint32) oct, ansi_trans_param_strings, &idx);
2064
2065     if (NULL == str)
2066     {
2067         return(FALSE);
2068     }
2069
2070     ett_param_idx = ett_ansi_637_trans_param[idx];
2071     param_fcn = ansi_637_trans_param_fcn[idx];
2072
2073     item =
2074         proto_tree_add_text(tree, tvb, curr_offset, -1, "%s", str);
2075
2076     subtree = proto_item_add_subtree(item, ett_param_idx);
2077
2078     proto_tree_add_uint(subtree, hf_ansi_637_trans_param_id,
2079         tvb, curr_offset, 1, oct);
2080
2081     curr_offset++;
2082
2083     len = tvb_get_guint8(tvb, curr_offset);
2084
2085     proto_item_set_len(item, (curr_offset - *offset) + len + 1);
2086
2087     proto_tree_add_uint(subtree, hf_ansi_637_trans_length,
2088         tvb, curr_offset, 1, len);
2089
2090     curr_offset++;
2091
2092     if (len > 0)
2093     {
2094         if (param_fcn == NULL)
2095         {
2096             proto_tree_add_text(subtree, tvb, curr_offset,
2097                 len, "Parameter Data");
2098         }
2099         else
2100         {
2101             gchar *ansi_637_add_string;
2102
2103             ansi_637_add_string = ep_alloc(1024);
2104             ansi_637_add_string[0] = '\0';
2105             (*param_fcn)(tvb, subtree, len, curr_offset, ansi_637_add_string, 1024);
2106
2107             if (ansi_637_add_string[0] != '\0')
2108             {
2109                 proto_item_append_text(item, "%s", ansi_637_add_string);
2110             }
2111         }
2112
2113         curr_offset += len;
2114     }
2115
2116     *offset = curr_offset;
2117
2118     return(TRUE);
2119 }
2120
2121
2122 static void
2123 dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2124 {
2125     proto_item  *ansi_637_item;
2126     proto_tree  *ansi_637_tree = NULL;
2127     guint32     curr_offset;
2128     gint        idx;
2129     const gchar *str = NULL;
2130     guint8      oct;
2131     guint8      len;
2132
2133     col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
2134
2135     /* In the interest of speed, if "tree" is NULL, don't do any work not
2136      * necessary to generate protocol tree items.
2137      */
2138     if (tree)
2139     {
2140         g_pinfo = pinfo;
2141         g_tree = tree;
2142
2143         /*
2144          * reset the teleservice ID for each dissection
2145          */
2146         ansi_637_trans_tele_id = 0;
2147
2148         /*
2149          * create the ansi_637 protocol tree
2150          */
2151         oct = tvb_get_guint8(tvb, 0);
2152
2153         str = match_strval_idx(oct, ansi_trans_msg_type_strings, &idx);
2154
2155         if (NULL == str)
2156         {
2157             ansi_637_item =
2158                 proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
2159                     "%s - Unrecognized Transport Layer Message Type (%d)",
2160                     ansi_proto_name_trans,
2161                     oct);
2162
2163             ansi_637_tree =
2164                 proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans);
2165         }
2166         else
2167         {
2168             ansi_637_item =
2169                 proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
2170                     "%s - %s",
2171                     ansi_proto_name_trans,
2172                     str);
2173
2174             ansi_637_tree =
2175                 proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans_msg[idx]);
2176
2177             if (oct == ANSI_TRANS_MSG_TYPE_BROADCAST)
2178             {
2179                 /*
2180                  * there is no teleservice ID for Broadcast but we want the
2181                  * bearer data to be dissected
2182                  *
2183                  * using a reserved value to key dissector port
2184                  */
2185                 ansi_637_trans_tele_id = 65535;
2186             }
2187         }
2188
2189         curr_offset = 1;
2190
2191         len = tvb_length(tvb);
2192
2193         while ((len - curr_offset) > 0)
2194         {
2195             if (!dissect_ansi_637_trans_param(tvb, ansi_637_tree, &curr_offset))
2196             {
2197                 proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
2198                     "Unknown Parameter Data");
2199                 break;
2200             }
2201         }
2202     }
2203 }
2204 /* Dissect SMS embedded in SIP */
2205 static void
2206 dissect_ansi_637_trans_app(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2207 {
2208     col_set_str(pinfo->cinfo, COL_PROTOCOL,"/");
2209     col_set_fence(pinfo->cinfo, COL_INFO);
2210     dissect_ansi_637_trans(tvb, pinfo, tree);
2211 }
2212 /* Register the protocol with Wireshark */
2213 void
2214 proto_register_ansi_637(void)
2215 {
2216     guint               i;
2217
2218     /* Setup list of header fields */
2219     static hf_register_info hf_trans[] =
2220     {
2221         { &hf_ansi_637_trans_msg_type,
2222           { "Message Type",
2223             "ansi_637_trans.msg_type",
2224             FT_UINT24, BASE_DEC, VALS(ansi_trans_msg_type_strings), 0xf00000,
2225             NULL, HFILL }},
2226         { &hf_ansi_637_trans_param_id,
2227             { "Transport Param ID", "ansi_637_trans.param_id",
2228             FT_UINT8, BASE_DEC, VALS(ansi_trans_param_strings), 0,
2229             NULL, HFILL }},
2230         { &hf_ansi_637_trans_length,
2231             { "Length", "ansi_637_trans.len",
2232             FT_UINT8, BASE_DEC, NULL, 0,
2233             NULL, HFILL }},
2234         { &hf_ansi_637_trans_bin_addr,
2235             { "Binary Address", "ansi_637_trans.bin_addr",
2236             FT_BYTES, BASE_NONE, 0, 0,
2237             NULL, HFILL }},
2238         };
2239     static hf_register_info hf_tele[] =
2240     {
2241         { &hf_ansi_637_tele_msg_type,
2242           { "Message Type",
2243             "ansi_637_tele.msg_type",
2244             FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_type_strings), 0xf00000,
2245             NULL, HFILL }},
2246         { &hf_ansi_637_tele_msg_id,
2247           { "Message ID",
2248             "ansi_637_tele.msg_id",
2249             FT_UINT24, BASE_DEC, NULL, 0x0ffff0,
2250             NULL, HFILL }},
2251         { &hf_ansi_637_tele_msg_status,
2252           { "Message Status",
2253             "ansi_637_tele.msg_status",
2254             FT_UINT8, BASE_DEC, VALS(ansi_tele_msg_status_strings), 0,
2255             NULL, HFILL }},
2256         { &hf_ansi_637_tele_msg_rsvd,
2257           { "Reserved",
2258             "ansi_637_tele.msg_rsvd",
2259             FT_UINT24, BASE_DEC, NULL, 0x00000f,
2260             NULL, HFILL }},
2261         { &hf_ansi_637_tele_length,
2262             { "Length", "ansi_637_tele.len",
2263             FT_UINT8, BASE_DEC, NULL, 0,
2264             NULL, HFILL }},
2265         { &hf_ansi_637_tele_subparam_id,
2266             { "Teleservice Subparam ID", "ansi_637_tele.subparam_id",
2267             FT_UINT8, BASE_DEC, VALS(ansi_tele_param_strings), 0,
2268             NULL, HFILL }},
2269     };
2270
2271     /* Setup protocol subtree array */
2272 #define NUM_INDIVIDUAL_PARAMS   3
2273     gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM];
2274
2275     memset((void *) ett, 0, sizeof(ett));
2276
2277     ett[0] = &ett_ansi_637_tele;
2278     ett[1] = &ett_ansi_637_trans;
2279     ett[2] = &ett_params;
2280
2281     for (i=0; i < NUM_TELE_PARAM; i++)
2282     {
2283         ett_ansi_637_tele_param[i] = -1;
2284         ett[NUM_INDIVIDUAL_PARAMS+i] = &ett_ansi_637_tele_param[i];
2285     }
2286
2287     for (i=0; i < NUM_TRANS_MSG_TYPE; i++)
2288     {
2289         ett_ansi_637_trans_msg[i] = -1;
2290         ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+i] = &ett_ansi_637_trans_msg[i];
2291     }
2292
2293     for (i=0; i < NUM_TRANS_PARAM; i++)
2294     {
2295         ett_ansi_637_trans_param[i] = -1;
2296         ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+i] = &ett_ansi_637_trans_param[i];
2297     }
2298
2299     /* Register the protocol name and description */
2300     proto_ansi_637_tele =
2301         proto_register_protocol(ansi_proto_name_tele, "ANSI IS-637-A Teleservice", "ansi_637_tele");
2302
2303     proto_ansi_637_trans =
2304         proto_register_protocol(ansi_proto_name_trans, "ANSI IS-637-A Transport", "ansi_637_trans");
2305
2306     register_dissector("ansi_637_tele", dissect_ansi_637_tele, proto_ansi_637_tele);
2307     register_dissector("ansi_637_trans", dissect_ansi_637_trans, proto_ansi_637_trans);
2308
2309     /* Required function calls to register the header fields and subtrees used */
2310     proto_register_field_array(proto_ansi_637_tele, hf_tele, array_length(hf_tele));
2311     proto_register_field_array(proto_ansi_637_trans, hf_trans, array_length(hf_trans));
2312     proto_register_subtree_array(ett, array_length(ett));
2313
2314     tele_dissector_table =
2315         register_dissector_table("ansi_637.tele_id",
2316             "ANSI IS-637-A Teleservice ID", FT_UINT8, BASE_DEC);
2317 }
2318
2319
2320 void
2321 proto_reg_handoff_ansi_637(void)
2322 {
2323     dissector_handle_t  ansi_637_tele_handle;
2324     dissector_handle_t  ansi_637_trans_handle;
2325     dissector_handle_t  ansi_637_trans_app_handle;
2326     guint               i;
2327
2328     ansi_637_tele_handle = create_dissector_handle(dissect_ansi_637_tele, proto_ansi_637_tele);
2329     ansi_637_trans_handle = create_dissector_handle(dissect_ansi_637_trans, proto_ansi_637_trans);
2330     ansi_637_trans_app_handle = create_dissector_handle(dissect_ansi_637_trans_app, proto_ansi_637_trans);
2331
2332     /* Dissect messages embedded in SIP */
2333     dissector_add_string("media_type","application/vnd.3gpp2.sms", ansi_637_trans_app_handle);
2334     /*
2335      * register for all known teleservices
2336      * '-1' is to stop before trailing '0' entry
2337      *
2338      * to add teleservices, modify 'ansi_tele_id_strings'
2339      */
2340     for (i=0; i < ((sizeof(ansi_tele_id_strings)/sizeof(value_string))-1); i++)
2341     {
2342         /*
2343          * ANSI MAP dissector will push out teleservice ids
2344          */
2345         dissector_add_uint("ansi_map.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
2346
2347         /*
2348          * we will push out teleservice ids after Transport layer decode
2349          */
2350         dissector_add_uint("ansi_637.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
2351     }
2352
2353     /*
2354      * ANSI A-interface will push out transport layer data
2355      */
2356     dissector_add_uint("ansi_a.sms", 0, ansi_637_trans_handle);
2357
2358     /* data_handle = find_dissector("data"); */
2359 }