Revert "Fixup: tvb_* -> tvb_captured"
[metze/wireshark/wip.git] / epan / dissectors / packet-ansi_683.c
1 /* packet-ansi_683.c
2  * Routines for ANSI IS-683 (OTA (Mobile)) dissection
3  *
4  * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
5  * In association with Telos Technology Inc.
6  * Copyright 2008, Michael Lum <mglum [AT] shaw.ca>
7  * In association with Global Star Solutions, ULC.
8  *
9  * Last Updated to:
10  * http://www.3gpp2.org/Public_html/specs/C.S0016-C_v2.0_081031.pdf
11  *
12  * Wireshark - Network traffic analyzer
13  * By Gerald Combs <gerald@wireshark.org>
14  * Copyright 1998 Gerald Combs
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29  */
30
31 #include "config.h"
32
33 #include <string.h>
34
35 #include <epan/packet.h>
36 #include <epan/to_str.h>
37
38 void proto_register_ansi_683(void);
39 void proto_reg_handoff_ansi_683(void);
40
41
42 static const char *ansi_proto_name = "ANSI IS-683 (OTA (Mobile))";
43 static const char *ansi_proto_name_short = "IS-683";
44
45 #define ANSI_683_FORWARD        0
46 #define ANSI_683_REVERSE        1
47
48
49 /* Initialize the subtree pointers */
50 static gint ett_ansi_683 = -1;
51 static gint ett_for_nam_block = -1;
52 static gint ett_for_sspr_block = -1;
53 static gint ett_rev_sspr_block = -1;
54 static gint ett_rev_nam_block = -1;
55 static gint ett_key_p = -1;
56 static gint ett_key_g = -1;
57 static gint ett_rev_feat = -1;
58 static gint ett_for_val_block = -1;
59 static gint ett_band_cap = -1;
60 static gint ett_scm = -1;
61 static gint ett_for_puzl_block = -1;
62 static gint ett_rev_puzl_block = -1;
63 static gint ett_for_3gpd_block = -1;
64 static gint ett_rev_3gpd_block = -1;
65 static gint ett_for_mmd_block = -1;
66 static gint ett_rev_mmd_block = -1;
67 static gint ett_for_mms_block = -1;
68 static gint ett_rev_mms_block = -1;
69 static gint ett_rev_cap = -1;
70 static gint ett_segment = -1;
71
72 /* Initialize the protocol and registered fields */
73 static int proto_ansi_683 = -1;
74 static int hf_ansi_683_none = -1;
75 static int hf_ansi_683_for_msg_type = -1;
76 static int hf_ansi_683_rev_msg_type = -1;
77 static int hf_ansi_683_length = -1;
78
79 static char bigbuf[1024];
80
81 static const char dtmf_digits[16] = {'?','1','2','3','4','5','6','7','8','9','0','?','?','?','?','?'};
82 static const char bcd_digits[16]  = {'0','1','2','3','4','5','6','7','8','9','?','?','?','?','?','?'};
83
84 /* FUNCTIONS */
85
86 /* PARAM FUNCTIONS */
87
88 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
89     if ((edc_len) > (edc_max_len)) \
90     { \
91         proto_tree_add_none_format(tree, hf_ansi_683_none, tvb, \
92             offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
93     }
94
95 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
96     if ((sdc_len) < (sdc_min_len)) \
97     { \
98         proto_tree_add_none_format(tree, hf_ansi_683_none, tvb, \
99             offset, (sdc_len), "Short Data (?)"); \
100         return; \
101     }
102
103 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
104     if ((edc_len) != (edc_eq_len)) \
105     { \
106         proto_tree_add_none_format(tree, hf_ansi_683_none, tvb, \
107             offset, (edc_len), "Unexpected Data Length"); \
108         return; \
109     }
110
111 static guint32
112 fresh_handler(tvbuff_t *tvb, proto_tree *tree, guint len _U_, guint32 offset)
113 {
114     guint32     value;
115     guint8      oct;
116
117     oct = tvb_get_guint8(tvb, offset);
118
119     if (oct & 0x80)
120     {
121         value = tvb_get_ntohs(tvb, offset);
122
123         other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
124         proto_tree_add_none_format(tree, hf_ansi_683_none,
125             tvb, offset, 2,
126             "%s :  FRESH_INCL : TRUE",
127             bigbuf);
128
129         other_decode_bitfield_value(bigbuf, value, 0x7fff, 16);
130         proto_tree_add_none_format(tree, hf_ansi_683_none,
131             tvb, offset, 2,
132             "%s :  FRESH",
133             bigbuf);
134
135         return(2);
136     }
137
138     other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
139     proto_tree_add_none_format(tree, hf_ansi_683_none,
140         tvb, offset, 1,
141         "%s :  FRESH_INCL : FALSE",
142         bigbuf);
143
144     other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
145     proto_tree_add_none_format(tree, hf_ansi_683_none,
146         tvb, offset, 1,
147         "%s :  Reserved",
148         bigbuf);
149
150     return(1);
151 }
152
153 /*
154  * Table 3.5.1.2-1 Result Codes
155  */
156 static const gchar *
157 rev_res_code_type(guint8 res_code)
158 {
159     const gchar *str;
160
161     switch (res_code)
162     {
163     case 0: str = "Accepted - Operation successful"; break;
164     case 1: str = "Rejected - Unknown reason"; break;
165     case 2: str = "Rejected - Data size mismatch"; break;
166     case 3: str = "Rejected - Protocol version mismatch"; break;
167     case 4: str = "Rejected - Invalid parameter"; break;
168     case 5: str = "Rejected - SID/NID length mismatch"; break;
169     case 6: str = "Rejected - Message not expected in this mode"; break;
170     case 7: str = "Rejected - BLOCK_ID value not supported"; break;
171     case 8: str = "Rejected - Preferred roaming list length mismatch"; break;
172     case 9: str = "Rejected - CRC error"; break;
173     case 10: str = "Rejected - Mobile station locked"; break;
174     case 11: str = "Rejected - Invalid SPC"; break;
175     case 12: str = "Rejected - SPC change denied by the user"; break;
176     case 13: str = "Rejected - Invalid SPASM"; break;
177     case 14: str = "Rejected - BLOCK_ID not expected in this mode"; break;
178     case 15: str = "Rejected - User Zone already in PUZL"; break;
179     case 16: str = " Rejected - User Zone not in PUZL"; break;
180     case 17: str = " Rejected - No entries in PUZL"; break;
181     case 18: str = "Rejected - Operation Mode mismatch"; break;
182     case 19: str = "Rejected - SimpleIP MAX_NUM_NAI mismatch"; break;
183     case 20: str = "Rejected - SimpleIP MAX_NAI_LENGTH mismatch"; break;
184     case 21: str = "Rejected - MobileIP MAX_NUM_NAI mismatch"; break;
185     case 22: str = "Rejected - MobileIP MAX_NAI_LENGTH mismatch"; break;
186     case 23: str = "Rejected - SimpleIP PAP MAX_SS_LENGTH mismatch"; break;
187     case 24: str = "Rejected - SimpleIP CHAP MAX_SS_LENGTH mismatch"; break;
188     case 25: str = "Rejected - MobileIP MAX_MNAAA_SS_LENGTH mismatch"; break;
189     case 26: str = "Rejected - MobileIP MAX_MN-HA_SS_LENGTH mismatch"; break;
190     case 27: str = "Rejected - MobileIP MN-AAA_AUTH_ALGORITHM mismatch"; break;
191     case 28: str = "Rejected - MobileIP MN-HA_AUTH_ALGORITHM mismatch"; break;
192     case 29: str = "Rejected - SimpleIP ACT_NAI_ENTRY_INDEX mismatch"; break;
193     case 30: str = "Rejected - MobileIP ACT_NAI_ENTRY_INDEX mismatch"; break;
194     case 31: str = "Rejected - SimpleIP PAP NAI_ENTRY_INDEX mismatch"; break;
195     case 32: str = "Rejected - SimpleIP CHAP NAI_ENTRY_INDEX mismatch"; break;
196     case 33: str = "Rejected - MobileIP NAI_ENTRY_INDEX mismatch"; break;
197     case 34: str = "Rejected - Unexpected PRL_BLOCK_ID change"; break;
198     case 35: str = "Rejected - PRL format mismatch"; break;
199     case 36: str = "Rejected - HRPD Access Authentication MAX_NAI_LENGTH mismatch"; break;
200     case 37: str = "Rejected - HRPD Access Authentication CHAP MAX_SS_LENGTH mismatch"; break;
201     case 38: str = " Rejected - MMD MAX_NUM_IMPU mismatch"; break;
202     case 39: str = " Rejected - MMD MAX_IMPU_LENGTH mismatch"; break;
203     case 40: str = " Rejected - MMD MAX_NUM_P-CSCF mismatch"; break;
204     case 41: str = " Rejected - MMD MAX_P-CSCF_LENGTH mismatch"; break;
205     case 42: str = " Rejected - Unexpected System Tag BLOCK_ID Change"; break;
206     case 43: str = " Rejected - System Tag Format mismatch"; break;
207     case 44: str = " Rejected - NUM_MMS_URI mismatch"; break;
208     case 45: str = " Rejected - MMS_URI _LENGTH mismatch"; break;
209     case 46: str = " Rejected - Invalid MMS_URI"; break;
210     default:
211         if ((res_code >= 47) && (res_code <= 127)) { str = "Reserved for future standardization"; break; }
212         else if ((res_code >= 128) && (res_code <= 254)) { str = "Available for manufacturer-specific Result Code definitions"; break; }
213         else { str = "Reserved"; break; }
214     }
215
216     return(str);
217 }
218
219 /*
220  * Table 3.5.1.7-1 Feature Identifier
221  */
222 static const gchar *
223 rev_feat_id_type(guint8 feat_id)
224 {
225     const gchar *str;
226
227     switch (feat_id)
228     {
229     case 0: str = "NAM Download (DATA_P_REV)"; break;
230     case 1: str = "Key Exchange (A_KEY_P_REV)"; break;
231     case 2: str = "System Selection for Preferred Roaming (SSPR_P_REV)"; break;
232     case 3: str = "Service Programming Lock (SPL_P_REV)"; break;
233     case 4: str = "Over-The-Air Parameter Administration (OTAPA_P_REV)"; break;
234     case 5: str = "Preferred User Zone List (PUZL_P_REV)"; break;
235     case 6: str = "3G Packet Data (3GPD)"; break;
236     case 7: str = "Secure MODE (SECURE_MODE_P_REV)"; break;
237     case 8: str = "Multimedia Domain (MMD)"; break;
238     case 9: str = "System Tag Download (TAG_P_REV)"; break;
239     case 10: str = "Multimedia Messaging Service (MMS)"; break;
240     default:
241         if ((feat_id >= 11) && (feat_id <= 191)) { str = "Reserved for future standardization"; break; }
242         else if ((feat_id >= 192) && (feat_id <= 254)) { str = "Available for manufacturer-specific features"; break; }
243         else { str = "Reserved"; break; }
244     }
245
246     return(str);
247 }
248
249 #define REV_TYPE_CAP_INFO_OP_MODE       0
250 #define REV_TYPE_CAP_INFO_CDMA_BAND     1
251 #define REV_TYPE_CAP_INFO_MEID          2
252 #define REV_TYPE_CAP_INFO_ICCID         3
253 #define REV_TYPE_CAP_INFO_EXT_UIM_ID    4
254 #define REV_TYPE_CAP_INFO_MEID_ME       5
255
256 /*
257  * Table 3.5.1.17.1-1 Capability Information Record Types
258  */
259 static const gchar *
260 rev_cap_info_record_type(guint8 rec_type)
261 {
262     const gchar *str;
263
264     switch (rec_type)
265     {
266     case 0: str = "Operating Mode Information"; break;
267     case 1: str = "CDMA Band Class Information"; break;
268     case 2: str = "MEID"; break;
269     case 3: str = "ICCID"; break;
270     case 4: str = "EXT_UIM_ID"; break;
271     case 5: str = "MEID_ME"; break;
272     default:
273         str = "Reserved"; break;
274     }
275
276     return(str);
277 }
278
279 #define FOR_BLOCK_VAL_VERIFY_SPC                0
280 #define FOR_BLOCK_VAL_CHANGE_SPC                1
281 #define FOR_BLOCK_VAL_VALDATE_SPASM             2
282
283 /*
284  * Table 4.5.4-1 Validation Parameter Block Types
285  */
286 static const gchar *
287 for_param_block_val(guint8 block_type)
288 {
289     const gchar *str;
290
291     switch (block_type)
292     {
293     case 0: str = "Verify SPC"; break;
294     case 1: str = "Change SPC"; break;
295     case 2: str = "Validate SPASM"; break;
296     default:
297         if ((block_type >= 3) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
298         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
299         else { str = "Reserved"; break; }
300     }
301
302     return(str);
303 }
304
305 #define REV_BLOCK_SSPR_PRL_DIM          0
306 #define REV_BLOCK_SSPR_PRL              1
307 #define REV_BLOCK_SSPR_EXT_PRL_DIM      2
308
309 /*
310  * Table 3.5.3-1 SSPR Parameter Block Types
311  */
312 static const gchar *
313 rev_param_block_sspr(guint8 block_type)
314 {
315     const gchar *str;
316
317     switch (block_type)
318     {
319     case 0: str = "Preferred Roaming List Dimensions"; break;
320     case 1: str = "Preferred Roaming List"; break;
321     case 2: str = "Extended Preferred Roaming List Dimensions"; break;
322     default:
323         if ((block_type >= 3) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
324         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
325         else { str = "Reserved"; break; }
326     }
327
328     return(str);
329 }
330
331 #define FOR_BLOCK_SSPR_PRL              0
332 #define FOR_BLOCK_SSPR_EXT_PRL          1
333
334 /*
335  * Table 4.5.3-1 SSPR Parameter Block Types
336  */
337 static const gchar *
338 for_param_block_sspr(guint8 block_type)
339 {
340     const gchar *str;
341
342     switch (block_type)
343     {
344     case 0: str = "Preferred Roaming List"; break;
345     case 1: str = "Extended Preferred Roaming List with SSPR_P_REV greater than 00000001"; break;
346     default:
347         if ((block_type >= 2) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
348         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
349         else { str = "Reserved"; break; }
350     }
351
352     return(str);
353 }
354
355 #define REV_BLOCK_NAM_CDMA_ANALOG       0
356 #define REV_BLOCK_NAM_MDN               1
357 #define REV_BLOCK_NAM_CDMA              2
358 #define REV_BLOCK_NAM_IMSI_T            3
359
360 /*
361  * Table 3.5.2-1 NAM Parameter Block Types
362  */
363 static const gchar *
364 rev_param_block_nam(guint8 block_type)
365 {
366     const gchar *str;
367
368     switch (block_type)
369     {
370     case 0: str = "CDMA/Analog NAM"; break;
371     case 1: str = "Mobile Directory Number"; break;
372     case 2: str = "CDMA NAM"; break;
373     case 3: str = "IMSI_T"; break;
374     default:
375         if ((block_type >= 4) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
376         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
377         else { str = "Reserved"; break; }
378     }
379
380     return(str);
381 }
382
383 #define FOR_BLOCK_NAM_CDMA_ANALOG       0
384 #define FOR_BLOCK_NAM_MDN               1
385 #define FOR_BLOCK_NAM_CDMA              2
386 #define FOR_BLOCK_NAM_IMSI_T            3
387
388 /*
389  * Table 4.5.2-1 NAM Parameter Block Types
390  */
391 static const gchar *
392 for_param_block_nam(guint8 block_type)
393 {
394     const gchar *str;
395
396     switch (block_type)
397     {
398     case 0: str = "CDMA/Analog NAM Download"; break;
399     case 1: str = "Mobile Directory Number"; break;
400     case 2: str = "CDMA NAM Download"; break;
401     case 3: str = "IMSI_T"; break;
402     default:
403         if ((block_type >= 4) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
404         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
405         else { str = "Reserved"; break; }
406     }
407
408     return(str);
409 }
410
411 /*
412  * Table 3.5.6-1 PUZL Parameter Block Types
413  */
414 static const gchar *
415 rev_param_block_puzl(guint8 block_type)
416 {
417     const gchar *str;
418
419     switch (block_type)
420     {
421     case 0: str = "PUZL Dimensions"; break;
422     case 1: str = "PUZL Priorities"; break;
423     case 2: str = "User Zone"; break;
424     case 3: str = "Preferred User Zone List"; break;
425     default:
426         if ((block_type >= 4) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
427         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
428         else { str = "Reserved"; break; }
429     }
430
431     return(str);
432 }
433
434 #define FOR_BLOCK_PUZL_UZ_INS                   0
435 #define FOR_BLOCK_PUZL_UZ_UPD                   1
436 #define FOR_BLOCK_PUZL_UZ_DEL                   2
437 #define FOR_BLOCK_PUZL_UZ_PRI_CHANGE            3
438 #define FOR_BLOCK_PUZL_FLAGS                    4
439
440 /*
441  * Table 4.5.6-1 PUZL Parameter Block Types
442  */
443 static const gchar *
444 for_param_block_puzl(guint8 block_type)
445 {
446     const gchar *str;
447
448     switch (block_type)
449     {
450     case 0: str = "User Zone Insert"; break;
451     case 1: str = "User Zone Update"; break;
452     case 2: str = "User Zone Delete"; break;
453     case 3: str = "User Zone Priority Change"; break;
454     case 4: str = "PUZL Flags"; break;
455     default:
456         if ((block_type >= 5) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
457         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
458         else { str = "Reserved"; break; }
459     }
460
461     return(str);
462 }
463
464 #define REV_BLOCK_3GPD_OP_CAP                   0
465 #define REV_BLOCK_3GPD_OP_MODE                  1
466 #define REV_BLOCK_3GPD_SIP_CAP                  2
467 #define REV_BLOCK_3GPD_MIP_CAP                  3
468 #define REV_BLOCK_3GPD_SIP_USER_PRO             4
469 #define REV_BLOCK_3GPD_MIP_USER_PRO             5
470 #define REV_BLOCK_3GPD_SIP_STATUS               6
471 #define REV_BLOCK_3GPD_MIP_STATUS               7
472 #define REV_BLOCK_3GPD_SIP_PAP_SS               8
473 #define REV_BLOCK_3GPD_SIP_CHAP_SS              9
474 #define REV_BLOCK_3GPD_MIP_SS                   10
475 #define REV_BLOCK_3GPD_HRPD_ACC_AUTH_CAP        11
476 #define REV_BLOCK_3GPD_HRPD_ACC_AUTH_USER       12
477 #define REV_BLOCK_3GPD_HRPD_ACC_AUTH_CHAP_SS    13
478
479 /*
480  * Table 3.5.8-1 3GPD Parameter Block Types
481  */
482 static const gchar *
483 rev_param_block_3gpd(guint8 block_type)
484 {
485     const gchar *str;
486
487     switch (block_type)
488     {
489     case 0: str = "3GPD Operation Capability Parameters"; break;
490     case 1: str = "3GPD Operation Mode Parameters"; break;
491     case 2: str = "SimpleIP Capability Parameters"; break;
492     case 3: str = "MobileIP Capability Parameters"; break;
493     case 4: str = "SimpleIP User Profile Parameters"; break;
494     case 5: str = "Mobile IP User Profile Parameters"; break;
495     case 6: str = "SimpleIP Status Parameters"; break;
496     case 7: str = "MobileIP Status Parameters"; break;
497     case 8: str = "SimpleIP PAP SS Parameters"; break;
498     case 9: str = "SimpleIP CHAP SS Parameters"; break;
499     case 10: str = "MobileIP SS Parameters"; break;
500     case 11: str = "HRPD Access Authentication Capability Parameters"; break;
501     case 12: str = "HRPD Access Authentication User Profile Parameters"; break;
502     case 13: str = "HRPD Access Authentication CHAP SS Parameters"; break;
503     default:
504         str = "Reserved"; break;
505     }
506
507     return(str);
508 }
509
510 #define FOR_BLOCK_3GPD_OP_MODE                  0
511 #define FOR_BLOCK_3GPD_SIP_USER_PRO             1
512 #define FOR_BLOCK_3GPD_MIP_USER_PRO             2
513 #define FOR_BLOCK_3GPD_SIP_STATUS               6
514 #define FOR_BLOCK_3GPD_MIP_STATUS               7
515 #define FOR_BLOCK_3GPD_SIP_PAP_SS               8
516 #define FOR_BLOCK_3GPD_SIP_CHAP_SS              9
517 #define FOR_BLOCK_3GPD_MIP_SS                   10
518 #define FOR_BLOCK_3GPD_HRPD_ACC_AUTH_USER       11
519 #define FOR_BLOCK_3GPD_HRPD_ACC_AUTH_CHAP_SS    12
520
521 /*
522  * Table 4.5.7-1 3GPD Parameter Block Types
523  */
524 static const gchar *
525 for_param_block_3gpd(guint8 block_type)
526 {
527     const gchar *str;
528
529     switch (block_type)
530     {
531     case 0: str = "3GPD Operation Mode Parameters"; break;
532     case 1: str = "SimpleIP User Profile Parameters"; break;
533     case 2: str = "Mobile IP User Profile Parameters"; break;
534     case 6: str = "SimpleIP Status Parameters"; break;
535     case 7: str = "MobileIP Status Parameters"; break;
536     case 8: str = "SimpleIP PAP SS Parameters"; break;
537     case 9: str = "SimpleIP CHAP SS Parameters"; break;
538     case 10: str = "MobileIP SS Parameters"; break;
539     case 11: str = "HRPD Access Authentication User Profile Parameters"; break;
540     case 12: str = "HRPD Access Authentication CHAP SS Parameters"; break;
541     default:
542         str = "Reserved"; break;
543     }
544
545     return(str);
546 }
547
548 #define REV_BLOCK_MMD_APP               0
549
550 /*
551  * Table 3.5.9-1 MMD Parameter Block Types
552  */
553 static const gchar *
554 rev_param_block_mmd(guint8 block_type)
555 {
556     const gchar *str;
557
558     switch (block_type)
559     {
560     case 0: str = "MMD Application Parameters"; break;
561     default:
562         str = "Reserved"; break;
563     }
564
565     return(str);
566 }
567
568 #define FOR_BLOCK_MMD_APP               0
569
570 /*
571  * Table 4.5.8-1 MMD Parameter Block Types
572  */
573 static const gchar *
574 for_param_block_mmd(guint8 block_type)
575 {
576     const gchar *str;
577
578     switch (block_type)
579     {
580     case 0: str = "MMD Application Parameters"; break;
581     default:
582         str = "Reserved"; break;
583     }
584
585     return(str);
586 }
587
588 #define REV_BLOCK_SYSTAG_HOME_SYSTAG            0
589 #define REV_BLOCK_SYSTAG_GROUP_TAG_LIST_DIM     1
590 #define REV_BLOCK_SYSTAG_GROUP_TAG_LIST         2
591 #define REV_BLOCK_SYSTAG_SPEC_TAG_LIST_DIM      3
592 #define REV_BLOCK_SYSTAG_SPEC_TAG_LIST          4
593 #define REV_BLOCK_SYSTAG_CALL_PROMPT_LIST_DIM   5
594 #define REV_BLOCK_SYSTAG_CALL_PROMPT_LIST       6
595
596 /*
597  * Table 3.5.10-1 System Tag Parameter Block Types
598  */
599 static const gchar *
600 rev_param_block_systag(guint8 block_type)
601 {
602     const gchar *str;
603
604     switch (block_type)
605     {
606     case 0: str = "Home System Tag"; break;
607     case 1: str = "Group Tag List Dimensions"; break;
608     case 2: str = "Group Tag List"; break;
609     case 3: str = "Specific Tag List Dimensions"; break;
610     case 4: str = "Specific Tag List"; break;
611     case 5: str = "Call Prompt List Dimensions"; break;
612     case 6: str = "Call Prompt List"; break;
613     default:
614         str = "Reserved"; break;
615     }
616
617     return(str);
618 }
619
620 /*
621  * Table 4.5.9-1 System Tag Parameter Block Types
622  */
623 static const gchar *
624 for_param_block_systag(guint8 block_type)
625 {
626     const gchar *str;
627
628     switch (block_type)
629     {
630     case 0: str = "Home System Tag"; break;
631     case 1: str = "Group Tag List"; break;
632     case 2: str = "Specific Tag List"; break;
633     case 3: str = "Call Prompt List"; break;
634     default:
635         if ((block_type >= 4) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
636         else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
637         else { str = "Reserved"; break; }
638     }
639
640     return(str);
641 }
642
643 #define REV_BLOCK_MMS_URI               0
644 #define REV_BLOCK_MMS_URI_CAP           1
645
646 /*
647  * Table 3.5.12-1 MMS Parameter Block Types
648  */
649 static const gchar *
650 rev_param_block_mms(guint8 block_type)
651 {
652     const gchar *str;
653
654     switch (block_type)
655     {
656     case 0: str = "MMS URI Parameters"; break;
657     case 1: str = "MMS URI Capability Parameters"; break;
658     default:
659         str = "Reserved"; break;
660     }
661
662     return(str);
663 }
664
665 #define FOR_BLOCK_MMS_URI               0
666
667 /*
668  * Table 4.5.10-1 MMS Parameter Block Types
669  */
670 static const gchar *
671 for_param_block_mms(guint8 block_type)
672 {
673     const gchar *str;
674
675     switch (block_type)
676     {
677     case 0: str = "MMS URI Parameters"; break;
678     default:
679         str = "Reserved"; break;
680     }
681
682     return(str);
683 }
684
685 /* PARAMETER BLOCK DISSECTION */
686
687 /*
688  * 3.5.2.1
689  */
690 static void
691 rev_param_block_nam_cdma_analog(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
692 {
693     guint32     saved_offset;
694     guint32     value;
695     guint32     count;
696     proto_tree  *subtree;
697     proto_item  *item;
698     const gchar *str = NULL;
699
700     saved_offset = offset;
701
702     value = tvb_get_ntohs(tvb, offset);
703
704     other_decode_bitfield_value(bigbuf, value, 0xffe0, 16);
705     proto_tree_add_none_format(tree, hf_ansi_683_none,
706         tvb, offset, 2,
707         "%s :  First paging channel (FIRSTCHP) used in the home system (%u)",
708         bigbuf,
709         (value & 0xffe0) >> 5);
710
711     offset++;
712
713     value = tvb_get_ntoh24(tvb, offset);
714
715     other_decode_bitfield_value(bigbuf, value, 0x1fffc0, 24);
716     proto_tree_add_none_format(tree, hf_ansi_683_none,
717         tvb, offset, 3,
718         "%s :  Home system identification (HOME_SID) (%u)",
719         bigbuf,
720         (value & 0x1fffc0) >> 6);
721
722     other_decode_bitfield_value(bigbuf, value, 0x20, 8);
723     proto_tree_add_none_format(tree, hf_ansi_683_none,
724         tvb, offset + 2, 1,
725         "%s :  Extended address indicator (EX)",
726         bigbuf);
727
728     offset += 2;
729
730     value = tvb_get_ntohs(tvb, offset);
731
732     other_decode_bitfield_value(bigbuf, value, 0x1fe0, 16);
733     item =
734         proto_tree_add_none_format(tree, hf_ansi_683_none,
735             tvb, offset, 2,
736             "%s :  Station class mark (SCM) (%u)",
737             bigbuf,
738             (value & 0x1fe0) >> 5);
739
740     /*
741      * following SCM decode is from:
742      *  3GPP2 C.S0005-0 section 2.3.3
743      *  3GPP2 C.S0072-0 section 2.1.2
744      */
745     subtree = proto_item_add_subtree(item, ett_scm);
746
747     other_decode_bitfield_value(bigbuf, value, 0x1000, 16);
748     proto_tree_add_none_format(subtree, hf_ansi_683_none,
749         tvb, offset, 2,
750         "%s :  Extended SCM Indicator: %s",
751         bigbuf,
752         (value & 0x1000) ? "Band Classes 1,4" : "Other bands");
753
754     other_decode_bitfield_value(bigbuf, value, 0x0800, 16);
755     proto_tree_add_none_format(subtree, hf_ansi_683_none,
756         tvb, offset, 2,
757         "%s :  %s",
758         bigbuf,
759         (value & 0x0800) ? "Dual Mode" : "CDMA Only");
760
761     other_decode_bitfield_value(bigbuf, value, 0x0400, 16);
762     proto_tree_add_none_format(subtree, hf_ansi_683_none,
763         tvb, offset, 2,
764         "%s :  %s",
765         bigbuf,
766         (value & 0x0400) ? "Slotted" : "Non-Slotted");
767
768     if (value & 0x0200)
769     {
770         str = "";
771         proto_item_append_text(item, "%s", " (MEID configured)");
772     }
773     else
774     {
775         str = "not ";
776     }
777
778     other_decode_bitfield_value(bigbuf, value, 0x0200, 16);
779     proto_tree_add_none_format(subtree, hf_ansi_683_none,
780         tvb, offset, 2,
781         "%s :  MEID %sconfigured",
782         bigbuf,
783         str);
784
785     other_decode_bitfield_value(bigbuf, value, 0x0100, 16);
786     proto_tree_add_none_format(subtree, hf_ansi_683_none,
787         tvb, offset, 2,
788         "%s :  25 MHz Bandwidth",
789         bigbuf);
790
791     other_decode_bitfield_value(bigbuf, value, 0x0080, 16);
792     proto_tree_add_none_format(subtree, hf_ansi_683_none,
793         tvb, offset, 2,
794         "%s :  %s Transmission",
795         bigbuf,
796         (value & 0x0080) ? "Discontinuous" : "Continuous");
797
798     switch ((value & 0x0060) >> 5)
799     {
800     case 0x00: str = "Class I"; break;
801     case 0x01: str = "Class II"; break;
802     case 0x02: str = "Class III"; break;
803     case 0x03: str = "Reserved"; break;
804     }
805
806     other_decode_bitfield_value(bigbuf, value, 0x0060, 16);
807     proto_tree_add_none_format(subtree, hf_ansi_683_none,
808         tvb, offset, 2,
809         "%s :  Power Class for Band Class 0 Analog Operation: %s",
810         bigbuf,
811         str);
812
813     offset++;
814
815     value = tvb_get_ntohs(tvb, offset);
816
817     other_decode_bitfield_value(bigbuf, value, 0x1fe0, 16);
818     proto_tree_add_none_format(tree, hf_ansi_683_none,
819         tvb, offset, 2,
820         "%s :  Mobile station protocol revision number (MOB_P_REV) (%u)",
821         bigbuf,
822         (value & 0x1fe0) >> 5);
823
824     other_decode_bitfield_value(bigbuf, value, 0x10, 8);
825     proto_tree_add_none_format(tree, hf_ansi_683_none,
826         tvb, offset + 1, 1,
827         "%s :  IMSI_M Class assignment of the mobile station (IMSI_M_CLASS), Class %u",
828         bigbuf,
829         (value & 0x10) >> 4);
830
831     other_decode_bitfield_value(bigbuf, value, 0x0e, 8);
832     proto_tree_add_none_format(tree, hf_ansi_683_none,
833         tvb, offset + 1, 1,
834         "%s :  Number of IMSI_M address digits (IMSI_M_ADDR_NUM) (%u), %u digits in NMSI",
835         bigbuf,
836         (value & 0x0e) >> 1,
837         (value & 0x10) ? ((value & 0x0e) >> 1) + 4 : 0);
838
839     offset++;
840
841     value = tvb_get_ntoh24(tvb, offset);
842
843     other_decode_bitfield_value(bigbuf, value, 0x01ff80, 24);
844     proto_tree_add_none_format(tree, hf_ansi_683_none,
845         tvb, offset, 3,
846         "%s :  Mobile country code (MCC_M)",
847         bigbuf);
848
849     other_decode_bitfield_value(bigbuf, value, 0x7f, 8);
850     proto_tree_add_none_format(tree, hf_ansi_683_none,
851         tvb, offset + 2, 1,
852         "%s :  11th and 12th digits of the IMSI_M (IMSI__M_11_12)",
853         bigbuf);
854
855     offset += 3;
856
857     proto_tree_add_none_format(tree, hf_ansi_683_none,
858         tvb, offset, 5,
859         "The least significant 10 digits of the IMSI_M (IMSI_M_S) (34 bits)");
860
861     offset += 4;
862
863     value = tvb_get_guint8(tvb, offset);
864
865     other_decode_bitfield_value(bigbuf, value, 0x3c, 8);
866     proto_tree_add_none_format(tree, hf_ansi_683_none,
867         tvb, offset, 1,
868         "%s :  Access overload class (ACCOLC) (%u)",
869         bigbuf,
870         (value & 0x3c) >> 2);
871
872     other_decode_bitfield_value(bigbuf, value, 0x02, 8);
873     proto_tree_add_none_format(tree, hf_ansi_683_none,
874         tvb, offset, 1,
875         "%s :  Local control status (LOCAL_CONTROL)",
876         bigbuf);
877
878     other_decode_bitfield_value(bigbuf, value, 0x01, 8);
879     proto_tree_add_none_format(tree, hf_ansi_683_none,
880         tvb, offset, 1,
881         "%s :  Termination indicator for the home system (MOB_TERM_HOME)",
882         bigbuf);
883
884     offset++;
885
886     value = tvb_get_guint8(tvb, offset);
887
888     other_decode_bitfield_value(bigbuf, value, 0x80, 8);
889     proto_tree_add_none_format(tree, hf_ansi_683_none,
890         tvb, offset, 1,
891         "%s :  Termination indicator for SID roaming (MOB_TERM_FOR_SID)",
892         bigbuf);
893
894     other_decode_bitfield_value(bigbuf, value, 0x40, 8);
895     proto_tree_add_none_format(tree, hf_ansi_683_none,
896         tvb, offset, 1,
897         "%s :  Termination indicator for NID roaming (MOB_TERM_FOR_NID)",
898         bigbuf);
899
900     value = tvb_get_ntohs(tvb, offset);
901
902     other_decode_bitfield_value(bigbuf, value, 0x3fc0, 16);
903     proto_tree_add_none_format(tree, hf_ansi_683_none,
904         tvb, offset, 2,
905         "%s :  Maximum stored SID/NID pairs (MAX_SID_NID) (%u)",
906         bigbuf,
907         (value & 0x3fc0) >> 6);
908
909     offset++;
910
911     value = tvb_get_ntohs(tvb, offset);
912
913     count = (value & 0x3fc0) >> 6;
914
915     other_decode_bitfield_value(bigbuf, value, 0x3fc0, 16);
916     proto_tree_add_none_format(tree, hf_ansi_683_none,
917         tvb, offset, 2,
918         "%s :  Number of stored SID/NID pairs (STORED_SID_NID) (%u)",
919         bigbuf,
920         count);
921
922     other_decode_bitfield_value(bigbuf, value, 0x003f, 16);
923     proto_tree_add_none_format(tree, hf_ansi_683_none,
924         tvb, offset, 2,
925         "%s :  SID/NID pairs (MSB)",
926         bigbuf);
927
928     offset += 2;
929
930     proto_tree_add_none_format(tree, hf_ansi_683_none,
931         tvb, offset, len - (offset - saved_offset),
932         "SID/NID pairs, Reserved");
933 }
934
935 /*
936  * 3.5.2.2
937  * 4.5.2.2
938  */
939 static void
940 param_block_nam_mdn(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
941 {
942     guint32     saved_offset;
943     guint32     value, count, i;
944
945     saved_offset = offset;
946
947     value = tvb_get_guint8(tvb, offset);
948
949     count = (value & 0xf0) >> 4;
950
951     other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
952     proto_tree_add_none_format(tree, hf_ansi_683_none,
953         tvb, offset, 1,
954         "%s :  Number of digits (N_DIGITS) (%u)",
955         bigbuf,
956         count);
957
958     for (i=0; i < count; i++)
959     {
960         bigbuf[i] = dtmf_digits[(value & 0x0f)];
961
962         if ((i + 1) < count)
963         {
964             offset++;
965             value = tvb_get_guint8(tvb, offset);
966             bigbuf[i+1] = dtmf_digits[(value & 0xf0) >> 4];
967             i++;
968         }
969     }
970     bigbuf[i] = '\0';
971
972     proto_tree_add_none_format(tree, hf_ansi_683_none,
973         tvb, saved_offset, len,
974         "Mobile directory number, %s",
975         bigbuf);
976
977     if (!(count & 0x01))
978     {
979         other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
980         proto_tree_add_none_format(tree, hf_ansi_683_none,
981             tvb, offset, 1,
982             "%s :  Reserved",
983             bigbuf);
984     }
985 }
986
987 /*
988  * 3.5.2.3
989  */
990 static void
991 rev_param_block_nam_cdma(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
992 {
993     guint32     saved_offset;
994     guint32     value;
995     guint32     count;
996
997     saved_offset = offset;
998
999     value = tvb_get_guint8(tvb, offset);
1000
1001     other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
1002     proto_tree_add_none_format(tree, hf_ansi_683_none,
1003         tvb, offset, 1,
1004         "%s :  Reserved",
1005         bigbuf);
1006
1007     other_decode_bitfield_value(bigbuf, value, 0x20, 8);
1008     proto_tree_add_none_format(tree, hf_ansi_683_none,
1009         tvb, offset, 1,
1010         "%s :  Slotted Mode",
1011         bigbuf);
1012
1013     other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
1014     proto_tree_add_none_format(tree, hf_ansi_683_none,
1015         tvb, offset, 1,
1016         "%s :  Reserved",
1017         bigbuf);
1018
1019     offset++;
1020
1021     value = tvb_get_guint8(tvb, offset);
1022
1023     other_decode_bitfield_value(bigbuf, value, 0xff, 8);
1024     proto_tree_add_none_format(tree, hf_ansi_683_none,
1025         tvb, offset, 1,
1026         "%s :  Mobile station protocol revision number (MOB_P_REV) (%u)",
1027         bigbuf,
1028         value);
1029
1030     offset++;
1031
1032     value = tvb_get_ntohs(tvb, offset);
1033
1034     other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
1035     proto_tree_add_none_format(tree, hf_ansi_683_none,
1036         tvb, offset, 2,
1037         "%s :  IMSI_M Class assignment of the mobile station (IMSI_M_CLASS), Class %u",
1038         bigbuf,
1039         (value & 0x8000) >> 15);
1040
1041     other_decode_bitfield_value(bigbuf, value, 0x7000, 16);
1042     proto_tree_add_none_format(tree, hf_ansi_683_none,
1043         tvb, offset, 2,
1044         "%s :  Number of IMSI_M address digits (IMSI_M_ADDR_NUM) (%u), %u digits in NMSI",
1045         bigbuf,
1046         (value & 0x7000) >> 12,
1047         (value & 0x8000) ? ((value & 0x7000) >> 12) + 4 : 0);
1048
1049     other_decode_bitfield_value(bigbuf, value, 0x0ffc, 16);
1050     proto_tree_add_none_format(tree, hf_ansi_683_none,
1051         tvb, offset, 2,
1052         "%s :  Mobile country code (MCC_M)",
1053         bigbuf);
1054
1055     offset++;
1056
1057     value = tvb_get_ntohs(tvb, offset);
1058
1059     other_decode_bitfield_value(bigbuf, value, 0x3f80, 16);
1060     proto_tree_add_none_format(tree, hf_ansi_683_none,
1061         tvb, offset, 2,
1062         "%s :  11th and 12th digits of the IMSI_M (IMSI__M_11_12)",
1063         bigbuf);
1064
1065     offset++;
1066
1067     proto_tree_add_none_format(tree, hf_ansi_683_none,
1068         tvb, offset, 5,
1069         "The least significant 10 digits of the IMSI_M (IMSI_M_S) (34 bits)");
1070
1071     offset += 4;
1072
1073     value = tvb_get_ntohs(tvb, offset);
1074
1075     other_decode_bitfield_value(bigbuf, value, 0x01e0, 16);
1076     proto_tree_add_none_format(tree, hf_ansi_683_none,
1077         tvb, offset, 2,
1078         "%s :  Access overload class (ACCOLC) (%u)",
1079         bigbuf,
1080         (value & 0x01e0) >> 5);
1081
1082     other_decode_bitfield_value(bigbuf, value, 0x0010, 16);
1083     proto_tree_add_none_format(tree, hf_ansi_683_none,
1084         tvb, offset, 2,
1085         "%s :  Local control status (LOCAL_CONTROL)",
1086         bigbuf);
1087
1088     other_decode_bitfield_value(bigbuf, value, 0x0008, 16);
1089     proto_tree_add_none_format(tree, hf_ansi_683_none,
1090         tvb, offset, 2,
1091         "%s :  Termination indicator for the home system (MOB_TERM_HOME)",
1092         bigbuf);
1093
1094     other_decode_bitfield_value(bigbuf, value, 0x0004, 16);
1095     proto_tree_add_none_format(tree, hf_ansi_683_none,
1096         tvb, offset, 2,
1097         "%s :  Termination indicator for SID roaming (MOB_TERM_FOR_SID)",
1098         bigbuf);
1099
1100     other_decode_bitfield_value(bigbuf, value, 0x0002, 16);
1101     proto_tree_add_none_format(tree, hf_ansi_683_none,
1102         tvb, offset, 2,
1103         "%s :  Termination indicator for NID roaming (MOB_TERM_FOR_NID)",
1104         bigbuf);
1105
1106     offset++;
1107
1108     value = tvb_get_ntohs(tvb, offset);
1109
1110     other_decode_bitfield_value(bigbuf, value, 0x01fe, 16);
1111     proto_tree_add_none_format(tree, hf_ansi_683_none,
1112         tvb, offset, 2,
1113         "%s :  Maximum stored SID/NID pairs (MAX_SID_NID) (%u)",
1114         bigbuf,
1115         (value & 0x01fe) >> 1);
1116
1117     offset++;
1118
1119     value = tvb_get_ntohs(tvb, offset);
1120
1121     count = (value & 0x01fe) >> 1;
1122
1123     other_decode_bitfield_value(bigbuf, value, 0x01fe, 16);
1124     proto_tree_add_none_format(tree, hf_ansi_683_none,
1125         tvb, offset, 2,
1126         "%s :  Number of stored SID/NID pairs (STORED_SID_NID) (%u)",
1127         bigbuf,
1128         count);
1129
1130     other_decode_bitfield_value(bigbuf, value, 0x0001, 16);
1131     proto_tree_add_none_format(tree, hf_ansi_683_none,
1132         tvb, offset, 2,
1133         "%s :  SID/NID pairs (MSB)",
1134         bigbuf);
1135
1136     offset += 2;
1137
1138     proto_tree_add_none_format(tree, hf_ansi_683_none,
1139         tvb, offset, len - (offset - saved_offset),
1140         "SID/NID pairs, Reserved");
1141 }
1142
1143 /*
1144  * 3.5.2.4
1145  * 4.5.2.4
1146  */
1147 static void
1148 param_block_nam_imsi_t(tvbuff_t *tvb, proto_tree *tree, guint len _U_, guint32 offset)
1149 {
1150     guint32     value;
1151
1152     value = tvb_get_guint8(tvb, offset);
1153
1154     other_decode_bitfield_value(bigbuf, value, 0x80, 8);
1155     proto_tree_add_none_format(tree, hf_ansi_683_none,
1156         tvb, offset, 1,
1157         "%s :  IMSI_T Class assignment of the mobile station (IMSI_T_CLASS), Class %u",
1158         bigbuf,
1159         (value & 0x80) >> 7);
1160
1161     other_decode_bitfield_value(bigbuf, value, 0x70, 8);
1162     proto_tree_add_none_format(tree, hf_ansi_683_none,
1163         tvb, offset, 1,
1164         "%s :  Number of IMSI_T address digits (IMSI_T_ADDR_NUM ) (%u), %u digits in NMSI",
1165         bigbuf,
1166         (value & 0x70) >> 4,
1167         (value & 0x80) ? ((value & 0x70) >> 4) + 4 : 0);
1168
1169     value = tvb_get_ntohs(tvb, offset);
1170
1171     other_decode_bitfield_value(bigbuf, value, 0x0ffc, 16);
1172     proto_tree_add_none_format(tree, hf_ansi_683_none,
1173         tvb, offset, 2,
1174         "%s :  Mobile country code (MCC_T)",
1175         bigbuf);
1176
1177     offset++;
1178
1179     value = tvb_get_ntohs(tvb, offset);
1180
1181     other_decode_bitfield_value(bigbuf, value, 0x03f8, 16);
1182     proto_tree_add_none_format(tree, hf_ansi_683_none,
1183         tvb, offset, 2,
1184         "%s :  11th and 12th digits of the IMSI_T (IMSI__T_11_12)",
1185         bigbuf);
1186
1187     offset++;
1188
1189     proto_tree_add_none_format(tree, hf_ansi_683_none,
1190         tvb, offset, 5,
1191         "The least significant 10 digits of the IMSI_T (IMSI_T_S) (34 bits)");
1192
1193     offset += 4;
1194
1195     value = tvb_get_guint8(tvb, offset);
1196
1197     other_decode_bitfield_value(bigbuf, value, 0x01, 8);
1198     proto_tree_add_none_format(tree, hf_ansi_683_none,
1199         tvb, offset, 1,
1200         "%s :  Reserved",
1201         bigbuf);
1202 }
1203
1204 /*
1205  * 4.5.2.1
1206  */
1207 static void
1208 for_param_block_nam_cdma_analog(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1209 {
1210     guint32     saved_offset;
1211     guint32     value;
1212     guint32     count;
1213
1214     saved_offset = offset;
1215
1216     value = tvb_get_ntohs(tvb, offset);
1217
1218     other_decode_bitfield_value(bigbuf, value, 0xffe0, 16);
1219     proto_tree_add_none_format(tree, hf_ansi_683_none,
1220         tvb, offset, 2,
1221         "%s :  First paging channel (FIRSTCHP) used in the home system (%u)",
1222         bigbuf,
1223         (value & 0xffe0) >> 5);
1224
1225     offset++;
1226
1227     value = tvb_get_ntoh24(tvb, offset);
1228
1229     other_decode_bitfield_value(bigbuf, value, 0x1fffc0, 24);
1230     proto_tree_add_none_format(tree, hf_ansi_683_none,
1231         tvb, offset, 3,
1232         "%s :  Home system identification (HOME_SID) (%u)",
1233         bigbuf,
1234         (value & 0x1fffc0) >> 6);
1235
1236     other_decode_bitfield_value(bigbuf, value, 0x20, 8);
1237     proto_tree_add_none_format(tree, hf_ansi_683_none,
1238         tvb, offset + 2, 1,
1239         "%s :  Extended address indicator (EX)",
1240         bigbuf);
1241
1242     other_decode_bitfield_value(bigbuf, value, 0x10, 8);
1243     proto_tree_add_none_format(tree, hf_ansi_683_none,
1244         tvb, offset + 2, 1,
1245         "%s :  IMSI_M Class assignment of the mobile station (IMSI_M_CLASS), Class %u",
1246         bigbuf,
1247         (value & 0x10) >> 4);
1248
1249     other_decode_bitfield_value(bigbuf, value, 0x0e, 8);
1250     proto_tree_add_none_format(tree, hf_ansi_683_none,
1251         tvb, offset + 2, 1,
1252         "%s :  Number of IMSI_M address digits (IMSI_M_ADDR_NUM) (%u), %u digits in NMSI",
1253         bigbuf,
1254         (value & 0x0e) >> 1,
1255         (value & 0x10) ? ((value & 0x0e) >> 1) + 4 : 0);
1256
1257     offset += 2;
1258
1259     value = tvb_get_ntoh24(tvb, offset);
1260
1261     other_decode_bitfield_value(bigbuf, value, 0x01ff80, 24);
1262     proto_tree_add_none_format(tree, hf_ansi_683_none,
1263         tvb, offset, 3,
1264         "%s :  Mobile country code (MCC_M)",
1265         bigbuf);
1266
1267     other_decode_bitfield_value(bigbuf, value, 0x7f, 8);
1268     proto_tree_add_none_format(tree, hf_ansi_683_none,
1269         tvb, offset + 2, 1,
1270         "%s :  11th and 12th digits of the IMSI_M (IMSI__M_11_12)",
1271         bigbuf);
1272
1273     offset += 3;
1274
1275     proto_tree_add_none_format(tree, hf_ansi_683_none,
1276         tvb, offset, 5,
1277         "The least significant 10 digits of the IMSI_M (IMSI_M_S) (34 bits)");
1278
1279     offset += 4;
1280
1281     value = tvb_get_guint8(tvb, offset);
1282
1283     other_decode_bitfield_value(bigbuf, value, 0x3c, 8);
1284     proto_tree_add_none_format(tree, hf_ansi_683_none,
1285         tvb, offset, 1,
1286         "%s :  Access overload class (ACCOLC) (%u)",
1287         bigbuf,
1288         (value & 0x3c) >> 2);
1289
1290     other_decode_bitfield_value(bigbuf, value, 0x02, 8);
1291     proto_tree_add_none_format(tree, hf_ansi_683_none,
1292         tvb, offset, 1,
1293         "%s :  Local control status (LOCAL_CONTROL)",
1294         bigbuf);
1295
1296     other_decode_bitfield_value(bigbuf, value, 0x01, 8);
1297     proto_tree_add_none_format(tree, hf_ansi_683_none,
1298         tvb, offset, 1,
1299         "%s :  Termination indicator for the home system (MOB_TERM_HOME)",
1300         bigbuf);
1301
1302     offset++;
1303
1304     value = tvb_get_ntohs(tvb, offset);
1305
1306     other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
1307     proto_tree_add_none_format(tree, hf_ansi_683_none,
1308         tvb, offset, 2,
1309         "%s :  Termination indicator for SID roaming (MOB_TERM_FOR_SID)",
1310         bigbuf);
1311
1312     other_decode_bitfield_value(bigbuf, value, 0x4000, 16);
1313     proto_tree_add_none_format(tree, hf_ansi_683_none,
1314         tvb, offset, 2,
1315         "%s :  Termination indicator for NID roaming (MOB_TERM_FOR_NID)",
1316         bigbuf);
1317
1318     count = (value & 0x3fc0) >> 6;
1319
1320     other_decode_bitfield_value(bigbuf, value, 0x3fc0, 16);
1321     proto_tree_add_none_format(tree, hf_ansi_683_none,
1322         tvb, offset, 2,
1323         "%s :  Number of SID/NID pairs (N_SID_NID) (%u)",
1324         bigbuf,
1325         count);
1326
1327     other_decode_bitfield_value(bigbuf, value, 0x003f, 16);
1328     proto_tree_add_none_format(tree, hf_ansi_683_none,
1329         tvb, offset, 2,
1330         "%s :  SID/NID pairs (MSB)",
1331         bigbuf);
1332
1333     offset += 2;
1334
1335     proto_tree_add_none_format(tree, hf_ansi_683_none,
1336         tvb, offset, len - (offset - saved_offset),
1337         "SID/NID pairs, Reserved");
1338 }
1339
1340 /*
1341  * 4.5.2.2
1342  * see param_block_nam_mdn()
1343  */
1344
1345 /*
1346  * 4.5.2.3
1347  */
1348 static void
1349 for_param_block_nam_cdma(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1350 {
1351     guint32     saved_offset;
1352     guint32     value;
1353     guint32     count;
1354
1355     saved_offset = offset;
1356
1357     value = tvb_get_ntohs(tvb, offset);
1358
1359     other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
1360     proto_tree_add_none_format(tree, hf_ansi_683_none,
1361         tvb, offset, 2,
1362         "%s :  IMSI_M Class assignment of the mobile station (IMSI_M_CLASS), Class %u",
1363         bigbuf,
1364         (value & 0x8000) >> 15);
1365
1366     other_decode_bitfield_value(bigbuf, value, 0x7000, 16);
1367     proto_tree_add_none_format(tree, hf_ansi_683_none,
1368         tvb, offset, 2,
1369         "%s :  Number of IMSI_M address digits (IMSI_M_ADDR_NUM) (%u), %u digits in NMSI",
1370         bigbuf,
1371         (value & 0x7000) >> 12,
1372         (value & 0x8000) ? ((value & 0x7000) >> 12) + 4 : 0);
1373
1374     other_decode_bitfield_value(bigbuf, value, 0x0ffc, 16);
1375     proto_tree_add_none_format(tree, hf_ansi_683_none,
1376         tvb, offset, 2,
1377         "%s :  Mobile country code (MCC_M)",
1378         bigbuf);
1379
1380     offset++;
1381
1382     value = tvb_get_ntohs(tvb, offset);
1383
1384     other_decode_bitfield_value(bigbuf, value, 0x3f80, 16);
1385     proto_tree_add_none_format(tree, hf_ansi_683_none,
1386         tvb, offset, 2,
1387         "%s :  11th and 12th digits of the IMSI_M (IMSI__M_11_12)",
1388         bigbuf);
1389
1390     offset++;
1391
1392     proto_tree_add_none_format(tree, hf_ansi_683_none,
1393         tvb, offset, 5,
1394         "The least significant 10 digits of the IMSI_M (IMSI_M_S) (34 bits)");
1395
1396     offset += 4;
1397
1398     value = tvb_get_ntohs(tvb, offset);
1399
1400     other_decode_bitfield_value(bigbuf, value, 0x01e0, 16);
1401     proto_tree_add_none_format(tree, hf_ansi_683_none,
1402         tvb, offset, 2,
1403         "%s :  Access overload class (ACCOLC) (%u)",
1404         bigbuf,
1405         (value & 0x01e0) >> 5);
1406
1407     other_decode_bitfield_value(bigbuf, value, 0x0010, 16);
1408     proto_tree_add_none_format(tree, hf_ansi_683_none,
1409         tvb, offset, 2,
1410         "%s :  Local control status (LOCAL_CONTROL)",
1411         bigbuf);
1412
1413     other_decode_bitfield_value(bigbuf, value, 0x0008, 16);
1414     proto_tree_add_none_format(tree, hf_ansi_683_none,
1415         tvb, offset, 2,
1416         "%s :  Termination indicator for the home system (MOB_TERM_HOME)",
1417         bigbuf);
1418
1419     other_decode_bitfield_value(bigbuf, value, 0x0004, 16);
1420     proto_tree_add_none_format(tree, hf_ansi_683_none,
1421         tvb, offset, 2,
1422         "%s :  Termination indicator for SID roaming (MOB_TERM_FOR_SID)",
1423         bigbuf);
1424
1425     other_decode_bitfield_value(bigbuf, value, 0x0002, 16);
1426     proto_tree_add_none_format(tree, hf_ansi_683_none,
1427         tvb, offset, 2,
1428         "%s :  Termination indicator for NID roaming (MOB_TERM_FOR_NID)",
1429         bigbuf);
1430
1431     offset++;
1432
1433     value = tvb_get_ntohs(tvb, offset);
1434
1435     count = (value & 0x01fe) >> 1;
1436
1437     other_decode_bitfield_value(bigbuf, value, 0x01fe, 16);
1438     proto_tree_add_none_format(tree, hf_ansi_683_none,
1439         tvb, offset, 2,
1440         "%s :  Number of SID/NID pairs (N_SID_NID) (%u)",
1441         bigbuf,
1442         count);
1443
1444     other_decode_bitfield_value(bigbuf, value, 0x0001, 16);
1445     proto_tree_add_none_format(tree, hf_ansi_683_none,
1446         tvb, offset, 2,
1447         "%s :  SID/NID pairs (MSB)",
1448         bigbuf);
1449
1450     offset += 2;
1451
1452     proto_tree_add_none_format(tree, hf_ansi_683_none,
1453         tvb, offset, len - (offset - saved_offset),
1454         "SID/NID pairs, Reserved");
1455 }
1456
1457 /*
1458  * 4.5.2.4
1459  * see param_block_nam_imsi_t()
1460  */
1461
1462 /*
1463  * 4.5.4.1
1464  * 4.5.4.2
1465  */
1466 static void
1467 for_param_block_val_spc(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1468 {
1469     guint32     saved_offset;
1470     guint32     value;
1471
1472     EXACT_DATA_CHECK(len, 3);
1473
1474     saved_offset = offset;
1475
1476     value = tvb_get_guint8(tvb, offset++);
1477     bigbuf[0] = bcd_digits[(value & 0x0f)];
1478     bigbuf[1] = bcd_digits[(value & 0xf0) >> 4];
1479
1480     value = tvb_get_guint8(tvb, offset++);
1481     bigbuf[2] = bcd_digits[(value & 0x0f)];
1482     bigbuf[3] = bcd_digits[(value & 0xf0) >> 4];
1483
1484     value = tvb_get_guint8(tvb, offset++);
1485     bigbuf[4] = bcd_digits[(value & 0x0f)];
1486     bigbuf[5] = bcd_digits[(value & 0xf0) >> 4];
1487     bigbuf[6] = '\0';
1488
1489     proto_tree_add_none_format(tree, hf_ansi_683_none,
1490         tvb, saved_offset, len,
1491         "Service programming code: %s",
1492         bigbuf);
1493 }
1494
1495 /*
1496  * 4.5.4.3
1497  */
1498 static void
1499 for_param_block_val_spasm(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1500 {
1501     guint32     value;
1502
1503     if (len == 1)
1504     {
1505         value = tvb_get_guint8(tvb, offset);
1506
1507         other_decode_bitfield_value(bigbuf, value, 0x80, 8);
1508         proto_tree_add_none_format(tree, hf_ansi_683_none,
1509             tvb, offset, 1,
1510             "%s :  OTAPA SPASM validation signature %sincluded indicator",
1511             bigbuf,
1512             (value & 0x80) ? "" : "not ");
1513
1514         other_decode_bitfield_value(bigbuf, value, 0x40, 8);
1515         proto_tree_add_none_format(tree, hf_ansi_683_none,
1516             tvb, offset, 1,
1517             "%s :  %s SPASM protection for the active NAM",
1518             bigbuf,
1519             (value & 0x40) ? "Activate" : "Do not activate");
1520
1521         other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
1522         proto_tree_add_none_format(tree, hf_ansi_683_none,
1523             tvb, offset, 1,
1524             "%s :  Reserved",
1525             bigbuf);
1526     }
1527     else
1528     {
1529         EXACT_DATA_CHECK(len, 3);
1530
1531         value = tvb_get_ntoh24(tvb, offset);
1532
1533         other_decode_bitfield_value(bigbuf, value, 0x800000, 24);
1534         proto_tree_add_none_format(tree, hf_ansi_683_none,
1535             tvb, offset, 3,
1536             "%s :  OTAPA SPASM validation signature %sincluded indicator",
1537             bigbuf,
1538             (value & 0x800000) ? "" : "not ");
1539
1540         other_decode_bitfield_value(bigbuf, value, 0x7fffe0, 24);
1541         proto_tree_add_none_format(tree, hf_ansi_683_none,
1542             tvb, offset, 3,
1543             "%s :  OTAPA SPASM validation signature (0x%x)",
1544             bigbuf,
1545             (value & 0x7fffe0) >> 5);
1546
1547         other_decode_bitfield_value(bigbuf, value, 0x000010, 24);
1548         proto_tree_add_none_format(tree, hf_ansi_683_none,
1549             tvb, offset, 3,
1550             "%s :  %s SPASM protection for the active NAM",
1551             bigbuf,
1552             (value & 0x000010) ? "Activate" : "Do not activate");
1553
1554         other_decode_bitfield_value(bigbuf, value, 0x00000f, 24);
1555         proto_tree_add_none_format(tree, hf_ansi_683_none,
1556             tvb, offset, 3,
1557             "%s :  Reserved",
1558             bigbuf);
1559     }
1560 }
1561
1562 /* FORWARD MESSAGES */
1563
1564 /*
1565  * 4.5.1.1
1566  */
1567 static void
1568 msg_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1569 {
1570     guint8      oct, num_blocks;
1571     const gchar *str = NULL;
1572     guint32     i, saved_offset;
1573
1574     SHORT_DATA_CHECK(len, 1);
1575
1576     saved_offset = offset;
1577
1578     num_blocks = tvb_get_guint8(tvb, offset);
1579
1580     proto_tree_add_none_format(tree, hf_ansi_683_none,
1581         tvb, offset, 1,
1582         "Number of parameter blocks (%u)",
1583         num_blocks);
1584
1585     offset++;
1586
1587     SHORT_DATA_CHECK((len - (offset - saved_offset)), num_blocks);
1588
1589     for (i=0; i < num_blocks; i++)
1590     {
1591         oct = tvb_get_guint8(tvb, offset);
1592
1593         str = rev_param_block_nam(oct);
1594
1595         proto_tree_add_none_format(tree, hf_ansi_683_none,
1596             tvb, offset, 1,
1597             "[%u]:  %s (%u)",
1598             i+1,
1599             str,
1600             oct);
1601
1602         offset++;
1603     }
1604
1605     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1606 }
1607
1608 /*
1609  * 4.5.1.2
1610  */
1611 static void
1612 msg_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1613 {
1614     guint8      block_id, num_blocks, block_len;
1615     const gchar *str = NULL;
1616     proto_tree  *subtree;
1617     proto_item  *item;
1618     guint32     i, saved_offset;
1619
1620     SHORT_DATA_CHECK(len, 1);
1621
1622     saved_offset = offset;
1623
1624     num_blocks = tvb_get_guint8(tvb, offset);
1625
1626     proto_tree_add_none_format(tree, hf_ansi_683_none,
1627         tvb, offset, 1,
1628         "Number of parameter blocks (%u)",
1629         num_blocks);
1630
1631     offset++;
1632
1633     for (i=0; i < num_blocks; i++)
1634     {
1635         block_id = tvb_get_guint8(tvb, offset);
1636
1637         str = for_param_block_nam(block_id);
1638
1639         item =
1640             proto_tree_add_none_format(tree, hf_ansi_683_none,
1641                 tvb, offset, 1,
1642                 "[%u]:  %s (%u)",
1643                 i+1,
1644                 str,
1645                 block_id);
1646
1647         subtree = proto_item_add_subtree(item, ett_for_nam_block);
1648         offset++;
1649
1650         block_len = tvb_get_guint8(tvb, offset);
1651
1652         proto_tree_add_uint(subtree, hf_ansi_683_length,
1653             tvb, offset, 1, block_len);
1654         offset++;
1655
1656         if (block_len > (len - (offset - saved_offset)))
1657         {
1658             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
1659                 offset, len - (offset - saved_offset), "Short Data (?)");
1660             return;
1661         }
1662
1663         if (block_len > 0)
1664         {
1665             switch (block_id)
1666             {
1667             case FOR_BLOCK_NAM_CDMA_ANALOG:
1668                 for_param_block_nam_cdma_analog(tvb, subtree, block_len, offset);
1669                 break;
1670
1671             case FOR_BLOCK_NAM_MDN:
1672                 param_block_nam_mdn(tvb, subtree, block_len, offset);
1673                 break;
1674
1675             case FOR_BLOCK_NAM_CDMA:
1676                 for_param_block_nam_cdma(tvb, subtree, block_len, offset);
1677                 break;
1678
1679             case FOR_BLOCK_NAM_IMSI_T:
1680                 param_block_nam_imsi_t(tvb, subtree, block_len, offset);
1681                 break;
1682
1683             default:
1684                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
1685                     tvb, offset, block_len, "Block Data");
1686                 break;
1687             }
1688
1689             offset += block_len;
1690         }
1691     }
1692
1693     if (len > (offset - saved_offset))
1694     {
1695         offset +=
1696             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
1697     }
1698
1699     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1700 }
1701
1702 /*
1703  * 4.5.1.3
1704  */
1705 static void
1706 msg_ms_key_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1707 {
1708     guint8      akey_prev, param_len;
1709     proto_tree  *subtree;
1710     proto_item  *item;
1711     guint32     saved_offset;
1712     const gchar *str = NULL;
1713
1714     SHORT_DATA_CHECK(len, 1);
1715
1716     saved_offset = offset;
1717
1718     akey_prev = tvb_get_guint8(tvb, offset);
1719
1720     switch (akey_prev)
1721     {
1722     case 0x02: str = "2G A-key generation"; break;
1723     case 0x03: str = "2G A-key and 3G Root Key generation"; break;
1724     case 0x04: str = "3G Root Key generation"; break;
1725     case 0x05: str = "Enhanced 3G Root Key generation"; break;
1726     default: str = "Unknown"; break;
1727     }
1728
1729     proto_tree_add_none_format(tree, hf_ansi_683_none,
1730         tvb, offset, 1,
1731         "A-Key Protocol Revision (%u):  %s",
1732         akey_prev,
1733         str);
1734     offset++;
1735
1736     if (akey_prev < 0x03)
1737     {
1738         param_len = tvb_get_guint8(tvb, offset);
1739
1740         item =
1741             proto_tree_add_none_format(tree, hf_ansi_683_none,
1742                 tvb, offset, param_len + 1,
1743                 "Key exchange parameter P");
1744         subtree = proto_item_add_subtree(item, ett_key_p);
1745
1746         proto_tree_add_uint(subtree, hf_ansi_683_length,
1747             tvb, offset, 1, param_len);
1748         offset++;
1749
1750         if (param_len > 0)
1751         {
1752             proto_tree_add_none_format(subtree, hf_ansi_683_none,
1753                 tvb, offset, param_len,
1754                 "Parameter P");
1755             offset += param_len;
1756         }
1757
1758         param_len = tvb_get_guint8(tvb, offset);
1759
1760         item =
1761             proto_tree_add_none_format(tree, hf_ansi_683_none,
1762                 tvb, offset, param_len + 1,
1763                 "Key exchange parameter G");
1764         subtree = proto_item_add_subtree(item, ett_key_g);
1765
1766         proto_tree_add_uint(subtree, hf_ansi_683_length,
1767             tvb, offset, 1, param_len);
1768         offset++;
1769
1770         if (param_len > 0)
1771         {
1772             proto_tree_add_none_format(subtree, hf_ansi_683_none,
1773                 tvb, offset, param_len,
1774                 "Parameter G");
1775             offset += param_len;
1776         }
1777     }
1778
1779     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1780 }
1781
1782 /*
1783  * 4.5.1.4
1784  */
1785 static void
1786 msg_key_gen_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1787 {
1788     guint8      param_len;
1789     guint32     saved_offset;
1790
1791     SHORT_DATA_CHECK(len, 2);
1792
1793     saved_offset = offset;
1794
1795     param_len = tvb_get_guint8(tvb, offset);
1796
1797     proto_tree_add_uint(tree, hf_ansi_683_length,
1798         tvb, offset, 1, param_len);
1799     offset++;
1800
1801     SHORT_DATA_CHECK((len - (offset - saved_offset)), param_len);
1802
1803     if (param_len > 0)
1804     {
1805         proto_tree_add_none_format(tree, hf_ansi_683_none,
1806             tvb, offset, param_len,
1807             "Base Station Calculation Result");
1808         offset += param_len;
1809     }
1810
1811     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1812 }
1813
1814 /*
1815  * 4.5.1.5
1816  */
1817 static void
1818 msg_reauth_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1819 {
1820
1821     EXACT_DATA_CHECK(len, 4);
1822
1823     proto_tree_add_none_format(tree, hf_ansi_683_none,
1824         tvb, offset, 4,
1825         "Random Challenge value");
1826 }
1827
1828 /*
1829  * 4.5.1.6
1830  * Commit Request (no data associated)
1831  */
1832
1833 /*
1834  * 4.5.1.7
1835  */
1836 static void
1837 msg_protocap_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1838 {
1839     guint32     i, saved_offset;
1840     guint8      oct, num_cap;
1841     const gchar *str = NULL;
1842
1843     if (len == 0)
1844     {
1845         /*
1846          * if the base station did not request new cap info OR
1847          * this is an earlier release
1848          */
1849         return;
1850     }
1851
1852     saved_offset = offset;
1853
1854     proto_tree_add_none_format(tree, hf_ansi_683_none,
1855         tvb, offset, 1,
1856         "OTASP protocol revision");
1857
1858     offset++;
1859
1860     num_cap = tvb_get_guint8(tvb, offset);
1861
1862     proto_tree_add_none_format(tree, hf_ansi_683_none,
1863         tvb, offset, 1,
1864         "Number of Capability Records (%u)",
1865         num_cap);
1866
1867     offset++;
1868
1869     SHORT_DATA_CHECK((len - (offset - saved_offset)), num_cap);
1870
1871     for (i=0; i < num_cap; i++)
1872     {
1873         oct = tvb_get_guint8(tvb, offset);
1874
1875         str = rev_cap_info_record_type(oct);
1876
1877         proto_tree_add_none_format(tree, hf_ansi_683_none,
1878             tvb, offset, 1,
1879             "[%u]:  %s (%u)",
1880             i+1,
1881             str,
1882             oct);
1883
1884         offset++;
1885     }
1886
1887     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1888 }
1889
1890 /*
1891  * 4.5.1.8
1892  */
1893 static void
1894 msg_sspr_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1895 {
1896     guint8      oct;
1897     const gchar *str = NULL;
1898     guint32     saved_offset;
1899     guint32     value;
1900     proto_tree  *subtree;
1901     proto_item  *item;
1902
1903     SHORT_DATA_CHECK(len, 1);
1904
1905     saved_offset = offset;
1906
1907     oct = tvb_get_guint8(tvb, offset);
1908
1909     str = rev_param_block_sspr(oct);
1910
1911     item =
1912         proto_tree_add_none_format(tree, hf_ansi_683_none,
1913             tvb, offset, 1,
1914             "%s (%u)",
1915             str,
1916             oct);
1917
1918     offset++;
1919
1920     if (oct == REV_BLOCK_SSPR_PRL)
1921     {
1922         subtree = proto_item_add_subtree(item, ett_rev_sspr_block);
1923
1924         if ((len - (offset - saved_offset)) < 3)
1925         {
1926             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
1927                 offset, len - (offset - saved_offset), "Short Data (?)");
1928             return;
1929         }
1930
1931         value = tvb_get_ntohs(tvb, offset);
1932
1933         proto_tree_add_none_format(subtree, hf_ansi_683_none,
1934             tvb, offset, 2,
1935             "Segment offset (%u)",
1936             value);
1937         offset += 2;
1938
1939         oct = tvb_get_guint8(tvb, offset);
1940
1941         proto_tree_add_none_format(subtree, hf_ansi_683_none,
1942             tvb, offset, 1,
1943             "Maximum segment size (%u)",
1944             oct);
1945         offset++;
1946     }
1947
1948     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1949 }
1950
1951 /*
1952  * 4.5.1.9
1953  */
1954 static void
1955 msg_sspr_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
1956 {
1957     guint8      oct, block_len;
1958     const gchar *str = NULL;
1959     guint32     saved_offset;
1960     proto_tree  *subtree;
1961     proto_item  *item;
1962
1963     SHORT_DATA_CHECK(len, 2);
1964
1965     saved_offset = offset;
1966
1967     oct = tvb_get_guint8(tvb, offset);
1968
1969     str = for_param_block_sspr(oct);
1970
1971     item =
1972         proto_tree_add_none_format(tree, hf_ansi_683_none,
1973             tvb, offset, 1,
1974             "%s (%u)",
1975             str,
1976             oct);
1977
1978     subtree = proto_item_add_subtree(item, ett_for_sspr_block);
1979     offset++;
1980
1981     block_len = tvb_get_guint8(tvb, offset);
1982
1983     proto_tree_add_uint(subtree, hf_ansi_683_length,
1984         tvb, offset, 1, block_len);
1985     offset++;
1986
1987     if (block_len > (len - (offset - saved_offset)))
1988     {
1989         proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
1990             offset, len - (offset - saved_offset), "Short Data (?)");
1991         return;
1992     }
1993
1994     if (block_len > 0)
1995     {
1996         proto_tree_add_none_format(subtree, hf_ansi_683_none,
1997             tvb, offset, block_len, "Block Data");
1998         offset += block_len;
1999     }
2000
2001     if (len > (offset - saved_offset))
2002     {
2003         offset +=
2004             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
2005     }
2006
2007     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2008 }
2009
2010 /*
2011  * 4.5.1.10
2012  */
2013 static void
2014 msg_validate_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2015 {
2016     guint8      block_id, num_blocks, block_len;
2017     const gchar *str = NULL;
2018     proto_tree  *subtree;
2019     proto_item  *item;
2020     guint32     i, saved_offset;
2021
2022     SHORT_DATA_CHECK(len, 1);
2023
2024     saved_offset = offset;
2025
2026     num_blocks = tvb_get_guint8(tvb, offset);
2027
2028     proto_tree_add_none_format(tree, hf_ansi_683_none,
2029         tvb, offset, 1,
2030         "Number of parameter blocks (%u)",
2031         num_blocks);
2032
2033     offset++;
2034
2035     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 2));
2036
2037     for (i=0; i < num_blocks; i++)
2038     {
2039         block_id = tvb_get_guint8(tvb, offset);
2040
2041         str = for_param_block_val(block_id);
2042
2043         item =
2044             proto_tree_add_none_format(tree, hf_ansi_683_none,
2045                 tvb, offset, 1,
2046                 "[%u]:  %s (%u)",
2047                 i+1,
2048                 str,
2049                 block_id);
2050
2051         subtree = proto_item_add_subtree(item, ett_for_val_block);
2052         offset++;
2053
2054         block_len = tvb_get_guint8(tvb, offset);
2055
2056         proto_tree_add_uint(subtree, hf_ansi_683_length,
2057             tvb, offset, 1, block_len);
2058
2059         offset++;
2060
2061         if (block_len > (len - (offset - saved_offset)))
2062         {
2063             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
2064                 offset, len - (offset - saved_offset), "Short Data (?)");
2065             return;
2066         }
2067
2068         if (block_len > 0)
2069         {
2070             switch (block_id)
2071             {
2072             case FOR_BLOCK_VAL_VERIFY_SPC:
2073             case FOR_BLOCK_VAL_CHANGE_SPC:
2074                 for_param_block_val_spc(tvb, subtree, block_len, offset);
2075                 break;
2076
2077             case FOR_BLOCK_VAL_VALDATE_SPASM:
2078                 for_param_block_val_spasm(tvb, subtree, block_len, offset);
2079                 break;
2080
2081             default:
2082                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
2083                     tvb, offset, block_len, "Block Data");
2084                 break;
2085             }
2086
2087             offset += block_len;
2088         }
2089     }
2090
2091     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2092 }
2093
2094 /*
2095  * 4.5.1.11
2096  */
2097 static void
2098 msg_otapa_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2099 {
2100     guint8      oct;
2101
2102     EXACT_DATA_CHECK(len, 1);
2103
2104     oct = tvb_get_guint8(tvb, offset);
2105
2106     other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
2107     proto_tree_add_none_format(tree, hf_ansi_683_none,
2108         tvb, offset, 1,
2109         "%s :  %s OTAPA session",
2110         bigbuf,
2111         (oct & 0x80) ? "Start" : "Stop");
2112
2113     other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
2114     proto_tree_add_none_format(tree, hf_ansi_683_none,
2115         tvb, offset, 1,
2116         "%s :  Reserved",
2117         bigbuf);
2118
2119     offset++;
2120 }
2121
2122 /*
2123  * 4.5.1.12
2124  */
2125 static void
2126 msg_puzl_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2127 {
2128     guint8      oct, block_len;
2129     const gchar *str = NULL;
2130     guint32     saved_offset;
2131     proto_tree  *subtree;
2132     proto_item  *item;
2133
2134     SHORT_DATA_CHECK(len, 1);
2135
2136     saved_offset = offset;
2137
2138     oct = tvb_get_guint8(tvb, offset);
2139
2140     str = rev_param_block_puzl(oct);
2141
2142     item =
2143         proto_tree_add_none_format(tree, hf_ansi_683_none,
2144             tvb, offset, 1,
2145             "%s (%u)",
2146             str,
2147             oct);
2148
2149     block_len = len - (offset - saved_offset);
2150
2151     if (block_len > 0)
2152     {
2153         subtree = proto_item_add_subtree(item, ett_rev_puzl_block);
2154
2155         proto_tree_add_none_format(subtree, hf_ansi_683_none,
2156             tvb, offset, block_len, "Block Data");
2157         offset += block_len;
2158     }
2159
2160     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2161 }
2162
2163 /*
2164  * 4.5.1.13
2165  */
2166 static void
2167 msg_puzl_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2168 {
2169     guint8      block_id, num_blocks, block_len;
2170     const gchar *str = NULL;
2171     proto_tree  *subtree;
2172     proto_item  *item;
2173     guint32     i, saved_offset;
2174
2175     SHORT_DATA_CHECK(len, 1);
2176
2177     saved_offset = offset;
2178
2179     num_blocks = tvb_get_guint8(tvb, offset);
2180
2181     proto_tree_add_none_format(tree, hf_ansi_683_none,
2182         tvb, offset, 1,
2183         "Number of parameter blocks (%u)",
2184         num_blocks);
2185
2186     offset++;
2187
2188     for (i=0; i < num_blocks; i++)
2189     {
2190         block_id = tvb_get_guint8(tvb, offset);
2191
2192         str = for_param_block_puzl(block_id);
2193
2194         item =
2195             proto_tree_add_none_format(tree, hf_ansi_683_none,
2196                 tvb, offset, 1,
2197                 "[%u]:  %s (%u)",
2198                 i+1,
2199                 str,
2200                 block_id);
2201
2202         subtree = proto_item_add_subtree(item, ett_for_puzl_block);
2203         offset++;
2204
2205         block_len = tvb_get_guint8(tvb, offset);
2206
2207         proto_tree_add_uint(subtree, hf_ansi_683_length,
2208             tvb, offset, 1, block_len);
2209         offset++;
2210
2211         if (block_len > (len - (offset - saved_offset)))
2212         {
2213             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
2214                 offset, len - (offset - saved_offset), "Short Data (?)");
2215             return;
2216         }
2217
2218         if (block_len > 0)
2219         {
2220             switch (block_id)
2221             {
2222             case FOR_BLOCK_PUZL_UZ_INS:
2223             case FOR_BLOCK_PUZL_UZ_UPD:
2224             case FOR_BLOCK_PUZL_UZ_DEL:
2225             case FOR_BLOCK_PUZL_UZ_PRI_CHANGE:
2226             case FOR_BLOCK_PUZL_FLAGS:
2227             default:
2228                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
2229                     tvb, offset, block_len, "Block Data");
2230                 break;
2231             }
2232
2233             offset += block_len;
2234         }
2235     }
2236
2237     if (len > (offset - saved_offset))
2238     {
2239         offset +=
2240             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
2241     }
2242
2243     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2244 }
2245
2246 /*
2247  * 4.5.1.14
2248  */
2249 static void
2250 msg_3gpd_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2251 {
2252     guint8      oct, num_blocks;
2253     const gchar *str = NULL;
2254     guint32     i, saved_offset;
2255
2256     SHORT_DATA_CHECK(len, 1);
2257
2258     saved_offset = offset;
2259
2260     num_blocks = tvb_get_guint8(tvb, offset);
2261
2262     proto_tree_add_none_format(tree, hf_ansi_683_none,
2263         tvb, offset, 1,
2264         "Number of parameter blocks (%u)",
2265         num_blocks);
2266
2267     offset++;
2268
2269     SHORT_DATA_CHECK((len - (offset - saved_offset)), num_blocks);
2270
2271     for (i=0; i < num_blocks; i++)
2272     {
2273         oct = tvb_get_guint8(tvb, offset);
2274
2275         str = rev_param_block_3gpd(oct);
2276
2277         proto_tree_add_none_format(tree, hf_ansi_683_none,
2278             tvb, offset, 1,
2279             "[%u]:  %s (%u)",
2280             i+1,
2281             str,
2282             oct);
2283
2284         offset++;
2285     }
2286
2287     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2288 }
2289
2290 /*
2291  * 4.5.1.15
2292  */
2293 static void
2294 msg_3gpd_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2295 {
2296     guint8      block_id, num_blocks, block_len;
2297     const gchar *str = NULL;
2298     proto_tree  *subtree;
2299     proto_item  *item;
2300     guint32     i, saved_offset;
2301
2302     SHORT_DATA_CHECK(len, 1);
2303
2304     saved_offset = offset;
2305
2306     num_blocks = tvb_get_guint8(tvb, offset);
2307
2308     proto_tree_add_none_format(tree, hf_ansi_683_none,
2309         tvb, offset, 1,
2310         "Number of parameter blocks (%u)",
2311         num_blocks);
2312
2313     offset++;
2314
2315     for (i=0; i < num_blocks; i++)
2316     {
2317         block_id = tvb_get_guint8(tvb, offset);
2318
2319         str = for_param_block_3gpd(block_id);
2320
2321         item =
2322             proto_tree_add_none_format(tree, hf_ansi_683_none,
2323                 tvb, offset, 1,
2324                 "[%u]:  %s (%u)",
2325                 i+1,
2326                 str,
2327                 block_id);
2328
2329         subtree = proto_item_add_subtree(item, ett_for_3gpd_block);
2330         offset++;
2331
2332         block_len = tvb_get_guint8(tvb, offset);
2333
2334         proto_tree_add_uint(subtree, hf_ansi_683_length,
2335             tvb, offset, 1, block_len);
2336         offset++;
2337
2338         if (block_len > (len - (offset - saved_offset)))
2339         {
2340             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
2341                 offset, len - (offset - saved_offset), "Short Data (?)");
2342             return;
2343         }
2344
2345         if (block_len > 0)
2346         {
2347             switch (block_id)
2348             {
2349             case FOR_BLOCK_3GPD_OP_MODE:
2350             case FOR_BLOCK_3GPD_SIP_USER_PRO:
2351             case FOR_BLOCK_3GPD_MIP_USER_PRO:
2352             case FOR_BLOCK_3GPD_SIP_STATUS:
2353             case FOR_BLOCK_3GPD_MIP_STATUS:
2354             case FOR_BLOCK_3GPD_SIP_PAP_SS:
2355             case FOR_BLOCK_3GPD_SIP_CHAP_SS:
2356             case FOR_BLOCK_3GPD_MIP_SS:
2357             case FOR_BLOCK_3GPD_HRPD_ACC_AUTH_USER:
2358             case FOR_BLOCK_3GPD_HRPD_ACC_AUTH_CHAP_SS:
2359             default:
2360                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
2361                     tvb, offset, block_len, "Block Data");
2362                 break;
2363             }
2364
2365             offset += block_len;
2366         }
2367     }
2368
2369     if (len > (offset - saved_offset))
2370     {
2371         offset +=
2372             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
2373     }
2374
2375     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2376 }
2377
2378 /*
2379  * 4.5.1.16
2380  */
2381 static void
2382 msg_secure_mode_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2383 {
2384     guint8      oct;
2385     const gchar *str = NULL;
2386     guint32     saved_offset;
2387
2388     SHORT_DATA_CHECK(len, 1);
2389
2390     saved_offset = offset;
2391
2392     oct = tvb_get_guint8(tvb, offset);
2393
2394     other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
2395     proto_tree_add_none_format(tree, hf_ansi_683_none,
2396         tvb, offset, 1,
2397         "%s :  %s Secure Mode",
2398         bigbuf,
2399         (oct & 0x80) ? "Start" : "Stop");
2400
2401     if (oct & 0x80)
2402     {
2403         switch ((oct & 0x78) >> 3)
2404         {
2405         case 0x0: str = "SMCK generation using SSD_A and SSD_B"; break;
2406         case 0x1: str = "SMCK generation using 3G Root Key"; break;
2407         default: str = "Key in use indicator"; break;
2408         }
2409     }
2410     else
2411     {
2412         str = "Key in use indicator";
2413     }
2414
2415     other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
2416     proto_tree_add_none_format(tree, hf_ansi_683_none,
2417         tvb, offset, 1,
2418         "%s :  %s",
2419         bigbuf,
2420         str);
2421
2422     other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
2423     proto_tree_add_none_format(tree, hf_ansi_683_none,
2424         tvb, offset, 1,
2425         "%s :  Reserved",
2426         bigbuf);
2427
2428     offset++;
2429
2430     if (oct & 0x80)
2431     {
2432         SHORT_DATA_CHECK(len, 8);
2433
2434         proto_tree_add_text(tree,
2435             tvb, offset, 8,
2436             "Random Number used for SMCK generation");
2437
2438         offset += 8;
2439     }
2440
2441     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2442 }
2443
2444 /*
2445  * 4.5.1.17
2446  * Reserved
2447  */
2448
2449 /*
2450  * 4.5.1.18
2451  */
2452 static void
2453 msg_mmd_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2454 {
2455     guint8      oct, num_blocks;
2456     const gchar *str = NULL;
2457     guint32     i, saved_offset;
2458
2459     SHORT_DATA_CHECK(len, 1);
2460
2461     saved_offset = offset;
2462
2463     num_blocks = tvb_get_guint8(tvb, offset);
2464
2465     proto_tree_add_none_format(tree, hf_ansi_683_none,
2466         tvb, offset, 1,
2467         "Number of parameter blocks (%u)",
2468         num_blocks);
2469
2470     offset++;
2471
2472     SHORT_DATA_CHECK((len - (offset - saved_offset)), num_blocks);
2473
2474     for (i=0; i < num_blocks; i++)
2475     {
2476         oct = tvb_get_guint8(tvb, offset);
2477
2478         str = rev_param_block_mmd(oct);
2479
2480         proto_tree_add_none_format(tree, hf_ansi_683_none,
2481             tvb, offset, 1,
2482             "[%u]:  %s (%u)",
2483             i+1,
2484             str,
2485             oct);
2486
2487         offset++;
2488     }
2489
2490     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2491 }
2492
2493 /*
2494  * 4.5.1.19
2495  */
2496 static void
2497 msg_mmd_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2498 {
2499     guint8      block_id, num_blocks, block_len;
2500     const gchar *str = NULL;
2501     proto_tree  *subtree;
2502     proto_item  *item;
2503     guint32     i, saved_offset;
2504
2505     SHORT_DATA_CHECK(len, 1);
2506
2507     saved_offset = offset;
2508
2509     num_blocks = tvb_get_guint8(tvb, offset);
2510
2511     proto_tree_add_none_format(tree, hf_ansi_683_none,
2512         tvb, offset, 1,
2513         "Number of parameter blocks (%u)",
2514         num_blocks);
2515
2516     offset++;
2517
2518     for (i=0; i < num_blocks; i++)
2519     {
2520         block_id = tvb_get_guint8(tvb, offset);
2521
2522         str = for_param_block_mmd(block_id);
2523
2524         item =
2525             proto_tree_add_none_format(tree, hf_ansi_683_none,
2526                 tvb, offset, 1,
2527                 "[%u]:  %s (%u)",
2528                 i+1,
2529                 str,
2530                 block_id);
2531
2532         subtree = proto_item_add_subtree(item, ett_for_mmd_block);
2533         offset++;
2534
2535         block_len = tvb_get_guint8(tvb, offset);
2536
2537         proto_tree_add_uint(subtree, hf_ansi_683_length,
2538             tvb, offset, 1, block_len);
2539         offset++;
2540
2541         if (block_len > (len - (offset - saved_offset)))
2542         {
2543             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
2544                 offset, len - (offset - saved_offset), "Short Data (?)");
2545             return;
2546         }
2547
2548         if (block_len > 0)
2549         {
2550             switch (block_id)
2551             {
2552             case FOR_BLOCK_MMD_APP:
2553             default:
2554                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
2555                     tvb, offset, block_len, "Block Data");
2556                 break;
2557             }
2558
2559             offset += block_len;
2560         }
2561     }
2562
2563     if (len > (offset - saved_offset))
2564     {
2565         offset +=
2566             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
2567     }
2568
2569     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2570 }
2571
2572 /*
2573  * 4.5.1.20
2574  */
2575 static void
2576 msg_systag_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2577 {
2578     guint8      oct;
2579     const gchar *str = NULL;
2580     guint32     saved_offset;
2581     guint32     value;
2582     proto_tree  *subtree;
2583     proto_item  *item;
2584
2585     SHORT_DATA_CHECK(len, 1);
2586
2587     saved_offset = offset;
2588
2589     oct = tvb_get_guint8(tvb, offset);
2590
2591     str = rev_param_block_systag(oct);
2592
2593     item =
2594         proto_tree_add_none_format(tree, hf_ansi_683_none,
2595             tvb, offset, 1,
2596             "%s (%u)",
2597             str,
2598             oct);
2599
2600     offset++;
2601
2602     /*
2603      * possible values, but unclear in spec
2604      *  REV_BLOCK_SYSTAG_HOME_SYSTAG
2605      *  REV_BLOCK_SYSTAG_GROUP_TAG_LIST_DIM
2606      *  REV_BLOCK_SYSTAG_GROUP_TAG_LIST
2607      *  REV_BLOCK_SYSTAG_SPEC_TAG_LIST_DIM
2608      *  REV_BLOCK_SYSTAG_SPEC_TAG_LIST
2609      *  REV_BLOCK_SYSTAG_CALL_PROMPT_LIST_DIM
2610      *  REV_BLOCK_SYSTAG_CALL_PROMPT_LIST
2611      */
2612     if (len > (offset - saved_offset))
2613     {
2614         SHORT_DATA_CHECK(len, 3);
2615
2616         subtree = proto_item_add_subtree(item, ett_segment);
2617
2618         value = tvb_get_ntohs(tvb, offset);
2619
2620         proto_tree_add_none_format(subtree, hf_ansi_683_none,
2621             tvb, offset, 2,
2622             "Segment offset (%u)",
2623             value);
2624         offset += 2;
2625
2626         oct = tvb_get_guint8(tvb, offset);
2627
2628         proto_tree_add_none_format(subtree, hf_ansi_683_none,
2629             tvb, offset, 1,
2630             "Maximum segment size (%u)",
2631             oct);
2632         offset++;
2633     }
2634
2635     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2636 }
2637
2638 /*
2639  * 4.5.1.21
2640  */
2641 static void
2642 msg_systag_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2643 {
2644     guint8      oct, block_len;
2645     const gchar *str = NULL;
2646     guint32     saved_offset;
2647
2648     SHORT_DATA_CHECK(len, 2);
2649
2650     saved_offset = offset;
2651
2652     oct = tvb_get_guint8(tvb, offset);
2653
2654     str = for_param_block_systag(oct);
2655
2656     proto_tree_add_none_format(tree, hf_ansi_683_none,
2657         tvb, offset, 1,
2658         "%s (%u)",
2659         str,
2660         oct);
2661
2662     offset++;
2663
2664     block_len = tvb_get_guint8(tvb, offset);
2665
2666     proto_tree_add_uint(tree, hf_ansi_683_length,
2667         tvb, offset, 1, block_len);
2668     offset++;
2669
2670     SHORT_DATA_CHECK((len - (offset - saved_offset)), block_len);
2671
2672     if (block_len > 0)
2673     {
2674         proto_tree_add_none_format(tree, hf_ansi_683_none,
2675             tvb, offset, block_len, "Block Data");
2676         offset += block_len;
2677     }
2678
2679     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2680 }
2681
2682
2683 /*
2684  * 4.5.1.22
2685  */
2686 static void
2687 msg_srvckey_gen_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2688 {
2689     guint32     saved_offset;
2690     guint32     value;
2691
2692     SHORT_DATA_CHECK(len, 2);
2693
2694     saved_offset = offset;
2695
2696     value = tvb_get_ntohs(tvb, offset);
2697
2698     other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
2699     proto_tree_add_none_format(tree, hf_ansi_683_none,
2700         tvb, offset, 2,
2701         "%s :  Key ID: IMS Root Key",
2702         bigbuf);
2703
2704     other_decode_bitfield_value(bigbuf, value, 0x4000, 16);
2705     proto_tree_add_none_format(tree, hf_ansi_683_none,
2706         tvb, offset, 2,
2707         "%s :  Key ID: BCMCS Root Key",
2708         bigbuf);
2709
2710     other_decode_bitfield_value(bigbuf, value, 0x2000, 16);
2711     proto_tree_add_none_format(tree, hf_ansi_683_none,
2712         tvb, offset, 2,
2713         "%s :  Key ID: WLAN Root Key",
2714         bigbuf);
2715
2716     other_decode_bitfield_value(bigbuf, value, 0x1ff0, 16);
2717     proto_tree_add_none_format(tree, hf_ansi_683_none,
2718         tvb, offset, 2,
2719         "%s :  Key ID: Reserved",
2720         bigbuf);
2721
2722     other_decode_bitfield_value(bigbuf, value, 0x000f, 16);
2723     proto_tree_add_none_format(tree, hf_ansi_683_none,
2724         tvb, offset, 2,
2725         "%s :  Reserved",
2726         bigbuf);
2727
2728     offset += 2;
2729
2730     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2731 }
2732
2733 /*
2734  * 4.5.1.23
2735  */
2736 static void
2737 msg_mms_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2738 {
2739     guint8      oct, num_blocks;
2740     const gchar *str = NULL;
2741     guint32     i, saved_offset;
2742
2743     SHORT_DATA_CHECK(len, 1);
2744
2745     saved_offset = offset;
2746
2747     num_blocks = tvb_get_guint8(tvb, offset);
2748
2749     proto_tree_add_none_format(tree, hf_ansi_683_none,
2750         tvb, offset, 1,
2751         "Number of parameter blocks (%u)",
2752         num_blocks);
2753
2754     offset++;
2755
2756     SHORT_DATA_CHECK((len - (offset - saved_offset)), num_blocks);
2757
2758     for (i=0; i < num_blocks; i++)
2759     {
2760         oct = tvb_get_guint8(tvb, offset);
2761
2762         str = rev_param_block_mms(oct);
2763
2764         proto_tree_add_none_format(tree, hf_ansi_683_none,
2765             tvb, offset, 1,
2766             "[%u]:  %s (%u)",
2767             i+1,
2768             str,
2769             oct);
2770
2771         offset++;
2772     }
2773
2774     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2775 }
2776
2777 /*
2778  * 4.5.1.24
2779  */
2780 static void
2781 msg_mms_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2782 {
2783     guint8      block_id, num_blocks, block_len;
2784     const gchar *str = NULL;
2785     proto_tree  *subtree;
2786     proto_item  *item;
2787     guint32     i, saved_offset;
2788
2789     SHORT_DATA_CHECK(len, 1);
2790
2791     saved_offset = offset;
2792
2793     num_blocks = tvb_get_guint8(tvb, offset);
2794
2795     proto_tree_add_none_format(tree, hf_ansi_683_none,
2796         tvb, offset, 1,
2797         "Number of parameter blocks (%u)",
2798         num_blocks);
2799
2800     offset++;
2801
2802     for (i=0; i < num_blocks; i++)
2803     {
2804         block_id = tvb_get_guint8(tvb, offset);
2805
2806         str = for_param_block_mms(block_id);
2807
2808         item =
2809             proto_tree_add_none_format(tree, hf_ansi_683_none,
2810                 tvb, offset, 1,
2811                 "[%u]:  %s (%u)",
2812                 i+1,
2813                 str,
2814                 block_id);
2815
2816         subtree = proto_item_add_subtree(item, ett_for_mms_block);
2817         offset++;
2818
2819         block_len = tvb_get_guint8(tvb, offset);
2820
2821         proto_tree_add_uint(subtree, hf_ansi_683_length,
2822             tvb, offset, 1, block_len);
2823         offset++;
2824
2825         if (block_len > (len - (offset - saved_offset)))
2826         {
2827             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
2828                 offset, len - (offset - saved_offset), "Short Data (?)");
2829             return;
2830         }
2831
2832         if (block_len > 0)
2833         {
2834             switch (block_id)
2835             {
2836             case FOR_BLOCK_MMS_URI:
2837             default:
2838                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
2839                     tvb, offset, block_len, "Block Data");
2840                 break;
2841             }
2842
2843             offset += block_len;
2844         }
2845     }
2846
2847     if (len > (offset - saved_offset))
2848     {
2849         offset +=
2850             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
2851     }
2852
2853     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2854 }
2855
2856 /* REVERSE MESSAGES */
2857
2858 /*
2859  * 3.5.1.1
2860  */
2861 static void
2862 msg_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2863 {
2864     guint8      oct, block_id, num_blocks, block_len;
2865     const gchar *str = NULL;
2866     guint32     i, saved_offset;
2867     proto_tree  *subtree;
2868     proto_item  *item;
2869
2870     SHORT_DATA_CHECK(len, 1);
2871
2872     saved_offset = offset;
2873
2874     num_blocks = tvb_get_guint8(tvb, offset);
2875
2876     proto_tree_add_none_format(tree, hf_ansi_683_none,
2877         tvb, offset, 1,
2878         "Number of parameter blocks (%u)",
2879         num_blocks);
2880
2881     offset++;
2882
2883     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 2));
2884
2885     for (i=0; i < num_blocks; i++)
2886     {
2887         block_id = tvb_get_guint8(tvb, offset);
2888
2889         str = rev_param_block_nam(block_id);
2890
2891         item =
2892             proto_tree_add_none_format(tree, hf_ansi_683_none,
2893                 tvb, offset, 1,
2894                 "[%u]:  %s (%u)",
2895                 i+1,
2896                 str,
2897                 block_id);
2898
2899         subtree = proto_item_add_subtree(item, ett_rev_nam_block);
2900         offset++;
2901
2902         block_len = tvb_get_guint8(tvb, offset);
2903
2904         proto_tree_add_uint(subtree, hf_ansi_683_length,
2905             tvb, offset, 1, block_len);
2906         offset++;
2907
2908         if (block_len > (len - (offset - saved_offset)))
2909         {
2910             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
2911                 offset, len - (offset - saved_offset), "Short Data (?)");
2912             return;
2913         }
2914
2915         if (block_len > 0)
2916         {
2917             switch (block_id)
2918             {
2919             case REV_BLOCK_NAM_CDMA_ANALOG:
2920                 rev_param_block_nam_cdma_analog(tvb, subtree, block_len, offset);
2921                 break;
2922
2923             case REV_BLOCK_NAM_MDN:
2924                 param_block_nam_mdn(tvb, subtree, block_len, offset);
2925                 break;
2926
2927             case REV_BLOCK_NAM_CDMA:
2928                 rev_param_block_nam_cdma(tvb, subtree, block_len, offset);
2929                 break;
2930
2931             case REV_BLOCK_NAM_IMSI_T:
2932                 param_block_nam_imsi_t(tvb, subtree, block_len, offset);
2933                 break;
2934
2935             default:
2936                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
2937                     tvb, offset, block_len, "Block Data");
2938                 break;
2939             }
2940
2941             offset += block_len;
2942         }
2943     }
2944
2945     SHORT_DATA_CHECK((len - (offset - saved_offset)), num_blocks);
2946
2947     for (i=0; i < num_blocks; i++)
2948     {
2949         oct = tvb_get_guint8(tvb, offset);
2950
2951         str = rev_res_code_type(oct);
2952
2953         proto_tree_add_none_format(tree, hf_ansi_683_none,
2954             tvb, offset, 1,
2955             "[%u]:  %s (%u)",
2956             i+1,
2957             str,
2958             oct);
2959
2960         offset++;
2961     }
2962
2963     if (len > (offset - saved_offset))
2964     {
2965         offset +=
2966             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
2967     }
2968
2969     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
2970 }
2971
2972 /*
2973  * 3.5.1.2
2974  */
2975 static void
2976 msg_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
2977 {
2978     guint8      oct, num_blocks;
2979     const gchar *str = NULL;
2980     guint32     i, saved_offset;
2981     proto_tree  *subtree;
2982     proto_item  *item;
2983
2984     SHORT_DATA_CHECK(len, 1);
2985
2986     saved_offset = offset;
2987
2988     num_blocks = tvb_get_guint8(tvb, offset);
2989
2990     proto_tree_add_none_format(tree, hf_ansi_683_none,
2991         tvb, offset, 1,
2992         "Number of parameter blocks (%u)",
2993         num_blocks);
2994
2995     offset++;
2996
2997     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 2));
2998
2999     for (i=0; i < num_blocks; i++)
3000     {
3001         oct = tvb_get_guint8(tvb, offset);
3002
3003         str = for_param_block_nam(oct);
3004
3005         item =
3006             proto_tree_add_none_format(tree, hf_ansi_683_none,
3007                 tvb, offset, 1,
3008                 "[%u]:  %s (%u)",
3009                 i+1,
3010                 str,
3011                 oct);
3012
3013         subtree = proto_item_add_subtree(item, ett_for_nam_block);
3014         offset++;
3015
3016         oct = tvb_get_guint8(tvb, offset);
3017
3018         str = rev_res_code_type(oct);
3019
3020         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3021             tvb, offset, 1,
3022             "%s (%u)",
3023             str,
3024             oct);
3025
3026         offset++;
3027     }
3028
3029     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3030 }
3031
3032 /*
3033  * 3.5.1.3
3034  */
3035 static void
3036 msg_ms_key_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3037 {
3038     guint8      oct;
3039     const gchar *str = NULL;
3040
3041     EXACT_DATA_CHECK(len, 1);
3042
3043     oct = tvb_get_guint8(tvb, offset);
3044
3045     str = rev_res_code_type(oct);
3046
3047     proto_tree_add_none_format(tree, hf_ansi_683_none,
3048         tvb, offset, 1,
3049         "Key exchange result code, %s (%u)",
3050         str,
3051         oct);
3052
3053     offset++;
3054 }
3055
3056 /*
3057  * 3.5.1.4
3058  */
3059 static void
3060 msg_key_gen_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3061 {
3062     guint8      oct, result_len;
3063     const gchar *str = NULL;
3064     guint32     saved_offset;
3065
3066     SHORT_DATA_CHECK(len, 2);
3067
3068     saved_offset = offset;
3069
3070     oct = tvb_get_guint8(tvb, offset);
3071
3072     str = rev_res_code_type(oct);
3073
3074     proto_tree_add_none_format(tree, hf_ansi_683_none,
3075         tvb, offset, 1,
3076         "Key exchange result code, %s (%u)",
3077         str,
3078         oct);
3079
3080     offset++;
3081
3082     result_len = tvb_get_guint8(tvb, offset);
3083
3084     proto_tree_add_uint(tree, hf_ansi_683_length,
3085         tvb, offset, 1, result_len);
3086     offset++;
3087
3088     SHORT_DATA_CHECK((len - (offset - saved_offset)), result_len);
3089
3090     if (result_len > 0)
3091     {
3092         proto_tree_add_none_format(tree, hf_ansi_683_none,
3093             tvb, offset, result_len, "Mobile station calculation result");
3094         offset += result_len;
3095     }
3096
3097     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3098 }
3099
3100 /*
3101  * 3.5.1.5
3102  */
3103 static void
3104 msg_reauth_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3105 {
3106     guint32     value;
3107
3108     EXACT_DATA_CHECK(len, 7);
3109
3110     value = tvb_get_ntoh24(tvb, offset);
3111
3112     other_decode_bitfield_value(bigbuf, value, 0xffffc0, 24);
3113     proto_tree_add_none_format(tree, hf_ansi_683_none,
3114         tvb, offset, 3,
3115         "%s :  Authentication signature data (AUTHR) (%u)",
3116         bigbuf,
3117         (value & 0xffffc0) >> 6);
3118
3119     offset += 2;
3120
3121     value = tvb_get_ntohs(tvb, offset);
3122
3123     other_decode_bitfield_value(bigbuf, value, 0x3fc0, 16);
3124     proto_tree_add_none_format(tree, hf_ansi_683_none,
3125         tvb, offset, 2,
3126         "%s :  Random challenge value (RANDC) (%u)",
3127         bigbuf,
3128         (value & 0x3fc0) >> 6);
3129
3130     other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
3131     proto_tree_add_none_format(tree, hf_ansi_683_none,
3132         tvb, offset + 1, 1,
3133         "%s :  Call history parameter (COUNT) (%u)",
3134         bigbuf,
3135         value & 0x3f);
3136
3137     offset += 2;
3138
3139     value = tvb_get_ntoh24(tvb, offset);
3140
3141     other_decode_bitfield_value(bigbuf, value, 0xffffff, 24);
3142     proto_tree_add_none_format(tree, hf_ansi_683_none,
3143         tvb, offset, 3,
3144         "%s :  Authentication Data input parameter (AUTH_DATA) (%u)",
3145         bigbuf,
3146         value);
3147 }
3148
3149 /*
3150  * 3.5.1.6
3151  */
3152 static void
3153 msg_commit_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3154 {
3155     guint8      oct;
3156     const gchar *str = NULL;
3157
3158     EXACT_DATA_CHECK(len, 1);
3159
3160     oct = tvb_get_guint8(tvb, offset);
3161
3162     str = rev_res_code_type(oct);
3163
3164     proto_tree_add_none_format(tree, hf_ansi_683_none,
3165         tvb, offset, 1,
3166         "Data commit result code, %s (%u)",
3167         str,
3168         oct);
3169
3170     offset++;
3171 }
3172
3173 /*
3174  * 3.5.1.7
3175  */
3176 static void
3177 msg_protocap_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3178 {
3179     guint8      oct, num_feat, add_len;
3180     const gchar *str = NULL;
3181     guint32     i, saved_offset;
3182     guint32     value;
3183     proto_tree  *subtree;
3184     proto_item  *item;
3185
3186     SHORT_DATA_CHECK(len, 5);
3187
3188     saved_offset = offset;
3189
3190     value = tvb_get_ntohs(tvb, offset);
3191
3192     proto_tree_add_none_format(tree, hf_ansi_683_none,
3193         tvb, offset, 2,
3194         "Mobile station firmware revision number (%u)",
3195         value);
3196
3197     offset += 2;
3198
3199     oct = tvb_get_guint8(tvb, offset);
3200
3201     proto_tree_add_none_format(tree, hf_ansi_683_none,
3202         tvb, offset, 1,
3203         "Mobile station manufacturer's model number (%u)",
3204         oct);
3205
3206     offset++;
3207
3208     num_feat = tvb_get_guint8(tvb, offset);
3209
3210     proto_tree_add_none_format(tree, hf_ansi_683_none,
3211         tvb, offset, 1,
3212         "Number of features (%u)",
3213         num_feat);
3214
3215     offset++;
3216
3217     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_feat * 2));
3218
3219     for (i=0; i < num_feat; i++)
3220     {
3221         oct = tvb_get_guint8(tvb, offset);
3222
3223         str = rev_feat_id_type(oct);
3224
3225         item =
3226             proto_tree_add_none_format(tree, hf_ansi_683_none,
3227                 tvb, offset, 1,
3228                 "[%u]:  Feature ID, %s (%u)",
3229                 i+1,
3230                 str,
3231                 oct);
3232
3233         subtree = proto_item_add_subtree(item, ett_rev_feat);
3234         offset++;
3235
3236         oct = tvb_get_guint8(tvb, offset);
3237
3238         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3239             tvb, offset, 1,
3240             "Feature protocol version (%u)",
3241             oct);
3242
3243         offset++;
3244     }
3245
3246     add_len = tvb_get_guint8(tvb, offset);
3247
3248     proto_tree_add_uint(tree, hf_ansi_683_length,
3249         tvb, offset, 1, add_len);
3250     offset++;
3251
3252     SHORT_DATA_CHECK((len - (offset - saved_offset)), add_len);
3253
3254     if (add_len > 0)
3255     {
3256         oct = tvb_get_guint8(tvb, offset);
3257
3258         item =
3259             proto_tree_add_none_format(tree, hf_ansi_683_none,
3260                 tvb, offset, 1,
3261                 "Band/Mode Capability Information");
3262
3263         subtree = proto_item_add_subtree(item, ett_band_cap);
3264
3265         other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
3266         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3267             tvb, offset, 1,
3268             "%s :  Band Class 0 Analog",
3269             bigbuf);
3270
3271         other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
3272         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3273             tvb, offset, 1,
3274             "%s :  Band Class 0 CDMA",
3275             bigbuf);
3276
3277         other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
3278         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3279             tvb, offset, 1,
3280             "%s :  Band Class 1 CDMA",
3281             bigbuf);
3282
3283         other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
3284         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3285             tvb, offset, 1,
3286             "%s :  Band Class 3 CDMA",
3287             bigbuf);
3288
3289         other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
3290         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3291             tvb, offset, 1,
3292             "%s :  Band Class 6 CDMA",
3293             bigbuf);
3294
3295         other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
3296         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3297             tvb, offset, 1,
3298             "%s :  Reserved",
3299             bigbuf);
3300
3301         offset++;
3302
3303         if (add_len > 1)
3304         {
3305             proto_tree_add_none_format(tree, hf_ansi_683_none,
3306                 tvb, offset, add_len - 1,
3307                 "More Additional Fields");
3308             offset += (add_len - 1);
3309         }
3310     }
3311
3312     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3313 }
3314
3315 /*
3316  * 3.5.1.8
3317  */
3318 static void
3319 msg_sspr_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3320 {
3321     guint8      oct, block_len;
3322     const gchar *str = NULL;
3323     guint32     saved_offset;
3324
3325     SHORT_DATA_CHECK(len, 3);
3326
3327     saved_offset = offset;
3328
3329     oct = tvb_get_guint8(tvb, offset);
3330
3331     str = rev_param_block_sspr(oct);
3332
3333     proto_tree_add_none_format(tree, hf_ansi_683_none,
3334         tvb, offset, 1,
3335         "%s (%u)",
3336         str,
3337         oct);
3338
3339     offset++;
3340
3341     oct = tvb_get_guint8(tvb, offset);
3342
3343     str = rev_res_code_type(oct);
3344
3345     proto_tree_add_none_format(tree, hf_ansi_683_none,
3346         tvb, offset, 1,
3347         "SSPR Configuration result code, %s (%u)",
3348         str,
3349         oct);
3350
3351     offset++;
3352
3353     block_len = tvb_get_guint8(tvb, offset);
3354
3355     proto_tree_add_uint(tree, hf_ansi_683_length,
3356         tvb, offset, 1, block_len);
3357     offset++;
3358
3359     SHORT_DATA_CHECK((len - (offset - saved_offset)), block_len);
3360
3361     if (block_len > 0)
3362     {
3363         proto_tree_add_none_format(tree, hf_ansi_683_none,
3364             tvb, offset, block_len, "Block Data");
3365         offset += block_len;
3366     }
3367
3368     if (len > (offset - saved_offset))
3369     {
3370         offset +=
3371             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
3372     }
3373
3374     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3375 }
3376
3377 /*
3378  * 3.5.1.9
3379  */
3380 static void
3381 msg_sspr_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3382 {
3383     guint8      oct, block_id;
3384     const gchar *str = NULL;
3385     guint32     value;
3386
3387     EXACT_DATA_CHECK(len, 5);
3388
3389     block_id = tvb_get_guint8(tvb, offset);
3390
3391     str = for_param_block_sspr(block_id);
3392
3393     proto_tree_add_none_format(tree, hf_ansi_683_none,
3394         tvb, offset, 1,
3395         "%s (%u)",
3396         str,
3397         block_id);
3398
3399     offset++;
3400
3401     oct = tvb_get_guint8(tvb, offset);
3402
3403     str = rev_res_code_type(oct);
3404
3405     proto_tree_add_none_format(tree, hf_ansi_683_none,
3406         tvb, offset, 1,
3407         "SSPR Download result code, %s (%u)",
3408         str,
3409         oct);
3410
3411     offset++;
3412
3413     switch (block_id)
3414     {
3415     case FOR_BLOCK_SSPR_PRL:
3416     case FOR_BLOCK_SSPR_EXT_PRL:
3417         value = tvb_get_ntohs(tvb, offset);
3418
3419         proto_tree_add_none_format(tree, hf_ansi_683_none,
3420             tvb, offset, 2,
3421             "Segment offset (%u)",
3422             value);
3423         offset += 2;
3424
3425         oct = tvb_get_guint8(tvb, offset);
3426
3427         proto_tree_add_none_format(tree, hf_ansi_683_none,
3428             tvb, offset, 1,
3429             "Maximum segment size (%u)",
3430             oct);
3431         offset++;
3432         break;
3433     }
3434 }
3435
3436 /*
3437  * 3.5.1.10
3438  */
3439 static void
3440 msg_validate_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3441 {
3442     guint8      oct, block_id, num_blocks;
3443     const gchar *str = NULL;
3444     guint32     i, saved_offset;
3445     proto_tree  *subtree;
3446     proto_item  *item;
3447
3448     SHORT_DATA_CHECK(len, 1);
3449
3450     saved_offset = offset;
3451
3452     num_blocks = tvb_get_guint8(tvb, offset);
3453
3454     proto_tree_add_none_format(tree, hf_ansi_683_none,
3455         tvb, offset, 1,
3456         "Number of parameter blocks (%u)",
3457         num_blocks);
3458
3459     offset++;
3460
3461     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 2));
3462
3463     for (i=0; i < num_blocks; i++)
3464     {
3465         block_id = tvb_get_guint8(tvb, offset);
3466
3467         str = for_param_block_val(block_id);
3468
3469         item =
3470             proto_tree_add_none_format(tree, hf_ansi_683_none,
3471                 tvb, offset, 1,
3472                 "[%u]:  %s (%u)",
3473                 i+1,
3474                 str,
3475                 block_id);
3476
3477         subtree = proto_item_add_subtree(item, ett_for_val_block);
3478         offset++;
3479
3480         oct = tvb_get_guint8(tvb, offset);
3481
3482         str = rev_res_code_type(oct);
3483
3484         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3485             tvb, offset, 1,
3486             "%s (%u)",
3487             str,
3488             oct);
3489
3490         offset++;
3491     }
3492
3493     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3494 }
3495
3496 /*
3497  * 3.5.1.11
3498  */
3499 static void
3500 msg_otapa_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3501 {
3502     guint8      oct;
3503     const gchar *str = NULL;
3504     guint32     saved_offset;
3505
3506     SHORT_DATA_CHECK(len, 2);
3507
3508     saved_offset = offset;
3509
3510     oct = tvb_get_guint8(tvb, offset);
3511
3512     str = rev_res_code_type(oct);
3513
3514     proto_tree_add_none_format(tree, hf_ansi_683_none,
3515         tvb, offset, 1,
3516         "%s (%d)",
3517         str,
3518         oct);
3519
3520     offset++;
3521
3522     oct = tvb_get_guint8(tvb, offset);
3523
3524     other_decode_bitfield_value(bigbuf, oct, 0xfe, 8);
3525     proto_tree_add_none_format(tree, hf_ansi_683_none,
3526         tvb, offset, 1,
3527         "%s :  Reserved",
3528         bigbuf);
3529
3530     other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
3531     proto_tree_add_none_format(tree, hf_ansi_683_none,
3532         tvb, offset, 1,
3533         "%s :  NAM_LOCK indicator",
3534         bigbuf);
3535
3536     offset++;
3537
3538     if (oct & 0x01)
3539     {
3540         SHORT_DATA_CHECK((len - (offset - saved_offset)), 4);
3541
3542         proto_tree_add_none_format(tree, hf_ansi_683_none,
3543             tvb, offset, 4,
3544             "SPASM random challenge");
3545         offset += 4;
3546     }
3547
3548     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3549 }
3550
3551 /*
3552  * 3.5.1.12
3553  */
3554 static void
3555 msg_puzl_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3556 {
3557     guint8      oct, block_len;
3558     const gchar *str = NULL;
3559     guint32     saved_offset;
3560
3561     SHORT_DATA_CHECK(len, 3);
3562
3563     saved_offset = offset;
3564
3565     oct = tvb_get_guint8(tvb, offset);
3566
3567     str = rev_param_block_puzl(oct);
3568
3569     proto_tree_add_none_format(tree, hf_ansi_683_none,
3570         tvb, offset, 1,
3571         "%s (%u)",
3572         str,
3573         oct);
3574
3575     offset++;
3576
3577     oct = tvb_get_guint8(tvb, offset);
3578
3579     str = rev_res_code_type(oct);
3580
3581     proto_tree_add_none_format(tree, hf_ansi_683_none,
3582         tvb, offset, 1,
3583         "PUZL Configuration result code, %s (%u)",
3584         str,
3585         oct);
3586
3587     offset++;
3588
3589     block_len = tvb_get_guint8(tvb, offset);
3590
3591     proto_tree_add_uint(tree, hf_ansi_683_length,
3592         tvb, offset, 1, block_len);
3593     offset++;
3594
3595     SHORT_DATA_CHECK((len - (offset - saved_offset)), block_len);
3596
3597     if (block_len > 0)
3598     {
3599         proto_tree_add_none_format(tree, hf_ansi_683_none,
3600             tvb, offset, block_len, "Block Data");
3601         offset += block_len;
3602     }
3603
3604     if (len > (offset - saved_offset))
3605     {
3606         offset +=
3607             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
3608     }
3609
3610     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3611 }
3612
3613 /*
3614  * 3.5.1.13
3615  */
3616 static void
3617 msg_puzl_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3618 {
3619     guint8      oct, block_id, num_blocks;
3620     const gchar *str = NULL;
3621     guint32     i, saved_offset;
3622     proto_tree  *subtree;
3623     proto_item  *item;
3624     guint32     value, temp_value;
3625
3626     SHORT_DATA_CHECK(len, 1);
3627
3628     saved_offset = offset;
3629
3630     num_blocks = tvb_get_guint8(tvb, offset);
3631
3632     proto_tree_add_none_format(tree, hf_ansi_683_none,
3633         tvb, offset, 1,
3634         "Number of parameter blocks (%u)",
3635         num_blocks);
3636
3637     offset++;
3638
3639     /* minimum required length */
3640     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 3));
3641
3642     for (i=0; i < num_blocks; i++)
3643     {
3644         block_id = tvb_get_guint8(tvb, offset);
3645
3646         str = for_param_block_puzl(block_id);
3647
3648         item =
3649             proto_tree_add_none_format(tree, hf_ansi_683_none,
3650                 tvb, offset, 1,
3651                 "[%u]:  %s (%u)",
3652                 i+1,
3653                 str,
3654                 block_id);
3655
3656         subtree = proto_item_add_subtree(item, ett_for_puzl_block);
3657         offset++;
3658
3659         oct = tvb_get_guint8(tvb, offset);
3660
3661         str = rev_res_code_type(oct);
3662
3663         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3664             tvb, offset, 1,
3665             "%s (%u)",
3666             str,
3667             oct);
3668
3669         offset++;
3670
3671         oct = tvb_get_guint8(tvb, offset);
3672
3673         if (oct & 0x80)
3674         {
3675             SHORT_DATA_CHECK(len, 4);
3676
3677             value = tvb_get_ntohs(tvb, offset);
3678
3679             other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
3680             proto_tree_add_none_format(tree, hf_ansi_683_none,
3681                 tvb, offset, 2,
3682                 "%s :  Identifiers present",
3683                 bigbuf);
3684
3685             other_decode_bitfield_value(bigbuf, value, 0x7fff, 16);
3686             proto_tree_add_none_format(tree, hf_ansi_683_none,
3687                 tvb, offset, 2,
3688                 "%s :  User Zone ID (MSB)",
3689                 bigbuf);
3690
3691             offset += 2;
3692
3693             temp_value = (value & 0x7fff) << 1;
3694             value = tvb_get_ntohs(tvb, offset);
3695
3696             other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
3697             proto_tree_add_none_format(tree, hf_ansi_683_none,
3698                 tvb, offset, 2,
3699                 "%s :  User Zone ID (%u)",
3700                 bigbuf,
3701                 temp_value + ((value & 0x8000) >> 15));
3702
3703             other_decode_bitfield_value(bigbuf, value, 0x7fff, 16);
3704             proto_tree_add_none_format(tree, hf_ansi_683_none,
3705                 tvb, offset, 2,
3706                 "%s :  User Zone SID (%u)",
3707                 bigbuf,
3708                 (value & 0x7fff));
3709
3710             offset += 2;
3711         }
3712         else
3713         {
3714             other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
3715             proto_tree_add_none_format(tree, hf_ansi_683_none,
3716                 tvb, offset, 1,
3717                 "%s :  Identifiers not present",
3718                 bigbuf);
3719
3720             other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
3721             proto_tree_add_none_format(tree, hf_ansi_683_none,
3722                 tvb, offset, 1,
3723                 "%s :  Reserved",
3724                 bigbuf);
3725
3726             offset++;
3727         }
3728     }
3729
3730     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3731 }
3732
3733 /*
3734  * 3.5.1.14
3735  */
3736 static void
3737 msg_3gpd_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3738 {
3739     guint8      oct, block_id, num_blocks, block_len;
3740     const gchar *str = NULL;
3741     guint32     i, saved_offset;
3742     proto_tree  *subtree;
3743     proto_item  *item;
3744
3745     SHORT_DATA_CHECK(len, 1);
3746
3747     saved_offset = offset;
3748
3749     num_blocks = tvb_get_guint8(tvb, offset);
3750
3751     proto_tree_add_none_format(tree, hf_ansi_683_none,
3752         tvb, offset, 1,
3753         "Number of parameter blocks (%u)",
3754         num_blocks);
3755
3756     offset++;
3757
3758     /* minimum required length */
3759     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 3));
3760
3761     for (i=0; i < num_blocks; i++)
3762     {
3763         block_id = tvb_get_guint8(tvb, offset);
3764
3765         str = rev_param_block_3gpd(block_id);
3766
3767         item =
3768             proto_tree_add_none_format(tree, hf_ansi_683_none,
3769                 tvb, offset, 1,
3770                 "[%u]:  %s (%u)",
3771                 i+1,
3772                 str,
3773                 block_id);
3774
3775         subtree = proto_item_add_subtree(item, ett_rev_3gpd_block);
3776         offset++;
3777
3778         block_len = tvb_get_guint8(tvb, offset);
3779
3780         proto_tree_add_uint(subtree, hf_ansi_683_length,
3781             tvb, offset, 1, block_len);
3782         offset++;
3783
3784         if (block_len > (len - (offset - saved_offset)))
3785         {
3786             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
3787                 offset, len - (offset - saved_offset), "Short Data (?)");
3788             return;
3789         }
3790
3791         if (block_len > 0)
3792         {
3793             switch (block_id)
3794             {
3795             case REV_BLOCK_3GPD_OP_CAP:
3796             case REV_BLOCK_3GPD_OP_MODE:
3797             case REV_BLOCK_3GPD_SIP_CAP:
3798             case REV_BLOCK_3GPD_MIP_CAP:
3799             case REV_BLOCK_3GPD_SIP_USER_PRO:
3800             case REV_BLOCK_3GPD_MIP_USER_PRO:
3801             case REV_BLOCK_3GPD_SIP_STATUS:
3802             case REV_BLOCK_3GPD_MIP_STATUS:
3803             case REV_BLOCK_3GPD_SIP_PAP_SS:
3804             case REV_BLOCK_3GPD_SIP_CHAP_SS:
3805             case REV_BLOCK_3GPD_MIP_SS:
3806             case REV_BLOCK_3GPD_HRPD_ACC_AUTH_CAP:
3807             case REV_BLOCK_3GPD_HRPD_ACC_AUTH_USER:
3808             case REV_BLOCK_3GPD_HRPD_ACC_AUTH_CHAP_SS:
3809             default:
3810                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
3811                     tvb, offset, block_len, "Block Data");
3812                 break;
3813             }
3814
3815             offset += block_len;
3816         }
3817
3818         SHORT_DATA_CHECK(len, 1);
3819
3820         oct = tvb_get_guint8(tvb, offset);
3821
3822         str = rev_res_code_type(oct);
3823
3824         proto_tree_add_none_format(tree, hf_ansi_683_none,
3825             tvb, offset, 1,
3826             "%s (%u)",
3827             str,
3828             oct);
3829
3830         offset++;
3831     }
3832
3833     if (len > (offset - saved_offset))
3834     {
3835         offset +=
3836             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
3837     }
3838
3839     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3840 }
3841
3842 /*
3843  * 3.5.1.15
3844  */
3845 static void
3846 msg_3gpd_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3847 {
3848     guint8      oct, num_blocks;
3849     const gchar *str = NULL;
3850     guint32     i, saved_offset;
3851     proto_tree  *subtree;
3852     proto_item  *item;
3853
3854     SHORT_DATA_CHECK(len, 1);
3855
3856     saved_offset = offset;
3857
3858     num_blocks = tvb_get_guint8(tvb, offset);
3859
3860     proto_tree_add_none_format(tree, hf_ansi_683_none,
3861         tvb, offset, 1,
3862         "Number of parameter blocks (%u)",
3863         num_blocks);
3864
3865     offset++;
3866
3867     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 2));
3868
3869     for (i=0; i < num_blocks; i++)
3870     {
3871         oct = tvb_get_guint8(tvb, offset);
3872
3873         str = for_param_block_3gpd(oct);
3874
3875         item =
3876             proto_tree_add_none_format(tree, hf_ansi_683_none,
3877                 tvb, offset, 1,
3878                 "[%u]:  %s (%u)",
3879                 i+1,
3880                 str,
3881                 oct);
3882
3883         subtree = proto_item_add_subtree(item, ett_for_3gpd_block);
3884         offset++;
3885
3886         oct = tvb_get_guint8(tvb, offset);
3887
3888         str = rev_res_code_type(oct);
3889
3890         proto_tree_add_none_format(subtree, hf_ansi_683_none,
3891             tvb, offset, 1,
3892             "%s (%u)",
3893             str,
3894             oct);
3895
3896         offset++;
3897     }
3898
3899     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
3900 }
3901
3902 /*
3903  * 3.5.1.16
3904  */
3905 static void
3906 msg_secure_mode_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3907 {
3908     guint8      oct;
3909     const gchar *str = NULL;
3910
3911     EXACT_DATA_CHECK(len, 1);
3912
3913     oct = tvb_get_guint8(tvb, offset);
3914
3915     str = rev_res_code_type(oct);
3916
3917     proto_tree_add_none_format(tree, hf_ansi_683_none,
3918         tvb, offset, 1,
3919         "Secure Mode result code, %s (%u)",
3920         str,
3921         oct);
3922
3923     offset++;
3924 }
3925
3926 /*
3927  * 3.5.1.17
3928  */
3929 static void
3930 msg_ext_protocap_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
3931 {
3932     guint8      oct, block_id, num_recs, block_len;
3933     const gchar *str = NULL;
3934     guint32     i, saved_offset;
3935     guint32     value;
3936     proto_tree  *subtree;
3937     proto_item  *item;
3938
3939     SHORT_DATA_CHECK(len, 6);
3940
3941     saved_offset = offset;
3942
3943     oct = tvb_get_guint8(tvb, offset);
3944
3945     proto_tree_add_none_format(tree, hf_ansi_683_none,
3946         tvb, offset, 1,
3947         "OTASP Mobile Protocol Revision (%u)",
3948         oct);
3949
3950     offset++;
3951
3952     value = tvb_get_ntohs(tvb, offset);
3953
3954     proto_tree_add_none_format(tree, hf_ansi_683_none,
3955         tvb, offset, 2,
3956         "Mobile station firmware revision number (%u)",
3957         value);
3958
3959     offset += 2;
3960
3961     oct = tvb_get_guint8(tvb, offset);
3962
3963     proto_tree_add_none_format(tree, hf_ansi_683_none,
3964         tvb, offset, 1,
3965         "Mobile station manufacturer's model number (%u)",
3966         oct);
3967
3968     offset++;
3969
3970     num_recs = tvb_get_guint8(tvb, offset);
3971
3972     proto_tree_add_none_format(tree, hf_ansi_683_none,
3973         tvb, offset, 1,
3974         "Number of features (%u)",
3975         num_recs);
3976
3977     offset++;
3978
3979     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_recs * 2));
3980
3981     for (i=0; i < num_recs; i++)
3982     {
3983         oct = tvb_get_guint8(tvb, offset);
3984
3985         str = rev_feat_id_type(oct);
3986
3987         item =
3988             proto_tree_add_none_format(tree, hf_ansi_683_none,
3989                 tvb, offset, 1,
3990                 "[%u]:  Feature ID, %s (%u)",
3991                 i+1,
3992                 str,
3993                 oct);
3994
3995         subtree = proto_item_add_subtree(item, ett_rev_feat);
3996         offset++;
3997
3998         oct = tvb_get_guint8(tvb, offset);
3999
4000         proto_tree_add_none_format(subtree, hf_ansi_683_none,
4001             tvb, offset, 1,
4002             "Feature protocol version (%u)",
4003             oct);
4004
4005         offset++;
4006     }
4007
4008     SHORT_DATA_CHECK((len - (offset - saved_offset)), 1);
4009
4010     num_recs = tvb_get_guint8(tvb, offset);
4011
4012     proto_tree_add_none_format(tree, hf_ansi_683_none,
4013         tvb, offset, 1,
4014         "Number of Capability Records (%u)",
4015         num_recs);
4016
4017     offset++;
4018
4019     /* minimum required length */
4020     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_recs * 2));
4021
4022     for (i=0; i < num_recs; i++)
4023     {
4024         block_id = tvb_get_guint8(tvb, offset);
4025
4026         str = rev_cap_info_record_type(block_id);
4027
4028         item =
4029             proto_tree_add_none_format(tree, hf_ansi_683_none,
4030                 tvb, offset, 1,
4031                 "[%u]:  %s (%u)",
4032                 i+1,
4033                 str,
4034                 block_id);
4035
4036         subtree = proto_item_add_subtree(item, ett_rev_cap);
4037         offset++;
4038
4039         block_len = tvb_get_guint8(tvb, offset);
4040
4041         proto_tree_add_uint(subtree, hf_ansi_683_length,
4042             tvb, offset, 1, block_len);
4043         offset++;
4044
4045         if (block_len > (len - (offset - saved_offset)))
4046         {
4047             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
4048                 offset, len - (offset - saved_offset), "Short Data (?)");
4049             return;
4050         }
4051
4052         if (block_len > 0)
4053         {
4054             switch (block_id)
4055             {
4056 #ifdef MLUM
4057             case REV_TYPE_CAP_INFO_OP_MODE:
4058             case REV_TYPE_CAP_INFO_CDMA_BAND:
4059             case REV_TYPE_CAP_INFO_MEID:
4060             case REV_TYPE_CAP_INFO_ICCID:
4061             case REV_TYPE_CAP_INFO_EXT_UIM_ID:
4062                 rev_param_block_mmd_app(tvb, subtree, block_len, offset);
4063                 break;
4064 #endif
4065
4066             default:
4067                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
4068                     tvb, offset, block_len, "Capability Data");
4069                 break;
4070             }
4071
4072             offset += block_len;
4073         }
4074     }
4075
4076     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
4077 }
4078
4079 /*
4080  * 3.5.1.18
4081  */
4082 static void
4083 msg_mmd_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
4084 {
4085     guint8      oct, block_id, num_blocks, block_len;
4086     const gchar *str = NULL;
4087     guint32     i, saved_offset;
4088     proto_tree  *subtree;
4089     proto_item  *item;
4090
4091     SHORT_DATA_CHECK(len, 1);
4092
4093     saved_offset = offset;
4094
4095     num_blocks = tvb_get_guint8(tvb, offset);
4096
4097     proto_tree_add_none_format(tree, hf_ansi_683_none,
4098         tvb, offset, 1,
4099         "Number of parameter blocks (%u)",
4100         num_blocks);
4101
4102     offset++;
4103
4104     /* minimum required length */
4105     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 3));
4106
4107     for (i=0; i < num_blocks; i++)
4108     {
4109         block_id = tvb_get_guint8(tvb, offset);
4110
4111         str = rev_param_block_mmd(block_id);
4112
4113         item =
4114             proto_tree_add_none_format(tree, hf_ansi_683_none,
4115                 tvb, offset, 1,
4116                 "[%u]:  %s (%u)",
4117                 i+1,
4118                 str,
4119                 block_id);
4120
4121         subtree = proto_item_add_subtree(item, ett_rev_mmd_block);
4122         offset++;
4123
4124         block_len = tvb_get_guint8(tvb, offset);
4125
4126         proto_tree_add_uint(subtree, hf_ansi_683_length,
4127             tvb, offset, 1, block_len);
4128         offset++;
4129
4130         if (block_len > (len - (offset - saved_offset)))
4131         {
4132             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
4133                 offset, len - (offset - saved_offset), "Short Data (?)");
4134             return;
4135         }
4136
4137         if (block_len > 0)
4138         {
4139             switch (block_id)
4140             {
4141 #ifdef MLUM
4142             case REV_BLOCK_MMD_APP:
4143                 rev_param_block_mmd_app(tvb, subtree, block_len, offset);
4144                 break;
4145 #endif
4146
4147             default:
4148                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
4149                     tvb, offset, block_len, "Block Data");
4150                 break;
4151             }
4152
4153             offset += block_len;
4154         }
4155
4156         SHORT_DATA_CHECK(len, 1);
4157
4158         oct = tvb_get_guint8(tvb, offset);
4159
4160         str = rev_res_code_type(oct);
4161
4162         proto_tree_add_none_format(tree, hf_ansi_683_none,
4163             tvb, offset, 1,
4164             "%s (%u)",
4165             str,
4166             oct);
4167
4168         offset++;
4169     }
4170
4171     if (len > (offset - saved_offset))
4172     {
4173         offset +=
4174             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
4175     }
4176
4177     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
4178 }
4179
4180 /*
4181  * 3.5.1.19
4182  */
4183 static void
4184 msg_mmd_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
4185 {
4186     guint8      oct, num_blocks;
4187     const gchar *str = NULL;
4188     guint32     i, saved_offset;
4189     proto_tree  *subtree;
4190     proto_item  *item;
4191
4192     SHORT_DATA_CHECK(len, 1);
4193
4194     saved_offset = offset;
4195
4196     num_blocks = tvb_get_guint8(tvb, offset);
4197
4198     proto_tree_add_none_format(tree, hf_ansi_683_none,
4199         tvb, offset, 1,
4200         "Number of parameter blocks (%u)",
4201         num_blocks);
4202
4203     offset++;
4204
4205     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 2));
4206
4207     for (i=0; i < num_blocks; i++)
4208     {
4209         oct = tvb_get_guint8(tvb, offset);
4210
4211         str = for_param_block_mmd(oct);
4212
4213         item =
4214             proto_tree_add_none_format(tree, hf_ansi_683_none,
4215                 tvb, offset, 1,
4216                 "[%u]:  %s (%u)",
4217                 i+1,
4218                 str,
4219                 oct);
4220
4221         subtree = proto_item_add_subtree(item, ett_for_mmd_block);
4222         offset++;
4223
4224         oct = tvb_get_guint8(tvb, offset);
4225
4226         str = rev_res_code_type(oct);
4227
4228         proto_tree_add_none_format(subtree, hf_ansi_683_none,
4229             tvb, offset, 1,
4230             "%s (%u)",
4231             str,
4232             oct);
4233
4234         offset++;
4235     }
4236
4237     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
4238 }
4239
4240 /*
4241  * 3.5.1.20
4242  */
4243 static void
4244 msg_systag_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
4245 {
4246     guint8      oct, block_len;
4247     const gchar *str = NULL;
4248     guint32     saved_offset;
4249
4250     SHORT_DATA_CHECK(len, 3);
4251
4252     saved_offset = offset;
4253
4254     oct = tvb_get_guint8(tvb, offset);
4255
4256     str = rev_param_block_systag(oct);
4257
4258     proto_tree_add_none_format(tree, hf_ansi_683_none,
4259         tvb, offset, 1,
4260         "%s (%u)",
4261         str,
4262         oct);
4263
4264     offset++;
4265
4266     oct = tvb_get_guint8(tvb, offset);
4267
4268     str = rev_res_code_type(oct);
4269
4270     proto_tree_add_none_format(tree, hf_ansi_683_none,
4271         tvb, offset, 1,
4272         "System Tag result code, %s (%u)",
4273         str,
4274         oct);
4275
4276     offset++;
4277
4278     block_len = tvb_get_guint8(tvb, offset);
4279
4280     proto_tree_add_uint(tree, hf_ansi_683_length,
4281         tvb, offset, 1, block_len);
4282     offset++;
4283
4284     SHORT_DATA_CHECK((len - (offset - saved_offset)), block_len);
4285
4286     if (block_len > 0)
4287     {
4288         proto_tree_add_none_format(tree, hf_ansi_683_none,
4289             tvb, offset, block_len, "Block Data");
4290         offset += block_len;
4291     }
4292
4293     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
4294 }
4295
4296 /*
4297  * 3.5.1.21
4298  */
4299 static void
4300 msg_systag_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
4301 {
4302     guint8      oct, block_id;
4303     const gchar *str = NULL;
4304     guint32     saved_offset;
4305     guint32     value;
4306
4307     SHORT_DATA_CHECK(len, 2);
4308
4309     saved_offset = offset;
4310
4311     block_id = tvb_get_guint8(tvb, offset);
4312
4313     str = for_param_block_systag(block_id);
4314
4315     proto_tree_add_none_format(tree, hf_ansi_683_none,
4316         tvb, offset, 1,
4317         "%s (%u)",
4318         str,
4319         block_id);
4320
4321     offset++;
4322
4323     oct = tvb_get_guint8(tvb, offset);
4324
4325     str = rev_res_code_type(oct);
4326
4327     proto_tree_add_none_format(tree, hf_ansi_683_none,
4328         tvb, offset, 1,
4329         "System Tag Download result code, %s (%u)",
4330         str,
4331         oct);
4332
4333     offset++;
4334
4335     switch (block_id)
4336     {
4337     case 0x01:          /* Group Tag List Parameter */
4338     case 0x02:          /* Specific Tag List Parameter */
4339     case 0x03:          /* Call Prompt List Parameter */
4340         SHORT_DATA_CHECK(len, 3);
4341
4342         value = tvb_get_ntohs(tvb, offset);
4343
4344         proto_tree_add_none_format(tree, hf_ansi_683_none,
4345             tvb, offset, 2,
4346             "Segment offset (%u)",
4347             value);
4348         offset += 2;
4349
4350         oct = tvb_get_guint8(tvb, offset);
4351
4352         proto_tree_add_none_format(tree, hf_ansi_683_none,
4353             tvb, offset, 1,
4354             "Segment size (%u)",
4355             oct);
4356         offset++;
4357         break;
4358
4359     default:
4360         break;
4361     }
4362
4363     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
4364 }
4365
4366 /*
4367  * 3.5.1.22
4368  */
4369 static void
4370 msg_srvckey_gen_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
4371 {
4372     guint8      oct;
4373     const gchar *str = NULL;
4374
4375     EXACT_DATA_CHECK(len, 1);
4376
4377     oct = tvb_get_guint8(tvb, offset);
4378
4379     str = rev_res_code_type(oct);
4380
4381     proto_tree_add_none_format(tree, hf_ansi_683_none,
4382         tvb, offset, 1,
4383         "Service Key Generation result code, %s (%u)",
4384         str,
4385         oct);
4386
4387     offset++;
4388 }
4389
4390 /*
4391  * 3.5.1.23
4392  */
4393 static void
4394 msg_mms_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
4395 {
4396     guint8      oct, block_id, num_blocks, block_len;
4397     const gchar *str = NULL;
4398     guint32     i, saved_offset;
4399     proto_tree  *subtree;
4400     proto_item  *item;
4401
4402     SHORT_DATA_CHECK(len, 1);
4403
4404     saved_offset = offset;
4405
4406     num_blocks = tvb_get_guint8(tvb, offset);
4407
4408     proto_tree_add_none_format(tree, hf_ansi_683_none,
4409         tvb, offset, 1,
4410         "Number of parameter blocks (%u)",
4411         num_blocks);
4412
4413     offset++;
4414
4415     /* minimum required length */
4416     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 3));
4417
4418     for (i=0; i < num_blocks; i++)
4419     {
4420         block_id = tvb_get_guint8(tvb, offset);
4421
4422         str = rev_param_block_mms(block_id);
4423
4424         item =
4425             proto_tree_add_none_format(tree, hf_ansi_683_none,
4426                 tvb, offset, 1,
4427                 "[%u]:  %s (%u)",
4428                 i+1,
4429                 str,
4430                 block_id);
4431
4432         subtree = proto_item_add_subtree(item, ett_rev_mms_block);
4433         offset++;
4434
4435         block_len = tvb_get_guint8(tvb, offset);
4436
4437         proto_tree_add_uint(subtree, hf_ansi_683_length,
4438             tvb, offset, 1, block_len);
4439         offset++;
4440
4441         if (block_len > (len - (offset - saved_offset)))
4442         {
4443             proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
4444                 offset, len - (offset - saved_offset), "Short Data (?)");
4445             return;
4446         }
4447
4448         if (block_len > 0)
4449         {
4450             switch (block_id)
4451             {
4452 #ifdef MLUM
4453             case REV_BLOCK_MMS_URI:
4454                 rev_param_block_mms_uri(tvb, subtree, block_len, offset);
4455                 break;
4456
4457             case REV_BLOCK_MMS_URI_CAP:
4458                 rev_param_block_mms_uri_cap(tvb, subtree, block_len, offset);
4459                 break;
4460 #endif
4461
4462             default:
4463                 proto_tree_add_none_format(subtree, hf_ansi_683_none,
4464                     tvb, offset, block_len, "Block Data");
4465                 break;
4466             }
4467
4468             offset += block_len;
4469         }
4470
4471         SHORT_DATA_CHECK(len, 1);
4472
4473         oct = tvb_get_guint8(tvb, offset);
4474
4475         str = rev_res_code_type(oct);
4476
4477         proto_tree_add_none_format(tree, hf_ansi_683_none,
4478             tvb, offset, 1,
4479             "%s (%u)",
4480             str,
4481             oct);
4482
4483         offset++;
4484     }
4485
4486     if (len > (offset - saved_offset))
4487     {
4488         offset +=
4489             fresh_handler(tvb, tree, len - (offset - saved_offset), offset);
4490     }
4491
4492     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
4493 }
4494
4495 /*
4496  * 3.5.1.24
4497  */
4498 static void
4499 msg_mms_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
4500 {
4501     guint8      oct, num_blocks;
4502     const gchar *str = NULL;
4503     guint32     i, saved_offset;
4504     proto_tree  *subtree;
4505     proto_item  *item;
4506
4507     SHORT_DATA_CHECK(len, 1);
4508
4509     saved_offset = offset;
4510
4511     num_blocks = tvb_get_guint8(tvb, offset);
4512
4513     proto_tree_add_none_format(tree, hf_ansi_683_none,
4514         tvb, offset, 1,
4515         "Number of parameter blocks (%u)",
4516         num_blocks);
4517
4518     offset++;
4519
4520     SHORT_DATA_CHECK((len - (offset - saved_offset)), (guint32)(num_blocks * 2));
4521
4522     for (i=0; i < num_blocks; i++)
4523     {
4524         oct = tvb_get_guint8(tvb, offset);
4525
4526         str = for_param_block_mms(oct);
4527
4528         item =
4529             proto_tree_add_none_format(tree, hf_ansi_683_none,
4530                 tvb, offset, 1,
4531                 "[%u]:  %s (%u)",
4532                 i+1,
4533                 str,
4534                 oct);
4535
4536         subtree = proto_item_add_subtree(item, ett_for_mms_block);
4537         offset++;
4538
4539         oct = tvb_get_guint8(tvb, offset);
4540
4541         str = rev_res_code_type(oct);
4542
4543         proto_tree_add_none_format(subtree, hf_ansi_683_none,
4544             tvb, offset, 1,
4545             "%s (%u)",
4546             str,
4547             oct);
4548
4549         offset++;
4550     }
4551
4552     EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
4553 }
4554
4555 static const value_string for_msg_type_strings[] = {
4556     { 0,        "Configuration Request" },
4557     { 1,        "Download Request" },
4558     { 2,        "MS Key Request" },
4559     { 3,        "Key Generation Request" },
4560     { 4,        "Re-Authenticate Request" },
4561     { 5,        "Commit Request" },
4562     { 6,        "Protocol Capability Request" },
4563     { 7,        "SSPR Configuration Request" },
4564     { 8,        "SSPR Download Request" },
4565     { 9,        "Validation Request" },
4566     { 10,       "OTAPA Request" },
4567     { 11,       "PUZL Configuration Request" },
4568     { 12,       "PUZL Download Request" },
4569     { 13,       "3GPD Configuration Request" },
4570     { 14,       "3GPD Download Request" },
4571     { 15,       "Secure Mode Request" },
4572     { 16,       "Reserved" },
4573     { 17,       "MMD Configuration Request" },
4574     { 18,       "MMD Download Request" },
4575     { 19,       "System Tag Configuration Request" },
4576     { 20,       "System Tag Download Request" },
4577     { 21,       "Service Key Generation Request" },
4578     { 22,       "MMS Configuration Request" },
4579     { 23,       "MMS Download Request" },
4580     { 0, NULL }
4581 };
4582 #define NUM_FOR_MSGS (sizeof(for_msg_type_strings)/sizeof(value_string))
4583 static void (*ansi_683_for_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
4584     msg_config_req,             /* Configuration Request */
4585     msg_download_req,           /* Download Request */
4586     msg_ms_key_req,             /* MS Key Request */
4587     msg_key_gen_req,            /* Key Generation Request */
4588     msg_reauth_req,             /* Re-Authenticate Request */
4589     NULL         /* No data */, /* Commit Request */
4590     msg_protocap_req,           /* Protocol Capability Request */
4591     msg_sspr_config_req,        /* SSPR Configuration Request */
4592     msg_sspr_download_req,      /* SSPR Download Request */
4593     msg_validate_req,           /* Validation Request */
4594     msg_otapa_req,              /* OTAPA Request */
4595     msg_puzl_config_req,        /* PUZL Configuration Request */
4596     msg_puzl_download_req,      /* PUZL Download Request */
4597     msg_3gpd_config_req,        /* 3GPD Configuration Request */
4598     msg_3gpd_download_req,      /* 3GPD Download Request */
4599     msg_secure_mode_req,        /* Secure Mode Request */
4600     NULL,               /* Reserved */
4601     msg_mmd_config_req,         /* MMD Configuration Request */
4602     msg_mmd_download_req,       /* MMD Download Request */
4603     msg_systag_config_req,      /* System Tag Configuration Request */
4604     msg_systag_download_req,    /* System Tag Download Request */
4605     msg_srvckey_gen_req,        /* Service Key Generation Request */
4606     msg_mms_config_req,         /* MMS Configuration Request */
4607     msg_mms_download_req,       /* MMS Download Request */
4608     NULL        /* NONE */
4609 };
4610
4611 static const value_string rev_msg_type_strings[] = {
4612     { 0,        "Configuration Response" },
4613     { 1,        "Download Response" },
4614     { 2,        "MS Key Response" },
4615     { 3,        "Key Generation Response" },
4616     { 4,        "Re-Authenticate Response" },
4617     { 5,        "Commit Response" },
4618     { 6,        "Protocol Capability Response" },
4619     { 7,        "SSPR Configuration Response" },
4620     { 8,        "SSPR Download Response" },
4621     { 9,        "Validation Response" },
4622     { 10,       "OTAPA Response" },
4623     { 11,       "PUZL Configuration Response" },
4624     { 12,       "PUZL Download Response" },
4625     { 13,       "3GPD Configuration Response" },
4626     { 14,       "3GPD Download Response" },
4627     { 15,       "Secure Mode Response" },
4628     { 16,       "Extended Protocol Capability Response" },
4629     { 17,       "MMD Configuration Response" },
4630     { 18,       "MMD Download Response" },
4631     { 19,       "System Tag Configuration Response" },
4632     { 20,       "System Tag Download Response" },
4633     { 21,       "Service Key Generation Response" },
4634     { 22,       "MMS Configuration Response" },
4635     { 23,       "MMS Download Response" },
4636     { 0, NULL }
4637 };
4638 #define NUM_REV_MSGS (sizeof(rev_msg_type_strings)/sizeof(value_string))
4639 static void (*ansi_683_rev_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
4640     msg_config_rsp,             /* Configuration Response */
4641     msg_download_rsp,           /* Download Response */
4642     msg_ms_key_rsp,             /* MS Key Response */
4643     msg_key_gen_rsp,            /* Key Generation Response */
4644     msg_reauth_rsp,             /* Re-Authenticate Response */
4645     msg_commit_rsp,             /* Commit Response */
4646     msg_protocap_rsp,           /* Protocol Capability Response */
4647     msg_sspr_config_rsp,        /* SSPR Configuration Response */
4648     msg_sspr_download_rsp,      /* SSPR Download Response */
4649     msg_validate_rsp,           /* Validation Response */
4650     msg_otapa_rsp,              /* OTAPA Response */
4651     msg_puzl_config_rsp,        /* PUZL Configuration Response */
4652     msg_puzl_download_rsp,      /* PUZL Download Response */
4653     msg_3gpd_config_rsp,        /* 3GPD Configuration Response */
4654     msg_3gpd_download_rsp,      /* 3GPD Download Response */
4655     msg_secure_mode_rsp,        /* Secure Mode Response */
4656     msg_ext_protocap_rsp,       /* Extended Protocol Capability Response */
4657     msg_mmd_config_rsp,         /* MMD Configuration Response */
4658     msg_mmd_download_rsp,       /* MMD Download Response */
4659     msg_systag_config_rsp,      /* System Tag Configuration Response */
4660     msg_systag_download_rsp,    /* System Tag Download Response */
4661     msg_srvckey_gen_rsp,        /* Service Key Generation Response */
4662     msg_mms_config_rsp,         /* MMS Configuration Response */
4663     msg_mms_download_rsp,       /* MMS Download Response */
4664     NULL        /* NONE */
4665 };
4666
4667
4668 static void
4669 dissect_ansi_683_for_message(tvbuff_t *tvb, proto_tree *ansi_683_tree)
4670 {
4671     guint8      msg_type;
4672     gint        idx;
4673     const gchar *str = NULL;
4674
4675
4676     msg_type = tvb_get_guint8(tvb, 0);
4677
4678     str = try_val_to_str_idx(msg_type, for_msg_type_strings, &idx);
4679
4680     if (str == NULL)
4681     {
4682         return;
4683     }
4684
4685     /*
4686      * No Information column data
4687      */
4688
4689     proto_tree_add_uint(ansi_683_tree, hf_ansi_683_for_msg_type,
4690         tvb, 0, 1, msg_type);
4691
4692     if (ansi_683_for_msg_fcn[idx] != NULL)
4693     {
4694         (*ansi_683_for_msg_fcn[idx])(tvb, ansi_683_tree, tvb_length(tvb) - 1, 1);
4695     }
4696 }
4697
4698 static void
4699 dissect_ansi_683_rev_message(tvbuff_t *tvb, proto_tree *ansi_683_tree)
4700 {
4701     guint8      msg_type;
4702     gint        idx;
4703     const gchar *str = NULL;
4704
4705
4706     msg_type = tvb_get_guint8(tvb, 0);
4707
4708     str = try_val_to_str_idx(msg_type, rev_msg_type_strings, &idx);
4709
4710     if (str == NULL)
4711     {
4712         return;
4713     }
4714
4715     /*
4716      * No Information column data
4717      */
4718
4719     proto_tree_add_uint(ansi_683_tree, hf_ansi_683_rev_msg_type,
4720         tvb, 0, 1, msg_type);
4721
4722     (*ansi_683_rev_msg_fcn[idx])(tvb, ansi_683_tree, tvb_length(tvb) - 1, 1);
4723 }
4724
4725 static void
4726 dissect_ansi_683(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4727 {
4728     proto_item  *ansi_683_item;
4729     proto_tree  *ansi_683_tree = NULL;
4730
4731     col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
4732
4733     /* In the interest of speed, if "tree" is NULL, don't do any work not
4734      * necessary to generate protocol tree items.
4735      */
4736     if (tree)
4737     {
4738         /*
4739          * create the ansi_683 protocol tree
4740          */
4741         ansi_683_item =
4742             proto_tree_add_protocol_format(tree, proto_ansi_683, tvb, 0, -1,
4743                 "%s %s Link",
4744                 ansi_proto_name,
4745                 (pinfo->match_uint == ANSI_683_FORWARD) ? "Forward" : "Reverse");
4746
4747         ansi_683_tree =
4748             proto_item_add_subtree(ansi_683_item, ett_ansi_683);
4749
4750         if (pinfo->match_uint == ANSI_683_FORWARD)
4751         {
4752             dissect_ansi_683_for_message(tvb, ansi_683_tree);
4753         }
4754         else
4755         {
4756             dissect_ansi_683_rev_message(tvb, ansi_683_tree);
4757         }
4758     }
4759 }
4760
4761
4762 /* Register the protocol with Wireshark */
4763 void
4764 proto_register_ansi_683(void)
4765 {
4766
4767     /* Setup list of header fields */
4768     static hf_register_info hf[] =
4769     {
4770         { &hf_ansi_683_for_msg_type,
4771           { "Forward Link Message Type",
4772             "ansi_683.for_msg_type",
4773             FT_UINT8, BASE_DEC, VALS(for_msg_type_strings), 0,
4774             NULL, HFILL }},
4775         { &hf_ansi_683_rev_msg_type,
4776           { "Reverse Link Message Type",
4777             "ansi_683.rev_msg_type",
4778             FT_UINT8, BASE_DEC, VALS(rev_msg_type_strings), 0,
4779             NULL, HFILL }},
4780         { &hf_ansi_683_length,
4781             { "Length",         "ansi_683.len",
4782             FT_UINT8, BASE_DEC, NULL, 0,
4783             NULL, HFILL }
4784         },
4785         { &hf_ansi_683_none,
4786             { "Sub tree",       "ansi_683.none",
4787             FT_NONE, BASE_NONE, 0, 0,
4788             NULL, HFILL }
4789         },
4790     };
4791
4792     /* Setup protocol subtree array */
4793 #define NUM_INDIVIDUAL_PARAMS   21
4794     static gint *ett[NUM_INDIVIDUAL_PARAMS];
4795
4796     memset((void *) ett, 0, sizeof(ett));
4797
4798     ett[0] = &ett_ansi_683;
4799     ett[1] = &ett_for_nam_block;
4800     ett[2] = &ett_rev_nam_block;
4801     ett[3] = &ett_key_p;
4802     ett[4] = &ett_key_g;
4803     ett[5] = &ett_rev_feat;
4804     ett[6] = &ett_for_val_block;
4805     ett[7] = &ett_for_sspr_block;
4806     ett[8] = &ett_band_cap;
4807     ett[9] = &ett_rev_sspr_block;
4808     ett[10] = &ett_scm;
4809     ett[11] = &ett_for_puzl_block;
4810     ett[12] = &ett_rev_puzl_block;
4811     ett[13] = &ett_for_3gpd_block;
4812     ett[14] = &ett_rev_3gpd_block;
4813     ett[15] = &ett_for_mmd_block;
4814     ett[16] = &ett_rev_mmd_block;
4815     ett[17] = &ett_for_mms_block;
4816     ett[18] = &ett_rev_mms_block;
4817     ett[19] = &ett_rev_cap;
4818     ett[20] = &ett_segment;
4819
4820     /* Register the protocol name and description */
4821     proto_ansi_683 =
4822         proto_register_protocol(ansi_proto_name, "ANSI IS-683 (OTA (Mobile))", "ansi_683");
4823
4824     /* Required function calls to register the header fields and subtrees used */
4825     proto_register_field_array(proto_ansi_683, hf, array_length(hf));
4826     proto_register_subtree_array(ett, array_length(ett));
4827 }
4828
4829
4830 void
4831 proto_reg_handoff_ansi_683(void)
4832 {
4833     dissector_handle_t  ansi_683_handle;
4834
4835     ansi_683_handle = create_dissector_handle(dissect_ansi_683, proto_ansi_683);
4836
4837     dissector_add_uint("ansi_map.ota", ANSI_683_FORWARD, ansi_683_handle);
4838     dissector_add_uint("ansi_map.ota", ANSI_683_REVERSE, ansi_683_handle);
4839     dissector_add_uint("ansi_a.ota", ANSI_683_FORWARD, ansi_683_handle);
4840     dissector_add_uint("ansi_a.ota", ANSI_683_REVERSE, ansi_683_handle);
4841 }