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