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