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