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