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