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