Squelch a "signed vs. unsigned comparison" warning (which warned of a
[obnox/wireshark/wip.git] / packet-q2931.c
1 /* packet-q2931.c
2  * Routines for Q.2931 frame disassembly
3  * Guy Harris <guy@alum.mit.edu>
4  *
5  * $Id: packet-q2931.c,v 1.18 2001/06/18 02:17:50 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998
10  *
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <stdio.h>
36 #include <glib.h>
37 #include <string.h>
38 #include "packet.h"
39 #include "oui.h"
40 #include "nlpid.h"
41 #include "etypes.h"
42 #include "packet-q931.h"
43 #include "packet-arp.h"
44
45 /*
46  * See
47  *
48  *      http://www.protocols.com/pbook/atmsig.htm
49  *
50  * for some information on Q.2931, although, alas, not the actual message
51  * type and information element values - those I got from the FreeBSD 3.2
52  * ATM code, and from Q.2931 (and Q.931) itself.
53  */
54
55 static int proto_q2931 = -1;
56 static int hf_q2931_discriminator = -1;
57 static int hf_q2931_call_ref_len = -1;
58 static int hf_q2931_call_ref = -1;
59 static int hf_q2931_message_type = -1;
60 static int hf_q2931_message_type_ext = -1;
61 static int hf_q2931_message_flag = -1;
62 static int hf_q2931_message_action_indicator = -1;
63 static int hf_q2931_message_len = -1;
64
65 static gint ett_q2931 = -1;
66 static gint ett_q2931_ext = -1;
67 static gint ett_q2931_ie = -1;
68 static gint ett_q2931_ie_ext = -1;
69 static gint ett_q2931_nsap = -1;
70
71 static void dissect_q2931_ie(tvbuff_t *tvb, int offset, int len,
72     proto_tree *tree, guint8 info_element, guint8 info_element_ext);
73
74 /*
75  * Q.2931 message types.
76  */
77 #define Q2931_ALERTING          0x01
78 #define Q2931_CALL_PROCEEDING   0x02
79 #define Q2931_CONNECT           0x07
80 #define Q2931_CONNECT_ACK       0x0F
81 #define Q2931_PROGRESS          0x03
82 #define Q2931_SETUP             0x05
83 #define Q2931_SETUP_ACK         0x0B
84 #define Q2931_RELEASE           0x4D
85 #define Q2931_RELEASE_COMPLETE  0x5A
86 #define Q2931_RESTART           0x46
87 #define Q2931_RESTART_ACK       0x4E
88 #define Q2931_INFORMATION       0x7B
89 #define Q2931_NOTIFY            0x6E
90 #define Q2931_STATUS            0x7D
91 #define Q2931_STATUS_ENQUIRY    0x75
92 #define Q2931_ADD_PARTY         0x80
93 #define Q2931_ADD_PARTY_ACK     0x81
94 #define Q2931_ADD_PARTY_REJ     0x82
95 #define Q2931_DROP_PARTY        0x83
96 #define Q2931_DROP_PARTY_ACK    0x84
97 #define Q2931_LEAF_SETUP_FAIL   0x90
98 #define Q2931_LEAF_SETUP_REQ    0x91
99
100 static const value_string q2931_message_type_vals[] = {
101         { Q2931_ALERTING,               "ALERTING" },
102         { Q2931_CALL_PROCEEDING,        "CALL PROCEEDING" },
103         { Q2931_CONNECT,                "CONNECT" },
104         { Q2931_CONNECT_ACK,            "CONNECT ACKNOWLEDGE" },
105         { Q2931_PROGRESS,               "PROGRESS" },
106         { Q2931_SETUP,                  "SETUP" },
107         { Q2931_SETUP_ACK,              "SETUP ACKNOWLEDGE" },
108         { Q2931_RELEASE,                "RELEASE" },
109         { Q2931_RELEASE_COMPLETE,       "RELEASE COMPLETE" },
110         { Q2931_RESTART,                "RESTART" },
111         { Q2931_RESTART_ACK,            "RESTART ACKNOWLEDGE" },
112         { Q2931_INFORMATION,            "INFORMATION" },
113         { Q2931_NOTIFY,                 "NOTIFY" },
114         { Q2931_STATUS,                 "STATUS" },
115         { Q2931_STATUS_ENQUIRY,         "STATUS ENQUIRY" },
116         { Q2931_ADD_PARTY,              "ADD PARTY" },
117         { Q2931_ADD_PARTY_ACK,          "ADD PARTY ACKNOWLEDGE" },
118         { Q2931_ADD_PARTY_REJ,          "ADD PARTY REJECT" },
119         { Q2931_DROP_PARTY,             "DROP PARTY" },
120         { Q2931_DROP_PARTY_ACK,         "DROP PARTY ACKNOWLEDGE" },
121         { Q2931_LEAF_SETUP_FAIL,        "LEAF SETUP FAILURE" },
122         { Q2931_LEAF_SETUP_REQ,         "LEAF SETUP REQUEST" },
123         { 0,                            NULL }
124 };
125
126 /*
127  * Bits in the message type extension.
128  */
129 #define Q2931_MSG_TYPE_EXT_FOLLOW_INST  0x10    /* follow instructions in action indicator */
130 #define Q2931_MSG_TYPE_EXT_ACTION_IND   0x03    /* said instructions */
131
132 static const true_false_string tos_msg_flag = {
133         "Regular error handling procedures apply",
134         "Follow explicit error handling instructions"
135 };
136
137 static const value_string msg_action_ind_vals[] = {
138         { 0x00, "Clear call" },
139         { 0x01, "Discard and ignore" },
140         { 0x02, "Discard and report status" },
141         { 0x00, NULL }
142 };
143
144 /*
145  * Bits in the compatibility instruction indicator octet of an
146  * information element.
147  */
148 #define Q2931_IE_COMPAT_CODING_STD      0x60    /* Coding standard */
149 #define Q2931_IE_COMPAT_FOLLOW_INST     0x10    /* follow instructions in action indicator */
150 #define Q2931_IE_COMPAT_ACTION_IND      0x07
151
152 /*
153  * ITU-standardized coding.
154  */
155 #define Q2931_ITU_STANDARDIZED_CODING   0x00
156
157 static const value_string coding_std_vals[] = {
158         { 0x00, "ITU-T standardized coding" },
159         { 0x20, "ISO/IEC standard" },
160         { 0x40, "National standard" },
161         { 0x60, "Standard defined for the network" },
162         { 0,    NULL }
163 };
164
165 static const value_string ie_action_ind_vals[] = {
166         { 0x00, "Clear call" },
167         { 0x01, "Discard information element and proceed" },
168         { 0x02, "Discard information element, proceed, and report status" },
169         { 0x05, "Discard message, and ignore" },
170         { 0x06, "Discard message, and report status" },
171         { 0x00, NULL }
172 };
173
174 /*
175  * Information elements.
176  */
177 #define Q2931_IE_EXTENSION              0x80    /* Extension flag */
178
179 #define Q2931_IE_NBAND_BEARER_CAP       0x04    /* Narrowband bearer capability */
180 #define Q2931_IE_CAUSE                  0x08
181 #define Q2931_IE_CALL_STATE             0x14
182 #define Q2931_IE_PROGRESS_INDICATOR     0x1E
183 #define Q2931_IE_NOTIFICATION_INDICATOR 0x27
184 #define Q2931_IE_E2E_TRANSIT_DELAY      0x42    /* End-to-end Transit Delay */
185 #define Q2931_IE_ENDPOINT_REFERENCE     0x54
186 #define Q2931_IE_ENDPOINT_STATE         0x55
187 #define Q2931_IE_AAL_PARAMETERS         0x58    /* ATM adaptation layer parameters */
188 #define Q2931_IE_ATM_USER_CELL_RATE     0x59    /* ATM traffic descriptor */
189 #define Q2931_IE_CONNECTION_IDENTIFIER  0x5A
190 #define Q2931_IE_OAM_TRAFFIC_DESCRIPTOR 0x5B
191 #define Q2931_IE_QOS_PARAMETER          0x5C    /* Quality of Service parameter */
192 #define Q2931_IE_BBAND_HI_LAYER_INFO    0x5D    /* Broadband high-layer information */
193 #define Q2931_IE_BBAND_BEARER_CAP       0x5E    /* Broadband bearer capability */
194 #define Q2931_IE_BBAND_LOW_LAYER_INFO   0x5F    /* Broadband low-layer information */
195 #define Q2931_IE_BBAND_LOCKING_SHIFT    0x60    /* Broadband locking shift */
196 #define Q2931_IE_BBAND_NLOCKING_SHIFT   0x61    /* Broadband non-locking shift */
197 #define Q2931_IE_BBAND_SENDING_COMPL    0x62    /* Broadband sending complete */
198 #define Q2931_IE_BBAND_RPT_INDICATOR    0x63    /* Broadband repeat indicator */
199 #define Q2931_IE_CALLING_PARTY_NUMBER   0x6C    /* Calling Party Number */
200 #define Q2931_IE_CALLING_PARTY_SUBADDR  0x6D    /* Calling Party Subaddress */
201 #define Q2931_IE_CALLED_PARTY_NUMBER    0x70    /* Called Party Number */
202 #define Q2931_IE_CALLED_PARTY_SUBADDR   0x71    /* Called Party Subaddress */
203 #define Q2931_IE_TRANSIT_NETWORK_SEL    0x78    /* Transit Network Selection */
204 #define Q2931_IE_RESTART_INDICATOR      0x79
205 #define Q2931_IE_NBAND_LOW_LAYER_COMPAT 0x7C    /* Narrowband Low-Layer Compatibility */
206 #define Q2931_IE_NBAND_HIGH_LAYER_COMPAT 0x7D   /* Narrowband High-Layer Compatibility */
207 #define Q2931_IE_GENERIC_IDENT_TRANSPORT 0x7F   /* Generic identifier transport */
208
209 static const value_string q2931_info_element_vals[] = {
210         { Q2931_IE_NBAND_BEARER_CAP,            "Narrowband bearer capability" },
211         { Q2931_IE_CAUSE,                       "Cause" },
212         { Q2931_IE_CALL_STATE,                  "Call state" },
213         { Q2931_IE_PROGRESS_INDICATOR,          "Progress indicator" },
214         { Q2931_IE_NOTIFICATION_INDICATOR,      "Notification indicator" },
215         { Q2931_IE_E2E_TRANSIT_DELAY,           "End-to-end transit delay" },
216         { Q2931_IE_ENDPOINT_REFERENCE,          "Endpoint reference" },
217         { Q2931_IE_ENDPOINT_STATE,              "Endpoint state" },
218         { Q2931_IE_AAL_PARAMETERS,              "AAL parameters" },
219         { Q2931_IE_ATM_USER_CELL_RATE,          "ATM user cell rate" },
220         { Q2931_IE_CONNECTION_IDENTIFIER,       "Connection identifier" },
221         { Q2931_IE_OAM_TRAFFIC_DESCRIPTOR,      "OAM traffic descriptor" },
222         { Q2931_IE_QOS_PARAMETER,               "Quality of service parameter" },
223         { Q2931_IE_BBAND_HI_LAYER_INFO,         "Broadband high-layer information" },
224         { Q2931_IE_BBAND_BEARER_CAP,            "Broadband bearer capability" },
225         { Q2931_IE_BBAND_LOW_LAYER_INFO,        "Broadband low-layer information" },
226         { Q2931_IE_BBAND_LOCKING_SHIFT,         "Broadband locking shift" },
227         { Q2931_IE_BBAND_NLOCKING_SHIFT,        "Broadband non-locking shift" },
228         { Q2931_IE_BBAND_SENDING_COMPL,         "Broadband sending complete" },
229         { Q2931_IE_BBAND_RPT_INDICATOR,         "Broadband repeat indicator" },
230         { Q2931_IE_CALLING_PARTY_NUMBER,        "Calling party number" },
231         { Q2931_IE_CALLING_PARTY_SUBADDR,       "Calling party subaddress" },
232         { Q2931_IE_CALLED_PARTY_NUMBER,         "Called party number" },
233         { Q2931_IE_CALLED_PARTY_SUBADDR,        "Called party subaddress" },
234         { Q2931_IE_TRANSIT_NETWORK_SEL,         "Transit network selection" },
235         { Q2931_IE_RESTART_INDICATOR,           "Restart indicator" },
236         { Q2931_IE_NBAND_LOW_LAYER_COMPAT,      "Narrowband low-layer compatibility" },
237         { Q2931_IE_NBAND_HIGH_LAYER_COMPAT,     "Narrowband high-layer compatibility" },
238         { Q2931_IE_GENERIC_IDENT_TRANSPORT,     "Generic identifier transport" },
239         { 0,                                    NULL }
240 };
241
242 /*
243  * Dissect a locking or non-locking shift information element.
244  */
245 static const value_string q2931_codeset_vals[] = {
246         { 0x00, "Q.2931 information elements" },
247         { 0x04, "Information elements for ISO/IEC use" },
248         { 0x05, "Information elements for national use" },
249         { 0x06, "Information elements specific to the local network" },
250         { 0x07, "User-specific information elements" },
251         { 0x00, NULL },
252 };
253
254 static void
255 dissect_q2931_shift_ie(tvbuff_t *tvb, int offset, int len,
256     proto_tree *tree, guint8 info_element)
257 {
258         gboolean non_locking_shift;
259         guint8 codeset;
260
261         non_locking_shift = (info_element == Q2931_IE_BBAND_NLOCKING_SHIFT);
262         codeset = tvb_get_guint8(tvb, offset) & 0x07;
263         proto_tree_add_text(tree, tvb, offset, 1, "%s shift to codeset %u: %s",
264             (non_locking_shift ? "Non-locking" : "Locking"),
265             codeset,
266             val_to_str(codeset, q2931_codeset_vals, "Unknown (0x%02X)"));
267 }
268
269 /*
270  * Dissect an ATM adaptation layer parameters information element.
271  */
272 #define Q2931_AAL_VOICE         0x00
273 #define Q2931_AAL1              0x01
274 #define Q2931_AAL2              0x02
275 #define Q2931_AAL3_4            0x03
276 #define Q2931_AAL5              0x05
277 #define Q2931_USER_DEFINED_AAL  0x10
278
279 static const value_string q9231_aal_type_vals[] = {
280         { 0x00, "AAL for voice" },
281         { 0x01, "AAL type 1" },
282         { 0x02, "AAL type 2" },
283         { 0x03, "AAL type 3/4" },
284         { 0x05, "AAL type 5" },
285         { 0x10, "User-defined AAL" },
286         { 0,    NULL }
287 };
288
289 static const value_string q9231_aal1_subtype_vals[] = {
290         { 0x00, "Null" },
291         { 0x01, "64 kbit/s voice-band signal transport (G.711/G.722)" },
292         { 0x02, "Circuit transport (I.363)" },
293         { 0x04, "High-quality audio signal transport (I.363)" },
294         { 0x05, "Video signal transport (I.363)" },
295         { 0x00, NULL }
296 };
297
298 #define Q2931_AAL1_nx64_KBIT_S  0x40
299 #define Q2931_AAL1_nx8_KBIT_S   0x41
300
301 static const value_string q9231_aal1_cbr_rate_vals[] = {
302         { 0x01,                   "64 kbit/s" },
303         { 0x04,                   "1544 kbit/s" },
304         { 0x05,                   "6312 kbit/s" },
305         { 0x06,                   "32064 kbit/s" },
306         { 0x07,                   "44736 kbit/s" },
307         { 0x08,                   "97728 kbit/s" },
308         { 0x10,                   "2048 kbit/s" },
309         { 0x11,                   "8448 kibt/s" },
310         { 0x12,                   "34368 kbit/s" },
311         { 0x13,                   "139264 kbit/s" },
312         { Q2931_AAL1_nx64_KBIT_S, "nx64 kbit/s" },
313         { Q2931_AAL1_nx8_KBIT_S,  "nx8 kbit/s" },
314         { 0x00,                   NULL }
315 };
316
317 static const value_string q2931_aal1_src_clk_rec_meth_vals[] = {
318         { 0x00, "Null (synchronous circuit transport)" },
319         { 0x01, "SRTS method (asynchronous circuit transport" },
320         { 0x02, "Adaptive clock method" },
321         { 0x00, NULL }
322 };
323
324 static const value_string q2931_aal1_err_correction_method_vals[] = {
325         { 0x00, "Null" },
326         { 0x01, "FEC method for less sensitive signal transport" },
327         { 0x02, "FEC method for delay-sensigive signal transport" },
328         { 0x00, NULL }
329 };
330
331 static const value_string q2931_sscs_type_vals[] = {
332         { 0x00, "Null" },
333         { 0x01, "Data SSCS based on SSCOP (assured operation)" },
334         { 0x02, "Data SSCS based on SSCOP (non-assured operation)" },
335         { 0x04, "Frame relay SSCS" },
336         { 0x00, NULL }
337 };
338
339 static void
340 dissect_q2931_aal_parameters_ie(tvbuff_t *tvb, int offset, int len,
341     proto_tree *tree)
342 {
343         guint8 aal_type;
344         guint8 identifier;
345         guint32 value;
346         guint32 low_mid, high_mid;
347
348         if (len == 0)
349                 return;
350         aal_type = tvb_get_guint8(tvb, offset);
351         proto_tree_add_text(tree, tvb, offset, 1, "AAL type: %s",
352             val_to_str(aal_type, q9231_aal_type_vals, "Unknown (0x%02X)"));
353         offset += 1;
354         len -= 1;
355
356         /*
357          * Now get the rest of the IE.
358          */
359         if (aal_type == 0x40) {
360                 /*
361                  * User-defined AAL.
362                  */
363                 if (len > 4)
364                         len = 4;
365                 proto_tree_add_text(tree, tvb, offset, len,
366                     "User defined AAL information: %s",
367                     tvb_bytes_to_str(tvb, offset, len));
368                 return;
369         }
370
371         while (len != 0) {
372                 identifier = tvb_get_guint8(tvb, offset);
373                 switch (identifier) {
374
375                 case 0x85:      /* Subtype identifier for AAL1 */
376                         if (len < 2)
377                                 return;
378                         value = tvb_get_guint8(tvb, offset + 1);
379                         proto_tree_add_text(tree, tvb, offset, 2,
380                             "Subtype: %s",
381                             val_to_str(value, q9231_aal1_subtype_vals,
382                             "Unknown (0x%02X)"));
383                         offset += 2;
384                         len -= 2;
385                         break;
386
387                 case 0x86:      /* CBR identifier for AAL1 */
388                         if (len < 2)
389                                 return;
390                         value = tvb_get_guint8(tvb, offset + 1);
391                         proto_tree_add_text(tree, tvb, offset, 2,
392                             "CBR rate: %s",
393                             val_to_str(value, q9231_aal1_cbr_rate_vals,
394                             "Unknown (0x%02X)"));
395                         offset += 2;
396                         len -= 2;
397                         break;
398
399                 case 0x87:      /* Multiplier identifier for AAL1 */
400                         if (len < 3)
401                                 return;
402                         value = tvb_get_ntohs(tvb, offset + 1);
403                         proto_tree_add_text(tree, tvb, offset, 3,
404                             "Multiplier: %u", value);
405                         offset += 3;
406                         len -= 3;
407                         break;
408
409                 case 0x88:      /* Source clock frequency recovery method identifier for AAL1 */
410                         if (len < 2)
411                                 return;
412                         value = tvb_get_guint8(tvb, offset + 1);
413                         proto_tree_add_text(tree, tvb, offset, 2,
414                             "Source clock frequency recovery method: %s",
415                             val_to_str(value, q2931_aal1_src_clk_rec_meth_vals,
416                             "Unknown (0x%02X)"));
417                         offset += 2;
418                         len -= 2;
419                         break;
420
421                 case 0x89:      /* Error correction method identifier for AAL1 */
422                         if (len < 2)
423                                 return;
424                         value = tvb_get_guint8(tvb, offset + 1);
425                         proto_tree_add_text(tree, tvb, offset, 2,
426                             "Error correction method: %s",
427                             val_to_str(value, q2931_aal1_err_correction_method_vals,
428                             "Unknown (0x%02X)"));
429                         offset += 2;
430                         len -= 2;
431                         break;
432
433                 case 0x8A:      /* Structured data transfer block size identifier for AAL1 */
434                         if (len < 3)
435                                 return;
436                         value = tvb_get_ntohs(tvb, offset + 1);
437                         proto_tree_add_text(tree, tvb, offset, 3,
438                             "Structured data transfer block size: %u", value);
439                         offset += 3;
440                         len -= 3;
441                         break;
442
443                 case 0x8B:      /* Partially filled cells identifier for AAL1 */
444                         if (len < 2)
445                                 return;
446                         value = tvb_get_guint8(tvb, offset + 1);
447                         proto_tree_add_text(tree, tvb, offset, 2,
448                             "Partially filled cells method: %u octets", value);
449                         offset += 2;
450                         len -= 2;
451                         break;
452
453                 case 0x8C:      /* Forward maximum CPCS-SDU size identifier for AAL3/4 and AAL5 */
454                         if (len < 3)
455                                 return;
456                         value = tvb_get_ntohs(tvb, offset + 1);
457                         proto_tree_add_text(tree, tvb, offset, 3,
458                             "Forward maximum CPCS-SDU size: %u", value);
459                         offset += 3;
460                         len -= 3;
461                         break;
462
463                 case 0x81:      /* Backward maximum CPCS-SDU size identifier for AAL3/4 and AAL5 */
464                         if (len < 3)
465                                 return;
466                         value = tvb_get_ntohs(tvb, offset + 1);
467                         proto_tree_add_text(tree, tvb, offset, 3,
468                             "Backward maximum CPCS-SDU size: %u", value);
469                         offset += 3;
470                         len -= 3;
471                         break;
472
473                 case 0x82:      /* MID range identifier for AAL3/4 */
474                         if (len < 5)
475                                 return;
476                         low_mid = tvb_get_ntohs(tvb, offset + 1);
477                         high_mid = tvb_get_ntohs(tvb, offset + 3);
478                         proto_tree_add_text(tree, tvb, offset, 3,
479                             "MID range: %u - %u", low_mid, high_mid);
480                         offset += 5;
481                         len -= 5;
482                         break;
483
484                 case 0x84:      /* SSCS type identifier for AAL3/4 and AAL5 */
485                         if (len < 2)
486                                 return;
487                         value = tvb_get_guint8(tvb, offset + 1);
488                         proto_tree_add_text(tree, tvb, offset, 2,
489                             "SSCS type: %s",
490                             val_to_str(value, q2931_sscs_type_vals,
491                             "Unknown (0x%02X)"));
492                         offset += 2;
493                         len -= 2;
494                         break;
495
496                 default:        /* unknown AAL parameter */
497                         proto_tree_add_text(tree, tvb, offset, 1,
498                             "Unknown AAL parameter (0x%02X)",
499                             identifier);
500                         return; /* give up */
501                 }
502         }
503 }
504
505 /*
506  * Dissect an ATM traffic descriptor information element.
507  */
508 #define Q2931_ATM_CR_FW_PEAK_CLP_0      0x82    /* Forward peak cell rate (CLP = 0) */
509 #define Q2931_ATM_CR_BW_PEAK_CLP_0      0x83    /* Backward peak cell rate (CLP = 0) */
510 #define Q2931_ATM_CR_FW_PEAK_CLP_0_1    0x84    /* Forward peak cell rate (CLP = 0 + 1) */
511 #define Q2931_ATM_CR_BW_PEAK_CLP_0_1    0x85    /* Backward peak cell rate (CLP = 0 + 1) */
512 #define Q2931_ATM_CR_FW_SUST_CLP_0      0x88    /* Forward sustainable cell rate (CLP = 0) */
513 #define Q2931_ATM_CR_BW_SUST_CLP_0      0x89    /* Backward sustainable cell rate (CLP = 0) */
514 #define Q2931_ATM_CR_FW_SUST_CLP_0_1    0x90    /* Forward sustainable cell rate (CLP = 0 + 1) */
515 #define Q2931_ATM_CR_BW_SUST_CLP_0_1    0x91    /* Backward sustainable cell rate (CLP = 0 + 1) */
516 #define Q2931_ATM_CR_FW_MAXB_CLP_0      0xA0    /* Forward maximum burst size (CLP = 0) */
517 #define Q2931_ATM_CR_BW_MAXB_CLP_0      0xA1    /* Backward maximum burst size (CLP = 0) */
518 #define Q2931_ATM_CR_FW_MAXB_CLP_0_1    0xB0    /* Forward maximum burst size (CLP = 0 + 1) */
519 #define Q2931_ATM_CR_BW_MAXB_CLP_0_1    0xB1    /* Backward maximum burst size (CLP = 0 + 1) */
520 #define Q2931_ATM_CR_BEST_EFFORT_IND    0xBE    /* Best effort indicator */
521 #define Q2931_ATM_CR_TRAFFIC_MGMT_OPT   0xBF    /* Traffic management options */
522
523 static const value_string q2931_atm_td_subfield_vals[] = {
524         { Q2931_ATM_CR_FW_PEAK_CLP_0,   "Forward peak cell rate (CLP = 0)" },
525         { Q2931_ATM_CR_BW_PEAK_CLP_0,   "Backward peak cell rate (CLP = 0)" },
526         { Q2931_ATM_CR_FW_PEAK_CLP_0_1, "Forward peak cell rate (CLP = 0 + 1)" },
527         { Q2931_ATM_CR_BW_PEAK_CLP_0_1, "Backward peak cell rate (CLP = 0 + 1)" },
528         { Q2931_ATM_CR_FW_SUST_CLP_0,   "Forward sustainable cell rate (CLP = 0)" },
529         { Q2931_ATM_CR_BW_SUST_CLP_0,   "Backward sustainable cell rate (CLP = 0)" },
530         { Q2931_ATM_CR_FW_SUST_CLP_0_1, "Forward sustainable cell rate (CLP = 0 + 1)" },
531         { Q2931_ATM_CR_BW_SUST_CLP_0_1, "Backward sustainable cell rate (CLP = 0 + 1)" },
532         { Q2931_ATM_CR_FW_MAXB_CLP_0,   "Forward maximum burst size (CLP = 0)" },
533         { Q2931_ATM_CR_BW_MAXB_CLP_0,   "Backward maximum burst size (CLP = 0)" },
534         { Q2931_ATM_CR_FW_MAXB_CLP_0_1, "Forward maximum burst size (CLP = 0 + 1)" },
535         { Q2931_ATM_CR_BW_MAXB_CLP_0_1, "Backward maximum burst size (CLP = 0 + 1)" },
536         { Q2931_ATM_CR_BEST_EFFORT_IND, "Best effort indicator" },
537         { Q2931_ATM_CR_TRAFFIC_MGMT_OPT,"Traffic management options" },
538         { 0x0,                          NULL }
539 };
540
541 static void
542 dissect_q2931_atm_cell_rate_ie(tvbuff_t *tvb, int offset, int len,
543     proto_tree *tree)
544 {
545         guint8 identifier;
546         guint32 value;
547
548         while (len != 0) {
549                 identifier = tvb_get_guint8(tvb, offset);
550                 switch (identifier) {
551
552                 case Q2931_ATM_CR_FW_PEAK_CLP_0:
553                 case Q2931_ATM_CR_BW_PEAK_CLP_0:
554                 case Q2931_ATM_CR_FW_PEAK_CLP_0_1:
555                 case Q2931_ATM_CR_BW_PEAK_CLP_0_1:
556                 case Q2931_ATM_CR_FW_SUST_CLP_0:
557                 case Q2931_ATM_CR_BW_SUST_CLP_0:
558                 case Q2931_ATM_CR_FW_SUST_CLP_0_1:
559                 case Q2931_ATM_CR_BW_SUST_CLP_0_1:
560                 case Q2931_ATM_CR_FW_MAXB_CLP_0:
561                 case Q2931_ATM_CR_BW_MAXB_CLP_0:
562                 case Q2931_ATM_CR_FW_MAXB_CLP_0_1:
563                 case Q2931_ATM_CR_BW_MAXB_CLP_0_1:
564                         if (len < 4)
565                                 return;
566                         value = tvb_get_ntoh24(tvb, offset + 1);
567                         proto_tree_add_text(tree, tvb, offset, 4,
568                             "%s: %u cell%s/s",
569                             val_to_str(identifier, q2931_atm_td_subfield_vals,
570                               NULL),
571                             value, plurality(value, "", "s"));
572                         offset += 4;
573                         len -= 4;
574                         break;
575
576                 case Q2931_ATM_CR_BEST_EFFORT_IND:
577                         /* Yes, its value *IS* 0xBE.... */
578                         proto_tree_add_text(tree, tvb, offset, 1,
579                             "%s",
580                             val_to_str(identifier, q2931_atm_td_subfield_vals,
581                               NULL));
582                         offset += 1;
583                         len -= 1;
584                         break;
585
586                 case Q2931_ATM_CR_TRAFFIC_MGMT_OPT:
587                         if (len < 2)
588                                 return;
589                         value = tvb_get_guint8(tvb, offset + 1);
590                         proto_tree_add_text(tree, tvb, offset, 2,
591                             "%s",
592                             val_to_str(identifier, q2931_atm_td_subfield_vals,
593                               NULL));
594                         proto_tree_add_text(tree, tvb, offset + 1, 1,
595                             "%s allowed in forward direction",
596                             (value & 0x80) ? "Frame discard" : "No frame discard");
597                         proto_tree_add_text(tree, tvb, offset + 1, 1,
598                             "%s allowed in backward direction",
599                             (value & 0x40) ? "Frame discard" : "No frame discard");
600                         proto_tree_add_text(tree, tvb, offset + 1, 1,
601                             "Tagging %srequested in backward direction",
602                             (value & 0x02) ? "" : "not ");
603                         proto_tree_add_text(tree, tvb, offset + 1, 1,
604                             "Tagging %srequested in forward direction",
605                             (value & 0x01) ? "" : "not ");
606                         offset += 2;
607                         len -= 2;
608                         break;
609
610                 default:        /* unknown ATM traffic descriptor element */
611                         proto_tree_add_text(tree, tvb, offset, 1,
612                             "Unknown ATM traffic descriptor element (0x%02X)",
613                             identifier);
614                         return; /* give up */
615                 }
616         }
617 }
618
619 /*
620  * Dissect a broadband bearer capability information element.
621  */
622 static const value_string q2931_bearer_class_vals[] = {
623         { 0x01, "BCOB-A" },
624         { 0x03, "BCOB-C" },
625         { 0x10, "BCOB-X" },
626         { 0x18, "Transparent VP Service" },
627         { 0x00, NULL }
628 };
629
630 static const value_string q2931_transfer_capability_vals[] = {
631         { 0x00, "No bit rate indication" },
632         { 0x01, "No bit rate indication, end-to-end timing required" },
633         { 0x02, "No bit rate indication, end-to-end timing not required" },
634         { 0x04, "CBR" },
635         { 0x05, "CBR, end-to-end timing required" },
636         { 0x06, "CBR, end-to-end timing not required" },
637         { 0x07, "CBR with CLR commitment on CLP=0+1" },
638         { 0x08, "VBR, no timing requirements indication" },
639         { 0x09, "Real time VBR" },
640         { 0x0A, "Non-real time VBR" },
641         { 0x0B, "Non-real time VBR with CLR commitment on CLP=0+1" },
642         { 0x0C, "ABR" },
643         { 0x00, NULL }
644 };
645
646 static const value_string q2931_susc_clip_vals[] = {
647         { 0x00, "Not susceptible to clipping" },
648         { 0x20, "Susceptible to clipping" },
649         { 0x00, NULL }
650 };
651
652 static const value_string q2931_up_conn_config_vals[] = {
653         { 0x00, "Point-to-point" },
654         { 0x01, "Point-to-multipoint" },
655         { 0x00, NULL }
656 };
657
658 void
659 dissect_q2931_bband_bearer_cap_ie(tvbuff_t *tvb, int offset, int len,
660     proto_tree *tree)
661 {
662         guint8 octet;
663
664         if (len == 0)
665                 return;
666         octet = tvb_get_guint8(tvb, offset);
667         proto_tree_add_text(tree, tvb, offset, 1,
668             "Bearer class: %s",
669             val_to_str(octet & 0x1F, q2931_bearer_class_vals,
670             "Unknown (0x%02X)"));
671         offset += 1;
672         len -= 1;
673
674         if (len == 0)
675                 return;
676         if (!(octet & Q2931_IE_EXTENSION)) {
677                 octet = tvb_get_guint8(tvb, offset);
678                 proto_tree_add_text(tree, tvb, offset, 1,
679                     "ATM Transfer Capability: %s",
680                     val_to_str(octet & 0x1F, q2931_transfer_capability_vals,
681                     "Unknown (0x%02X)"));
682                 offset += 1;
683                 len -= 1;
684         }
685
686         if (len == 0)
687                 return;
688         octet = tvb_get_guint8(tvb, offset);
689         proto_tree_add_text(tree, tvb, offset, 1,
690             "Susceptibility to clipping: %s",
691             val_to_str(octet & 0x60, q2931_susc_clip_vals,
692             "Unknown (0x%02X)"));
693         proto_tree_add_text(tree, tvb, offset, 1,
694             "User-plane connection configuration: %s",
695             val_to_str(octet & 0x03, q2931_up_conn_config_vals,
696             "Unknown (0x%02X)"));
697 }
698
699 /*
700  * Dissect a broadband high layer information information element.
701  */
702 static const value_string q2931_hi_layer_info_type_vals[] = {
703         { 0x00, "ISO/IEC" },
704         { 0x01, "User-specific" },
705         { 0x03, "Vendor-specific" },
706         { 0x04, "ITU-T SG 1 B-ISDN teleservice recommendation" },
707         { 0x00, NULL }
708 };
709
710 void
711 dissect_q2931_bband_hi_layer_info_ie(tvbuff_t *tvb, int offset, int len,
712     proto_tree *tree)
713 {
714         guint8 octet;
715
716         if (len == 0)
717                 return;
718         octet = tvb_get_guint8(tvb, offset);
719         proto_tree_add_text(tree, tvb, offset, 1,
720             "High layer information type: %s",
721             val_to_str(octet & 0x7F, q2931_hi_layer_info_type_vals,
722             "Unknown (0x%02X)"));
723         offset += 1;
724         len -= 1;
725 }
726
727 /*
728  * Dissect a Bearer capability or Low-layer compatibility information element.
729  */
730 #define Q2931_UIL2_USER_SPEC    0x10
731
732 static const value_string q2931_uil2_vals[] = {
733         { 0x01,                 "Basic mode ISO 1745" },
734         { 0x02,                 "Q.921/I.441" },        /* LAPD */
735         { 0x06,                 "X.25, link layer" },   /* LAPB */
736         { 0x07,                 "X.25 multilink" },     /* or 0x0F? */
737         { 0x08,                 "T.71 Extended LAPB" },
738         { 0x09,                 "HDLC ARM" },
739         { 0x0A,                 "HDLC NRM" },
740         { 0x0B,                 "HDLC ABM" },
741         { 0x0C,                 "ISO 8802/2 LLC" },
742         { 0x0D,                 "X.75 Single Link Procedure" },
743         { 0x0E,                 "Q.922" },
744         { Q2931_UIL2_USER_SPEC, "User-specified" },
745         { 0x11,                 "ISO 7776 DTE-DTE operation" },
746         { 0,                    NULL }
747 };
748
749 static const value_string q2931_mode_vals[] = {
750         { 0x20, "Normal mode" },
751         { 0x40, "Extended mode" },
752         { 0,    NULL }
753 };
754
755 #define Q2931_UIL3_X25_PL       0x06
756 #define Q2931_UIL3_ISO_8208     0x07    /* X.25-based */
757 #define Q2931_UIL3_X223         0x08    /* X.25-based */
758 #define Q2931_UIL3_TR_9577      0x0B
759 #define Q2931_UIL3_USER_SPEC    0x10
760
761 static const value_string q2931_uil3_vals[] = {
762         { Q2931_UIL3_X25_PL,    "X.25, packet layer" },
763         { Q2931_UIL3_ISO_8208,  "ISO/IEC 8208" },
764         { Q2931_UIL3_X223,      "X.223/ISO 8878" },
765         { 0x09,                 "ISO/IEC 8473" },
766         { 0x0A,                 "T.70" },
767         { Q2931_UIL3_TR_9577,   "ISO/IEC TR 9577" },
768         { Q2931_UIL3_USER_SPEC, "User-specified" },
769         { 0,                    NULL }
770 };
771
772 static const value_string lane_pid_vals[] = {
773         { 0x0001, "LE Configuration Direct/Control Direct/Control Distribute" },
774         { 0x0002, "Ethernet/IEEE 002.3 LE Data Direct" },
775         { 0x0003, "IEEE 802.5 LE Data Direct" },
776         { 0x0004, "Ethernet/IEEE 802.3 LE Multicast Send/Multicast Forward" },
777         { 0x0005, "IEEE 802.5 LE Multicast Send/Multicast Forward" },
778         { 0,      NULL },
779 };
780
781 /*
782  * Dissect a broadband low layer information information element.
783  */
784 void
785 dissect_q2931_bband_low_layer_info_ie(tvbuff_t *tvb, int offset, int len,
786     proto_tree *tree)
787 {
788         guint8 octet;
789         guint8 uil2_protocol;
790         guint8 uil3_protocol;
791         guint8 add_l3_info;
792         guint32 organization_code;
793         guint16 pid;
794
795         if (len == 0)
796                 return;
797         octet = tvb_get_guint8(tvb, offset);
798         if ((octet & 0x60) == 0x20) {
799                 /*
800                  * Layer 1 information.
801                  */
802                 proto_tree_add_text(tree, tvb, offset, 1,
803                     "User information layer 1 protocol: 0x%02X",
804                     octet & 0x1F);
805                 offset += 1;
806                 len -= 1;
807         }
808
809         if (len == 0)
810                 return;
811         octet = tvb_get_guint8(tvb, offset);
812         if ((octet & 0x60) == 0x40) {
813                 /*
814                  * Layer 2 information.
815                  */
816                 uil2_protocol = octet & 0x1F;
817                 proto_tree_add_text(tree, tvb, offset, 1,
818                     "User information layer 2 protocol: %s",
819                     val_to_str(uil2_protocol, q2931_uil2_vals,
820                       "Unknown (0x%02X)"));
821                 offset += 1;
822                 len -= 1;
823
824                 if (octet & Q2931_IE_EXTENSION)
825                         goto l2_done;
826                 if (len == 0)
827                         return;
828                 octet = tvb_get_guint8(tvb, offset);
829                 if (uil2_protocol == Q2931_UIL2_USER_SPEC) {
830                         proto_tree_add_text(tree, tvb, offset, 1,
831                             "User-specified layer 2 protocol information: 0x%02X",
832                             octet & 0x7F);
833                 } else {
834                         proto_tree_add_text(tree, tvb, offset, 1,
835                             "Mode: %s",
836                             val_to_str(octet & 0x60, q2931_mode_vals,
837                               "Unknown (0x%02X)"));
838                 }
839                 offset += 1;
840                 len -= 1;
841
842                 if (octet & Q2931_IE_EXTENSION)
843                         goto l2_done;
844                 if (len == 0)
845                         return;
846                 octet = tvb_get_guint8(tvb, offset);
847                 proto_tree_add_text(tree, tvb, offset, 1,
848                     "Window size: %u k", octet & 0x7F);
849                 offset += 1;
850                 len -= 1;
851         }
852 l2_done:
853         ;
854
855         if (len == 0)
856                 return;
857         octet = tvb_get_guint8(tvb, offset);
858         if ((octet & 0x60) == 0x60) {
859                 /*
860                  * Layer 3 information.
861                  */
862                 uil3_protocol = octet & 0x1F;
863                 proto_tree_add_text(tree, tvb, offset, 1,
864                     "User information layer 3 protocol: %s",
865                     val_to_str(uil3_protocol, q2931_uil3_vals,
866                       "Unknown (0x%02X)"));
867                 offset += 1;
868                 len -= 1;
869
870
871                 /*
872                  * XXX - only in Low-layer compatibility information element.
873                  */
874                 if (octet & Q2931_IE_EXTENSION)
875                         goto l3_done;
876                 if (len == 0)
877                         return;
878                 octet = tvb_get_guint8(tvb, offset);
879                 switch (uil3_protocol) {
880
881                 case Q2931_UIL3_X25_PL:
882                 case Q2931_UIL3_ISO_8208:
883                 case Q2931_UIL3_X223:
884                         proto_tree_add_text(tree, tvb, offset, 1,
885                             "Mode: %s",
886                             val_to_str(octet & 0x60, q2931_mode_vals,
887                               "Unknown (0x%02X)"));
888                         offset += 1;
889                         len -= 1;
890
891                         if (octet & Q2931_IE_EXTENSION)
892                                 goto l3_done;
893                         if (len == 0)
894                                 return;
895                         octet = tvb_get_guint8(tvb, offset);
896                         proto_tree_add_text(tree, tvb, offset, 1,
897                             "Default packet size: %u", octet & 0x0F);
898                         offset += 1;
899                         len -= 1;
900
901                         if (octet & Q2931_IE_EXTENSION)
902                                 goto l3_done;
903                         if (len == 0)
904                                 return;
905                         octet = tvb_get_guint8(tvb, offset);
906                         proto_tree_add_text(tree, tvb, offset, 1,
907                             "Packet window size: %u", octet & 0x7F);
908                         offset += 1;
909                         len -= 1;
910                         break;
911
912                 case Q2931_UIL3_USER_SPEC:
913                         proto_tree_add_text(tree, tvb, offset, 1,
914                             "Default packet size: %u octets",
915                             1 << (octet & 0x0F));
916                         offset += 1;
917                         len -= 1;
918                         break;
919
920                 case Q2931_UIL3_TR_9577:
921                         add_l3_info = (octet & 0x7F) << 1;
922                         if (octet & Q2931_IE_EXTENSION)
923                                 goto l3_done;
924                         if (len < 2)
925                                 return;
926                         add_l3_info |= (tvb_get_guint8(tvb, offset + 1) & 0x40) >> 6;
927                         proto_tree_add_text(tree, tvb, offset, 2,
928                             "Additional layer 3 protocol information: %s",
929                             val_to_str(add_l3_info, nlpid_vals,
930                               "Unknown (0x%02X)"));
931                         offset += 2;
932                         len -= 2;
933                         if (add_l3_info == NLPID_SNAP) {
934                                 if (len < 6)
935                                         return;
936                                 offset += 1;
937                                 len -= 1;
938                                 organization_code = tvb_get_ntoh24(tvb, offset);
939                                 proto_tree_add_text(tree, tvb, offset, 3,
940                                     "Organization Code: 0x%06X (%s)",
941                                     organization_code,
942                                     val_to_str(organization_code, oui_vals,
943                                         "Unknown"));
944                                 offset += 3;
945                                 len -= 3;
946
947                                 if (len < 2)
948                                         return;
949                                 pid = tvb_get_ntohs(tvb, offset);
950                                 switch (organization_code) {
951
952                                 case OUI_ENCAP_ETHER:
953                                         proto_tree_add_text(tree, tvb, offset, 2,
954                                             "Ethernet type: %s",
955                                             val_to_str(pid, etype_vals,
956                                                 "Unknown (0x%04X)"));
957                                         break;
958
959                                 case OUI_ATM_FORUM:
960                                         proto_tree_add_text(tree, tvb, offset, 2,
961                                             "LANE Protocol ID: %s",
962                                             val_to_str(pid, lane_pid_vals,
963                                                 "Unknown (0x%04X)"));
964                                         break;
965
966                                 default:
967                                         proto_tree_add_text(tree, tvb, offset, 2,
968                                             "Protocol ID: 0x%04X", pid);
969                                         break;
970                                 }
971                         }
972                         break;
973                 }
974         }
975 l3_done:
976         ;
977 }
978
979 /*
980  * Dissect a Cause information element.
981  */
982 static const value_string q2931_cause_coding_standard_vals[] = {
983         { 0x00, "ITU-T standardized coding" },
984         { 0x20, "ISO/IEC standard" },
985         { 0x40, "National standard" },
986         { 0x60, "Standard defined for the network" },
987         { 0,    NULL }
988 };
989         
990 static const value_string q2931_cause_location_vals[] = {
991         { 0x00, "User (U)" },
992         { 0x01, "Private network serving the local user (LPN)" },
993         { 0x02, "Public network serving the local user (LN)" },
994         { 0x03, "Transit network (TN)" },
995         { 0x04, "Public network serving the remote user (RLN)" },
996         { 0x05, "Private network serving the remote user (RPN)" },
997         { 0x07, "International network (INTL)" },
998         { 0x0A, "Network beyond interworking point (BI)" },
999         { 0,    NULL }
1000 };
1001
1002 /*
1003  * Cause codes for Cause.
1004  */
1005 #define Q2931_CAUSE_UNALLOC_NUMBER      0x01
1006 #define Q2931_CAUSE_NO_ROUTE_TO_DEST    0x03
1007 #define Q2931_CAUSE_CALL_REJECTED       0x15
1008 #define Q2931_CAUSE_NUMBER_CHANGED      0x16
1009 #define Q2931_CAUSE_CELL_RATE_UNAVAIL   0x25
1010 #define Q2931_CAUSE_ACCESS_INFO_DISC    0x2B
1011 #define Q2931_CAUSE_QOS_UNAVAILABLE     0x31
1012 #define Q2931_CAUSE_CHAN_NONEXISTENT    0x52
1013 #define Q2931_CAUSE_INCOMPATIBLE_DEST   0x58
1014 #define Q2931_CAUSE_MAND_IE_MISSING     0x60
1015 #define Q2931_CAUSE_MT_NONEX_OR_UNIMPL  0x61
1016 #define Q2931_CAUSE_IE_NONEX_OR_UNIMPL  0x63
1017 #define Q2931_CAUSE_INVALID_IE_CONTENTS 0x64
1018 #define Q2931_CAUSE_MSG_INCOMPAT_W_CS   0x65
1019 #define Q2931_CAUSE_REC_TIMER_EXP       0x66
1020
1021 static const value_string q2931_cause_code_vals[] = {
1022         { Q2931_CAUSE_UNALLOC_NUMBER,   "Unallocated (unassigned) number" },
1023         { 0x02,                         "No route to specified transit network" },
1024         { Q2931_CAUSE_NO_ROUTE_TO_DEST, "No route to destination" },
1025         { 0x10,                         "Normal call clearing" },
1026         { 0x11,                         "User busy" },
1027         { 0x12,                         "No user responding" },
1028         { Q2931_CAUSE_CALL_REJECTED,    "Call rejected" },
1029         { Q2931_CAUSE_NUMBER_CHANGED,   "Number changed" },
1030         { 0x17,                         "User rejects calls with calling line identification restriction" },
1031         { 0x1B,                         "Destination out of order" },
1032         { 0x1C,                         "Invalid number format (incomplete number)" },
1033         { 0x1E,                         "Response to STATUS ENQUIRY" },
1034         { 0x1F,                         "Normal unspecified" },
1035         { 0x23,                         "Requested VPCI/VCI not available" },
1036         { 0x24,                         "VPCI/VCI assignment failure" },
1037         { Q2931_CAUSE_CELL_RATE_UNAVAIL,"User cell rate not available" },
1038         { 0x26,                         "Network out of order" },
1039         { 0x29,                         "Temporary failure" },
1040         { Q2931_CAUSE_ACCESS_INFO_DISC, "Access information discarded" },
1041         { 0x2D,                         "No VPCI/VCI available" },
1042         { 0x2F,                         "Resources unavailable, unspecified" },
1043         { Q2931_CAUSE_QOS_UNAVAILABLE,  "Quality of service unavailable" },
1044         { 0x39,                         "Bearer capability not authorized" },
1045         { 0x3A,                         "Bearer capability not presently available" },
1046         { 0x3F,                         "Service or option not available, unspecified" },
1047         { 0x41,                         "Bearer capability not implemented" },
1048         { 0x49,                         "Unsupported combination of traffic parameters" },
1049         { 0x4E,                         "AAL parameters cannot be supported" },
1050         { 0x51,                         "Invalid call reference value" },
1051         { Q2931_CAUSE_CHAN_NONEXISTENT, "Identified channel does not exist" },
1052         { Q2931_CAUSE_INCOMPATIBLE_DEST,"Incompatible destination" },
1053         { 0x59,                         "Invalid endpoint reference" },
1054         { 0x5B,                         "Invalid transit network selection" },
1055         { 0x5C,                         "Too many pending ADD PARTY requests" },
1056         { Q2931_CAUSE_MAND_IE_MISSING,  "Mandatory information element is missing" },
1057         { Q2931_CAUSE_MT_NONEX_OR_UNIMPL,"Message type non-existent or not implemented" },
1058         { Q2931_CAUSE_IE_NONEX_OR_UNIMPL,"Information element nonexistant or not implemented" },
1059         { Q2931_CAUSE_INVALID_IE_CONTENTS,"Invalid information element contents" },
1060         { Q2931_CAUSE_MSG_INCOMPAT_W_CS,"Message not compatible with call state" },
1061         { Q2931_CAUSE_REC_TIMER_EXP,    "Recovery on timer expiry" },
1062         { 0x68,                         "Incorrect message length" },
1063         { 0x6F,                         "Protocol error, unspecified" },
1064         { 0,                            NULL }
1065 };
1066
1067 static const value_string q2931_cause_condition_vals[] = {
1068         { 0x00, "Unknown" },
1069         { 0x01, "Permanent" },
1070         { 0x02, "Transient" },
1071         { 0x00, NULL }
1072 };
1073
1074 #define Q2931_REJ_USER_SPECIFIC         0x00
1075 #define Q2931_REJ_IE_MISSING            0x04
1076 #define Q2931_REJ_IE_INSUFFICIENT       0x08
1077
1078 static const value_string q2931_rejection_reason_vals[] = {
1079         { 0x00, "User specific" },
1080         { 0x04, "Information element missing" },
1081         { 0x08, "Information element contents are not sufficient" },
1082         { 0x00, NULL }
1083 };
1084
1085 static void
1086 dissect_q2931_cause_ie(tvbuff_t *tvb, int offset, int len,
1087     proto_tree *tree)
1088 {
1089         guint8 octet;
1090         guint8 cause_value;
1091         guint8 rejection_reason;
1092         guint8 info_element;
1093         guint8 info_element_ext;
1094         guint16 info_element_len;
1095
1096         if (len == 0)
1097                 return;
1098         octet = tvb_get_guint8(tvb, offset);
1099         proto_tree_add_text(tree, tvb, offset, 1,
1100             "Location: %s",
1101             val_to_str(octet & 0x0F, q2931_cause_location_vals,
1102               "Unknown (0x%X)"));
1103         offset += 1;
1104         len -= 1;
1105
1106         if (len == 0)
1107                 return;
1108         octet = tvb_get_guint8(tvb, offset);
1109         cause_value = octet & 0x7F;
1110         proto_tree_add_text(tree, tvb, offset, 1,
1111             "Cause value: %s",
1112             val_to_str(cause_value, q2931_cause_code_vals,
1113               "Unknown (0x%X)"));
1114         offset += 1;
1115         len -= 1;
1116
1117         if (len == 0)
1118                 return;
1119         switch (cause_value) {
1120
1121         case Q2931_CAUSE_UNALLOC_NUMBER:
1122         case Q2931_CAUSE_NO_ROUTE_TO_DEST:
1123         case Q2931_CAUSE_QOS_UNAVAILABLE:
1124                 octet = tvb_get_guint8(tvb, offset);
1125                 proto_tree_add_text(tree, tvb, offset, 1,
1126                     "Network service: %s",
1127                     (octet & 0x80) ? "User" : "Provider");
1128                 proto_tree_add_text(tree, tvb, offset, 1,
1129                     "%s",
1130                     (octet & 0x40) ? "Abnormal" : "Normal");
1131                 proto_tree_add_text(tree, tvb, offset, 1,
1132                     "Condition: %s",
1133                     val_to_str(octet & 0x03, q2931_cause_condition_vals,
1134                       "Unknown (0x%X)"));
1135                 break;
1136                 
1137         case Q2931_CAUSE_CALL_REJECTED:
1138                 rejection_reason = octet & 0x7C;
1139                 proto_tree_add_text(tree, tvb, offset, 1,
1140                     "Rejection reason: %s",
1141                     val_to_str(octet & 0x7C, q2931_cause_condition_vals,
1142                       "Unknown (0x%X)"));
1143                 proto_tree_add_text(tree, tvb, offset, 1,
1144                     "Condition: %s",
1145                     val_to_str(octet & 0x03, q2931_cause_condition_vals,
1146                       "Unknown (0x%X)"));
1147                 offset += 1;
1148                 len -= 1;
1149
1150                 if (len == 0)
1151                         return;
1152                 switch (rejection_reason) {
1153
1154                 case Q2931_REJ_USER_SPECIFIC:
1155                         proto_tree_add_text(tree, tvb, offset, len,
1156                             "User specific diagnostic: %s",
1157                             tvb_bytes_to_str(tvb, offset, len));
1158                         break;
1159
1160                 case Q2931_REJ_IE_MISSING:
1161                         proto_tree_add_text(tree, tvb, offset, 1,
1162                             "Missing information element: %s",
1163                             val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
1164                               "Unknown (0x%02X)"));
1165                         break;
1166
1167                 case Q2931_REJ_IE_INSUFFICIENT:
1168                         proto_tree_add_text(tree, tvb, offset, 1,
1169                             "Insufficient information element: %s",
1170                             val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
1171                               "Unknown (0x%02X)"));
1172                         break;
1173
1174                 default:
1175                         proto_tree_add_text(tree, tvb, offset, len,
1176                             "Diagnostic: %s",
1177                             tvb_bytes_to_str(tvb, offset, len));
1178                         break;
1179                 }
1180                 break;
1181
1182         case Q2931_CAUSE_NUMBER_CHANGED:
1183                 /*
1184                  * UNI 3.1 claims this "is formatted as the called party
1185                  * number information element, including information
1186                  * element identifier.
1187                  */
1188                 info_element = tvb_get_guint8(tvb, offset);
1189                 info_element_ext = tvb_get_guint8(tvb, offset + 1);
1190                 info_element_len = tvb_get_ntohs(tvb, offset + 2);
1191                 dissect_q2931_ie(tvb, offset, info_element_len, tree,
1192                     info_element, info_element_ext);
1193                 break;
1194
1195         case Q2931_CAUSE_ACCESS_INFO_DISC:
1196         case Q2931_CAUSE_INCOMPATIBLE_DEST:
1197         case Q2931_CAUSE_MAND_IE_MISSING:
1198         case Q2931_CAUSE_IE_NONEX_OR_UNIMPL:
1199         case Q2931_CAUSE_INVALID_IE_CONTENTS:
1200                 do {
1201                         proto_tree_add_text(tree, tvb, offset, 1,
1202                             "Information element: %s",
1203                             val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
1204                               "Unknown (0x%02X)"));
1205                         offset += 1;
1206                         len -= 1;
1207                 } while (len != 0);
1208                 break;
1209
1210         case Q2931_CAUSE_CELL_RATE_UNAVAIL:
1211                 do {
1212                         proto_tree_add_text(tree, tvb, offset, 1,
1213                             "Cell rate subfield identifier: %s",
1214                             val_to_str(tvb_get_guint8(tvb, offset), q2931_atm_td_subfield_vals,
1215                               "Unknown (0x%02X)"));
1216                         offset += 1;
1217                         len -= 1;
1218                 } while (len != 0);
1219                 break;
1220
1221         case Q2931_CAUSE_CHAN_NONEXISTENT:
1222                 if (len < 2)
1223                         return;
1224                 proto_tree_add_text(tree, tvb, offset, 2,
1225                     "VPCI: %u", tvb_get_ntohs(tvb, offset));
1226                 offset += 2;
1227                 len -= 2;
1228
1229                 if (len < 2)
1230                         return;
1231                 proto_tree_add_text(tree, tvb, offset, 2,
1232                     "VCI: %u", tvb_get_ntohs(tvb, offset));
1233                 break;
1234
1235         case Q2931_CAUSE_MT_NONEX_OR_UNIMPL:
1236         case Q2931_CAUSE_MSG_INCOMPAT_W_CS:
1237                 proto_tree_add_text(tree, tvb, offset, 1,
1238                     "Message type: %s",
1239                     val_to_str(tvb_get_guint8(tvb, offset), q2931_message_type_vals,
1240                       "Unknown (0x%02X)"));
1241                 break;
1242
1243         case Q2931_CAUSE_REC_TIMER_EXP:
1244                 if (len < 3)
1245                         return;
1246                 proto_tree_add_text(tree, tvb, offset, 3,
1247                     "Timer: %.3s", tvb_get_ptr(tvb, offset, 3));
1248                 break;
1249
1250         default:
1251                 proto_tree_add_text(tree, tvb, offset, len,
1252                     "Diagnostics: %s",
1253                     tvb_bytes_to_str(tvb, offset, len));
1254         }
1255 }
1256
1257 /*
1258  * Dissect a Call state information element.
1259  */
1260 static const value_string q2931_call_state_vals[] = {
1261         { 0x00, "Null" },
1262         { 0x01, "Call initiated" },
1263         { 0x02, "Overlap sending" },
1264         { 0x03, "Outgoing call proceeding" },
1265         { 0x04, "Call delivered" },
1266         { 0x06, "Call present" },
1267         { 0x07, "Call received" },
1268         { 0x09, "Connect request" },
1269         { 0x0A, "Incoming call proceeding" },
1270         { 0x0B, "Active" },
1271         { 0x0C, "Disconnect request" },
1272         { 0x0F, "Disconnect indication" },
1273         { 0x11, "Suspend request" },
1274         { 0x13, "Resume request" },
1275         { 0x16, "Release request" },
1276         { 0x19, "Overlap receiving" },
1277         { 0x3D, "Restart request" },
1278         { 0x3E, "Restart" },
1279         { 0,    NULL }
1280 };
1281
1282 static void
1283 dissect_q2931_call_state_ie(tvbuff_t *tvb, int offset, int len,
1284     proto_tree *tree)
1285 {
1286         guint8 octet;
1287
1288         if (len == 0)
1289                 return;
1290         octet = tvb_get_guint8(tvb, offset);
1291         proto_tree_add_text(tree, tvb, offset, 1,
1292             "Call state: %s",
1293             val_to_str(octet & 0x3F, q2931_call_state_vals,
1294               "Unknown (0x%02X)"));
1295 }
1296
1297 /*
1298  * Dissect a (phone) number information element.
1299  */
1300 static const value_string q2931_number_type_vals[] = {
1301         { 0x00, "Unknown" },
1302         { 0x10, "International number" },
1303         { 0x20, "National number" },
1304         { 0x30, "Network specific number" },
1305         { 0x40, "Subscriber number" },
1306         { 0x60, "Abbreviated number" },
1307         { 0,    NULL }
1308 };
1309
1310 #define Q2931_ISDN_NUMBERING    0x01
1311 #define Q2931_NSAP_ADDRESSING   0x02
1312
1313 static const value_string q2931_numbering_plan_vals[] = {
1314         { 0x00,                  "Unknown" },
1315         { Q2931_ISDN_NUMBERING,  "E.164 ISDN/telephony numbering" },
1316         { Q2931_NSAP_ADDRESSING, "ISO/IEC 8348 NSAP addressing" },
1317         { 0x09,                  "Private numbering" },
1318         { 0,                     NULL }
1319 };
1320
1321 static const value_string q2931_presentation_indicator_vals[] = {
1322         { 0x00, "Presentation allowed" },
1323         { 0x20, "Presentation restricted" },
1324         { 0x40, "Number not available" },
1325         { 0,    NULL }
1326 };
1327
1328 static const value_string q2931_screening_indicator_vals[] = {
1329         { 0x00, "User-provided, not screened" },
1330         { 0x01, "User-provided, verified and passed" },
1331         { 0x02, "User-provided, verified and failed" },
1332         { 0x03, "Network-provided" },
1333         { 0,    NULL }
1334 };
1335
1336 static void
1337 dissect_q2931_number_ie(tvbuff_t *tvb, int offset, int len,
1338     proto_tree *tree)
1339 {
1340         guint8 octet;
1341         guint8 numbering_plan;
1342         proto_item *ti;
1343         proto_tree *nsap_tree;
1344
1345         if (len == 0)
1346                 return;
1347         octet = tvb_get_guint8(tvb, offset);
1348         proto_tree_add_text(tree, tvb, offset, 1,
1349             "Type of number: %s",
1350             val_to_str(octet & 0x70, q2931_number_type_vals,
1351               "Unknown (0x%02X)"));
1352         numbering_plan = octet & 0x0F;
1353         proto_tree_add_text(tree, tvb, offset, 1,
1354             "Numbering plan: %s",
1355             val_to_str(numbering_plan, q2931_numbering_plan_vals,
1356               "Unknown (0x%02X)"));
1357         offset += 1;
1358         len -= 1;
1359
1360         if (!(octet & Q2931_IE_EXTENSION)) {
1361                 if (len == 0)
1362                         return;
1363                 octet = tvb_get_guint8(tvb, offset);
1364                 proto_tree_add_text(tree, tvb, offset, 1,
1365                     "Presentation indicator: %s",
1366                     val_to_str(octet & 0x60, q2931_presentation_indicator_vals,
1367                       "Unknown (0x%X)"));
1368                 proto_tree_add_text(tree, tvb, offset, 1,
1369                     "Screening indicator: %s",
1370                     val_to_str(octet & 0x03, q2931_screening_indicator_vals,
1371                       "Unknown (0x%X)"));
1372                 offset += 1;
1373                 len -= 1;
1374         }
1375
1376         if (len == 0)
1377                 return;
1378         switch (numbering_plan) {
1379
1380         case Q2931_ISDN_NUMBERING:
1381                 proto_tree_add_text(tree, tvb, offset, len, "Number: %.*s",
1382                     len, tvb_get_ptr(tvb, offset, len));
1383                 break;
1384
1385         case Q2931_NSAP_ADDRESSING:
1386                 if (len < 20) {
1387                         proto_tree_add_text(tree, tvb, offset, len,
1388                             "Number (too short): %s",
1389                             tvb_bytes_to_str(tvb, offset, len));
1390                         return;
1391                 }
1392                 ti = proto_tree_add_text(tree, tvb, offset, len, "Number");
1393                 nsap_tree = proto_item_add_subtree(ti, ett_q2931_nsap);
1394                 dissect_atm_nsap(tvb, offset, len, nsap_tree);
1395                 break;
1396
1397         default:
1398                 proto_tree_add_text(tree, tvb, offset, len, "Number: %s",
1399                     tvb_bytes_to_str(tvb, offset, len));
1400                 break;
1401         }
1402 }
1403
1404 /*
1405  * Dissect a party subaddress information element.
1406  */
1407 static const value_string q2931_subaddress_type_vals[] = {
1408         { 0x00, "X.213/ISO 8348 NSAP" },
1409         { 0x10, "User-specified ATM endsystem address" },
1410         { 0x20, "User-specified" },
1411         { 0,    NULL }
1412 };
1413
1414 static const value_string q2931_odd_even_indicator_vals[] = {
1415         { 0x00, "Even number of address signals" },
1416         { 0x10, "Odd number of address signals" },
1417         { 0,    NULL }
1418 };
1419
1420 static void
1421 dissect_q2931_party_subaddr_ie(tvbuff_t *tvb, int offset, int len,
1422     proto_tree *tree)
1423 {
1424         guint8 octet;
1425
1426         if (len == 0)
1427                 return;
1428         octet = tvb_get_guint8(tvb, offset);
1429         proto_tree_add_text(tree, tvb, offset, 1,
1430             "Type of subaddress: %s",
1431             val_to_str(octet & 0x70, q2931_subaddress_type_vals,
1432               "Unknown (0x%02X)"));
1433         proto_tree_add_text(tree, tvb, offset, 1,
1434             "Odd/even indicator: %s",
1435             val_to_str(octet & 0x10, q2931_odd_even_indicator_vals,
1436               NULL));
1437         offset += 1;
1438         len -= 1;
1439
1440         if (len == 0)
1441                 return;
1442         proto_tree_add_text(tree, tvb, offset, len, "Subaddress: %s",
1443             tvb_bytes_to_str(tvb, offset, len));
1444 }
1445
1446 /*
1447  * Dissect a connection identifier information element.
1448  */
1449 static const value_string q2931_vp_associated_signalling_vals[] = {
1450         { 0x00, "Yes" },
1451         { 0x08, "No - explicit indication of VPCI" },
1452         { 0x00, NULL }
1453 };
1454
1455 static const value_string q2931_preferred_exclusive_vals[] = {
1456         { 0x00, "Exclusive VPCI; exclusive VCI" },
1457         { 0x01, "Exclusive VPCI; any VCI" },
1458         { 0x04, "Exclusive VPCI; no VCI" },
1459         { 0x00, NULL }
1460 };
1461
1462 static void
1463 dissect_q2931_connection_identifier_ie(tvbuff_t *tvb, int offset, int len,
1464     proto_tree *tree)
1465 {
1466         guint8 octet;
1467
1468         if (len == 0)
1469                 return;
1470         octet = tvb_get_guint8(tvb, offset);
1471         proto_tree_add_text(tree, tvb, offset, 1,
1472             "VP-associated signalling: %s",
1473             val_to_str(octet & 0x18, q2931_vp_associated_signalling_vals,
1474               "Unknown (0x%02X)"));
1475         proto_tree_add_text(tree, tvb, offset, 1,
1476             "Preferred/exclusive: %s",
1477             val_to_str(octet & 0x07, q2931_preferred_exclusive_vals,
1478               "Unknown (0x%02X)"));
1479         offset += 1;
1480         len -= 1;
1481
1482         if (len < 2)
1483                 return;
1484         proto_tree_add_text(tree, tvb, offset, 2, "VPCI: %u",
1485             tvb_get_ntohs(tvb, offset));
1486         offset += 2;
1487         len -= 2;
1488
1489         if (len < 2)
1490                 return;
1491         proto_tree_add_text(tree, tvb, offset, 2, "VCI: %u",
1492             tvb_get_ntohs(tvb, offset));
1493 }
1494
1495 /*
1496  * Dissect an End-to-end transit delay information element.
1497  */
1498 static void
1499 dissect_q2931_e2e_transit_delay_ie(tvbuff_t *tvb, int offset, int len,
1500     proto_tree *tree)
1501 {
1502         guint8 identifier;
1503         guint16 value;
1504
1505         while (len >= 3) {
1506                 identifier = tvb_get_guint8(tvb, offset);
1507                 value = tvb_get_ntohs(tvb, offset + 1);
1508                 switch (identifier) {
1509
1510                 case 0x01:      /* Cumulative transit delay identifier */
1511                         proto_tree_add_text(tree, tvb, offset, 3,
1512                             "Cumulative transit delay: %u ms", value);
1513                         break;
1514
1515                 case 0x03:      /* Maximum transit delay identifier */
1516                         if (value == 0xFFFF) {
1517                                 proto_tree_add_text(tree, tvb, offset, 3,
1518                                     "Any end-to-end transit delay value acceptable");
1519                         } else {
1520                                 proto_tree_add_text(tree, tvb, offset, 3,
1521                                     "Maximum end-to-end transit delay: %u ms",
1522                                     value);
1523                         }
1524                         break;
1525
1526                 default:        /* Unknown transit delay identifier */
1527                         proto_tree_add_text(tree, tvb, offset, 1,
1528                             "Unknown transit delay identifier (0x%02X)",
1529                             identifier);
1530                         return; /* give up */
1531                 }
1532         }
1533 }
1534
1535 /*
1536  * Dissect a Quality of Service parameter information element.
1537  */
1538 static const value_string q2931_qos_parameter_vals[] = {
1539         { 0x00, "Unspecified QOS class" },
1540         { 0x00, NULL }
1541 };
1542
1543 static void
1544 dissect_q2931_qos_parameter_ie(tvbuff_t *tvb, int offset, int len,
1545     proto_tree *tree)
1546 {
1547         guint8 octet;
1548
1549         if (len == 0)
1550                 return;
1551         octet = tvb_get_guint8(tvb, offset);
1552         proto_tree_add_text(tree, tvb, offset, 1,
1553             "QOS class forward: %s",
1554             val_to_str(octet, q2931_qos_parameter_vals,
1555               "Unknown (0x%02X)"));
1556         offset += 1;
1557         len -= 1;
1558
1559         if (len == 0)
1560                 return;
1561         octet = tvb_get_guint8(tvb, offset);
1562         proto_tree_add_text(tree, tvb, offset, 1,
1563             "QOS class backward: %s",
1564             val_to_str(octet, q2931_qos_parameter_vals,
1565               "Unknown (0x%02X)"));
1566 }
1567
1568 /*
1569  * Dissect a broadband repeat indicator.
1570  */
1571 static const value_string q2931_bband_rpt_indicator_vals[] = {
1572         { 0x02, "Prioritized list for selecting one possibility (descending order)" },
1573         { 0x00, NULL }
1574 };
1575
1576 static void
1577 dissect_q2931_bband_rpt_indicator(tvbuff_t *tvb, int offset, int len,
1578     proto_tree *tree)
1579 {
1580         guint8 octet;
1581
1582         if (len == 0)
1583                 return;
1584         octet = tvb_get_guint8(tvb, offset);
1585         proto_tree_add_text(tree, tvb, offset, 1,
1586             "Broadband repeat indicator: %s",
1587             val_to_str(octet & 0x0F, q2931_bband_rpt_indicator_vals,
1588               "Unknown (0x%02X)"));
1589 }
1590
1591 /*
1592  * Dissect a restart indicator.
1593  */
1594 static const value_string q2931_class_vals[] = {
1595         { 0x00, "Indicated VC" },
1596         { 0x01, "All VC's in the indicated VPC controlled via this channel" },
1597         { 0x02, "All VC's controlled by the L3 entity that sent this message" },
1598         { 0x00, NULL }
1599 };
1600
1601 static void
1602 dissect_q2931_restart_indicator(tvbuff_t *tvb, int offset, int len,
1603     proto_tree *tree)
1604 {
1605         guint8 octet;
1606
1607         if (len == 0)
1608                 return;
1609         octet = tvb_get_guint8(tvb, offset);
1610         proto_tree_add_text(tree, tvb, offset, 1,
1611             "Restart indicator: %s",
1612             val_to_str(octet & 0x07, q2931_class_vals,
1613               "Unknown (0x%02X)"));
1614 }
1615
1616 /*
1617  * Dissect an broadband sending complete information element.
1618  */
1619 static void
1620 dissect_q2931_bband_sending_compl_ie(tvbuff_t *tvb, int offset, int len,
1621     proto_tree *tree)
1622 {
1623         guint8 identifier;
1624
1625         while (len != 0) {
1626                 identifier = tvb_get_guint8(tvb, offset);
1627                 switch (identifier) {
1628
1629                 case 0xA1:      /* Sending complete indication */
1630                         proto_tree_add_text(tree, tvb, offset, 1,
1631                             "Broadband sending complete indication");
1632                         offset += 1;
1633                         len -= 1;
1634                         break;
1635
1636                 default:        /* unknown broadband sending complete element */
1637                         proto_tree_add_text(tree, tvb, offset, 1,
1638                             "Unknown broadband sending complete element (0x%02X)",
1639                             identifier);
1640                         return; /* give up */
1641                 }
1642         }
1643 }
1644
1645 /*
1646  * Dissect a Transit network selection information element.
1647  */
1648 static const value_string q2931_netid_type_vals[] = {
1649         { 0x00, "User specified" },
1650         { 0x20, "National network identification" },
1651         { 0x30, "International network identification" },
1652         { 0,    NULL }
1653 };
1654
1655 static const value_string q2931_netid_plan_vals[] = {
1656         { 0x00, "Unknown" },
1657         { 0x01, "Carrier Identification Code" },
1658         { 0x03, "X.121 data network identification code" },
1659         { 0,    NULL }
1660 };
1661
1662 static void
1663 dissect_q2931_transit_network_sel_ie(tvbuff_t *tvb, int offset, int len,
1664     proto_tree *tree)
1665 {
1666         guint8 octet;
1667
1668         if (len == 0)
1669                 return;
1670         octet = tvb_get_guint8(tvb, offset);
1671         proto_tree_add_text(tree, tvb, offset, 1,
1672             "Type of network identification: %s",
1673             val_to_str(octet & 0x70, q2931_netid_type_vals,
1674               "Unknown (0x%02X)"));
1675         proto_tree_add_text(tree, tvb, offset, 1,
1676             "Network identification plan: %s",
1677             val_to_str(octet & 0x0F, q2931_netid_plan_vals,
1678               "Unknown (0x%02X)"));
1679         offset += 1;
1680         len -= 1;
1681
1682         if (len == 0)
1683                 return;
1684         proto_tree_add_text(tree, tvb, offset, len,
1685             "Network identification: %.*s", len, tvb_get_ptr(tvb, offset, len));
1686 }
1687
1688 /*
1689  * Dissect an OAM traffic descriptor information element.
1690  */
1691 static const value_string q2931_shaping_indicator_vals[] = {
1692         { 0x00, "No user specified requirement" },
1693         { 0x20, "Aggregate shaping of user and OAM cells not allowed" },
1694         { 0,    NULL }
1695 };
1696
1697 static const value_string q2931_user_net_fault_mgmt_vals[] = {
1698         { 0x00, "No user-originated fault managment indications" },
1699         { 0x01, "User-originated fault management indications, cell rate 1 cell/s" },
1700         { 0,    NULL }
1701 };
1702
1703 static const value_string q2931_fwd_e2e_oam_f5_flow_indicator_vals[] = {
1704         { 0x00, "0% of the forward cell rate" },
1705         { 0x10, "0.1% of the forward cell rate" },
1706         { 0x40, "1% of the forward cell rate" },
1707         { 0x0,  NULL }
1708 };
1709
1710 static const value_string q2931_bwd_e2e_oam_f5_flow_indicator_vals[] = {
1711         { 0x00, "0% of the backward cell rate" },
1712         { 0x01, "0.1% of the backward cell rate" },
1713         { 0x04, "1% of the backward cell rate" },
1714         { 0x0,  NULL }
1715 };
1716
1717 static void
1718 dissect_q2931_oam_traffic_descriptor_ie(tvbuff_t *tvb, int offset, int len,
1719     proto_tree *tree)
1720 {
1721         guint8 octet;
1722
1723         if (len == 0)
1724                 return;
1725         octet = tvb_get_guint8(tvb, offset);
1726         proto_tree_add_text(tree, tvb, offset, 1,
1727             "Shaping indicator: %s",
1728             val_to_str(octet & 0x60, q2931_shaping_indicator_vals,
1729               "Unknown (0x%02X)"));
1730         proto_tree_add_text(tree, tvb, offset, 1,
1731             "Use of end-to-end OAM F5 flow is %s",
1732             (octet & 0x10) ? "mandatory" : "optional");
1733         proto_tree_add_text(tree, tvb, offset, 1,
1734             "User-Network fault management indicator: %s",
1735             val_to_str(octet & 0x07, q2931_user_net_fault_mgmt_vals,
1736               "Unknown (0x%02X)"));
1737         offset += 1;
1738         len -= 1;
1739
1740         if (len == 0)
1741                 return;
1742         octet = tvb_get_guint8(tvb, offset);
1743         proto_tree_add_text(tree, tvb, offset, 1,
1744             "Forward end-to-end OAM F5 flow indicator: %s",
1745             val_to_str(octet & 0x70, q2931_fwd_e2e_oam_f5_flow_indicator_vals,
1746               "Unknown (0x%02X)"));
1747         proto_tree_add_text(tree, tvb, offset, 1,
1748             "Backward end-to-end OAM F5 flow indicator: %s",
1749             val_to_str(octet & 0x07, q2931_bwd_e2e_oam_f5_flow_indicator_vals,
1750               "Unknown (0x%02X)"));
1751 }
1752
1753 /*
1754  * Dissect an Endpoint reference information element.
1755  */
1756 static const value_string q2931_endpoint_reference_type_vals[] = {
1757         { 0x00, "Locally defined integer" },
1758         { 0,    NULL }
1759 };
1760
1761 static void
1762 dissect_q2931_endpoint_reference_ie(tvbuff_t *tvb, int offset, int len,
1763     proto_tree *tree)
1764 {
1765         guint8 octet;
1766         guint16 value;
1767
1768         if (len == 0)
1769                 return;
1770         octet = tvb_get_guint8(tvb, offset);
1771         proto_tree_add_text(tree, tvb, offset, 1,
1772             "Endpoint reference type: %s",
1773             val_to_str(octet, q2931_endpoint_reference_type_vals,
1774               "Unknown (0x%02X)"));
1775         offset += 1;
1776         len -= 1;
1777
1778         if (len < 2)
1779                 return;
1780         value = tvb_get_ntohs(tvb, offset);
1781         proto_tree_add_text(tree, tvb, offset, 2,
1782             "Endpoint reference flag: %s",
1783             (value & 0x8000) ? "Message sent to side that originates the endpoint reference" :
1784                                "Message sent from side that originates the endpoint reference");
1785         proto_tree_add_text(tree, tvb, offset, 2,
1786             "Endpoint reference identifier value: %u",
1787             value & 0x7FFF);
1788 }
1789
1790 /*
1791  * Dissect an Endpoint state information element.
1792  */
1793 static const value_string q2931_endpoint_reference_party_state_vals[] = {
1794         { 0x00, "Null" },
1795         { 0x01, "ADD PARTY initiated" },
1796         { 0x06, "ADD PARTY received" },
1797         { 0x0B, "DROP PARTY initiated" },
1798         { 0x0C, "DROP PARTY received" },
1799         { 0x0A, "Active" },
1800         { 0,    NULL }
1801 };
1802
1803 static void
1804 dissect_q2931_endpoint_state_ie(tvbuff_t *tvb, int offset, int len,
1805     proto_tree *tree)
1806 {
1807         guint8 octet;
1808
1809         if (len == 0)
1810                 return;
1811         octet = tvb_get_guint8(tvb, offset);
1812         proto_tree_add_text(tree, tvb, offset, 1,
1813             "Endpoint reference party-state: %s",
1814             val_to_str(octet & 0x3F, q2931_endpoint_reference_party_state_vals,
1815               "Unknown (0x%02X)"));
1816 }
1817
1818 static void
1819 dissect_q2931_ie_contents(tvbuff_t *tvb, int offset, int len,
1820     proto_tree *tree, guint8 info_element)
1821 {
1822         switch (info_element) {
1823
1824         case Q2931_IE_BBAND_LOCKING_SHIFT:
1825         case Q2931_IE_BBAND_NLOCKING_SHIFT:
1826                 dissect_q2931_shift_ie(tvb, offset, len, tree, info_element);
1827                 break;
1828
1829         case Q2931_IE_NBAND_BEARER_CAP:
1830         case Q2931_IE_NBAND_LOW_LAYER_COMPAT:
1831                 dissect_q931_bearer_capability_ie(tvb, offset, len, tree);
1832                 break;
1833
1834         case Q2931_IE_NBAND_HIGH_LAYER_COMPAT:
1835                 dissect_q931_high_layer_compat_ie(tvb, offset, len, tree);
1836                 break;
1837
1838         case Q2931_IE_PROGRESS_INDICATOR:
1839                 dissect_q931_progress_indicator_ie(tvb, offset, len, tree);
1840                 break;
1841
1842         case Q2931_IE_AAL_PARAMETERS:
1843                 dissect_q2931_aal_parameters_ie(tvb, offset, len, tree);
1844                 break;
1845
1846         case Q2931_IE_ATM_USER_CELL_RATE:
1847                 dissect_q2931_atm_cell_rate_ie(tvb, offset, len, tree);
1848                 break;
1849
1850         case Q2931_IE_BBAND_BEARER_CAP:
1851                 dissect_q2931_bband_bearer_cap_ie(tvb, offset, len, tree);
1852                 break;
1853
1854         case Q2931_IE_BBAND_HI_LAYER_INFO:
1855                 dissect_q2931_bband_hi_layer_info_ie(tvb, offset, len, tree);
1856                 break;
1857
1858         case Q2931_IE_BBAND_LOW_LAYER_INFO:
1859                 dissect_q2931_bband_low_layer_info_ie(tvb, offset, len, tree);
1860                 break;
1861
1862         case Q2931_IE_CALL_STATE:
1863                 dissect_q2931_call_state_ie(tvb, offset, len, tree);
1864                 break;
1865
1866         case Q2931_IE_CALLED_PARTY_NUMBER:
1867         case Q2931_IE_CALLING_PARTY_NUMBER:
1868                 dissect_q2931_number_ie(tvb, offset, len, tree);
1869                 break;
1870
1871         case Q2931_IE_CALLED_PARTY_SUBADDR:
1872         case Q2931_IE_CALLING_PARTY_SUBADDR:
1873                 dissect_q2931_party_subaddr_ie(tvb, offset, len, tree);
1874                 break;
1875
1876         case Q2931_IE_CAUSE:
1877                 dissect_q2931_cause_ie(tvb, offset, len, tree);
1878                 break;
1879
1880         case Q2931_IE_CONNECTION_IDENTIFIER:
1881                 dissect_q2931_connection_identifier_ie(tvb, offset, len, tree);
1882                 break;
1883
1884         case Q2931_IE_E2E_TRANSIT_DELAY:
1885                 dissect_q2931_e2e_transit_delay_ie(tvb, offset, len, tree);
1886                 break;
1887
1888         case Q2931_IE_QOS_PARAMETER:
1889                 dissect_q2931_qos_parameter_ie(tvb, offset, len, tree);
1890                 break;
1891
1892         case Q2931_IE_BBAND_RPT_INDICATOR:
1893                 dissect_q2931_bband_rpt_indicator(tvb, offset, len, tree);
1894                 break;
1895
1896         case Q2931_IE_RESTART_INDICATOR:
1897                 dissect_q2931_restart_indicator(tvb, offset, len, tree);
1898                 break;
1899
1900         case Q2931_IE_BBAND_SENDING_COMPL:
1901                 dissect_q2931_bband_sending_compl_ie(tvb, offset, len, tree);
1902                 break;
1903
1904         case Q2931_IE_TRANSIT_NETWORK_SEL:
1905                 dissect_q2931_transit_network_sel_ie(tvb, offset, len, tree);
1906                 break;
1907
1908         case Q2931_IE_OAM_TRAFFIC_DESCRIPTOR:
1909                 dissect_q2931_oam_traffic_descriptor_ie(tvb, offset, len, tree);
1910                 break;
1911
1912         case Q2931_IE_ENDPOINT_REFERENCE:
1913                 dissect_q2931_endpoint_reference_ie(tvb, offset, len, tree);
1914                 break;
1915
1916         case Q2931_IE_ENDPOINT_STATE:
1917                 dissect_q2931_endpoint_state_ie(tvb, offset, len, tree);
1918                 break;
1919         }
1920 }
1921
1922 static void
1923 dissect_q2931_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree,
1924     guint8 info_element, guint8 info_element_ext)
1925 {
1926         proto_item      *ti;
1927         proto_tree      *ie_tree;
1928         proto_tree      *ie_ext_tree;
1929
1930         ti = proto_tree_add_text(tree, tvb, offset, 1+1+2+len, "%s",
1931             val_to_str(info_element, q2931_info_element_vals,
1932               "Unknown information element (0x%02X)"));
1933         ie_tree = proto_item_add_subtree(ti, ett_q2931_ie);
1934         proto_tree_add_text(ie_tree, tvb, offset, 1, "Information element: %s",
1935             val_to_str(info_element, q2931_info_element_vals,
1936               "Unknown (0x%02X)"));
1937         ti = proto_tree_add_text(ie_tree, tvb, offset + 1, 1,
1938             "Information element extension: 0x%02x",
1939             info_element_ext);
1940         ie_ext_tree = proto_item_add_subtree(ti, ett_q2931_ie_ext);
1941         proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
1942             decode_enumerated_bitfield(info_element_ext,
1943                 Q2931_IE_COMPAT_CODING_STD, 8,
1944                 coding_std_vals, "Coding standard: %s"));
1945         proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
1946             decode_boolean_bitfield(info_element_ext,
1947             Q2931_IE_COMPAT_FOLLOW_INST, 8,
1948             "Follow explicit error handling instructions",
1949             "Regular error handling procedures apply"));
1950         if (info_element_ext & Q2931_IE_COMPAT_FOLLOW_INST) {
1951                 proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
1952                     decode_enumerated_bitfield(info_element_ext,
1953                         Q2931_IE_COMPAT_ACTION_IND, 8,
1954                         ie_action_ind_vals,
1955                         "Action indicator: %s"));
1956         }
1957         proto_tree_add_text(ie_tree, tvb, offset + 2, 2, "Length: %u", len);
1958
1959         if ((info_element_ext & Q2931_IE_COMPAT_CODING_STD)
1960             == Q2931_ITU_STANDARDIZED_CODING) {
1961                 dissect_q2931_ie_contents(tvb, offset + 4,
1962                     len, ie_tree, info_element);
1963         } else {
1964                 /*
1965                  * We don't know how it's encoded, so just
1966                  * dump it as data and be done with it.
1967                  */
1968                 proto_tree_add_text(ie_tree, tvb, offset + 4,  len,
1969                     "Data: %s", tvb_bytes_to_str(tvb, offset + 4, len));
1970         }
1971 }
1972
1973 static void
1974 dissect_q2931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1975 {
1976         int             offset = 0;
1977         guint           reported_length;
1978         proto_tree      *q2931_tree = NULL;
1979         proto_item      *ti;
1980         proto_tree      *ext_tree;
1981         guint8          call_ref_len;
1982         guint8          call_ref[15];
1983         guint8          message_type;
1984         guint8          message_type_ext;
1985         guint16         message_len;
1986         guint8          info_element;
1987         guint8          info_element_ext;
1988         guint16         info_element_len;
1989         int             codeset;
1990         gboolean        non_locking_shift;
1991
1992         if (check_col(pinfo->fd, COL_PROTOCOL))
1993                 col_set_str(pinfo->fd, COL_PROTOCOL, "Q.2931");
1994
1995         if (tree) {
1996                 ti = proto_tree_add_item(tree, proto_q2931, tvb, offset,
1997                     tvb_length(tvb), FALSE);
1998                 q2931_tree = proto_item_add_subtree(ti, ett_q2931);
1999
2000                 proto_tree_add_uint(q2931_tree, hf_q2931_discriminator, tvb, offset, 1, tvb_get_guint8(tvb, offset));
2001         }
2002         offset += 1;
2003         call_ref_len = tvb_get_guint8(tvb, offset) & 0xF;       /* XXX - do as a bit field? */
2004         if (q2931_tree != NULL)
2005                 proto_tree_add_uint(q2931_tree, hf_q2931_call_ref_len, tvb, offset, 1, call_ref_len);
2006         offset += 1;
2007         if (call_ref_len != 0) {
2008                 /* XXX - split this into flag and value */
2009                 tvb_memcpy(tvb, call_ref, offset, call_ref_len);
2010                 if (q2931_tree != NULL)
2011                         proto_tree_add_bytes(q2931_tree, hf_q2931_call_ref, tvb, offset, call_ref_len, call_ref);
2012                 offset += call_ref_len;
2013         }
2014         message_type = tvb_get_guint8(tvb, offset);
2015         if (check_col(pinfo->fd, COL_INFO)) {
2016                 col_add_str(pinfo->fd, COL_INFO,
2017                     val_to_str(message_type, q2931_message_type_vals,
2018                       "Unknown message type (0x%02X)"));
2019         }
2020         if (q2931_tree != NULL)
2021                 proto_tree_add_uint(q2931_tree, hf_q2931_message_type, tvb, offset, 1, message_type);
2022         offset += 1;
2023
2024         message_type_ext = tvb_get_guint8(tvb, offset);
2025         if (q2931_tree != NULL) {
2026                 ti = proto_tree_add_uint(q2931_tree, hf_q2931_message_type_ext, tvb,
2027                     offset, 1, message_type_ext);
2028                 ext_tree = proto_item_add_subtree(ti, ett_q2931_ext);
2029                 proto_tree_add_boolean(ext_tree, hf_q2931_message_flag, tvb,
2030                     offset, 1, message_type_ext);
2031                 if (message_type_ext & Q2931_MSG_TYPE_EXT_FOLLOW_INST) {
2032                         proto_tree_add_uint(ext_tree, hf_q2931_message_action_indicator, tvb,
2033                             offset, 1, message_type_ext);
2034                 }
2035         }
2036         offset += 1;
2037
2038         message_len = tvb_get_ntohs(tvb, offset);
2039         if (q2931_tree != NULL)
2040                 proto_tree_add_uint(q2931_tree, hf_q2931_message_len, tvb, offset, 2, message_len);
2041         offset += 2;
2042
2043         /*
2044          * And now for the information elements....
2045          */
2046         codeset = 0;    /* start out in codeset 0 */
2047         non_locking_shift = TRUE;
2048         reported_length = tvb_reported_length(tvb);
2049         while (offset < reported_length) {
2050                 info_element = tvb_get_guint8(tvb, offset);
2051                 info_element_ext = tvb_get_guint8(tvb, offset + 1);
2052                 info_element_len = tvb_get_ntohs(tvb, offset + 2);
2053                 if (q2931_tree != NULL) {
2054                         dissect_q2931_ie(tvb, offset, info_element_len,
2055                             q2931_tree, info_element, info_element_ext);
2056                 }
2057                 if (non_locking_shift)
2058                         codeset = 0;
2059
2060                 /*
2061                  * Handle shifts.
2062                  */
2063                 switch (info_element) {
2064
2065                 case Q2931_IE_BBAND_LOCKING_SHIFT:
2066                         if (info_element_len >= 1) {
2067                                 non_locking_shift = FALSE;
2068                                 codeset = tvb_get_guint8(tvb, offset + 4) & 0x07;
2069                         }
2070                         break;
2071
2072                 case Q2931_IE_BBAND_NLOCKING_SHIFT:
2073                         if (info_element_len >= 1) {
2074                                 non_locking_shift = TRUE;
2075                                 codeset = tvb_get_guint8(tvb, offset + 4) & 0x07;
2076                         }
2077                         break;
2078                 }
2079                 offset += 1 + 1 + 2 + info_element_len;
2080         }
2081 }
2082
2083 void
2084 proto_register_q2931(void)
2085 {
2086         static hf_register_info hf[] = {
2087                 { &hf_q2931_discriminator,
2088                   { "Protocol discriminator", "q2931.disc", FT_UINT8, BASE_HEX, NULL, 0x0, 
2089                         "", HFILL }},
2090
2091                 { &hf_q2931_call_ref_len,
2092                   { "Call reference value length", "q2931.call_ref_len", FT_UINT8, BASE_DEC, NULL, 0x0,
2093                         "", HFILL }},
2094
2095                 { &hf_q2931_call_ref,
2096                   { "Call reference value", "q2931.call_ref", FT_BYTES, BASE_HEX, NULL, 0x0,
2097                         "", HFILL }},
2098
2099                 { &hf_q2931_message_type,
2100                   { "Message type", "q2931.message_type", FT_UINT8, BASE_HEX, VALS(q2931_message_type_vals), 0x0,
2101                         "", HFILL }},
2102
2103                 { &hf_q2931_message_type_ext,
2104                   { "Message type extension", "q2931.message_type_ext", FT_UINT8, BASE_HEX, NULL, 0x0,
2105                         "", HFILL }},
2106
2107                 { &hf_q2931_message_flag,
2108                   { "Flag", "q2931.message_flag", FT_BOOLEAN, 8, TFS(&tos_msg_flag), Q2931_MSG_TYPE_EXT_FOLLOW_INST,
2109                         "", HFILL }},
2110
2111                 { &hf_q2931_message_action_indicator,
2112                   { "Action indicator", "q2931.message_action_indicator", FT_UINT8, BASE_DEC, VALS(msg_action_ind_vals), Q2931_MSG_TYPE_EXT_ACTION_IND,
2113                         "", HFILL }},
2114
2115                 { &hf_q2931_message_len,
2116                   { "Message length", "q2931.message_len", FT_UINT16, BASE_DEC, NULL, 0x0,
2117                         "", HFILL }},
2118
2119         };
2120         static gint *ett[] = {
2121                 &ett_q2931,
2122                 &ett_q2931_ext,
2123                 &ett_q2931_ie,
2124                 &ett_q2931_ie_ext,
2125                 &ett_q2931_nsap,
2126         };
2127
2128         proto_q2931 = proto_register_protocol("Q.2931", "Q.2931", "q2931");
2129         proto_register_field_array (proto_q2931, hf, array_length(hf));
2130         proto_register_subtree_array(ett, array_length(ett));
2131
2132         register_dissector("q2931", dissect_q2931, proto_q2931);
2133 }