Move the GSM SMS dissection to a dedicated subdissector (currently still within
[obnox/wireshark/wip.git] / 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: packet-ansi_637.c,v 1.5 2003/12/09 00:52:02 guy Exp $
13  *
14  * Ethereal - Network traffic analyzer
15  * By Gerald Combs <gerald@ethereal.com>
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 #include <stdio.h>
38 #include <stdlib.h>
39 #include <gmodule.h>
40
41 #ifdef HAVE_SYS_TYPES_H
42 # include <sys/types.h>
43 #endif
44
45 #ifdef HAVE_NETINET_IN_H
46 # include <netinet/in.h>
47 #endif
48
49 #include <string.h>
50
51 #include "epan/packet.h"
52
53
54 static char *ansi_proto_name_tele = "ANSI IS-637-A (SMS) Teleservice Layer";
55 static char *ansi_proto_name_trans = "ANSI IS-637-A (SMS) Transport Layer";
56 static char *ansi_proto_name_short = "IS-637-A";
57
58 static const value_string ansi_srvc_cat_strings[] = {
59     { 0x0000,   "Unknown or unspecified" },
60     { 0x0001,   "Emergency Broadcasts" },
61     { 0x0002,   "Administrative" },
62     { 0x0003,   "Maintenance" },
63     { 0x0004,   "General News - Local" },
64     { 0x0005,   "General News - Regional" },
65     { 0x0006,   "General News - National" },
66     { 0x0007,   "General News - International" },
67     { 0x0008,   "Business/Financial News - Local" },
68     { 0x0009,   "Business/Financial News - Regional" },
69     { 0x000A,   "Business/Financial News - National" },
70     { 0x000B,   "Business/Financial News - International" },
71     { 0x000C,   "Sports News - Local" },
72     { 0x000D,   "Sports News - Regional" },
73     { 0x000E,   "Sports News - National" },
74     { 0x000F,   "Sports News - International" },
75     { 0x0010,   "Entertainment News - Local" },
76     { 0x0011,   "Entertainment News - Regional" },
77     { 0x0012,   "Entertainment News - National" },
78     { 0x0013,   "Entertainment News - International" },
79     { 0x0014,   "Local Weather" },
80     { 0x0015,   "Area Traffic Reports" },
81     { 0x0016,   "Local Airport Flight Schedules" },
82     { 0x0017,   "Restaurants" },
83     { 0x0018,   "Lodgings" },
84     { 0x0019,   "Retail Directory" },
85     { 0x001A,   "Advertisements" },
86     { 0x001B,   "Stock Quotes" },
87     { 0x001C,   "Employment Opportunities" },
88     { 0x001D,   "Medical/Health/Hospitals" },
89     { 0x001E,   "Technology News" },
90     { 0x001F,   "Multi-category" },
91     { 0, NULL },
92 };
93
94 static const value_string ansi_tele_msg_type_strings[] = {
95     { 1,        "Deliver (mobile-terminated only)" },
96     { 2,        "Submit (mobile-originated only)" },
97     { 3,        "Cancellation (mobile-originated only)" },
98     { 4,        "Delivery Acknowledgement (mobile-terminated only)" },
99     { 5,        "User Acknowledgement (either direction)" },
100     { 0, NULL },
101 };
102
103 static const value_string ansi_tele_id_strings[] = {
104     { 1,        "Reserved for maintenance" },
105     { 4096,     "AMPS Extended Protocol Enhanced Services" },
106     { 4097,     "CDMA Cellular Paging Teleservice" },
107     { 4098,     "CDMA Cellular Messaging Teleservice" },
108     { 4099,     "CDMA Voice Mail Notification" },
109     { 32513,    "TDMA Cellular Messaging Teleservice" },
110     { 32520,    "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)" },
111     { 32584,    "TDMA Segmented System Assisted Mobile Positioning Service" },
112     { 0, NULL },
113 };
114
115 static const value_string ansi_tele_param_strings[] = {
116     { 0x00,     "Message Identifier" },
117     { 0x01,     "User Data" },
118     { 0x02,     "User Response Code" },
119     { 0x03,     "Message Center Time Stamp" },
120     { 0x04,     "Validity Period - Absolute" },
121     { 0x05,     "Validity Period - Relative" },
122     { 0x06,     "Deferred Delivery Time - Absolute" },
123     { 0x07,     "Deferred Delivery Time - Relative" },
124     { 0x08,     "Priority Indicator" },
125     { 0x09,     "Privacy Indicator" },
126     { 0x0a,     "Reply Option" },
127     { 0x0b,     "Number of Messages" },
128     { 0x0c,     "Alert on Message Delivery" },
129     { 0x0d,     "Language Indicator" },
130     { 0x0e,     "Call-Back Number" },
131     { 0x0f,     "Message Display Mode" },
132     { 0x10,     "Multiple Encoding User Data" },
133     { 0, NULL },
134 };
135
136 static const value_string ansi_trans_msg_type_strings[] = {
137     { 0,        "Point-to-Point" },
138     { 1,        "Broadcast" },
139     { 2,        "Acknowledge" },
140     { 0, NULL },
141 };
142
143 static const value_string ansi_trans_param_strings[] = {
144     { 0x00,     "Teleservice Identifier" },
145     { 0x01,     "Service Category" },
146     { 0x02,     "Originating Address" },
147     { 0x03,     "Originating Subaddress" },
148     { 0x04,     "Destination Address" },
149     { 0x05,     "Destination Subaddress" },
150     { 0x06,     "Bearer Reply Option" },
151     { 0x07,     "Cause Codes" },
152     { 0x08,     "Bearer Data" },
153     { 0, NULL },
154 };
155
156 /*
157  * from Table 2.7.1.3.2.4-4. Representation of DTMF Digits
158  * 3GPP2 C.S0005-C (IS-2000 aka cdma2000)
159  */
160 static unsigned char air_digits[] = {
161   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
162      '?','1','2','3','4','5','6','7','8','9','0','*','#','?','?'
163 };
164
165 /* Initialize the protocol and registered fields */
166 static int proto_ansi_637_tele = -1;
167 static int proto_ansi_637_trans = -1;
168 static int hf_ansi_637_none = -1;
169 static int hf_ansi_637_length = -1;
170 static int hf_ansi_637_bin_addr = -1;
171 static int hf_ansi_637_tele_msg_type = -1;
172 static int hf_ansi_637_tele_msg_id = -1;
173 static int hf_ansi_637_tele_msg_rsvd = -1;
174 static int hf_ansi_637_tele_subparam_id = -1;
175 static int hf_ansi_637_trans_msg_type = -1;
176 static int hf_ansi_637_trans_param_id = -1;
177
178 /* Initialize the subtree pointers */
179 static gint ett_ansi_637_tele = -1;
180 static gint ett_ansi_637_trans = -1;
181 static gint ett_params = -1;
182
183 static guint32 ansi_637_trans_tele_id;
184 static char ansi_637_bigbuf[1024];
185 static gchar ansi_637_add_string[1024];
186 static dissector_handle_t data_handle;
187 static dissector_table_t tele_dissector_table;
188 static packet_info *g_pinfo;
189 static proto_tree *g_tree;
190
191 /* FUNCTIONS */
192
193 static void
194 decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oct, guint8 *last_bit, gchar *buf)
195 {
196     guint8      oct, oct2, bit;
197     guint32     saved_offset;
198     guint32     i;
199
200
201     if (num_fields == 0)
202     {
203         return;
204     }
205
206     saved_offset = *offset;
207     oct = oct2 = *last_oct;
208     bit = *last_bit;
209
210     if (bit == 1)
211     {
212         oct2 = tvb_get_guint8(tvb, *offset);
213         (*offset)++;
214     }
215
216     for (i=0; i < num_fields; i++)
217     {
218         if (bit != 1)
219         {
220             oct = oct2;
221
222             /*
223              * cannot grab an octet if we are getting
224              * the last field and bit is 7 or 8
225              * because there may not be another octet
226              */
227             if (((i + 1) != num_fields) ||
228                 ((bit != 7) && (bit != 8)))
229             {
230                 oct2 = tvb_get_guint8(tvb, *offset);
231                 (*offset)++;
232             }
233         }
234
235         switch (bit)
236         {
237         case 1:
238             buf[i] = ((oct & 0x01) << 6) | ((oct2 & 0xfc) >> 2);
239             break;
240
241         case 2:
242             buf[i] = ((oct & 0x03) << 5) | ((oct2 & 0xf8) >> 3);
243             break;
244
245         case 3:
246             buf[i] = ((oct & 0x07) << 4) | ((oct2 & 0xf0) >> 4);
247             break;
248
249         case 4:
250             buf[i] = ((oct & 0x0f) << 3) | ((oct2 & 0xe0) >> 5);
251             break;
252
253         case 5:
254             buf[i] = ((oct & 0x1f) << 2) | ((oct2 & 0xc0) >> 6);
255             break;
256
257         case 6:
258             buf[i] = ((oct & 0x3f) << 1) | ((oct2 & 0x80) >> 7);
259             break;
260
261         case 7:
262             buf[i] = oct & 0x7f;
263             break;
264
265         case 8:
266             buf[i] = (oct & 0xfe) >> 1;
267             break;
268         }
269
270         bit = (bit % 8) + 1;
271     }
272
273     buf[i] = '\0';
274     *last_bit = bit;
275     *last_oct = (bit == 1) ? oct : oct2;
276 }
277
278 static gchar *
279 my_match_strval(guint32 val, const value_string *vs, gint *idx)
280 {
281     gint i = 0;
282
283     while (vs[i].strptr)
284     {
285         if (vs[i].value == val)
286         {
287             *idx = i;
288             return(vs[i].strptr);
289         }
290
291         i++;
292     }
293
294     *idx = -1;
295     return(NULL);
296 }
297
298
299 /* PARAM FUNCTIONS */
300
301 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
302     if ((edc_len) > (edc_max_len)) \
303     { \
304         proto_tree_add_text(tree, tvb, offset, \
305             (edc_len) - (edc_max_len), "Extraneous Data"); \
306     }
307
308 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
309     if ((sdc_len) < (sdc_min_len)) \
310     { \
311         proto_tree_add_text(tree, tvb, offset, \
312             (sdc_len), "Short Data (?)"); \
313         return; \
314     }
315
316 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
317     if ((edc_len) != (edc_eq_len)) \
318     { \
319         proto_tree_add_text(tree, tvb, offset, \
320             (edc_len), "Unexpected Data Length"); \
321         return; \
322     }
323
324 static void
325 tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
326 {
327     guint8      oct, oct2;
328     guint8      encoding;
329     guint8      msg_type;
330     guint8      num_fields;
331     guint8      used;
332     guint8      bit;
333     guint32     required_octs;
334     guint32     saved_offset;
335     guint32     i;
336     gchar       *str = NULL;
337
338     SHORT_DATA_CHECK(len, 2);
339
340     /*
341      * message encoding
342      */
343     oct = tvb_get_guint8(tvb, offset);
344     oct2 = 0;
345     msg_type = 0;
346     used = 0;
347
348     encoding = ((oct & 0xf8) >> 3);
349     switch (encoding)
350     {
351     case 0x00: str = "Octet, unspecified"; break;
352     case 0x01: str = "Extended Protocol Message";
353         oct2 = tvb_get_guint8(tvb, offset+1);
354         msg_type = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
355         break;
356     case 0x02: str = "7-bit ASCII"; break;
357     case 0x03: str = "IA5"; break;
358     case 0x04: str = "UNICODE"; break;
359     case 0x05: str = "Shift-JIS"; break;
360     case 0x06: str = "Korean"; break;
361     case 0x07: str = "Latin/Hebrew"; break;
362     case 0x08: str = "Latin"; break;
363     case 0x09: str = "GSM 7-bit default alphabet"; break;
364     default: str = "Reserved"; break;
365     }
366
367     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
368     proto_tree_add_text(tree, tvb, offset, 1,
369         "%s :  Encoding: %s",
370         ansi_637_bigbuf,
371         str);
372
373     if (encoding == 0x01)
374     {
375         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
376         proto_tree_add_text(tree, tvb, offset, 1,
377             "%s :  Message type: see TIA/EIA/IS-91 (%d)",
378             ansi_637_bigbuf,
379             msg_type);
380
381         other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
382         proto_tree_add_text(tree, tvb, offset+1, 1,
383             "%s :  Message type",
384             ansi_637_bigbuf);
385
386         oct = oct2;
387         offset++;
388         used++;
389     }
390
391     offset++;
392     used++;
393
394     /*
395      * number of fields
396      */
397     oct2 = tvb_get_guint8(tvb, offset);
398     num_fields = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
399
400     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
401     proto_tree_add_text(tree, tvb, offset-1, 1,
402         "%s :  Number of fields (MSB): %d",
403         ansi_637_bigbuf,
404         num_fields);
405
406     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
407     proto_tree_add_text(tree, tvb, offset, 1,
408         "%s :  Number of fields (LSB)",
409         ansi_637_bigbuf);
410
411     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
412     proto_tree_add_text(tree, tvb, offset, 1,
413         "%s :  Most significant bits of first field",
414         ansi_637_bigbuf);
415
416     offset++;
417     used++;
418     oct = oct2;
419
420     /* NOTE: there are now 3 bits remaining in 'oct' */
421
422     if (len - used <= 0) return;
423
424     /*
425      * decode rest if 7-bit ASCII
426      */
427     if (encoding == 0x02)
428     {
429         /*
430          * magic numbers:
431          *      3 bits remaining from last octet
432          *      7 bit encoding
433          *      8 bits per octet
434          */
435         i = (num_fields * 7) - 3;
436         required_octs = (i / 8) + ((i % 8) ? 1 : 0);
437
438         if (required_octs + used > len)
439         {
440             proto_tree_add_text(tree, tvb, offset, 1,
441                 "Missing %d octet(s) for number of fields",
442                 (required_octs + used) - len);
443
444             return;
445         }
446
447         bit = 3;
448         saved_offset = offset;
449
450         decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
451
452         proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
453             "Encoded user data: %s",
454             ansi_637_bigbuf);
455
456         switch (bit)
457         {
458         case 1: oct2 = 0x01; break;
459         case 2: oct2 = 0x03; break;
460         case 3: oct2 = 0x07; break;
461         case 4: oct2 = 0x0f; break;
462         case 5: oct2 = 0x1f; break;
463         case 6: oct2 = 0x3f; break;
464         case 7: oct2 = 0x7f; break;
465         }
466
467         if (bit != 8)
468         {
469             other_decode_bitfield_value(ansi_637_bigbuf, oct, oct2, 8);
470             proto_tree_add_text(tree, tvb, offset - 1, 1,
471                 "%s :  Reserved",
472                 ansi_637_bigbuf);
473         }
474     }
475     else
476     {
477         proto_tree_add_text(tree, tvb, offset, len - used,
478             "Encoded user data");
479     }
480 }
481
482 static void
483 tele_param_rsp_code(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
484 {
485     guint8      oct;
486
487     EXACT_DATA_CHECK(len, 1);
488
489     /*
490      * response code
491      */
492     oct = tvb_get_guint8(tvb, offset);
493
494     proto_tree_add_text(tree, tvb, offset, 1,
495         "Response code: %d",
496         oct);
497 }
498
499 static void
500 tele_param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
501 {
502     guint8      oct, oct2, oct3;
503
504     EXACT_DATA_CHECK(len, 6);
505
506     oct = tvb_get_guint8(tvb, offset);
507     oct2 = tvb_get_guint8(tvb, offset+1);
508     oct3 = tvb_get_guint8(tvb, offset+2);
509
510     proto_tree_add_text(tree, tvb, offset, 3,
511         "Year %d%d, Month %d%d, Day %d%d",
512         (oct & 0xf0) >> 4,
513         oct & 0x0f,
514         (oct2 & 0xf0) >> 4,
515         oct2 & 0x0f,
516         (oct3 & 0xf0) >> 4,
517         oct3 & 0x0f);
518
519     offset += 3;
520
521     oct = tvb_get_guint8(tvb, offset);
522     oct2 = tvb_get_guint8(tvb, offset+1);
523     oct3 = tvb_get_guint8(tvb, offset+2);
524
525     proto_tree_add_text(tree, tvb, offset, 3,
526         "Hour %d%d, Minutes %d%d, Seconds %d%d",
527         (oct & 0xf0) >> 4,
528         oct & 0x0f,
529         (oct2 & 0xf0) >> 4,
530         oct2 & 0x0f,
531         (oct3 & 0xf0) >> 4,
532         oct3 & 0x0f);
533 }
534
535 static void
536 tele_param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
537 {
538     guint8      oct;
539     guint32     value = 0;
540     gchar       *str = NULL;
541     gchar       *str2 = NULL;
542
543     EXACT_DATA_CHECK(len, 1);
544
545     oct = tvb_get_guint8(tvb, offset);
546
547     switch (oct)
548     {
549     case 245: str = "Indefinite"; break;
550     case 246: str = "Immediate"; break;
551     case 247: str = "Valid until mobile becomes inactive/Deliver when mobile next becomes active"; break;
552     case 248: str = "Valid until registration area changes, discard if not registered" ; break;
553     default:
554         if (oct <= 143) { value = (oct + 1) * 5; str2 = "Minutes"; break; }
555         else if ((oct >= 144) && (oct <= 167)) { value = (oct - 143) * 30; str2 = "Minutes + 12 Hours"; break; }
556         else if ((oct >= 168) && (oct <= 196)) { value = oct - 166; str2 = "Days"; break; }
557         else if ((oct >= 197) && (oct <= 244)) { value = oct - 192; str2 = "Weeks"; break; }
558         else { str = "Reserved"; break; }
559     }
560
561     if (str == NULL)
562     {
563         proto_tree_add_text(tree, tvb, offset, 1,
564             str2);
565     }
566     else
567     {
568         proto_tree_add_text(tree, tvb, offset, 1,
569             "%d %s",
570             value, str2);
571     }
572 }
573
574 static void
575 tele_param_pri_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
576 {
577     guint8      oct;
578     gchar       *str = NULL;
579
580     EXACT_DATA_CHECK(len, 1);
581
582     oct = tvb_get_guint8(tvb, offset);
583
584     switch ((oct & 0xc0) >> 6)
585     {
586     case 0: str = "Normal"; break;
587     case 1: str = "Interactive"; break;
588     case 2: str = "Urgent"; break;
589     case 3: str = "Emergency"; break;
590     }
591
592     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
593     proto_tree_add_text(tree, tvb, offset, 1,
594         "%s :  %s",
595         ansi_637_bigbuf,
596         str);
597
598     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
599     proto_tree_add_text(tree, tvb, offset, 1,
600         "%s :  Reserved",
601         ansi_637_bigbuf);
602 }
603
604 static void
605 tele_param_priv_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
606 {
607     guint8      oct;
608     gchar       *str = NULL;
609
610     EXACT_DATA_CHECK(len, 1);
611
612     oct = tvb_get_guint8(tvb, offset);
613
614     switch ((oct & 0xc0) >> 6)
615     {
616     case 0: str = "Not restricted (privacy level 0)"; break;
617     case 1: str = "Restricted (privacy level 1)"; break;
618     case 2: str = "Confidential (privacy level 2)"; break;
619     case 3: str = "Secret (privacy level 3)"; break;
620     }
621
622     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
623     proto_tree_add_text(tree, tvb, offset, 1,
624         "%s :  %s",
625         ansi_637_bigbuf,
626         str);
627
628     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
629     proto_tree_add_text(tree, tvb, offset, 1,
630         "%s :  Reserved",
631         ansi_637_bigbuf);
632 }
633
634 static void
635 tele_param_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
636 {
637     guint8      oct;
638
639     EXACT_DATA_CHECK(len, 1);
640
641     oct = tvb_get_guint8(tvb, offset);
642
643     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
644     proto_tree_add_text(tree, tvb, offset, 1,
645         "%s :  %s (manual) acknowledgment is requested",
646         ansi_637_bigbuf,
647         (oct & 0x80) ? "User" : "No user");
648
649     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
650     proto_tree_add_text(tree, tvb, offset, 1,
651         "%s :  %s acknowledgment requested",
652         ansi_637_bigbuf,
653         (oct & 0x40) ? "Delivery" : "No delivery");
654
655     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
656     proto_tree_add_text(tree, tvb, offset, 1,
657         "%s :  Reserved",
658         ansi_637_bigbuf);
659 }
660
661 static void
662 tele_param_num_messages(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
663 {
664     guint8      oct;
665
666     EXACT_DATA_CHECK(len, 1);
667
668     oct = tvb_get_guint8(tvb, offset);
669
670     proto_tree_add_text(tree, tvb, offset, 1,
671         "Number of voice mail messages: %d%d",
672         (oct & 0xf0) >> 4,
673         oct & 0x0f);
674 }
675
676 static void
677 tele_param_alert(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
678 {
679     guint8      oct;
680     gchar       *str = NULL;
681
682     EXACT_DATA_CHECK(len, 1);
683
684     oct = tvb_get_guint8(tvb, offset);
685
686     switch ((oct & 0xc0) >> 6)
687     {
688     case 0: str = "Use Mobile default alert"; break;
689     case 1: str = "Use Low-priority alert"; break;
690     case 2: str = "Use Medium-priority alert"; break;
691     case 3: str = "Use High-priority alert"; break;
692     }
693
694     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
695     proto_tree_add_text(tree, tvb, offset, 1,
696         "%s :  %s",
697         ansi_637_bigbuf,
698         str);
699
700     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
701     proto_tree_add_text(tree, tvb, offset, 1,
702         "%s :  Reserved",
703         ansi_637_bigbuf);
704 }
705
706 static void
707 tele_param_lang_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
708 {
709     guint8      oct;
710     gchar       *str = NULL;
711
712     EXACT_DATA_CHECK(len, 1);
713
714     oct = tvb_get_guint8(tvb, offset);
715
716     switch (oct)
717     {
718     case 0x00: str = "Unknown or unspecified"; break;
719     case 0x01: str = "English"; break;
720     case 0x02: str = "French"; break;
721     case 0x03: str = "Spanish"; break;
722     case 0x04: str = "Japanese"; break;
723     case 0x05: str = "Korean"; break;
724     case 0x06: str = "Chinese"; break;
725     case 0x07: str = "Hebrew"; break;
726     default: str = "Reserved"; break;
727     }
728
729     proto_tree_add_text(tree, tvb, offset, 1,
730         str);
731 }
732
733 static void
734 tele_param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
735 {
736     guint8      oct, oct2, num_fields, odd;
737     guint32     saved_offset;
738     guint32     required_octs;
739     guint32     i;
740
741     SHORT_DATA_CHECK(len, 2);
742
743     oct = tvb_get_guint8(tvb, offset);
744
745     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
746     proto_tree_add_text(tree, tvb, offset, 1,
747         "%s :  Digit mode: %s",
748         ansi_637_bigbuf,
749         (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
750
751     if (oct & 0x80)
752     {
753         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x70, 8);
754         proto_tree_add_text(tree, tvb, offset, 1,
755             "%s :  Type of number: (%d)",
756             ansi_637_bigbuf,
757             (oct & 0x70) >> 4);
758
759         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
760         proto_tree_add_text(tree, tvb, offset, 1,
761             "%s :  Numbering plan: (%d)",
762             ansi_637_bigbuf,
763             oct & 0x0f);
764
765         offset++;
766         num_fields = tvb_get_guint8(tvb, offset);
767
768         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xff, 8);
769         proto_tree_add_text(tree, tvb, offset, 1,
770             "%s :  Number of fields: (%d)",
771             ansi_637_bigbuf,
772             num_fields);
773
774         if (num_fields == 0) return;
775
776         if (num_fields > (len - 2))
777         {
778             proto_tree_add_text(tree, tvb, offset, 1,
779                 "Missing %d octet(s) for number of fields",
780                 (num_fields + 2) - len);
781
782             return;
783         }
784
785         offset++;
786
787         i = 0;
788         while (i < num_fields)
789         {
790             ansi_637_bigbuf[i] = tvb_get_guint8(tvb, offset+i) & 0x7f;
791             i++;
792         }
793         ansi_637_bigbuf[i] = '\0';
794
795         proto_tree_add_text(tree, tvb, offset, num_fields,
796             "Number: %s",
797             ansi_637_bigbuf);
798     }
799     else
800     {
801         offset++;
802         num_fields = (oct & 0x7f) << 1;
803         oct2 = tvb_get_guint8(tvb, offset);
804         num_fields |= ((oct2 & 0x80) >> 7);
805
806         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
807         proto_tree_add_text(tree, tvb, offset-1, 1,
808             "%s :  Number of fields (MBS): (%d)",
809             ansi_637_bigbuf,
810             num_fields);
811
812         other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
813         proto_tree_add_text(tree, tvb, offset, 1,
814             "%s :  Number of fields (LSB)",
815             ansi_637_bigbuf);
816
817         oct = oct2;
818         odd = FALSE;
819
820         if (num_fields > 0)
821         {
822             i = (num_fields - 1) * 4;
823             required_octs = (i / 8) + ((i % 8) ? 1 : 0);
824
825             if (required_octs + 2 > len)
826             {
827                 proto_tree_add_text(tree, tvb, offset, 1,
828                     "Missing %d octet(s) for number of fields",
829                     (required_octs + 2) - len);
830
831                 return;
832             }
833
834             odd = num_fields & 0x01;
835             memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
836             saved_offset = offset;
837             offset++;
838
839             i = 0;
840             while (i < num_fields)
841             {
842                 ansi_637_bigbuf[i] =
843                     air_digits[(oct & 0x78) >> 3];
844
845                 i++;
846                 if (i >= num_fields) break;
847
848                 oct2 = tvb_get_guint8(tvb, offset);
849                 offset++;
850
851                 ansi_637_bigbuf[i] =
852                     air_digits[((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)];
853
854                 oct = oct2;
855
856                 i++;
857             }
858
859             proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
860                 "Number: %s",
861                 ansi_637_bigbuf);
862         }
863
864         other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x07: 0x7f, 8);
865         proto_tree_add_text(tree, tvb, offset, 1,
866             "%s :  Reserved",
867             ansi_637_bigbuf);
868     }
869 }
870
871 static void
872 tele_param_disp_mode(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
873 {
874     guint8      oct;
875     gchar       *str = NULL;
876
877     EXACT_DATA_CHECK(len, 1);
878
879     oct = tvb_get_guint8(tvb, offset);
880
881     switch ((oct & 0xc0) >> 6)
882     {
883     case 0: str = "Immediate Display: The mobile station is to display the received message as soon as possible."; break;
884     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;
885     case 2: str = "User Invoke: The mobile station is to display the received message based on the mode selected by the user."; break;
886     case 3: str = "Reserved"; break;
887     }
888
889     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
890     proto_tree_add_text(tree, tvb, offset, 1,
891         "%s :  %s",
892         ansi_637_bigbuf,
893         str);
894
895     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
896     proto_tree_add_text(tree, tvb, offset, 1,
897         "%s :  Reserved",
898         ansi_637_bigbuf);
899 }
900
901 #define NUM_TELE_PARAM (sizeof(ansi_tele_param_strings)/sizeof(value_string))
902 static gint ett_ansi_637_tele_param[NUM_TELE_PARAM];
903 static void (*ansi_637_tele_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
904     NULL,                       /* Message Identifier */
905     tele_param_user_data,       /* User Data */
906     tele_param_rsp_code,        /* User Response Code */
907     tele_param_timestamp,       /* Message Center Time Stamp */
908     tele_param_timestamp,       /* Validity Period  Absolute */
909     tele_param_rel_timestamp,   /* Validity Period  Relative */
910     tele_param_timestamp,       /* Deferred Delivery Time - Absolute */
911     tele_param_rel_timestamp,   /* Deferred Delivery Time - Relative */
912     tele_param_pri_ind,         /* Priority Indicator */
913     tele_param_priv_ind,        /* Privacy Indicator */
914     tele_param_reply_opt,       /* Reply Option */
915     tele_param_num_messages,    /* Number of Messages */
916     tele_param_alert,           /* Alert on Message Delivery */
917     tele_param_lang_ind,        /* Language Indicator */
918     tele_param_cb_num,          /* Call-Back Number */
919     tele_param_disp_mode,       /* Message Display Mode */
920     NULL,                       /* Multiple Encoding User Data */
921     NULL,                       /* NONE */
922 };
923
924 static void
925 trans_param_tele_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
926 {
927     guint32     value;
928     gchar       *str = NULL;
929
930     EXACT_DATA_CHECK(len, 2);
931
932     value = tvb_get_ntohs(tvb, offset);
933
934     ansi_637_trans_tele_id = value;
935
936     str = match_strval(value, ansi_tele_id_strings);
937
938     if (NULL == str) str = "Unrecognized Teleservice ID";
939
940     proto_tree_add_text(tree, tvb, offset, 2,
941         "%s (%d)",
942         str,
943         value);
944
945     sprintf(add_string, " - %s (%d)", str, value);
946 }
947
948 static void
949 trans_param_srvc_cat(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
950 {
951     guint32     value;
952     gchar       *str = NULL;
953
954     EXACT_DATA_CHECK(len, 2);
955
956     value = tvb_get_ntohs(tvb, offset);
957
958     str = match_strval(value, ansi_srvc_cat_strings);
959
960     if (NULL == str) str = "Reserved";
961
962     proto_tree_add_text(tree, tvb, offset, 2,
963         str);
964
965     sprintf(add_string, " - %s (%d)", str, value);
966 }
967
968 static void
969 trans_param_address(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
970 {
971     guint8      oct, oct2, num_fields, odd;
972     gboolean    email_addr;
973     guint32     saved_offset;
974     guint32     required_octs;
975     guint32     i;
976     gchar       *str;
977
978     SHORT_DATA_CHECK(len, 2);
979
980     add_string = add_string;
981     email_addr = FALSE;
982
983     oct = tvb_get_guint8(tvb, offset);
984
985     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
986     proto_tree_add_text(tree, tvb, offset, 1,
987         "%s :  Digit mode: %s",
988         ansi_637_bigbuf,
989         (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
990
991     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
992     proto_tree_add_text(tree, tvb, offset, 1,
993         "%s :  Number mode: %s",
994         ansi_637_bigbuf,
995         (oct & 0x40) ? "Data Network Address" : "ANSI T1.607");
996
997     if (oct & 0x80)
998     {
999         if (oct & 0x40)
1000         {
1001             switch ((oct & 0x38) >> 3)
1002             {
1003             case 0: str = "Unknown"; break;
1004             case 1: str = "Internet Protocol (RFC 791)"; break;
1005             case 2: str = "Internet Email Address (RFC 822)"; email_addr = TRUE; break;
1006             default:
1007                 str = "Reserved";
1008                 break;
1009             }
1010
1011             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
1012             proto_tree_add_text(tree, tvb, offset, 1,
1013                 "%s :  Type of number: %s (%d)",
1014                 ansi_637_bigbuf,
1015                 str,
1016                 (oct & 0x38) >> 3);
1017
1018             offset++;
1019             num_fields = (oct & 0x07) << 5;
1020             oct2 = tvb_get_guint8(tvb, offset);
1021             num_fields |= ((oct2 & 0xf8) >> 3);
1022
1023             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
1024             proto_tree_add_text(tree, tvb, offset-1, 1,
1025                 "%s :  Number of fields (MSB): (%d)",
1026                 ansi_637_bigbuf,
1027                 num_fields);
1028
1029             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
1030             proto_tree_add_text(tree, tvb, offset, 1,
1031                 "%s :  Number of fields (LSB)",
1032                 ansi_637_bigbuf);
1033
1034             if (num_fields == 0) return;
1035
1036             if (num_fields > (len - 2))
1037             {
1038                 proto_tree_add_text(tree, tvb, offset, 1,
1039                     "Missing %d octet(s) for number of fields",
1040                     (num_fields + 2) - len);
1041
1042                 return;
1043             }
1044
1045             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
1046             proto_tree_add_text(tree, tvb, offset, 1,
1047                 "%s :  Most significant bits of first field",
1048                 ansi_637_bigbuf);
1049
1050             offset++;
1051             oct = oct2;
1052
1053             i = 0;
1054             while (i < num_fields)
1055             {
1056                 ansi_637_bigbuf[i] = (oct & 0x07) << 5;
1057                 ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf8) >> 3;
1058                 i++;
1059             }
1060             ansi_637_bigbuf[i] = '\0';
1061
1062             if (email_addr)
1063             {
1064                 proto_tree_add_text(tree, tvb, offset, num_fields - 1,
1065                     "Number: %s",
1066                     ansi_637_bigbuf);
1067             }
1068             else
1069             {
1070                 proto_tree_add_bytes(tree, hf_ansi_637_bin_addr, tvb, offset, num_fields - 1,
1071                     ansi_637_bigbuf);
1072             }
1073
1074             offset += (num_fields - 1);
1075
1076             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
1077             proto_tree_add_text(tree, tvb, offset, 1,
1078                 "%s :  Least significant bits of last field",
1079                 ansi_637_bigbuf);
1080
1081             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
1082             proto_tree_add_text(tree, tvb, offset, 1,
1083                 "%s :  Reserved",
1084                 ansi_637_bigbuf);
1085         }
1086         else
1087         {
1088             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
1089             proto_tree_add_text(tree, tvb, offset, 1,
1090                 "%s :  Type of number: (%d)",
1091                 ansi_637_bigbuf,
1092                 (oct & 0x38) >> 3);
1093
1094             oct2 = tvb_get_guint8(tvb, offset + 1);
1095
1096             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
1097             proto_tree_add_text(tree, tvb, offset, 1,
1098                 "%s :  Numbering plan (MSB): (%d)",
1099                 ansi_637_bigbuf,
1100                 ((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7));
1101
1102             offset++;
1103             oct = oct2;
1104
1105             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
1106             proto_tree_add_text(tree, tvb, offset, 1,
1107                 "%s :  Numbering plan (LSB)",
1108                 ansi_637_bigbuf);
1109
1110             offset++;
1111             num_fields = (oct & 0x7f) << 1;
1112             oct2 = tvb_get_guint8(tvb, offset);
1113             num_fields |= ((oct2 & 0x80) >> 7);
1114
1115             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
1116             proto_tree_add_text(tree, tvb, offset-1, 1,
1117                 "%s :  Number of fields (MSB): (%d)",
1118                 ansi_637_bigbuf,
1119                 num_fields);
1120
1121             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
1122             proto_tree_add_text(tree, tvb, offset, 1,
1123                 "%s :  Number of fields (LSB)",
1124                 ansi_637_bigbuf);
1125
1126             if (num_fields == 0) return;
1127
1128             if (num_fields > (len - 3))
1129             {
1130                 proto_tree_add_text(tree, tvb, offset, 1,
1131                     "Missing %d octet(s) for number of fields",
1132                     (num_fields + 3) - len);
1133
1134                 return;
1135             }
1136
1137             other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x7f, 8);
1138             proto_tree_add_text(tree, tvb, offset, 1,
1139                 "%s :  Most significant bits of first field",
1140                 ansi_637_bigbuf);
1141
1142             offset++;
1143             oct = oct2;
1144
1145             i = 0;
1146             while (i < num_fields)
1147             {
1148                 ansi_637_bigbuf[i] = (oct & 0x7f) << 1;
1149                 ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0x80) >> 7;
1150                 i++;
1151             }
1152             ansi_637_bigbuf[i] = '\0';
1153
1154             proto_tree_add_text(tree, tvb, offset, num_fields - 1,
1155                 "Number: %s",
1156                 ansi_637_bigbuf);
1157
1158             offset += (num_fields - 1);
1159
1160             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
1161             proto_tree_add_text(tree, tvb, offset, 1,
1162                 "%s :  Least significant bit of last field",
1163                 ansi_637_bigbuf);
1164
1165             other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
1166             proto_tree_add_text(tree, tvb, offset, 1,
1167                 "%s :  Reserved",
1168                 ansi_637_bigbuf);
1169         }
1170     }
1171     else
1172     {
1173         offset++;
1174         num_fields = (oct & 0x3f) << 2;
1175         oct2 = tvb_get_guint8(tvb, offset);
1176         num_fields |= ((oct2 & 0xc0) >> 6);
1177
1178         other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
1179         proto_tree_add_text(tree, tvb, offset-1, 1,
1180             "%s :  Number of fields (MSB): (%d)",
1181             ansi_637_bigbuf,
1182             num_fields);
1183
1184         other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xc0, 8);
1185         proto_tree_add_text(tree, tvb, offset, 1,
1186             "%s :  Number of fields (LSB)",
1187             ansi_637_bigbuf);
1188
1189         oct = oct2;
1190         odd = FALSE;
1191
1192         if (num_fields > 0)
1193         {
1194             i = (num_fields - 1) * 4;
1195             required_octs = (i / 8) + ((i % 8) ? 1 : 0);
1196
1197             if (required_octs + 2 > len)
1198             {
1199                 proto_tree_add_text(tree, tvb, offset, 1,
1200                     "Missing %d octet(s) for number of fields",
1201                     (required_octs + 2) - len);
1202
1203                 return;
1204             }
1205
1206             odd = num_fields & 0x01;
1207             memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
1208             saved_offset = offset;
1209             offset++;
1210
1211             i = 0;
1212             while (i < num_fields)
1213             {
1214                 ansi_637_bigbuf[i] =
1215                     air_digits[(oct & 0x3c) >> 2];
1216
1217                 i++;
1218                 if (i >= num_fields) break;
1219
1220                 oct2 = tvb_get_guint8(tvb, offset);
1221                 offset++;
1222
1223                 ansi_637_bigbuf[i] =
1224                     air_digits[((oct & 0x03) << 2) | ((oct2 & 0xc0) >> 6)];
1225
1226                 oct = oct2;
1227
1228                 i++;
1229             }
1230
1231             proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
1232                 "Number: %s",
1233                 ansi_637_bigbuf);
1234         }
1235
1236         other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x03: 0x3f, 8);
1237         proto_tree_add_text(tree, tvb, offset, 1,
1238             "%s :  Reserved",
1239             ansi_637_bigbuf);
1240     }
1241 }
1242
1243 static void
1244 trans_param_subaddress(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
1245 {
1246     guint8      oct, oct2, num_fields;
1247     guint32     i;
1248     gchar       *str;
1249
1250     SHORT_DATA_CHECK(len, 2);
1251
1252     add_string = add_string;
1253
1254     oct = tvb_get_guint8(tvb, offset);
1255
1256     switch ((oct & 0xe0) >> 5)
1257     {
1258     case 0: str = "NSAP (CCITT Recommendation X.213 or ISO 8348 AD2)"; break;
1259     case 1: str = "User-specified"; break;
1260     default:
1261         str = "Reserved";
1262         break;
1263     }
1264
1265     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xe0, 8);
1266     proto_tree_add_text(tree, tvb, offset, 1,
1267         "%s :  Type: %s",
1268         ansi_637_bigbuf,
1269         str);
1270
1271     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x10, 8);
1272     proto_tree_add_text(tree, tvb, offset, 1,
1273         "%s :  Odd",
1274         ansi_637_bigbuf);
1275
1276     offset++;
1277     num_fields = (oct & 0x0f) << 4;
1278     oct2 = tvb_get_guint8(tvb, offset);
1279     num_fields |= ((oct2 & 0xf0) >> 4);
1280
1281     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
1282     proto_tree_add_text(tree, tvb, offset-1, 1,
1283         "%s :  Number of fields (MSB): (%d)",
1284         ansi_637_bigbuf,
1285         num_fields);
1286
1287     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf0, 8);
1288     proto_tree_add_text(tree, tvb, offset, 1,
1289         "%s :  Number of fields (LSB)",
1290         ansi_637_bigbuf);
1291
1292     if (num_fields == 0) return;
1293
1294     if (num_fields > (len - 2))
1295     {
1296         proto_tree_add_text(tree, tvb, offset, 1,
1297             "Missing %d octet(s) for number of fields",
1298             (num_fields + 2) - len);
1299
1300         return;
1301     }
1302
1303     other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x0f, 8);
1304     proto_tree_add_text(tree, tvb, offset, 1,
1305         "%s :  Most significant bits of first field",
1306         ansi_637_bigbuf);
1307
1308     offset++;
1309     oct = oct2;
1310
1311     i = 0;
1312     while (i < num_fields)
1313     {
1314         ansi_637_bigbuf[i] = (oct & 0x0f) << 4;
1315         ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf0) >> 4;
1316         i++;
1317     }
1318     ansi_637_bigbuf[i] = '\0';
1319
1320     proto_tree_add_bytes(tree, hf_ansi_637_bin_addr, tvb, offset, num_fields - 1,
1321         ansi_637_bigbuf);
1322
1323     offset += (num_fields - 1);
1324
1325     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf0, 8);
1326     proto_tree_add_text(tree, tvb, offset, 1,
1327         "%s :  Least significant bits of last field",
1328         ansi_637_bigbuf);
1329
1330     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
1331     proto_tree_add_text(tree, tvb, offset, 1,
1332         "%s :  Reserved",
1333         ansi_637_bigbuf);
1334 }
1335
1336 static void
1337 trans_param_bearer_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
1338 {
1339     guint8      oct;
1340
1341     len = len;
1342     oct = tvb_get_guint8(tvb, offset);
1343
1344     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
1345     proto_tree_add_text(tree, tvb, offset, 1,
1346         "%s :  Reply Sequence Number: %d",
1347         ansi_637_bigbuf,
1348         (oct & 0xfc) >> 2);
1349
1350     sprintf(add_string, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
1351
1352     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
1353     proto_tree_add_text(tree, tvb, offset, 1,
1354         "%s :  Reserved",
1355         ansi_637_bigbuf);
1356 }
1357
1358 static void
1359 trans_param_cause_codes(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
1360 {
1361     guint8      oct;
1362     gchar       *str = NULL;
1363
1364     oct = tvb_get_guint8(tvb, offset);
1365
1366     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
1367     proto_tree_add_text(tree, tvb, offset, 1,
1368         "%s :  Reply Sequence Number: %d",
1369         ansi_637_bigbuf,
1370         (oct & 0xfc) >> 2);
1371
1372     switch (oct & 0x03)
1373     {
1374     case 0x00: str = "No error"; break;
1375     case 0x02: str = "Temporary Condition"; break;
1376     case 0x03: str = "Permanent Condition"; break;
1377     default:
1378         str = "Reserved";
1379         break;
1380     }
1381
1382     sprintf(add_string, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
1383
1384     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
1385     proto_tree_add_text(tree, tvb, offset, 1,
1386         "%s :  Error Class: %s",
1387         ansi_637_bigbuf,
1388         str);
1389
1390     offset++;
1391
1392     if (!(oct & 0x03)) return;
1393
1394     if (len == 1) return;
1395
1396     oct = tvb_get_guint8(tvb, offset);
1397
1398     switch (oct)
1399     {
1400     case 0: str = "Address vacant"; break;
1401     case 1: str = "Address translation failure"; break;
1402     case 2: str = "Network resource shortage"; break;
1403     case 3: str = "Network failure"; break;
1404     case 4: str = "Invalid Teleservice ID"; break;
1405     case 5: str = "Other network problem"; break;
1406     case 6: str = "Unsupported network interface"; break;
1407     case 32: str = "No page response"; break;
1408     case 33: str = "Destination busy"; break;
1409     case 34: str = "No acknowledgement"; break;
1410     case 35: str = "Destination resource shortage"; break;
1411     case 36: str = "SMS delivery postponed"; break;
1412     case 37: str = "Destination out of service"; break;
1413     case 38: str = "Destination no longer at this address"; break;
1414     case 39: str = "Other terminal problem"; break;
1415     case 64: str = "Radio interface resource shortage"; break;
1416     case 65: str = "Radio interface incompatibility"; break;
1417     case 66: str = "Other radio interface problem"; break;
1418     case 67: str = "Unsupported Base Station Capability"; break;
1419     case 96: str = "Encoding problem"; break;
1420     case 97: str = "Service origination denied"; break;
1421     case 98: str = "Service termination denied"; break;
1422     case 99: str = "Supplementary service not supported"; break;
1423     case 100: str = "Service not supported"; break;
1424     case 101: str = "Reserved"; break;
1425     case 102: str = "Missing expected parameter"; break;
1426     case 103: str = "Missing mandatory parameter"; break;
1427     case 104: str = "Unrecognized parameter value"; break;
1428     case 105: str = "Unexpected parameter value"; break;
1429     case 106: str = "User Data size error"; break;
1430     case 107: str = "Other general problems"; break;
1431     case 108: str = "Session not active"; break;
1432     default:
1433         if ((oct >= 7) && (oct <= 31)) { str = "Reserved, treat as Other network problem"; }
1434         else if ((oct >= 40) && (oct <= 47)) { str = "Reserved, treat as Other terminal problem"; }
1435         else if ((oct >= 48) && (oct <= 63)) { str = "Reserved, treat as SMS delivery postponed"; }
1436         else if ((oct >= 68) && (oct <= 95)) { str = "Reserved, treat as Other radio interface problem"; }
1437         else if ((oct >= 109) && (oct <= 223)) { str = "Reserved, treat as Other general problems"; }
1438         else { str = "Reserved for protocol extension, treat as Other general problems"; }
1439         break;
1440     }
1441
1442     proto_tree_add_text(tree, tvb, offset, 1,
1443         str);
1444 }
1445
1446 static void
1447 trans_param_bearer_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
1448 {
1449     tvbuff_t    *tele_tvb;
1450
1451     add_string = add_string;
1452
1453     proto_tree_add_text(tree, tvb, offset, len,
1454         "Bearer Data");
1455
1456     /*
1457      * dissect the embedded teleservice data
1458      */
1459     tele_tvb = tvb_new_subset(tvb, offset, len, len);
1460
1461     dissector_try_port(tele_dissector_table, ansi_637_trans_tele_id,
1462         tele_tvb, g_pinfo, g_tree);
1463 }
1464
1465 #define NUM_TRANS_PARAM (sizeof(ansi_trans_param_strings)/sizeof(value_string))
1466 static gint ett_ansi_637_trans_param[NUM_TRANS_PARAM];
1467 static void (*ansi_637_trans_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string) = {
1468     trans_param_tele_id,        /* Teleservice Identifier */
1469     trans_param_srvc_cat,       /* Service Category */
1470     trans_param_address,        /* Originating Address */
1471     trans_param_subaddress,     /* Originating Subaddress */
1472     trans_param_address,        /* Destination Address */
1473     trans_param_subaddress,     /* Destination Subaddress */
1474     trans_param_bearer_reply_opt,       /* Bearer Reply Option */
1475     trans_param_cause_codes,    /* Cause Codes */
1476     trans_param_bearer_data,    /* Bearer Data */
1477     NULL,       /* NONE */
1478 };
1479
1480 #define NUM_TRANS_MSG_TYPE (sizeof(ansi_trans_msg_type_strings)/sizeof(value_string))
1481 static gint ett_ansi_637_trans_msg[NUM_TRANS_MSG_TYPE];
1482
1483 /* GENERIC IS-637 DISSECTOR FUNCTIONS */
1484
1485 static gboolean
1486 dissect_ansi_637_tele_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
1487 {
1488     void (*param_fcn)(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = NULL;
1489     guint8      oct;
1490     guint8      len;
1491     guint32     curr_offset;
1492     gint        ett_param_idx, idx;
1493     proto_tree  *subtree;
1494     proto_item  *item;
1495     gchar       *str = NULL;
1496
1497
1498     curr_offset = *offset;
1499
1500     oct = tvb_get_guint8(tvb, curr_offset);
1501     str = my_match_strval((guint32) oct, ansi_tele_param_strings, &idx);
1502
1503     if (NULL == str)
1504     {
1505         return(FALSE);
1506     }
1507
1508     ett_param_idx = ett_ansi_637_tele_param[idx];
1509     param_fcn = ansi_637_tele_param_fcn[idx];
1510
1511     item =
1512         proto_tree_add_text(tree, tvb, curr_offset, -1, str);
1513
1514     subtree = proto_item_add_subtree(item, ett_param_idx);
1515
1516     proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id,
1517         tvb, curr_offset, 1, oct);
1518
1519     curr_offset++;
1520
1521     len = tvb_get_guint8(tvb, curr_offset);
1522
1523     proto_item_set_len(item, (curr_offset - *offset) + len + 1);
1524
1525     proto_tree_add_uint(subtree, hf_ansi_637_length,
1526         tvb, curr_offset, 1, len);
1527
1528     curr_offset++;
1529
1530     if (len > 0)
1531     {
1532         if (param_fcn == NULL)
1533         {
1534             proto_tree_add_text(subtree, tvb, curr_offset,
1535                 len, "Parameter Data");
1536         }
1537         else
1538         {
1539             (*param_fcn)(tvb, subtree, len, curr_offset);
1540         }
1541
1542         curr_offset += len;
1543     }
1544
1545     *offset = curr_offset;
1546
1547     return(TRUE);
1548 }
1549
1550 static void
1551 dissect_ansi_637_tele_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
1552 {
1553     guint8      oct;
1554     guint8      len;
1555     guint32     octs;
1556     guint32     curr_offset;
1557     guint32     msg_id;
1558     guint32     msg_type;
1559     gchar       *str = NULL;
1560     proto_item  *item;
1561     proto_tree  *subtree;
1562
1563
1564     oct = tvb_get_guint8(tvb, 0);
1565     if (oct != 0x00)
1566     {
1567         return;
1568     }
1569
1570     len = tvb_get_guint8(tvb, 1);
1571     if (len != 3)
1572     {
1573         return;
1574     }
1575
1576     octs = tvb_get_ntoh24(tvb, 2);
1577     msg_type = (octs >> 20) & 0x0f;
1578     msg_id = (octs >> 4) & 0xffff;
1579
1580     str = match_strval(msg_type, ansi_tele_msg_type_strings);
1581
1582     /*
1583      * do not append to COL_INFO
1584      */
1585
1586     item =
1587         proto_tree_add_none_format(ansi_637_tree, hf_ansi_637_none,
1588             tvb, 0, -1, str);
1589
1590     subtree = proto_item_add_subtree(item, ett_params);
1591
1592     proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id,
1593         tvb, 0, 1, oct);
1594
1595     proto_tree_add_uint(subtree, hf_ansi_637_length,
1596         tvb, 1, 1, len);
1597
1598     proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_type,
1599         tvb, 2, 3, octs);
1600
1601     proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_id,
1602         tvb, 2, 3, octs);
1603
1604     proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_rsvd,
1605         tvb, 2, 3, octs);
1606
1607     proto_item_set_len(item, 2 + len);
1608
1609     curr_offset = 2 + len;
1610     len = tvb_length(tvb);
1611
1612     while ((len - curr_offset) > 0)
1613     {
1614         if (!dissect_ansi_637_tele_param(tvb, ansi_637_tree, &curr_offset))
1615         {
1616             proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
1617                 "Unknown Parameter Data");
1618             break;
1619         }
1620     }
1621 }
1622
1623 static void
1624 dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1625 {
1626     proto_item  *ansi_637_item;
1627     proto_tree  *ansi_637_tree = NULL;
1628     gchar       *str = NULL;
1629
1630     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1631     {
1632         col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
1633     }
1634
1635     /* In the interest of speed, if "tree" is NULL, don't do any work not
1636      * necessary to generate protocol tree items.
1637      */
1638     if (tree)
1639     {
1640         /*
1641          * create the ansi_637 protocol tree
1642          */
1643         str = match_strval(pinfo->match_port, ansi_tele_id_strings);
1644
1645         if (NULL == str) str = "Unrecognized Teleservice ID";
1646
1647         ansi_637_item =
1648             proto_tree_add_protocol_format(tree, proto_ansi_637_tele, tvb, 0, -1,
1649                 "%s - %s (%d)",
1650                 ansi_proto_name_tele,
1651                 str,
1652                 pinfo->match_port);
1653
1654         ansi_637_tree =
1655             proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele);
1656
1657         dissect_ansi_637_tele_message(tvb, ansi_637_tree);
1658     }
1659 }
1660
1661 static gboolean
1662 dissect_ansi_637_trans_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
1663 {
1664     void (*param_fcn)(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string) = NULL;
1665     guint8      oct;
1666     guint8      len;
1667     guint32     curr_offset;
1668     gint        ett_param_idx, idx;
1669     proto_tree  *subtree;
1670     proto_item  *item;
1671     gchar       *str = NULL;
1672
1673     curr_offset = *offset;
1674
1675     oct = tvb_get_guint8(tvb, curr_offset);
1676     str = my_match_strval((guint32) oct, ansi_trans_param_strings, &idx);
1677
1678     if (NULL == str)
1679     {
1680         return(FALSE);
1681     }
1682
1683     ett_param_idx = ett_ansi_637_trans_param[idx];
1684     param_fcn = ansi_637_trans_param_fcn[idx];
1685
1686     item =
1687         proto_tree_add_text(tree, tvb, curr_offset, -1, str);
1688
1689     subtree = proto_item_add_subtree(item, ett_param_idx);
1690
1691     proto_tree_add_uint(subtree, hf_ansi_637_trans_param_id,
1692         tvb, curr_offset, 1, oct);
1693
1694     curr_offset++;
1695
1696     len = tvb_get_guint8(tvb, curr_offset);
1697
1698     proto_item_set_len(item, (curr_offset - *offset) + len + 1);
1699
1700     proto_tree_add_uint(subtree, hf_ansi_637_length,
1701         tvb, curr_offset, 1, len);
1702
1703     curr_offset++;
1704
1705     if (len > 0)
1706     {
1707         if (param_fcn == NULL)
1708         {
1709             proto_tree_add_text(subtree, tvb, curr_offset,
1710                 len, "Parameter Data");
1711         }
1712         else
1713         {
1714             ansi_637_add_string[0] = '\0';
1715             (*param_fcn)(tvb, subtree, len, curr_offset, ansi_637_add_string);
1716
1717             if (ansi_637_add_string[0] != '\0')
1718             {
1719                 proto_item_append_text(item, ansi_637_add_string);
1720             }
1721         }
1722
1723         curr_offset += len;
1724     }
1725
1726     *offset = curr_offset;
1727
1728     return(TRUE);
1729 }
1730
1731 static void
1732 dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1733 {
1734     proto_item  *ansi_637_item;
1735     proto_tree  *ansi_637_tree = NULL;
1736     guint32     curr_offset;
1737     gint        idx;
1738     gchar       *str = NULL;
1739     guint8      oct;
1740     guint8      len;
1741
1742     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1743     {
1744         col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
1745     }
1746
1747     /* In the interest of speed, if "tree" is NULL, don't do any work not
1748      * necessary to generate protocol tree items.
1749      */
1750     if (tree)
1751     {
1752         g_pinfo = pinfo;
1753         g_tree = tree;
1754
1755         /*
1756          * create the ansi_637 protocol tree
1757          */
1758         oct = tvb_get_guint8(tvb, 0);
1759
1760         str = my_match_strval(oct, ansi_trans_msg_type_strings, &idx);
1761
1762         if (NULL == str)
1763         {
1764             ansi_637_item =
1765                 proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
1766                     "%s - Unrecognized Transport Layer Message Type (%d)",
1767                     ansi_proto_name_trans,
1768                     oct);
1769
1770             ansi_637_tree =
1771                 proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans);
1772         }
1773         else
1774         {
1775             ansi_637_item =
1776                 proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
1777                     "%s - %s",
1778                     ansi_proto_name_trans,
1779                     str);
1780
1781             ansi_637_tree =
1782                 proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans_msg[idx]);
1783         }
1784
1785         curr_offset = 1;
1786
1787         len = tvb_length(tvb);
1788
1789         while ((len - curr_offset) > 0)
1790         {
1791             if (!dissect_ansi_637_trans_param(tvb, ansi_637_tree, &curr_offset))
1792             {
1793                 proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
1794                     "Unknown Parameter Data");
1795                 break;
1796             }
1797         }
1798     }
1799 }
1800
1801 /* Register the protocol with Ethereal */
1802 void
1803 proto_register_ansi_637(void)
1804 {
1805     guint               i;
1806
1807     /* Setup list of header fields */
1808     static hf_register_info hf[] =
1809     {
1810         { &hf_ansi_637_trans_msg_type,
1811           { "Message Type",
1812             "ansi_637.trans_msg_type",
1813             FT_UINT24, BASE_DEC, VALS(ansi_trans_msg_type_strings), 0xf00000,
1814             "", HFILL }},
1815         { &hf_ansi_637_tele_msg_type,
1816           { "Message Type",
1817             "ansi_637.tele_msg_type",
1818             FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_type_strings), 0xf00000,
1819             "", HFILL }},
1820         { &hf_ansi_637_tele_msg_id,
1821           { "Message ID",
1822             "ansi_637.tele_msg_id",
1823             FT_UINT24, BASE_DEC, NULL, 0x0ffff0,
1824             "", HFILL }},
1825         { &hf_ansi_637_tele_msg_rsvd,
1826           { "Reserved",
1827             "ansi_637.tele_msg_rsvd",
1828             FT_UINT24, BASE_DEC, NULL, 0x00000f,
1829             "", HFILL }},
1830         { &hf_ansi_637_length,
1831             { "Length",         "ansi_637.len",
1832             FT_UINT8, BASE_DEC, NULL, 0,
1833             "", HFILL }
1834         },
1835         { &hf_ansi_637_none,
1836             { "Sub tree",       "ansi_637.none",
1837             FT_NONE, 0, 0, 0,
1838             "", HFILL }
1839         },
1840         { &hf_ansi_637_tele_subparam_id,
1841             { "Teleservice Subparam ID",        "ansi_637.tele_subparam_id",
1842             FT_UINT8, BASE_DEC, VALS(ansi_tele_param_strings), 0,
1843             "", HFILL }
1844         },
1845         { &hf_ansi_637_trans_param_id,
1846             { "Transport Param ID",     "ansi_637.trans_param_id",
1847             FT_UINT8, BASE_DEC, VALS(ansi_trans_param_strings), 0,
1848             "", HFILL }
1849         },
1850         { &hf_ansi_637_bin_addr,
1851             { "Binary Address", "ansi_637.bin_addr",
1852             FT_BYTES, BASE_HEX, 0, 0,
1853             "", HFILL }
1854         },
1855     };
1856
1857     /* Setup protocol subtree array */
1858 #define NUM_INDIVIDUAL_PARAMS   3
1859     static gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM];
1860
1861     memset((void *) ett, 0, sizeof(ett));
1862
1863     ett[0] = &ett_ansi_637_tele;
1864     ett[1] = &ett_ansi_637_trans;
1865     ett[2] = &ett_params;
1866
1867     for (i=0; i < NUM_TELE_PARAM; i++)
1868     {
1869         ett_ansi_637_tele_param[i] = -1;
1870         ett[NUM_INDIVIDUAL_PARAMS+i] = &ett_ansi_637_tele_param[i];
1871     }
1872
1873     for (i=0; i < NUM_TRANS_MSG_TYPE; i++)
1874     {
1875         ett_ansi_637_trans_msg[i] = -1;
1876         ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+i] = &ett_ansi_637_trans_msg[i];
1877     }
1878
1879     for (i=0; i < NUM_TRANS_PARAM; i++)
1880     {
1881         ett_ansi_637_trans_param[i] = -1;
1882         ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+i] = &ett_ansi_637_trans_param[i];
1883     }
1884
1885     /* Register the protocol name and description */
1886     proto_ansi_637_tele =
1887         proto_register_protocol(ansi_proto_name_tele, "ANSI IS-637-A Teleservice", "ansi_637_tele");
1888
1889     proto_ansi_637_trans =
1890         proto_register_protocol(ansi_proto_name_trans, "ANSI IS-637-A Transport", "ansi_637_trans");
1891
1892     /* Required function calls to register the header fields and subtrees used */
1893     proto_register_field_array(proto_ansi_637_tele, hf, array_length(hf));
1894     proto_register_subtree_array(ett, array_length(ett));
1895
1896     tele_dissector_table =
1897         register_dissector_table("ansi_637.tele_id",
1898             "ANSI IS-637-A Teleservice ID", FT_UINT8, BASE_DEC);
1899 }
1900
1901
1902 void
1903 proto_reg_handoff_ansi_637(void)
1904 {
1905     dissector_handle_t  ansi_637_tele_handle;
1906     dissector_handle_t  ansi_637_trans_handle;
1907     guint               i;
1908
1909     ansi_637_tele_handle = create_dissector_handle(dissect_ansi_637_tele, proto_ansi_637_tele);
1910     ansi_637_trans_handle = create_dissector_handle(dissect_ansi_637_trans, proto_ansi_637_trans);
1911
1912     /*
1913      * register for all known teleservices
1914      * '-1' is to stop before trailing '0' entry
1915      *
1916      * to add teleservices, modify 'ansi_tele_id_strings'
1917      */
1918     for (i=0; i < ((sizeof(ansi_tele_id_strings)/sizeof(value_string))-1); i++)
1919     {
1920         /*
1921          * ANSI MAP dissector will push out teleservice ids
1922          */
1923         dissector_add("ansi_map.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
1924
1925         /*
1926          * we will push out teleservice ids after Transport layer decode
1927          */
1928         dissector_add("ansi_637.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
1929     }
1930
1931     /*
1932      * ANSI A-interface will push out transport layer data
1933      */
1934     dissector_add("ansi_a.sms", 0, ansi_637_trans_handle);
1935
1936     data_handle = find_dissector("data");
1937 }