e559deb8a7d9c5c87544238be932dbcb49e51caa
[metze/wireshark/wip.git] / plugins / v5ua / packet-v5ua.c
1 /* packet-v5ua.c
2  * Routines for V5.2-User Adaptation Layer dissection
3  * 
4  * Extension of ISDN Q.921-User Adaptation Layer dissection
5  * Copyright 2002, Michael Tuexen <Michael.Tuexen[AT]siemens.com>
6  *
7  * Christoph Neusch <christoph.neusch@nortelnetworks.com>
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@ethereal.com>
11  * Copyright 1998 Gerald Combs
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include "moduleinfo.h"
33
34 #include <gmodule.h>
35
36 #ifndef ENABLE_STATIC
37 G_MODULE_EXPORT const gchar version[] = VERSION;
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include <glib.h>
45
46 #include <ctype.h>
47 #include <epan/packet.h>
48 #include <epan/addr_resolv.h>
49 #include <epan/strutil.h>
50 #include <epan/sctpppids.h>      /* include V5UA payload protocol ID */
51
52
53 #include <epan/packet.h>
54
55
56 /* Initialize the protocol and registered fields */
57
58 static int proto_v5ua                    = -1;
59
60
61 static dissector_handle_t q931_handle;
62
63         /* round up parameter length to multiple of four */
64 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
65
66    /* common msg-header */
67 static int hf_version               = -1;
68 static int hf_reserved              = -1;
69 static int hf_msg_class             = -1;
70 static int hf_msg_type              = -1;
71 static int hf_msg_type_id           = -1;
72 static int hf_msg_length            = -1;
73    /* V5UA message header */
74 static int hf_link_id               = -1;
75 static int hf_chnl_id               = -1;
76 static int hf_adaptation_layer_id   = -1;
77 static int hf_text_if_id     = -1;
78 static int hf_scn_protocol_id       = -1;
79 static int hf_info_string           = -1;
80 static int hf_dlci_zero_bit         = -1;
81 static int hf_dlci_spare_bit        = -1;
82 static int hf_dlci_sapi             = -1;
83 static int hf_dlci_one_bit          = -1;
84 static int hf_dlci_tei              = -1;
85 static int hf_efa                   = -1;
86 static int hf_spare_efa             = -1;
87
88    /* variable length parameter (msg) */
89 static int hf_parameter_tag         = -1;
90 static int hf_parameter_tag_draft   = -1;
91 static int hf_parameter_length      = -1;
92 static int hf_parameter_value       = -1;
93 static int hf_parameter_padding     = -1;
94
95
96         /* parameter fields */
97 static int hf_link_status           = -1;
98 static int hf_sa_bit_id             = -1;
99 static int hf_sa_bit_value          = -1;
100 static int hf_diagnostic_info       = -1;
101 static int hf_if_range_start        = -1;
102 static int hf_if_range_end          = -1;
103 static int hf_heartbeat_data        = -1;
104 static int hf_traffic_mode_type     = -1;
105 static int hf_error_code            = -1;
106 static int hf_draft_error_code      = -1;
107 static int hf_status_type           = -1;
108 static int hf_status_id             = -1;
109 static int hf_error_reason          = -1;
110 static int hf_asp_reason            = -1;
111 static int hf_tei_status            = -1;
112 static int hf_tei_draft_status      = -1;
113 static int hf_release_reason        = -1;
114
115         /* Layer 3 message fields */
116 static int hf_l3_protocol_discriminator  = -1;
117 static int hf_l3_adress                  = -1;
118 static int hf_l3_low_adress              = -1;
119 static int hf_l3_msg_type                = -1;
120 static int hf_l3_info_element            = -1;
121
122 static int hf_l3_sequence_number         = -1;
123 static int hf_l3_v5_link_id              = -1;
124 static int hf_l3_v5_time_slot            = -1;
125
126                 /*PSTN Message*/
127 static int hf_l3_line_info               = -1;
128 static int hf_l3_cad_ringing             = -1;
129 static int hf_l3_pulse_type              = -1;
130 static int hf_l3_suppression_indicator   = -1;
131 static int hf_l3_pulse_duration          = -1;
132 static int hf_l3_ack_request_indicator   = -1;
133 static int hf_l3_number_of_pulses        = -1;
134 static int hf_l3_steady_signal           = -1;
135 static int hf_l3_auto_signalling_sequence= -1;
136 static int hf_l3_pulse_notify            = -1;
137 static int hf_l3_sequence_response       = -1;
138 static int hf_l3_digit_ack               = -1;
139 static int hf_l3_digit_info              = -1;
140 static int hf_l3_res_unavailable         = -1;
141 static int hf_l3_state                   = -1;
142 static int hf_l3_cause_type              = -1;
143 static int hf_l3_pstn_sequence_number    = -1;
144 static int hf_l3_duration_type           = -1;
145                 /*link control*/
146 static int hf_l3_link_control_function   = -1;
147                 /*Protection protocol*/
148 static int hf_l3_rejection_cause_type    = -1;
149                 /*BCC protocol*/
150 static int hf_l3_pstn_user_port_id            = -1;
151 static int hf_l3_pstn_user_port_id_lower      = -1;
152 static int hf_l3_isdn_user_port_id            = -1;
153 static int hf_l3_isdn_user_port_id_lower      = -1;
154 static int hf_l3_isdn_user_port_ts_num        = -1;
155 static int hf_l3_override                     = -1;
156 static int hf_l3_reject_cause_type            = -1;
157 static int hf_l3_bcc_protocol_error_cause     = -1;
158 static int hf_l3_connection_incomplete_reason = -1;
159                 /*Control protocol*/
160 static int hf_l3_control_function_element = -1;
161 static int hf_l3_control_function_id      = -1;
162 static int hf_l3_variant                  = -1;
163 static int hf_l3_if_id                    = -1;
164 static int hf_l3_performance_grading      = -1;
165 static int hf_l3_cp_rejection_cause       = -1;
166
167
168 /* Initialize the subtree pointers */
169 static gint ett_v5ua              = -1;
170 static gint ett_v5ua_common_header= -1;
171 static gint ett_v5ua_parameter    = -1;
172 static gint ett_v5ua_layer3       = -1;
173
174 #define RFC             0x1
175 #define DRAFT           0x2
176         /* Version of IUA */
177 static int iua_version = RFC;
178     /* Variables neccessary for dissection of draft messages */
179 static int msg_class   = -1;
180 static int msg_type    = -1;
181 static int msg_length  = -1;
182
183
184
185 /* Code to actually dissect the packets */
186
187
188         /* define the parameters for the Tags: Tag-Type,Tag-Length,Tag-Value (Payload) */
189 #define PARAMETER_TAG_OFFSET    0
190 #define PARAMETER_TAG_LENGTH    2
191 #define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
192 #define PARAMETER_LENGTH_LENGTH 2
193 #define PARAMETER_VALUE_OFFSET  (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
194 #define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
195 #define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
196
197
198 /*----------------------V5UA Interface Identifier (int) (Draft,RFC)------------*/ 
199
200         /* define parameter for the format of the integer formatted Interface Identifier */
201 #define INT_IF_ID_LINK_OFFSET PARAMETER_VALUE_OFFSET
202 #define INT_IF_ID_LINK_LENGTH 4
203 #define INT_IF_ID_CHNL_OFFSET INT_IF_ID_LINK_OFFSET
204 #define INT_IF_ID_CHNL_LENGTH 1
205         
206 static void
207 dissect_int_interface_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
208 {
209   guint32 identifier;
210
211   proto_tree_add_item(parameter_tree, hf_link_id, parameter_tvb, INT_IF_ID_LINK_OFFSET, INT_IF_ID_LINK_LENGTH, FALSE);
212   identifier = tvb_get_ntohl(parameter_tvb,INT_IF_ID_LINK_OFFSET)>>5;
213   proto_item_append_text(parameter_item, "  Link: %d ",identifier);
214   
215   proto_tree_add_item(parameter_tree, hf_chnl_id, parameter_tvb, INT_IF_ID_CHNL_OFFSET+3, INT_IF_ID_CHNL_LENGTH, FALSE);
216   identifier = tvb_get_guint8(parameter_tvb,INT_IF_ID_CHNL_OFFSET+3)&0x1f;
217   proto_item_append_text(parameter_item, " Chnl: %d ", identifier);
218
219
220 }
221 /*----------------------V5UA Interface Identifier (int) (Draft,RFC)------------*/
222
223 /*----------------------Text Interface Identifier (RFC)------------------------*/
224
225 #define TEXT_IF_ID_LENGTH_OFFSET PARAMETER_LENGTH_OFFSET
226 #define TEXT_IF_ID_VALUE_OFFSET  PARAMETER_VALUE_OFFSET
227 #define TEXT_IF_ID_HEADER_LENGTH PARAMETER_HEADER_LENGTH
228 static void
229 dissect_text_interface_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
230 {
231   guint16 if_id_length;
232
233   if_id_length = tvb_get_ntohs(parameter_tvb, TEXT_IF_ID_LENGTH_OFFSET) - TEXT_IF_ID_HEADER_LENGTH;
234
235   proto_tree_add_item(parameter_tree, hf_text_if_id, parameter_tvb, TEXT_IF_ID_VALUE_OFFSET, if_id_length, FALSE);
236   proto_item_append_text(parameter_item, " (0x%.*s)", if_id_length,
237                          (const char *)tvb_get_ptr(parameter_tvb, TEXT_IF_ID_VALUE_OFFSET, if_id_length));
238 }
239 /*----------------------Text Interface Identifier (RFC)------------------------*/
240
241 /*----------------------DLCI & Envelope Function Adress-------------------------*/
242
243
244 /* interpretaion of EFA-values */
245 static const value_string efa_values[] = {
246         { 8175, "ISDN Protocol" },
247         { 8176, "PSTN Protocol" },
248         { 8177, "CC Protocol" },
249         { 8178, "BCC Protocol" },
250         { 8179, "PROT Protocol" },
251         { 8180, "Link Contol Protocol" },
252         { 8191, "VALUE RESERVED" },
253         { 0,    NULL } };
254
255 #define DLCI_LENGTH_OFFSET PARAMETER_LENGTH_OFFSET
256 #define DLCI_SAPI_OFFSET   PARAMETER_VALUE_OFFSET
257 #define DLCI_HEADER_LENGTH PARAMETER_HEADER_LENGTH
258
259 #define DLCI_SAPI_LENGTH   1
260 #define DLCI_TEI_LENGTH    1
261 #define EFA_LENGTH         2
262
263 static void
264 dissect_dlci_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
265 {
266   guint16 efa = 0, offset=0;
267
268   if     (iua_version == RFC)   offset = DLCI_SAPI_OFFSET;
269   else if(iua_version == DRAFT) offset = DLCI_HEADER_LENGTH + tvb_get_ntohs(parameter_tvb, DLCI_LENGTH_OFFSET);
270
271   proto_tree_add_item(parameter_tree, hf_dlci_zero_bit,  parameter_tvb, offset,  DLCI_SAPI_LENGTH,  FALSE);
272   proto_tree_add_item(parameter_tree, hf_dlci_spare_bit, parameter_tvb, offset,  DLCI_SAPI_LENGTH,  FALSE);
273   proto_tree_add_item(parameter_tree, hf_dlci_sapi,      parameter_tvb, offset,  DLCI_SAPI_LENGTH,  FALSE);
274
275   offset += DLCI_SAPI_LENGTH;
276   proto_tree_add_item(parameter_tree, hf_dlci_one_bit,   parameter_tvb, offset,  DLCI_TEI_LENGTH,   FALSE);
277   proto_tree_add_item(parameter_tree, hf_dlci_tei,       parameter_tvb, offset,  DLCI_TEI_LENGTH,   FALSE);
278
279   /* if SAPI & TEI not set to ZERO, value of EFA must be decode (EFA = 0 -> ISDN protocol)*/
280   if(tvb_get_ntohs(parameter_tvb,offset-DLCI_TEI_LENGTH) != 0x01){
281
282           offset += DLCI_TEI_LENGTH;
283           efa = tvb_get_ntohs(parameter_tvb, offset);
284           /* EFA-Values for ISDN-Protocal. For the "value_string"-function value must set to 8175 */
285           if(efa < 8175) efa = 8175;
286           /* Reserved values. For the "value_string"-function value must set to 8191 */
287           else if ((efa >= 8181) && (efa < 8191)) efa = 8191;
288           proto_tree_add_uint_format(parameter_tree, hf_efa,  parameter_tvb, offset, EFA_LENGTH, efa,
289                                                                 "Envelope function address: %s (%u)", val_to_str(efa, efa_values, "unknown EFA"),tvb_get_ntohs(parameter_tvb, offset));
290           proto_item_append_text(parameter_item, " (EFA: %s )",val_to_str(efa, efa_values, "unknown EFA-value"));
291   }
292   /* if SAPI & TEI set to ZERO, EFA also shall be set to ZERO and didn't comply with value for ISDN protocol */
293   else{
294           proto_tree_add_uint_format(parameter_tree, hf_efa,  parameter_tvb, offset, EFA_LENGTH, efa,
295                                                                 "Envelope function address: 0");
296           proto_item_append_text(parameter_item, " (EFA: 0 )");
297   }
298
299 }
300 /*----------------------DLCI & Envelope Function Adress-------------------------*/
301
302 /*----------------------Error Indication (Draft)-------------------------------*/
303
304         /* define Error Code Parameter for Layer Management (MGMT) Messages */
305 #define MGMT_ERROR_INVALID_TEI_DRAFT                       0x00
306 #define MGMT_ERROR_INVALID_IFID_DRAFT                      0x01
307 #define MGMT_ERROR_UNDEFINIED_MSG_DRAFT                    0x02
308 #define MGMT_ERROR_VERSION_ERR_DRAFT                       0x03
309 #define MGMT_ERROR_INVALID_STID_DRAFT                      0x04
310 #define MGMT_ERROR_INVALID_SCNV_DRAFT                      0x05
311 #define MGMT_ERROR_INVALID_ALI_DRAFT                       0x06
312
313 static const value_string draft_error_code_values[] = {
314   { MGMT_ERROR_INVALID_TEI_DRAFT,     "Invalid TEI" },
315   { MGMT_ERROR_INVALID_IFID_DRAFT,    "Invalid interface ID" },
316   { MGMT_ERROR_UNDEFINIED_MSG_DRAFT,  "An unexpected message was received" },
317   { MGMT_ERROR_VERSION_ERR_DRAFT,     "The IUA layers are of different version" },
318   { MGMT_ERROR_INVALID_STID_DRAFT,    "Invalid SCTP stream idetifier" },
319   { MGMT_ERROR_INVALID_SCNV_DRAFT,    "Invalid SCN version" },
320   { MGMT_ERROR_INVALID_ALI_DRAFT,     "Invalid Adapiotion Layer Identifier" },
321   { 0,                                NULL } };
322
323 #define MGMT_ERROR_MSG_LENGTH_OFFSET PARAMETER_LENGTH_OFFSET
324 #define MGMT_ERROR_MSG_HEADER_LENGTH PARAMETER_HEADER_LENGTH
325
326 #define MGMT_ERROR_CODE_LENGTH 4
327
328 static void
329 dissect_draft_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
330 {
331   guint16 offset = MGMT_ERROR_MSG_HEADER_LENGTH + tvb_get_ntohs(parameter_tvb, MGMT_ERROR_MSG_LENGTH_OFFSET) + 4;
332   proto_tree_add_item(parameter_tree, hf_draft_error_code, parameter_tvb, offset, MGMT_ERROR_CODE_LENGTH, FALSE);
333   offset += MGMT_ERROR_CODE_LENGTH ;
334   if( tvb_length_remaining(parameter_tvb,offset) > 0 )
335           proto_tree_add_item(parameter_tree, hf_info_string, parameter_tvb, offset, msg_length - offset,FALSE);
336 }
337 /*----------------------Error Indication (Draft)-------------------------------*/
338
339 /*----------------------Error Indication (RFC)---------------------------------*/
340
341         /* define Error Code Parameter for Layer Management (MGMT) Messages */
342 #define MGMT_ERROR_INVALID_VERSION                     0x01
343 #define MGMT_ERROR_INVALID_IF_ID                       0x02
344 #define MGMT_ERROR_UNSUPPORTED_MSG_CLASS               0x03
345 #define MGMT_ERROR_UNSUPPORTED_MSG_TYPE                0x04
346 #define MGMT_ERROR_UNSUPPORTED_TRAFFIC_HANDLING_MODE   0x05
347 #define MGMT_ERROR_UNEXPECTED_MSG                      0x06
348 #define MGMT_ERROR_PROTOCOL_ERROR                      0x07
349 #define MGMT_ERROR_UNSUPPORTED_IF_ID_TYPE              0x08
350 #define MGMT_ERROR_INVALID_STREAM_ID                   0x09
351 #define MGMT_ERROR_UNASSIGNED_TEI                      0x0a
352 #define MGMT_ERROR_UNRECOGNIZED_SAPI                   0x0b
353 #define MGMT_ERROR_INVALID_TEI_SAPI_COMBINATION        0x0c
354
355 static const value_string error_code_values[] = {
356   { MGMT_ERROR_INVALID_VERSION,                       "Invalid version" },
357   { MGMT_ERROR_INVALID_IF_ID,                         "Invalid interface identifier" },
358   { MGMT_ERROR_UNSUPPORTED_MSG_CLASS,                 "Unsuported message class" },
359   { MGMT_ERROR_UNSUPPORTED_MSG_TYPE,                  "Unsupported message type" },
360   { MGMT_ERROR_UNSUPPORTED_TRAFFIC_HANDLING_MODE,     "Unsupported traffic handling mode" },
361   { MGMT_ERROR_UNEXPECTED_MSG,                        "Unexpected message" },
362   { MGMT_ERROR_PROTOCOL_ERROR,                        "Protocol error" },
363   { MGMT_ERROR_UNSUPPORTED_IF_ID_TYPE,                "Unsupported interface identifier type" },
364   { MGMT_ERROR_INVALID_STREAM_ID,                     "Invalid stream identifier" },
365   { MGMT_ERROR_UNASSIGNED_TEI,                        "Unassigned TEI" },
366   { MGMT_ERROR_UNRECOGNIZED_SAPI,                     "Unrecognized SAPI" },
367   { MGMT_ERROR_INVALID_TEI_SAPI_COMBINATION,          "Invalid TEI/SAPI combination" },
368   { 0,                                                NULL } };
369
370 #define MGMT_ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
371
372 static void
373 dissect_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
374 {
375   proto_tree_add_item(parameter_tree, hf_error_code, parameter_tvb, MGMT_ERROR_CODE_OFFSET, MGMT_ERROR_CODE_LENGTH, FALSE);
376   proto_item_append_text(parameter_item, " (%s)",
377                          val_to_str(tvb_get_ntohl(parameter_tvb, MGMT_ERROR_CODE_OFFSET), error_code_values, "Unknown error code"));
378 }
379
380 static void
381 dissect_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
382 {
383   guint16 diag_info_length;
384
385   diag_info_length = tvb_get_ntohs(parameter_tvb, MGMT_ERROR_MSG_LENGTH_OFFSET) - MGMT_ERROR_MSG_HEADER_LENGTH;
386   proto_tree_add_item(parameter_tree, hf_diagnostic_info, parameter_tvb, PARAMETER_VALUE_OFFSET, diag_info_length, FALSE);
387   proto_item_append_text(parameter_item, " (%u byte%s)", diag_info_length, plurality(diag_info_length, "", "s"));
388 }
389 /*----------------------Error Indication (RFC)---------------------------------*/
390
391 /*----------------------Notify (RFC)-------------------------------------------*/
392
393         /* define Status Type parameters for Notify (NTFY) Messages */
394 #define NTFY_STATUS_TYPE_AS_STATE_CHANGE  0x01
395 #define NTFY_STATUS_TYPE_OTHER            0x02
396
397 static const value_string status_type_values[] = {
398   { NTFY_STATUS_TYPE_AS_STATE_CHANGE,        "Application server state change" },
399   { NTFY_STATUS_TYPE_OTHER,                  "Other" },
400   { 0,                                       NULL } };
401
402         /* define Status Identification parameters for NTFY Messages (AS state change)*/
403 #define NTFY_STATUS_IDENT_AS_DOWN          0x01
404 #define NTFY_STATUS_IDENT_AS_INACTIVE      0x02
405 #define NTFY_STATUS_IDENT_AS_ACTIVE        0x03
406 #define NTFY_STATUS_IDENT_AS_PENDING       0x04
407         /* define Status Identification parameters for NTFY Messages (Other)*/
408 #define NTFY_STATUS_INSUFFICIENT_ASP_RES_ACTIVE 0x01
409 #define NTFY_STATUS_ALTERNATE_ASP_ACTIVE        0x02
410
411 static const value_string status_type_id_values[] = {
412   { NTFY_STATUS_TYPE_AS_STATE_CHANGE * 256 * 256 + NTFY_STATUS_IDENT_AS_DOWN,         "Application server down" },
413   { NTFY_STATUS_TYPE_AS_STATE_CHANGE * 256 * 256 + NTFY_STATUS_IDENT_AS_INACTIVE,     "Application server inactive" },
414   { NTFY_STATUS_TYPE_AS_STATE_CHANGE * 256 * 256 + NTFY_STATUS_IDENT_AS_ACTIVE,       "Application server active" },
415   { NTFY_STATUS_TYPE_AS_STATE_CHANGE * 256 * 256 + NTFY_STATUS_IDENT_AS_PENDING,      "Application server pending" },
416   { NTFY_STATUS_TYPE_OTHER * 256 * 256 + NTFY_STATUS_INSUFFICIENT_ASP_RES_ACTIVE,     "Insufficient ASP resources active in AS" },
417   { NTFY_STATUS_TYPE_OTHER * 256 * 256 + NTFY_STATUS_ALTERNATE_ASP_ACTIVE,            "Alternate ASP active" },
418   { 0,                                           NULL } };
419
420 #define NTFY_STATUS_TYPE_OFFSET  PARAMETER_VALUE_OFFSET
421 #define NTFY_STATUS_TYPE_LENGTH  2
422 #define NTFY_STATUS_IDENT_OFFSET (NTFY_STATUS_TYPE_OFFSET + NTFY_STATUS_TYPE_LENGTH)
423 #define NTFY_STATUS_IDENT_LENGTH 2
424
425 static void
426 dissect_status_type_identification_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
427 {
428   guint16 status_type, status_id;
429
430   status_type = tvb_get_ntohs(parameter_tvb, NTFY_STATUS_TYPE_OFFSET);
431   status_id   = tvb_get_ntohs(parameter_tvb, NTFY_STATUS_IDENT_OFFSET);
432
433   proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, NTFY_STATUS_TYPE_OFFSET, NTFY_STATUS_TYPE_LENGTH, FALSE);
434   proto_tree_add_uint_format(parameter_tree, hf_status_id,  parameter_tvb, NTFY_STATUS_IDENT_OFFSET, NTFY_STATUS_IDENT_LENGTH,
435                              status_id, "Status identification: %u (%s)", status_id,
436                              val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "unknown"));
437
438   proto_item_append_text(parameter_item, " (%s)",
439                          val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "Unknown status information"));
440 }
441 /*----------------------Notify (RFC)-------------------------------------------*/
442
443 /*----------------------TEI Status Indication,Confirm (RFC)--------------------*/
444
445         /* define parameters for TEI Status (Indication,Confirm) Messages */
446 #define TEI_STATUS_ASSIGNED       0x0
447 #define TEI_STATUS_UNASSIGNED     0x1
448
449 static const value_string tei_status_values[] = {
450   { TEI_STATUS_ASSIGNED,   "TEI is considered assigned by Q.921" },
451   { TEI_STATUS_UNASSIGNED, "TEI is considered unassigned by Q.921" },
452   { 0,                     NULL } };
453
454 #define TEI_STATUS_OFFSET PARAMETER_VALUE_OFFSET
455 #define TEI_STATUS_LENGTH 4
456
457 static void
458 dissect_tei_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
459 {
460   proto_tree_add_item(parameter_tree, hf_tei_status, parameter_tvb, TEI_STATUS_OFFSET, TEI_STATUS_LENGTH, FALSE);
461   proto_item_append_text(parameter_item, " (%s)",
462                       val_to_str(tvb_get_ntohl(parameter_tvb, TEI_STATUS_OFFSET), tei_status_values, "Unknown TEI status"));
463 }
464 /*----------------------TEI Status (RFC)---------------------------------------*/
465
466 /*----------------------TEI Status Indication,Confirm (Draft)------------------*/
467 #define TEI_DRAFT_IN_SERVICE     0x0
468 #define TEI_DRAFT_OUT_OF_SERVICE 0x1
469
470 static const value_string tei_draft_status_values[] = {
471         { TEI_DRAFT_IN_SERVICE,    "TEI is in service" },
472         { TEI_DRAFT_OUT_OF_SERVICE,"TEI is out of service" },
473         { 0,                       NULL } };
474
475 #define TEI_STATUS_LENGTH_OFFSET PARAMETER_LENGTH_OFFSET
476
477 static void
478 dissect_draft_tei_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
479 {
480   gint length, offset;
481   offset = tvb_get_ntohs(parameter_tvb, TEI_STATUS_LENGTH_OFFSET) + 8;
482   length = msg_length - offset;
483   if(tvb_length_remaining(parameter_tvb, offset) > 0 ){
484           proto_tree_add_item(parameter_tree, hf_tei_draft_status, parameter_tvb, offset, TEI_STATUS_LENGTH, FALSE);
485           proto_item_append_text(parameter_item, " (%s)",
486                                                                 val_to_str(tvb_get_ntohl(parameter_tvb, offset), tei_draft_status_values, "Unknown TEI Status"));
487   }
488 }
489 /*----------------------TEI Status (Draft)-------------------------------------*/
490
491 /*----------------------ASP Up,Down,Active,Inactive (Draft)--------------------*/
492
493 static void
494 dissect_asp_msg_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
495 {
496   guint16 adaptation_layer_id_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
497
498   proto_tree_add_item(parameter_tree, hf_adaptation_layer_id, parameter_tvb, PARAMETER_VALUE_OFFSET, adaptation_layer_id_length, FALSE);
499   proto_item_append_text(parameter_item, " (%.*s)", adaptation_layer_id_length,
500                          (const char *)tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, adaptation_layer_id_length));
501 }
502
503 static void
504 dissect_scn_protocol_id_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
505 {
506   guint16 id_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
507   proto_tree_add_item(parameter_tree, hf_scn_protocol_id, parameter_tvb, PARAMETER_VALUE_OFFSET, id_length, FALSE);
508   proto_item_append_text(parameter_item, " (%.*s)", id_length,
509                          (const char *)tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, id_length));
510 }
511
512 /*----------------------ASP (Draft)--------------------------------------------*/
513
514 /*----------------------ASP Down + Ack (RFC)--------------------------------*/
515         /* define reason parameter for Application Server Process Maintenance (ASPM) Messages */
516 #define ASP_REASON_MGMT   1
517
518 static const value_string asp_reason_values[] = {
519   { ASP_REASON_MGMT,      "Management inhibit" },
520   { 0,                    NULL } };
521
522 #define ASP_REASON_OFFSET PARAMETER_VALUE_OFFSET
523 #define ASP_REASON_LENGTH 4
524
525 static void
526 dissect_asp_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
527 {
528   proto_tree_add_item(parameter_tree, hf_asp_reason, parameter_tvb, ASP_REASON_OFFSET, ASP_REASON_LENGTH, FALSE);
529   proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ASP_REASON_OFFSET), asp_reason_values, "Unknown ASP down reason"));
530 }
531
532
533 /*----------------------ASP (RFC)----------------------------------------------*/
534
535 /*----------------------Heartbeat Data + Ack (RFC)-----------------------------*/
536
537 #define HEARTBEAT_MSG_LENGTH_OFFSET PARAMETER_LENGTH_OFFSET
538 #define HEARTBEAT_DATA_OFFSET       PARAMETER_VALUE_OFFSET
539 #define HEARTBEAT_MSG_HEADER_LENGTH PARAMETER_HEADER_LENGTH
540
541 static void
542 dissect_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
543 {
544   guint16 heartbeat_data_length;
545
546   heartbeat_data_length = tvb_get_ntohs(parameter_tvb, HEARTBEAT_MSG_LENGTH_OFFSET) - HEARTBEAT_MSG_HEADER_LENGTH;
547   proto_tree_add_item(parameter_tree, hf_heartbeat_data, parameter_tvb, HEARTBEAT_DATA_OFFSET, heartbeat_data_length, FALSE);
548   proto_item_append_text(parameter_item, " (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
549 }
550 /*----------------------Heartbeat Data (RFC)-----------------------------------*/
551
552
553 /*----------------------ASP Active,Inactive + Ack (RFC)------------------------*/
554 #define OVER_RIDE_TRAFFIC_MODE_TYPE  1
555 #define LOAD_SHARE_TRAFFIC_MODE_TYPE 2
556
557 static const value_string traffic_mode_type_values[] = {
558   { OVER_RIDE_TRAFFIC_MODE_TYPE,      "Over-ride" },
559   { LOAD_SHARE_TRAFFIC_MODE_TYPE,     "Load-share" },
560   { 0,                    NULL } };
561
562 #define TRAFFIC_MODE_TYPE_LENGTH 4
563 #define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
564
565 static void
566 dissect_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
567 {
568   proto_tree_add_item(parameter_tree, hf_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, FALSE);
569   proto_item_append_text(parameter_item, " (%s)",
570                          val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), traffic_mode_type_values, "Unknown traffic mode type"));
571 }
572
573 #define INT_RANGE_START_OFFSET  PARAMETER_VALUE_OFFSET
574 #define INT_RANGE_LENGTH_OFFSET PARAMETER_LENGTH_OFFSET
575 #define INT_RANGE_HEADER_LENGTH PARAMETER_HEADER_LENGTH
576
577 #define IF_ID_START_OFFSET      0
578 #define IF_ID_START_LENGTH      4
579 #define IF_ID_END_OFFSET        (IF_ID_START_OFFSET + IF_ID_START_LENGTH)
580 #define IF_ID_END_LENGTH        4
581 #define IF_ID_INTERVAL_LENGTH   (IF_ID_START_LENGTH + IF_ID_END_LENGTH)
582
583
584 static void
585 dissect_integer_range_interface_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
586 {
587   guint16 number_of_ranges, range_number, offset;
588
589   number_of_ranges = (tvb_get_ntohs(parameter_tvb, INT_RANGE_LENGTH_OFFSET) - INT_RANGE_HEADER_LENGTH) / IF_ID_INTERVAL_LENGTH;
590   offset = INT_RANGE_START_OFFSET;
591   for(range_number = 1; range_number <= number_of_ranges; range_number++) {
592     proto_tree_add_item(parameter_tree, hf_if_range_start, parameter_tvb, offset + IF_ID_START_OFFSET, IF_ID_START_LENGTH, FALSE);
593     proto_tree_add_item(parameter_tree, hf_if_range_end,   parameter_tvb, offset + IF_ID_END_OFFSET,   IF_ID_END_LENGTH,   FALSE);
594     offset += IF_ID_INTERVAL_LENGTH;
595   };
596
597   proto_item_append_text(parameter_item, " (%u range%s)", number_of_ranges, plurality(number_of_ranges, "", "s"));
598 }
599 /*----------------------ASP Active,Inactive (RFC)------------------------------*/
600
601 /*----------------------Data Request,Indication (Draft,RFC)--------------------*/
602 /* message types of PSTN */
603 #define ESTABLISH           0x00
604 #define ESTABLISH_ACK       0x01
605 #define SIGNAL              0x02
606 #define SIGNAL_ACK          0x03
607 #define DISCONNECT          0x08
608 #define DISCONNECT_COMPLETE 0x09
609 #define STATUS_ENQUIRY      0x0c
610 #define STATUS              0x0d
611 #define PROTOCOL_PARAMETER  0x0e
612 /* message types of Control protocol */
613 #define PORT_CONTROL        0x10
614 #define PORT_CONTROL_ACK    0x11
615 #define COMMON_CONTROL      0x12
616 #define COMMON_CONTROL_ACK  0x13
617 /* message types of PROT protocol */
618 #define SWITCH_OVER_REQ     0x18
619 #define SWITCH_OVER_COM     0x19
620 #define OS_SWITCH_OVER_COM  0x1a
621 #define SWITCH_OVER_ACK     0x1b
622 #define SWITCH_OVER_REJECT  0x1c
623 #define PROT_PROTOCOL_ERROR 0x1d
624 #define RESET_SN_COM        0x1e
625 #define RESET_SN_ACK        0x1f
626 /* message types of BCC */
627 #define ALLOCATION             0x20
628 #define ALLOCATION_COMPLETE    0x21
629 #define ALLOCATION_REJECT      0x22
630 #define DE_ALLOCATION          0x23
631 #define DE_ALLOCATION_COMPLETE 0x24
632 #define DE_ALLOCATION_REJECT   0x25
633 #define AUDIT                  0x26
634 #define AUDIT_COMPLETE         0x27
635 #define AN_FAULT               0x28
636 #define AN_FAULT_ACKNOWLEDGE   0x29
637 #define BCC_PROTOCOL_ERROR     0x2a
638 /* message types of Link Control protocol */
639 #define LINK_CONTROL        0x30
640 #define LINK_CONTROL_ACK    0x31
641
642 static const value_string l3_msg_type_values [] = {
643         { ESTABLISH,             "Establish" },
644         { ESTABLISH_ACK,         "Establish Ack" },
645         { SIGNAL,                "Signal" },
646         { SIGNAL_ACK,            "Signal Ack" },
647         { DISCONNECT,            "Disconnect" },
648         { DISCONNECT_COMPLETE,   "Disconnect Complete" },
649         { STATUS_ENQUIRY,        "Status Enqueiry" },
650         { STATUS,                "Status" },
651         { PROTOCOL_PARAMETER,    "Protocol Parameter" },
652         { PORT_CONTROL,          "Port Control" },
653         { PORT_CONTROL_ACK,      "Port Control Ack" },
654         { COMMON_CONTROL,        "Common Control" },
655         { COMMON_CONTROL_ACK,    "Common Control Ack" },
656         { SWITCH_OVER_REQ,       "Switch-Over Request" },
657         { SWITCH_OVER_COM,       "Switch-Over Com" },
658         { OS_SWITCH_OVER_COM,    "OS-Switch-Over Com" },
659         { SWITCH_OVER_ACK,       "Switch-Over Ack" },
660         { SWITCH_OVER_REJECT,    "Switch-Over Reject" },
661         { PROT_PROTOCOL_ERROR,   "Protection Protocol Error" },
662         { RESET_SN_COM,          "Reset SN Com" },
663         { RESET_SN_ACK,          "Reset SN Ack" },
664         { ALLOCATION,            "Allocation" },
665         { ALLOCATION_COMPLETE,   "Allocation Complete" },
666         { ALLOCATION_REJECT,     "Allocation Reject" },
667         { DE_ALLOCATION,         "DE Allocation" },
668         { DE_ALLOCATION_COMPLETE,"DE Allocation Complete" },
669         { DE_ALLOCATION_REJECT,  "DE Allocation Reject" },
670         { AUDIT,                 "Audit" },
671         { AUDIT_COMPLETE,        "Audit Complete" },
672         { AN_FAULT,              "AN Fault" },
673         { AN_FAULT_ACKNOWLEDGE,  "AN Fault Ack" },
674         { BCC_PROTOCOL_ERROR,    "BCC Protocol Error" },
675         { LINK_CONTROL,          "Link Control" },
676         { LINK_CONTROL_ACK,      "Link Control Ack" },
677         { 0,                     NULL } };
678
679 /* PSTN protocol message info elements */
680 #define PULSE_NOTIFICATION   0xc0
681 #define LINE_INFORMATION     0x80
682 #define STATE                0x90
683 #define AUTO_SIG_SEQUENCE    0xa0
684 #define SEQUENCE_RESPONSE    0xb0
685 #define PSTN_SEQUENCE_NUMBER 0x00
686 #define CADENCED_RINGING     0x01
687 #define PULSED_SIGNAL        0x02
688 #define STEADY_SIGNAL        0x03
689 #define DIGIT_SIGNAL         0x04
690 #define RECOGNITION_TIME     0x10
691 #define ENABLE_AUTO_ACK      0x11
692 #define DISABLE_AUTO_ACK     0x12
693 #define CAUSE                0x13
694 #define RESOURCE_UNAVAILABLE 0x14
695
696 static const value_string l3_line_info_values [] = {
697         { 0x00, "Impedance marker reset" },
698         { 0x01, "Impedance marker set" },
699         { 0x02, "Low loop impedance" },
700         { 0x03, "Anomalous loop impedance" },
701         { 0x04, "Anomalous line condition received"},
702         { 0,    NULL } };
703
704 static const value_string l3_pulse_type_values [] = {
705         { 0xff, "Pulsed normal polarity" },
706         { 0xfe, "Pulsed reversed polarity" },
707         { 0xfd, "Pulsed battery on c-wire" },
708         { 0xfc, "Pulsed on hook" },
709         { 0xfb, "Pulsed reduced battery" },
710         { 0xfa, "Pulsed no battery" },
711         { 0xf9, "Initial ring" },
712         { 0xf8, "Meter pulse" },
713         { 0xf7, "50 Hz pulse" },
714         { 0xf6, "Register recall (timed loop open)" },
715         { 0xf5, "Pulsed off hook (pulsed loop closed)" },
716         { 0xf4, "Pulsed b-wire connected to earth" },
717         { 0xf3, "Earth loop pulse" },
718         { 0xf2, "Pulsed b-wire connected to battery" },
719         { 0xf1, "Pulsed a-wire connected to earth" },
720         { 0xf0, "Pulsed a-wire connected to battery" },
721         { 0xef, "Pulsed c-wire connected to earth" },
722         { 0xee, "Pulsed c-wire disconnected" },
723         { 0xed, "Pulsed normal battery" },
724         { 0xec, "Pulsed a-wire disconnected" },
725         { 0xeb, "Pulsed b-wire disconnected" },
726         { 0,    NULL } };
727
728 static const value_string l3_suppression_indication_values [] = {
729         { 0x0, "No suppression" },
730         { 0x1, "Suppression allowed by pre-defined V5.1 SIGNAL msg from LE" },
731         { 0x2, "Suppression allowed by pre-defined line signal from TE" },
732         { 0x3, "Suppression allowed by pre-defined V5.1 SIGNAL msg from LE or line signal from TE" },
733         { 0,   NULL } };
734
735 static const value_string l3_ack_request_indication_values [] = {
736         { 0x0, "No acknowledgement requested" },
737         { 0x1, "Ending acknowledgement requested when finished each pulses" },
738         { 0x2, "Ending acknowledgement requested when finished all pulses" },
739         { 0x3, "Start of pulse acknowledgement requested" },
740         { 0,   NULL } };
741
742 static const value_string l3_digit_ack_values [] = {
743         { 0x0, "No ending acknowledgement requested" },
744         { 0x1, "Ending acknowledgement requested when digit transmission is finished" },
745         { 0,   NULL } };
746
747 static const value_string l3_state_values [] = {
748         { 0x00, "AN0" },
749         { 0x01, "AN1" },
750         { 0x02, "AN2" },
751         { 0x03, "AN3" },
752         { 0x04, "AN4" },
753         { 0x05, "AN5" },
754         { 0x06, "AN6" },
755         { 0x07, "AN7" },
756         { 0,    NULL } };
757
758 static const value_string l3_steady_signal_values [] = {
759         { 0x80, "Normal polarity" },
760         { 0x81, "Reversed polarity" },
761         { 0x82, "Battery on c-wire" },
762         { 0x83, "No battery on c-wire" },
763         { 0x84, "Off hook (loop closed)" },
764         { 0x85, "On hook (loop open)" },
765         { 0x86, "Battery on a-wire" },
766         { 0x87, "A-wire on earth" },
767         { 0x88, "No battery on a-wire" },
768         { 0x89, "No batery on b-wire" },
769         { 0x8a, "Reduced battery" },
770         { 0x8b, "No battery" },
771         { 0x8c, "Alternate reduced power / no power" },
772         { 0x8d, "Normal battery" },
773         { 0x8e, "Stop ringing" },
774         { 0x8f, "Start pilot frequency" },
775         { 0x90, "Stop pilot frequency" },
776         { 0x91, "Low impedance on b-wire" },
777         { 0x92, "B-wire connected to earth" },
778         { 0x93, "B-wire disconnected from earth" },
779         { 0x94, "Battery on b-wire" },
780         { 0x95, "Low loop impedance" },
781         { 0x96, "High loop impedance" },
782         { 0x97, "Anomalous loop impedance" },
783         { 0x98, "A-wire disconnected from earth" },
784         { 0x99, "C-wire on earth" },
785         { 0x9a, "C-wire disconnected from earth" },
786         { 0,    NULL } };
787
788 static const value_string l3_cause_type_values [] = {
789         { 0x00, "Response to STATUS ENQUIRY" },
790         { 0x01, "Protocol discriminator error" },
791         { 0x03, "L3 address error" },
792         { 0x04, "Message type unrecognized" },
793         { 0x05, "Out of sequence information element" },
794         { 0x06, "Repeated optional information element" },
795         { 0x07, "Mandatory information element missing" },
796         { 0x08, "Unrecognized information element" },
797         { 0x09, "Mandatory information element content error" },
798         { 0x0a, "Optional information element content error" },
799         { 0x0b, "Message not compatible with path state" },
800         { 0x0c, "Repeated mandatory information element" },
801         { 0x0d, "Too many information elements" },
802         { 0,    NULL } };
803
804 /* BCC protocol message info elements */
805 #define USER_PORT_ID             0x40
806 #define ISDN_PORT_CHNL_ID        0x41
807 #define V5_TIME_SLOT_ID          0x42
808 #define MULTI_SLOT_MAP           0x43
809 #define BCC_REJECT_CAUSE         0x44
810 #define BCC_PROTOCOL_ERROR_CAUSE 0x45
811 #define CONNECTION_INCOMPLETE    0x46
812
813 static const value_string l3_reject_cause_type_values [] = {
814         { 0x00, "Unspecified" },
815         { 0x01, "Access network fault" },
816         { 0x02, "Access network blocked (internally)" },
817         { 0x03, "Connection already present at the PSTN user port to a different V5 time slot" },
818         { 0x04, "Connection already present at the V5 time slot(s) to a different port or ISDN user port time slot(s)" },
819         { 0x05, "Connection already present at the ISDN user port time slot(s) to a different V5 time slot(s)" },
820         { 0x06, "User port unavailable (blocked)" },
821         { 0x07, "De-allocation cannot completeddue to incompatible data content" },
822         { 0x08, "De-allocation cannot completeddue to V5 time slot(s) data incompatibility" },
823         { 0x09, "De-allocation cannot completeddue to port data incompatibility" },
824         { 0x0a, "De-allocation cannot completeddue to user port time slot(s) data incompatibility" },
825         { 0x0b, "User port not provisioned" },
826         { 0x0c, "Invalid V5 time slot(s) indication(s)" },
827         { 0x0d, "Invalid V5 2048 kbit/s link indication" },
828         { 0x0e, "Invalid user time slot(s) indication(s)" },
829         { 0x0f, "V5 time slot(s) being used as physikal C-channel(s)" },
830         { 0x10, "V5 link unavailable (blocked)" },
831         { 0,    NULL } };
832
833 static const value_string l3_bcc_protocol_error_cause_type_values [] = {
834         { 0x01, "Protocol discriminator error" },
835         { 0x04, "Message type unrecognized" },
836         { 0x05, "Out of sequence information element" },
837         { 0x06, "Repeated optional information element" },
838         { 0x07, "Mandatory information element missing" },
839         { 0x08, "Unrecognized information element" },
840         { 0x09, "Mandatory information element content error" },
841         { 0x0a, "Optional infromation element content error" },
842         { 0x0b, "Message not compatible with the BCC protocol state" },
843         { 0x0c, "Repeated mandatory information element" },
844         { 0x0d, "Too many information element" },
845         { 0x0f, "BCC Reference Number coding error" },
846         { 0,    NULL } };
847
848 static const value_string l3_connection_incomplete_reason_values [] = {
849         { 0x00, "Incomplete normal" },
850         { 0x01, "Access network fault" },
851         { 0x02, "User port not provisioned" },
852         { 0x03, "Invalid V5 time slot identification" },
853         { 0x04, "Invalid V5 2048 kbit/s link identification" },
854         { 0x05, "Time slot being used as physikal C-channel" },
855         { 0,    NULL } };
856
857
858 /* Link control protocol message info elements */
859 #define LINK_CONTROL_FUNCTION 0x30
860
861 static const value_string l3_link_control_function_values [] = {
862         { 0x00, "FE-IDReq" },
863         { 0x01, "FE-IDAck" },
864         { 0x02, "FE-IDRel" },
865         { 0x03, "FE-IDRej" },
866         { 0x04, "FE301/302 (link unblock)" },
867         { 0x05, "FE303/304 (link block)" },
868         { 0x06, "FE305 (deferred link block request" },
869         { 0x07, "FE306 (non-deferred link block request)" },
870         { 0,    NULL } };
871
872 /* Protection protocol message info elements */
873 #define SEQUENCE_NUMBER    0x50
874 #define C_CHANNEL_ID       0x51
875 #define PP_REJECTION_CAUSE 0x52
876 #define PROTOCOL_ERROR     0x53
877
878 /* Control protocolmessage info elements  */
879 #define PERFORMANCE_GRADING      0xe0
880 #define CP_REJECTION_CAUSE       0xf0
881 #define CONTROL_FUNCTION_ELEMENT 0x20
882 #define CONTROL_FUNCTION_ID      0x21
883 #define VARIANT                  0x22
884 #define INTERFACE_ID             0x23
885
886 static const value_string l3_performance_grading_values [] = {
887         { 0x00, "normal grade" },
888         { 0x01, "degraded" },
889         { 0,    NULL } };
890
891 static const value_string l3_cp_rejection_cause_values [] = {
892         { 0x00, "variant unknown" },
893         { 0x01, "variant known, not ready" },
894         { 0x02, "re-provisioning in progress (re-pro)" },
895         { 0,    NULL } };
896
897 static const value_string l3_control_function_element_values [] = {
898         { 0x01, "FE101 (activate access)" },
899         { 0x02, "FE102 (activation initiated by user)" },
900         { 0x03, "FE103 (DS activated)" },
901         { 0x04, "FE104 (access activated)" },
902         { 0x05, "FE105 (deactivate access)" },
903         { 0x06, "FE106 (access deactivated)" },
904         { 0x11, "FE201/202 (unblock)" },
905         { 0x13, "FE203/204 (block)" },
906         { 0x15, "FE205 (block request)" },
907         { 0x16, "FE206 (performance grading)" },
908         { 0x17, "FE207 (D-channel block)" },
909         { 0x18, "FE208 (D-channel unblock)" },
910         { 0,    NULL } };
911
912 static const value_string l3_control_function_id_values [] = {
913         { 0x00, "Verify re-provisioning" },
914         { 0x01, "Ready for re-provisioning" },
915         { 0x02, "Not ready for re-provisioning" },
916         { 0x03, "Switch-over to new variant" },
917         { 0x04, "Re-provisioning started" },
918         { 0x05, "Cannot re-provision" },
919         { 0x06, "Request variant and interface ID" },
920         { 0x07, "Variant and interface ID" },
921         { 0x08, "Blocking started" },
922         { 0x10, "Restart request" },
923         { 0x11, "Restart complete" },
924         { 0,    NULL } };
925
926 static const value_string l3_info_element_values [] = {
927         { PULSE_NOTIFICATION,      "Pulse notification" },
928         { LINE_INFORMATION,        "Line information" },
929         { STATE,                   "State" },
930         { AUTO_SIG_SEQUENCE,       "Autonomous signal sequence" },
931         { SEQUENCE_RESPONSE,       "Sequence response" },
932         { PSTN_SEQUENCE_NUMBER,    "Sequence number" },
933         { CADENCED_RINGING,        "Cadenced ringing" },
934         { PULSED_SIGNAL,           "Pulsed signal" },
935         { STEADY_SIGNAL,           "Steady signal" },
936         { DIGIT_SIGNAL,            "Digit signal" },
937         { RECOGNITION_TIME,        "Recognition time" },
938         { ENABLE_AUTO_ACK,         "Enable autonomous acknowledge" },
939         { DISABLE_AUTO_ACK,        "Disable autonomous acknowledge" },
940         { CAUSE,                   "Cause" },
941         { RESOURCE_UNAVAILABLE,    "Resource unavailable" },
942         { PERFORMANCE_GRADING,     "Performance grading" },
943         { CP_REJECTION_CAUSE,      "Rejection cause" },
944         { CONTROL_FUNCTION_ELEMENT,"Control function element" },
945         { CONTROL_FUNCTION_ID,     "Control function ID" },
946         { VARIANT,                 "Variant" },
947         { INTERFACE_ID,            "Interface ID" },
948         { LINK_CONTROL_FUNCTION,   "Link control funktion" },
949         { USER_PORT_ID,            "User port ID" },
950         { ISDN_PORT_CHNL_ID,       "ISDN port channel ID" },
951         { V5_TIME_SLOT_ID,         "V5 time slot ID" },
952         { MULTI_SLOT_MAP,          "Multi slot map" },
953         { BCC_REJECT_CAUSE,        "Reject cause" },
954         { BCC_PROTOCOL_ERROR_CAUSE,"Protocol error cause" },
955         { CONNECTION_INCOMPLETE,   "Connection incomplete" },
956         { SEQUENCE_NUMBER,         "Sequence number" },
957         { C_CHANNEL_ID,            "C-Channel ID" },
958         { PP_REJECTION_CAUSE,      "Rejection cause" },
959         { PROTOCOL_ERROR,          "Protocol error" },
960         { 0,                       NULL } };
961
962
963 #define DISCRIMINATOR_OFFSET 0
964 #define DISCRIMINATOR_LENGTH 1
965 #define ADDRESS_OFFSET       1
966 #define ADDRESS_LENGTH       1
967 #define LOW_ADDRESS_OFFSET   2
968 #define LOW_ADDRESS_LENGTH   1
969 #define MSG_TYPE_OFFSET      3
970 #define MSG_TYPE_LENGTH      1
971 #define MSG_HEADER_LENGTH    4
972 #define INFO_ELEMENT_OFFSET  4
973 #define INFO_ELEMENT_LENGTH  1
974
975 static void
976 dissect_layer3_message(tvbuff_t *layer3_data_tvb, proto_tree *v5ua_tree,proto_item *parameter_item, packet_info *pinfo)
977 {
978   proto_item *layer3_header_item,*layer3_item;
979   proto_tree *layer3_header_tree,*layer3_tree;
980   guint16 discriminator_offset, address_offset, low_address_offset, msg_type_offset,  info_element_offset;
981   guint8  info_element, info_element_length, buffer;
982
983   if(iua_version == DRAFT){
984           discriminator_offset = DISCRIMINATOR_OFFSET;
985           address_offset       = ADDRESS_OFFSET;
986           low_address_offset   = LOW_ADDRESS_OFFSET;
987           msg_type_offset      = MSG_TYPE_OFFSET;
988           info_element_offset  = INFO_ELEMENT_OFFSET;
989   }
990   else{
991           discriminator_offset = DISCRIMINATOR_OFFSET + PARAMETER_HEADER_LENGTH;
992           address_offset       = ADDRESS_OFFSET + PARAMETER_HEADER_LENGTH;
993           low_address_offset   = LOW_ADDRESS_OFFSET + PARAMETER_HEADER_LENGTH;
994           msg_type_offset      = MSG_TYPE_OFFSET + PARAMETER_HEADER_LENGTH;
995           info_element_offset  = INFO_ELEMENT_OFFSET + PARAMETER_HEADER_LENGTH;
996   }
997   
998
999   if(tvb_get_guint8(layer3_data_tvb, discriminator_offset) == 0x48){
1000           layer3_header_item   = proto_tree_add_text(v5ua_tree, layer3_data_tvb, discriminator_offset, MSG_HEADER_LENGTH,"Layer3 header");
1001           layer3_header_tree   = proto_item_add_subtree(layer3_header_item, ett_v5ua_layer3);
1002
1003           proto_tree_add_item(layer3_header_tree, hf_l3_protocol_discriminator, layer3_data_tvb, discriminator_offset, DISCRIMINATOR_LENGTH, FALSE);
1004           proto_tree_add_item(layer3_header_tree, hf_l3_adress, layer3_data_tvb, address_offset, ADDRESS_LENGTH, FALSE);
1005           proto_tree_add_item(layer3_header_tree, hf_l3_low_adress, layer3_data_tvb, low_address_offset, LOW_ADDRESS_LENGTH, FALSE);
1006           proto_tree_add_item(layer3_header_tree, hf_l3_msg_type, layer3_data_tvb, msg_type_offset, MSG_TYPE_LENGTH, FALSE);
1007           proto_item_append_text(layer3_header_item, "  Msg Type: %s",
1008                                                   val_to_str(tvb_get_guint8(layer3_data_tvb, msg_type_offset), l3_msg_type_values, "Unknown layer3 msg type"));
1009
1010           if(tvb_length_remaining(layer3_data_tvb,info_element_offset)){
1011                   layer3_item   = proto_tree_add_text(v5ua_tree, layer3_data_tvb, info_element_offset, tvb_length(layer3_data_tvb)-MSG_HEADER_LENGTH,"Layer3 message");
1012                   layer3_tree   = proto_item_add_subtree(layer3_item, ett_v5ua_layer3);
1013
1014                   info_element_offset  = INFO_ELEMENT_OFFSET;
1015
1016                   while(tvb_length_remaining(layer3_data_tvb,info_element_offset)){
1017                           info_element = tvb_get_guint8(layer3_data_tvb, info_element_offset);
1018                           proto_tree_add_item_hidden(layer3_tree, hf_l3_info_element, layer3_data_tvb,info_element_offset,INFO_ELEMENT_LENGTH,FALSE);
1019                           switch(tvb_get_guint8(layer3_data_tvb, msg_type_offset) & 0xf0){
1020                           case 0x00:
1021                                   /* Variable Length */
1022                                   if(info_element < 0x80){
1023                                   switch(info_element){
1024                                   case PSTN_SEQUENCE_NUMBER:
1025                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1026                                           proto_tree_add_item(layer3_tree,hf_l3_pstn_sequence_number,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1027                                           info_element_offset +=info_element_length+2;
1028                                           break;
1029                                   case CADENCED_RINGING:
1030                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1031                                           proto_tree_add_item(layer3_tree,hf_l3_cad_ringing,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1032                                           info_element_offset +=info_element_length+2;
1033                                           break;
1034                                   case PULSED_SIGNAL:
1035                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1036                                           proto_tree_add_item(layer3_tree,hf_l3_pulse_type,layer3_data_tvb,info_element_offset+2,1,FALSE);/*info_element_length,FALSE); */
1037                                           proto_tree_add_item(layer3_tree,hf_l3_suppression_indicator,layer3_data_tvb,info_element_offset+3,1,FALSE);
1038                                           proto_tree_add_item(layer3_tree,hf_l3_pulse_duration,layer3_data_tvb,info_element_offset+3,1,FALSE);
1039                                           proto_tree_add_item(layer3_tree,hf_l3_ack_request_indicator,layer3_data_tvb,info_element_offset+4,1,FALSE);
1040                                           proto_tree_add_item(layer3_tree,hf_l3_number_of_pulses,layer3_data_tvb,info_element_offset+4,1,FALSE);
1041                                           info_element_offset +=info_element_length+2;
1042                                           break;
1043                                   case STEADY_SIGNAL:
1044                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1045                                           proto_tree_add_item(layer3_tree,hf_l3_steady_signal,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1046                                           proto_item_append_text(layer3_item, "  Steady Signal: %s",
1047                                                                                         val_to_str(tvb_get_guint8(layer3_data_tvb, info_element_offset+2), l3_steady_signal_values, "Unknown Signal"));
1048                                           info_element_offset +=info_element_length+2;
1049                                           break;
1050                                   case DIGIT_SIGNAL:
1051                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1052                                           buffer = tvb_get_guint8(layer3_data_tvb, info_element_offset+2)>>6;
1053                                           buffer = buffer&0x01;
1054                                           proto_tree_add_uint_format(layer3_tree, hf_l3_digit_ack,layer3_data_tvb,info_element_offset+2,1,buffer,
1055                                                                                                         "Digit ack request indication: %s",val_to_str(buffer,l3_digit_ack_values,"unknown"));
1056                                           proto_tree_add_item(layer3_tree,hf_l3_digit_info,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1057                                           info_element_offset +=info_element_length+2;
1058                                           break;
1059                                   case RECOGNITION_TIME:
1060                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1061                                           buffer = tvb_get_guint8(layer3_data_tvb,info_element_offset+2)&0x7f;
1062                                           /*Signal = Coding of pulse type*/
1063                                           if(buffer>=0x6b)
1064                                                 proto_tree_add_item(layer3_tree,hf_l3_pulse_type,layer3_data_tvb,info_element_offset+2,1,FALSE);
1065                                           /*Signal = Coding of steady signal type*/
1066                                           else if(buffer<=0x1a)
1067                                                 proto_tree_add_item(layer3_tree,hf_l3_steady_signal,layer3_data_tvb,info_element_offset+2,1,FALSE);
1068                                           proto_tree_add_item(layer3_tree,hf_l3_duration_type,layer3_data_tvb,info_element_offset+3,1,FALSE);
1069                                           info_element_offset +=info_element_length+2;
1070                                           break;
1071                                   case ENABLE_AUTO_ACK:
1072                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1073                                           buffer = tvb_get_guint8(layer3_data_tvb,info_element_offset+2)&0x7f;
1074                                           /*Signal*/
1075                                           if(buffer>=0x6b)
1076                                                 proto_tree_add_item(layer3_tree,hf_l3_pulse_type,layer3_data_tvb,info_element_offset+2,1,FALSE);
1077                                           else if(buffer<=0x1a)
1078                                                 proto_tree_add_item(layer3_tree,hf_l3_steady_signal,layer3_data_tvb,info_element_offset+2,1,FALSE);
1079
1080                                           buffer = tvb_get_guint8(layer3_data_tvb,info_element_offset+3)&0x7f;
1081                                           /*Response*/
1082                                           if(buffer>=0x6b)
1083                                                 proto_tree_add_item(layer3_tree,hf_l3_pulse_type,layer3_data_tvb,info_element_offset+3,1,FALSE);
1084                                           else if(buffer<=0x1a)
1085                                                 proto_tree_add_item(layer3_tree,hf_l3_steady_signal,layer3_data_tvb,info_element_offset+3,1,FALSE);
1086                                                 
1087                                           if(tvb_length_remaining(layer3_data_tvb, info_element_offset+4)){
1088                                                 proto_tree_add_item(layer3_tree,hf_l3_suppression_indicator,layer3_data_tvb,info_element_offset+4,1,FALSE);
1089                                                 proto_tree_add_item(layer3_tree,hf_l3_pulse_duration,layer3_data_tvb,info_element_offset+4,1,FALSE);
1090                                           }
1091                                           if(tvb_length_remaining(layer3_data_tvb, info_element_offset+5)){
1092                                                 proto_tree_add_item(layer3_tree,hf_l3_ack_request_indicator,layer3_data_tvb,info_element_offset+5,1,FALSE);
1093                                                 proto_tree_add_item(layer3_tree,hf_l3_number_of_pulses,layer3_data_tvb,info_element_offset+5,1,FALSE);
1094                                           }
1095                                           info_element_offset +=info_element_length+2;
1096                                           break;
1097                                   case DISABLE_AUTO_ACK:
1098                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1099                                           buffer = tvb_get_guint8(layer3_data_tvb,info_element_offset+2)&0x7f;
1100                                           if(buffer>=0x6b)
1101                                                 proto_tree_add_item(layer3_tree,hf_l3_pulse_type,layer3_data_tvb,info_element_offset+2,1,FALSE);
1102                                           else if(buffer<=0x1a)
1103                                                 proto_tree_add_item(layer3_tree,hf_l3_steady_signal,layer3_data_tvb,info_element_offset+2,1,FALSE);
1104                                           info_element_offset +=info_element_length+2;
1105                                           break;
1106                                   case CAUSE:
1107                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1108                                           proto_tree_add_item(layer3_tree,hf_l3_cause_type,layer3_data_tvb,info_element_offset+2,1,FALSE);
1109                                           if(tvb_length_remaining(layer3_data_tvb, info_element_offset+3))
1110                                           proto_tree_add_uint_format(layer3_tree, hf_l3_msg_type,layer3_data_tvb, info_element_offset+3,1,tvb_get_guint8(layer3_data_tvb,info_element_offset+3),
1111                                                                                                 "Diagnostic: %s",val_to_str(tvb_get_guint8(layer3_data_tvb,info_element_offset+3),l3_msg_type_values,"unknown"));
1112                                           info_element_offset +=info_element_length+2;
1113                                           break;
1114                                   case RESOURCE_UNAVAILABLE:
1115                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1116                                           proto_tree_add_item(layer3_tree,hf_l3_res_unavailable,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1117                                           info_element_offset +=info_element_length+2;
1118                                           break;
1119                                   default:
1120                                           info_element_offset += 1;
1121                                           break;
1122                                   }
1123                                   }
1124                                   /* Single Octet */
1125                                   else if(info_element >= 0x80){
1126                                           switch(info_element & 0xf0){
1127                                           case PULSE_NOTIFICATION:
1128                                                   proto_tree_add_item(layer3_tree,hf_l3_pulse_notify,layer3_data_tvb,info_element_offset,1,FALSE);
1129                                                   break;
1130                                           case LINE_INFORMATION:
1131                                                   proto_tree_add_item(layer3_tree,hf_l3_line_info,layer3_data_tvb,info_element_offset,1,FALSE);
1132                                                   break;
1133                                           case STATE:
1134                                                   proto_tree_add_item(layer3_tree,hf_l3_state,layer3_data_tvb,info_element_offset,1,FALSE);
1135                                                   break;
1136                                           case AUTO_SIG_SEQUENCE:
1137                                                   proto_tree_add_item(layer3_tree,hf_l3_auto_signalling_sequence,layer3_data_tvb,info_element_offset,1,FALSE);
1138                                                   break;
1139                                           case SEQUENCE_RESPONSE:
1140                                                   proto_tree_add_item(layer3_tree,hf_l3_sequence_response,layer3_data_tvb,info_element_offset,1,FALSE);
1141                                                   break;
1142                                           default:
1143                                                   break;
1144                                           }
1145                                           info_element_offset += 1;
1146                                   }
1147                                   break;
1148
1149                           case 0x10:
1150                                   /* Variable Length */
1151                                   if(info_element < 0x80){
1152                                   switch(info_element){
1153                                   case CONTROL_FUNCTION_ELEMENT:
1154                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1155                                           proto_tree_add_item(layer3_tree,hf_l3_control_function_element,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1156                                           info_element_offset +=info_element_length+2;
1157                                           break;
1158                                   case CONTROL_FUNCTION_ID:
1159                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1160                                           proto_tree_add_item(layer3_tree,hf_l3_control_function_id,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1161                                           info_element_offset +=info_element_length+2;
1162                                           break;
1163                                   case VARIANT:
1164                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1165                                           proto_tree_add_item(layer3_tree,hf_l3_variant,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1166                                           info_element_offset +=info_element_length+2;
1167                                           break;
1168                                   case INTERFACE_ID:
1169                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1170                                           proto_tree_add_item(layer3_tree,hf_l3_if_id,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1171                                           info_element_offset +=info_element_length+2;
1172                                           break;
1173                                   case SEQUENCE_NUMBER:
1174                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1175                                           proto_tree_add_item(layer3_tree,hf_l3_sequence_number,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1176                                           info_element_offset +=info_element_length+2;
1177                                           break;
1178                                   case C_CHANNEL_ID:
1179                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1180                                           proto_tree_add_item(layer3_tree,hf_l3_v5_link_id,layer3_data_tvb,info_element_offset+2,1,FALSE);
1181                                           proto_tree_add_item(layer3_tree,hf_l3_v5_time_slot,layer3_data_tvb,info_element_offset+3,1,FALSE);
1182                                           info_element_offset +=info_element_length+2;
1183                                           break;
1184                                   case PP_REJECTION_CAUSE:
1185                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1186                                           proto_tree_add_item(layer3_tree,hf_l3_rejection_cause_type,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1187                                           info_element_offset +=info_element_length+2;
1188                                           break;
1189                                   case PROTOCOL_ERROR:
1190                                           break;
1191                                   default:
1192                                           info_element_offset += 1;
1193                                           break;
1194                                   }
1195                                   }
1196                                   /* Single Octet */
1197                                   else if(info_element >= 0x80){
1198                                           switch(info_element & 0xf0){
1199                                           case PERFORMANCE_GRADING:
1200                                                   proto_tree_add_item(layer3_tree,hf_l3_performance_grading,layer3_data_tvb,info_element_offset,1,FALSE);
1201                                                   break;
1202                                           case CP_REJECTION_CAUSE:
1203                                                   proto_tree_add_item(layer3_tree,hf_l3_cp_rejection_cause,layer3_data_tvb,info_element_offset,1,FALSE);
1204                                                   break;
1205                                           default:
1206                                                   break;
1207                                           }
1208                                           info_element_offset += 1;
1209                                   }
1210                                   break;
1211
1212                           case 0x20:
1213                                   /* Variable Length */
1214                                   switch(info_element){
1215                                   case USER_PORT_ID:
1216                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1217                                           buffer = tvb_get_guint8(layer3_data_tvb,info_element_offset+2)&0x01;
1218                                           if(buffer==0x01){
1219                                                   proto_tree_add_item(layer3_tree,hf_l3_pstn_user_port_id,layer3_data_tvb,info_element_offset+2,1,FALSE);
1220                                                   proto_tree_add_item(layer3_tree,hf_l3_pstn_user_port_id_lower,layer3_data_tvb,info_element_offset+3,1,FALSE);
1221                                           }
1222                                           else if(buffer == 0x00){
1223                                                   proto_tree_add_item(layer3_tree,hf_l3_isdn_user_port_id,layer3_data_tvb,info_element_offset+2,1,FALSE);
1224                                                   proto_tree_add_item(layer3_tree,hf_l3_isdn_user_port_id_lower,layer3_data_tvb,info_element_offset+3,1,FALSE);
1225                                           }
1226                                           info_element_offset +=info_element_length+2;                    
1227                                           break;
1228                                   case ISDN_PORT_CHNL_ID:
1229                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1230                                           proto_tree_add_item(layer3_tree,hf_l3_isdn_user_port_ts_num,layer3_data_tvb,info_element_offset+2,1,FALSE);
1231                                           info_element_offset +=info_element_length+2;
1232                                           break;
1233                                   case V5_TIME_SLOT_ID:
1234                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1235                                           proto_tree_add_item(layer3_tree,hf_l3_v5_link_id,layer3_data_tvb,info_element_offset+2,1,FALSE);
1236                                           proto_tree_add_item(layer3_tree,hf_l3_override,layer3_data_tvb,info_element_offset+3,1,FALSE);
1237                                           proto_tree_add_item(layer3_tree,hf_l3_v5_time_slot,layer3_data_tvb,info_element_offset+3,1,FALSE);
1238                                           info_element_offset +=info_element_length+2;
1239                                           break;
1240                                   case MULTI_SLOT_MAP:
1241                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1242                                           proto_tree_add_item(layer3_tree,hf_l3_v5_link_id,layer3_data_tvb,info_element_offset+2,1,FALSE);
1243                                           /* add ts upts here */
1244                                           info_element_offset +=info_element_length+2;
1245                                           break;
1246                                   case BCC_REJECT_CAUSE:
1247                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1248                                           proto_tree_add_item(layer3_tree,hf_l3_reject_cause_type,layer3_data_tvb,info_element_offset+2,1,FALSE);
1249                                           /* add diagnostic */
1250                                           info_element_offset +=info_element_length+2;
1251                                           break;
1252                                   case BCC_PROTOCOL_ERROR_CAUSE:
1253                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1254                                           proto_tree_add_item(layer3_tree,hf_l3_bcc_protocol_error_cause,layer3_data_tvb,info_element_offset+2,1,FALSE);
1255                                           /* add diagnostic */
1256                                           info_element_offset +=info_element_length+2;
1257                                           break;
1258                                   case CONNECTION_INCOMPLETE:
1259                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1260                                           proto_tree_add_item(layer3_tree,hf_l3_connection_incomplete_reason,layer3_data_tvb,info_element_offset+2,1,FALSE);
1261                                           info_element_offset +=info_element_length+2;
1262                                           break;
1263                                   default:
1264                                           info_element_offset += 1;
1265                                           break;
1266                                   }
1267                                   break;
1268
1269                           case 0x30:
1270                                   /* Variable Length */
1271                                   switch(info_element){
1272                                   case LINK_CONTROL_FUNCTION:
1273                                           info_element_length = tvb_get_guint8(layer3_data_tvb,info_element_offset+1);
1274                                           proto_tree_add_item(layer3_tree,hf_l3_link_control_function,layer3_data_tvb,info_element_offset+2,info_element_length,FALSE);
1275                                           info_element_offset += info_element_length+2;
1276                                           break;
1277                                   default:
1278                                           info_element_offset += 1;
1279                                           break;
1280                                   }
1281                                   break;
1282
1283                           default:
1284                                   info_element_offset += 1;
1285                                   break;
1286                           }
1287                   }
1288           }
1289   }
1290   else{
1291           guint16 protocol_data_length;
1292           tvbuff_t *protocol_data_tvb;
1293
1294           protocol_data_length = tvb_get_ntohs(layer3_data_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1295           protocol_data_tvb    = tvb_new_subset(layer3_data_tvb, PARAMETER_VALUE_OFFSET, protocol_data_length, protocol_data_length);
1296           call_dissector(q931_handle, protocol_data_tvb, pinfo, v5ua_tree);
1297
1298           proto_item_append_text(parameter_item, " (%u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
1299   }
1300 }
1301
1302 /*----------------------Data Request,Indication (Draft,RFC)------------------------*/
1303
1304 /*----------------------Establish Request,Confirm,Indication (Draft,RFC)-------*/
1305 /*
1306  * no additional parameter
1307  */
1308 /*----------------------Establish Request,Confirm,Indication (Draft,RFC)-------*/
1309
1310 /*----------------------Release Indication, Request (Draft,RFC)----------------*/
1311
1312         /* define parameters for Release Request and Indication Messages */
1313 #define RELEASE_MGMT   0x0
1314 #define RELEASE_PHYS   0x1
1315 #define RELEASE_DM     0x2
1316 #define RELEASE_OTHER  0x3
1317
1318 static const value_string release_reason_values[] = {
1319         { RELEASE_MGMT,    "Management layer generated release" },
1320         { RELEASE_PHYS,    "Physical layer alarm generated release" },
1321         { RELEASE_DM,      "Specific to a request" },
1322         { RELEASE_OTHER,   "Other reason" },
1323         { 0,               NULL } };
1324
1325 #define RELEASE_REASON_LENGTH_OFFSET PARAMETER_LENGTH_OFFSET
1326 #define RELEASE_REASON_OFFSET        PARAMETER_VALUE_OFFSET
1327 #define RELEASE_REASON_LENGTH        4
1328
1329 static void
1330 dissect_release_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1331 {
1332   gint offset = RELEASE_REASON_OFFSET;
1333   if(iua_version == DRAFT) offset = tvb_get_ntohs(parameter_tvb, RELEASE_REASON_LENGTH_OFFSET)+8;
1334   proto_tree_add_item(parameter_tree, hf_release_reason, parameter_tvb, offset, RELEASE_REASON_LENGTH, FALSE);
1335   if(iua_version != DRAFT)
1336           proto_item_append_text(parameter_item, " (%s)",
1337                                                 val_to_str(tvb_get_ntohl(parameter_tvb, offset), release_reason_values, "Unknown release reason"));
1338 }
1339 /*----------------------Release Indication,Request (Draft,RFC)-----------------*/
1340
1341 /*----------------------Link Status Start,Stop Report (Draft,RFC)--------------*/
1342 /*
1343  * No additional Parameter
1344  */
1345 /*----------------------Link Status Start,Stop Report (Draft,RFC)--------------*/
1346
1347 /*----------------------Link Status Indication (Draft,RFC)---------------------*/
1348
1349         /* define parameters for Link Status Indication */
1350 #define LINK_STATUS_OPERTIONAL      0x0
1351 #define LINK_STATUS_NON_OPERTIONAL  0x1
1352
1353 static const value_string link_status_values[] = {
1354   { LINK_STATUS_OPERTIONAL,      "Link is in operation" },
1355   { LINK_STATUS_NON_OPERTIONAL,  "Link is not in operation" },
1356   { 0,                           NULL } };
1357
1358 #define LINK_STATUS_OFFSET   PARAMETER_VALUE_OFFSET
1359 #define LINK_STATUS_LENGTH   4
1360
1361 static void
1362 dissect_link_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1363 {
1364   proto_tree_add_item(parameter_tree, hf_link_status, parameter_tvb, LINK_STATUS_OFFSET, LINK_STATUS_LENGTH, FALSE);
1365   proto_item_append_text(parameter_item, " (%s)",
1366                                           val_to_str(tvb_get_ntohl(parameter_tvb, LINK_STATUS_OFFSET),link_status_values, "Unknown Link status"));
1367 }
1368 /*----------------------Link Status Indication (Draft,RFC)---------------------*/
1369
1370 /*----------------------Sa-Bit (Draft,RFC)-------------------------------------*/
1371
1372         /* define parameter for sa-bit message */
1373 #define SA_BIT_ID_ZERO     0x0
1374 #define SA_BIT_ID_ONE      0x1
1375 #define SA_BIT_VALUE_SA7   0x7
1376
1377 static const value_string sa_bit_values[] = {
1378         { SA_BIT_ID_ZERO,    "set to ZERO" },
1379         { SA_BIT_ID_ONE,     "set to ONE" },
1380         { SA_BIT_VALUE_SA7,  "Sa7 Bit" },
1381         { 0,                 NULL } };
1382
1383 #define SA_BIT_ID_OFFSET     PARAMETER_VALUE_OFFSET
1384 #define SA_BIT_ID_LENGTH     2
1385 #define SA_BIT_VALUE_OFFSET  (SA_BIT_ID_OFFSET + SA_BIT_ID_LENGTH)
1386 #define SA_BIT_VALUE_LENGTH  2
1387
1388 static void
1389 dissect_sa_bit_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1390 {
1391   proto_tree_add_item(parameter_tree, hf_sa_bit_id, parameter_tvb, SA_BIT_ID_OFFSET, SA_BIT_ID_LENGTH, FALSE);
1392   proto_tree_add_item(parameter_tree, hf_sa_bit_value, parameter_tvb, SA_BIT_VALUE_OFFSET, SA_BIT_VALUE_LENGTH, FALSE);
1393   proto_item_append_text(parameter_item, " (%s %s)",
1394                                           val_to_str(tvb_get_ntohs(parameter_tvb, SA_BIT_ID_OFFSET), sa_bit_values, "unknown"),
1395                                           val_to_str(tvb_get_ntohs(parameter_tvb, SA_BIT_VALUE_OFFSET), sa_bit_values, "unknown Bit"));
1396
1397 }
1398 /*----------------------Sa-Bit (Draft,RFC)-------------------------------------*/
1399
1400 /*----------------------Error Indication (RFC)---------------------------------*/
1401
1402 #define ERROR_REASON_OVERLOAD 0x1
1403
1404 static const value_string error_reason_values[] = {
1405         { ERROR_REASON_OVERLOAD, "C-Channel is in overload state" },
1406         { 0,                     NULL } };
1407
1408 #define ERROR_REASON_LENGTH 4
1409 #define ERROR_REASON_OFFSET PARAMETER_VALUE_OFFSET
1410
1411 static void
1412 dissect_error_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1413 {
1414   proto_tree_add_item(parameter_tree, hf_error_reason, parameter_tvb, ERROR_REASON_OFFSET, ERROR_REASON_LENGTH, FALSE);
1415   proto_item_append_text(parameter_item, " (%s)",
1416                                           val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_REASON_OFFSET), error_reason_values, "unknown"));
1417 }
1418 /*----------------------Error Indication (RFC)---------------------------------*/
1419
1420 #define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
1421
1422 static void
1423 dissect_info_string_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1424 {
1425   guint16 info_string_length;
1426
1427   info_string_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1428   if(iua_version == DRAFT) info_string_length += 4;
1429   if(info_string_length > 4){
1430         info_string_length -= PARAMETER_HEADER_LENGTH;
1431         proto_tree_add_item(parameter_tree, hf_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, FALSE);
1432         proto_item_append_text(parameter_item, " (%.*s)", info_string_length,
1433                                      (const char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length));
1434   }
1435 }
1436
1437 static void
1438 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1439 {
1440   guint16 parameter_value_length;
1441
1442   parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1443   if (parameter_value_length > 0)
1444     proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, FALSE);
1445   proto_item_append_text(parameter_item, " with tag %u and %u byte%s value",
1446                          tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET), parameter_value_length, plurality(parameter_value_length, "", "s"));
1447 }
1448
1449
1450 #define INT_INTERFACE_IDENTIFIER_PARAMETER_TAG           0x01
1451 #define ASP_MSG_PARAMETER_TAG                            0x02
1452 #define TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG          0x03
1453 #define INFO_PARAMETER_TAG                               0x04
1454 #define DLCI_PARAMETER_TAG                               0x05
1455 #define DIAGNOSTIC_INFORMATION_PARAMETER_TAG             0x07
1456 #define INTEGER_RANGE_INTERFACE_IDENTIFIER_PARAMETER_TAG 0x08
1457 #define HEARTBEAT_DATA_PARAMETER_TAG                     0x09
1458 #define ASP_DOWN_REASON_PARAMETER_TAG                    0x0a
1459 #define TRAFFIC_MODE_TYPE_PARAMETER_TAG                  0x0b
1460 #define ERROR_CODE_PARAMETER_TAG                         0x0c
1461 #define STATUS_TYPE_INDENTIFICATION_PARAMETER_TAG        0x0d
1462 #define PROTOCOL_DATA_PARAMETER_TAG                      0x0e
1463 #define RELEASE_REASON_PARAMETER_TAG                     0x0f
1464 #define TEI_STATUS_PARAMETER_TAG                         0x10
1465 #define LINK_STATUS_PARAMETER_TAG                        0x11
1466 #define SA_BIT_STATUS_PARAMETER_TAG                      0x12
1467 #define ERROR_INDICATION_PARAMETER_TAG                   0x13
1468
1469 static const value_string parameter_tag_values[] = {
1470   { INT_INTERFACE_IDENTIFIER_PARAMETER_TAG,              "V5UA Interface Identifier (int)" },
1471   { TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG,             "Text Interface Identifier" },
1472   { INFO_PARAMETER_TAG,                                  "Info" },
1473   { DLCI_PARAMETER_TAG,                                  "DLCI" },
1474   { DIAGNOSTIC_INFORMATION_PARAMETER_TAG,                "Diagnostic information" },
1475   { INTEGER_RANGE_INTERFACE_IDENTIFIER_PARAMETER_TAG,    "Integer range interface identifier" },
1476   { HEARTBEAT_DATA_PARAMETER_TAG,                        "Hearbeat data" },
1477   { ASP_DOWN_REASON_PARAMETER_TAG,                       "ASP DOWN Reason" },
1478   { TRAFFIC_MODE_TYPE_PARAMETER_TAG,                     "Traffic mode type" },
1479   { ERROR_CODE_PARAMETER_TAG,                            "Error code" },
1480   { STATUS_TYPE_INDENTIFICATION_PARAMETER_TAG,           "Status type/identification" },
1481   { PROTOCOL_DATA_PARAMETER_TAG,                         "Protocol Data" },
1482   { RELEASE_REASON_PARAMETER_TAG,                        "Reason" },
1483   { TEI_STATUS_PARAMETER_TAG,                            "TEI status" },
1484   { LINK_STATUS_PARAMETER_TAG,                           "Link status" },
1485   { SA_BIT_STATUS_PARAMETER_TAG,                         "SA-Bit status" },
1486   { ERROR_INDICATION_PARAMETER_TAG,                      "Error reason" },
1487   { 0,                                                   NULL } };
1488
1489 static const value_string parameter_tag_draft_values[] = {
1490   { INT_INTERFACE_IDENTIFIER_PARAMETER_TAG,              "V5UA Interface Identifier (int)" },
1491   { ASP_MSG_PARAMETER_TAG,                               "ASP Adaption Layer ID" },
1492   { TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG,             "SCN Protocol Identifier" },
1493   { INFO_PARAMETER_TAG,                                  "Info" },
1494   { LINK_STATUS_PARAMETER_TAG,                           "Link status" },
1495   { SA_BIT_STATUS_PARAMETER_TAG,                         "SA-Bit status" },
1496   { ERROR_INDICATION_PARAMETER_TAG,                      "Error reason" },
1497   { 0,                                                   NULL } };
1498
1499
1500
1501 static void
1502 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *v5ua_tree)
1503 {
1504   guint16 tag, length, padding_length;
1505   proto_item *parameter_item;
1506   proto_tree *parameter_tree;
1507
1508   /* extract tag and length from the parameter */
1509   tag      = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1510   length   = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1511   /* on IUA-Draft messages the message length not including the message header */
1512   if((iua_version==DRAFT)&&(tag<=0x4)){
1513           /* at V5UA Header, length of header and length of DLCI+EFA must be added */
1514           if(tag==0x1)       length += 8;
1515           /* at ASP message tags only length of header must be added */
1516           else if(tag<=0x4)  length += PARAMETER_HEADER_LENGTH;
1517           /* for following message-tags are no length information available. Only in common msg header */
1518       if((msg_class==0 || msg_class==1 || msg_class==9) && msg_type<=10)
1519         length = msg_length;
1520   }
1521   padding_length = tvb_length(parameter_tvb) - length;
1522
1523   /* create proto_tree stuff */
1524
1525   switch(iua_version){
1526   case RFC:
1527           parameter_item   = proto_tree_add_text(v5ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb),
1528                                                            val_to_str(tag, parameter_tag_values, "Unknown parameter"));
1529       parameter_tree   = proto_item_add_subtree(parameter_item, ett_v5ua_parameter);
1530
1531           /* add tag to the v5ua tree */
1532       proto_tree_add_item(parameter_tree, hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, FALSE);
1533           break;
1534
1535   case DRAFT:
1536   default:
1537           parameter_item   = proto_tree_add_text(v5ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb),
1538                                                            val_to_str(tag, parameter_tag_draft_values, "Unknown parameter"));
1539       parameter_tree   = proto_item_add_subtree(parameter_item, ett_v5ua_parameter);
1540
1541           /* add tag to the v5ua tree */
1542          proto_tree_add_item(parameter_tree, hf_parameter_tag_draft, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, FALSE);
1543           break;
1544   
1545   };
1546
1547   /* add length to the v5ua tree */
1548   proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, FALSE);
1549
1550   switch(tag) {
1551   case INT_INTERFACE_IDENTIFIER_PARAMETER_TAG:
1552     if(iua_version == RFC )
1553                 dissect_int_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1554         if(iua_version == DRAFT){
1555                 dissect_int_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1556
1557                 dissect_dlci_parameter(parameter_tvb, parameter_tree, parameter_item);
1558
1559                 /* for the following parameters no tag- and length-informations available. Parameters must be dissect with info from common msg header */
1560                 if(msg_class==0 && msg_type==0)    dissect_draft_error_code_parameter(parameter_tvb, parameter_tree);
1561                 if(msg_class==1)                   dissect_draft_tei_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1562                 if(msg_class==9){
1563           if(msg_type==1||msg_type==2||msg_type==3||msg_type==4){
1564                  guint16 length, offset;
1565                  tvbuff_t *layer3_data_tvb;
1566                  offset = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) + 8;
1567                  length = msg_length - offset;
1568
1569              if(length > 0){
1570                if(tvb_get_guint8(parameter_tvb, offset) == 0x48){
1571                               layer3_data_tvb = tvb_new_subset(parameter_tvb, offset, length, length);
1572                               dissect_layer3_message(layer3_data_tvb, v5ua_tree, parameter_item, pinfo);
1573                            }
1574                          }
1575                   }
1576                   else if(msg_type==8||msg_type==10) dissect_release_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
1577                 }
1578         }
1579     break;
1580   case ASP_MSG_PARAMETER_TAG:
1581         dissect_asp_msg_parameter(parameter_tvb, parameter_tree, parameter_item);
1582         break;
1583   case TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG:
1584     if(iua_version == RFC)
1585                 dissect_text_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1586         if(iua_version == DRAFT)
1587                 dissect_scn_protocol_id_parameter(parameter_tvb, parameter_tree, parameter_item);
1588     break;
1589   case INFO_PARAMETER_TAG:
1590     dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
1591     break;
1592   case DLCI_PARAMETER_TAG:
1593     dissect_dlci_parameter(parameter_tvb, parameter_tree, parameter_item);
1594     break;
1595   case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
1596     dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1597     break;
1598   case INTEGER_RANGE_INTERFACE_IDENTIFIER_PARAMETER_TAG:
1599     dissect_integer_range_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1600     break;
1601   case HEARTBEAT_DATA_PARAMETER_TAG:
1602     dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1603     break;
1604   case ASP_DOWN_REASON_PARAMETER_TAG:
1605     dissect_asp_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
1606     break;
1607   case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1608     dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1609     break;
1610   case ERROR_CODE_PARAMETER_TAG:
1611     dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1612     break;
1613   case STATUS_TYPE_INDENTIFICATION_PARAMETER_TAG:
1614     dissect_status_type_identification_parameter(parameter_tvb, parameter_tree, parameter_item);
1615     break;
1616   case PROTOCOL_DATA_PARAMETER_TAG:
1617         dissect_layer3_message(parameter_tvb, v5ua_tree, parameter_item, pinfo);
1618         break;
1619   case RELEASE_REASON_PARAMETER_TAG:
1620         dissect_release_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
1621         break;
1622   case TEI_STATUS_PARAMETER_TAG:
1623     dissect_tei_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1624     break;
1625   case LINK_STATUS_PARAMETER_TAG:
1626     dissect_link_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1627     break;
1628   case SA_BIT_STATUS_PARAMETER_TAG:
1629         dissect_sa_bit_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1630         break;
1631   case ERROR_INDICATION_PARAMETER_TAG:
1632         dissect_error_indication_parameter( parameter_tvb, parameter_tree, parameter_item);
1633         break;
1634   default:
1635     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1636     break;
1637   };
1638
1639   if (padding_length > 0){
1640     proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, FALSE);
1641   }
1642 }
1643
1644 /* dissect the V5UA-Parameters into subsets which are separated by Tag-Length-Header and call up the dissector for the subsets */
1645 static void
1646 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree _U_, proto_tree *v5ua_tree)
1647 {
1648   gint tag, offset, length, total_length, remaining_length;
1649   tvbuff_t *parameter_tvb;
1650
1651   
1652   offset = 0;
1653   while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
1654         tag = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_TAG_OFFSET);
1655         length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
1656         if(iua_version==DRAFT){
1657                 if(tag==0x1) length += 8;               /* V5UA Header */
1658                 else if(tag<=0x4) length += PARAMETER_HEADER_LENGTH;    /* ASP MSGs */
1659
1660                 /* add the parameters which are not separated by tag-length-header to the V5UA header */
1661                 if((msg_class==0 || msg_class==1 || msg_class==9)&&msg_type<=10)
1662                         length = msg_length;
1663         }        
1664         total_length = ADD_PADDING(length);
1665         if (remaining_length >= length)
1666           total_length = MIN(total_length, remaining_length);
1667         /* create a tvb for the parameter including the padding bytes */
1668         parameter_tvb  = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
1669         dissect_parameter(parameter_tvb, pinfo, v5ua_tree);
1670         /* get rid of the handled parameter */
1671         offset += total_length;
1672         }       
1673 }
1674
1675
1676
1677         /* define the common header fields of V5UA MSG */
1678 #define COMMON_HEADER_VERSION_LENGTH        1
1679 #define COMMON_HEADER_RESERVED_LENGTH       1
1680 #define COMMON_HEADER_MSG_CLASS_LENGTH  1
1681 #define COMMON_HEADER_MSG_TYPE_LENGTH   1
1682 #define COMMON_HEADER_MSG_LENGTH_LENGTH 4
1683 #define COMMON_HEADER_LENGTH                (COMMON_HEADER_VERSION_LENGTH + COMMON_HEADER_RESERVED_LENGTH +\
1684                                                                                          COMMON_HEADER_MSG_CLASS_LENGTH + COMMON_HEADER_MSG_TYPE_LENGTH +\
1685                                                                                          COMMON_HEADER_MSG_LENGTH_LENGTH)
1686
1687         /* define the offsets of common header */
1688 #define COMMON_HEADER_OFFSET            0
1689 #define COMMON_HEADER_VERSION_OFFSET    COMMON_HEADER_OFFSET
1690 #define COMMON_HEADER_RESERVED_OFFSET   (COMMON_HEADER_VERSION_OFFSET       + COMMON_HEADER_VERSION_LENGTH)
1691 #define COMMON_HEADER_MSG_CLASS_OFFSET  (COMMON_HEADER_RESERVED_OFFSET      + COMMON_HEADER_RESERVED_LENGTH)
1692 #define COMMON_HEADER_MSG_TYPE_OFFSET   (COMMON_HEADER_MSG_CLASS_OFFSET     + COMMON_HEADER_MSG_CLASS_LENGTH)
1693 #define COMMON_HEADER_MSG_LENGTH_OFFSET (COMMON_HEADER_MSG_TYPE_OFFSET      + COMMON_HEADER_MSG_TYPE_LENGTH)
1694 #define COMMON_HEADER_PARAMETERS_OFFSET (COMMON_HEADER_OFFSET               + COMMON_HEADER_LENGTH)
1695
1696         /* version of V5UA protocol */
1697 #define V5UA_PROTOCOL_VERSION_RELEASE_1     1   
1698
1699 static const value_string v5ua_protocol_version_values[] = {
1700   { V5UA_PROTOCOL_VERSION_RELEASE_1,  "Release 1" },
1701   { 0,                                NULL } };
1702
1703         /* define V5UA MSGs */
1704 #define MSG_CLASS_MGMT_MSG       0
1705 #define MSG_CLASS_MGMT_MSG_DRAFT 1
1706 #define MSG_CLASS_ASPSM_MSG      3
1707 #define MSG_CLASS_ASPTM_MSG      4
1708 #define MSG_CLASS_V5PTM_MSG      9
1709
1710 static const value_string msg_class_values[] = {
1711         { MSG_CLASS_MGMT_MSG,  "Management Messages" },
1712         { MSG_CLASS_MGMT_MSG_DRAFT,"Management Messages"},
1713         { MSG_CLASS_ASPSM_MSG, "ASP state maintenance message" },
1714         { MSG_CLASS_ASPTM_MSG, "ASP traffic maintenance message" },
1715         { MSG_CLASS_V5PTM_MSG, "V5 Boundary Primitives Transport Message" },
1716         { 0,                           NULL } }; 
1717
1718         /* message types for MGMT messages */
1719 #define MGMT_MSG_TYPE_ERR                  0
1720 #define MGMT_MSG_TYPE_NTFY                 1
1721 #define MGMT_MSG_TYPE_TEI_STATUS_REQ       2
1722 #define MGMT_MSG_TYPE_TEI_STATUS_CON       3
1723 #define MGMT_MSG_TYPE_TEI_STATUS_IND       4
1724         /* MGMT messages for Nortel draft version*/
1725 #define MGMT_MSG_DRAFT_TYPE_TEI_STATUS_REQ       1
1726 #define MGMT_MSG_DRAFT_TYPE_TEI_STATUS_CON       2
1727 #define MGMT_MSG_DRAFT_TYPE_TEI_STATUS_IND       3
1728
1729
1730         /* message types for ASPSM messages */
1731 #define ASPSM_MSG_TYPE_UP                   1
1732 #define ASPSM_MSG_TYPE_DOWN                 2
1733 #define ASPSM_MSG_TYPE_BEAT                 3
1734 #define ASPSM_MSG_TYPE_UP_ACK               4
1735 #define ASPSM_MSG_TYPE_DOWN_ACK             5
1736 #define ASPSM_MSG_TYPE_BEAT_ACK             6
1737
1738         /* message types for ASPTM messages */
1739 #define ASPTM_MSG_TYPE_ACTIVE               1
1740 #define ASPTM_MSG_TYPE_INACTIVE             2
1741 #define ASPTM_MSG_TYPE_ACTIVE_ACK           3
1742 #define ASPTM_MSG_TYPE_INACTIVE_ACK         4
1743
1744         /* message types for V5PTM messages */
1745 #define V5PTM_MSG_TYPE_DATA_REQUEST                 1
1746 #define V5PTM_MSG_TYPE_DATA_INDICATION              2
1747 #define V5PTM_MSG_TYPE_UNIT_DATA_REQUEST            3
1748 #define V5PTM_MSG_TYPE_UNIT_DATA_INDICATION         4
1749 #define V5PTM_MSG_TYPE_ESTABLISH_REQUEST            5
1750 #define V5PTM_MSG_TYPE_ESTABLISH_CONFIRM            6
1751 #define V5PTM_MSG_TYPE_ESTABLISH_INDICATION         7
1752 #define V5PTM_MSG_TYPE_RELEASE_REQUEST              8
1753 #define V5PTM_MSG_TYPE_RELEASE_CONFIRM              9
1754 #define V5PTM_MSG_TYPE_RELEASE_INDICATION          10
1755 #define V5PTM_MSG_TYPE_LINK_STATUS_START_REPORTING 11
1756 #define V5PTM_MSG_TYPE_LINK_STATUS_STOP_REPORTING  12
1757 #define V5PTM_MSG_TYPE_LINK_STATUS_INDICATION      13
1758 #define V5PTM_MSG_TYPE_SA_BIT_SET_REQUEST          14
1759 #define V5PTM_MSG_TYPE_SA_BIT_SET_CONFIRM          15
1760 #define V5PTM_MSG_TYPE_SA_BIT_STATUS_REQUEST       16
1761 #define V5PTM_MSG_TYPE_SA_BIT_STATUS_INDICATION    17
1762 #define V5PTM_MSG_TYPE_ERROR_INDICATION            18
1763
1764 static const value_string msg_class_type_values[] = {
1765   { MSG_CLASS_MGMT_MSG  * 256 + MGMT_MSG_TYPE_ERR,                         "Error" },
1766   { MSG_CLASS_MGMT_MSG  * 256 + MGMT_MSG_TYPE_NTFY,                        "Notify" },
1767   { MSG_CLASS_MGMT_MSG  * 256 + MGMT_MSG_TYPE_TEI_STATUS_REQ,              "TEI status request" },
1768   { MSG_CLASS_MGMT_MSG  * 256 + MGMT_MSG_TYPE_TEI_STATUS_CON,              "TEI status confirmation" },
1769   { MSG_CLASS_MGMT_MSG  * 256 + MGMT_MSG_TYPE_TEI_STATUS_IND,              "TEI status indication" },
1770   { MSG_CLASS_MGMT_MSG_DRAFT * 256 + MGMT_MSG_DRAFT_TYPE_TEI_STATUS_REQ,   "TEI status request" },
1771   { MSG_CLASS_MGMT_MSG_DRAFT * 256 + MGMT_MSG_DRAFT_TYPE_TEI_STATUS_CON,   "TEI status confimation" },
1772   { MSG_CLASS_MGMT_MSG_DRAFT * 256 + MGMT_MSG_DRAFT_TYPE_TEI_STATUS_IND,   "TEI status indication" },
1773   { MSG_CLASS_ASPSM_MSG * 256 + ASPSM_MSG_TYPE_UP,                         "ASP up" },
1774   { MSG_CLASS_ASPSM_MSG * 256 + ASPSM_MSG_TYPE_DOWN,                       "ASP down" },
1775   { MSG_CLASS_ASPSM_MSG * 256 + ASPSM_MSG_TYPE_BEAT,                       "Heartbeat" },
1776   { MSG_CLASS_ASPSM_MSG * 256 + ASPSM_MSG_TYPE_UP_ACK,                     "ASP up ack" },
1777   { MSG_CLASS_ASPSM_MSG * 256 + ASPSM_MSG_TYPE_DOWN_ACK,                   "ASP down ack" },
1778   { MSG_CLASS_ASPSM_MSG * 256 + ASPSM_MSG_TYPE_BEAT_ACK,                   "Heartbeat ack" },
1779   { MSG_CLASS_ASPTM_MSG * 256 + ASPTM_MSG_TYPE_ACTIVE ,                    "ASP active" },
1780   { MSG_CLASS_ASPTM_MSG * 256 + ASPTM_MSG_TYPE_INACTIVE ,                  "ASP inactive" },
1781   { MSG_CLASS_ASPTM_MSG * 256 + ASPTM_MSG_TYPE_ACTIVE_ACK ,                "ASP active ack" },
1782   { MSG_CLASS_ASPTM_MSG * 256 + ASPTM_MSG_TYPE_INACTIVE_ACK ,              "ASP inactive ack" },
1783   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_DATA_REQUEST,               "Data request" },
1784   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_DATA_INDICATION,            "Data indication" },
1785   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_UNIT_DATA_REQUEST,          "Unit data request" },
1786   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_UNIT_DATA_INDICATION,       "Unit data indication" },
1787   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_ESTABLISH_REQUEST,          "Establish request" },
1788   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_ESTABLISH_CONFIRM,          "Establish confirmation" },
1789   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_ESTABLISH_INDICATION,       "Establish indication" },
1790   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_RELEASE_REQUEST,            "Release request" },
1791   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_RELEASE_CONFIRM,            "Release confirmation" },
1792   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_RELEASE_INDICATION,         "Release indication" },
1793   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_LINK_STATUS_START_REPORTING,"Link status start reporting" },
1794   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_LINK_STATUS_STOP_REPORTING, "Link status stop reporting" },
1795   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_LINK_STATUS_INDICATION,     "Link status indication" },
1796   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_SA_BIT_SET_REQUEST,         "Sa-Bit set request" },
1797   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_SA_BIT_SET_CONFIRM,         "Sa-Bit set confirm" },
1798   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_SA_BIT_STATUS_REQUEST,      "Sa-Bit status request" },
1799   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_SA_BIT_STATUS_INDICATION,   "Sa-Bit status indication" },
1800   { MSG_CLASS_V5PTM_MSG * 256 + V5PTM_MSG_TYPE_ERROR_INDICATION,           "Error indication" },
1801   { 0,                                                                                  NULL } };
1802   
1803
1804 static void
1805 dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *v5ua_tree)
1806 {
1807   proto_item *common_header_item;
1808   proto_tree *common_header_tree;
1809
1810   guint8 message_class, message_type;
1811
1812   message_class  = tvb_get_guint8(common_header_tvb, COMMON_HEADER_MSG_CLASS_OFFSET);
1813   message_type   = tvb_get_guint8(common_header_tvb, COMMON_HEADER_MSG_TYPE_OFFSET);
1814
1815   /* Add message type into info column */
1816   if (check_col(pinfo->cinfo, COL_INFO)) {
1817     col_add_str(pinfo->cinfo, COL_INFO, val_to_str(message_class * 256 + message_type, msg_class_type_values, "UNKNOWN"));
1818     col_append_str(pinfo->cinfo, COL_INFO, " ");
1819   }
1820
1821   if (v5ua_tree) {
1822
1823           /* create proto_tree stuff */
1824     common_header_item   = proto_tree_add_text(v5ua_tree, common_header_tvb, COMMON_HEADER_OFFSET, tvb_length(common_header_tvb),"Common Msg-Header");
1825     common_header_tree   = proto_item_add_subtree(common_header_item, ett_v5ua_common_header);
1826
1827     /* add the components of the common header to the protocol tree */
1828     proto_tree_add_item(common_header_tree, hf_version, common_header_tvb, COMMON_HEADER_VERSION_OFFSET, COMMON_HEADER_VERSION_LENGTH, FALSE);
1829     proto_tree_add_item(common_header_tree, hf_reserved, common_header_tvb, COMMON_HEADER_RESERVED_OFFSET, COMMON_HEADER_RESERVED_LENGTH, FALSE);
1830     proto_tree_add_item(common_header_tree, hf_msg_class, common_header_tvb, COMMON_HEADER_MSG_CLASS_OFFSET, COMMON_HEADER_MSG_CLASS_LENGTH, FALSE);
1831     proto_tree_add_uint_format(common_header_tree, hf_msg_type,
1832                               common_header_tvb, COMMON_HEADER_MSG_TYPE_OFFSET, COMMON_HEADER_MSG_TYPE_LENGTH,
1833                               message_type, "Message type: %s ( %u )",
1834                               val_to_str(message_class * 256 + message_type, msg_class_type_values, "reserved"), message_type);
1835     proto_tree_add_uint(common_header_tree, hf_msg_type_id, common_header_tvb, COMMON_HEADER_MSG_TYPE_OFFSET, COMMON_HEADER_MSG_TYPE_LENGTH,
1836                               message_class * 256 + message_type);
1837     proto_tree_add_item(common_header_tree, hf_msg_length, common_header_tvb, COMMON_HEADER_MSG_LENGTH_OFFSET, COMMON_HEADER_MSG_LENGTH_LENGTH, FALSE);
1838     
1839         /* Add message type to the Common Msg-Header line */
1840         proto_item_append_text(common_header_item, " (%s)",val_to_str(message_class * 256 + message_type, msg_class_type_values, "Unknown Msg-Type"));
1841   }
1842   
1843   /* the following info are required to dissect IUA-Draft messages.
1844                 In the DRAFT-Specification V5UA-Parameters are not separated by Tag-Length-Header (as defined in RFC-Spec) */
1845   if (iua_version == DRAFT){
1846           msg_class = message_class;
1847           msg_type  = message_type;
1848           msg_length = tvb_get_ntohl (common_header_tvb, COMMON_HEADER_MSG_LENGTH_OFFSET);
1849   }
1850 }
1851
1852 /* dissect the V5UA-packet in two subsets: Common Msg-Header (used by all msgs) and V5UA-parameter */
1853 static void
1854 dissect_v5ua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *v5ua_tree)
1855 {
1856   tvbuff_t *common_header_tvb, *parameters_tvb;
1857
1858   common_header_tvb = tvb_new_subset(tvb, COMMON_HEADER_OFFSET, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
1859   dissect_common_header(common_header_tvb, pinfo, v5ua_tree);
1860
1861   parameters_tvb    = tvb_new_subset(tvb, COMMON_HEADER_LENGTH, -1, -1);
1862   dissect_parameters(parameters_tvb, pinfo, tree, v5ua_tree);
1863 }
1864         
1865         
1866 static void
1867 dissect_v5ua(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1868 {
1869
1870    gint    offset, remaining_length, length, tag, one_bit;
1871
1872
1873 /* Set up structures needed to add the protocol subtree and manage it */
1874         proto_tree *v5ua_tree;
1875         proto_item *ti;
1876
1877 /* Make entries in Protocol column and Info column on summary display */
1878         if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
1879                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "V5UA");
1880     
1881 /* This field shows up as the "Info" column in the display; you should make
1882    it, if possible, summarize what's in the packet, so that a user looking
1883    at the list of packets can tell what type of packet it is. See section 1.5
1884    for more information. */
1885
1886
1887         if (check_col(pinfo->cinfo, COL_INFO)) 
1888                 col_clear(pinfo->cinfo, COL_INFO);
1889
1890    
1891 /* In the interest of speed, if "tree" is NULL, don't do any work not
1892    necessary to generate protocol tree items. */
1893         if (tree) {
1894
1895 /* NOTE: The offset and length values in the call to
1896    "proto_tree_add_item()" define what data bytes to highlight in the hex
1897    display window when the line in the protocol tree display
1898    corresponding to that item is selected.
1899
1900    Supplying a length of -1 is the way to highlight all data from the
1901    offset to the end of the packet. */
1902
1903 /* create display subtree for the protocol */
1904                 ti = proto_tree_add_item(tree, proto_v5ua, tvb, 0, -1, FALSE);
1905                 v5ua_tree = proto_item_add_subtree(ti, ett_v5ua);
1906
1907         }
1908         else {
1909         v5ua_tree=NULL;
1910         };
1911
1912
1913         /* detect version of IUA */
1914    iua_version = RFC;
1915    offset = COMMON_HEADER_LENGTH;
1916
1917    remaining_length = tvb_length_remaining(tvb, offset);
1918
1919    while(remaining_length) {
1920            tag = tvb_get_ntohs(tvb, offset);
1921            /*0x01,0x03: Inerface Id (draft&RFC)*/
1922                 if(tag==0x1){
1923                         length = tvb_get_ntohs(tvb, offset+2);
1924                         tag = tvb_get_ntohs(tvb, offset+length);
1925                         /* tag 0x5 indicates the DLCI in the V5UA-Header accoriding to RFC spec */
1926                         if(tag==0x5){
1927                                 remaining_length = FALSE;
1928                         }
1929                         else{
1930                                 one_bit = tvb_get_guint8(tvb, offset+4+length+1);
1931                                 /* no indication from DLCI by tag (in the V5UA-Header according DRAFT).
1932                                         Thus the ONE-Bit within DLCI have to compare */
1933                                 if((one_bit & 0x01) == 0x01){
1934                                         iua_version = DRAFT;
1935                                         remaining_length = FALSE;
1936                                 }
1937                                 /* an indication to incorrect bit in DLCI.
1938                                         Must be include to decode an incorrect implemented message on Nortels PVG*/
1939                                 else{
1940                                         proto_item_append_text(v5ua_tree, "   !! DLCI INCORRECT !!");
1941
1942                                         iua_version = DRAFT;
1943                                         remaining_length = FALSE;
1944                                 }
1945                         }
1946                 }
1947                 /*0x02: AL Id (draft) following after common msg header without V5UA header*/
1948                 else if(tag==0x02){
1949                         iua_version = DRAFT;
1950                         remaining_length = FALSE;
1951                 }
1952                 /*0x03: Text formatted IId SHALL not be supported by draft*/
1953                 else if(tag==0x03){
1954                         iua_version = RFC;
1955                         remaining_length = FALSE;
1956                 }
1957                 /*ASP, Notify and Error messages (RFC) only contain common msg header followed by parameter*/
1958                 else if(tag==0x04 || tag == 0x0a || tag == 0x0b || tag == 0x0c || tag == 0x0d){
1959                         remaining_length = FALSE;
1960                 }
1961                 else{
1962                         offset+=2;
1963                         remaining_length = tvb_length_remaining(tvb, offset);
1964                 }
1965                 /* add a notice for the draft version */
1966                 if(iua_version == DRAFT){
1967                         if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
1968                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "V5UA (draft)");
1969                 }
1970    }
1971  
1972
1973    /* dissect the message */
1974   dissect_v5ua_message(tvb, pinfo, tree, v5ua_tree);
1975 }
1976
1977
1978
1979 /* Register the protocol with Ethereal */
1980
1981 /* this format is require because a script is used to build the C function
1982    that calls all the protocol registration. */
1983
1984
1985 void
1986 proto_register_v5ua(void)
1987 {                 
1988
1989 /* Setup list of header fields  */
1990         static hf_register_info hf[] = {
1991                 { &hf_version,
1992                         { "Version",                "v5ua.version",
1993                            FT_UINT8,    BASE_DEC, VALS(v5ua_protocol_version_values),0x0,
1994                            "", HFILL } },
1995                 { &hf_reserved,
1996                         { "Reserved",               "v5ua.reserved",
1997                            FT_UINT8,    BASE_HEX, NULL,                             0x0,
1998                            "", HFILL } },
1999                 { &hf_msg_class,
2000                         { "Message class",          "v5ua.msg_class",
2001                            FT_UINT8,    BASE_DEC, VALS(msg_class_values),           0x0,
2002                            "", HFILL } },
2003                 { &hf_msg_type,
2004                         { "Message Type",           "v5ua.msg_type",
2005                            FT_UINT8,    BASE_DEC, NULL,                             0x0,
2006                            "", HFILL } },
2007                 { &hf_msg_type_id,
2008                         { "Message Type ID",        "v5ua.msg_type_id",
2009                            FT_UINT8,    BASE_DEC, VALS(msg_class_type_values),      0x0,
2010                            "", HFILL } },
2011                 { &hf_msg_length,
2012                         { "Message length",         "v5ua.msg_length",
2013                FT_UINT32,   BASE_DEC, NULL,                             0x0,
2014                            "", HFILL } },
2015                 { &hf_link_id,
2016                         { "Link Identifier",        "v5ua.link_id",
2017                            FT_UINT32,   BASE_DEC, NULL,                                                         ~0x1f,
2018                            "", HFILL } },
2019                 { &hf_chnl_id,
2020                         { "Channel Identifier",     "v5ua.channel_id",
2021                            FT_UINT8,    BASE_DEC, NULL,                                                         0x1f,
2022                            "", HFILL } },
2023                 { &hf_adaptation_layer_id,
2024                         { "Adaptation Layer ID",      "v5ua.adaptation_layer_id",
2025                            FT_STRING,   BASE_NONE,NULL,                                                         0x0,
2026                            "", HFILL } },
2027                 { &hf_text_if_id,
2028                         { "Text interface identifier","v5ua.text_interface_id",
2029                            FT_STRING,   BASE_NONE,NULL,                                                         0x0,
2030                            "", HFILL } },
2031                 { &hf_scn_protocol_id,
2032                         { "SCN Protocol Identifier","v5ua.scn_protocol_id",
2033                            FT_STRING,   BASE_NONE,NULL,                                                         0x0,
2034                            "", HFILL } },
2035                 { &hf_info_string,
2036                         { "Info String",            "v5ua.info_string",
2037                            FT_STRING,   BASE_NONE,NULL,                             0x0,
2038                            "", HFILL } },
2039                 { &hf_dlci_zero_bit,
2040                         { "Zero bit",               "v5ua.dlci_zero_bit",
2041                            FT_BOOLEAN,  8,        NULL,                             0x01,
2042                            "", HFILL } },
2043                 { &hf_dlci_spare_bit,
2044                         { "Spare bit",              "v5ua.dlci_spare_bit",
2045                FT_BOOLEAN,      8,        NULL,                             0x02,
2046                            "", HFILL } },
2047                 { &hf_dlci_sapi,
2048                         { "SAPI",                   "v5ua.dlci_sapi",
2049                            FT_UINT8,    BASE_HEX, NULL,                             0xfc,
2050                            "", HFILL } },
2051                 { &hf_dlci_one_bit,
2052                         { "One bit",                "v5ua.dlci_one_bit",
2053                            FT_BOOLEAN,  8,        NULL,                             0x01,
2054                            "", HFILL } },
2055                 { &hf_dlci_tei,
2056                         { "TEI",                    "v5ua.dlci_tei",
2057                            FT_UINT8,    BASE_HEX, NULL,                             0xfe,
2058                            "", HFILL } },
2059                 { &hf_efa,
2060                         { "Envelope Function Address","v5ua.efa",
2061                            FT_UINT16,   BASE_DEC, VALS(efa_values),                 0x0,
2062                            "", HFILL } },
2063                 { &hf_spare_efa,
2064                         { "Envelope Function Address (spare)","v5ua.efa",
2065                            FT_UINT16,   BASE_DEC, NULL,                             ~7,
2066                            "", HFILL } },
2067                 { &hf_asp_reason,
2068                         { "Reason",                 "v5ua.asp_reason",
2069                            FT_UINT32,   BASE_HEX, VALS(asp_reason_values),          0x0,
2070                            "", HFILL } },
2071                 { &hf_release_reason,
2072                         { "Release Reason",         "v5ua.release_reason",
2073                            FT_UINT32,   BASE_HEX, VALS(release_reason_values),      0x0,
2074                            "", HFILL } },
2075                 { &hf_tei_status,
2076                         { "TEI status",             "v5ua.tei_status",
2077                            FT_UINT32,   BASE_HEX, VALS(tei_status_values),          0x0,
2078                            "", HFILL } },
2079                 { &hf_tei_draft_status,
2080                         { "TEI status",             "v5ua.tei_draft_status",
2081                            FT_UINT32,   BASE_HEX, VALS(tei_draft_status_values),    0x0,
2082                            "", HFILL } },
2083         { &hf_link_status,
2084                         { "Link Status",            "v5ua.link_status",
2085                            FT_UINT32,   BASE_HEX, NULL,                             0x0,
2086                            "", HFILL } },
2087                 { &hf_sa_bit_id,
2088                         { "BIT ID",                 "v5ua.sa_bit_id",
2089                            FT_UINT16,   BASE_HEX, VALS(sa_bit_values),              0x0,
2090                            "", HFILL } },
2091                 { &hf_sa_bit_value,
2092                         { "Bit Value",              "v5ua.sa_bit_value",
2093                            FT_UINT16,   BASE_HEX, VALS(sa_bit_values),              0x0,
2094                            "", HFILL } },
2095                 { &hf_parameter_tag,
2096                         { "Parameter Tag",          "v5ua.parameter_tag",
2097                            FT_UINT16,   BASE_HEX, VALS(parameter_tag_values),       0x0,
2098                            "", HFILL } },
2099                 { &hf_parameter_tag_draft,
2100                         { "Parameter Tag",          "v5ua.parameter_tag",
2101                            FT_UINT16,   BASE_HEX, VALS(parameter_tag_draft_values), 0x0,
2102                            "", HFILL } },
2103                 { &hf_parameter_length, 
2104                         { "Parameter length",       "v5ua.parameter_length",
2105                            FT_UINT16,   BASE_DEC, NULL,                             0x0,
2106                            "", HFILL } },
2107                 { &hf_parameter_value,
2108                         { "Parameter value",        "v5ua.parameter_value",
2109                            FT_BYTES,    BASE_NONE,NULL,                             0x0,
2110                            "", HFILL } },
2111                 { &hf_parameter_padding,
2112                         { "Parameter padding",      "v5ua.parameter_padding",
2113                            FT_BYTES,    BASE_NONE,NULL,                             0x0,
2114                            "", HFILL } },
2115                 { &hf_diagnostic_info,
2116                         { "Diagnostic Information", "v5ua.diagnostic_info",
2117                            FT_BYTES,    BASE_NONE,NULL,                                                 0x0,
2118                            "", HFILL } },
2119                 { &hf_if_range_start,
2120                         { "Interface range Start",  "v5ua.interface_range_start",
2121                            FT_UINT32,   BASE_HEX, NULL,                             0x0,
2122                            "", HFILL } },
2123                 { &hf_if_range_end,
2124                         { "Interface range End",    "v5ua.interface_range_end",
2125                            FT_UINT32,   BASE_HEX, NULL,                             0x0,
2126                            "", HFILL } },
2127                 { &hf_heartbeat_data,
2128                         { "Heartbeat data",         "v5ua.heartbeat_data",
2129                FT_BYTES,    BASE_NONE,NULL,                             0x0,
2130                            "", HFILL } },
2131                 { &hf_traffic_mode_type,
2132                         { "Traffic mode type",      "v5ua.traffic_mode_type",
2133                            FT_UINT32,   BASE_HEX, VALS(traffic_mode_type_values),   0x0,
2134                            "", HFILL } },
2135                 { &hf_error_code,
2136             { "Error code",             "v5ua.error_code",
2137                            FT_UINT32,   BASE_HEX, VALS(error_code_values),          0x0,
2138                            "", HFILL } },
2139                 { &hf_draft_error_code,
2140                         { "Error code (draft)",     "v5ua.draft_error_code",
2141                            FT_UINT32,   BASE_HEX, VALS(draft_error_code_values),    0x0,
2142                            "", HFILL } },
2143                 { &hf_status_type,
2144                         { "Status type",            "v5ua.status_type",
2145                            FT_UINT16,   BASE_DEC, VALS(status_type_values),         0x0,
2146                            "", HFILL } },
2147                 { &hf_status_id,
2148                         { "Status identification",  "v5ua.status_id",
2149                            FT_UINT16,   BASE_DEC, NULL,                             0x0,
2150                            "", HFILL } },
2151                 { &hf_error_reason,
2152                         { "Error Reason",           "v5ua.error_reason",
2153                            FT_UINT32,   BASE_HEX, VALS(error_reason_values),        0x0,
2154                            "", HFILL } },
2155
2156                            
2157                 /* header fields for layer 3 content*/
2158                 { &hf_l3_protocol_discriminator,
2159                         { "Protocol Discriminator", "v5ua.l3_protocol_disc",
2160                FT_UINT8,    BASE_HEX, NULL,                             0x0,
2161                            "", HFILL } },
2162                 { &hf_l3_adress,
2163                         { "Layer3 adress",         "v5ua.l3_adress",
2164                            FT_UINT8,    BASE_HEX, NULL,                             0xfe,
2165                            "", HFILL } },
2166                 { &hf_l3_low_adress,
2167                         { "Layer3 low adress",     "v5ua.l3_low_adress",
2168                            FT_UINT8,    BASE_HEX, NULL,                             0x0,
2169                            "", HFILL } },
2170                 {&hf_l3_msg_type,
2171                         { "Layer3 message type",   "v5ua.l3_msg_type",
2172                            FT_UINT8,    BASE_HEX, VALS(l3_msg_type_values),         0x0,
2173                            "", HFILL } },
2174                 {&hf_l3_info_element,
2175                         { "Layer3 information element",   "v5ua.l3_info_element",
2176                            FT_UINT8,    BASE_HEX, VALS(l3_info_element_values),     0x0,
2177                            "", HFILL } },
2178                 {&hf_l3_line_info,
2179                         { "Line_Information",      "v5ua.l3_line_info",
2180                            FT_UINT8,    BASE_HEX, VALS(l3_line_info_values),        0x0f,
2181                            "", HFILL } },
2182                 {&hf_l3_cad_ringing,
2183                         {"Cadenced ringing type",  "v5ua.l3_cad_ringing",
2184                            FT_UINT8,    BASE_HEX, NULL,                             0x7f,
2185                            "", HFILL } },
2186                 {&hf_l3_pulse_type,
2187                         { "Pulse Type",            "v5ua.l3_pulse_type",
2188                            FT_UINT8,    BASE_HEX, VALS(l3_pulse_type_values),       0x0,
2189                            "", HFILL } },
2190                 {&hf_l3_suppression_indicator,
2191                         { "Suppression indicator",  "v5ua.l3_suppression_indicator",
2192                            FT_UINT8,    BASE_HEX, VALS(l3_suppression_indication_values),0x60,
2193                            "", HFILL } },
2194                 {&hf_l3_pulse_duration,
2195                         { "Pulse duration type",   "v5ua.l3_pulse_duration",
2196                            FT_UINT8,    BASE_HEX, NULL,                             0x1f,
2197                            "", HFILL } },
2198                 {&hf_l3_ack_request_indicator,
2199                         { "Ack request indicator",    "v5ua.l3_ack_request_indicator",
2200                            FT_UINT8,    BASE_HEX, VALS(l3_ack_request_indication_values),0x60,
2201                            "", HFILL } },
2202                 {&hf_l3_number_of_pulses,
2203                         { "Number of pulses",      "v5ua.l3_number_of_pulses",
2204                            FT_UINT8,    BASE_DEC, NULL,                             0x1f,
2205                            "", HFILL } },
2206                 {&hf_l3_steady_signal,
2207                         { "Steady Signal",         "v5ua.l3_steady_signal",
2208                            FT_UINT8,    BASE_HEX, VALS(l3_steady_signal_values),    0x0,
2209                            "", HFILL } },
2210                 {&hf_l3_auto_signalling_sequence,
2211                         { "Autonomous signalling sequence","v5ua.l3_auto_signalling_sequence",
2212                            FT_UINT8,    BASE_HEX, NULL,                             0x0f,
2213                            "", HFILL } },
2214                 {&hf_l3_sequence_number,
2215                         { "Sequence number",    "v5ua.l3_sequence_number",
2216                            FT_UINT8,    BASE_HEX, NULL,                             0x7f,
2217                            "", HFILL } },
2218                 {&hf_l3_pulse_notify,
2219                         { "Pulse notification",    "v5ua.l3_pulse_notification",
2220                            FT_UINT8,    BASE_HEX, NULL,                             0x0,
2221                            "", HFILL } },
2222                 {&hf_l3_sequence_response,
2223                         { "Sequence response",    "v5ua.l3_sequence_response",
2224                            FT_UINT8,    BASE_HEX, NULL,                             0x0f,
2225                            "", HFILL } },
2226                 {&hf_l3_digit_ack,
2227                         { "Digit ack request indication","v5ua.l3_digit_ack",
2228                            FT_UINT8,    BASE_HEX, VALS(l3_digit_ack_values),        0x40,
2229                            "", HFILL } },
2230                 {&hf_l3_digit_info,
2231                         { "Digit information",    "v5ua.l3_digit_info",
2232                            FT_UINT8,    BASE_HEX, NULL,                             0x0f,
2233                            "", HFILL } },
2234                 {&hf_l3_res_unavailable,
2235                         { "Resource unavailable", "v5ua.l3_res_unavailable",
2236                            FT_STRING,   BASE_NONE,NULL,                             0x0,
2237                            "", HFILL } },
2238                 {&hf_l3_state,
2239                         { "PSTN FSM state",       "v5ua.l3_state",
2240                            FT_UINT8,    BASE_HEX, VALS(l3_state_values),            0x0f,
2241                            "", HFILL } },
2242                 {&hf_l3_cause_type,
2243                         { "Cause type",           "v5ua.l3_cause_type",
2244                            FT_UINT8,    BASE_HEX, VALS(l3_cause_type_values),       0x7f,
2245                            "", HFILL } },
2246                 {&hf_l3_link_control_function,
2247                         { "Link control function","v5ua.l3_link_control_function",
2248                            FT_UINT8,    BASE_HEX, VALS(l3_link_control_function_values),0x7f,
2249                            "", HFILL } },
2250                 {&hf_l3_pstn_user_port_id,
2251                         { "PSTN User Port identification Value","v5ua.l3_pstn_user_port_id",
2252                            FT_UINT8,    BASE_HEX, NULL,                             0xfe,
2253                            "", HFILL } },
2254                 {&hf_l3_pstn_user_port_id_lower,
2255                         { "PSTN User Port Identification Value (lower)","v5ua.l3_pstn_user_port_id_lower",
2256                            FT_UINT8,    BASE_HEX, NULL,                             0x0,
2257                            "", HFILL } },
2258                 {&hf_l3_isdn_user_port_id,
2259                         { "ISDN User Port Identification Value","v5ua.l3_isdn_user_port_id",
2260                            FT_UINT8,    BASE_HEX, NULL,                             0xfc,
2261                            "", HFILL } },
2262                 {&hf_l3_isdn_user_port_id_lower,
2263                         { "ISDN User Port Identification Value (lower)","v5ua.l3_user_port_id_lower",
2264                            FT_UINT8,    BASE_HEX, NULL,                             0x0fe,
2265                            "", HFILL } },
2266                 {&hf_l3_isdn_user_port_ts_num,
2267                         { "ISDN user port time slot number","v5ua.l3_isdn_user_port_ts_num",
2268                            FT_UINT8,    BASE_HEX, NULL,                             0x1f,
2269                            "", HFILL } },
2270                 {&hf_l3_override,
2271                         { "Override",    "v5ua.l3_override", 
2272                            FT_BOOLEAN,  8,        NULL,                             0x20,
2273                            "", HFILL } },
2274                 {&hf_l3_v5_link_id,
2275                         { "V5 2048 kbit/s Link Identifier",    "v5ua.l3_link_id",
2276                            FT_UINT8,    BASE_HEX, NULL,                             0x0,
2277                            "", HFILL } },
2278                 {&hf_l3_v5_time_slot,
2279                         { "V5 Time Slot Number",    "v5ua.l3_v5_time_slot",
2280                            FT_UINT8,    BASE_DEC, NULL,                             0x1f,
2281                            "", HFILL } },
2282                 {&hf_l3_reject_cause_type,
2283                         { "Reject cause type",    "v5ua.l3_reject_cause_type",
2284                            FT_UINT8,    BASE_HEX, VALS(l3_reject_cause_type_values),0x7f,
2285                            "", HFILL } },
2286                 {&hf_l3_bcc_protocol_error_cause,
2287                         { "BCC Protocol error cause type",    "v5ua.l3_bcc_protocol_cause",
2288                            FT_UINT8,    BASE_HEX, VALS(l3_bcc_protocol_error_cause_type_values),0x7f,
2289                            "", HFILL } },
2290                 {&hf_l3_connection_incomplete_reason,
2291                         { "Reason",    "v5ua.l3_connection_incomplete_reason",
2292                            FT_UINT8,    BASE_HEX, VALS(l3_connection_incomplete_reason_values), 0x0,
2293                            "", HFILL } },
2294                 {&hf_l3_control_function_element,
2295                         { "Control function element",    "v5ua.l3_control_function_element",
2296                            FT_UINT8,    BASE_HEX, VALS(l3_control_function_element_values),     0x7f,
2297                            "", HFILL } },
2298                 {&hf_l3_control_function_id,
2299                         { "Control function ID",    "v5ua.l3_control_function",
2300                            FT_UINT8,    BASE_HEX, VALS(l3_control_function_id_values),          0x7f,
2301                            "", HFILL } },
2302                 {&hf_l3_variant,
2303                         { "Variant",    "v5ua.l3_variant",
2304                            FT_UINT8,    BASE_DEC, NULL,                                         0x0,
2305                            "", HFILL } },
2306                 {&hf_l3_if_id,
2307                         { "Interface ID",    "v5ua.l3_interface_id",
2308                            FT_UINT32,   BASE_HEX, NULL,                                         0x0,
2309                            "", HFILL } },
2310                 {&hf_l3_performance_grading,
2311                         { "Performance grading",    "v5ua.l3_performance_grading",
2312                            FT_UINT8,    BASE_HEX, VALS(l3_performance_grading_values),          0x0f,
2313                            "", HFILL } },
2314                 {&hf_l3_cp_rejection_cause,
2315                         { "Rejection cause",    "v5ua.l3_cp_rejection_cause",
2316                            FT_UINT8,    BASE_HEX, VALS(l3_cp_rejection_cause_values),           0x0f,
2317                            "", HFILL } },
2318                 {&hf_l3_pstn_sequence_number,
2319                         { "Sequence number",    "v5ua.l3_pstn_sequence_number",
2320                            FT_UINT8,    BASE_HEX, NULL,                                         0x7f,
2321                            "", HFILL } },
2322                 {&hf_l3_duration_type,
2323                         { "Duration Type",    "v5ua.l3_duration_type",
2324                            FT_UINT8,    BASE_HEX, NULL,                                         0x3f,
2325                            "", HFILL } },
2326
2327                 };
2328
2329 /* Setup protocol subtree array */
2330         static gint *ett[] = {
2331                 &ett_v5ua,
2332                 &ett_v5ua_common_header,
2333                 &ett_v5ua_parameter,
2334                 &ett_v5ua_layer3,
2335         };
2336
2337 /* Register the protocol name and description */
2338
2339         proto_v5ua = proto_register_protocol("V5.2-User Adaptation Layer", "V5UA", "v5ua");
2340
2341 /* Required function calls to register the header fields and subtrees used */
2342         proto_register_field_array(proto_v5ua, hf, array_length(hf));
2343         proto_register_subtree_array(ett, array_length(ett));
2344 }
2345
2346
2347 /* In RFC specification the SCTP registered User Port Number Assignment for V5UA is 5675 */
2348 /* #define SCTP_PORT_V5UA      5675 */
2349
2350 #define SCTP_PORT_V5UA      10001
2351
2352 void
2353 proto_reg_handoff_v5ua(void)
2354 {
2355         dissector_handle_t v5ua_handle;
2356
2357         v5ua_handle = create_dissector_handle(dissect_v5ua, proto_v5ua);
2358     q931_handle = find_dissector("q931");
2359
2360         dissector_add("sctp.port", SCTP_PORT_V5UA, v5ua_handle);
2361         dissector_add("sctp.ppi",  V5UA_PAYLOAD_PROTOCOL_ID, v5ua_handle);
2362 }
2363
2364
2365 /* Start the functions we need for the plugin stuff */
2366
2367 #ifndef ENABLE_STATIC
2368
2369 G_MODULE_EXPORT void
2370 plugin_register(void)
2371 {
2372     /* register the new protocol, protocol fields, and subtrees */
2373     if (proto_v5ua == -1) { /* execute protocol initialization only once */
2374         proto_register_v5ua();
2375     }
2376 }
2377
2378 G_MODULE_EXPORT void
2379 plugin_reg_handoff(void){
2380     proto_reg_handoff_v5ua();
2381 }
2382
2383 #endif
2384
2385 /* End the functions we need for plugin stuff */