fixed integer overflow in zigbee timestamp conversion
[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_SE_ATTR_REPORT_PENDING                     0x00
45 #define ZBEE_ZCL_SE_ATTR_REPORT_COMPLETE                    0x01
46
47 static const value_string zbee_zcl_se_reporting_status_names[] = {
48     { ZBEE_ZCL_SE_ATTR_REPORT_PENDING,                   "Pending" },
49     { ZBEE_ZCL_SE_ATTR_REPORT_COMPLETE,                  "Complete" },
50     { 0, NULL }
51 };
52
53 /*************************/
54 /* Global Variables      */
55 /*************************/
56
57 /* ########################################################################## */
58 /* #### (0x0702) METERING CLUSTER ########################################## */
59 /* ########################################################################## */
60
61 /* Attributes */
62 #define zbee_zcl_met_attr_names_VALUE_STRING_LIST(XXX) \
63 /* Client: Notification AttributeSet / Server: Reading Information Set */ \
64     XXX(ZBEE_ZCL_ATTR_ID_MET_FUNC_NOTI_FLAGS_CUR_SUM_DEL,       0x0000, "Client: Functional Notification Flags / Server: Current Summation Delivered" ) \
65     XXX(ZBEE_ZCL_ATTR_ID_MET_NOT_FLAGS2_CUR_SUM_RECV,           0x0001, "Client: Notification Flag 2 / Server: Current Summation Received" ) \
66     XXX(ZBEE_ZCL_ATTR_ID_MET_NOT_FLAGS3_CUR_MAX_DE_DEL,         0x0002, "Client: Notification Flag 3 / Server: Current Max Demand Delivered" ) \
67     XXX(ZBEE_ZCL_ATTR_ID_MET_NOT_FLAGS4_CUR_MAX_DE_RECV,        0x0003, "Client: Notification Flag 4 / Server: Current Max Demand Received" ) \
68     XXX(ZBEE_ZCL_ATTR_ID_MET_NOT_FLAGS5_DFT_SUM,                0x0004, "Client: Notification Flag 5 / Server: DFTSummation" ) \
69     XXX(ZBEE_ZCL_ATTR_ID_MET_NOT_FLAGS6_DAI_FREE_TIME,          0x0005, "Client: Notification Flag 6 / Server: Daily Freeze Time" ) \
70     XXX(ZBEE_ZCL_ATTR_ID_MET_NOT_FLAGS7_POW_FAC,                0x0006, "Client: Notification Flag 7 / Server: Power Factor" ) \
71     XXX(ZBEE_ZCL_ATTR_ID_MET_NOT_FLAGS8_READ_SNAP_TIME,         0x0007, "Client: Notification Flag 8 / Server: Reading Snapshot Time" ) \
72     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_MAX_DEMAND_DEL_TIME,           0x0008, "Current Max Demand Delivered Time" ) \
73     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_MAX_DEMAND_RECV_TIME,          0x0009, "Current Max Demand Received Time" ) \
74     XXX(ZBEE_ZCL_ATTR_ID_MET_DEFAULT_UPDATE_PERIOD,             0x000A, "Default Update Period" ) \
75     XXX(ZBEE_ZCL_ATTR_ID_MET_FAST_POLL_UPDATE_PERIOD,           0x000B, "Fast Poll Update Period" ) \
76     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_BLOCK_PER_CON_DEL,             0x000C, "Current Block Period Consumption Delivered" ) \
77     XXX(ZBEE_ZCL_ATTR_ID_MET_DAILY_CON_TARGET,                  0x000D, "Daily Consumption Target" ) \
78     XXX(ZBEE_ZCL_ATTR_ID_MET_CURRENT_BLOCK,                     0x000E, "Current Block" ) \
79     XXX(ZBEE_ZCL_ATTR_ID_MET_PROFILE_INTERVAL_PERIOD,           0x000F, "Profile Interval Period" ) \
80 /*     XXX(ZBEE_ZCL_ATTR_ID_MET_DEPRECATED,                        0x0010, "Deprecated" }, */ \
81     XXX(ZBEE_ZCL_ATTR_ID_MET_PRESET_READING_TIME,               0x0011, "Preset Reading Time" ) \
82     XXX(ZBEE_ZCL_ATTR_ID_MET_VOLUME_PER_REPORT,                 0x0012, "Volume Per Report" ) \
83     XXX(ZBEE_ZCL_ATTR_ID_MET_FLOW_RESTRICTION,                  0x0013, "Flow Restriction" ) \
84     XXX(ZBEE_ZCL_ATTR_ID_MET_SUPPLY_STATUS,                     0x0014, "Supply Status" ) \
85     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_INLET_ENER_CAR_SUM,            0x0015, "Current Inlet Energy Carrier Summation" ) \
86     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_OUTLET_ENER_CAR_SUM,           0x0016, "Current Outlet Energy Carrier Summation" ) \
87     XXX(ZBEE_ZCL_ATTR_ID_MET_INLET_TEMPERATURE,                 0x0017, "Inlet Temperature" ) \
88     XXX(ZBEE_ZCL_ATTR_ID_MET_OUTLET_TEMPERATURE,                0x0018, "Outlet Temperature" ) \
89     XXX(ZBEE_ZCL_ATTR_ID_MET_CONTROL_TEMPERATURE,               0x0019, "Control Temperature" ) \
90     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_INLET_ENER_CAR_DEM,            0x001A, "Current Inlet Energy Carrier Demand" ) \
91     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_OUTLET_ENER_CAR_DEM,           0x001B, "Current Outlet Energy Carrier Demand" ) \
92     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_BLOCK_CON_DEL,                0x001C, "Previous Block Period Consumption Delivered" ) \
93     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_BLOCL_CON_RECV,               0x001D, "Current Block Period Consumption Received" ) \
94     XXX(ZBEE_ZCL_ATTR_ID_MET_CURRENT_BLOCK_RECEIVED,            0x001E, "Current Block Received" ) \
95     XXX(ZBEE_ZCL_ATTR_ID_MET_DFT_SUMMATION_RECEIVED,            0x001F, "DFT Summation Received" ) \
96     XXX(ZBEE_ZCL_ATTR_ID_MET_ACTIVE_REG_TIER_DEL,               0x0020, "Active Register Tier Delivered" ) \
97     XXX(ZBEE_ZCL_ATTR_ID_MET_ACTIVE_REG_TIER_RECV,              0x0021, "Active Register Tier Received" ) \
98     XXX(ZBEE_ZCL_ATTR_ID_MET_LAST_BLOCK_SWITCH_TIME,            0x0022, "Last Block Switch Time" ) \
99 /* Summation TOU Information Set */ \
100     XXX(ZBEE_ZCL_ATTR_ID_MET_CURRENT_TIER_1_SUM_DEL,            0x0100, "Current Tier 1 Summation Delivered" ) \
101     XXX(ZBEE_ZCL_ATTR_ID_MET_CURRENT_TIER_2_SUM_DEL,            0x0102, "Current Tier 2 Summation Delivered" ) \
102     XXX(ZBEE_ZCL_ATTR_ID_MET_CURRENT_TIER_3_SUM_DEL,            0x0104, "Current Tier 3 Summation Delivered" ) \
103     XXX(ZBEE_ZCL_ATTR_ID_MET_CURRENT_TIER_4_SUM_DEL,            0x0106, "Current Tier 4 Summation Delivered" ) \
104 /* Meter Status Attribute Set */ \
105     XXX(ZBEE_ZCL_ATTR_ID_MET_STATUS,                            0x0200, "Status" ) \
106     XXX(ZBEE_ZCL_ATTR_ID_MET_REMAIN_BAT_LIFE_DAYS,              0x0205, "Remaining Battery Life in Days" ) \
107     XXX(ZBEE_ZCL_ATTR_ID_MET_CURRENT_METER_ID,                  0x0206, "Current Meter ID" ) \
108     XXX(ZBEE_ZCL_ATTR_ID_MET_AMBIENT_CON_IND,                   0x0207, "Ambient Consumption Indicator" ) \
109 /* Formatting */ \
110     XXX(ZBEE_ZCL_ATTR_ID_MET_UNIT_OF_MEASURE,                   0x0300, "Unit of Measure" ) \
111     XXX(ZBEE_ZCL_ATTR_ID_MET_MULTIPLIER,                        0x0301, "Multiplier" ) \
112     XXX(ZBEE_ZCL_ATTR_ID_MET_DIVISOR,                           0x0302, "Divisor" ) \
113     XXX(ZBEE_ZCL_ATTR_ID_MET_SUMMATION_FORMATTING,              0x0303, "Summation Formatting" ) \
114     XXX(ZBEE_ZCL_ATTR_ID_MET_METERING_DEVICE_TYPE,              0x0306, "Metering Device Type" ) \
115     XXX(ZBEE_ZCL_ATTR_ID_MET_SITE_ID,                           0x0307, "Site ID" ) \
116     XXX(ZBEE_ZCL_ATTR_ID_MET_CUSTOMER_ID_NUMBER,                0x0311, "Customer ID Number" ) \
117     XXX(ZBEE_ZCL_ATTR_ID_MET_ALT_UNIT_OF_MEASURE,               0x0312, "Alternative Unit of Measure" ) \
118     XXX(ZBEE_ZCL_ATTR_ID_MET_ALT_CON_FORMATTING,                0x0314, "Alternative Consumption Formatting" ) \
119 /* Historical Consumption Attribute */ \
120     XXX(ZBEE_ZCL_ATTR_ID_MET_INSTANT_DEMAND,                    0x0400, "Instantaneous Demand" ) \
121     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_DAY_CON_DEL,                   0x0401, "Current Day Consumption Delivered" ) \
122     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_CON_DEL,                  0x0403, "Previous Day Consumption Delivered" ) \
123     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_2_DAY_CON_DEL,                0x0420, "Previous Day 2 Consumption Delivered" ) \
124     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_3_DAY_CON_DEL,                0x0422, "Previous Day 3 Consumption Delivered" ) \
125     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_4_DAY_CON_DEL,                0x0424, "Previous Day 4 Consumption Delivered" ) \
126     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_5_DAY_CON_DEL,                0x0426, "Previous Day 5 Consumption Delivered" ) \
127     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_6_DAY_CON_DEL,                0x0428, "Previous Day 6 Consumption Delivered" ) \
128     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_7_DAY_CON_DEL,                0x042A, "Previous Day 7 Consumption Delivered" ) \
129     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_8_DAY_CON_DEL,                0x042C, "Previous Day 8 Consumption Delivered" ) \
130     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_WEEK_CON_DEL,                  0x0430, "Current Week Consumption Delivered" ) \
131     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_CON_DEL,                 0x0432, "Previous Week Consumption Delivered" ) \
132     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_2_CON_DEL,               0x0434, "Previous Week 2 Consumption Delivered" ) \
133     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_3_CON_DEL,               0x0436, "Previous Week 3 Consumption Delivered" ) \
134     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_4_CON_DEL,               0x0438, "Previous Week 4 Consumption Delivered" ) \
135     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_5_CON_DEL,               0x043A, "Previous Week 5 Consumption Delivered" ) \
136     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_MONTH_CON_DEL,                 0x0440, "Current Month Consumption Delivered" ) \
137     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_CON_DEL,                0x0442, "Previous Month Consumption Delivered" ) \
138     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_2_CON_DEL,              0x0444, "Previous Month 2 Consumption Delivered" ) \
139     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_3_CON_DEL,              0x0446, "Previous Month 3 Consumption Delivered" ) \
140     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_4_CON_DEL,              0x0448, "Previous Month 4 Consumption Delivered" ) \
141     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_5_CON_DEL,              0x044A, "Previous Month 5 Consumption Delivered" ) \
142     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_6_CON_DEL,              0x044C, "Previous Month 6 Consumption Delivered" ) \
143     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_7_CON_DEL,              0x044E, "Previous Month 7 Consumption Delivered" ) \
144     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_8_CON_DEL,              0x0450, "Previous Month 8 Consumption Delivered" ) \
145     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_9_CON_DEL,              0x0452, "Previous Month 9 Consumption Delivered" ) \
146     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_10_CON_DEL,             0x0454, "Previous Month 10 Consumption Delivered" ) \
147     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_11_CON_DEL,             0x0456, "Previous Month 11 Consumption Delivered" ) \
148     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_12_CON_DEL,             0x0458, "Previous Month 12 Consumption Delivered" ) \
149     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_13_CON_DEL,             0x045A, "Previous Month 13 Consumption Delivered" ) \
150 /* Supply Limit Attributes */ \
151     XXX(ZBEE_ZCL_ATTR_ID_MET_SUPPLY_TAMPER_STATE,               0x0607, "Supply Tamper State" ) \
152     XXX(ZBEE_ZCL_ATTR_ID_MET_SUPPLY_DEPLETION_STATE,            0x0608, "Supply Depletion State" ) \
153 /* Block Information Attribute Set (Delivered) */ \
154     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_NO_TIER_BLOCK_1_SUM_DEL,       0x0700, "Current No Tier Block 1 Summation Delivered" ) \
155     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_NO_TIER_BLOCK_2_SUM_DEL,       0x0701, "Current No Tier Block 2 Summation Delivered" ) \
156     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_NO_TIER_BLOCK_3_SUM_DEL,       0x0702, "Current No Tier Block 3 Summation Delivered" ) \
157     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_NO_TIER_BLOCK_4_SUM_DEL,       0x0703, "Current No Tier Block 4 Summation Delivered" ) \
158     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_1_BLOCK_1_SUM_DEL,        0x0710, "Current Tier 1 Block 1 Summation Delivered" ) \
159     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_1_BLOCK_2_SUM_DEL,        0x0711, "Current Tier 1 Block 2 Summation Delivered" ) \
160     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_1_BLOCK_3_SUM_DEL,        0x0712, "Current Tier 1 Block 3 Summation Delivered" ) \
161     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_1_BLOCK_4_SUM_DEL,        0x0713, "Current Tier 1 Block 4 Summation Delivered" ) \
162     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_2_BLOCK_1_SUM_DEL,        0x0720, "Current Tier 2 Block 1 Summation Delivered" ) \
163     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_2_BLOCK_2_SUM_DEL,        0x0721, "Current Tier 2 Block 2 Summation Delivered" ) \
164     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_2_BLOCK_3_SUM_DEL,        0x0722, "Current Tier 2 Block 3 Summation Delivered" ) \
165     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_2_BLOCK_4_SUM_DEL,        0x0723, "Current Tier 2 Block 4 Summation Delivered" ) \
166     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_3_BLOCK_1_SUM_DEL,        0x0730, "Current Tier 3 Block 1 Summation Delivered" ) \
167     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_3_BLOCK_2_SUM_DEL,        0x0731, "Current Tier 3 Block 2 Summation Delivered" ) \
168     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_3_BLOCK_3_SUM_DEL,        0x0732, "Current Tier 3 Block 3 Summation Delivered" ) \
169     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_3_BLOCK_4_SUM_DEL,        0x0733, "Current Tier 3 Block 4 Summation Delivered" ) \
170     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_4_BLOCK_1_SUM_DEL,        0x0740, "Current Tier 4 Block 1 Summation Delivered" ) \
171     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_4_BLOCK_2_SUM_DEL,        0x0741, "Current Tier 4 Block 2 Summation Delivered" ) \
172     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_4_BLOCK_3_SUM_DEL,        0x0742, "Current Tier 4 Block 3 Summation Delivered" ) \
173     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_TIER_4_BLOCK_4_SUM_DEL,        0x0743, "Current Tier 4 Block 4 Summation Delivered" ) \
174 /* Meter Billing Attribute Set */ \
175     XXX(ZBEE_ZCL_ATTR_ID_MET_BILL_TO_DATE_DELIVERED,            0x0A00, "Bill To Date Delivered" ) \
176     XXX(ZBEE_ZCL_ATTR_ID_MET_BILL_TO_DATE_TIMESTAMP_DEL,        0x0A01, "BillToDateTimeStampDelivered" ) \
177     XXX(ZBEE_ZCL_ATTR_ID_MET_BILL_DELIVERED_TRAILING_DIGIT,     0x0A04, "Bill Delivered Trailing Digit" ) \
178 /* Alternative Historical Consumption Attribute Set */ \
179     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_DAY_ALT_CON_DEL,               0x0C01, "Current Day Alternative Consumption Delivered" ) \
180     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_ALT_CON_DEL,              0x0C03, "Previous Day Alternative Consumption Delivered" ) \
181     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_2_ALT_CON_DEL,            0x0C20, "Previous Day 2 Alternative Consumption Delivered" ) \
182     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_3_ALT_CON_DEL,            0x0C22, "Previous Day 3 Alternative Consumption Delivered" ) \
183     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_4_ALT_CON_DEL,            0x0C24, "Previous Day 4 Alternative Consumption Delivered" ) \
184     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_5_ALT_CON_DEL,            0x0C26, "Previous Day 5 Alternative Consumption Delivered" ) \
185     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_6_ALT_CON_DEL,            0x0C28, "Previous Day 6 Alternative Consumption Delivered" ) \
186     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_7_ALT_CON_DEL,            0x0C2A, "Previous Day 7 Alternative Consumption Delivered" ) \
187     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_DAY_8_ALT_CON_DEL,            0x0C2C, "Previous Day 8 Alternative Consumption Delivered" ) \
188     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_WEEK_ALT_CON_DEL,              0x0C30, "Current Week Alternative Consumption Delivered" ) \
189     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_ALT_CON_DEL,             0x0C32, "Previous Week Alternative Consumption Delivered" ) \
190     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_2_ALT_CON_DEL,           0x0C34, "Previous Week 2 Alternative Consumption Delivered" ) \
191     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_3_ALT_CON_DEL,           0x0C36, "Previous Week 3 Alternative Consumption Delivered" ) \
192     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_4_ALT_CON_DEL,           0x0C38, "Previous Week 4 Alternative Consumption Delivered" ) \
193     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_WEEK_5_ALT_CON_DEL,           0x0C3A, "Previous Week 5 Alternative Consumption Delivered" ) \
194     XXX(ZBEE_ZCL_ATTR_ID_MET_CUR_MONTH_ALT_CON_DEL,             0x0C40, "Current Month Alternative Consumption Delivered" ) \
195     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_ALT_CON_DEL,            0x0C42, "Previous Month Alternative Consumption Delivered" ) \
196     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_2_ALT_CON_DEL,          0x0C44, "Previous Month 2 Alternative Consumption Delivered" ) \
197     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_3_ALT_CON_DEL,          0x0C46, "Previous Month 3 Alternative Consumption Delivered" ) \
198     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_4_ALT_CON_DEL,          0x0C48, "Previous Month 4 Alternative Consumption Delivered" ) \
199     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_5_ALT_CON_DEL,          0x0C4A, "Previous Month 5 Alternative Consumption Delivered" ) \
200     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_6_ALT_CON_DEL,          0x0C4C, "Previous Month 6 Alternative Consumption Delivered" ) \
201     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_7_ALT_CON_DEL,          0x0C4E, "Previous Month 7 Alternative Consumption Delivered" ) \
202     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_8_ALT_CON_DEL,          0x0C50, "Previous Month 8 Alternative Consumption Delivered" ) \
203     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_9_ALT_CON_DEL,          0x0C52, "Previous Month 9 Alternative Consumption Delivered" ) \
204     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_10_ALT_CON_DEL,         0x0C54, "Previous Month 10 Alternative Consumption Delivered" ) \
205     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_11_ALT_CON_DEL,         0x0C56, "Previous Month 11 Alternative Consumption Delivered" ) \
206     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_12_ALT_CON_DEL,         0x0C58, "Previous Month 12 Alternative Consumption Delivered" ) \
207     XXX(ZBEE_ZCL_ATTR_ID_MET_PREV_MONTH_13_ALT_CON_DEL,         0x0C5A, "Previous Month 13 Alternative Consumption Delivered" ) \
208 /* Smart Energy */ \
209     XXX(ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_MET,             0xFFFE, "Attribute Reporting Status" )
210
211 VALUE_STRING_ENUM(zbee_zcl_met_attr_names);
212 VALUE_STRING_ARRAY(zbee_zcl_met_attr_names);
213 static value_string_ext zbee_zcl_met_attr_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_met_attr_names);
214
215 /* Server Commands Received */
216 #define zbee_zcl_met_srv_rx_cmd_names_VALUE_STRING_LIST(XXX) \
217     XXX(ZBEE_ZCL_CMD_ID_MET_REQUEST_MIRROR_RSP,                 0x01, "Request Mirror Response" ) \
218     XXX(ZBEE_ZCL_CMD_ID_MET_GET_SNAPSHOT,                       0x06, "Get Snapshot" ) \
219     XXX(ZBEE_ZCL_CMD_ID_MET_GET_SAMPLED_DATA,                   0x08, "Get Sampled Data" ) \
220     XXX(ZBEE_ZCL_CMD_ID_MET_LOCAL_CHANGE_SUPPLY,                0x0C, "Local Change Supply" )
221
222 VALUE_STRING_ENUM(zbee_zcl_met_srv_rx_cmd_names);
223 VALUE_STRING_ARRAY(zbee_zcl_met_srv_rx_cmd_names);
224
225 /* Server Commands Generated */
226 #define zbee_zcl_met_srv_tx_cmd_names_VALUE_STRING_LIST(XXX) \
227     XXX(ZBEE_ZCL_CMD_ID_MET_REQUEST_MIRROR,                     0x01, "Request Mirror" ) \
228     XXX(ZBEE_ZCL_CMD_ID_MET_PUBLISH_SNAPSHOT,                   0x06, "Publish Snapshot" ) \
229     XXX(ZBEE_ZCL_CMD_ID_MET_GET_SAMPLED_DATA_RSP,               0x07, "Get Sampled Data Response" ) \
230     XXX(ZBEE_ZCL_CMD_ID_MET_CONFIGURE_MIRROR,                   0x08, "Configure Mirror" ) \
231     XXX(ZBEE_ZCL_CMD_ID_MET_GET_NOTIFIED_MESSAGE,               0x0B, "Get Notified Message" )
232
233 VALUE_STRING_ENUM(zbee_zcl_met_srv_tx_cmd_names);
234 VALUE_STRING_ARRAY(zbee_zcl_met_srv_tx_cmd_names);
235
236 /*************************/
237 /* Function Declarations */
238 /*************************/
239 void proto_register_zbee_zcl_met(void);
240 void proto_reg_handoff_zbee_zcl_met(void);
241
242 /* Attribute Dissector Helpers */
243 static void dissect_zcl_met_attr_data  (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type);
244
245 /*************************/
246 /* Global Variables      */
247 /*************************/
248
249 static dissector_handle_t met_handle;
250
251 /* Initialize the protocol and registered fields */
252 static int proto_zbee_zcl_met = -1;
253
254 static int hf_zbee_zcl_met_srv_tx_cmd_id = -1;
255 static int hf_zbee_zcl_met_srv_rx_cmd_id = -1;
256 static int hf_zbee_zcl_met_attr_id = -1;
257 static int hf_zbee_zcl_met_attr_reporting_status = -1;
258
259 /* Initialize the subtree pointers */
260 static gint ett_zbee_zcl_met = -1;
261
262 /*************************/
263 /* Function Bodies       */
264 /*************************/
265
266 /**
267  *This function is called by ZCL foundation dissector in order to decode
268  *
269  *@param tree pointer to data tree Wireshark uses to display packet.
270  *@param tvb pointer to buffer containing raw packet.
271  *@param offset pointer to buffer offset
272  *@param attr_id attribute identifier
273  *@param data_type attribute data type
274 */
275 static void
276 dissect_zcl_met_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type)
277 {
278     switch (attr_id) {
279         /* applies to all SE clusters */
280         case ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_MET:
281             proto_tree_add_item(tree, hf_zbee_zcl_met_attr_reporting_status, tvb, *offset, 1, ENC_NA);
282             *offset += 1;
283             break;
284
285         default: /* Catch all */
286             dissect_zcl_attr_data(tvb, tree, offset, data_type);
287             break;
288     }
289 } /*dissect_zcl_met_attr_data*/
290
291 /**
292  *ZigBee ZCL Metering cluster dissector for wireshark.
293  *
294  *@param tvb pointer to buffer containing raw packet.
295  *@param pinfo pointer to packet information fields
296  *@param tree pointer to data tree Wireshark uses to display packet.
297 */
298 static int
299 dissect_zbee_zcl_met(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
300 {
301     zbee_zcl_packet   *zcl;
302     guint             offset = 0;
303     guint8            cmd_id;
304     gint              rem_len;
305
306     /* Reject the packet if data is NULL */
307     if (data == NULL)
308         return 0;
309     zcl = (zbee_zcl_packet *)data;
310     cmd_id = zcl->cmd_id;
311
312     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
313     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
314         /* Append the command name to the info column. */
315         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
316             val_to_str_const(cmd_id, zbee_zcl_met_srv_rx_cmd_names, "Unknown Command"),
317             zcl->tran_seqno);
318
319         /* Add the command ID. */
320         proto_tree_add_uint(tree, hf_zbee_zcl_met_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
321
322         /* Check is this command has a payload, than add the payload tree */
323         rem_len = tvb_reported_length_remaining(tvb, ++offset);
324         if (rem_len > 0) {
325             proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_met, NULL, "Payload");
326
327             /* Call the appropriate command dissector */
328             switch (cmd_id) {
329
330                 case ZBEE_ZCL_CMD_ID_MET_REQUEST_MIRROR_RSP:
331                     /* Add function to dissect payload */
332                     break;
333
334                 case ZBEE_ZCL_CMD_ID_MET_GET_SNAPSHOT:
335                     /* Add function to dissect payload */
336                     break;
337
338                 case ZBEE_ZCL_CMD_ID_MET_GET_SAMPLED_DATA:
339                     /* Add function to dissect payload */
340                     break;
341
342                 case ZBEE_ZCL_CMD_ID_MET_LOCAL_CHANGE_SUPPLY:
343                     /* Add function to dissect payload */
344                     break;
345
346                 default:
347                     break;
348             }
349         }
350     }
351     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
352         /* Append the command name to the info column. */
353         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
354             val_to_str_const(cmd_id, zbee_zcl_met_srv_tx_cmd_names, "Unknown Command"),
355             zcl->tran_seqno);
356
357         /* Add the command ID. */
358         proto_tree_add_uint(tree, hf_zbee_zcl_met_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
359
360         /* Check is this command has a payload, than add the payload tree */
361         rem_len = tvb_reported_length_remaining(tvb, ++offset);
362         if (rem_len > 0) {
363             proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_met, NULL, "Payload");
364
365             /* Call the appropriate command dissector */
366             switch (cmd_id) {
367
368                 case ZBEE_ZCL_CMD_ID_MET_REQUEST_MIRROR:
369                     /* No payload */
370                     break;
371
372                 case ZBEE_ZCL_CMD_ID_MET_PUBLISH_SNAPSHOT:
373                     /* Add function to dissect payload */
374                     break;
375
376                 case ZBEE_ZCL_CMD_ID_MET_GET_SAMPLED_DATA_RSP:
377                     /* Add function to dissect payload */
378                     break;
379
380                 case ZBEE_ZCL_CMD_ID_MET_CONFIGURE_MIRROR:
381                     /* Add function to dissect payload */
382                     break;
383
384                 case ZBEE_ZCL_CMD_ID_MET_GET_NOTIFIED_MESSAGE:
385                     /* Add function to dissect payload */
386                     break;
387
388                 default:
389                     break;
390             }
391         }
392     }
393
394     return tvb_captured_length(tvb);
395 } /*dissect_zbee_zcl_met*/
396
397 /**
398  *This function registers the ZCL Metering dissector
399  *
400 */
401 void
402 proto_register_zbee_zcl_met(void)
403 {
404     static hf_register_info hf[] = {
405
406         { &hf_zbee_zcl_met_attr_id,
407             { "Attribute", "zbee_zcl_se.met.attr_id", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &zbee_zcl_met_attr_names_ext,
408             0x0, NULL, HFILL } },
409
410         { &hf_zbee_zcl_met_attr_reporting_status,                         /* common to all SE clusters */
411             { "Attribute Reporting Status", "zbee_zcl_se.met.attr.attr_reporting_status",
412             FT_UINT8, BASE_HEX, VALS(zbee_zcl_se_reporting_status_names), 0x00, NULL, HFILL } },
413
414         { &hf_zbee_zcl_met_srv_tx_cmd_id,
415             { "Command", "zbee_zcl_se.met.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_met_srv_tx_cmd_names),
416             0x00, NULL, HFILL } },
417
418         { &hf_zbee_zcl_met_srv_rx_cmd_id,
419             { "Command", "zbee_zcl_se.met.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_met_srv_rx_cmd_names),
420             0x00, NULL, HFILL } },
421
422     };
423
424     /* ZCL Metering subtrees */
425     gint *ett[] = {
426         &ett_zbee_zcl_met,
427     };
428
429     /* Register the ZigBee ZCL Metering cluster protocol name and description */
430     proto_zbee_zcl_met = proto_register_protocol("ZigBee ZCL Metering", "ZCL Metering", ZBEE_PROTOABBREV_ZCL_MET);
431     proto_register_field_array(proto_zbee_zcl_met, hf, array_length(hf));
432     proto_register_subtree_array(ett, array_length(ett));
433
434     /* Register the ZigBee ZCL Metering dissector. */
435     met_handle = register_dissector(ZBEE_PROTOABBREV_ZCL_MET, dissect_zbee_zcl_met, proto_zbee_zcl_met);
436 } /*proto_register_zbee_zcl_met*/
437
438 /**
439  *Hands off the Zcl Metering dissector.
440  *
441 */
442 void
443 proto_reg_handoff_zbee_zcl_met(void)
444 {
445     /* Register our dissector with the ZigBee application dissectors. */
446     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_SIMPLE_METERING, met_handle);
447
448     zbee_zcl_init_cluster(  proto_zbee_zcl_met,
449                             ett_zbee_zcl_met,
450                             ZBEE_ZCL_CID_SIMPLE_METERING,
451                             hf_zbee_zcl_met_attr_id,
452                             hf_zbee_zcl_met_srv_rx_cmd_id,
453                             hf_zbee_zcl_met_srv_tx_cmd_id,
454                             (zbee_zcl_fn_attr_data)dissect_zcl_met_attr_data
455                          );
456 } /*proto_reg_handoff_zbee_zcl_met*/
457
458 /* ########################################################################## */
459 /* #### (0x0703) MESSAGING CLUSTER ########################################## */
460 /* ########################################################################## */
461
462 /* Attributes - None (other than Attribute Reporting Status) */
463 #define zbee_zcl_msg_attr_names_VALUE_STRING_LIST(XXX) \
464 /* Smart Energy */ \
465     XXX(ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_MSG,     0xFFFE, "Attribute Reporting Status" )
466
467 VALUE_STRING_ENUM(zbee_zcl_msg_attr_names);
468 VALUE_STRING_ARRAY(zbee_zcl_msg_attr_names);
469
470 /* Server Commands Received */
471 #define zbee_zcl_msg_srv_rx_cmd_names_VALUE_STRING_LIST(XXX) \
472     XXX(ZBEE_ZCL_CMD_ID_MSG_GET_LAST_MSG,               0x00, "Get Last Message" ) \
473     XXX(ZBEE_ZCL_CMD_ID_MSG_MSG_CONFIRM,                0x01, "Message Confirmation" ) \
474     XXX(ZBEE_ZCL_CMD_ID_MSG_GET_MESSAGE_CANCEL,         0x02, "Get Message Cancellation" )
475
476 VALUE_STRING_ENUM(zbee_zcl_msg_srv_rx_cmd_names);
477 VALUE_STRING_ARRAY(zbee_zcl_msg_srv_rx_cmd_names);
478
479 /* Server Commands Generated */
480 #define zbee_zcl_msg_srv_tx_cmd_names_VALUE_STRING_LIST(XXX) \
481     XXX(ZBEE_ZCL_CMD_ID_MSG_DISPLAY_MSG,                0x00, "Display Message" ) \
482     XXX(ZBEE_ZCL_CMD_ID_MSG_CANCEL_MSG,                 0x01, "Cancel Message" ) \
483     XXX(ZBEE_ZCL_CMD_ID_MSG_DISPLAY_PROTECTED_MSG,      0x02, "Display Protected Message" ) \
484     XXX(ZBEE_ZCL_CMD_ID_MSG_CANCEL_ALL_MSG,             0x03, "Cancel All Messages" )
485
486 VALUE_STRING_ENUM(zbee_zcl_msg_srv_tx_cmd_names);
487 VALUE_STRING_ARRAY(zbee_zcl_msg_srv_tx_cmd_names);
488
489 /* Message Control Field Bit Map */
490 #define ZBEE_ZCL_MSG_CTRL_TX_MASK                       0x03
491 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MASK               0x0C
492 #define ZBEE_ZCL_MSG_CTRL_RESERVED_MASK                 0x50
493 #define ZBEE_ZCL_MSG_CTRL_ENHANCED_CONFIRM_MASK         0x20
494 #define ZBEE_ZCL_MSG_CTRL_CONFIRM_MASK                  0x80
495
496 #define ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ONLY                0x00 /* Normal Transmission Only */
497 #define ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ANON_INTERPAN       0x01 /* Normal and Anonymous Inter-PAN Transmission Only */
498 #define ZBEE_ZCL_MSG_CTRL_TX_ANON_INTERPAN_ONLY         0x02 /* Anonymous Inter-PAN Transmission Only */
499
500 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_LOW                0x00 /* Low */
501 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MEDIUM             0x01 /* Medium */
502 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_HIGH               0x02 /* High */
503 #define ZBEE_ZCL_MSG_CTRL_IMPORTANCE_CRITICAL           0x03 /* Critical */
504
505 #define ZBEE_ZCL_MSG_EXT_CTRL_STATUS_MASK               0x01
506
507 #define ZBEE_ZCL_MSG_CONFIRM_CTRL_MASK                  0x01
508
509 #define ZBEE_ZCL_MSG_START_TIME_NOW                     0x00000000 /* Now */
510
511 /*************************/
512 /* Function Declarations */
513 /*************************/
514 void proto_register_zbee_zcl_msg(void);
515 void proto_reg_handoff_zbee_zcl_msg(void);
516
517 /* Attribute Dissector Helpers */
518 static void dissect_zcl_msg_attr_data  (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type);
519
520 /* Command Dissector Helpers */
521 static void dissect_zcl_msg_display             (tvbuff_t *tvb, proto_tree *tree, guint *offset);
522 static void dissect_zcl_msg_cancel              (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset);
523 static void dissect_zcl_msg_confirm             (tvbuff_t *tvb, proto_tree *tree, guint *offset);
524 static void dissect_zcl_msg_cancel_all          (tvbuff_t *tvb, proto_tree *tree, guint *offset);
525 static void dissect_zcl_msg_get_cancel          (tvbuff_t *tvb, proto_tree *tree, guint *offset);
526
527 /* Private functions prototype */
528 static void decode_zcl_msg_duration             (gchar *s, guint16 value);
529
530 /*************************/
531 /* Global Variables      */
532 /*************************/
533
534 static dissector_handle_t msg_handle;
535
536 /* Initialize the protocol and registered fields */
537 static int proto_zbee_zcl_msg = -1;
538
539 static int hf_zbee_zcl_msg_srv_tx_cmd_id = -1;
540 static int hf_zbee_zcl_msg_srv_rx_cmd_id = -1;
541 static int hf_zbee_zcl_msg_attr_id = -1;
542 static int hf_zbee_zcl_msg_attr_reporting_status = -1;
543 static int hf_zbee_zcl_msg_message_id = -1;
544 static int hf_zbee_zcl_msg_ctrl = -1;
545 static int hf_zbee_zcl_msg_ctrl_tx = -1;
546 static int hf_zbee_zcl_msg_ctrl_importance = -1;
547 static int hf_zbee_zcl_msg_ctrl_enh_confirm = -1;
548 static int hf_zbee_zcl_msg_ctrl_reserved = -1;
549 static int hf_zbee_zcl_msg_ctrl_confirm = -1;
550 static int hf_zbee_zcl_msg_ext_ctrl = -1;
551 static int hf_zbee_zcl_msg_ext_ctrl_status = -1;
552 static int hf_zbee_zcl_msg_start_time = -1;
553 static int hf_zbee_zcl_msg_duration = -1;
554 static int hf_zbee_zcl_msg_message_length = - 1;
555 static int hf_zbee_zcl_msg_message = -1;
556 static int hf_zbee_zcl_msg_confirm_time = -1;
557 static int hf_zbee_zcl_msg_confirm_ctrl = -1;
558 static int hf_zbee_zcl_msg_confirm_response = -1;
559 static int hf_zbee_zcl_msg_confirm_response_length = - 1;
560 static int hf_zbee_zcl_msg_implementation_time = -1;
561 static int hf_zbee_zcl_msg_earliest_time = -1;
562
563 /* Initialize the subtree pointers */
564 static gint ett_zbee_zcl_msg = -1;
565 static gint ett_zbee_zcl_msg_message_control = -1;
566 static gint ett_zbee_zcl_msg_ext_message_control = -1;
567
568 static expert_field ei_zbee_zcl_msg_msg_ctrl_depreciated = EI_INIT;
569
570 /* Message Control Transmission */
571 static const value_string zbee_zcl_msg_ctrl_tx_names[] = {
572     { ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ONLY,                 "Normal Transmission Only" },
573     { ZBEE_ZCL_MSG_CTRL_TX_NORMAL_ANON_INTERPAN,        "Normal and Anonymous Inter-PAN Transmission Only" },
574     { ZBEE_ZCL_MSG_CTRL_TX_ANON_INTERPAN_ONLY,          "Anonymous Inter-PAN Transmission Only" },
575     { 0, NULL }
576 };
577
578 /* Message Control Importance */
579 static const value_string zbee_zcl_msg_ctrl_importance_names[] = {
580     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_LOW,                 "Low" },
581     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MEDIUM,              "Medium" },
582     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_HIGH,                "High" },
583     { ZBEE_ZCL_MSG_CTRL_IMPORTANCE_CRITICAL,            "Critical" },
584     { 0, NULL }
585 };
586
587 /*************************/
588 /* Function Bodies       */
589 /*************************/
590
591 /**
592  *This function is called by ZCL foundation dissector in order to decode
593  *
594  *@param tree pointer to data tree Wireshark uses to display packet.
595  *@param tvb pointer to buffer containing raw packet.
596  *@param offset pointer to buffer offset
597  *@param attr_id attribute identifier
598  *@param data_type attribute data type
599 */
600 static void
601 dissect_zcl_msg_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type)
602 {
603     switch (attr_id) {
604         /* no cluster specific attributes */
605
606         /* applies to all SE clusters */
607         case ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_MSG:
608             proto_tree_add_item(tree, hf_zbee_zcl_msg_attr_reporting_status, tvb, *offset, 1, ENC_NA);
609             *offset += 1;
610             break;
611
612         default: /* Catch all */
613             dissect_zcl_attr_data(tvb, tree, offset, data_type);
614             break;
615     }
616 } /*dissect_zcl_ias_zone_attr_data*/
617
618 /**
619  *ZigBee ZCL Messaging cluster dissector for wireshark.
620  *
621  *@param tvb pointer to buffer containing raw packet.
622  *@param pinfo pointer to packet information fields
623  *@param tree pointer to data tree Wireshark uses to display packet.
624 */
625 static int
626 dissect_zbee_zcl_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
627 {
628     proto_tree        *payload_tree;
629     zbee_zcl_packet   *zcl;
630     guint             offset = 0;
631     guint8            cmd_id;
632     gint              rem_len;
633
634     /* Reject the packet if data is NULL */
635     if (data == NULL)
636         return 0;
637     zcl = (zbee_zcl_packet *)data;
638     cmd_id = zcl->cmd_id;
639
640     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
641     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
642         /* Append the command name to the info column. */
643         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
644             val_to_str_const(cmd_id, zbee_zcl_msg_srv_rx_cmd_names, "Unknown Command"),
645             zcl->tran_seqno);
646
647         /* Add the command ID. */
648         proto_tree_add_uint(tree, hf_zbee_zcl_msg_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
649
650         /* Check is this command has a payload, than add the payload tree */
651         rem_len = tvb_reported_length_remaining(tvb, ++offset);
652         if (rem_len > 0) {
653             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_msg, NULL, "Payload");
654
655             /* Call the appropriate command dissector */
656             switch (cmd_id) {
657
658                 case ZBEE_ZCL_CMD_ID_MSG_GET_LAST_MSG:
659                     /* No payload */
660                     break;
661
662                 case ZBEE_ZCL_CMD_ID_MSG_MSG_CONFIRM:
663                     dissect_zcl_msg_confirm(tvb, payload_tree, &offset);
664                     break;
665
666                 case ZBEE_ZCL_CMD_ID_MSG_GET_MESSAGE_CANCEL:
667                     dissect_zcl_msg_get_cancel(tvb, payload_tree, &offset);
668                     break;
669
670                 default:
671                     break;
672             }
673         }
674     }
675     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
676         /* Append the command name to the info column. */
677         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
678             val_to_str_const(cmd_id, zbee_zcl_msg_srv_tx_cmd_names, "Unknown Command"),
679             zcl->tran_seqno);
680
681         /* Add the command ID. */
682         proto_tree_add_uint(tree, hf_zbee_zcl_msg_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
683
684         /* Check is this command has a payload, than add the payload tree */
685         rem_len = tvb_reported_length_remaining(tvb, ++offset);
686         if (rem_len > 0) {
687             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_msg, NULL, "Payload");
688
689             /* Call the appropriate command dissector */
690             switch (cmd_id) {
691
692                 case ZBEE_ZCL_CMD_ID_MSG_DISPLAY_MSG:
693                     dissect_zcl_msg_display(tvb, payload_tree, &offset);
694                     break;
695
696                 case ZBEE_ZCL_CMD_ID_MSG_CANCEL_MSG:
697                     dissect_zcl_msg_cancel(tvb, pinfo, payload_tree, &offset);
698                     break;
699
700                 case ZBEE_ZCL_CMD_ID_MSG_DISPLAY_PROTECTED_MSG:
701                     dissect_zcl_msg_display(tvb, payload_tree, &offset);
702                     break;
703
704                 case ZBEE_ZCL_CMD_ID_MSG_CANCEL_ALL_MSG:
705                     dissect_zcl_msg_cancel_all(tvb, payload_tree, &offset);
706                     break;
707
708                 default:
709                     break;
710             }
711         }
712     }
713
714     return tvb_captured_length(tvb);
715 } /*dissect_zbee_zcl_msg*/
716
717 /**
718  *This function manages the Display Message payload
719  *
720  *@param tvb pointer to buffer containing raw packet.
721  *@param tree pointer to data tree Wireshark uses to display packet.
722  *@param offset pointer to offset from caller
723 */
724 static void
725 dissect_zcl_msg_display(tvbuff_t *tvb, proto_tree *tree, guint *offset)
726 {
727     guint   msg_len;
728     guint8 *msg_data;
729
730     static const int * message_ctrl_flags[] = {
731         &hf_zbee_zcl_msg_ctrl_tx,
732         &hf_zbee_zcl_msg_ctrl_importance,
733         &hf_zbee_zcl_msg_ctrl_enh_confirm,
734         &hf_zbee_zcl_msg_ctrl_reserved,
735         &hf_zbee_zcl_msg_ctrl_confirm,
736         NULL
737     };
738
739     static const int * message_ext_ctrl_flags[] = {
740         &hf_zbee_zcl_msg_ext_ctrl_status,
741         NULL
742     };
743
744     /* Message ID */
745     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_id, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
746     *offset += 4;
747
748     /* Message Control */
749     proto_tree_add_bitmask(tree, tvb, *offset, hf_zbee_zcl_msg_ctrl, ett_zbee_zcl_msg_message_control, message_ctrl_flags, ENC_NA);
750     *offset += 1;
751
752     /* Start Time */
753     proto_tree_add_item(tree, hf_zbee_zcl_msg_start_time, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
754     *offset += 4;
755
756     /* Duration In Minutes*/
757     proto_tree_add_item(tree, hf_zbee_zcl_msg_duration, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
758     *offset += 2;
759
760     /* Message Length */
761     msg_len = tvb_get_guint8(tvb, *offset); /* string length */
762     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_length, tvb, *offset, 1, ENC_NA);
763     *offset += 1;
764
765     /* Message */
766     msg_data = tvb_get_string_enc(wmem_packet_scope(), tvb, *offset, msg_len, ENC_LITTLE_ENDIAN);
767     proto_tree_add_string(tree, hf_zbee_zcl_msg_message, tvb, *offset, msg_len, msg_data);
768     *offset += msg_len;
769
770     /* (Optional) Extended Message Control */
771     if (tvb_reported_length_remaining(tvb, *offset) > 0) {
772         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);
773         *offset += 1;
774     }
775
776 } /*dissect_zcl_msg_display*/
777
778 /**
779  *This function manages the Cancel Message payload
780  *
781  *@param tvb pointer to buffer containing raw packet.
782  *@param tree pointer to data tree Wireshark uses to display packet.
783  *@param offset pointer to offset from caller
784 */
785 static void
786 dissect_zcl_msg_cancel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset)
787 {
788     gint8 msg_ctrl;
789
790     /* Message ID */
791     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_id, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
792     *offset += 4;
793
794     /* Message Control */
795     msg_ctrl = tvb_get_guint8(tvb, *offset);
796     proto_tree_add_item(tree, hf_zbee_zcl_msg_ctrl, tvb, *offset, 1, ENC_NA);
797     *offset += 1;
798
799     if (msg_ctrl != 0x00) {
800        expert_add_info(pinfo, tree, &ei_zbee_zcl_msg_msg_ctrl_depreciated);
801     }
802
803 } /* dissect_zcl_msg_cancel */
804
805
806 /**
807  *Send Cancel All command
808  *
809  *@param tvb pointer to buffer containing raw packet.
810  *@param tree pointer to data tree Wireshark uses to display packet.
811  *@param offset pointer to offset from caller
812 */
813 static void
814 dissect_zcl_msg_cancel_all(tvbuff_t *tvb, proto_tree *tree, guint *offset)
815 {
816     nstime_t impl_time;
817
818     /* Retrieve "Confirmation Time" field */
819     impl_time.secs = (time_t)tvb_get_letohl(tvb, *offset) + ZBEE_ZCL_NSTIME_UTC_OFFSET;
820     impl_time.nsecs = 0;
821     proto_tree_add_time(tree, hf_zbee_zcl_msg_implementation_time, tvb, *offset, 4, &impl_time);
822     *offset += 4;
823
824 } /* dissect_zcl_msg_cancel_all */
825
826 /**
827  *Send Cancel All command
828  *
829  *@param tvb pointer to buffer containing raw packet.
830  *@param tree pointer to data tree Wireshark uses to display packet.
831  *@param offset pointer to offset from caller
832 */
833 static void
834 dissect_zcl_msg_get_cancel(tvbuff_t *tvb, proto_tree *tree, guint *offset)
835 {
836     nstime_t impl_time;
837
838     /* Earliest Implementation Time */
839     impl_time.secs = (time_t)tvb_get_letohl(tvb, *offset) + ZBEE_ZCL_NSTIME_UTC_OFFSET;
840     impl_time.nsecs = 0;
841     proto_tree_add_time(tree, hf_zbee_zcl_msg_earliest_time, tvb, *offset, 4, &impl_time);
842     *offset += 4;
843
844 } /* dissect_zcl_msg_get_cancel */
845
846
847 /**
848  *This function manages the Message Confirmation payload
849  *
850  *@param tvb pointer to buffer containing raw packet.
851  *@param tree pointer to data tree Wireshark uses to display packet.
852  *@param offset pointer to offset from caller
853 */
854 static void
855 dissect_zcl_msg_confirm(tvbuff_t *tvb, proto_tree *tree, guint *offset)
856 {
857     guint   msg_len;
858     guint8 *msg_data;
859     nstime_t confirm_time;
860
861     /* Retrieve "Message ID" field */
862     proto_tree_add_item(tree, hf_zbee_zcl_msg_message_id, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
863     *offset += 4;
864
865     /* Retrieve "Confirmation Time" field */
866     confirm_time.secs = (time_t)tvb_get_letohl(tvb, *offset) + ZBEE_ZCL_NSTIME_UTC_OFFSET;
867     confirm_time.nsecs = 0;
868     proto_tree_add_time(tree, hf_zbee_zcl_msg_confirm_time, tvb, *offset, 4, &confirm_time);
869     *offset += 4;
870
871     /* (Optional) Confirm Control */
872     if ( tvb_reported_length_remaining(tvb, *offset) <= 0 ) return;
873     proto_tree_add_item(tree, hf_zbee_zcl_msg_confirm_ctrl, tvb, *offset, 1, ENC_NA);
874     *offset += 1;
875
876     /* (Optional) Response Text Length */
877     if ( tvb_reported_length_remaining(tvb, *offset) <= 0 ) return;
878     msg_len = tvb_get_guint8(tvb, *offset); /* string length */
879     proto_tree_add_item(tree, hf_zbee_zcl_msg_confirm_response_length, tvb, *offset, 1, ENC_NA);
880     *offset += 1;
881
882     /* (Optional) Response Text, but is we have a length we expect to find the subsequent string */
883     if (msg_len > 0) {
884         msg_data = tvb_get_string_enc(wmem_packet_scope(), tvb, *offset, msg_len, ENC_LITTLE_ENDIAN);
885         proto_tree_add_string(tree, hf_zbee_zcl_msg_confirm_response, tvb, *offset, msg_len, msg_data);
886         *offset += msg_len;
887     }
888
889 } /* dissect_zcl_msg_confirm */
890
891 /**
892  *This function decodes duration in minute type variable
893  *
894 */
895 static void
896 decode_zcl_msg_duration(gchar *s, guint16 value)
897 {
898     if (value == 0xffff)
899         g_snprintf(s, ITEM_LABEL_LENGTH, "Until changed");
900     else
901         g_snprintf(s, ITEM_LABEL_LENGTH, "%d minutes", value);
902     return;
903 } /*decode_zcl_msg_duration*/
904
905 /**
906  *This function decodes start time, with peculiarity case for
907  *
908  *@param s string to display
909  *@param value value to decode
910 */
911 static void
912 decode_zcl_msg_start_time(gchar *s, guint32 value)
913 {
914     if (value == ZBEE_ZCL_MSG_START_TIME_NOW)
915         g_snprintf(s, ITEM_LABEL_LENGTH, "Now");
916     else {
917         gchar *start_time;
918         time_t time = (time_t)value + ZBEE_ZCL_NSTIME_UTC_OFFSET;
919         start_time = abs_time_secs_to_str (NULL, time, ABSOLUTE_TIME_LOCAL, TRUE);
920         g_snprintf(s, ITEM_LABEL_LENGTH, "%s", start_time);
921         wmem_free(NULL, start_time);
922     }
923 } /* decode_zcl_msg_start_time */
924
925 /**
926  *This function registers the ZCL Messaging dissector
927  *
928 */
929 void
930 proto_register_zbee_zcl_msg(void)
931 {
932     static hf_register_info hf[] = {
933
934         { &hf_zbee_zcl_msg_attr_id,
935             { "Attribute", "zbee_zcl_se.msg.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_msg_attr_names),
936             0x0, NULL, HFILL } },
937
938         { &hf_zbee_zcl_msg_attr_reporting_status,                         /* common to all SE clusters */
939             { "Attribute Reporting Status", "zbee_zcl_se.msg.attr.attr_reporting_status",
940             FT_UINT8, BASE_HEX, VALS(zbee_zcl_se_reporting_status_names), 0x00, NULL, HFILL } },
941
942         { &hf_zbee_zcl_msg_srv_tx_cmd_id,
943             { "Command", "zbee_zcl_se.msg.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_srv_tx_cmd_names),
944             0x00, NULL, HFILL } },
945
946         { &hf_zbee_zcl_msg_srv_rx_cmd_id,
947             { "Command", "zbee_zcl_se.msg.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_srv_rx_cmd_names),
948             0x00, NULL, HFILL } },
949
950         { &hf_zbee_zcl_msg_message_id,
951             { "Message ID", "zbee_zcl_se.msg.message.id", FT_UINT32, BASE_HEX, NULL,
952             0x00, NULL, HFILL } },
953
954 /* Start of 'Message Control' fields */
955         { &hf_zbee_zcl_msg_ctrl,
956             { "Message Control", "zbee_zcl_se.msg.message.ctrl", FT_UINT8, BASE_HEX, NULL,
957             0x0, NULL, HFILL } },
958
959         { &hf_zbee_zcl_msg_ctrl_tx,
960             { "Transmission", "zbee_zcl_se.msg.message.ctrl.tx", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_ctrl_tx_names),
961             ZBEE_ZCL_MSG_CTRL_TX_MASK, NULL, HFILL } },
962
963         { &hf_zbee_zcl_msg_ctrl_importance,
964             { "Importance", "zbee_zcl_se.msg.message.ctrl.importance", FT_UINT8, BASE_HEX, VALS(zbee_zcl_msg_ctrl_importance_names),
965             ZBEE_ZCL_MSG_CTRL_IMPORTANCE_MASK, NULL, HFILL } },
966
967         { &hf_zbee_zcl_msg_ctrl_enh_confirm,
968             { "Confirmation", "zbee_zcl_se.msg.message.ctrl.enhconfirm", FT_BOOLEAN, 8, TFS(&tfs_required_not_required),
969             ZBEE_ZCL_MSG_CTRL_ENHANCED_CONFIRM_MASK, NULL, HFILL } },
970
971         { &hf_zbee_zcl_msg_ctrl_reserved,
972             { "Reserved", "zbee_zcl_se.msg.message.ctrl.reserved", FT_UINT8, BASE_HEX, NULL,
973             ZBEE_ZCL_MSG_CTRL_RESERVED_MASK, NULL, HFILL } },
974
975         { &hf_zbee_zcl_msg_ctrl_confirm,
976             { "Confirmation", "zbee_zcl_se.msg.message.ctrl.confirm", FT_BOOLEAN, 8, TFS(&tfs_required_not_required),
977             ZBEE_ZCL_MSG_CTRL_CONFIRM_MASK, NULL, HFILL } },
978 /* End of 'Message Control' fields */
979
980 /* Start of 'Extended Message Control' fields */
981         { &hf_zbee_zcl_msg_ext_ctrl,
982             { "Extended Message Control", "zbee_zcl_se.msg.message.ext.ctrl", FT_UINT8, BASE_HEX, NULL,
983             0x0, NULL, HFILL } },
984
985         { &hf_zbee_zcl_msg_ext_ctrl_status,
986             { "Message Confirmation Status", "zbee_zcl_se.msg.message.ext.ctrl.status", FT_BOOLEAN, 8, TFS(&tfs_confirmed_unconfirmed),
987             ZBEE_ZCL_MSG_EXT_CTRL_STATUS_MASK, NULL, HFILL } },
988 /* End of 'Extended Message Control' fields */
989
990         { &hf_zbee_zcl_msg_start_time,
991             { "Start Time", "zbee_zcl_se.msg.message.start_time", FT_UINT32, BASE_CUSTOM, CF_FUNC(decode_zcl_msg_start_time),
992             0x00, NULL, HFILL } },
993
994         { &hf_zbee_zcl_msg_duration,
995             { "Duration", "zbee_zcl_se.msg.message.duration", FT_UINT16, BASE_CUSTOM, CF_FUNC(decode_zcl_msg_duration),
996             0x00, NULL, HFILL } },
997
998         { &hf_zbee_zcl_msg_message_length,
999             { "Message Length", "zbee_zcl_se.msg.message.length", FT_UINT8, BASE_DEC, NULL,
1000             0x00, NULL, HFILL } },
1001
1002         { &hf_zbee_zcl_msg_message,
1003             { "Message", "zbee_zcl_se.msg.message", FT_STRING, BASE_NONE, NULL,
1004             0x00, NULL, HFILL } },
1005
1006         { &hf_zbee_zcl_msg_confirm_time,
1007             { "Confirmation Time", "zbee_zcl_se.msg.message.confirm_time",  FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL,
1008             0x0, NULL, HFILL } },
1009
1010         { &hf_zbee_zcl_msg_confirm_ctrl,
1011             { "Confirmation Control", "zbee_zcl_se.msg.message.confirm.ctrl", FT_BOOLEAN, 8, TFS(&tfs_no_yes),
1012             ZBEE_ZCL_MSG_CONFIRM_CTRL_MASK, NULL, HFILL } },
1013
1014         { &hf_zbee_zcl_msg_confirm_response_length,
1015             { "Response Length", "zbee_zcl_se.msg.message.length", FT_UINT8, BASE_DEC, NULL,
1016             0x00, NULL, HFILL } },
1017
1018         { &hf_zbee_zcl_msg_confirm_response,
1019             { "Response", "zbee_zcl_se.msg.message", FT_STRING, BASE_NONE, NULL,
1020             0x00, NULL, HFILL } },
1021
1022         { &hf_zbee_zcl_msg_implementation_time,
1023             { "Implementation Time", "zbee_zcl_se.msg.impl_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
1024             0, NULL, HFILL } },
1025
1026         { &hf_zbee_zcl_msg_earliest_time,
1027             { "Earliest Implementation Time", "zbee_zcl_se.msg.earliest_impl_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
1028             0, NULL, HFILL } },
1029
1030     };
1031
1032     /* ZCL Messaging subtrees */
1033     gint *ett[] = {
1034         &ett_zbee_zcl_msg,
1035         &ett_zbee_zcl_msg_message_control,
1036         &ett_zbee_zcl_msg_ext_message_control,
1037     };
1038
1039     /* Expert Info */
1040     expert_module_t* expert_zbee_zcl_msg;
1041     static ei_register_info ei[] = {
1042         { &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 }},
1043     };
1044
1045     /* Register the ZigBee ZCL Messaging cluster protocol name and description */
1046     proto_zbee_zcl_msg = proto_register_protocol("ZigBee ZCL Messaging", "ZCL Messaging", ZBEE_PROTOABBREV_ZCL_MSG);
1047     proto_register_field_array(proto_zbee_zcl_msg, hf, array_length(hf));
1048     proto_register_subtree_array(ett, array_length(ett));
1049
1050     expert_zbee_zcl_msg = expert_register_protocol(proto_zbee_zcl_msg);
1051     expert_register_field_array(expert_zbee_zcl_msg, ei, array_length(ei));
1052
1053     /* Register the ZigBee ZCL Messaging dissector. */
1054     msg_handle = register_dissector(ZBEE_PROTOABBREV_ZCL_MSG, dissect_zbee_zcl_msg, proto_zbee_zcl_msg);
1055 } /*proto_register_zbee_zcl_msg*/
1056
1057 /**
1058  *Hands off the Zcl Messaging dissector.
1059  *
1060 */
1061 void
1062 proto_reg_handoff_zbee_zcl_msg(void)
1063 {
1064     /* Register our dissector with the ZigBee application dissectors. */
1065     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_MESSAGE, msg_handle);
1066
1067     zbee_zcl_init_cluster(  proto_zbee_zcl_msg,
1068                             ett_zbee_zcl_msg,
1069                             ZBEE_ZCL_CID_MESSAGE,
1070                             hf_zbee_zcl_msg_attr_id,
1071                             hf_zbee_zcl_msg_srv_rx_cmd_id,
1072                             hf_zbee_zcl_msg_srv_tx_cmd_id,
1073                             (zbee_zcl_fn_attr_data)dissect_zcl_msg_attr_data
1074                          );
1075 } /*proto_reg_handoff_zbee_zcl_msg*/
1076
1077 /* ########################################################################## */
1078 /* #### (0x0704) TUNNELING CLUSTER ########################################### */
1079 /* ########################################################################## */
1080
1081 /* Attributes */
1082 #define zbee_zcl_tun_attr_names_VALUE_STRING_LIST(XXX) \
1083     XXX(ZBEE_ZCL_ATTR_ID_TUN_CLOSE_TIMEOUT,                     0x0000, "Close Tunnel Timeout" ) \
1084 /* Smart Energy */ \
1085     XXX(ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_TUN,             0xFFFE, "Attribute Reporting Status" )
1086
1087 VALUE_STRING_ENUM(zbee_zcl_tun_attr_names);
1088 VALUE_STRING_ARRAY(zbee_zcl_tun_attr_names);
1089
1090 /* Server Commands Received */
1091 #define zbee_zcl_tun_srv_rx_cmd_names_VALUE_STRING_LIST(XXX) \
1092     XXX(ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL,                     0x00, "Request Tunnel" ) \
1093     XXX(ZBEE_ZCL_CMD_ID_TUN_CLOSE_TUNNEL,                       0x01, "Close Tunnel" ) \
1094     XXX(ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA,                      0x02, "Transfer Data" ) \
1095     XXX(ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR,                0x03, "Transfer Data Error" ) \
1096     XXX(ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA,                  0x04, "Ack Transfer Data" ) \
1097     XXX(ZBEE_ZCL_CMD_ID_TUN_READY_DATA,                         0x05, "Ready Data" ) \
1098     XXX(ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS,            0x06, "Get Supported Protocols" )
1099
1100 VALUE_STRING_ENUM(zbee_zcl_tun_srv_rx_cmd_names);
1101 VALUE_STRING_ARRAY(zbee_zcl_tun_srv_rx_cmd_names);
1102
1103 /* Server Commands Generated */
1104 #define zbee_zcl_tun_srv_tx_cmd_names_VALUE_STRING_LIST(XXX) \
1105     XXX(ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL_RSP,                 0x00, "Request Tunnel Response" ) \
1106     XXX(ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_TX,                   0x01, "Transfer Data" ) \
1107     XXX(ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR_TX,             0x02, "Transfer Data Error" ) \
1108     XXX(ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA_TX,               0x03, "Ack Transfer Data" ) \
1109     XXX(ZBEE_ZCL_CMD_ID_TUN_READY_DATA_TX,                      0x04, "Ready Data" ) \
1110     XXX(ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS_RSP,        0x05, "Get Supported Tunnel Protocols" ) \
1111     XXX(ZBEE_ZCL_CMD_ID_TUN_CLOSURE_NOTIFY,                     0x06, "Tunnel Closure Notification" )
1112
1113 VALUE_STRING_ENUM(zbee_zcl_tun_srv_tx_cmd_names);
1114 VALUE_STRING_ARRAY(zbee_zcl_tun_srv_tx_cmd_names);
1115
1116 /*************************/
1117 /* Function Declarations */
1118 /*************************/
1119 void proto_register_zbee_zcl_tun(void);
1120 void proto_reg_handoff_zbee_zcl_tun(void);
1121
1122 /* Attribute Dissector Helpers */
1123 static void dissect_zcl_tun_attr_data  (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type);
1124
1125 /* Private functions prototype */
1126
1127 /*************************/
1128 /* Global Variables      */
1129 /*************************/
1130
1131 static dissector_handle_t tun_handle;
1132
1133 /* Initialize the protocol and registered fields */
1134 static int proto_zbee_zcl_tun = -1;
1135
1136 static int hf_zbee_zcl_tun_srv_tx_cmd_id = -1;
1137 static int hf_zbee_zcl_tun_srv_rx_cmd_id = -1;
1138 static int hf_zbee_zcl_tun_attr_id = -1;
1139 static int hf_zbee_zcl_tun_attr_reporting_status = -1;
1140 static int hf_zbee_zcl_tun_attr_close_timeout = -1;
1141 static int hf_zbee_zcl_tun_protocol_id = -1;
1142 static int hf_zbee_zcl_tun_manufacturer_code = -1;
1143 static int hf_zbee_zcl_tun_flow_control_support = -1;
1144 static int hf_zbee_zcl_tun_max_in_size = -1;
1145 static int hf_zbee_zcl_tun_tunnel_id = -1;
1146 static int hf_zbee_zcl_tun_num_octets_left = -1;
1147 static int hf_zbee_zcl_tun_protocol_offset = -1;
1148 static int hf_zbee_zcl_tun_protocol_list_complete = -1;
1149 static int hf_zbee_zcl_tun_protocol_count = -1;
1150 static int hf_zbee_zcl_tun_transfer_status = -1;
1151 static int hf_zbee_zcl_tun_transfer_data = -1;
1152 static int hf_zbee_zcl_tun_transfer_data_status = -1;
1153
1154 /* Initialize the subtree pointers */
1155 static gint ett_zbee_zcl_tun = -1;
1156
1157 /* Subdissector handles. */
1158 static dissector_handle_t       ipv4_handle;
1159 static dissector_handle_t       ipv6_handle;
1160
1161 #define zbee_zcl_tun_protocol_names_VALUE_STRING_LIST(XXX) \
1162     XXX(ZBEE_ZCL_TUN_PROTO_DLMS,                                0x00, "DLMS/COSEM (IEC 62056)" ) \
1163     XXX(ZBEE_ZCL_TUN_PROTO_IEC_61107,                           0x01, "IEC 61107" ) \
1164     XXX(ZBEE_ZCL_TUN_PROTO_ANSI_C12,                            0x02, "ANSI C12" ) \
1165     XXX(ZBEE_ZCL_TUN_PROTO_M_BUS,                               0x03, "M-BUS" ) \
1166     XXX(ZBEE_ZCL_TUN_PROTO_SML,                                 0x04, "SML" ) \
1167     XXX(ZBEE_ZCL_TUN_PROTO_CLIMATE_TALK,                        0x05, "ClimateTalk" ) \
1168     XXX(ZBEE_ZCL_TUN_PROTO_GB_HRGP,                             0x06, "GB-HRGP" ) \
1169     XXX(ZBEE_ZCL_TUN_PROTO_IPV6,                                0x07, "IPv6" ) \
1170     XXX(ZBEE_ZCL_TUN_PROTO_IPV4,                                0x08, "IPv4" ) \
1171     XXX(ZBEE_ZCL_TUN_PROTO_NULL,                                0x09, "null" ) \
1172     XXX(ZBEE_ZCL_TUN_PROTO_TEST,                                 199, "test" ) \
1173     XXX(ZBEE_ZCL_TUN_PROTO_MANUFACTURER,                         200, "Manufacturer Specific" ) \
1174     XXX(ZBEE_ZCL_TUN_PROTO_RESERVED,                            0xFF, "Reserved" )
1175
1176 VALUE_STRING_ENUM(zbee_zcl_tun_protocol_names);
1177 VALUE_STRING_ARRAY(zbee_zcl_tun_protocol_names);
1178
1179 #define zbee_zcl_tun_trans_data_status_names_VALUE_STRING_LIST(XXX) \
1180     XXX(ZBEE_ZCL_TUN_TRANS_STATUS_NO_TUNNEL,                    0x00, "Tunnel ID Does Not Exist" ) \
1181     XXX(ZBEE_ZCL_TUN_TRANS_STATUS_WRONG_DEV,                    0x01, "Wrong Device" ) \
1182     XXX(ZBEE_ZCL_TUN_TRANS_STATUS_OVERFLOW,                     0x02, "Data Overflow" )
1183
1184 VALUE_STRING_ENUM(zbee_zcl_tun_trans_data_status_names);
1185 VALUE_STRING_ARRAY(zbee_zcl_tun_trans_data_status_names);
1186
1187 #define zbee_zcl_tun_status_names_VALUE_STRING_LIST(XXX) \
1188     XXX(ZBEE_ZCL_TUN_STATUS_SUCCESS,                            0x00, "Success" ) \
1189     XXX(ZBEE_ZCL_TUN_STATUS_BUSY,                               0x01, "Busy" ) \
1190     XXX(ZBEE_ZCL_TUN_STATUS_NO_MORE_IDS,                        0x02, "No More Tunnel IDs" ) \
1191     XXX(ZBEE_ZCL_TUN_STATUS_PROTO_NOT_SUPP,                     0x03, "Protocol Not Supported" ) \
1192     XXX(ZBEE_ZCL_TUN_STATUS_FLOW_CONTROL_NOT_SUPP,              0x04, "Flow Control Not Supported" )
1193
1194 VALUE_STRING_ENUM(zbee_zcl_tun_status_names);
1195 VALUE_STRING_ARRAY(zbee_zcl_tun_status_names);
1196
1197 /*************************/
1198 /* Function Bodies       */
1199 /*************************/
1200
1201 /**
1202  *This function is called by ZCL foundation dissector in order to decode
1203  *
1204  *@param tree pointer to data tree Wireshark uses to display packet.
1205  *@param tvb pointer to buffer containing raw packet.
1206  *@param offset pointer to buffer offset
1207  *@param attr_id attribute identifier
1208  *@param data_type attribute data type
1209 */
1210 static void
1211 dissect_zcl_tun_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type)
1212 {
1213     switch (attr_id) {
1214         /* cluster specific attributes */
1215         case ZBEE_ZCL_ATTR_ID_TUN_CLOSE_TIMEOUT:
1216             proto_tree_add_item(tree, hf_zbee_zcl_tun_attr_close_timeout, tvb, *offset, 2, ENC_NA);
1217             *offset += 2;
1218             break;
1219
1220         /* applies to all SE clusters */
1221         case ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_TUN:
1222             proto_tree_add_item(tree, hf_zbee_zcl_tun_attr_reporting_status, tvb, *offset, 1, ENC_NA);
1223             *offset += 1;
1224             break;
1225
1226         default: /* Catch all */
1227             dissect_zcl_attr_data(tvb, tree, offset, data_type);
1228             break;
1229     }
1230 } /*dissect_zcl_ias_zone_attr_data*/
1231
1232 /**
1233  *This function manages the Display Message payload
1234  *
1235  *@param tvb pointer to buffer containing raw packet.
1236  *@param tree pointer to data tree Wireshark uses to display packet.
1237  *@param offset pointer to offset from caller
1238 */
1239 static void
1240 dissect_zcl_tun_request_tunnel(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1241 {
1242     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_id, tvb, *offset, 1, ENC_NA);
1243     *offset += 1;
1244
1245     proto_tree_add_item(tree, hf_zbee_zcl_tun_manufacturer_code, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1246     *offset += 2;
1247
1248     proto_tree_add_item(tree, hf_zbee_zcl_tun_flow_control_support, tvb, *offset, 1, ENC_NA);
1249     *offset += 1;
1250
1251     proto_tree_add_item(tree, hf_zbee_zcl_tun_max_in_size, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1252     *offset += 2;
1253 }
1254
1255 /**
1256  *This function manages the Display Message payload
1257  *
1258  *@param tvb pointer to buffer containing raw packet.
1259  *@param tree pointer to data tree Wireshark uses to display packet.
1260  *@param offset pointer to offset from caller
1261 */
1262 static void
1263 dissect_zcl_tun_close_tunnel(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1264 {
1265     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1266     *offset += 2;
1267 }
1268
1269 /**
1270  *This function manages the Display Message payload
1271  *
1272  *@param tvb pointer to buffer containing raw packet.
1273  *@param tree pointer to data tree Wireshark uses to display packet.
1274  *@param offset pointer to offset from caller
1275 */
1276 static void
1277 dissect_zcl_tun_transfer_data(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1278 {
1279     gint length;
1280
1281     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1282     *offset += 2;
1283
1284     length = tvb_reported_length_remaining(tvb, *offset);
1285     proto_tree_add_item(tree, hf_zbee_zcl_tun_transfer_data, tvb, *offset, length, ENC_NA);
1286     *offset += length;
1287 }
1288
1289 /**
1290  *This function manages the Display Message payload
1291  *
1292  *@param tvb pointer to buffer containing raw packet.
1293  *@param tree pointer to data tree Wireshark uses to display packet.
1294  *@param offset pointer to offset from caller
1295 */
1296 static void
1297 dissect_zcl_tun_transfer_data_error(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1298 {
1299     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1300     *offset += 2;
1301
1302     proto_tree_add_item(tree, hf_zbee_zcl_tun_transfer_data_status, tvb, *offset, 1, ENC_NA);
1303     *offset += 1;
1304 }
1305
1306 /**
1307  *This function manages the Display Message payload
1308  *
1309  *@param tvb pointer to buffer containing raw packet.
1310  *@param tree pointer to data tree Wireshark uses to display packet.
1311  *@param offset pointer to offset from caller
1312 */
1313 static void
1314 dissect_zcl_tun_ack_transfer_data(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1315 {
1316     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1317     *offset += 2;
1318
1319     proto_tree_add_item(tree, hf_zbee_zcl_tun_num_octets_left, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1320     *offset += 2;
1321 }
1322
1323 /**
1324  *This function manages the Display Message payload
1325  *
1326  *@param tvb pointer to buffer containing raw packet.
1327  *@param tree pointer to data tree Wireshark uses to display packet.
1328  *@param offset pointer to offset from caller
1329 */
1330 static void
1331 dissect_zcl_tun_ready_data(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1332 {
1333     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1334     *offset += 2;
1335
1336     proto_tree_add_item(tree, hf_zbee_zcl_tun_num_octets_left, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1337     *offset += 2;
1338 }
1339
1340 /**
1341  *This function manages the Display Message payload
1342  *
1343  *@param tvb pointer to buffer containing raw packet.
1344  *@param tree pointer to data tree Wireshark uses to display packet.
1345  *@param offset pointer to offset from caller
1346 */
1347 static void
1348 dissect_zcl_tun_get_supported(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1349 {
1350     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_offset, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1351     *offset += 2;
1352 }
1353
1354 /**
1355  *This function manages the Display Message payload
1356  *
1357  *@param tvb pointer to buffer containing raw packet.
1358  *@param tree pointer to data tree Wireshark uses to display packet.
1359  *@param offset pointer to offset from caller
1360 */
1361 static void
1362 dissect_zcl_tun_request_tunnel_rsp(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1363 {
1364     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1365     *offset += 2;
1366
1367     proto_tree_add_item(tree, hf_zbee_zcl_tun_transfer_status, tvb, *offset, 1, ENC_NA);
1368     *offset += 1;
1369
1370     proto_tree_add_item(tree, hf_zbee_zcl_tun_max_in_size, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1371     *offset += 2;
1372 }
1373
1374 /**
1375  *This function manages the Display Message payload
1376  *
1377  *@param tvb pointer to buffer containing raw packet.
1378  *@param tree pointer to data tree Wireshark uses to display packet.
1379  *@param offset pointer to offset from caller
1380 */
1381 static void
1382 dissect_zcl_tun_get_supported_rsp(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1383 {
1384     guint16     mfg_code;
1385
1386     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_list_complete, tvb, *offset, 1, ENC_NA);
1387     *offset += 1;
1388
1389     proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_count, tvb, *offset, 1, ENC_NA);
1390     *offset += 1;
1391
1392     while (tvb_reported_length_remaining(tvb, *offset) > 0) {
1393         mfg_code = tvb_get_letohs(tvb, *offset);
1394         if (mfg_code == 0xFFFF) {
1395             proto_tree_add_string(tree, hf_zbee_zcl_tun_manufacturer_code, tvb, *offset, 2, "Standard Protocol (Mfg Code 0xFFFF)");
1396         }
1397         else {
1398             proto_tree_add_item(tree, hf_zbee_zcl_tun_manufacturer_code, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1399         }
1400         *offset += 2;
1401
1402         proto_tree_add_item(tree, hf_zbee_zcl_tun_protocol_id, tvb, *offset, 1, ENC_NA);
1403         *offset += 1;
1404     }
1405 }
1406
1407 /**
1408  *This function manages the Display Message payload
1409  *
1410  *@param tvb pointer to buffer containing raw packet.
1411  *@param tree pointer to data tree Wireshark uses to display packet.
1412  *@param offset pointer to offset from caller
1413 */
1414 static void
1415 dissect_zcl_tun_closure_notify(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1416 {
1417     proto_tree_add_item(tree, hf_zbee_zcl_tun_tunnel_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1418     *offset += 2;
1419 }
1420
1421 /**
1422  *ZigBee ZCL Messaging cluster dissector for wireshark.
1423  *
1424  *@param tvb pointer to buffer containing raw packet.
1425  *@param pinfo pointer to packet information fields
1426  *@param tree pointer to data tree Wireshark uses to display packet.
1427 */
1428 static int
1429 dissect_zbee_zcl_tun(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1430 {
1431     proto_tree        *payload_tree;
1432     zbee_zcl_packet   *zcl;
1433     guint             offset = 0;
1434     guint8            cmd_id;
1435     gint              rem_len;
1436
1437     /* Reject the packet if data is NULL */
1438     if (data == NULL)
1439         return 0;
1440     zcl = (zbee_zcl_packet *)data;
1441     cmd_id = zcl->cmd_id;
1442
1443     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
1444     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
1445         /* Append the command name to the info column. */
1446         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1447             val_to_str_const(cmd_id, zbee_zcl_tun_srv_rx_cmd_names, "Unknown Command"),
1448             zcl->tran_seqno);
1449
1450         /* Add the command ID. */
1451         proto_tree_add_uint(tree, hf_zbee_zcl_tun_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
1452
1453         /* Check is this command has a payload, than add the payload tree */
1454         rem_len = tvb_reported_length_remaining(tvb, ++offset);
1455         if (rem_len > 0) {
1456             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_tun, NULL, "Payload");
1457
1458             /* Call the appropriate command dissector */
1459             switch (cmd_id) {
1460
1461                 case ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL:
1462                     dissect_zcl_tun_request_tunnel(tvb, payload_tree, &offset);
1463                     break;
1464
1465                 case ZBEE_ZCL_CMD_ID_TUN_CLOSE_TUNNEL:
1466                     dissect_zcl_tun_close_tunnel(tvb, payload_tree, &offset);
1467                     break;
1468
1469                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA:
1470                     dissect_zcl_tun_transfer_data(tvb, payload_tree, &offset);
1471                     break;
1472
1473                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR:
1474                     dissect_zcl_tun_transfer_data_error(tvb, payload_tree, &offset);
1475                     break;
1476
1477                 case ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA:
1478                     dissect_zcl_tun_ack_transfer_data(tvb, payload_tree, &offset);
1479                     break;
1480
1481                 case ZBEE_ZCL_CMD_ID_TUN_READY_DATA:
1482                     dissect_zcl_tun_ready_data(tvb, payload_tree, &offset);
1483                     break;
1484
1485                 case ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS:
1486                     dissect_zcl_tun_get_supported(tvb, payload_tree, &offset);
1487                     break;
1488
1489                 default:
1490                     break;
1491             }
1492         }
1493     }
1494     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
1495         /* Append the command name to the info column. */
1496         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1497             val_to_str_const(cmd_id, zbee_zcl_tun_srv_tx_cmd_names, "Unknown Command"),
1498             zcl->tran_seqno);
1499
1500         /* Add the command ID. */
1501         proto_tree_add_uint(tree, hf_zbee_zcl_tun_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
1502
1503         /* Check is this command has a payload, than add the payload tree */
1504         rem_len = tvb_reported_length_remaining(tvb, ++offset);
1505         if (rem_len > 0) {
1506             payload_tree = proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_tun, NULL, "Payload");
1507
1508             /* Call the appropriate command dissector */
1509             switch (cmd_id) {
1510
1511                 case ZBEE_ZCL_CMD_ID_TUN_REQUEST_TUNNEL_RSP:
1512                     dissect_zcl_tun_request_tunnel_rsp(tvb, payload_tree, &offset);
1513                     break;
1514
1515                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_TX:
1516                     dissect_zcl_tun_transfer_data(tvb, payload_tree, &offset);
1517                     break;
1518
1519                 case ZBEE_ZCL_CMD_ID_TUN_TRANSFER_DATA_ERROR_TX:
1520                     dissect_zcl_tun_transfer_data_error(tvb, payload_tree, &offset);
1521                     break;
1522
1523                 case ZBEE_ZCL_CMD_ID_TUN_ACK_TRANSFER_DATA_TX:
1524                     dissect_zcl_tun_ack_transfer_data(tvb, payload_tree, &offset);
1525                     break;
1526
1527                 case ZBEE_ZCL_CMD_ID_TUN_READY_DATA_TX:
1528                     dissect_zcl_tun_ready_data(tvb, payload_tree, &offset);
1529                     break;
1530
1531                 case ZBEE_ZCL_CMD_ID_TUN_GET_SUPPORTED_PROTOCOLS_RSP:
1532                     dissect_zcl_tun_get_supported_rsp(tvb, payload_tree, &offset);
1533                     break;
1534
1535                 case ZBEE_ZCL_CMD_ID_TUN_CLOSURE_NOTIFY:
1536                     dissect_zcl_tun_closure_notify(tvb, payload_tree, &offset);
1537                     break;
1538
1539                 default:
1540                     break;
1541             }
1542         }
1543     }
1544
1545     return tvb_captured_length(tvb);
1546 } /*dissect_zbee_zcl_tun*/
1547
1548 /**
1549  *This function registers the ZCL Messaging dissector
1550  *
1551 */
1552 void
1553 proto_register_zbee_zcl_tun(void)
1554 {
1555     static hf_register_info hf[] = {
1556
1557         { &hf_zbee_zcl_tun_attr_id,
1558             { "Attribute", "zbee_zcl_se.tun.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_tun_attr_names),
1559             0x0, NULL, HFILL } },
1560
1561         { &hf_zbee_zcl_tun_attr_reporting_status,                         /* common to all SE clusters */
1562             { "Attribute Reporting Status", "zbee_zcl_se.tun.attr.attr_reporting_status",
1563             FT_UINT8, BASE_HEX, VALS(zbee_zcl_se_reporting_status_names), 0x00, NULL, HFILL } },
1564
1565         { &hf_zbee_zcl_tun_attr_close_timeout,
1566             { "Close Tunnel Timeout", "zbee_zcl_se.tun.attr.close_tunnel", FT_UINT16, BASE_DEC, NULL,
1567             0x0, NULL, HFILL } },
1568
1569         { &hf_zbee_zcl_tun_srv_tx_cmd_id,
1570             { "Command", "zbee_zcl_se.tun.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_srv_tx_cmd_names),
1571             0x00, NULL, HFILL } },
1572
1573         { &hf_zbee_zcl_tun_srv_rx_cmd_id,
1574             { "Command", "zbee_zcl_se.tun.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_srv_rx_cmd_names),
1575             0x00, NULL, HFILL } },
1576
1577         { &hf_zbee_zcl_tun_protocol_id,
1578             { "Protocol ID", "zbee_zcl_se.tun.protocol_id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_protocol_names),
1579             0x00, NULL, HFILL } },
1580
1581         { &hf_zbee_zcl_tun_manufacturer_code,
1582             { "Manufacturer Code", "zbee_zcl_se.tun.manufacturer_code", FT_UINT16, BASE_HEX, VALS(zbee_mfr_code_names),
1583             0x00, NULL, HFILL } },
1584
1585         { &hf_zbee_zcl_tun_flow_control_support,
1586             { "Flow Control Supported", "zbee_zcl_se.tun.flow_control_supported", FT_BOOLEAN, 8, TFS(&tfs_true_false),
1587             0x00, NULL, HFILL } },
1588
1589         { &hf_zbee_zcl_tun_max_in_size,
1590             { "Max Incoming Transfer Size", "zbee_zcl_se.tun.max_in_transfer_size", FT_UINT16, BASE_HEX, NULL,
1591             0x00, NULL, HFILL } },
1592
1593         { &hf_zbee_zcl_tun_tunnel_id,
1594             { "Tunnel Id", "zbee_zcl_se.tun.tunnel_id", FT_UINT16, BASE_HEX, NULL,
1595             0x00, NULL, HFILL } },
1596
1597         { &hf_zbee_zcl_tun_num_octets_left,
1598             { "Num Octets Left", "zbee_zcl_se.tun.octets_left", FT_UINT16, BASE_HEX, NULL,
1599             0x00, NULL, HFILL } },
1600
1601         { &hf_zbee_zcl_tun_protocol_offset,
1602             { "Protocol Offset", "zbee_zcl_se.tun.protocol_offset", FT_UINT8, BASE_HEX, NULL,
1603             0x00, NULL, HFILL } },
1604
1605         { &hf_zbee_zcl_tun_transfer_status,
1606             { "Transfer Status", "zbee_zcl_se.tun.transfer_status", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_status_names),
1607             0x00, NULL, HFILL } },
1608
1609         { &hf_zbee_zcl_tun_transfer_data,
1610             { "Transfer Data", "zbee_zcl_se.tun.transfer_data", FT_BYTES, BASE_NONE, NULL,
1611             0, NULL, HFILL } },
1612
1613         { &hf_zbee_zcl_tun_transfer_data_status,
1614             { "Transfer Data Status", "zbee_zcl_se.tun.transfer_data_status", FT_UINT8, BASE_HEX, VALS(zbee_zcl_tun_trans_data_status_names),
1615             0x00, NULL, HFILL } },
1616
1617         { &hf_zbee_zcl_tun_protocol_count,
1618             { "Protocol Count", "zbee_zcl_se.tun.protocol_count", FT_UINT8, BASE_HEX, NULL,
1619             0x00, NULL, HFILL } },
1620
1621         { &hf_zbee_zcl_tun_protocol_list_complete,
1622             { "List Complete", "zbee_zcl_se.tun.protocol_list_complete", FT_BOOLEAN, 8, TFS(&tfs_true_false),
1623             0x00, NULL, HFILL } },
1624
1625     };
1626
1627     /* ZCL Messaging subtrees */
1628     gint *ett[] = {
1629         &ett_zbee_zcl_tun,
1630     };
1631
1632     /* Register the ZigBee ZCL Messaging cluster protocol name and description */
1633     proto_zbee_zcl_tun = proto_register_protocol("ZigBee ZCL Tunneling", "ZCL Tunneling", ZBEE_PROTOABBREV_ZCL_TUN);
1634     proto_register_field_array(proto_zbee_zcl_tun, hf, array_length(hf));
1635     proto_register_subtree_array(ett, array_length(ett));
1636
1637     /* Register the ZigBee ZCL Messaging dissector. */
1638     tun_handle = register_dissector(ZBEE_PROTOABBREV_ZCL_TUN, dissect_zbee_zcl_tun, proto_zbee_zcl_tun);
1639
1640 } /* proto_register_zbee_zcl_tun */
1641
1642 /**
1643  *Hands off the Zcl Messaging dissector.
1644  *
1645 */
1646 void
1647 proto_reg_handoff_zbee_zcl_tun(void)
1648 {
1649     ipv4_handle = find_dissector("ipv4");
1650     ipv6_handle = find_dissector("ipv6");
1651
1652     /* Register our dissector with the ZigBee application dissectors. */
1653     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_TUNNELING, tun_handle);
1654
1655     zbee_zcl_init_cluster(  proto_zbee_zcl_tun,
1656                             ett_zbee_zcl_tun,
1657                             ZBEE_ZCL_CID_TUNNELING,
1658                             hf_zbee_zcl_tun_attr_id,
1659                             hf_zbee_zcl_tun_srv_rx_cmd_id,
1660                             hf_zbee_zcl_tun_srv_tx_cmd_id,
1661                             (zbee_zcl_fn_attr_data)dissect_zcl_tun_attr_data
1662                          );
1663 } /* proto_reg_handoff_zbee_zcl_tun */
1664
1665
1666 /* ########################################################################## */
1667 /* #### (0x0705) PREPAYMENT CLUSTER ########################################## */
1668 /* ########################################################################## */
1669
1670 /* Attributes */
1671 #define zbee_zcl_pp_attr_names_VALUE_STRING_LIST(XXX) \
1672 /* Prepayment Information Set */ \
1673     XXX(ZBEE_ZCL_ATTR_ID_PP_PAYMENT_CONTROL_CONFIGURATION,      0x0000, "Payment Control Configuration" ) \
1674     XXX(ZBEE_ZCL_ATTR_ID_PP_CREDIT_REMAINING,                   0x0001, "Credit Remaining" ) \
1675     XXX(ZBEE_ZCL_ATTR_ID_PP_EMERGENCY_CREDIT_REMAINING,         0x0002, "Emergency Credit Remaining" ) \
1676     XXX(ZBEE_ZCL_ATTR_ID_PP_ACCUMULATED_DEBT,                   0x0005, "Accumulated Debt" ) \
1677     XXX(ZBEE_ZCL_ATTR_ID_PP_OVERALL_DEBT_CAP,                   0x0006, "Overall Debt Cap" ) \
1678     XXX(ZBEE_ZCL_ATTR_ID_PP_EMERGENCY_CREDIT_LIMIT,             0x0010, "Emergency Credit Limit / Allowance" ) \
1679     XXX(ZBEE_ZCL_ATTR_ID_PP_EMERGENCY_CREDIT_THRESHOLD,         0x0011, "Emergency Credit Threshold" ) \
1680     XXX(ZBEE_ZCL_ATTR_ID_PP_MAX_CREDIT_LIMIT,                   0x0021, "Max Credit Limit" ) \
1681     XXX(ZBEE_ZCL_ATTR_ID_PP_MAX_CREDIT_PER_TOPUP,               0x0022, "Max Credit Per Top Up" ) \
1682     XXX(ZBEE_ZCL_ATTR_ID_PP_LOW_CREDIT_WARNING,                 0x0031, "Low Credit Warning" ) \
1683     XXX(ZBEE_ZCL_ATTR_ID_PP_CUT_OFF_VALUE,                      0x0040, "Cut Off Value" ) \
1684 /* Debt Set */ \
1685     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_AMOUNT_1,                      0x0211, "Debt Amount 1" ) \
1686     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_FREQ_1,               0x0216, "Debt Recovery Frequency 1" ) \
1687     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_AMOUNT_1,             0x0217, "Debt Recovery Amount 1" ) \
1688     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_TOP_UP_PERCENTAGE_1,  0x0219, "Debt Recovery Top Up Percentage 1" ) \
1689     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_AMOUNT_2,                      0x0221, "Debt Amount 2" ) \
1690     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_FREQ_2,               0x0226, "Debt Recovery Frequency 2" ) \
1691     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_AMOUNT_2,             0x0227, "Debt Recovery Amount 2" ) \
1692     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_TOP_UP_PERCENTAGE_2,  0x0229, "Debt Recovery Top Up Percentage 2" ) \
1693     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_AMOUNT_3,                      0x0231, "Debt Amount 3" ) \
1694     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_FREQ_3,               0x0236, "Debt Recovery Frequency 3" ) \
1695     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_AMOUNT_3,             0x0237, "Debt Recovery Amount 3" ) \
1696     XXX(ZBEE_ZCL_ATTR_ID_PP_DEBT_RECOVERY_TOP_UP_PERCENTAGE_3,  0x0239, "Debt Recovery Top Up Percentage 3" ) \
1697 /* Alarm Set */ \
1698     XXX(ZBEE_ZCL_ATTR_ID_PP_PREPAYMENT_ALARM_STATUS,            0x0400, "Prepayment Alarm Status" ) \
1699 /* Historical Cost Consumption Information Set */ \
1700     XXX(ZBEE_ZCL_ATTR_ID_PP_HISTORICAL_COST_CON_FORMAT,         0x0500, "Historical Cost Consumption Formatting" ) \
1701     XXX(ZBEE_ZCL_ATTR_ID_PP_CONSUMPTION_UNIT_OF_MEASUREMENT,    0x0501, "Consumption Unit of Measurement" ) \
1702     XXX(ZBEE_ZCL_ATTR_ID_PP_CURRENCY_SCALING_FACTOR,            0x0502, "Currency Scaling Factor" ) \
1703     XXX(ZBEE_ZCL_ATTR_ID_PP_CURRENCY,                           0x0503, "Currency" ) \
1704     XXX(ZBEE_ZCL_ATTR_ID_PP_CURRENT_DAY_COST_CON_DELIVERED,     0x051C, "Current Day Cost Consumption Delivered" ) \
1705     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_COST_CON_DELIVERED,    0x051E, "Previous Day Cost Consumption Delivered" ) \
1706     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_2_COST_CON_DELIVERED,  0x0520, "Previous Day 2 Cost Consumption Delivered" ) \
1707     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_3_COST_CON_DELIVERED,  0x0522, "Previous Day 3 Cost Consumption Delivered" ) \
1708     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_4_COST_CON_DELIVERED,  0x0524, "Previous Day 4 Cost Consumption Delivered" ) \
1709     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_5_COST_CON_DELIVERED,  0x0526, "Previous Day 5 Cost Consumption Delivered" ) \
1710     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_6_COST_CON_DELIVERED,  0x0528, "Previous Day 6 Cost Consumption Delivered" ) \
1711     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_7_COST_CON_DELIVERED,  0x052A, "Previous Day 7 Cost Consumption Delivered" ) \
1712     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_DAY_8_COST_CON_DELIVERED,  0x052C, "Previous Day 8 Cost Consumption Delivered" ) \
1713     XXX(ZBEE_ZCL_ATTR_ID_PP_CURRENT_WEEK_COST_CON_DELIVERED,    0x0530, "Current Week Cost Consumption Delivered" ) \
1714     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_WEEK_COST_CON_DELIVERED,   0x0532, "Previous Week Cost Consumption Delivered" ) \
1715     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_WEEK_2_COST_CON_DELIVERED, 0x0534, "Previous Week 2 Cost Consumption Delivered" ) \
1716     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_WEEK_3_COST_CON_DELIVERED, 0x0536, "Previous Week 3 Cost Consumption Delivered" ) \
1717     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_WEEK_4_COST_CON_DELIVERED, 0x0538, "Previous Week 4 Cost Consumption Delivered" ) \
1718     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_WEEK_5_COST_CON_DELIVERED, 0x053A, "Previous Week 5 Cost Consumption Delivered" ) \
1719     XXX(ZBEE_ZCL_ATTR_ID_PP_CURRENT_MON_COST_CON_DELIVERED,     0x0540, "Current Month Cost Consumption Delivered" ) \
1720     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_COST_CON_DELIVERED,    0x0542, "Previous Month Cost Consumption Delivered" ) \
1721     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_2_COST_CON_DELIVERED,  0x0544, "Previous Month 2 Cost Consumption Delivered" ) \
1722     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_3_COST_CON_DELIVERED,  0x0546, "Previous Month 3 Cost Consumption Delivered" ) \
1723     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_4_COST_CON_DELIVERED,  0x0548, "Previous Month 4 Cost Consumption Delivered" ) \
1724     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_5_COST_CON_DELIVERED,  0x054A, "Previous Month 5 Cost Consumption Delivered" ) \
1725     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_6_COST_CON_DELIVERED,  0x054C, "Previous Month 6 Cost Consumption Delivered" ) \
1726     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_7_COST_CON_DELIVERED,  0x054E, "Previous Month 7 Cost Consumption Delivered" ) \
1727     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_8_COST_CON_DELIVERED,  0x0550, "Previous Month 8 Cost Consumption Delivered" ) \
1728     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_9_COST_CON_DELIVERED,  0x0552, "Previous Month 9 Cost Consumption Delivered" ) \
1729     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_10_COST_CON_DELIVERED, 0x0554, "Previous Month 10 Cost Consumption Delivered" ) \
1730     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_11_COST_CON_DELIVERED, 0x0556, "Previous Month 11 Cost Consumption Delivered" ) \
1731     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_12_COST_CON_DELIVERED, 0x0558, "Previous Month 12 Cost Consumption Delivered" ) \
1732     XXX(ZBEE_ZCL_ATTR_ID_PP_PREVIOUS_MON_13_COST_CON_DELIVERED, 0x055A, "Previous Month 13 Cost Consumption Delivered" ) \
1733     XXX(ZBEE_ZCL_ATTR_ID_PP_HISTORICAL_FREEZE_TIME,             0x055C, "Historical Freeze Time" ) \
1734 /* Smart Energy */ \
1735     XXX(ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_PP,              0xFFFE, "Attribute Reporting Status" )
1736
1737 VALUE_STRING_ENUM(zbee_zcl_pp_attr_names);
1738 VALUE_STRING_ARRAY(zbee_zcl_pp_attr_names);
1739 static value_string_ext zbee_zcl_pp_attr_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_pp_attr_names);
1740
1741 /* Server Commands Received */
1742 #define zbee_zcl_pp_srv_rx_cmd_names_VALUE_STRING_LIST(XXX) \
1743     XXX(ZBEE_ZCL_CMD_ID_PP_SELECT_AVAILABLE_EMERGENCY_CREDIT,   0x00, "Select Available Emergency Credit" ) \
1744     XXX(ZBEE_ZCL_CMD_ID_PP_CONSUMER_TOP_UP,                     0x04, "Consumer Top Up" ) \
1745     XXX(ZBEE_ZCL_CMD_ID_PP_GET_PREPAY_SNAPTSHOT,                0x07, "Get Prepay Snapshot" ) \
1746     XXX(ZBEE_ZCL_CMD_ID_PP_GET_TOP_UP_LOG,                      0x08, "Get Top Up Log" ) \
1747     XXX(ZBEE_ZCL_CMD_ID_PP_GET_DEBT_REPAYMENT_LOG,              0x0A, "Get Debt Repayment Log" )
1748
1749 VALUE_STRING_ENUM(zbee_zcl_pp_srv_rx_cmd_names);
1750 VALUE_STRING_ARRAY(zbee_zcl_pp_srv_rx_cmd_names);
1751
1752 /* Server Commands Generated */
1753 #define zbee_zcl_pp_srv_tx_cmd_names_VALUE_STRING_LIST(XXX) \
1754     XXX(ZBEE_ZCL_CMD_ID_PP_PUBLISH_PREPAY_SNAPSHOT,             0x01, "Publish Prepay Snapshot" ) \
1755     XXX(ZBEE_ZCL_CMD_ID_PP_CONSUMER_TOP_UP_RESPONSE,            0x03, "Consumer Top Up Response" ) \
1756     XXX(ZBEE_ZCL_CMD_ID_PP_PUBLISH_TOP_UP_LOG,                  0x05, "Publish Top Up Log" ) \
1757     XXX(ZBEE_ZCL_CMD_ID_PP_PUBLISH_DEBT_LOG,                    0x06, "Publish Debt Log" )
1758
1759 VALUE_STRING_ENUM(zbee_zcl_pp_srv_tx_cmd_names);
1760 VALUE_STRING_ARRAY(zbee_zcl_pp_srv_tx_cmd_names);
1761
1762 /*************************/
1763 /* Function Declarations */
1764 /*************************/
1765 void proto_register_zbee_zcl_pp(void);
1766 void proto_reg_handoff_zbee_zcl_pp(void);
1767
1768 /* Attribute Dissector Helpers */
1769 static void dissect_zcl_pp_attr_data  (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type);
1770
1771 /*************************/
1772 /* Global Variables      */
1773 /*************************/
1774
1775 static dissector_handle_t pp_handle;
1776
1777 /* Initialize the protocol and registered fields */
1778 static int proto_zbee_zcl_pp = -1;
1779
1780 static int hf_zbee_zcl_pp_srv_tx_cmd_id = -1;
1781 static int hf_zbee_zcl_pp_srv_rx_cmd_id = -1;
1782 static int hf_zbee_zcl_pp_attr_id = -1;
1783 static int hf_zbee_zcl_pp_attr_reporting_status = -1;
1784
1785 /* Initialize the subtree pointers */
1786 static gint ett_zbee_zcl_pp = -1;
1787
1788 /*************************/
1789 /* Function Bodies       */
1790 /*************************/
1791
1792 /**
1793  *This function is called by ZCL foundation dissector in order to decode
1794  *
1795  *@param tree pointer to data tree Wireshark uses to display packet.
1796  *@param tvb pointer to buffer containing raw packet.
1797  *@param offset pointer to buffer offset
1798  *@param attr_id attribute identifier
1799  *@param data_type attribute data type
1800 */
1801 static void
1802 dissect_zcl_pp_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type)
1803 {
1804     switch (attr_id) {
1805         /* applies to all SE clusters */
1806         case ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_PP:
1807             proto_tree_add_item(tree, hf_zbee_zcl_pp_attr_reporting_status, tvb, *offset, 1, ENC_NA);
1808             *offset += 1;
1809             break;
1810
1811         default: /* Catch all */
1812             dissect_zcl_attr_data(tvb, tree, offset, data_type);
1813             break;
1814     }
1815 } /*dissect_zcl_pp_attr_data*/
1816
1817 /**
1818  *ZigBee ZCL Prepayment cluster dissector for wireshark.
1819  *
1820  *@param tvb pointer to buffer containing raw packet.
1821  *@param pinfo pointer to packet information fields
1822  *@param tree pointer to data tree Wireshark uses to display packet.
1823 */
1824 static int
1825 dissect_zbee_zcl_pp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1826 {
1827     zbee_zcl_packet   *zcl;
1828     guint             offset = 0;
1829     guint8            cmd_id;
1830     gint              rem_len;
1831
1832     /* Reject the packet if data is NULL */
1833     if (data == NULL)
1834         return 0;
1835     zcl = (zbee_zcl_packet *)data;
1836     cmd_id = zcl->cmd_id;
1837
1838     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
1839     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
1840         /* Append the command name to the info column. */
1841         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1842             val_to_str_const(cmd_id, zbee_zcl_pp_srv_rx_cmd_names, "Unknown Command"),
1843             zcl->tran_seqno);
1844
1845         /* Add the command ID. */
1846         proto_tree_add_uint(tree, hf_zbee_zcl_pp_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
1847
1848         /* Check is this command has a payload, than add the payload tree */
1849         rem_len = tvb_reported_length_remaining(tvb, ++offset);
1850         if (rem_len > 0) {
1851             proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_pp, NULL, "Payload");
1852
1853             /* Call the appropriate command dissector */
1854             switch (cmd_id) {
1855
1856                 case ZBEE_ZCL_CMD_ID_PP_SELECT_AVAILABLE_EMERGENCY_CREDIT:
1857                     /* Add function to dissect payload */
1858                     break;
1859
1860                 case ZBEE_ZCL_CMD_ID_PP_CONSUMER_TOP_UP:
1861                     /* Add function to dissect payload */
1862                     break;
1863
1864                 case ZBEE_ZCL_CMD_ID_PP_GET_PREPAY_SNAPTSHOT:
1865                     /* Add function to dissect payload */
1866                     break;
1867
1868                 case ZBEE_ZCL_CMD_ID_PP_GET_TOP_UP_LOG:
1869                     /* Add function to dissect payload */
1870                     break;
1871
1872                 case ZBEE_ZCL_CMD_ID_PP_GET_DEBT_REPAYMENT_LOG:
1873                     /* Add function to dissect payload */
1874                     break;
1875
1876                 default:
1877                     break;
1878             }
1879         }
1880     }
1881     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
1882         /* Append the command name to the info column. */
1883         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
1884             val_to_str_const(cmd_id, zbee_zcl_pp_srv_tx_cmd_names, "Unknown Command"),
1885             zcl->tran_seqno);
1886
1887         /* Add the command ID. */
1888         proto_tree_add_uint(tree, hf_zbee_zcl_pp_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
1889
1890         /* Check is this command has a payload, than add the payload tree */
1891         rem_len = tvb_reported_length_remaining(tvb, ++offset);
1892         if (rem_len > 0) {
1893             proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_pp, NULL, "Payload");
1894
1895             /* Call the appropriate command dissector */
1896             switch (cmd_id) {
1897
1898                 case ZBEE_ZCL_CMD_ID_PP_PUBLISH_PREPAY_SNAPSHOT:
1899                     /* Add function to dissect payload */
1900                     break;
1901
1902                 case ZBEE_ZCL_CMD_ID_PP_CONSUMER_TOP_UP_RESPONSE:
1903                     /* Add function to dissect payload */
1904                     break;
1905
1906                 case ZBEE_ZCL_CMD_ID_PP_PUBLISH_TOP_UP_LOG:
1907                     /* Add function to dissect payload */
1908                     break;
1909
1910                 case ZBEE_ZCL_CMD_ID_PP_PUBLISH_DEBT_LOG:
1911                     /* Add function to dissect payload */
1912                     break;
1913
1914                 default:
1915                     break;
1916             }
1917         }
1918     }
1919
1920     return tvb_captured_length(tvb);
1921 } /*dissect_zbee_zcl_pp*/
1922
1923 /**
1924  *This function registers the ZCL Prepayment dissector
1925  *
1926 */
1927 void
1928 proto_register_zbee_zcl_pp(void)
1929 {
1930     static hf_register_info hf[] = {
1931
1932         { &hf_zbee_zcl_pp_attr_id,
1933             { "Attribute", "zbee_zcl_se.pp.attr_id", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &zbee_zcl_pp_attr_names_ext,
1934             0x0, NULL, HFILL } },
1935
1936         { &hf_zbee_zcl_pp_attr_reporting_status,                         /* common to all SE clusters */
1937             { "Attribute Reporting Status", "zbee_zcl_se.pp.attr.attr_reporting_status",
1938             FT_UINT8, BASE_HEX, VALS(zbee_zcl_se_reporting_status_names), 0x00, NULL, HFILL } },
1939
1940         { &hf_zbee_zcl_pp_srv_tx_cmd_id,
1941             { "Command", "zbee_zcl_se.pp.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_pp_srv_tx_cmd_names),
1942             0x00, NULL, HFILL } },
1943
1944         { &hf_zbee_zcl_pp_srv_rx_cmd_id,
1945             { "Command", "zbee_zcl_se.pp.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_pp_srv_rx_cmd_names),
1946             0x00, NULL, HFILL } },
1947
1948     };
1949
1950     /* ZCL Prepayment subtrees */
1951     gint *ett[] = {
1952         &ett_zbee_zcl_pp,
1953     };
1954
1955     /* Register the ZigBee ZCL Prepayment cluster protocol name and description */
1956     proto_zbee_zcl_pp = proto_register_protocol("ZigBee ZCL Prepayment", "ZCL Prepayment", ZBEE_PROTOABBREV_ZCL_PRE_PAYMENT);
1957     proto_register_field_array(proto_zbee_zcl_pp, hf, array_length(hf));
1958     proto_register_subtree_array(ett, array_length(ett));
1959
1960     /* Register the ZigBee ZCL Prepayment dissector. */
1961     pp_handle = register_dissector(ZBEE_PROTOABBREV_ZCL_PRE_PAYMENT, dissect_zbee_zcl_pp, proto_zbee_zcl_pp);
1962 } /*proto_register_zbee_zcl_pp*/
1963
1964 /**
1965  *Hands off the Zcl Prepayment dissector.
1966  *
1967 */
1968 void
1969 proto_reg_handoff_zbee_zcl_pp(void)
1970 {
1971     /* Register our dissector with the ZigBee application dissectors. */
1972     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_PRE_PAYMENT, pp_handle);
1973
1974     zbee_zcl_init_cluster(  proto_zbee_zcl_pp,
1975                             ett_zbee_zcl_pp,
1976                             ZBEE_ZCL_CID_PRE_PAYMENT,
1977                             hf_zbee_zcl_pp_attr_id,
1978                             hf_zbee_zcl_pp_srv_rx_cmd_id,
1979                             hf_zbee_zcl_pp_srv_tx_cmd_id,
1980                             (zbee_zcl_fn_attr_data)dissect_zcl_pp_attr_data
1981                          );
1982 } /*proto_reg_handoff_zbee_zcl_pp*/
1983
1984 /* ########################################################################## */
1985 /* #### (0x0709) EVENTS CLUSTER ############################################# */
1986 /* ########################################################################## */
1987
1988 /* Attributes */
1989 #define zbee_zcl_events_attr_names_VALUE_STRING_LIST(XXX) \
1990 /* Smart Energy */ \
1991     XXX(ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_EVENTS,          0xFFFE, "Attribute Reporting Status" )
1992
1993 VALUE_STRING_ENUM(zbee_zcl_events_attr_names);
1994 VALUE_STRING_ARRAY(zbee_zcl_events_attr_names);
1995
1996 /* Server Commands Received */
1997 #define zbee_zcl_events_srv_rx_cmd_names_VALUE_STRING_LIST(XXX) \
1998     XXX(ZBEE_ZCL_CMD_ID_EVENTS_GET_EVENT_LOG,                   0x00, "Get Event Log" ) \
1999     XXX(ZBEE_ZCL_CMD_ID_EVENTS_CLEAR_EVENT_LOG_REQUEST,         0x01, "Clear Event Log Request" )
2000
2001 VALUE_STRING_ENUM(zbee_zcl_events_srv_rx_cmd_names);
2002 VALUE_STRING_ARRAY(zbee_zcl_events_srv_rx_cmd_names);
2003
2004 /* Server Commands Generated */
2005 #define zbee_zcl_events_srv_tx_cmd_names_VALUE_STRING_LIST(XXX) \
2006     XXX(ZBEE_ZCL_CMD_ID_EVENTS_PUBLISH_EVENT,                   0x00, "Publish Event" ) \
2007     XXX(ZBEE_ZCL_CMD_ID_EVENTS_PUBLISH_EVENT_LOG,               0x01, "Publish Event Log" ) \
2008     XXX(ZBEE_ZCL_CMD_ID_EVENTS_CLEAR_EVENT_LOG_RESPONSE,        0x02, "Clear Event Log Response" )
2009
2010 VALUE_STRING_ENUM(zbee_zcl_events_srv_tx_cmd_names);
2011 VALUE_STRING_ARRAY(zbee_zcl_events_srv_tx_cmd_names);
2012
2013 /*************************/
2014 /* Function Declarations */
2015 /*************************/
2016 void proto_register_zbee_zcl_events(void);
2017 void proto_reg_handoff_zbee_zcl_events(void);
2018
2019 /* Attribute Dissector Helpers */
2020 static void dissect_zcl_events_attr_data  (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type);
2021
2022 /*************************/
2023 /* Global Variables      */
2024 /*************************/
2025
2026 static dissector_handle_t events_handle;
2027
2028 /* Initialize the protocol and registered fields */
2029 static int proto_zbee_zcl_events = -1;
2030
2031 static int hf_zbee_zcl_events_srv_tx_cmd_id = -1;
2032 static int hf_zbee_zcl_events_srv_rx_cmd_id = -1;
2033 static int hf_zbee_zcl_events_attr_id = -1;
2034 static int hf_zbee_zcl_events_attr_reporting_status = -1;
2035
2036 /* Initialize the subtree pointers */
2037 static gint ett_zbee_zcl_events = -1;
2038
2039 /*************************/
2040 /* Function Bodies       */
2041 /*************************/
2042
2043 /**
2044  *This function is called by ZCL foundation dissector in order to decode
2045  *
2046  *@param tree pointer to data tree Wireshark uses to display packet.
2047  *@param tvb pointer to buffer containing raw packet.
2048  *@param offset pointer to buffer offset
2049  *@param attr_id attribute identifier
2050  *@param data_type attribute data type
2051 */
2052 static void
2053 dissect_zcl_events_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type)
2054 {
2055     switch (attr_id) {
2056         /* applies to all SE clusters */
2057         case ZBEE_ZCL_ATTR_ID_SE_ATTR_REPORT_STATUS_EVENTS:
2058             proto_tree_add_item(tree, hf_zbee_zcl_events_attr_reporting_status, tvb, *offset, 1, ENC_NA);
2059             *offset += 1;
2060             break;
2061
2062         default: /* Catch all */
2063             dissect_zcl_attr_data(tvb, tree, offset, data_type);
2064             break;
2065     }
2066 } /*dissect_zcl_events_attr_data*/
2067
2068 /**
2069  *ZigBee ZCL Events cluster dissector for wireshark.
2070  *
2071  *@param tvb pointer to buffer containing raw packet.
2072  *@param pinfo pointer to packet information fields
2073  *@param tree pointer to data tree Wireshark uses to display packet.
2074 */
2075 static int
2076 dissect_zbee_zcl_events(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2077 {
2078     zbee_zcl_packet   *zcl;
2079     guint             offset = 0;
2080     guint8            cmd_id;
2081     gint              rem_len;
2082
2083     /* Reject the packet if data is NULL */
2084     if (data == NULL)
2085         return 0;
2086     zcl = (zbee_zcl_packet *)data;
2087     cmd_id = zcl->cmd_id;
2088
2089     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
2090     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
2091         /* Append the command name to the info column. */
2092         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
2093             val_to_str_const(cmd_id, zbee_zcl_events_srv_rx_cmd_names, "Unknown Command"),
2094             zcl->tran_seqno);
2095
2096         /* Add the command ID. */
2097         proto_tree_add_uint(tree, hf_zbee_zcl_events_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
2098
2099         /* Check is this command has a payload, than add the payload tree */
2100         rem_len = tvb_reported_length_remaining(tvb, ++offset);
2101         if (rem_len > 0) {
2102             proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_events, NULL, "Payload");
2103
2104             /* Call the appropriate command dissector */
2105             switch (cmd_id) {
2106
2107                 case ZBEE_ZCL_CMD_ID_EVENTS_GET_EVENT_LOG:
2108                     /* Add function to dissect payload */
2109                     break;
2110
2111                 case ZBEE_ZCL_CMD_ID_EVENTS_CLEAR_EVENT_LOG_REQUEST:
2112                     /* Add function to dissect payload */
2113                     break;
2114
2115                 default:
2116                     break;
2117             }
2118         }
2119     }
2120     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
2121         /* Append the command name to the info column. */
2122         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
2123             val_to_str_const(cmd_id, zbee_zcl_events_srv_tx_cmd_names, "Unknown Command"),
2124             zcl->tran_seqno);
2125
2126         /* Add the command ID. */
2127         proto_tree_add_uint(tree, hf_zbee_zcl_events_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
2128
2129         /* Check is this command has a payload, than add the payload tree */
2130         rem_len = tvb_reported_length_remaining(tvb, ++offset);
2131         if (rem_len > 0) {
2132             proto_tree_add_subtree(tree, tvb, offset, rem_len, ett_zbee_zcl_events, NULL, "Payload");
2133
2134             /* Call the appropriate command dissector */
2135             switch (cmd_id) {
2136
2137                 case ZBEE_ZCL_CMD_ID_EVENTS_PUBLISH_EVENT:
2138                     /* Add function to dissect payload */
2139                     break;
2140
2141                 case ZBEE_ZCL_CMD_ID_EVENTS_PUBLISH_EVENT_LOG:
2142                     /* Add function to dissect payload */
2143                     break;
2144
2145                 case ZBEE_ZCL_CMD_ID_EVENTS_CLEAR_EVENT_LOG_RESPONSE:
2146                     /* Add function to dissect payload */
2147                     break;
2148
2149                 default:
2150                     break;
2151             }
2152         }
2153     }
2154
2155     return tvb_captured_length(tvb);
2156 } /*dissect_zbee_zcl_events*/
2157
2158 /**
2159  *This function registers the ZCL Events dissector
2160  *
2161 */
2162 void
2163 proto_register_zbee_zcl_events(void)
2164 {
2165     static hf_register_info hf[] = {
2166
2167         { &hf_zbee_zcl_events_attr_id,
2168             { "Attribute", "zbee_zcl_se.events.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_events_attr_names),
2169             0x0, NULL, HFILL } },
2170
2171         { &hf_zbee_zcl_events_attr_reporting_status,                         /* common to all SE clusters */
2172             { "Attribute Reporting Status", "zbee_zcl_se.events.attr.attr_reporting_status",
2173             FT_UINT8, BASE_HEX, VALS(zbee_zcl_se_reporting_status_names), 0x00, NULL, HFILL } },
2174
2175         { &hf_zbee_zcl_events_srv_tx_cmd_id,
2176             { "Command", "zbee_zcl_se.events.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_events_srv_tx_cmd_names),
2177             0x00, NULL, HFILL } },
2178
2179         { &hf_zbee_zcl_events_srv_rx_cmd_id,
2180             { "Command", "zbee_zcl_se.events.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_events_srv_rx_cmd_names),
2181             0x00, NULL, HFILL } },
2182
2183     };
2184
2185     /* ZCL Events subtrees */
2186     gint *ett[] = {
2187         &ett_zbee_zcl_events,
2188     };
2189
2190     /* Register the ZigBee ZCL Events cluster protocol name and description */
2191     proto_zbee_zcl_events = proto_register_protocol("ZigBee ZCL Events", "ZCL Events", ZBEE_PROTOABBREV_ZCL_EVENTS);
2192     proto_register_field_array(proto_zbee_zcl_events, hf, array_length(hf));
2193     proto_register_subtree_array(ett, array_length(ett));
2194
2195     /* Register the ZigBee ZCL Events dissector. */
2196     events_handle = register_dissector(ZBEE_PROTOABBREV_ZCL_EVENTS, dissect_zbee_zcl_events, proto_zbee_zcl_events);
2197 } /*proto_register_zbee_zcl_events*/
2198
2199 /**
2200  *Hands off the Zcl Events dissector.
2201  *
2202 */
2203 void
2204 proto_reg_handoff_zbee_zcl_events(void)
2205 {
2206     /* Register our dissector with the ZigBee application dissectors. */
2207     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_EVENTS, events_handle);
2208
2209     zbee_zcl_init_cluster(  proto_zbee_zcl_events,
2210                             ett_zbee_zcl_events,
2211                             ZBEE_ZCL_CID_EVENTS,
2212                             hf_zbee_zcl_events_attr_id,
2213                             hf_zbee_zcl_events_srv_rx_cmd_id,
2214                             hf_zbee_zcl_events_srv_tx_cmd_id,
2215                             (zbee_zcl_fn_attr_data)dissect_zcl_events_attr_data
2216                          );
2217 } /*proto_reg_handoff_zbee_zcl_events*/
2218
2219 /* ########################################################################## */
2220 /* #### (0x0800) KEY ESTABLISHMENT ########################################## */
2221 /* ########################################################################## */
2222
2223 /*************************/
2224 /* Defines               */
2225 /*************************/
2226
2227 #define ZBEE_ZCL_KE_USAGE_KEY_AGREEMENT                         0x08
2228 #define ZBEE_ZCL_KE_USAGE_DIGITAL_SIGNATURE                     0x80
2229
2230 /* Attributes */
2231 #define zbee_zcl_ke_attr_names_VALUE_STRING_LIST(XXX) \
2232     XXX(ZBEE_ZCL_ATTR_ID_KE_SUITE,                              0x0000, "Supported Key Establishment Suites" )
2233
2234 VALUE_STRING_ARRAY(zbee_zcl_ke_attr_names);
2235
2236 /* Server Commands Received and Generated */
2237 #define zbee_zcl_ke_srv_cmd_names_VALUE_STRING_LIST(XXX) \
2238     XXX(ZBEE_ZCL_CMD_ID_KE_INITIATE,                            0x00, "Initiate Key Establishment" ) \
2239     XXX(ZBEE_ZCL_CMD_ID_KE_EPHEMERAL,                           0x01, "Ephemeral Data" ) \
2240     XXX(ZBEE_ZCL_CMD_ID_KE_CONFIRM,                             0x02, "Confirm Key Data" ) \
2241     XXX(ZBEE_ZCL_CMD_ID_KE_TERMINATE,                           0x03, "Terminate Key Establishment" )
2242
2243 VALUE_STRING_ENUM(zbee_zcl_ke_srv_cmd_names);
2244 VALUE_STRING_ARRAY(zbee_zcl_ke_srv_cmd_names);
2245
2246 /* Suite Names */
2247 #define zbee_zcl_ke_suite_names_VALUE_STRING_LIST(XXX) \
2248     XXX(ZBEE_ZCL_KE_SUITE_1,                                    0x0001, "Crypto Suite 1 (CBKE K163)" ) \
2249     XXX(ZBEE_ZCL_KE_SUITE_2,                                    0x0002, "Crypto Suite 2 (CBKE K283)" )
2250
2251 VALUE_STRING_ENUM(zbee_zcl_ke_suite_names);
2252 VALUE_STRING_ARRAY(zbee_zcl_ke_suite_names);
2253
2254 /* Crypto Suite 2 Type Names */
2255 #define zbee_zcl_ke_type_names_VALUE_STRING_LIST(XXX) \
2256     XXX(ZBEE_ZCL_KE_TYPE_NO_EXT,                                0x00, "No Extensions" )
2257
2258 VALUE_STRING_ARRAY(zbee_zcl_ke_type_names);
2259
2260 /* Crypto Suite 2 Curve Names */
2261 #define zbee_zcl_ke_curve_names_VALUE_STRING_LIST(XXX) \
2262     XXX(ZBEE_ZCL_KE_CURVE_SECT283K1,                            0x0D, "sect283k1" )
2263
2264 VALUE_STRING_ARRAY(zbee_zcl_ke_curve_names);
2265
2266 /* Crypto Suite 2 Hash Names */
2267 #define zbee_zcl_ke_hash_names_VALUE_STRING_LIST(XXX) \
2268     XXX(ZBEE_ZCL_KE_HASH_AES_MMO,                               0x08, "AES MMO" )
2269
2270 VALUE_STRING_ARRAY(zbee_zcl_ke_hash_names);
2271
2272 #define zbee_zcl_ke_status_names_VALUE_STRING_LIST(XXX) \
2273     XXX(ZBEE_ZCL_KE_STATUS_RESERVED,                            0x00, "Reserved" ) \
2274     XXX(ZBEE_ZCL_KE_STATUS_UNKNOWN_ISSUER,                      0x01, "Unknown Issuer" ) \
2275     XXX(ZBEE_ZCL_KE_STATUS_BAD_KEY_CONFIRM,                     0x02, "Bad Key Confirm" ) \
2276     XXX(ZBEE_ZCL_KE_STATUS_BAD_MESSAGE,                         0x03, "Bad Message" ) \
2277     XXX(ZBEE_ZCL_KE_STATUS_NO_RESOURCES,                        0x04, "No Resources" ) \
2278     XXX(ZBEE_ZCL_KE_STATUS_UNSUPPORTED_SUITE,                   0x05, "Unsupported Suite" ) \
2279     XXX(ZBEE_ZCL_KE_STATUS_INVALID_CERTIFICATE,                 0x06, "Invalid Certificate" )
2280
2281 VALUE_STRING_ARRAY(zbee_zcl_ke_status_names);
2282
2283 /*************************/
2284 /* Function Declarations */
2285 /*************************/
2286
2287 void proto_register_zbee_zcl_ke(void);
2288 void proto_reg_handoff_zbee_zcl_ke(void);
2289
2290 /* Private functions prototype */
2291
2292 /*************************/
2293 /* Global Variables      */
2294 /*************************/
2295
2296 static dissector_handle_t ke_handle;
2297
2298 /* Initialize the protocol and registered fields */
2299 static int proto_zbee_zcl_ke = -1;
2300 static int hf_zbee_zcl_ke_srv_tx_cmd_id = -1;
2301 static int hf_zbee_zcl_ke_srv_rx_cmd_id = -1;
2302 static int hf_zbee_zcl_ke_attr_id = -1;
2303 static int hf_zbee_zcl_ke_suite = -1;
2304 static int hf_zbee_zcl_ke_ephemeral_time = -1;
2305 static int hf_zbee_zcl_ke_confirm_time = -1;
2306 static int hf_zbee_zcl_ke_status = -1;
2307 static int hf_zbee_zcl_ke_wait_time = -1;
2308 static int hf_zbee_zcl_ke_cert_reconstr = -1;
2309 static int hf_zbee_zcl_ke_cert_subject = -1;
2310 static int hf_zbee_zcl_ke_cert_issuer = -1;
2311 static int hf_zbee_zcl_ke_cert_profile_attr = -1;
2312 static int hf_zbee_zcl_ke_cert_type = -1;
2313 static int hf_zbee_zcl_ke_cert_serialno = -1;
2314 static int hf_zbee_zcl_ke_cert_curve = -1;
2315 static int hf_zbee_zcl_ke_cert_hash = -1;
2316 static int hf_zbee_zcl_ke_cert_valid_from = -1;
2317 static int hf_zbee_zcl_ke_cert_valid_to = -1;
2318 static int hf_zbee_zcl_ke_cert_key_usage_agreement = -1;
2319 static int hf_zbee_zcl_ke_cert_key_usage_signature = -1;
2320 static int hf_zbee_zcl_ke_ephemeral_qeu = -1;
2321 static int hf_zbee_zcl_ke_ephemeral_qev = -1;
2322 static int hf_zbee_zcl_ke_macu = -1;
2323 static int hf_zbee_zcl_ke_macv = -1;
2324
2325 /* Initialize the subtree pointers */
2326 static gint ett_zbee_zcl_ke = -1;
2327 static gint ett_zbee_zcl_ke_cert = -1;
2328 static gint ett_zbee_zcl_ke_key_usage = -1;
2329
2330 /*************************/
2331 /* Function Bodies       */
2332 /*************************/
2333
2334 /**
2335  *This function dissects the Suite 1 Certificate
2336  *
2337  *@param tvb pointer to buffer containing raw packet.
2338  *@param tree pointer to data tree Wireshark uses to display packet.
2339  *@param offset pointer to offset from caller
2340 */
2341 static void
2342 dissect_zcl_ke_suite1_certificate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2343 {
2344     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_reconstr, tvb, *offset, 22, ENC_NA);
2345     *offset += 22;
2346
2347     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_subject, tvb, *offset, 8, ENC_NA);
2348     *offset += 8;
2349
2350     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_issuer, tvb, *offset, 8, ENC_NA);
2351     *offset += 8;
2352
2353     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_profile_attr, tvb, *offset, 10, ENC_NA);
2354     *offset += 10;
2355
2356 } /*dissect_zcl_ke_suite1_certificate*/
2357
2358 /**
2359  *This function dissects the Suite 2 Certificate
2360  *
2361  *@param tvb pointer to buffer containing raw packet.
2362  *@param tree pointer to data tree Wireshark uses to display packet.
2363  *@param offset pointer to offset from caller
2364 */
2365 static void
2366 dissect_zcl_ke_suite2_certificate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2367 {
2368     nstime_t      valid_from_time;
2369     nstime_t      valid_to_time;
2370     guint32       valid_to;
2371     guint8        key_usage;
2372     proto_tree   *usage_tree;
2373
2374     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_type, tvb, *offset, 1, ENC_NA);
2375     *offset += 1;
2376
2377     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_serialno, tvb, *offset, 8, ENC_NA);
2378     *offset += 8;
2379
2380     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_curve, tvb, *offset, 1, ENC_NA);
2381     *offset += 1;
2382
2383     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_hash, tvb, *offset, 1, ENC_NA);
2384     *offset += 1;
2385
2386     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_issuer, tvb, *offset, 8, ENC_NA);
2387     *offset += 8;
2388
2389     valid_from_time.secs = (time_t)tvb_get_ntoh40(tvb, *offset);
2390     valid_from_time.nsecs = 0;
2391     proto_tree_add_time(tree, hf_zbee_zcl_ke_cert_valid_from, tvb, *offset, 5, &valid_from_time);
2392     *offset += 5;
2393
2394     valid_to = tvb_get_ntohl(tvb, *offset);
2395     if (valid_to == 0xFFFFFFFF) {
2396         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)");
2397     }
2398     else {
2399         valid_to_time.secs = valid_from_time.secs + valid_to;
2400         valid_to_time.nsecs = 0;
2401         proto_tree_add_time(tree, hf_zbee_zcl_ke_cert_valid_to, tvb, *offset, 4, &valid_to_time);
2402     }
2403     *offset += 4;
2404
2405     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_subject, tvb, *offset, 8, ENC_NA);
2406     *offset += 8;
2407
2408     key_usage = tvb_get_guint8(tvb, *offset);
2409     usage_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 1, ett_zbee_zcl_ke_key_usage, NULL, "Key Usage (0x%02x)", key_usage);
2410
2411     proto_tree_add_item(usage_tree, hf_zbee_zcl_ke_cert_key_usage_agreement, tvb, *offset, 1, ENC_NA);
2412     proto_tree_add_item(usage_tree, hf_zbee_zcl_ke_cert_key_usage_signature, tvb, *offset, 1, ENC_NA);
2413     *offset += 1;
2414
2415     proto_tree_add_item(tree, hf_zbee_zcl_ke_cert_reconstr, tvb, *offset, 37, ENC_NA);
2416     *offset += 37;
2417
2418 } /*dissect_zcl_ke_suite2_certificate*/
2419
2420 /**
2421  *This function manages the Initiate Key Establishment message
2422  *
2423  *@param tvb pointer to buffer containing raw packet.
2424  *@param tree pointer to data tree Wireshark uses to display packet.
2425  *@param offset pointer to offset from caller
2426 */
2427 static void
2428 dissect_zcl_ke_initiate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2429 {
2430     gint               rem_len;
2431     proto_tree        *subtree;
2432     guint16            suite;
2433
2434     suite = tvb_get_letohs(tvb, *offset);
2435
2436     proto_tree_add_item(tree, hf_zbee_zcl_ke_suite, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
2437     *offset += 2;
2438
2439     proto_tree_add_item(tree, hf_zbee_zcl_ke_ephemeral_time, tvb, *offset, 1, ENC_NA);
2440     *offset += 1;
2441
2442     proto_tree_add_item(tree, hf_zbee_zcl_ke_confirm_time, tvb, *offset, 1, ENC_NA);
2443     *offset += 1;
2444
2445     rem_len = tvb_reported_length_remaining(tvb, *offset);
2446     subtree = proto_tree_add_subtree(tree, tvb, *offset, rem_len, ett_zbee_zcl_ke_cert, NULL, "Implicit Certificate");
2447
2448     switch (suite) {
2449         case ZBEE_ZCL_KE_SUITE_1:
2450             dissect_zcl_ke_suite1_certificate(tvb, subtree, offset);
2451             break;
2452
2453         case ZBEE_ZCL_KE_SUITE_2:
2454             dissect_zcl_ke_suite2_certificate(tvb, subtree, offset);
2455             break;
2456
2457         default:
2458             break;
2459     }
2460 } /* dissect_zcl_ke_initiate */
2461
2462 /**
2463  *This function dissects the Ephemeral Data QEU
2464  *
2465  *@param tvb pointer to buffer containing raw packet.
2466  *@param tree pointer to data tree Wireshark uses to display packet.
2467  *@param offset pointer to offset from caller
2468 */
2469 static int
2470 dissect_zcl_ke_ephemeral_qeu(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2471 {
2472     gint length;
2473
2474     /* size depends on suite but without a session we don't know that here */
2475     /* so just report what we have */
2476     length = tvb_reported_length_remaining(tvb, *offset);
2477     proto_tree_add_item(tree, hf_zbee_zcl_ke_ephemeral_qeu, tvb, *offset, length, ENC_NA);
2478     *offset += length;
2479     return tvb_captured_length(tvb);
2480 }
2481
2482 /**
2483  *This function dissects the Ephemeral Data QEV
2484  *
2485  *@param tvb pointer to buffer containing raw packet.
2486  *@param tree pointer to data tree Wireshark uses to display packet.
2487  *@param offset pointer to offset from caller
2488 */
2489 static int
2490 dissect_zcl_ke_ephemeral_qev(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2491 {
2492     gint length;
2493
2494     /* size depends on suite but without a session we don't know that here */
2495     /* so just report what we have */
2496     length = tvb_reported_length_remaining(tvb, *offset);
2497     proto_tree_add_item(tree, hf_zbee_zcl_ke_ephemeral_qev, tvb, *offset, length, ENC_NA);
2498     *offset += length;
2499     return tvb_captured_length(tvb);
2500 }
2501
2502 /**
2503  *This function dissects the Confirm MACU
2504  *
2505  *@param tvb pointer to buffer containing raw packet.
2506  *@param tree pointer to data tree Wireshark uses to display packet.
2507  *@param offset pointer to offset from caller
2508 */
2509 static int
2510 dissect_zcl_ke_confirm_macu(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2511 {
2512     proto_tree_add_item(tree, hf_zbee_zcl_ke_macu, tvb, *offset, ZBEE_SEC_CONST_BLOCKSIZE, ENC_NA);
2513     *offset += ZBEE_SEC_CONST_BLOCKSIZE;
2514     return tvb_captured_length(tvb);
2515 }
2516
2517 /**
2518  *This function dissects the Confirm MACV
2519  *
2520  *@param tvb pointer to buffer containing raw packet.
2521  *@param tree pointer to data tree Wireshark uses to display packet.
2522  *@param offset pointer to offset from caller
2523 */
2524 static int
2525 dissect_zcl_ke_confirm_macv(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2526 {
2527     proto_tree_add_item(tree, hf_zbee_zcl_ke_macv, tvb, *offset, ZBEE_SEC_CONST_BLOCKSIZE, ENC_NA);
2528     *offset += ZBEE_SEC_CONST_BLOCKSIZE;
2529     return tvb_captured_length(tvb);
2530 }
2531
2532 /**
2533  *This function dissects the Terminate Key Establishment message
2534  *
2535  *@param tvb pointer to buffer containing raw packet.
2536  *@param tree pointer to data tree Wireshark uses to display packet.
2537  *@param offset pointer to offset from caller
2538 */
2539 static void
2540 dissect_zcl_ke_terminate(tvbuff_t *tvb, proto_tree *tree, guint *offset)
2541 {
2542     proto_tree_add_item(tree, hf_zbee_zcl_ke_status, tvb, *offset, 1, ENC_NA);
2543     *offset += 1;
2544
2545     proto_tree_add_item(tree, hf_zbee_zcl_ke_wait_time, tvb, *offset, 1, ENC_NA);
2546     *offset += 1;
2547
2548     proto_tree_add_item(tree, hf_zbee_zcl_ke_suite, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
2549     *offset += 2;
2550 }
2551
2552 /**
2553  *ZigBee ZCL Key Establishment cluster dissector for wireshark.
2554  *
2555  *@param tvb pointer to buffer containing raw packet.
2556  *@param pinfo pointer to packet information fields
2557  *@param tree pointer to data tree Wireshark uses to display packet.
2558 */
2559 static int
2560 dissect_zbee_zcl_ke(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2561 {
2562     zbee_zcl_packet   *zcl;
2563     guint             offset = 0;
2564     guint8            cmd_id;
2565     gint              rem_len;
2566
2567     /* Reject the packet if data is NULL */
2568     if (data == NULL)
2569         return 0;
2570     zcl = (zbee_zcl_packet *)data;
2571     cmd_id = zcl->cmd_id;
2572
2573     /*  Create a subtree for the ZCL Command frame, and add the command ID to it. */
2574     if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) {
2575         /* Append the command name to the info column. */
2576         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
2577             val_to_str_const(cmd_id, zbee_zcl_ke_srv_cmd_names, "Unknown Command"),
2578             zcl->tran_seqno);
2579
2580         /* Add the command ID. */
2581         proto_tree_add_uint(tree, hf_zbee_zcl_ke_srv_rx_cmd_id, tvb, offset, 1, cmd_id);
2582
2583         /* Check is this command has a payload, than add the payload tree */
2584         rem_len = tvb_reported_length_remaining(tvb, offset);
2585         offset += 1; /* delay from last add_item */
2586         if (rem_len > 0) {
2587
2588             /* Call the appropriate command dissector */
2589             switch (cmd_id) {
2590                 case ZBEE_ZCL_CMD_ID_KE_INITIATE:
2591                     dissect_zcl_ke_initiate(tvb, tree, &offset);
2592                     break;
2593
2594                 case ZBEE_ZCL_CMD_ID_KE_EPHEMERAL:
2595                     return dissect_zcl_ke_ephemeral_qeu(tvb, tree, &offset);
2596
2597                 case ZBEE_ZCL_CMD_ID_KE_CONFIRM:
2598                     return dissect_zcl_ke_confirm_macu(tvb, tree, &offset);
2599
2600                 case ZBEE_ZCL_CMD_ID_KE_TERMINATE:
2601                     dissect_zcl_ke_terminate(tvb, tree, &offset);
2602                     break;
2603
2604                 default:
2605                     break;
2606             }
2607         }
2608     }
2609     else { /* ZBEE_ZCL_FCF_TO_CLIENT */
2610         /* Append the command name to the info column. */
2611         col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
2612             val_to_str_const(cmd_id, zbee_zcl_ke_srv_cmd_names, "Unknown Command"),
2613             zcl->tran_seqno);
2614
2615         /* Add the command ID. */
2616         proto_tree_add_uint(tree, hf_zbee_zcl_ke_srv_tx_cmd_id, tvb, offset, 1, cmd_id);
2617
2618         /* Check is this command has a payload, than add the payload tree */
2619         rem_len = tvb_reported_length_remaining(tvb, ++offset);
2620         if (rem_len > 0) {
2621             /* Call the appropriate command dissector */
2622             switch (cmd_id) {
2623                 case ZBEE_ZCL_CMD_ID_KE_INITIATE:
2624                     dissect_zcl_ke_initiate(tvb, tree, &offset);
2625                     break;
2626
2627                 case ZBEE_ZCL_CMD_ID_KE_EPHEMERAL:
2628                     return dissect_zcl_ke_ephemeral_qev(tvb, tree, &offset);
2629
2630                 case ZBEE_ZCL_CMD_ID_KE_CONFIRM:
2631                     return dissect_zcl_ke_confirm_macv(tvb, tree, &offset);
2632
2633                 case ZBEE_ZCL_CMD_ID_KE_TERMINATE:
2634                     dissect_zcl_ke_terminate(tvb, tree, &offset);
2635                     break;
2636
2637                 default:
2638                     break;
2639             }
2640         }
2641     }
2642
2643     return tvb_captured_length(tvb);
2644 } /*dissect_zbee_zcl_ke*/
2645
2646
2647 /**
2648  *This function registers the ZCL Messaging dissector
2649  *
2650 */
2651 void
2652 proto_register_zbee_zcl_ke(void)
2653 {
2654     static hf_register_info hf[] = {
2655
2656         { &hf_zbee_zcl_ke_attr_id,
2657             { "Attribute", "zbee_zcl_se.ke.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_ke_attr_names),
2658             0x00, NULL, HFILL } },
2659
2660         { &hf_zbee_zcl_ke_srv_tx_cmd_id,
2661             { "Command", "zbee_zcl_se.ke.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_srv_cmd_names),
2662             0x00, NULL, HFILL } },
2663
2664         { &hf_zbee_zcl_ke_srv_rx_cmd_id,
2665             { "Command", "zbee_zcl_se.ke.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_srv_cmd_names),
2666             0x00, NULL, HFILL } },
2667
2668         { &hf_zbee_zcl_ke_suite,
2669             { "Key Establishment Suite", "zbee_zcl_se.ke.attr.suite", FT_UINT16, BASE_HEX, VALS(zbee_zcl_ke_suite_names),
2670             0x00, NULL, HFILL } },
2671
2672         { &hf_zbee_zcl_ke_ephemeral_time,
2673             { "Ephemeral Data Generate Time", "zbee_zcl_se.ke.init.ephemeral.time", FT_UINT8, BASE_DEC, NULL,
2674             0, NULL, HFILL } },
2675
2676         { &hf_zbee_zcl_ke_confirm_time,
2677             { "Confirm Key Generate Time", "zbee_zcl_se.ke.init.confirm.time", FT_UINT8, BASE_DEC, NULL,
2678             0, NULL, HFILL } },
2679
2680         { &hf_zbee_zcl_ke_status,
2681             { "Status", "zbee_zcl_se.ke.terminate.status", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_status_names),
2682             0x00, NULL, HFILL } },
2683
2684         { &hf_zbee_zcl_ke_wait_time,
2685             { "Wait Time", "zbee_zcl_se.ke.terminate.wait.time", FT_UINT8, BASE_DEC, NULL,
2686             0, NULL, HFILL } },
2687
2688         { &hf_zbee_zcl_ke_cert_reconstr,
2689             { "Public Key", "zbee_zcl_se.ke.cert.reconst", FT_BYTES, BASE_NONE, NULL,
2690             0, NULL, HFILL } },
2691
2692         { &hf_zbee_zcl_ke_cert_subject,
2693             { "Subject", "zbee_zcl_se.ke.cert.subject", FT_BYTES, BASE_NONE, NULL,
2694             0, NULL, HFILL } },
2695
2696         { &hf_zbee_zcl_ke_cert_issuer,
2697             { "Issuer", "zbee_zcl_se.ke.cert.issuer", FT_BYTES, BASE_NONE, NULL,
2698             0, NULL, HFILL } },
2699
2700         { &hf_zbee_zcl_ke_cert_profile_attr,
2701             { "Profile Attribute Data", "zbee_zcl_se.ke.cert.profile", FT_BYTES, BASE_NONE, NULL,
2702             0, NULL, HFILL } },
2703
2704         { &hf_zbee_zcl_ke_cert_type,
2705             { "Type", "zbee_zcl_se.ke.cert.type", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_type_names),
2706             0, NULL, HFILL } },
2707
2708         { &hf_zbee_zcl_ke_cert_serialno,
2709             { "Serial No", "zbee_zcl_se.ke.cert.serialno", FT_UINT64, BASE_HEX, NULL,
2710             0, NULL, HFILL } },
2711
2712         { &hf_zbee_zcl_ke_cert_curve,
2713             { "Curve", "zbee_zcl_se.ke.cert.curve", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_curve_names),
2714             0, NULL, HFILL } },
2715
2716         { &hf_zbee_zcl_ke_cert_hash,
2717             { "Hash", "zbee_zcl_se.ke.cert.hash", FT_UINT8, BASE_HEX, VALS(zbee_zcl_ke_hash_names),
2718             0, NULL, HFILL } },
2719
2720         { &hf_zbee_zcl_ke_cert_valid_from,
2721             { "Valid From", "zbee_zcl_se.ke.cert.valid.from", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
2722             0, NULL, HFILL } },
2723
2724         { &hf_zbee_zcl_ke_cert_valid_to,
2725             { "Valid To", "zbee_zcl_se.ke.cert.valid.to", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
2726             0, NULL, HFILL } },
2727
2728         { &hf_zbee_zcl_ke_cert_key_usage_agreement,
2729             { "Key Agreement", "zbee_zcl_se.ke.cert.key.usage.agreement", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
2730             ZBEE_ZCL_KE_USAGE_KEY_AGREEMENT, NULL, HFILL }},
2731
2732         { &hf_zbee_zcl_ke_cert_key_usage_signature,
2733             { "Digital Signature", "zbee_zcl_se.ke.cert.key.usage.signature", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
2734             ZBEE_ZCL_KE_USAGE_DIGITAL_SIGNATURE, NULL, HFILL }},
2735
2736         { &hf_zbee_zcl_ke_ephemeral_qeu,
2737             { "Ephemeral Data (QEU)", "zbee_zcl_se.ke.qeu", FT_BYTES, BASE_NONE, NULL,
2738             0, NULL, HFILL } },
2739
2740         { &hf_zbee_zcl_ke_ephemeral_qev,
2741             { "Ephemeral Data (QEV)", "zbee_zcl_se.ke.qev", FT_BYTES, BASE_NONE, NULL,
2742             0, NULL, HFILL } },
2743
2744         { &hf_zbee_zcl_ke_macu,
2745             { "Message Authentication Code (MACU)", "zbee_zcl_se.ke.macu", FT_BYTES, BASE_NONE, NULL,
2746             0, NULL, HFILL } },
2747
2748         { &hf_zbee_zcl_ke_macv,
2749             { "Message Authentication Code (MACV)", "zbee_zcl_se.ke.macv", FT_BYTES, BASE_NONE, NULL,
2750             0, NULL, HFILL } },
2751     };
2752
2753     /* subtrees */
2754     gint *ett[] = {
2755         &ett_zbee_zcl_ke,
2756         &ett_zbee_zcl_ke_cert,
2757         &ett_zbee_zcl_ke_key_usage,
2758     };
2759
2760     /* Register the ZigBee ZCL Messaging cluster protocol name and description */
2761     proto_zbee_zcl_ke = proto_register_protocol("ZigBee ZCL Key Establishment", "ZCL Key Establishment", ZBEE_PROTOABBREV_ZCL_KE);
2762     proto_register_field_array(proto_zbee_zcl_ke, hf, array_length(hf));
2763     proto_register_subtree_array(ett, array_length(ett));
2764
2765     /* Register the ZigBee ZCL Messaging dissector. */
2766     ke_handle = register_dissector(ZBEE_PROTOABBREV_ZCL_KE, dissect_zbee_zcl_ke, proto_zbee_zcl_ke);
2767 } /*proto_register_zbee_zcl_ke*/
2768
2769 /**
2770  *Hands off the Zcl Key Establishment dissector.
2771  *
2772 */
2773 void
2774 proto_reg_handoff_zbee_zcl_ke(void)
2775 {
2776     /* Register our dissector with the ZigBee application dissectors. */
2777     dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_KE, ke_handle);
2778
2779     zbee_zcl_init_cluster(  proto_zbee_zcl_ke,
2780                             ett_zbee_zcl_ke,
2781                             ZBEE_ZCL_CID_KE,
2782                             hf_zbee_zcl_ke_attr_id,
2783                             hf_zbee_zcl_ke_srv_rx_cmd_id,
2784                             hf_zbee_zcl_ke_srv_tx_cmd_id,
2785                             NULL
2786                          );
2787 } /*proto_reg_handoff_zbee_zcl_ke*/
2788
2789 /*
2790  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2791  *
2792  * Local variables:
2793  * c-basic-offset: 4
2794  * tab-width: 8
2795  * indent-tabs-mode: nil
2796  * End:
2797  *
2798  * vi: set shiftwidth=4 tabstop=8 expandtab:
2799  * :indentSize=4:tabSize=8:noTabs=true:
2800  */