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