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