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