Spelling fixes for errors found by lintian
[metze/wireshark/wip.git] / epan / dissectors / packet-zbee-zcl-se.c
1 /* packet-zbee-zcl-se.c
2  * Dissector routines for the ZigBee ZCL SE clusters like
3  * Messaging
4  * By Fabio Tarabelloni <fabio.tarabelloni@reloc.it>
5  * Copyright 2013 RELOC s.r.l.
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 /*  Include Files */
27 #include "config.h"
28
29
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
32 #include <epan/expert.h>
33 #include <epan/to_str.h>
34
35 #include "packet-zbee.h"
36 #include "packet-zbee-aps.h"
37 #include "packet-zbee-zcl.h"
38 #include "packet-zbee-security.h"
39
40 /* ########################################################################## */
41 /* #### common to all SE clusters ########################################### */
42 /* ########################################################################## */
43
44 #define ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS            0xFFFE
45 #define ZBEE_ZCL_SE_ATTR_REPORT_PENDING                     0x00
46 #define ZBEE_ZCL_SE_ATTR_REPORT_COMPLETE                    0x01
47
48 static const value_string zbee_zcl_se_reporting_status_names[] = {
49     { ZBEE_ZCL_SE_ATTR_REPORT_PENDING,                   "Pending" },
50     { ZBEE_ZCL_SE_ATTR_REPORT_COMPLETE,                  "Complete" },
51     { 0, NULL }
52 };
53
54 #define ZBEE_ZCL_SE_ATTR_NAMES \
55     { ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS,            "Attribute Reporting Status" }
56
57 /*************************/
58 /* Global Variables      */
59 /*************************/
60
61 /* ########################################################################## */
62 /* #### (0x0703) MESSAGING CLUSTER ########################################## */
63 /* ########################################################################## */
64
65 /* Attributes - None (other than Attribute Reporting Status) */
66 static const value_string zbee_zcl_msg_attr_names[] = {
67     ZBEE_ZCL_SE_ATTR_NAMES,
68     { 0, NULL }
69 };
70
71 /* Server Commands Received */
72 #define ZBEE_ZCL_CMD_ID_MSG_GET_LAST_MSG                0x00  /* Get Last Message */
73 #define ZBEE_ZCL_CMD_ID_MSG_MSG_CONFIRM                 0x01  /* Message Confirmation */
74 #define ZBEE_ZCL_CMD_ID_MSG_GET_MESSAGE_CANCEL          0x02  /* Get Message Cancellation */
75
76 /* Server Commands Generated */
77 #define ZBEE_ZCL_CMD_ID_MSG_DISPLAY_MSG                 0x00  /* Display Message */
78 #define ZBEE_ZCL_CMD_ID_MSG_CANCEL_MSG                  0x01  /* Cancel Message */
79 #define ZBEE_ZCL_CMD_ID_MSG_DISPLAY_PROTECTED_MSG       0x02  /* Display Protected Message */
80 #define ZBEE_ZCL_CMD_ID_MSG_CANCEL_ALL_MSG              0x03  /* Cancel All Messages */
81
82 /* Message Control Field Bit Map */
83 #define ZBEE_ZCL_MSG_CTRL_TX_MASK                       0x03
84 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MASK               0x0C
85 #define ZBEE_ZCL_MSG_CTRL_RESERVED_MASK                 0x50
86 #define ZBEE_ZCL_MSG_CTRL_ENHANCED_CONFIRM_MASK         0x20
87 #define ZBEE_ZCL_MSG_CTRL_CONFIRM_MASK                  0x80
88
89 #define ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ONLY                0x00 /* Normal Transmission Only */
90 #define ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ANON_INTERPAN       0x01 /* Normal and Anonymous Inter-PAN Transmission Only */
91 #define ZBEE_ZCL_MSG_CTRL_TX_ANON_INTERPAN_ONLY         0x02 /* Anonymous Inter-PAN Transmission Only */
92
93 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_LOW                0x00 /* Low */
94 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MEDIUM             0x01 /* Medium */
95 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_HIGH               0x02 /* High */
96 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_CRITICAL           0x03 /* Critical */
97
98 #define ZBEE_ZCL_MSG_EXT_CTRL_STATUS_MASK               0x01
99
100 #define ZBEE_ZCL_MSG_CONFIRM_CTRL_MASK                  0x01
101
102 #define ZBEE_ZCL_MSG_START_TIME_NOW                     0x00000000 /* Now */
103
104 /*************************/
105 /* Function Declarations */
106 /*************************/
107 void proto_register_zbee_zcl_msg(void);
108 void proto_reg_handoff_zbee_zcl_msg(void);
109
110 /* Attribute Dissector Helpers */
111 static void dissect_zcl_msg_attr_data  (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type);
112
113 /* Command Dissector Helpers */
114 static void dissect_zcl_msg_display             (tvbuff_t *tvb, proto_tree *tree, guint *offset);
115 static void dissect_zcl_msg_cancel              (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset);
116 static void dissect_zcl_msg_confirm             (tvbuff_t *tvb, proto_tree *tree, guint *offset);
117 static void dissect_zcl_msg_cancel_all          (tvbuff_t *tvb, proto_tree *tree, guint *offset);
118 static void dissect_zcl_msg_get_cancel          (tvbuff_t *tvb, proto_tree *tree, guint *offset);
119
120 /* Private functions prototype */
121 static void decode_zcl_msg_duration             (gchar *s, guint16 value);
122
123 /*************************/
124 /* Global Variables      */
125 /*************************/
126
127 /* Initialize the protocol and registered fields */
128 static int proto_zbee_zcl_msg = -1;
129
130 static int hf_zbee_zcl_msg_srv_tx_cmd_id = -1;
131 static int hf_zbee_zcl_msg_srv_rx_cmd_id = -1;
132 static int hf_zbee_zcl_msg_attr_id = -1;
133 static int hf_zbee_zcl_msg_attr_reporting_status = -1;
134 static int hf_zbee_zcl_msg_message_id = -1;
135 static int hf_zbee_zcl_msg_ctrl = -1;
136 static int hf_zbee_zcl_msg_ctrl_tx = -1;
137 static int hf_zbee_zcl_msg_ctrl_importance = -1;
138 static int hf_zbee_zcl_msg_ctrl_enh_confirm = -1;
139 static int hf_zbee_zcl_msg_ctrl_reserved = -1;
140 static int hf_zbee_zcl_msg_ctrl_confirm = -1;
141 static int hf_zbee_zcl_msg_ext_ctrl = -1;
142 static int hf_zbee_zcl_msg_ext_ctrl_status = -1;
143 static int hf_zbee_zcl_msg_start_time = -1;
144 static int hf_zbee_zcl_msg_duration = -1;
145 static int hf_zbee_zcl_msg_message_length = - 1;
146 static int hf_zbee_zcl_msg_message = -1;
147 static int hf_zbee_zcl_msg_confirm_time = -1;
148 static int hf_zbee_zcl_msg_confirm_ctrl = -1;
149 static int hf_zbee_zcl_msg_confirm_response = -1;
150 static int hf_zbee_zcl_msg_confirm_response_length = - 1;
151 static int hf_zbee_zcl_msg_implementation_time = -1;
152 static int hf_zbee_zcl_msg_earliest_time = -1;
153
154 /* Initialize the subtree pointers */
155 static gint ett_zbee_zcl_msg = -1;
156 static gint ett_zbee_zcl_msg_message_control = -1;
157 static gint ett_zbee_zcl_msg_ext_message_control = -1;
158
159 static expert_field ei_zbee_zcl_msg_msg_ctrl_depreciated = EI_INIT;
160
161 /* Server Commands Received */
162 static const value_string zbee_zcl_msg_srv_rx_cmd_names[] = {
163     { ZBEE_ZCL_CMD_ID_MSG_GET_LAST_MSG,                 "Get Last Message" },
164     { ZBEE_ZCL_CMD_ID_MSG_MSG_CONFIRM,                  "Message Confirmation" },
165     { ZBEE_ZCL_CMD_ID_MSG_GET_MESSAGE_CANCEL,           "Get Message Cancellation" },
166     { 0, NULL }
167 };
168
169 /* Server Commands Generated */
170 static const value_string zbee_zcl_msg_srv_tx_cmd_names[] = {
171     { ZBEE_ZCL_CMD_ID_MSG_DISPLAY_MSG,                  "Display Message" },
172     { ZBEE_ZCL_CMD_ID_MSG_CANCEL_MSG,                   "Cancel Message" },
173     { ZBEE_ZCL_CMD_ID_MSG_DISPLAY_PROTECTED_MSG,        "Display Protected Message"},
174     { ZBEE_ZCL_CMD_ID_MSG_CANCEL_ALL_MSG,               "Cancel All Messages" },
175     { 0, NULL }
176 };
177
178 /* Message Control Transmission */
179 static const value_string zbee_zcl_msg_ctrl_tx_names[] = {
180     { ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ONLY,                 "Normal Transmission Only" },
181     { ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ANON_INTERPAN,        "Normal and Anonymous Inter-PAN Transmission Only" },
182     { ZBEE_ZCL_MSG_CTRL_TX_ANON_INTERPAN_ONLY,          "Anonymous Inter-PAN Transmission Only" },
183     { 0, NULL }
184 };
185
186 /* Message Control Importance */
187 static const value_string zbee_zcl_msg_ctrl_importance_names[] = {
188     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_LOW,                 "Low" },
189     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MEDIUM,              "Medium" },
190     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_HIGH,                "High" },
191     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_CRITICAL,            "Critical" },
192     { 0, NULL }
193 };
194
195 /*************************/
196 /* Function Bodies       */
197 /*************************/
198
199 /*FUNCTION:------------------------------------------------------
200  *  NAME
201  *      dissect_zcl_msg_attr_data
202  *  DESCRIPTION
203  *      this function is called by ZCL foundation dissector in order to decode
204  *      specific cluster attributes data.
205  *  PARAMETERS
206  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
207  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
208  *      guint *offset       - pointer to buffer offset
209  *      guint16 attr_id     - attribute identifier
210  *      guint data_type     - attribute data type
211  *  RETURNS
212  *      none
213  *---------------------------------------------------------------
214  */
215 static void
216 dissect_zcl_msg_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type)
217 {
218     switch (attr_id) {
219         /* no cluster specific attributes */
220
221         /* applies to all SE clusters */
222         case ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS:
223             proto_tree_add_item(tree, hf_zbee_zcl_msg_attr_reporting_status, tvb, *offset, 1, ENC_NA);
224             *offset += 1;
225             break;
226
227         default: /* Catch all */
228             dissect_zcl_attr_data(tvb, tree, offset, data_type);
229             break;
230     }
231 } /*dissect_zcl_ias_zone_attr_data*/
232
233 /*FUNCTION:------------------------------------------------------
234  *  NAME
235  *      dissect_zbee_zcl_msg
236  *  DESCRIPTION
237  *      ZigBee ZCL Messaging cluster dissector for wireshark.
238  *  PARAMETERS
239  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
240  *      packet_info *pinfo  - pointer to packet information fields
241  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
242  *  RETURNS
243  *      none
244  *---------------------------------------------------------------
245  */
246 static int
247 dissect_zbee_zcl_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
248 {
249     proto_tree        *payload_tree;
250     zbee_zcl_packet   *zcl;
251     guint             offset = 0;
252     guint8            cmd_id;
253     gint              rem_len;
254
255     /* Reject the packet if data is NULL */
256     if (data == NULL)
257         return 0;
258     zcl = (zbee_zcl_packet *)data;
259     cmd_id = zcl->cmd_id;
260
261     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
262     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
263         /* Append the command name to the info column. */
264         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
265             val_to_str_const(cmd_id, zbee_zcl_msg_srv_rx_cmd_names, "Unknown Command"),
266             zcl->tran_seqno);
267
268         /* Add the command ID. */
269         proto_tree_add_item(tree, hf_zbee_zcl_msg_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
270
271         /* Check is this command has a payload, than add the payload tree */
272         rem_len = tvb_reported_length_remaining(tvb, ++offset);
273         if (rem_len > 0) {
274             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_msg, NULL, "Payload");
275
276             /* Call the appropriate command dissector */
277             switch (cmd_id) {
278
279                 case ZBEE_ZCL_CMD_ID_MSG_GET_LAST_MSG:
280                     /* No payload */
281                     break;
282
283                 case ZBEE_ZCL_CMD_ID_MSG_MSG_CONFIRM:
284                     dissect_zcl_msg_confirm(tvb, payload_tree, &offset);
285                     break;
286
287                 case ZBEE_ZCL_CMD_ID_MSG_GET_MESSAGE_CANCEL:
288                     dissect_zcl_msg_get_cancel(tvb, payload_tree, &offset);
289                     break;
290
291                 default:
292                     break;
293             }
294         }
295     }
296     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
297         /* Append the command name to the info column. */
298         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
299             val_to_str_const(cmd_id, zbee_zcl_msg_srv_tx_cmd_names, "Unknown Command"),
300             zcl->tran_seqno);
301
302         /* Add the command ID. */
303         proto_tree_add_item(tree, hf_zbee_zcl_msg_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
304
305         /* Check is this command has a payload, than add the payload tree */
306         rem_len = tvb_reported_length_remaining(tvb, ++offset);
307         if (rem_len > 0) {
308             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_msg, NULL, "Payload");
309
310             /* Call the appropriate command dissector */
311             switch (cmd_id) {
312
313                 case ZBEE_ZCL_CMD_ID_MSG_DISPLAY_MSG:
314                     dissect_zcl_msg_display(tvb, payload_tree, &offset);
315                     break;
316
317                 case ZBEE_ZCL_CMD_ID_MSG_CANCEL_MSG:
318                     dissect_zcl_msg_cancel(tvb, pinfo, payload_tree, &offset);
319                     break;
320
321                 case ZBEE_ZCL_CMD_ID_MSG_DISPLAY_PROTECTED_MSG:
322                     dissect_zcl_msg_display(tvb, payload_tree, &offset);
323                     break;
324
325                 case ZBEE_ZCL_CMD_ID_MSG_CANCEL_ALL_MSG:
326                     dissect_zcl_msg_cancel_all(tvb, payload_tree, &offset);
327                     break;
328
329                 default:
330                     break;
331             }
332         }
333     }
334
335     return tvb_captured_length(tvb);
336 } /*dissect_zbee_zcl_msg*/
337
338  /*FUNCTION:------------------------------------------------------
339  *  NAME
340  *      dissect_zcl_msg_display
341  *  DESCRIPTION
342  *      This function manages the Display Message payload
343  *  PARAMETERS
344  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
345  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
346  *      offset              - offset
347  *  RETURNS
348  *      none
349  *---------------------------------------------------------------
350  */
351 static void
352 dissect_zcl_msg_display(tvbuff_t *tvb, proto_tree *tree, guint *offset)
353 {
354     guint   msg_len;
355     guint8 *msg_data;
356
357     static const int * message_ctrl_flags[] = {
358         &hf_zbee_zcl_msg_ctrl_tx,
359         &hf_zbee_zcl_msg_ctrl_importance,
360         &hf_zbee_zcl_msg_ctrl_enh_confirm,
361         &hf_zbee_zcl_msg_ctrl_reserved,
362         &hf_zbee_zcl_msg_ctrl_confirm,
363         NULL
364     };
365
366     static const int * message_ext_ctrl_flags[] = {
367         &hf_zbee_zcl_msg_ext_ctrl_status,
368         NULL
369     };
370
371     /* Message ID */
372     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_id, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
373     *offset += 4;
374
375     /* Message Control */
376     proto_tree_add_bitmask(tree, tvb, *offset, hf_zbee_zcl_msg_ctrl, ett_zbee_zcl_msg_message_control, message_ctrl_flags, ENC_NA);
377     *offset += 1;
378
379     /* Start Time */
380     proto_tree_add_item(tree, hf_zbee_zcl_msg_start_time, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
381     *offset += 4;
382
383     /* Duration In Minutes*/
384     proto_tree_add_item(tree, hf_zbee_zcl_msg_duration, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
385     *offset += 2;
386
387     /* Message Length */
388     msg_len = tvb_get_guint8(tvb, *offset); /* string length */
389     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_length, tvb, *offset, 1, ENC_NA);
390     *offset += 1;
391
392     /* Message */
393     msg_data = tvb_get_string_enc(wmem_packet_scope(), tvb, *offset, msg_len, ENC_LITTLE_ENDIAN);
394     proto_tree_add_string(tree, hf_zbee_zcl_msg_message, tvb, *offset, msg_len, msg_data);
395     *offset += msg_len;
396
397     /* (Optional) Extended Message Control */
398     if (tvb_reported_length_remaining(tvb, *offset) > 0) {
399         proto_tree_add_bitmask(tree, tvb, *offset, hf_zbee_zcl_msg_ext_ctrl, ett_zbee_zcl_msg_ext_message_control, message_ext_ctrl_flags, ENC_NA);
400         *offset += 1;
401     }
402
403 } /*dissect_zcl_msg_display*/
404
405  /*FUNCTION:------------------------------------------------------
406  *  NAME
407  *      dissect_zcl_msg_cancel
408  *  DESCRIPTION
409  *      This function manages the Cancel Message payload
410  *  PARAMETERS
411  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
412  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
413  *      offset              - offset
414  *  RETURNS
415  *      none
416  *---------------------------------------------------------------
417  */
418 static void
419 dissect_zcl_msg_cancel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset)
420 {
421     gint8 msg_ctrl;
422
423     /* Message ID */
424     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_id, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
425     *offset += 4;
426
427     /* Message Control */
428     msg_ctrl = tvb_get_guint8(tvb, *offset);
429     proto_tree_add_item(tree, hf_zbee_zcl_msg_ctrl, tvb, *offset, 1, ENC_NA);
430     *offset += 1;
431
432     if (msg_ctrl != 0x00) {
433        expert_add_info(pinfo, tree, &ei_zbee_zcl_msg_msg_ctrl_depreciated);
434     }
435
436 } /* dissect_zcl_msg_cancel */
437
438
439  /*FUNCTION:------------------------------------------------------
440  *  NAME
441  *      dissect_zcl_msg_cancel_all
442  *  DESCRIPTION
443  *      Send Cancel All command
444  *  PARAMETERS
445  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
446  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
447  *      offset              - offset
448  *  RETURNS
449  *      none
450  *---------------------------------------------------------------
451  */
452 static void
453 dissect_zcl_msg_cancel_all(tvbuff_t *tvb, proto_tree *tree, guint *offset)
454 {
455     nstime_t impl_time;
456
457     /* Retrieve "Confirmation Time" field */
458     impl_time.secs = tvb_get_letohl(tvb, *offset) + ZBEE_ZCL_NSTIME_UTC_OFFSET;
459     impl_time.nsecs = 0;
460     proto_tree_add_time(tree, hf_zbee_zcl_msg_implementation_time, tvb, *offset, 4, &impl_time);
461     *offset += 4;
462
463 } /* dissect_zcl_msg_cancel_all */
464
465  /*FUNCTION:------------------------------------------------------
466  *  NAME
467  *      dissect_zcl_msg_get_cancel
468  *  DESCRIPTION
469  *      Send Cancel All command
470  *  PARAMETERS
471  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
472  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
473  *      offset              - offset
474  *  RETURNS
475  *      none
476  *---------------------------------------------------------------
477  */
478 static void
479 dissect_zcl_msg_get_cancel(tvbuff_t *tvb, proto_tree *tree, guint *offset)
480 {
481     nstime_t impl_time;
482
483     /* Earliest Implementation Time */
484     impl_time.secs = tvb_get_letohl(tvb, *offset) + ZBEE_ZCL_NSTIME_UTC_OFFSET;
485     impl_time.nsecs = 0;
486     proto_tree_add_time(tree, hf_zbee_zcl_msg_earliest_time, tvb, *offset, 4, &impl_time);
487     *offset += 4;
488
489 } /* dissect_zcl_msg_get_cancel */
490
491
492  /*FUNCTION:------------------------------------------------------
493  *  NAME
494  *      dissect_zcl_msg_confirm
495  *  DESCRIPTION
496  *      This function manages the Message Confirmation payload
497  *  PARAMETERS
498  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
499  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
500  *      offset              - offset
501  *  RETURNS
502  *      none
503  *---------------------------------------------------------------
504  */
505 static void
506 dissect_zcl_msg_confirm(tvbuff_t *tvb, proto_tree *tree, guint *offset)
507 {
508     guint   msg_len;
509     guint8 *msg_data;
510     nstime_t confirm_time;
511
512     /* Retrieve "Message ID" field */
513     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_id, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
514     *offset += 4;
515
516     /* Retrieve "Confirmation Time" field */
517     confirm_time.secs = tvb_get_letohl(tvb, *offset) + ZBEE_ZCL_NSTIME_UTC_OFFSET;
518     confirm_time.nsecs = 0;
519     proto_tree_add_time(tree, hf_zbee_zcl_msg_confirm_time, tvb, *offset, 4, &confirm_time);
520     *offset += 4;
521
522     /* (Optional) Confirm Control */
523     if ( tvb_reported_length_remaining(tvb, *offset) <= 0 ) return;
524     proto_tree_add_item(tree, hf_zbee_zcl_msg_confirm_ctrl, tvb, *offset, 1, ENC_NA);
525     *offset += 1;
526
527     /* (Optional) Response Text Length */
528     if ( tvb_reported_length_remaining(tvb, *offset) <= 0 ) return;
529     msg_len = tvb_get_guint8(tvb, *offset); /* string length */
530     proto_tree_add_item(tree, hf_zbee_zcl_msg_confirm_response_length, tvb, *offset, 1, ENC_NA);
531     *offset += 1;
532
533     /* (Optional) Response Text, but is we have a length we expect to find the subsequent string */
534     if (msg_len > 0) {
535         msg_data = tvb_get_string_enc(wmem_packet_scope(), tvb, *offset, msg_len, ENC_LITTLE_ENDIAN);
536         proto_tree_add_string(tree, hf_zbee_zcl_msg_confirm_response, tvb, *offset, msg_len, msg_data);
537         *offset += msg_len;
538     }
539
540 } /* dissect_zcl_msg_confirm */
541
542 /*FUNCTION:------------------------------------------------------
543  *  NAME
544  *      decode_zcl_msg_duration
545  *  DESCRIPTION
546  *    this function decodes duration in minute type variable
547  *  PARAMETERS
548  *  RETURNS
549  *      none
550  *---------------------------------------------------------------
551  */
552 static void
553 decode_zcl_msg_duration(gchar *s, guint16 value)
554 {
555     if (value == 0xffff)
556         g_snprintf(s, ITEM_LABEL_LENGTH, "Until changed");
557     else
558         g_snprintf(s, ITEM_LABEL_LENGTH, "%d minutes", value);
559     return;
560 } /*decode_zcl_msg_duration*/
561
562 /*FUNCTION:------------------------------------------------------
563  *  NAME
564  *      decode_zcl_msg_start_time
565  *  DESCRIPTION
566  *      this function decodes start time, with peculiarity case for
567  *      messaging specifications.
568  *  PARAMETERS
569  *      guint *s        - string to display
570  *      guint32 value   - value to decode
571  *  RETURNS
572  *      none
573  *---------------------------------------------------------------
574  */
575 static void
576 decode_zcl_msg_start_time(gchar *s, guint32 value)
577 {
578     if (value == ZBEE_ZCL_MSG_START_TIME_NOW)
579         g_snprintf(s, ITEM_LABEL_LENGTH, "Now");
580     else {
581         gchar *start_time;
582         value += ZBEE_ZCL_NSTIME_UTC_OFFSET;
583         start_time = abs_time_secs_to_str (NULL, value, ABSOLUTE_TIME_LOCAL, TRUE);
584         g_snprintf(s, ITEM_LABEL_LENGTH, "%s", start_time);
585         wmem_free(NULL, start_time);
586     }
587 } /* decode_zcl_msg_start_time */
588
589 /*FUNCTION:------------------------------------------------------
590  *  NAME
591  *      proto_register_zbee_zcl_msg
592  *  DESCRIPTION
593  *      this function registers the ZCL Messaging dissector
594  *      and all its information.
595  *  PARAMETERS
596  *      none
597  *  RETURNS
598  *      none
599  *---------------------------------------------------------------
600  */
601 void
602 proto_register_zbee_zcl_msg(void)
603 {
604     static hf_register_info hf[] = {
605
606         { &hf_zbee_zcl_msg_attr_id,
607             { "Attribute", "zbee_zcl_se.msg.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_msg_attr_names),
608             0x0, NULL, HFILL } },
609
610         { &hf_zbee_zcl_msg_attr_reporting_status,                         /* common to all SE clusters */
611             { "Attribute Reporting Status", "zbee_zcl_se.msg.attr.attr_reporting_status",
612             FT_UINT8, BASE_HEX, VALS(zbee_zcl_se_reporting_status_names), 0x00, NULL, HFILL } },
613
614         { &hf_zbee_zcl_msg_srv_tx_cmd_id,
615             { "Command", "zbee_zcl_se.msg.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_srv_tx_cmd_names),
616             0x00, NULL, HFILL } },
617
618         { &hf_zbee_zcl_msg_srv_rx_cmd_id,
619             { "Command", "zbee_zcl_se.msg.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_srv_rx_cmd_names),
620             0x00, NULL, HFILL } },
621
622         { &hf_zbee_zcl_msg_message_id,
623             { "Message ID", "zbee_zcl_se.msg.message.id", FT_UINT32, BASE_HEX, NULL,
624             0x00, NULL, HFILL } },
625
626 /* Start of 'Message Control' fields */
627         { &hf_zbee_zcl_msg_ctrl,
628             { "Message Control", "zbee_zcl_se.msg.message.ctrl", FT_UINT8, BASE_HEX, NULL,
629             0x0, NULL, HFILL } },
630
631         { &hf_zbee_zcl_msg_ctrl_tx,
632             { "Transmission", "zbee_zcl_se.msg.message.ctrl.tx", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_ctrl_tx_names),
633             ZBEE_ZCL_MSG_CTRL_TX_MASK, NULL, HFILL } },
634
635         { &hf_zbee_zcl_msg_ctrl_importance,
636             { "Importance", "zbee_zcl_se.msg.message.ctrl.importance", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_ctrl_importance_names),
637             ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MASK, NULL, HFILL } },
638
639         { &hf_zbee_zcl_msg_ctrl_enh_confirm,
640             { "Confirmation", "zbee_zcl_se.msg.message.ctrl.enhconfirm", FT_BOOLEAN, 8, TFS(&tfs_required_not_required),
641             ZBEE_ZCL_MSG_CTRL_ENHANCED_CONFIRM_MASK, NULL, HFILL } },
642
643         { &hf_zbee_zcl_msg_ctrl_reserved,
644             { "Reserved", "zbee_zcl_se.msg.message.ctrl.reserved", FT_UINT8, BASE_HEX, NULL,
645             ZBEE_ZCL_MSG_CTRL_RESERVED_MASK, NULL, HFILL } },
646
647         { &hf_zbee_zcl_msg_ctrl_confirm,
648             { "Confirmation", "zbee_zcl_se.msg.message.ctrl.confirm", FT_BOOLEAN, 8, TFS(&tfs_required_not_required),
649             ZBEE_ZCL_MSG_CTRL_CONFIRM_MASK, NULL, HFILL } },
650 /* End of 'Message Control' fields */
651
652 /* Start of 'Extended Message Control' fields */
653         { &hf_zbee_zcl_msg_ext_ctrl,
654             { "Extended Message Control", "zbee_zcl_se.msg.message.ext.ctrl", FT_UINT8, BASE_HEX, NULL,
655             0x0, NULL, HFILL } },
656
657         { &hf_zbee_zcl_msg_ext_ctrl_status,
658             { "Message Confirmation Satus", "zbee_zcl_se.msg.message.ext.ctrl.status", FT_BOOLEAN, 8, TFS(&tfs_confirmed_unconfirmed),
659             ZBEE_ZCL_MSG_EXT_CTRL_STATUS_MASK, NULL, HFILL } },
660 /* End of 'Extended Message Control' fields */
661
662         { &hf_zbee_zcl_msg_start_time,
663             { "Start Time", "zbee_zcl_se.msg.message.start_time", FT_UINT32, BASE_CUSTOM, CF_FUNC(decode_zcl_msg_start_time),
664             0x00, NULL, HFILL } },
665
666         { &hf_zbee_zcl_msg_duration,
667             { "Duration", "zbee_zcl_se.msg.message.duration", FT_UINT16, BASE_CUSTOM, CF_FUNC(decode_zcl_msg_duration),
668             0x00, NULL, HFILL } },
669
670         { &hf_zbee_zcl_msg_message_length,
671             { "Message Length", "zbee_zcl_se.msg.message.length", FT_UINT8, BASE_DEC, NULL,
672             0x00, NULL, HFILL } },
673
674         { &hf_zbee_zcl_msg_message,
675             { "Message", "zbee_zcl_se.msg.message", FT_STRING, BASE_NONE, NULL,
676             0x00, NULL, HFILL } },
677
678         { &hf_zbee_zcl_msg_confirm_time,
679             { "Confirmation Time", "zbee_zcl_se.msg.message.confirm_time",  FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL,
680             0x0, NULL, HFILL } },
681
682         { &hf_zbee_zcl_msg_confirm_ctrl,
683             { "Confirmation Control", "zbee_zcl_se.msg.message.confirm.ctrl", FT_BOOLEAN, 8, TFS(&tfs_no_yes),
684             ZBEE_ZCL_MSG_CONFIRM_CTRL_MASK, NULL, HFILL } },
685
686         { &hf_zbee_zcl_msg_confirm_response_length,
687             { "Response Length", "zbee_zcl_se.msg.message.length", FT_UINT8, BASE_DEC, NULL,
688             0x00, NULL, HFILL } },
689
690         { &hf_zbee_zcl_msg_confirm_response,
691             { "Response", "zbee_zcl_se.msg.message", FT_STRING, BASE_NONE, NULL,
692             0x00, NULL, HFILL } },
693
694         { &hf_zbee_zcl_msg_implementation_time,
695             { "Implementation Time", "zbee_zcl_se.msg.impl_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
696             0, NULL, HFILL } },
697
698         { &hf_zbee_zcl_msg_earliest_time,
699             { "Earliest Implementation Time", "zbee_zcl_se.msg.earliest_impl_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
700             0, NULL, HFILL } },
701
702     };
703
704     /* ZCL Messaging subtrees */
705     gint *ett[] = {
706         &ett_zbee_zcl_msg,
707         &ett_zbee_zcl_msg_message_control,
708         &ett_zbee_zcl_msg_ext_message_control,
709     };
710
711     /* Expert Info */
712     expert_module_t* expert_zbee_zcl_msg;
713     static ei_register_info ei[] = {
714         { &ei_zbee_zcl_msg_msg_ctrl_depreciated, { "zbee_zcl_se.msg.msg_ctrl.depreciated", PI_PROTOCOL, PI_WARN, "Message Control depreciated in this message, should be 0x00", EXPFILL }},
715     };
716
717     /* Register the ZigBee ZCL Messaging cluster protocol name and description */
718     proto_zbee_zcl_msg = proto_register_protocol("ZigBee ZCL Messaging", "ZCL Messaging", ZBEE_PROTOABBREV_ZCL_MSG);
719     proto_register_field_array(proto_zbee_zcl_msg, hf, array_length(hf));
720     proto_register_subtree_array(ett, array_length(ett));
721
722     expert_zbee_zcl_msg = expert_register_protocol(proto_zbee_zcl_msg);
723     expert_register_field_array(expert_zbee_zcl_msg, ei, array_length(ei));
724
725     /* Register the ZigBee ZCL Messaging dissector. */
726     new_register_dissector(ZBEE_PROTOABBREV_ZCL_MSG, dissect_zbee_zcl_msg, proto_zbee_zcl_msg);
727 } /*proto_register_zbee_zcl_msg*/
728
729 /*FUNCTION:------------------------------------------------------
730  *  NAME
731  *      proto_reg_handoff_zbee_zcl_msg
732  *  DESCRIPTION
733  *      Hands off the Zcl Messaging dissector.
734  *  PARAMETERS
735  *      none
736  *  RETURNS
737  *      void
738  *---------------------------------------------------------------
739  */
740 void
741 proto_reg_handoff_zbee_zcl_msg(void)
742 {
743     dissector_handle_t msg_handle;
744
745     /* Register our dissector with the ZigBee application dissectors. */
746     msg_handle = find_dissector(ZBEE_PROTOABBREV_ZCL_MSG);
747     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_MESSAGE, msg_handle);
748
749     zbee_zcl_init_cluster(  proto_zbee_zcl_msg,
750                             ett_zbee_zcl_msg,
751                             ZBEE_ZCL_CID_MESSAGE,
752                             hf_zbee_zcl_msg_attr_id,
753                             hf_zbee_zcl_msg_srv_rx_cmd_id,
754                             hf_zbee_zcl_msg_srv_tx_cmd_id,
755                             (zbee_zcl_fn_attr_data)dissect_zcl_msg_attr_data
756                          );
757 } /*proto_reg_handoff_zbee_zcl_msg*/
758
759 /* ########################################################################## */
760 /* #### (0x0704) TUNNELING CLUSTER ########################################### */
761 /* ########################################################################## */
762
763 /* Attributes */
764 #define ZBEE_ZCL_ATTR_ID_TUN_CLOSE_TIMEOUT             0x0000   /* Close Tunnel Timeout */
765
766 static const value_string zbee_zcl_tun_attr_names[] = {
767     { ZBEE_ZCL_ATTR_ID_TUN_CLOSE_TIMEOUT,      "Close Tunnel Timeout" },
768     ZBEE_ZCL_SE_ATTR_NAMES,
769     { 0, NULL }
770 };
771
772 /* Server Commands Received */
773 #define ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL                       0x00  /* Request Tunnel */
774 #define ZBEE_ZCL_CMD_ID_TUN_CLOSE_TUNNEL                         0x01  /* Close Tunnel */
775 #define ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA                        0x02  /* Transfer Data */
776 #define ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR                  0x03  /* Transfer Data Error */
777 #define ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA                    0x04  /* Ack Transfer Data */
778 #define ZBEE_ZCL_CMD_ID_TUN_READY_DATA                           0x05  /* Ready Data */
779 #define ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS              0x06  /* Get Supported Tunnel Protocols */
780
781 /* Server Commands Generated */
782 #define ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL_RSP                   0x00  /* Request Tunnel Response*/
783 #define ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_TX                     0x01  /* Transfer Data */
784 #define ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR_TX               0x02  /* Transfer Data Error */
785 #define ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA_TX                 0x03  /* Ack Transfer Data */
786 #define ZBEE_ZCL_CMD_ID_TUN_READY_DATA_TX                        0x04  /* Ready Data */
787 #define ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS_RSP          0x05  /* Get Supported Tunnel Protocols */
788 #define ZBEE_ZCL_CMD_ID_TUN_CLOSURE_NOTIFY                       0x06  /* Tunnel Closure Notification */
789
790 /*************************/
791 /* Function Declarations */
792 /*************************/
793 void proto_register_zbee_zcl_tun(void);
794 void proto_reg_handoff_zbee_zcl_tun(void);
795
796 /* Attribute Dissector Helpers */
797 static void dissect_zcl_tun_attr_data  (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type);
798
799 /* Private functions prototype */
800
801 /*************************/
802 /* Global Variables      */
803 /*************************/
804
805 /* Initialize the protocol and registered fields */
806 static int proto_zbee_zcl_tun = -1;
807
808 static int hf_zbee_zcl_tun_srv_tx_cmd_id = -1;
809 static int hf_zbee_zcl_tun_srv_rx_cmd_id = -1;
810 static int hf_zbee_zcl_tun_attr_id = -1;
811 static int hf_zbee_zcl_tun_attr_reporting_status = -1;
812 static int hf_zbee_zcl_tun_attr_close_timeout = -1;
813 static int hf_zbee_zcl_tun_protocol_id = -1;
814 static int hf_zbee_zcl_tun_manufacturer_code = -1;
815 static int hf_zbee_zcl_tun_flow_control_support = -1;
816 static int hf_zbee_zcl_tun_max_in_size = -1;
817 static int hf_zbee_zcl_tun_tunnel_id = -1;
818 static int hf_zbee_zcl_tun_num_octets_left = -1;
819 static int hf_zbee_zcl_tun_protocol_offset = -1;
820 static int hf_zbee_zcl_tun_protocol_list_complete = -1;
821 static int hf_zbee_zcl_tun_protocol_count = -1;
822 static int hf_zbee_zcl_tun_transfer_status = -1;
823 static int hf_zbee_zcl_tun_transfer_data = -1;
824 static int hf_zbee_zcl_tun_transfer_data_status = -1;
825
826 /* Initialize the subtree pointers */
827 static gint ett_zbee_zcl_tun = -1;
828
829 /* Subdissector handles. */
830 static dissector_handle_t       ipv4_handle;
831 static dissector_handle_t       ipv6_handle;
832
833 /* Server Commands Received */
834 static const value_string zbee_zcl_tun_srv_rx_cmd_names[] = {
835     { ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL,                 "Request Tunnel" },
836     { ZBEE_ZCL_CMD_ID_TUN_CLOSE_TUNNEL,                   "Close Tunnel" },
837     { ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA,                  "Transfer Data" },
838     { ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR,            "Transfer Data Error" },
839     { ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA,              "Ack Transfer Data" },
840     { ZBEE_ZCL_CMD_ID_TUN_READY_DATA,                     "Ready Data" },
841     { ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS,        "Get Supported Protocols" },
842     { 0, NULL }
843 };
844
845 /* Server Commands Generated */
846 static const value_string zbee_zcl_tun_srv_tx_cmd_names[] = {
847     { ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL_RSP,             "Request Tunnel Response" },
848     { ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_TX,               "Transfer Data" },
849     { ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR_TX,         "Transfer Data Error" },
850     { ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA_TX,           "Ack Transfer Data" },
851     { ZBEE_ZCL_CMD_ID_TUN_READY_DATA_TX,                  "Ready Data" },
852     { ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS_RSP,    "Get Supported Tunnel Protocols" },
853     { ZBEE_ZCL_CMD_ID_TUN_CLOSURE_NOTIFY,                 "Tunnel Closure Notification" },
854     { 0, NULL }
855 };
856
857 #define ZBEE_ZCL_TUN_PROTO_DLMS                    0x00
858 #define ZBEE_ZCL_TUN_PROTO_IEC_61107               0x01
859 #define ZBEE_ZCL_TUN_PROTO_ANSI_C12                0x02
860 #define ZBEE_ZCL_TUN_PROTO_M_BUS                   0x03
861 #define ZBEE_ZCL_TUN_PROTO_SML                     0x04
862 #define ZBEE_ZCL_TUN_PROTO_CLIMATE_TALK            0x05
863 #define ZBEE_ZCL_TUN_PROTO_GB_HRGP                 0x06
864 #define ZBEE_ZCL_TUN_PROTO_IPV6                    0x07
865 #define ZBEE_ZCL_TUN_PROTO_IPV4                    0x08
866 #define ZBEE_ZCL_TUN_PROTO_NULL                    0x09
867 #define ZBEE_ZCL_TUN_PROTO_TEST                     199
868 #define ZBEE_ZCL_TUN_PROTO_MANUFACTURER             200
869 #define ZBEE_ZCL_TUN_PROTO_RESERVED                0xFF
870
871 static const value_string zbee_zcl_tun_protocol_names[] = {
872     { ZBEE_ZCL_TUN_PROTO_DLMS,            "DLMS/COSEM (IEC 62056)" },
873     { ZBEE_ZCL_TUN_PROTO_IEC_61107,       "IEC 61107" },
874     { ZBEE_ZCL_TUN_PROTO_ANSI_C12,        "ANSI C12" },
875     { ZBEE_ZCL_TUN_PROTO_M_BUS,           "M-BUS" },
876     { ZBEE_ZCL_TUN_PROTO_SML,             "SML" },
877     { ZBEE_ZCL_TUN_PROTO_CLIMATE_TALK,    "ClimateTalk" },
878     { ZBEE_ZCL_TUN_PROTO_GB_HRGP,         "GB-HRGP" },
879     { ZBEE_ZCL_TUN_PROTO_IPV6,            "IPv6" },
880     { ZBEE_ZCL_TUN_PROTO_IPV4,            "IPv4" },
881     { ZBEE_ZCL_TUN_PROTO_NULL,            "null" },
882     { ZBEE_ZCL_TUN_PROTO_TEST,            "test" },
883     { ZBEE_ZCL_TUN_PROTO_MANUFACTURER,    "Manufacturer Specific" },
884     { ZBEE_ZCL_TUN_PROTO_RESERVED,        "Reserved" },
885     { 0, NULL }
886 };
887
888 #define ZBEE_ZCL_TUN_TRANS_STATUS_NO_TUNNEL               0x00
889 #define ZBEE_ZCL_TUN_TRANS_STATUS_WRONG_DEV               0x01
890 #define ZBEE_ZCL_TUN_TRANS_STATUS_OVERFLOW                0x02
891
892 static const value_string zbee_zcl_tun_trans_data_status_names[] = {
893     { ZBEE_ZCL_TUN_TRANS_STATUS_NO_TUNNEL,        "Tunnel ID Does Not Exist" },
894     { ZBEE_ZCL_TUN_TRANS_STATUS_WRONG_DEV,        "Wrong Device" },
895     { ZBEE_ZCL_TUN_TRANS_STATUS_OVERFLOW,         "Data Overflow" },
896     { 0, NULL }
897 };
898
899 #define ZBEE_ZCL_TUN_STATUS_SUCCESS                       0x00
900 #define ZBEE_ZCL_TUN_STATUS_BUSY                          0x01
901 #define ZBEE_ZCL_TUN_STATUS_NO_MORE_IDS                   0x02
902 #define ZBEE_ZCL_TUN_STATUS_PROTO_NOT_SUPP                0x03
903 #define ZBEE_ZCL_TUN_STATUS_FLOW_CONTROL_NOT_SUPP         0x04
904
905 static const value_string zbee_zcl_tun_status_names[] = {
906     { ZBEE_ZCL_TUN_STATUS_SUCCESS,                "Success" },
907     { ZBEE_ZCL_TUN_STATUS_BUSY,                   "Busy" },
908     { ZBEE_ZCL_TUN_STATUS_NO_MORE_IDS,            "No More Tunnel IDs" },
909     { ZBEE_ZCL_TUN_STATUS_PROTO_NOT_SUPP,         "Protocol Not Supported" },
910     { ZBEE_ZCL_TUN_STATUS_FLOW_CONTROL_NOT_SUPP,  "Flow Control Not Supported" },
911     { 0, NULL }
912 };
913
914 /*************************/
915 /* Function Bodies       */
916 /*************************/
917
918 /*FUNCTION:------------------------------------------------------
919  *  NAME
920  *      dissect_zcl_tun_attr_data
921  *  DESCRIPTION
922  *      this function is called by ZCL foundation dissector in order to decode
923  *      specific cluster attributes data.
924  *  PARAMETERS
925  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
926  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
927  *      guint *offset       - pointer to buffer offset
928  *      guint16 attr_id     - attribute identifier
929  *      guint data_type     - attribute data type
930  *  RETURNS
931  *      none
932  *---------------------------------------------------------------
933  */
934 static void
935 dissect_zcl_tun_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type)
936 {
937     switch (attr_id) {
938         /* cluster specific attributes */
939         case ZBEE_ZCL_ATTR_ID_TUN_CLOSE_TIMEOUT:
940             proto_tree_add_item(tree, hf_zbee_zcl_tun_attr_close_timeout, tvb, *offset, 2, ENC_NA);
941             *offset += 2;
942             break;
943
944         /* applies to all SE clusters */
945         case ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS:
946             proto_tree_add_item(tree, hf_zbee_zcl_tun_attr_reporting_status, tvb, *offset, 1, ENC_NA);
947             *offset += 1;
948             break;
949
950         default: /* Catch all */
951             dissect_zcl_attr_data(tvb, tree, offset, data_type);
952             break;
953     }
954 } /*dissect_zcl_ias_zone_attr_data*/
955
956  /*FUNCTION:------------------------------------------------------
957  *  NAME
958  *      dissect_zcl_tun_request_tunnel
959  *  DESCRIPTION
960  *      This function manages the Display Message payload
961  *  PARAMETERS
962  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
963  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
964  *      offset              - offset
965  *  RETURNS
966  *      none
967  *---------------------------------------------------------------
968  */
969 static void
970 dissect_zcl_tun_request_tunnel(tvbuff_t *tvb, proto_tree *tree, guint *offset)
971 {
972     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_id, tvb, *offset, 1, ENC_NA);
973     *offset += 1;
974
975     proto_tree_add_item(tree, hf_zbee_zcl_tun_manufacturer_code, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
976     *offset += 2;
977
978     proto_tree_add_item(tree, hf_zbee_zcl_tun_flow_control_support, tvb, *offset, 1, ENC_NA);
979     *offset += 1;
980
981     proto_tree_add_item(tree, hf_zbee_zcl_tun_max_in_size, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
982     *offset += 2;
983 }
984
985 /*FUNCTION:------------------------------------------------------
986  *  NAME
987  *      dissect_zcl_tun_close_tunnel
988  *  DESCRIPTION
989  *      This function manages the Display Message payload
990  *  PARAMETERS
991  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
992  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
993  *      offset              - offset
994  *  RETURNS
995  *      none
996  *---------------------------------------------------------------
997  */
998 static void
999 dissect_zcl_tun_close_tunnel(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1000 {
1001     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1002     *offset += 2;
1003 }
1004
1005 /*FUNCTION:------------------------------------------------------
1006  *  NAME
1007  *      dissect_zcl_tun_transfer_data
1008  *  DESCRIPTION
1009  *      This function manages the Display Message payload
1010  *  PARAMETERS
1011  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1012  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1013  *      offset              - offset
1014  *  RETURNS
1015  *      none
1016  *---------------------------------------------------------------
1017  */
1018 static void
1019 dissect_zcl_tun_transfer_data(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1020 {
1021     gint length;
1022
1023     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1024     *offset += 2;
1025
1026     length = tvb_reported_length_remaining(tvb, *offset);
1027     proto_tree_add_item(tree, hf_zbee_zcl_tun_transfer_data, tvb, *offset, length, ENC_NA);
1028     *offset += length;
1029 }
1030
1031 /*FUNCTION:------------------------------------------------------
1032  *  NAME
1033  *      dissect_zcl_tun_transfer_data_error
1034  *  DESCRIPTION
1035  *      This function manages the Display Message payload
1036  *  PARAMETERS
1037  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1038  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1039  *      offset              - offset
1040  *  RETURNS
1041  *      none
1042  *---------------------------------------------------------------
1043  */
1044 static void
1045 dissect_zcl_tun_transfer_data_error(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1046 {
1047     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1048     *offset += 2;
1049
1050     proto_tree_add_item(tree, hf_zbee_zcl_tun_transfer_data_status, tvb, *offset, 1, ENC_NA);
1051     *offset += 1;
1052 }
1053
1054 /*FUNCTION:------------------------------------------------------
1055  *  NAME
1056  *      dissect_zcl_tun_ack_transfer_data
1057  *  DESCRIPTION
1058  *      This function manages the Display Message payload
1059  *  PARAMETERS
1060  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1061  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1062  *      offset              - offset
1063  *  RETURNS
1064  *      none
1065  *---------------------------------------------------------------
1066  */
1067 static void
1068 dissect_zcl_tun_ack_transfer_data(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1069 {
1070     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1071     *offset += 2;
1072
1073     proto_tree_add_item(tree, hf_zbee_zcl_tun_num_octets_left, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1074     *offset += 2;
1075 }
1076
1077 /*FUNCTION:------------------------------------------------------
1078  *  NAME
1079  *      dissect_zcl_tun_ready_data
1080  *  DESCRIPTION
1081  *      This function manages the Display Message payload
1082  *  PARAMETERS
1083  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1084  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1085  *      offset              - offset
1086  *  RETURNS
1087  *      none
1088  *---------------------------------------------------------------
1089  */
1090 static void
1091 dissect_zcl_tun_ready_data(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1092 {
1093     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1094     *offset += 2;
1095
1096     proto_tree_add_item(tree, hf_zbee_zcl_tun_num_octets_left, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1097     *offset += 2;
1098 }
1099
1100 /*FUNCTION:------------------------------------------------------
1101  *  NAME
1102  *      dissect_zcl_tun_get_supported
1103  *  DESCRIPTION
1104  *      This function manages the Display Message payload
1105  *  PARAMETERS
1106  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1107  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1108  *      offset              - offset
1109  *  RETURNS
1110  *      none
1111  *---------------------------------------------------------------
1112  */
1113 static void
1114 dissect_zcl_tun_get_supported(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1115 {
1116     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_offset, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1117     *offset += 2;
1118 }
1119
1120  /*FUNCTION:------------------------------------------------------
1121  *  NAME
1122  *      dissect_zcl_tun_request_tunnel_rsp
1123  *  DESCRIPTION
1124  *      This function manages the Display Message payload
1125  *  PARAMETERS
1126  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1127  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1128  *      offset              - offset
1129  *  RETURNS
1130  *      none
1131  *---------------------------------------------------------------
1132  */
1133 static void
1134 dissect_zcl_tun_request_tunnel_rsp(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1135 {
1136     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1137     *offset += 2;
1138
1139     proto_tree_add_item(tree, hf_zbee_zcl_tun_transfer_status, tvb, *offset, 1, ENC_NA);
1140     *offset += 1;
1141
1142     proto_tree_add_item(tree, hf_zbee_zcl_tun_max_in_size, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1143     *offset += 2;
1144 }
1145
1146 /*FUNCTION:------------------------------------------------------
1147  *  NAME
1148  *      dissect_zcl_tun_get_supported_rsp
1149  *  DESCRIPTION
1150  *      This function manages the Display Message payload
1151  *  PARAMETERS
1152  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1153  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1154  *      offset              - offset
1155  *  RETURNS
1156  *      none
1157  *---------------------------------------------------------------
1158  */
1159 static void
1160 dissect_zcl_tun_get_supported_rsp(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1161 {
1162     guint16     mfg_code;
1163
1164     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_list_complete, tvb, *offset, 1, ENC_NA);
1165     *offset += 1;
1166
1167     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_count, tvb, *offset, 1, ENC_NA);
1168     *offset += 1;
1169
1170     while (tvb_reported_length_remaining(tvb, *offset) > 0) {
1171         mfg_code = tvb_get_letohs(tvb, *offset);
1172         if (mfg_code == 0xFFFF) {
1173             proto_tree_add_string(tree, hf_zbee_zcl_tun_manufacturer_code, tvb, *offset, 2, "Standard Protocol (Mfg Code 0xFFFF)");
1174         }
1175         else {
1176             proto_tree_add_item(tree, hf_zbee_zcl_tun_manufacturer_code, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1177         }
1178         *offset += 2;
1179
1180         proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_id, tvb, *offset, 1, ENC_NA);
1181         *offset += 1;
1182     }
1183 }
1184
1185 /*FUNCTION:------------------------------------------------------
1186  *  NAME
1187  *      dissect_zcl_tun_closure_notify
1188  *  DESCRIPTION
1189  *      This function manages the Display Message payload
1190  *  PARAMETERS
1191  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1192  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1193  *      offset              - offset
1194  *  RETURNS
1195  *      none
1196  *---------------------------------------------------------------
1197  */
1198 static void
1199 dissect_zcl_tun_closure_notify(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1200 {
1201     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1202     *offset += 2;
1203 }
1204
1205 /*FUNCTION:------------------------------------------------------
1206  *  NAME
1207  *      dissect_zbee_zcl_tun
1208  *  DESCRIPTION
1209  *      ZigBee ZCL Messaging cluster dissector for wireshark.
1210  *  PARAMETERS
1211  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1212  *      packet_info *pinfo  - pointer to packet information fields
1213  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1214  *  RETURNS
1215  *      none
1216  *---------------------------------------------------------------
1217  */
1218 static int
1219 dissect_zbee_zcl_tun(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1220 {
1221     proto_tree        *payload_tree;
1222     zbee_zcl_packet   *zcl;
1223     guint             offset = 0;
1224     guint8            cmd_id;
1225     gint              rem_len;
1226
1227     /* Reject the packet if data is NULL */
1228     if (data == NULL)
1229         return 0;
1230     zcl = (zbee_zcl_packet *)data;
1231     cmd_id = zcl->cmd_id;
1232
1233     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
1234     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
1235         /* Append the command name to the info column. */
1236         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1237             val_to_str_const(cmd_id, zbee_zcl_tun_srv_rx_cmd_names, "Unknown Command"),
1238             zcl->tran_seqno);
1239
1240         /* Add the command ID. */
1241         proto_tree_add_item(tree, hf_zbee_zcl_tun_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
1242
1243         /* Check is this command has a payload, than add the payload tree */
1244         rem_len = tvb_reported_length_remaining(tvb, ++offset);
1245         if (rem_len > 0) {
1246             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_tun, NULL, "Payload");
1247
1248             /* Call the appropriate command dissector */
1249             switch (cmd_id) {
1250
1251                 case ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL:
1252                     dissect_zcl_tun_request_tunnel(tvb, payload_tree, &offset);
1253                     break;
1254
1255                 case ZBEE_ZCL_CMD_ID_TUN_CLOSE_TUNNEL:
1256                     dissect_zcl_tun_close_tunnel(tvb, payload_tree, &offset);
1257                     break;
1258
1259                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA:
1260                     dissect_zcl_tun_transfer_data(tvb, payload_tree, &offset);
1261                     break;
1262
1263                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR:
1264                     dissect_zcl_tun_transfer_data_error(tvb, payload_tree, &offset);
1265                     break;
1266
1267                 case ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA:
1268                     dissect_zcl_tun_ack_transfer_data(tvb, payload_tree, &offset);
1269                     break;
1270
1271                 case ZBEE_ZCL_CMD_ID_TUN_READY_DATA:
1272                     dissect_zcl_tun_ready_data(tvb, payload_tree, &offset);
1273                     break;
1274
1275                 case ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS:
1276                     dissect_zcl_tun_get_supported(tvb, payload_tree, &offset);
1277                     break;
1278
1279                 default:
1280                     break;
1281             }
1282         }
1283     }
1284     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
1285         /* Append the command name to the info column. */
1286         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1287             val_to_str_const(cmd_id, zbee_zcl_tun_srv_tx_cmd_names, "Unknown Command"),
1288             zcl->tran_seqno);
1289
1290         /* Add the command ID. */
1291         proto_tree_add_item(tree, hf_zbee_zcl_tun_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
1292
1293         /* Check is this command has a payload, than add the payload tree */
1294         rem_len = tvb_reported_length_remaining(tvb, ++offset);
1295         if (rem_len > 0) {
1296             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_tun, NULL, "Payload");
1297
1298             /* Call the appropriate command dissector */
1299             switch (cmd_id) {
1300
1301                 case ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL_RSP:
1302                     dissect_zcl_tun_request_tunnel_rsp(tvb, payload_tree, &offset);
1303                     break;
1304
1305                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_TX:
1306                     dissect_zcl_tun_transfer_data(tvb, payload_tree, &offset);
1307                     break;
1308
1309                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR_TX:
1310                     dissect_zcl_tun_transfer_data_error(tvb, payload_tree, &offset);
1311                     break;
1312
1313                 case ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA_TX:
1314                     dissect_zcl_tun_ack_transfer_data(tvb, payload_tree, &offset);
1315                     break;
1316
1317                 case ZBEE_ZCL_CMD_ID_TUN_READY_DATA_TX:
1318                     dissect_zcl_tun_ready_data(tvb, payload_tree, &offset);
1319                     break;
1320
1321                 case ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS_RSP:
1322                     dissect_zcl_tun_get_supported_rsp(tvb, payload_tree, &offset);
1323                     break;
1324
1325                 case ZBEE_ZCL_CMD_ID_TUN_CLOSURE_NOTIFY:
1326                     dissect_zcl_tun_closure_notify(tvb, payload_tree, &offset);
1327                     break;
1328
1329                 default:
1330                     break;
1331             }
1332         }
1333     }
1334
1335     return tvb_captured_length(tvb);
1336 } /*dissect_zbee_zcl_tun*/
1337
1338 /*FUNCTION:------------------------------------------------------
1339  *  NAME
1340  *      proto_register_zbee_zcl_tun
1341  *  DESCRIPTION
1342  *      this function registers the ZCL Messaging dissector
1343  *      and all its information.
1344  *  PARAMETERS
1345  *      none
1346  *  RETURNS
1347  *      none
1348  *---------------------------------------------------------------
1349  */
1350 void
1351 proto_register_zbee_zcl_tun(void)
1352 {
1353     static hf_register_info hf[] = {
1354
1355         { &hf_zbee_zcl_tun_attr_id,
1356             { "Attribute", "zbee_zcl_se.tun.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_tun_attr_names),
1357             0x0, NULL, HFILL } },
1358
1359         { &hf_zbee_zcl_tun_attr_reporting_status,                         /* common to all SE clusters */
1360             { "Attribute Reporting Status", "zbee_zcl_se.tun.attr.attr_reporting_status",
1361             FT_UINT8, BASE_HEX, VALS(zbee_zcl_se_reporting_status_names), 0x00, NULL, HFILL } },
1362
1363         { &hf_zbee_zcl_tun_attr_close_timeout,
1364             { "Close Tunnel Timeout", "zbee_zcl_se.tun.attr.close_tunnel", FT_UINT16, BASE_DEC, NULL,
1365             0x0, NULL, HFILL } },
1366
1367         { &hf_zbee_zcl_tun_srv_tx_cmd_id,
1368             { "Command", "zbee_zcl_se.tun.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_srv_tx_cmd_names),
1369             0x00, NULL, HFILL } },
1370
1371         { &hf_zbee_zcl_tun_srv_rx_cmd_id,
1372             { "Command", "zbee_zcl_se.tun.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_srv_rx_cmd_names),
1373             0x00, NULL, HFILL } },
1374
1375         { &hf_zbee_zcl_tun_protocol_id,
1376             { "Protocol ID", "zbee_zcl_se.tun.protocol_id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_protocol_names),
1377             0x00, NULL, HFILL } },
1378
1379         { &hf_zbee_zcl_tun_manufacturer_code,
1380             { "Manufacturer Code", "zbee_zcl_se.tun.manufacturer_code", FT_UINT16, BASE_HEX, VALS(zbee_mfr_code_names),
1381             0x00, NULL, HFILL } },
1382
1383         { &hf_zbee_zcl_tun_flow_control_support,
1384             { "Flow Control Supported", "zbee_zcl_se.tun.flow_control_supported", FT_BOOLEAN, 8, TFS(&tfs_true_false),
1385             0x00, NULL, HFILL } },
1386
1387         { &hf_zbee_zcl_tun_max_in_size,
1388             { "Max Incoming Transfer Size", "zbee_zcl_se.tun.max_in_transfer_size", FT_UINT16, BASE_HEX, NULL,
1389             0x00, NULL, HFILL } },
1390
1391         { &hf_zbee_zcl_tun_tunnel_id,
1392             { "Tunnel Id", "zbee_zcl_se.tun.tunnel_id", FT_UINT16, BASE_HEX, NULL,
1393             0x00, NULL, HFILL } },
1394
1395         { &hf_zbee_zcl_tun_num_octets_left,
1396             { "Num Octets Left", "zbee_zcl_se.tun.octets_left", FT_UINT16, BASE_HEX, NULL,
1397             0x00, NULL, HFILL } },
1398
1399         { &hf_zbee_zcl_tun_protocol_offset,
1400             { "Protocol Offset", "zbee_zcl_se.tun.protocol_offset", FT_UINT8, BASE_HEX, NULL,
1401             0x00, NULL, HFILL } },
1402
1403         { &hf_zbee_zcl_tun_transfer_status,
1404             { "Transfer Status", "zbee_zcl_se.tun.transfer_status", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_status_names),
1405             0x00, NULL, HFILL } },
1406
1407         { &hf_zbee_zcl_tun_transfer_data,
1408             { "Transfer Data", "zbee_zcl_se.tun.transfer_data", FT_BYTES, BASE_NONE, NULL,
1409             0, NULL, HFILL } },
1410
1411         { &hf_zbee_zcl_tun_transfer_data_status,
1412             { "Transfer Data Status", "zbee_zcl_se.tun.transfer_data_status", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_trans_data_status_names),
1413             0x00, NULL, HFILL } },
1414
1415         { &hf_zbee_zcl_tun_protocol_count,
1416             { "Protocol Count", "zbee_zcl_se.tun.protocol_count", FT_UINT8, BASE_HEX, NULL,
1417             0x00, NULL, HFILL } },
1418
1419         { &hf_zbee_zcl_tun_protocol_list_complete,
1420             { "List Complete", "zbee_zcl_se.tun.protocol_list_complete", FT_BOOLEAN, 8, TFS(&tfs_true_false),
1421             0x00, NULL, HFILL } },
1422
1423     };
1424
1425     /* ZCL Messaging subtrees */
1426     gint *ett[] = {
1427         &ett_zbee_zcl_tun,
1428     };
1429
1430     /* Register the ZigBee ZCL Messaging cluster protocol name and description */
1431     proto_zbee_zcl_tun = proto_register_protocol("ZigBee ZCL Tunneling", "ZCL Tunneling", ZBEE_PROTOABBREV_ZCL_TUN);
1432     proto_register_field_array(proto_zbee_zcl_tun, hf, array_length(hf));
1433     proto_register_subtree_array(ett, array_length(ett));
1434
1435     /* Register the ZigBee ZCL Messaging dissector. */
1436     new_register_dissector(ZBEE_PROTOABBREV_ZCL_TUN, dissect_zbee_zcl_tun, proto_zbee_zcl_tun);
1437
1438 } /* proto_register_zbee_zcl_tun */
1439
1440 /*FUNCTION:------------------------------------------------------
1441  *  NAME
1442  *      proto_reg_handoff_zbee_zcl_tun
1443  *  DESCRIPTION
1444  *      Hands off the Zcl Messaging dissector.
1445  *  PARAMETERS
1446  *      none
1447  *  RETURNS
1448  *      void
1449  *---------------------------------------------------------------
1450  */
1451 void
1452 proto_reg_handoff_zbee_zcl_tun(void)
1453 {
1454     dissector_handle_t msg_handle;
1455
1456     ipv4_handle = find_dissector("ipv4");
1457     ipv6_handle = find_dissector("ipv6");
1458
1459     /* Register our dissector with the ZigBee application dissectors. */
1460     msg_handle = find_dissector(ZBEE_PROTOABBREV_ZCL_TUN);
1461     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_TUNNELING, msg_handle);
1462
1463     zbee_zcl_init_cluster(  proto_zbee_zcl_tun,
1464                             ett_zbee_zcl_tun,
1465                             ZBEE_ZCL_CID_TUNNELING,
1466                             hf_zbee_zcl_tun_attr_id,
1467                             hf_zbee_zcl_tun_srv_rx_cmd_id,
1468                             hf_zbee_zcl_tun_srv_tx_cmd_id,
1469                             (zbee_zcl_fn_attr_data)dissect_zcl_tun_attr_data
1470                          );
1471 } /* proto_reg_handoff_zbee_zcl_tun */
1472
1473 /* ########################################################################## */
1474 /* #### (0x0800) KEY ESTABLISHMENT ########################################## */
1475 /* ########################################################################## */
1476
1477 /*************************/
1478 /* Defines               */
1479 /*************************/
1480
1481 /* Initialize the subtree pointers */
1482 static gint ett_zbee_zcl_ke = -1;
1483 static gint ett_zbee_zcl_ke_cert = -1;
1484 static gint ett_zbee_zcl_ke_key_usage = -1;
1485
1486 /* Attributes */
1487 #define ZBEE_ZCL_ATTR_ID_KE_SUITE                     0x0000  /* Key Establishment Suite */
1488
1489 /*************************/
1490 /* Function Declarations */
1491 /*************************/
1492
1493 void proto_register_zbee_zcl_ke(void);
1494 void proto_reg_handoff_zbee_zcl_ke(void);
1495
1496 /* Private functions prototype */
1497
1498 /*************************/
1499 /* Global Variables      */
1500 /*************************/
1501
1502 /* Initialize the protocol and registered fields */
1503 static int proto_zbee_zcl_ke = -1;
1504 static int hf_zbee_zcl_ke_srv_tx_cmd_id = -1;
1505 static int hf_zbee_zcl_ke_srv_rx_cmd_id = -1;
1506 static int hf_zbee_zcl_ke_attr_id = -1;
1507 static int hf_zbee_zcl_ke_suite = -1;
1508 static int hf_zbee_zcl_ke_ephemeral_time = -1;
1509 static int hf_zbee_zcl_ke_confirm_time = -1;
1510 static int hf_zbee_zcl_ke_status = -1;
1511 static int hf_zbee_zcl_ke_wait_time = -1;
1512 static int hf_zbee_zcl_ke_cert_reconstr = -1;
1513 static int hf_zbee_zcl_ke_cert_subject = -1;
1514 static int hf_zbee_zcl_ke_cert_issuer = -1;
1515 static int hf_zbee_zcl_ke_cert_profile_attr = -1;
1516 static int hf_zbee_zcl_ke_cert_type = -1;
1517 static int hf_zbee_zcl_ke_cert_serialno = -1;
1518 static int hf_zbee_zcl_ke_cert_curve = -1;
1519 static int hf_zbee_zcl_ke_cert_hash = -1;
1520 static int hf_zbee_zcl_ke_cert_valid_from = -1;
1521 static int hf_zbee_zcl_ke_cert_valid_to = -1;
1522 static int hf_zbee_zcl_ke_cert_key_usage_agreement = -1;
1523 static int hf_zbee_zcl_ke_cert_key_usage_signature = -1;
1524 static int hf_zbee_zcl_ke_ephemeral_qeu = -1;
1525 static int hf_zbee_zcl_ke_ephemeral_qev = -1;
1526 static int hf_zbee_zcl_ke_macu = -1;
1527 static int hf_zbee_zcl_ke_macv = -1;
1528
1529 /* Server Commands Received and Generates (symmetrical) */
1530 #define ZBEE_ZCL_CMD_ID_KE_INITIATE                     0x00  /* Initiate Key Establishment */
1531 #define ZBEE_ZCL_CMD_ID_KE_EPHEMERAL                    0x01  /* Ephemeral Data Request */
1532 #define ZBEE_ZCL_CMD_ID_KE_CONFIRM                      0x02  /* Confirm Key Data Request */
1533 #define ZBEE_ZCL_CMD_ID_KE_TERMINATE                    0x03  /* Terminate Key Establishment */
1534
1535 #define ZBEE_ZCL_KE_SUITE_1                           0x0001
1536 #define ZBEE_ZCL_KE_SUITE_2                           0x0002
1537
1538 #define ZBEE_ZCL_KE_TYPE_NO_EXT                         0x00  /* no extensions were used */
1539
1540 #define ZBEE_ZCL_KE_CURVE_SECT283K1                     0x0D
1541
1542 #define ZBEE_ZCL_KE_HASH_AES_MMO                        0x08
1543
1544 #define ZBEE_ZCL_KE_USAGE_KEY_AGREEMENT                 0x08
1545 #define ZBEE_ZCL_KE_USAGE_DIGITAL_SIGNATURE             0x80
1546
1547 /* Attributes */
1548 static const value_string zbee_zcl_ke_attr_names[] = {
1549     { ZBEE_ZCL_ATTR_ID_KE_SUITE,           "Supported Key Establishment Suites" },
1550     { 0, NULL }
1551 };
1552
1553 /* Server Commands Received and Generated */
1554 static const value_string zbee_zcl_ke_srv_cmd_names[] = {
1555     { ZBEE_ZCL_CMD_ID_KE_INITIATE,     "Initiate Key Establishment" },
1556     { ZBEE_ZCL_CMD_ID_KE_EPHEMERAL,    "Ephemeral Data" },
1557     { ZBEE_ZCL_CMD_ID_KE_CONFIRM,      "Confirm Key Data" },
1558     { ZBEE_ZCL_CMD_ID_KE_TERMINATE,    "Terminate Key Establishment" },
1559     { 0, NULL }
1560 };
1561
1562 /* Suite Names */
1563 static const value_string zbee_zcl_ke_suite_names[] = {
1564     { ZBEE_ZCL_KE_SUITE_1,                 "Crypto Suite 1 (CBKE K163)" },
1565     { ZBEE_ZCL_KE_SUITE_2,                 "Crypto Suite 2 (CBKE K283)" },
1566     { 0, NULL }
1567 };
1568
1569 /* Crypto Suite 2 Type Names */
1570 static const value_string zbee_zcl_ke_type_names[] = {
1571     { ZBEE_ZCL_KE_TYPE_NO_EXT,             "No Extensions" },
1572     { 0, NULL }
1573 };
1574
1575 /* Crypto Suite 2 Curve Names */
1576 static const value_string zbee_zcl_ke_curve_names[] = {
1577     { ZBEE_ZCL_KE_CURVE_SECT283K1,         "sect283k1" },
1578     { 0, NULL }
1579 };
1580
1581 /* Crypto Suite 2 Hash Names */
1582 static const value_string zbee_zcl_ke_hash_names[] = {
1583     { ZBEE_ZCL_KE_HASH_AES_MMO,            "AES MMO" },
1584     { 0, NULL }
1585 };
1586
1587 #define ZBEE_ZCL_KE_STATUS_RESERVED                     0x00
1588 #define ZBEE_ZCL_KE_STATUS_UNKNOWN_ISSUER               0x01
1589 #define ZBEE_ZCL_KE_STATUS_BAD_KEY_CONFIRM              0x02
1590 #define ZBEE_ZCL_KE_STATUS_BAD_MESSAGE                  0x03
1591 #define ZBEE_ZCL_KE_STATUS_NO_RESOURCES                 0x04
1592 #define ZBEE_ZCL_KE_STATUS_UNSUPPORTED_SUITE            0x05
1593 #define ZBEE_ZCL_KE_STATUS_INVALID_CERTIFICATE          0x06
1594
1595 static const value_string zbee_zcl_ke_status_names[] = {
1596     { ZBEE_ZCL_KE_STATUS_RESERVED,             "Reserved" },
1597     { ZBEE_ZCL_KE_STATUS_UNKNOWN_ISSUER,       "Unknown Issuer"},
1598     { ZBEE_ZCL_KE_STATUS_BAD_KEY_CONFIRM,      "Bad Key Confirm"},
1599     { ZBEE_ZCL_KE_STATUS_BAD_MESSAGE,          "Bad Message"},
1600     { ZBEE_ZCL_KE_STATUS_NO_RESOURCES,         "No Resources"},
1601     { ZBEE_ZCL_KE_STATUS_UNSUPPORTED_SUITE,    "Unsupported Suite"},
1602     { ZBEE_ZCL_KE_STATUS_INVALID_CERTIFICATE,  "Invalid Certificate"},
1603     { 0, NULL }
1604 };
1605
1606 /*************************/
1607 /* Function Bodies       */
1608 /*************************/
1609
1610
1611  /*FUNCTION:------------------------------------------------------
1612  *  NAME
1613  *      dissect_zcl_ke_suite1_certificate
1614  *  DESCRIPTION
1615  *      This function dissects the Suite 1 Certificate
1616  *  PARAMETERS
1617  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1618  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1619  *      offset              - offset
1620  *  RETURNS
1621  *      none
1622  *---------------------------------------------------------------
1623  */
1624 static void
1625 dissect_zcl_ke_suite1_certificate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1626 {
1627     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_reconstr, tvb, *offset, 22, ENC_NA);
1628     *offset += 22;
1629
1630     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_subject, tvb, *offset, 8, ENC_NA);
1631     *offset += 8;
1632
1633     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_issuer, tvb, *offset, 8, ENC_NA);
1634     *offset += 8;
1635
1636     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_profile_attr, tvb, *offset, 10, ENC_NA);
1637     *offset += 10;
1638
1639 } /*dissect_zcl_ke_suite1_certificate*/
1640
1641  /*FUNCTION:------------------------------------------------------
1642  *  NAME
1643  *      dissect_zcl_ke_suite2_certificate
1644  *  DESCRIPTION
1645  *      This function dissects the Suite 2 Certificate
1646  *  PARAMETERS
1647  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1648  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1649  *      offset              - offset
1650  *  RETURNS
1651  *      none
1652  *---------------------------------------------------------------
1653  */
1654 static void
1655 dissect_zcl_ke_suite2_certificate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1656 {
1657     nstime_t      valid_from_time;
1658     nstime_t      valid_to_time;
1659     guint32       valid_to;
1660     guint8        key_usage;
1661     proto_tree   *usage_tree;
1662
1663     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_type, tvb, *offset, 1, ENC_NA);
1664     *offset += 1;
1665
1666     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_serialno, tvb, *offset, 8, ENC_NA);
1667     *offset += 8;
1668
1669     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_curve, tvb, *offset, 1, ENC_NA);
1670     *offset += 1;
1671
1672     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_hash, tvb, *offset, 1, ENC_NA);
1673     *offset += 1;
1674
1675     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_issuer, tvb, *offset, 8, ENC_NA);
1676     *offset += 8;
1677
1678     valid_from_time.secs = (time_t)tvb_get_ntoh40(tvb, *offset);
1679     valid_from_time.nsecs = 0;
1680     proto_tree_add_time(tree, hf_zbee_zcl_ke_cert_valid_from, tvb, *offset, 5, &valid_from_time);
1681     *offset += 5;
1682
1683     valid_to = tvb_get_ntohl(tvb, *offset);
1684     if (valid_to == 0xFFFFFFFF) {
1685         proto_tree_add_time_format(tree, hf_zbee_zcl_ke_cert_valid_to, tvb, *offset, 4, &valid_to_time, "Valid To: does not expire (0xFFFFFFFF)");
1686     }
1687     else {
1688         valid_to_time.secs = valid_from_time.secs + valid_to;
1689         valid_to_time.nsecs = 0;
1690         proto_tree_add_time(tree, hf_zbee_zcl_ke_cert_valid_to, tvb, *offset, 4, &valid_to_time);
1691     }
1692     *offset += 4;
1693
1694     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_subject, tvb, *offset, 8, ENC_NA);
1695     *offset += 8;
1696
1697     key_usage = tvb_get_guint8(tvb, *offset);
1698     usage_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 1, ett_zbee_zcl_ke_key_usage, NULL, "Key Usage (0x%02x)", key_usage);
1699
1700     proto_tree_add_item(usage_tree, hf_zbee_zcl_ke_cert_key_usage_agreement, tvb, *offset, 1, ENC_NA);
1701     proto_tree_add_item(usage_tree, hf_zbee_zcl_ke_cert_key_usage_signature, tvb, *offset, 1, ENC_NA);
1702     *offset += 1;
1703
1704     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_reconstr, tvb, *offset, 37, ENC_NA);
1705     *offset += 37;
1706
1707 } /*dissect_zcl_ke_suite2_certificate*/
1708
1709  /*FUNCTION:------------------------------------------------------
1710  *  NAME
1711  *      dissect_zcl_ke_initiate_req
1712  *  DESCRIPTION
1713  *      This function manages the Initiate Key Establishment message
1714  *  PARAMETERS
1715  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1716  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1717  *      offset              - offset
1718  *  RETURNS
1719  *      none
1720  *---------------------------------------------------------------
1721  */
1722 static void
1723 dissect_zcl_ke_initiate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1724 {
1725     gint               rem_len;
1726     proto_tree        *subtree;
1727     guint16            suite;
1728
1729     suite = tvb_get_letohs(tvb, *offset);
1730
1731     proto_tree_add_item(tree, hf_zbee_zcl_ke_suite, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1732     *offset += 2;
1733
1734     proto_tree_add_item(tree, hf_zbee_zcl_ke_ephemeral_time, tvb, *offset, 1, ENC_NA);
1735     *offset += 1;
1736
1737     proto_tree_add_item(tree, hf_zbee_zcl_ke_confirm_time, tvb, *offset, 1, ENC_NA);
1738     *offset += 1;
1739
1740     rem_len = tvb_reported_length_remaining(tvb, *offset);
1741     subtree = proto_tree_add_subtree(tree, tvb, *offset, rem_len, ett_zbee_zcl_ke_cert, NULL, "Implicit Certificate");
1742
1743     switch (suite) {
1744         case ZBEE_ZCL_KE_SUITE_1:
1745             dissect_zcl_ke_suite1_certificate(tvb, subtree, offset);
1746             break;
1747
1748         case ZBEE_ZCL_KE_SUITE_2:
1749             dissect_zcl_ke_suite2_certificate(tvb, subtree, offset);
1750             break;
1751
1752         default:
1753             break;
1754     }
1755 } /* dissect_zcl_ke_initiate */
1756
1757  /*FUNCTION:------------------------------------------------------
1758  *  NAME
1759  *      dissect_zcl_ke_ephemeral_qeu
1760  *  DESCRIPTION
1761  *      This function dissects the Ephemeral Data QEU
1762  *  PARAMETERS
1763  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1764  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1765  *      offset              - offset
1766  *  RETURNS
1767  *      none
1768  *---------------------------------------------------------------
1769  */
1770 static int
1771 dissect_zcl_ke_ephemeral_qeu(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1772 {
1773     gint length;
1774
1775     /* size depends on suite but without a session we don't know that here */
1776     /* so just report what we have */
1777     length = tvb_reported_length_remaining(tvb, *offset);
1778     proto_tree_add_item(tree, hf_zbee_zcl_ke_ephemeral_qeu, tvb, *offset, length, ENC_NA);
1779     *offset += length;
1780     return tvb_captured_length(tvb);
1781 }
1782
1783  /*FUNCTION:------------------------------------------------------
1784  *  NAME
1785  *      dissect_zcl_ke_ephemeral_qev
1786  *  DESCRIPTION
1787  *      This function dissects the Ephemeral Data QEV
1788  *  PARAMETERS
1789  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1790  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1791  *      offset              - offset
1792  *  RETURNS
1793  *      none
1794  *---------------------------------------------------------------
1795  */
1796 static int
1797 dissect_zcl_ke_ephemeral_qev(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1798 {
1799     gint length;
1800
1801     /* size depends on suite but without a session we don't know that here */
1802     /* so just report what we have */
1803     length = tvb_reported_length_remaining(tvb, *offset);
1804     proto_tree_add_item(tree, hf_zbee_zcl_ke_ephemeral_qev, tvb, *offset, length, ENC_NA);
1805     *offset += length;
1806     return tvb_captured_length(tvb);
1807 }
1808
1809 /*FUNCTION:------------------------------------------------------
1810  *  NAME
1811  *      dissect_zcl_ke_confirm_macu
1812  *  DESCRIPTION
1813  *      This function dissects the Confirm MACU
1814  *  PARAMETERS
1815  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1816  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1817  *      offset              - offset
1818  *  RETURNS
1819  *      none
1820  *---------------------------------------------------------------
1821  */
1822 static int
1823 dissect_zcl_ke_confirm_macu(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1824 {
1825     proto_tree_add_item(tree, hf_zbee_zcl_ke_macu, tvb, *offset, ZBEE_SEC_CONST_BLOCKSIZE, ENC_NA);
1826     *offset += ZBEE_SEC_CONST_BLOCKSIZE;
1827     return tvb_captured_length(tvb);
1828 }
1829
1830  /*FUNCTION:------------------------------------------------------
1831  *  NAME
1832  *      dissect_zcl_ke_confirm_macv
1833  *  DESCRIPTION
1834  *      This function dissects the Confirm MACV
1835  *  PARAMETERS
1836  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1837  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1838  *      offset              - offset
1839  *  RETURNS
1840  *      none
1841  *---------------------------------------------------------------
1842  */
1843 static int
1844 dissect_zcl_ke_confirm_macv(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1845 {
1846     proto_tree_add_item(tree, hf_zbee_zcl_ke_macv, tvb, *offset, ZBEE_SEC_CONST_BLOCKSIZE, ENC_NA);
1847     *offset += ZBEE_SEC_CONST_BLOCKSIZE;
1848     return tvb_captured_length(tvb);
1849 }
1850
1851  /*FUNCTION:------------------------------------------------------
1852  *  NAME
1853  *      dissect_zcl_ke_terminate
1854  *  DESCRIPTION
1855  *      This function dissects the Terminate Key Establishment message
1856  *  PARAMETERS
1857  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1858  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1859  *      offset              - offset
1860  *  RETURNS
1861  *      none
1862  *---------------------------------------------------------------
1863  */
1864 static void
1865 dissect_zcl_ke_terminate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1866 {
1867     proto_tree_add_item(tree, hf_zbee_zcl_ke_status, tvb, *offset, 1, ENC_NA);
1868     *offset += 1;
1869
1870     proto_tree_add_item(tree, hf_zbee_zcl_ke_wait_time, tvb, *offset, 1, ENC_NA);
1871     *offset += 1;
1872
1873     proto_tree_add_item(tree, hf_zbee_zcl_ke_suite, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1874     *offset += 2;
1875 }
1876
1877 /*FUNCTION:------------------------------------------------------
1878  *  NAME
1879  *      dissect_zbee_zcl_ke
1880  *  DESCRIPTION
1881  *      ZigBee ZCL Key Establishment cluster dissector for wireshark.
1882  *  PARAMETERS
1883  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1884  *      packet_info *pinfo  - pointer to packet information fields
1885  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1886  *  RETURNS
1887  *      none
1888  *---------------------------------------------------------------
1889  */
1890 static int
1891 dissect_zbee_zcl_ke(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1892 {
1893     zbee_zcl_packet   *zcl;
1894     guint             offset = 0;
1895     guint8            cmd_id;
1896     gint              rem_len;
1897
1898     /* Reject the packet if data is NULL */
1899     if (data == NULL)
1900         return 0;
1901     zcl = (zbee_zcl_packet *)data;
1902     cmd_id = zcl->cmd_id;
1903
1904     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
1905     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
1906         /* Append the command name to the info column. */
1907         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1908             val_to_str_const(cmd_id, zbee_zcl_ke_srv_cmd_names, "Unknown Command"),
1909             zcl->tran_seqno);
1910
1911         /* Add the command ID. */
1912         proto_tree_add_item(tree, hf_zbee_zcl_ke_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
1913
1914         /* Check is this command has a payload, than add the payload tree */
1915         rem_len = tvb_reported_length_remaining(tvb, offset);
1916         offset += 1; /* delay from last add_item */
1917         if (rem_len > 0) {
1918
1919             /* Call the appropriate command dissector */
1920             switch (cmd_id) {
1921                 case ZBEE_ZCL_CMD_ID_KE_INITIATE:
1922                     dissect_zcl_ke_initiate(tvb, tree, &offset);
1923                     break;
1924
1925                 case ZBEE_ZCL_CMD_ID_KE_EPHEMERAL:
1926                     return dissect_zcl_ke_ephemeral_qeu(tvb, tree, &offset);
1927
1928                 case ZBEE_ZCL_CMD_ID_KE_CONFIRM:
1929                     return dissect_zcl_ke_confirm_macu(tvb, tree, &offset);
1930
1931                 case ZBEE_ZCL_CMD_ID_KE_TERMINATE:
1932                     dissect_zcl_ke_terminate(tvb, tree, &offset);
1933                     break;
1934
1935                 default:
1936                     break;
1937             }
1938         }
1939     }
1940     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
1941         /* Append the command name to the info column. */
1942         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1943             val_to_str_const(cmd_id, zbee_zcl_ke_srv_cmd_names, "Unknown Command"),
1944             zcl->tran_seqno);
1945
1946         /* Add the command ID. */
1947         proto_tree_add_item(tree, hf_zbee_zcl_ke_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
1948
1949         /* Check is this command has a payload, than add the payload tree */
1950         rem_len = tvb_reported_length_remaining(tvb, ++offset);
1951         if (rem_len > 0) {
1952             /* Call the appropriate command dissector */
1953             switch (cmd_id) {
1954                 case ZBEE_ZCL_CMD_ID_KE_INITIATE:
1955                     dissect_zcl_ke_initiate(tvb, tree, &offset);
1956                     break;
1957
1958                 case ZBEE_ZCL_CMD_ID_KE_EPHEMERAL:
1959                     return dissect_zcl_ke_ephemeral_qev(tvb, tree, &offset);
1960
1961                 case ZBEE_ZCL_CMD_ID_KE_CONFIRM:
1962                     return dissect_zcl_ke_confirm_macv(tvb, tree, &offset);
1963
1964                 case ZBEE_ZCL_CMD_ID_KE_TERMINATE:
1965                     dissect_zcl_ke_terminate(tvb, tree, &offset);
1966                     break;
1967
1968                 default:
1969                     break;
1970             }
1971         }
1972     }
1973
1974     return tvb_captured_length(tvb);
1975 } /*dissect_zbee_zcl_ke*/
1976
1977
1978 /*FUNCTION:------------------------------------------------------
1979  *  NAME
1980  *      proto_register_zbee_zcl_ke
1981  *  DESCRIPTION
1982  *      this function registers the ZCL Messaging dissector
1983  *      and all its information.
1984  *  PARAMETERS
1985  *      none
1986  *  RETURNS
1987  *      none
1988  *---------------------------------------------------------------
1989  */
1990 void
1991 proto_register_zbee_zcl_ke(void)
1992 {
1993     static hf_register_info hf[] = {
1994
1995         { &hf_zbee_zcl_ke_attr_id,
1996             { "Attribute", "zbee_zcl_se.ke.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_ke_attr_names),
1997             0x00, NULL, HFILL } },
1998
1999         { &hf_zbee_zcl_ke_srv_tx_cmd_id,
2000             { "Command", "zbee_zcl_se.ke.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_srv_cmd_names),
2001             0x00, NULL, HFILL } },
2002
2003         { &hf_zbee_zcl_ke_srv_rx_cmd_id,
2004             { "Command", "zbee_zcl_se.ke.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_srv_cmd_names),
2005             0x00, NULL, HFILL } },
2006
2007         { &hf_zbee_zcl_ke_suite,
2008             { "Key Establishment Suite", "zbee_zcl_se.ke.attr.suite", FT_UINT16, BASE_HEX, VALS(zbee_zcl_ke_suite_names),
2009             0x00, NULL, HFILL } },
2010
2011         { &hf_zbee_zcl_ke_ephemeral_time,
2012             { "Ephemeral Data Generate Time", "zbee_zcl_se.ke.init.ephemeral.time", FT_UINT8, BASE_DEC, NULL,
2013             0, NULL, HFILL } },
2014
2015         { &hf_zbee_zcl_ke_confirm_time,
2016             { "Confirm Key Generate Time", "zbee_zcl_se.ke.init.confirm.time", FT_UINT8, BASE_DEC, NULL,
2017             0, NULL, HFILL } },
2018
2019         { &hf_zbee_zcl_ke_status,
2020             { "Status", "zbee_zcl_se.ke.terminate.status", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_status_names),
2021             0x00, NULL, HFILL } },
2022
2023         { &hf_zbee_zcl_ke_wait_time,
2024             { "Wait Time", "zbee_zcl_se.ke.terminate.wait.time", FT_UINT8, BASE_DEC, NULL,
2025             0, NULL, HFILL } },
2026
2027         { &hf_zbee_zcl_ke_cert_reconstr,
2028             { "Public Key", "zbee_zcl_se.ke.cert.reconst", FT_BYTES, BASE_NONE, NULL,
2029             0, NULL, HFILL } },
2030
2031         { &hf_zbee_zcl_ke_cert_subject,
2032             { "Subject", "zbee_zcl_se.ke.cert.subject", FT_BYTES, BASE_NONE, NULL,
2033             0, NULL, HFILL } },
2034
2035         { &hf_zbee_zcl_ke_cert_issuer,
2036             { "Issuer", "zbee_zcl_se.ke.cert.issuer", FT_BYTES, BASE_NONE, NULL,
2037             0, NULL, HFILL } },
2038
2039         { &hf_zbee_zcl_ke_cert_profile_attr,
2040             { "Profile Attribute Data", "zbee_zcl_se.ke.cert.profile", FT_BYTES, BASE_NONE, NULL,
2041             0, NULL, HFILL } },
2042
2043         { &hf_zbee_zcl_ke_cert_type,
2044             { "Type", "zbee_zcl_se.ke.cert.type", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_type_names),
2045             0, NULL, HFILL } },
2046
2047         { &hf_zbee_zcl_ke_cert_serialno,
2048             { "Serial No", "zbee_zcl_se.ke.cert.type", FT_UINT64, BASE_HEX, NULL,
2049             0, NULL, HFILL } },
2050
2051         { &hf_zbee_zcl_ke_cert_curve,
2052             { "Curve", "zbee_zcl_se.ke.cert.curve", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_curve_names),
2053             0, NULL, HFILL } },
2054
2055         { &hf_zbee_zcl_ke_cert_hash,
2056             { "Hash", "zbee_zcl_se.ke.cert.hash", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_hash_names),
2057             0, NULL, HFILL } },
2058
2059         { &hf_zbee_zcl_ke_cert_valid_from,
2060             { "Valid From", "zbee_zcl_se.ke.cert.valid.from", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
2061             0, NULL, HFILL } },
2062
2063         { &hf_zbee_zcl_ke_cert_valid_to,
2064             { "Valid To", "zbee_zcl_se.ke.cert.valid.to", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
2065             0, NULL, HFILL } },
2066
2067         { &hf_zbee_zcl_ke_cert_key_usage_agreement,
2068             { "Key Agreement", "zbee_zcl_se.ke.cert.key.usage.agreement", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
2069             ZBEE_ZCL_KE_USAGE_KEY_AGREEMENT, NULL, HFILL }},
2070
2071         { &hf_zbee_zcl_ke_cert_key_usage_signature,
2072             { "Digital Signature", "zbee_zcl_se.ke.cert.key.usage.signature", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
2073             ZBEE_ZCL_KE_USAGE_DIGITAL_SIGNATURE, NULL, HFILL }},
2074
2075         { &hf_zbee_zcl_ke_ephemeral_qeu,
2076             { "Ephemeral Data (QEU)", "zbee_zcl_se.ke.qeu", FT_BYTES, BASE_NONE, NULL,
2077             0, NULL, HFILL } },
2078
2079         { &hf_zbee_zcl_ke_ephemeral_qev,
2080             { "Ephemeral Data (QEV)", "zbee_zcl_se.ke.qev", FT_BYTES, BASE_NONE, NULL,
2081             0, NULL, HFILL } },
2082
2083         { &hf_zbee_zcl_ke_macu,
2084             { "Message Authentication Code (MACU)", "zbee_zcl_se.ke.macu", FT_BYTES, BASE_NONE, NULL,
2085             0, NULL, HFILL } },
2086
2087         { &hf_zbee_zcl_ke_macv,
2088             { "Message Authentication Code (MACV)", "zbee_zcl_se.ke.macv", FT_BYTES, BASE_NONE, NULL,
2089             0, NULL, HFILL } },
2090     };
2091
2092     /* subtrees */
2093     gint *ett[] = {
2094         &ett_zbee_zcl_ke,
2095         &ett_zbee_zcl_ke_cert,
2096         &ett_zbee_zcl_ke_key_usage,
2097     };
2098
2099     /* Register the ZigBee ZCL Messaging cluster protocol name and description */
2100     proto_zbee_zcl_ke = proto_register_protocol("ZigBee ZCL Key Establishment", "ZCL Key Establishment", ZBEE_PROTOABBREV_ZCL_KE);
2101     proto_register_field_array(proto_zbee_zcl_ke, hf, array_length(hf));
2102     proto_register_subtree_array(ett, array_length(ett));
2103
2104     /* Register the ZigBee ZCL Messaging dissector. */
2105     new_register_dissector(ZBEE_PROTOABBREV_ZCL_KE, dissect_zbee_zcl_ke, proto_zbee_zcl_ke);
2106 } /*proto_register_zbee_zcl_ke*/
2107
2108 /*FUNCTION:------------------------------------------------------
2109  *  NAME
2110  *      proto_reg_handoff_zbee_zcl_ke
2111  *  DESCRIPTION
2112  *      Hands off the Zcl Key Establishment dissector.
2113  *  PARAMETERS
2114  *      none
2115  *  RETURNS
2116  *      void
2117  *---------------------------------------------------------------
2118  */
2119 void
2120 proto_reg_handoff_zbee_zcl_ke(void)
2121 {
2122     dissector_handle_t ke_handle;
2123
2124     /* Register our dissector with the ZigBee application dissectors. */
2125     ke_handle = find_dissector(ZBEE_PROTOABBREV_ZCL_KE);
2126     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_KE, ke_handle);
2127
2128     zbee_zcl_init_cluster(  proto_zbee_zcl_ke,
2129                             ett_zbee_zcl_ke,
2130                             ZBEE_ZCL_CID_KE,
2131                             hf_zbee_zcl_ke_attr_id,
2132                             hf_zbee_zcl_ke_srv_rx_cmd_id,
2133                             hf_zbee_zcl_ke_srv_tx_cmd_id,
2134                             NULL
2135                          );
2136 } /*proto_reg_handoff_zbee_zcl_ke*/
2137
2138 /*
2139  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2140  *
2141  * Local variables:
2142  * c-basic-offset: 4
2143  * tab-width: 8
2144  * indent-tabs-mode: nil
2145  * End:
2146  *
2147  * vi: set shiftwidth=4 tabstop=8 expandtab:
2148  * :indentSize=4:tabSize=8:noTabs=true:
2149  */