Fixup: tvb_get_string(z) -> tvb_get_string(z)_enc
[metze/wireshark/wip.git] / epan / dissectors / packet-zbee-nwk.c
1 /* packet-zbee-nwk.c
2  * Dissector routines for the ZigBee Network Layer (NWK)
3  * By Owen Kirby <osk@exegin.com>
4  * Copyright 2009 Exegin Technologies Limited
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 /*  Include Files */
26 #include "config.h"
27
28 #include <string.h>
29
30 #include <glib.h>
31
32 #include <epan/packet.h>
33 #include <epan/exceptions.h>
34 #include <epan/prefs.h>
35 #include <epan/addr_resolv.h>
36 #include <epan/expert.h>
37 #include <epan/wmem/wmem.h>
38
39 #include "packet-ieee802154.h"
40 #include "packet-zbee.h"
41 #include "packet-zbee-nwk.h"
42 #include "packet-zbee-security.h"
43
44 /*************************/
45 /* Function Declarations */
46 /*************************/
47 /* Dissector Routines */
48 static int         dissect_zbee_nwk        (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
49 static void        dissect_zbee_nwk_cmd    (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet* packet);
50 static int         dissect_zbee_beacon     (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
51 static int         dissect_zbip_beacon     (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
52
53 /* Command Dissector Helpers */
54 static guint       dissect_zbee_nwk_route_req  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
55                                                 zbee_nwk_packet * packet, guint offset);
56 static guint       dissect_zbee_nwk_route_rep  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 version);
57 static guint       dissect_zbee_nwk_status     (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
58 static guint       dissect_zbee_nwk_leave      (tvbuff_t *tvb, proto_tree *tree, guint offset);
59 static guint       dissect_zbee_nwk_route_rec  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
60                                                 zbee_nwk_packet * packet, guint offset);
61 static guint       dissect_zbee_nwk_rejoin_req (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
62                                                 zbee_nwk_packet * packet, guint offset);
63 static guint       dissect_zbee_nwk_rejoin_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
64                                                 zbee_nwk_packet * packet, guint offset);
65 static guint       dissect_zbee_nwk_link_status(tvbuff_t *tvb, proto_tree *tree, guint offset);
66 static guint       dissect_zbee_nwk_report     (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
67 static guint       dissect_zbee_nwk_update     (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
68 static void        proto_init_zbee_nwk         (void);
69 void               proto_register_zbee_nwk(void);
70 void               proto_reg_handoff_zbee_nwk(void);
71
72 /********************/
73 /* Global Variables */
74 /********************/
75 static int proto_zbee_nwk = -1;
76 static int hf_zbee_nwk_frame_type = -1;
77 static int hf_zbee_nwk_proto_version = -1;
78 static int hf_zbee_nwk_discover_route = -1;
79 static int hf_zbee_nwk_multicast = -1;
80 static int hf_zbee_nwk_security = -1;
81 static int hf_zbee_nwk_source_route = -1;
82 static int hf_zbee_nwk_ext_dst = -1;
83 static int hf_zbee_nwk_ext_src = -1;
84 static int hf_zbee_nwk_dst = -1;
85 static int hf_zbee_nwk_src = -1;
86 static int hf_zbee_nwk_radius = -1;
87 static int hf_zbee_nwk_seqno = -1;
88 static int hf_zbee_nwk_mcast_mode = -1;
89 static int hf_zbee_nwk_mcast_radius = -1;
90 static int hf_zbee_nwk_mcast_max_radius = -1;
91 static int hf_zbee_nwk_dst64 = -1;
92 static int hf_zbee_nwk_src64 = -1;
93 static int hf_zbee_nwk_src64_origin = -1;
94 static int hf_zbee_nwk_relay_count = -1;
95 static int hf_zbee_nwk_relay_index = -1;
96
97 static int hf_zbee_nwk_cmd_id = -1;
98 static int hf_zbee_nwk_cmd_addr = -1;
99 static int hf_zbee_nwk_cmd_route_id = -1;
100 static int hf_zbee_nwk_cmd_route_dest = -1;
101 static int hf_zbee_nwk_cmd_route_orig = -1;
102 static int hf_zbee_nwk_cmd_route_resp = -1;
103 static int hf_zbee_nwk_cmd_route_dest_ext = -1;
104 static int hf_zbee_nwk_cmd_route_orig_ext = -1;
105 static int hf_zbee_nwk_cmd_route_resp_ext = -1;
106 static int hf_zbee_nwk_cmd_route_cost = -1;
107 static int hf_zbee_nwk_cmd_route_opt_repair = -1;
108 static int hf_zbee_nwk_cmd_route_opt_multicast = -1;
109 static int hf_zbee_nwk_cmd_route_opt_dest_ext = -1;
110 static int hf_zbee_nwk_cmd_route_opt_resp_ext = -1;
111 static int hf_zbee_nwk_cmd_route_opt_orig_ext = -1;
112 static int hf_zbee_nwk_cmd_route_opt_many_to_one = -1;
113 static int hf_zbee_nwk_cmd_nwk_status = -1;
114 static int hf_zbee_nwk_cmd_leave_rejoin = -1;
115 static int hf_zbee_nwk_cmd_leave_request = -1;
116 static int hf_zbee_nwk_cmd_leave_children = -1;
117 static int hf_zbee_nwk_cmd_relay_count = -1;
118 static int hf_zbee_nwk_cmd_cinfo_alt_coord = -1;
119 static int hf_zbee_nwk_cmd_cinfo_type = -1;
120 static int hf_zbee_nwk_cmd_cinfo_power = -1;
121 static int hf_zbee_nwk_cmd_cinfo_idle_rx = -1;
122 static int hf_zbee_nwk_cmd_cinfo_security = -1;
123 static int hf_zbee_nwk_cmd_cinfo_alloc = -1;
124 static int hf_zbee_nwk_cmd_rejoin_status = -1;
125 static int hf_zbee_nwk_cmd_link_last = -1;
126 static int hf_zbee_nwk_cmd_link_first = -1;
127 static int hf_zbee_nwk_cmd_link_count = -1;
128 static int hf_zbee_nwk_cmd_report_type = -1;
129 static int hf_zbee_nwk_cmd_report_count = -1;
130 static int hf_zbee_nwk_cmd_update_type = -1;
131 static int hf_zbee_nwk_cmd_update_count = -1;
132 static int hf_zbee_nwk_cmd_update_id = -1;
133 static int hf_zbee_nwk_cmd_epid = -1;
134
135 /*  ZigBee Beacons */
136 static int hf_zbee_beacon_protocol = -1;
137 static int hf_zbee_beacon_stack_profile = -1;
138 static int hf_zbee_beacon_version = -1;
139 static int hf_zbee_beacon_router_capacity = -1;
140 static int hf_zbee_beacon_depth = -1;
141 static int hf_zbee_beacon_end_device_capacity = -1;
142 static int hf_zbee_beacon_epid = -1;
143 static int hf_zbee_beacon_tx_offset = -1;
144 static int hf_zbee_beacon_update_id = -1;
145
146 static int hf_zbip_beacon_allow_join = -1;
147 static int hf_zbip_beacon_router_capacity = -1;
148 static int hf_zbip_beacon_host_capacity = -1;
149 static int hf_zbip_beacon_unsecure = -1;
150 static int hf_zbip_beacon_network_id = -1;
151
152 static gint ett_zbee_nwk = -1;
153 static gint ett_zbee_beacon = -1;
154 static gint ett_zbee_nwk_fcf = -1;
155 static gint ett_zbee_nwk_fcf_ext = -1;
156 static gint ett_zbee_nwk_mcast = -1;
157 static gint ett_zbee_nwk_route = -1;
158 static gint ett_zbee_nwk_cmd = -1;
159 static gint ett_zbee_nwk_cmd_options = -1;
160 static gint ett_zbee_nwk_cmd_cinfo = -1;
161
162 static expert_field ei_zbee_nwk_missing_payload = EI_INIT;
163
164 static dissector_handle_t   data_handle;
165 static dissector_handle_t   aps_handle;
166 static dissector_handle_t   zbee_gp_handle;
167
168 /********************/
169 /* Field Names      */
170 /********************/
171 /* Frame Types */
172 static const value_string zbee_nwk_frame_types[] = {
173     { ZBEE_NWK_FCF_DATA,    "Data" },
174     { ZBEE_NWK_FCF_CMD,     "Command" },
175     { 0, NULL }
176 };
177
178 /* Route Discovery Modes */
179 static const value_string zbee_nwk_discovery_modes[] = {
180     { ZBEE_NWK_FCF_DISCOVERY_SUPPRESS,  "Suppress" },
181     { ZBEE_NWK_FCF_DISCOVERY_ENABLE,    "Enable" },
182     { ZBEE_NWK_FCF_DISCOVERY_FORCE,     "Force" },
183     { 0, NULL }
184 };
185
186 /* Command Names*/
187 static const value_string zbee_nwk_cmd_names[] = {
188     { ZBEE_NWK_CMD_ROUTE_REQ,       "Route Request" },
189     { ZBEE_NWK_CMD_ROUTE_REPLY,     "Route Reply" },
190     { ZBEE_NWK_CMD_NWK_STATUS,      "Network Status" },
191     { ZBEE_NWK_CMD_LEAVE,           "Leave" },
192     { ZBEE_NWK_CMD_ROUTE_RECORD,    "Route Record" },
193     { ZBEE_NWK_CMD_REJOIN_REQ,      "Rejoin Request" },
194     { ZBEE_NWK_CMD_REJOIN_RESP,     "Rejoin Response" },
195     { ZBEE_NWK_CMD_LINK_STATUS,     "Link Status" },
196     { ZBEE_NWK_CMD_NWK_REPORT,      "Network Report" },
197     { ZBEE_NWK_CMD_NWK_UPDATE,      "Network Update" },
198     { 0, NULL }
199 };
200
201 /* Many-To-One Route Discovery Modes. */
202 static const value_string zbee_nwk_cmd_route_many_modes[] = {
203     { ZBEE_NWK_CMD_ROUTE_OPTION_MANY_NONE,  "Not Many-to-One" },
204     { ZBEE_NWK_CMD_ROUTE_OPTION_MANY_REC,   "With Source Routing" },
205     { ZBEE_NWK_CMD_ROUTE_OPTION_MANY_NOREC, "Without Source Routing" },
206     { 0, NULL }
207 };
208
209 /* Rejoin Status Codes */
210 static const value_string zbee_nwk_rejoin_codes[] = {
211     { IEEE802154_CMD_ASRSP_AS_SUCCESS,      "Success" },
212     { IEEE802154_CMD_ASRSP_PAN_FULL,        "PAN Full" },
213     { IEEE802154_CMD_ASRSP_PAN_DENIED,      "PAN Access Denied" },
214     { 0, NULL }
215 };
216
217 /* Network Report Types */
218 static const value_string zbee_nwk_report_types[] = {
219     { ZBEE_NWK_CMD_NWK_REPORT_ID_PAN_CONFLICT,  "PAN Identifier Conflict" },
220     { 0, NULL }
221 };
222
223 /* Network Update Types */
224 static const value_string zbee_nwk_update_types[] = {
225     { ZBEE_NWK_CMD_NWK_UPDATE_ID_PAN_UPDATE,  "PAN Identifier Update" },
226     { 0, NULL }
227 };
228
229 /* Network Status Codes */
230 static const value_string zbee_nwk_status_codes[] = {
231     { ZBEE_NWK_STATUS_NO_ROUTE_AVAIL,       "No Route Available" },
232     { ZBEE_NWK_STATUS_TREE_LINK_FAIL,       "Tree Link Failure" },
233     { ZBEE_NWK_STATUS_NON_TREE_LINK_FAIL,   "Non-tree Link Failure" },
234     { ZBEE_NWK_STATUS_LOW_BATTERY,          "Low Battery" },
235     { ZBEE_NWK_STATUS_NO_ROUTING,           "No Routing Capacity" },
236     { ZBEE_NWK_STATUS_NO_INDIRECT,          "No Indirect Capacity" },
237     { ZBEE_NWK_STATUS_INDIRECT_EXPIRE,      "Indirect Transaction Expiry" },
238     { ZBEE_NWK_STATUS_DEVICE_UNAVAIL,       "Target Device Unavailable" },
239     { ZBEE_NWK_STATUS_ADDR_UNAVAIL,         "Target Address Unallocated" },
240     { ZBEE_NWK_STATUS_PARENT_LINK_FAIL,     "Parent Link Failure" },
241     { ZBEE_NWK_STATUS_VALIDATE_ROUTE,       "Validate Route" },
242     { ZBEE_NWK_STATUS_SOURCE_ROUTE_FAIL,    "Source Route Failure" },
243     { ZBEE_NWK_STATUS_MANY_TO_ONE_FAIL,     "Many-to-One Route Failure" },
244     { ZBEE_NWK_STATUS_ADDRESS_CONFLICT,     "Address Conflict" },
245     { ZBEE_NWK_STATUS_VERIFY_ADDRESS,       "Verify Address" },
246     { ZBEE_NWK_STATUS_PANID_UPDATE,         "PAN ID Update" },
247     { ZBEE_NWK_STATUS_ADDRESS_UPDATE,       "Network Address Update" },
248     { ZBEE_NWK_STATUS_BAD_FRAME_COUNTER,    "Bad Frame Counter" },
249     { ZBEE_NWK_STATUS_BAD_KEY_SEQNO,        "Bad Key Sequence Number" },
250     { 0, NULL }
251 };
252
253 /* Stack Profile Values. */
254 static const value_string zbee_nwk_stack_profiles[] = {
255     { 0x00, "Network Specific" },
256     { 0x01, "ZigBee Home" },
257     { 0x02, "ZigBee PRO" },
258     { 0, NULL }
259 };
260
261 /* TODO: much of the following copied from ieee80154 dissector */
262 /*-------------------------------------
263  * Hash Tables and Lists
264  *-------------------------------------
265  */
266 ieee802154_map_tab_t zbee_nwk_map = { NULL, NULL };
267 GHashTable *zbee_table_nwk_keyring = NULL;
268 GHashTable *zbee_table_link_keyring = NULL;
269
270 /*FUNCTION:------------------------------------------------------
271  *  NAME
272  *      zbee_get_bit_field
273  *  DESCRIPTION
274  *      Extracts an integer sub-field from an int with a given mask
275  *      if the mask is 0, this will return 0, if the mask is non-
276  *      continuous the output is undefined.
277  *  PARAMETERS
278  *      guint       input
279  *      guint       mask
280  *  RETURNS
281  *      guint
282  *---------------------------------------------------------------
283  */
284 guint
285 zbee_get_bit_field(guint input, guint mask)
286 {
287     /* Sanity Check, don't want infinite loops. */
288     if (mask == 0) return 0;
289     /* Shift input and mask together. */
290     while (!(mask & 0x1)) {
291         input >>= 1;
292         mask >>=1;
293     } /* while */
294     return (input & mask);
295 } /* zbee_get_bit_field */
296
297 /*FUNCTION:------------------------------------------------------
298  *  NAME
299  *      dissect_zbee_nwk_heur
300  *  DESCRIPTION
301  *      Heuristic interpreter for the ZigBee network dissectors.
302  *  PARAMETERS
303  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
304  *      packet_into *pinfo  - pointer to packet information fields
305  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
306  *  RETURNS
307  *      Boolean value, whether it handles the packet or not.
308  *---------------------------------------------------------------
309  */
310 static gboolean
311 dissect_zbee_nwk_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
312 {
313     ieee802154_packet   *packet = (ieee802154_packet *)data;
314     guint16             fcf;
315     guint               ver;
316
317     /* All ZigBee frames must always have a 16-bit source and destination address. */
318     if (packet == NULL) return FALSE;
319     if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) return FALSE;
320     if (packet->dst_addr_mode != IEEE802154_FCF_ADDR_SHORT) return FALSE;
321
322     /* If the frame type and version are not sane, then it's probably not ZigBee. */
323     fcf = tvb_get_letohs(tvb, 0);
324     ver = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_VERSION);
325     if ((ver < ZBEE_VERSION_2004) || (ver > ZBEE_VERSION_2007)) return FALSE;
326     if (!try_val_to_str(zbee_get_bit_field(fcf, ZBEE_NWK_FCF_FRAME_TYPE), zbee_nwk_frame_types)) return FALSE;
327
328     /* Assume it's ZigBee */
329     dissect_zbee_nwk(tvb, pinfo, tree, packet);
330     return TRUE;
331 } /* dissect_zbee_heur */
332
333 /*FUNCTION:------------------------------------------------------
334  *  NAME
335  *      dissect_zbee_nwk_full
336  *  DESCRIPTION
337  *      ZigBee NWK packet dissection routine for 2006, 2007 and Pro stack versions.
338  *  PARAMETERS
339  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
340  *      packet_into *pinfo  - pointer to packet information fields.
341  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
342  *      void *data          - raw packet private data.
343  *  RETURNS
344  *      int
345  *---------------------------------------------------------------
346  */
347
348 static int
349 dissect_zbee_nwk_full(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
350 {
351     tvbuff_t            *payload_tvb = NULL;
352
353     proto_item          *proto_root = NULL;
354     proto_item          *ti = NULL;
355     proto_tree          *nwk_tree = NULL;
356     proto_tree          *field_tree = NULL;
357
358     zbee_nwk_packet     packet;
359     ieee802154_packet   *ieee_packet;
360
361     guint               offset = 0;
362     static gchar        src_addr[32], dst_addr[32]; /* has to be static due to SET_ADDRESS */
363
364     guint16             fcf;
365
366     ieee802154_short_addr   addr16;
367     ieee802154_map_rec     *map_rec;
368     ieee802154_hints_t     *ieee_hints;
369
370     zbee_nwk_hints_t       *nwk_hints;
371     gboolean                unicast_src;
372
373     /* Reject the packet if data is NULL */
374     if (data == NULL)
375         return 0;
376     ieee_packet = (ieee802154_packet *)data;
377
378     memset(&packet, 0, sizeof(packet));
379
380     /* Set up hint structures */
381     if (!pinfo->fd->flags.visited) {
382         /* Allocate frame data with hints for upper layers */
383         nwk_hints = wmem_new0(wmem_file_scope(), zbee_nwk_hints_t);
384         p_add_proto_data(wmem_file_scope(), pinfo, proto_zbee_nwk, 0, nwk_hints);
385     } else {
386         /* Retrieve existing structure */
387         nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_zbee_nwk, 0);
388     }
389
390     ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
391             proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
392
393     /* Add ourself to the protocol column, clear the info column, and create the protocol tree. */
394     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee");
395     col_clear(pinfo->cinfo, COL_INFO);
396     if (tree) {
397         proto_root = proto_tree_add_protocol_format(tree, proto_zbee_nwk, tvb, offset,
398                                                     tvb_length(tvb), "ZigBee Network Layer");
399         nwk_tree = proto_item_add_subtree(proto_root, ett_zbee_nwk);
400     }
401
402     /* Get and parse the FCF */
403     fcf = tvb_get_letohs(tvb, offset);
404     packet.type         = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_FRAME_TYPE);
405     packet.version      = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_VERSION);
406     packet.discovery    = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_DISCOVER_ROUTE);
407     packet.security     = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_SECURITY);
408     packet.multicast    = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_MULTICAST);
409     packet.route        = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_SOURCE_ROUTE);
410     packet.ext_dst      = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_EXT_DEST);
411     packet.ext_src      = zbee_get_bit_field(fcf, ZBEE_NWK_FCF_EXT_SOURCE);
412
413     /* Display the FCF. */
414     if (tree) {
415         /* Create a subtree for the FCF. */
416         ti = proto_tree_add_text(nwk_tree, tvb, offset, 2, "Frame Control Field: %s (0x%04x)",
417                 val_to_str_const(packet.type, zbee_nwk_frame_types, "Unknown"), fcf);
418         field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_fcf);
419         proto_tree_add_item(field_tree, hf_zbee_nwk_frame_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
420
421         /*  Add the rest of the fcf fields to the subtree */
422         proto_tree_add_item(field_tree, hf_zbee_nwk_proto_version, tvb, offset, 2, ENC_LITTLE_ENDIAN);
423         proto_tree_add_item(field_tree, hf_zbee_nwk_discover_route, tvb, offset, 2, ENC_LITTLE_ENDIAN);
424         if (packet.version >= ZBEE_VERSION_2007) {
425             proto_tree_add_item(field_tree, hf_zbee_nwk_multicast, tvb, offset, 2, ENC_LITTLE_ENDIAN);
426         }
427         proto_tree_add_item(field_tree, hf_zbee_nwk_security, tvb, offset, 2, ENC_LITTLE_ENDIAN);
428         if (packet.version >= ZBEE_VERSION_2007) {
429             proto_tree_add_item(field_tree, hf_zbee_nwk_source_route, tvb, offset, 2, ENC_LITTLE_ENDIAN);
430             proto_tree_add_item(field_tree, hf_zbee_nwk_ext_dst, tvb, offset, 2, ENC_LITTLE_ENDIAN);
431             proto_tree_add_item(field_tree, hf_zbee_nwk_ext_src, tvb, offset, 2, ENC_LITTLE_ENDIAN);
432         }
433     }
434     offset += 2;
435
436     /* Add the frame type to the info column and protocol root. */
437     if (tree) {
438         proto_item_append_text(proto_root, " %s", val_to_str_const(packet.type, zbee_nwk_frame_types, "Unknown Type"));
439     }
440     col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet.type, zbee_nwk_frame_types, "Reserved Frame Type"));
441
442     /* Get the destination address. */
443     packet.dst = tvb_get_letohs(tvb, offset);
444     proto_tree_add_uint(nwk_tree, hf_zbee_nwk_dst, tvb, offset, 2, packet.dst);
445
446     offset += 2;
447
448     /* Display the destination address. */
449     if (   (packet.dst == ZBEE_BCAST_ALL)
450         || (packet.dst == ZBEE_BCAST_ACTIVE)
451         || (packet.dst == ZBEE_BCAST_ROUTERS)){
452         g_snprintf(dst_addr, 32, "Broadcast");
453     }
454     else {
455         g_snprintf(dst_addr, 32, "0x%04x", packet.dst);
456     }
457
458     SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr);
459     SET_ADDRESS(&pinfo->net_dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr);
460
461     if (tree) {
462         proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
463     }
464     col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
465
466
467     /* Get the short nwk source address and pass it to upper layers */
468     packet.src = tvb_get_letohs(tvb, offset);
469     if (nwk_hints) nwk_hints->src = packet.src;
470     if (tree) {
471         proto_tree_add_uint(nwk_tree, hf_zbee_nwk_src, tvb, offset, 2, packet.src);
472     }
473     offset += 2;
474
475     /* Display the source address. */
476     if (   (packet.src == ZBEE_BCAST_ALL)
477         || (packet.src == ZBEE_BCAST_ACTIVE)
478         || (packet.src == ZBEE_BCAST_ROUTERS)){
479         /* Source Broadcast doesn't make much sense. */
480         g_snprintf(src_addr, 32, "Unexpected Source Broadcast");
481         unicast_src = FALSE;
482     }
483     else {
484         g_snprintf(src_addr, 32, "0x%04x", packet.src);
485         unicast_src = TRUE;
486     }
487
488     SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr);
489     SET_ADDRESS(&pinfo->net_src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr);
490
491     if (tree) {
492         proto_item_append_text(proto_root, ", Src: %s", src_addr);
493     }
494     col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
495
496     /* Get and display the radius. */
497     packet.radius = tvb_get_guint8(tvb, offset);
498     if (tree) {
499         proto_tree_add_uint(nwk_tree, hf_zbee_nwk_radius, tvb, offset, 1, packet.radius);
500     }
501     offset += 1;
502
503     /* Get and display the sequence number. */
504     packet.seqno = tvb_get_guint8(tvb, offset);
505     if (tree) {
506         proto_tree_add_uint(nwk_tree, hf_zbee_nwk_seqno, tvb, offset, 1, packet.seqno);
507     }
508     offset += 1;
509
510     /* Add the extended destination address (ZigBee 2006 and later). */
511     if ((packet.version >= ZBEE_VERSION_2007) && packet.ext_dst) {
512         packet.dst64 = tvb_get_letoh64(tvb, offset);
513         if (tree) {
514             proto_tree_add_item(nwk_tree, hf_zbee_nwk_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
515         }
516         offset += 8;
517     }
518
519     /* Display the extended source address. (ZigBee 2006 and later). */
520     if (packet.version >= ZBEE_VERSION_2007) {
521         addr16.pan = ieee_packet->src_pan;
522
523         if (packet.ext_src) {
524             packet.src64 = tvb_get_letoh64(tvb, offset);
525             proto_tree_add_item(nwk_tree, hf_zbee_nwk_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
526             offset += 8;
527
528             if (!pinfo->fd->flags.visited && nwk_hints) {
529                 /* Provide hints to upper layers */
530                 nwk_hints->src_pan = ieee_packet->src_pan;
531
532                 /* Update nwk extended address hash table */
533                 if ( unicast_src ) {
534                     nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map,
535                             packet.src, addr16.pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
536                 }
537             }
538         }
539         else {
540             /* See if extended source info was previously sniffed */
541             if (!pinfo->fd->flags.visited && nwk_hints) {
542                 nwk_hints->src_pan = ieee_packet->src_pan;
543                 addr16.addr = packet.src;
544
545                 map_rec = (ieee802154_map_rec *) g_hash_table_lookup(zbee_nwk_map.short_table, &addr16);
546                 if (map_rec) {
547                     /* found a nwk mapping record */
548                     nwk_hints->map_rec = map_rec;
549                 }
550                 else {
551                     /* does ieee layer know? */
552                     map_rec = (ieee802154_map_rec *) g_hash_table_lookup(ieee_packet->short_table, &addr16);
553                     if (map_rec) nwk_hints->map_rec = map_rec;
554                 }
555             } /* (!pinfo->fd->flags.visited) */
556             else {
557                 if (tree && nwk_hints && nwk_hints->map_rec ) {
558                     /* Display inferred source address info */
559                     ti = proto_tree_add_eui64(nwk_tree, hf_zbee_nwk_src64, tvb, offset, 0,
560                             nwk_hints->map_rec->addr64);
561                     PROTO_ITEM_SET_GENERATED(ti);
562
563                     if ( nwk_hints->map_rec->start_fnum ) {
564                         ti = proto_tree_add_uint(nwk_tree, hf_zbee_nwk_src64_origin, tvb, 0, 0,
565                             nwk_hints->map_rec->start_fnum);
566                     }
567                     else {
568                         ti = proto_tree_add_text(nwk_tree, tvb, 0, 0, "Origin: Pre-configured");
569                     }
570                     PROTO_ITEM_SET_GENERATED(ti);
571                 }
572             }
573         }
574
575         /* If ieee layer didn't know its extended source address, and nwk layer does, fill it in */
576         if (!pinfo->fd->flags.visited) {
577             if ( (ieee_packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
578                     ieee_hints && !ieee_hints->map_rec ) {
579                 addr16.pan = ieee_packet->src_pan;
580                 addr16.addr = ieee_packet->src16;
581                 map_rec = (ieee802154_map_rec *) g_hash_table_lookup(zbee_nwk_map.short_table, &addr16);
582
583                 if (map_rec) {
584                     /* found a ieee mapping record */
585                     ieee_hints->map_rec = map_rec;
586                 }
587             }
588         } /* (!pinfo->fd->flags.visited */
589     } /* (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) */
590
591     /* Add multicast control field (ZigBee 2006 and later). */
592     if ((packet.version >= ZBEE_VERSION_2007) && packet.multicast) {
593         guint8 mcast_control = tvb_get_guint8(tvb, offset);
594         packet.mcast_mode = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_MODE);
595         packet.mcast_radius = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_RADIUS);
596         packet.mcast_max_radius = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_MAX_RADIUS);
597         if (tree) {
598             /* Create a subtree for the multicast control field. */
599             ti = proto_tree_add_text(nwk_tree, tvb, offset, 1, "Multicast Control Field");
600             field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_mcast);
601             /* Add the fields. */
602             proto_tree_add_item(field_tree, hf_zbee_nwk_mcast_mode, tvb, offset, 1, ENC_NA);
603             proto_tree_add_item(field_tree, hf_zbee_nwk_mcast_radius, tvb, offset, 1, ENC_NA);
604             proto_tree_add_item(field_tree, hf_zbee_nwk_mcast_max_radius, tvb, offset, 1, ENC_NA);
605         }
606         offset += 1;
607     }
608
609     /* Add the Source Route field. (ZigBee 2006 and later). */
610     if ((packet.version >= ZBEE_VERSION_2007) && packet.route) {
611         guint8  relay_count;
612         guint8  relay_index;
613         guint16 relay_addr;
614         guint   i;
615
616         if (tree) {
617             /* Create a subtree for the source route field. */
618             ti = proto_tree_add_text(nwk_tree, tvb, offset, 1, "Source Route");
619             field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_route);
620         }
621
622         /* Get and display the relay count. */
623         relay_count = tvb_get_guint8(tvb, offset);
624         if (tree) {
625             proto_tree_add_uint(field_tree, hf_zbee_nwk_relay_count, tvb, offset, 1, relay_count);
626             proto_item_append_text(ti, ", Length: %d", relay_count);
627         }
628         offset += 1;
629
630         if (tree) {
631             /* Correct the length of the source route fields. */
632             proto_item_set_len(ti, 1 + relay_count*2);
633         }
634
635         /* Get and display the relay index. */
636         relay_index = tvb_get_guint8(tvb, offset);
637         proto_tree_add_uint(field_tree, hf_zbee_nwk_relay_index, tvb, offset, 1, relay_index);
638
639         offset += 1;
640
641         /* Get and display the relay list. */
642         for (i=0; i<relay_count; i++) {
643             relay_addr = tvb_get_letohs(tvb, offset);
644             if (tree) {
645                 proto_tree_add_text(field_tree, tvb, offset, 2, "Relay %d: 0x%04x", i+1, relay_addr);
646             }
647             offset += 2;
648         } /* for */
649     }
650
651     /*
652      * Ensure that the payload exists. There are no valid ZigBee network
653      * packets that have no payload.
654      */
655     if (offset >= tvb_length(tvb)) {
656         /* Non-existent or truncated payload. */
657         expert_add_info(pinfo, proto_root, &ei_zbee_nwk_missing_payload);
658         THROW(BoundsError);
659     }
660     /* Payload is encrypted, attempt security operations. */
661     else if (packet.security) {
662         payload_tvb = dissect_zbee_secure(tvb, pinfo, nwk_tree, offset);
663         if (payload_tvb == NULL) {
664             /* If Payload_tvb is NULL, then the security dissector cleaned up. */
665             return tvb_length(tvb);
666         }
667     }
668     /* Plaintext payload. */
669     else {
670         payload_tvb = tvb_new_subset_remaining(tvb, offset);
671     }
672
673     if (packet.type == ZBEE_NWK_FCF_CMD) {
674         /* Dissect the Network Command. */
675         dissect_zbee_nwk_cmd(payload_tvb, pinfo, nwk_tree, &packet);
676     }
677     else if (packet.type == ZBEE_NWK_FCF_DATA) {
678         /* Dissect the Network Payload (APS layer). */
679         call_dissector_with_data(aps_handle, payload_tvb, pinfo, tree, &packet);
680     }
681     else {
682         /* Invalid type. */
683         call_dissector(data_handle, payload_tvb, pinfo, tree);
684     }
685
686     return tvb_length(tvb);
687 } /* dissect_zbee_nwk */
688
689 /*FUNCTION:------------------------------------------------------
690  *  NAME
691  *      dissect_zbee_nwk
692  *  DESCRIPTION
693  *      ZigBee packet dissection with proto version determination.
694  *  PARAMETERS
695  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
696  *      packet_into *pinfo  - pointer to packet information fields.
697  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
698  *      void *data          - raw packet private data.
699  *  RETURNS
700  *      void
701  *---------------------------------------------------------------
702  */
703 static int
704 dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
705 {
706     guint8 fcf0;
707     guint8 proto_version;
708
709     fcf0 = tvb_get_guint8(tvb, 0);
710     proto_version = (fcf0 & ZBEE_NWK_FCF_VERSION) >> 2;
711     if (proto_version == ZBEE_VERSION_GREEN_POWER) {
712         call_dissector(zbee_gp_handle, tvb, pinfo, tree);
713     } else {
714         /* TODO: add check for FCF proto versions. */
715         dissect_zbee_nwk_full(tvb, pinfo, tree, data);
716     }
717     return tvb_captured_length(tvb);
718 }
719
720 /*FUNCTION:------------------------------------------------------
721  *  NAME
722  *      dissect_zbee_nwk_cmd
723  *  DESCRIPTION
724  *      ZigBee Network command packet dissection routine for Wireshark.
725  *          note: this dissector differs from others in that it shouldn't be
726  *                  passed the main tree pointer, but the nwk tree instead.
727  *  PARAMETERS
728  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
729  *      packet_into *pinfo  - pointer to packet information fields
730  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
731  *  RETURNS
732  *      void
733  *---------------------------------------------------------------
734  */
735 static void dissect_zbee_nwk_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet* packet)
736 {
737     proto_tree  *cmd_tree = NULL;
738     proto_item  *cmd_root = NULL;
739
740     guint       offset=0;
741     guint8      cmd_id = tvb_get_guint8(tvb, offset);
742
743     /* Create a subtree for this command. */
744     if (tree) {
745         cmd_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Command Frame: %s",
746                                         val_to_str_const(cmd_id, zbee_nwk_cmd_names, "Unknown"));
747         cmd_tree = proto_item_add_subtree(cmd_root, ett_zbee_nwk_cmd);
748
749         /* Add the command ID. */
750         proto_tree_add_uint(cmd_tree, hf_zbee_nwk_cmd_id, tvb, offset, 1, cmd_id);
751     }
752     offset += 1;
753
754     /* Add the command name to the info column. */
755     col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd_id, zbee_nwk_cmd_names, "Unknown Command"));
756
757
758     /* Handle the command. */
759     switch(cmd_id){
760         case ZBEE_NWK_CMD_ROUTE_REQ:
761             /* Route Request Command. */
762             offset = dissect_zbee_nwk_route_req(tvb, pinfo, cmd_tree, packet, offset);
763             break;
764
765         case ZBEE_NWK_CMD_ROUTE_REPLY:
766             /* Route Reply Command. */
767             offset = dissect_zbee_nwk_route_rep(tvb, pinfo, cmd_tree, offset, packet->version);
768             break;
769
770         case ZBEE_NWK_CMD_NWK_STATUS:
771             /* Network Status Command. */
772             offset = dissect_zbee_nwk_status(tvb, pinfo, cmd_tree, offset);
773             break;
774
775         case ZBEE_NWK_CMD_LEAVE:
776             /* Leave Command. */
777             offset = dissect_zbee_nwk_leave(tvb, cmd_tree, offset);
778             break;
779
780         case ZBEE_NWK_CMD_ROUTE_RECORD:
781             /* Route Record Command. */
782             offset = dissect_zbee_nwk_route_rec(tvb, pinfo, cmd_tree, packet, offset);
783             break;
784
785         case ZBEE_NWK_CMD_REJOIN_REQ:
786             /* Rejoin Request Command. */
787             offset = dissect_zbee_nwk_rejoin_req(tvb, pinfo, cmd_tree, packet, offset);
788             break;
789
790         case ZBEE_NWK_CMD_REJOIN_RESP:
791             /* Rejoin Response Command. */
792             offset = dissect_zbee_nwk_rejoin_resp(tvb, pinfo, cmd_tree, packet, offset);
793             break;
794
795         case ZBEE_NWK_CMD_LINK_STATUS:
796             /* Link Status Command. */
797             offset = dissect_zbee_nwk_link_status(tvb, cmd_tree, offset);
798             break;
799
800         case ZBEE_NWK_CMD_NWK_REPORT:
801             /* Network Report Command. */
802             offset = dissect_zbee_nwk_report(tvb, pinfo, cmd_tree, offset);
803             break;
804
805         case ZBEE_NWK_CMD_NWK_UPDATE:
806             /* Network Update Command. */
807             offset = dissect_zbee_nwk_update(tvb, pinfo, cmd_tree, offset);
808             break;
809
810         default:
811             /* Just break out and let the overflow handler deal with the payload. */
812             break;
813     } /* switch */
814
815     /* There is excess data in the packet. */
816     if (offset < tvb_length(tvb)) {
817         /* There are leftover bytes! */
818         tvbuff_t    *leftover_tvb   = tvb_new_subset_remaining(tvb, offset);
819         proto_tree  *root           = NULL;
820
821         /* Correct the length of the command tree. */
822         if (tree) {
823             root = proto_tree_get_root(tree);
824             proto_item_set_len(cmd_root, offset);
825         }
826
827         /* Dump the leftover to the data dissector. */
828         call_dissector(data_handle, leftover_tvb, pinfo, root);
829     }
830 } /* dissect_zbee_nwk_cmd */
831
832 /*FUNCTION:------------------------------------------------------
833  *  NAME
834  *      dissect_zbee_nwk_route_req
835  *  DESCRIPTION
836  *      Helper dissector for the Route Request command.
837  *  PARAMETERS
838  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
839  *      packet_into *pinfo  - pointer to packet information fields
840  *      proto_tree *tree    - pointer to the command subtree.
841  *      zbee_nwk_packet *packet - pointer to the network packet struct.
842  *      offset              - offset into the tvb to begin dissection.
843  *  RETURNS
844  *      guint               - offset after command dissection.
845  *---------------------------------------------------------------
846  */
847 static guint
848 dissect_zbee_nwk_route_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset)
849 {
850     proto_tree  *field_tree;
851     proto_item  *ti;
852
853     guint8  route_options;
854     guint8  route_id;
855     guint16 dest_addr;
856     guint8  path_cost;
857
858     /* Get and display the route options field. */
859     route_options = tvb_get_guint8(tvb, offset);
860     if (tree) {
861         /* Create a subtree for the command options. */
862         ti = proto_tree_add_text(tree, tvb, offset, 1, "Command Options (0x%02x)", route_options);
863         field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
864
865         if (packet->version >= ZBEE_VERSION_2007) {
866             proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_multicast, tvb, offset,
867                                     1, route_options & ZBEE_NWK_CMD_ROUTE_OPTION_MCAST);
868             proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_dest_ext, tvb, offset,
869                                     1, route_options & ZBEE_NWK_CMD_ROUTE_OPTION_DEST_EXT);
870             proto_tree_add_uint(field_tree, hf_zbee_nwk_cmd_route_opt_many_to_one, tvb, offset,
871                                     1, route_options & ZBEE_NWK_CMD_ROUTE_OPTION_MANY_MASK);
872         }
873         else {
874             proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_route_opt_repair, tvb, offset, 1,
875                                     route_options & ZBEE_NWK_CMD_ROUTE_OPTION_REPAIR);
876         }
877     }
878     offset += 1;
879
880     /* Get and display the route request ID. */
881     route_id = tvb_get_guint8(tvb, offset);
882     if (tree) {
883         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_id, tvb, offset, 1, route_id);
884     }
885     offset += 1;
886
887     /* Get and display the destination address. */
888     dest_addr = tvb_get_letohs(tvb, offset);
889     if (tree) {
890         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_dest, tvb, offset, 2, dest_addr);
891     }
892     offset += 2;
893
894     /* Get and display the path cost. */
895     path_cost = tvb_get_guint8(tvb, offset);
896     if (tree) {
897         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_cost, tvb, offset, 1, path_cost);
898     }
899     offset += 1;
900
901     /* Get and display the extended destination address. */
902     if (route_options & ZBEE_NWK_CMD_ROUTE_OPTION_DEST_EXT) {
903         if (tree) {
904             proto_tree_add_item(tree, hf_zbee_nwk_cmd_route_dest_ext, tvb, offset, 8, ENC_LITTLE_ENDIAN);
905         }
906         offset += 8;
907     }
908
909     /* Update the info column. */
910     col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: 0x%04x, Src: 0x%04x", dest_addr, packet->src);
911
912     /* Done */
913     return offset;
914 } /* dissect_zbee_nwk_route_req */
915
916 /*FUNCTION:------------------------------------------------------
917  *  NAME
918  *      dissect_zbee_nwk_route_rep
919  *  DESCRIPTION
920  *      Helper dissector for the Route Reply command.
921  *  PARAMETERS
922  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
923  *      packet_into *pinfo  - pointer to packet information fields
924  *      proto_tree *tree    - pointer to the command subtree.
925  *      offset              - offset into the tvb to begin dissection.
926  *  RETURNS
927  *      guint               - offset after command dissection.
928  *---------------------------------------------------------------
929  */
930 static guint
931 dissect_zbee_nwk_route_rep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 version)
932 {
933     proto_tree  *field_tree;
934     proto_item  *ti;
935
936     guint8  route_options;
937     guint8  route_id;
938     guint16 orig_addr;
939     guint16 resp_addr;
940     guint8  path_cost;
941
942     /* Get and display the route options field. */
943     route_options = tvb_get_guint8(tvb, offset);
944     if (tree) {
945         /* Create a subtree for the command options. */
946         ti = proto_tree_add_text(tree, tvb, offset, 1, "Command Options (0x%02x)", route_options);
947         field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
948
949         if (version >= ZBEE_VERSION_2007) {
950             proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_multicast, tvb, offset, 1, route_options & ZBEE_NWK_CMD_ROUTE_OPTION_MCAST);
951             proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_resp_ext, tvb, offset, 1, route_options & ZBEE_NWK_CMD_ROUTE_OPTION_RESP_EXT);
952             proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_orig_ext, tvb, offset, 1, route_options & ZBEE_NWK_CMD_ROUTE_OPTION_ORIG_EXT);
953         }
954         else {
955             proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_route_opt_repair, tvb, offset, 1, route_options & ZBEE_NWK_CMD_ROUTE_OPTION_REPAIR);
956         }
957     }
958     offset += 1;
959
960     /* Get and display the route request ID. */
961     route_id = tvb_get_guint8(tvb, offset);
962     if (tree) {
963         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_id, tvb, offset, 1, route_id);
964     }
965     offset += 1;
966
967     /* Get and display the originator address. */
968     orig_addr = tvb_get_letohs(tvb, offset);
969     if (tree) {
970         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_orig, tvb, offset, 2, orig_addr);
971     }
972     offset += 2;
973
974     /* Get and display the responder address. */
975     resp_addr = tvb_get_letohs(tvb, offset);
976     if (tree) {
977         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_resp, tvb, offset, 2, resp_addr);
978     }
979     offset += 2;
980
981     /* Get and display the path cost. */
982     path_cost = tvb_get_guint8(tvb, offset);
983     if (tree) {
984         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_cost, tvb, offset, 1, path_cost);
985     }
986     offset += 1;
987
988     /* Get and display the originator extended address. */
989     if (route_options & ZBEE_NWK_CMD_ROUTE_OPTION_ORIG_EXT) {
990         if (tree) {
991             proto_tree_add_item(tree, hf_zbee_nwk_cmd_route_orig_ext, tvb, offset, 8, ENC_LITTLE_ENDIAN);
992         }
993         offset += 8;
994     }
995
996     /* Get and display the responder extended address. */
997     if (route_options & ZBEE_NWK_CMD_ROUTE_OPTION_RESP_EXT) {
998         if (tree) {
999             proto_tree_add_item(tree, hf_zbee_nwk_cmd_route_resp_ext, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1000         }
1001         offset += 8;
1002     }
1003
1004     /* Update the info column. */
1005     col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: 0x%04x, Src: 0x%04x", resp_addr, orig_addr);
1006
1007     /* Done */
1008     return offset;
1009 } /* dissect_zbee_nwk_route_rep */
1010
1011 /*FUNCTION:------------------------------------------------------
1012  *  NAME
1013  *      dissect_zbee_nwk_status
1014  *  DESCRIPTION
1015  *      Helper dissector for the Network Status command.
1016  *  PARAMETERS
1017  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1018  *      packet_into *pinfo  - pointer to packet information fields
1019  *      proto_tree *tree    - pointer to the command subtree.
1020  *      offset              - offset into the tvb to begin dissection.
1021  *  RETURNS
1022  *      guint               - offset after command dissection.
1023  *---------------------------------------------------------------
1024  */
1025 static guint
1026 dissect_zbee_nwk_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
1027 {
1028     guint8  status_code;
1029     guint16 addr;
1030
1031     /* Get and display the status code. */
1032     status_code = tvb_get_guint8(tvb, offset);
1033     if (tree) {
1034         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_nwk_status, tvb, offset, 1, status_code);
1035     }
1036     offset += 1;
1037
1038     /* Get and display the destination address. */
1039     addr = tvb_get_letohs(tvb, offset);
1040     if (tree) {
1041         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_route_dest, tvb, offset, 2, addr);
1042     }
1043     offset += 2;
1044
1045     /* Update the info column. */
1046     col_append_fstr(pinfo->cinfo, COL_INFO, ", 0x%04x: %s", addr, val_to_str_const(status_code, zbee_nwk_status_codes, "Unknown Status Code"));
1047
1048     /* Done */
1049     return offset;
1050 } /* dissect_zbee_nwk_status */
1051
1052 /*FUNCTION:------------------------------------------------------
1053  *  NAME
1054  *      dissect_zbee_nwk_leave
1055  *  DESCRIPTION
1056  *      Helper dissector for the Leave command.
1057  *  PARAMETERS
1058  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1059  *      proto_tree *tree    - pointer to the command subtree.
1060  *      offset              - offset into the tvb to begin dissection.
1061  *  RETURNS
1062  *      guint               - offset after command dissection.
1063  *---------------------------------------------------------------
1064  */
1065 static guint
1066 dissect_zbee_nwk_leave(tvbuff_t *tvb, proto_tree *tree, guint offset)
1067 {
1068     guint8  leave_options;
1069
1070     /* Get and display the leave options. */
1071     leave_options = tvb_get_guint8(tvb, offset);
1072     if (tree) {
1073         proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_rejoin, tvb, offset, 1,
1074                                  leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_REJOIN);
1075         proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_request, tvb, offset, 1,
1076                                  leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_REQUEST);
1077         proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_children, tvb, offset, 1,
1078                                 leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_CHILDREN);
1079     }
1080     offset += 1;
1081
1082     /* Done */
1083     return offset;
1084 } /* dissect_zbee_nwk_leave */
1085
1086 /*FUNCTION:------------------------------------------------------
1087  *  NAME
1088  *      dissect_zbee_nwk_route_rec
1089  *  DESCRIPTION
1090  *      Helper dissector for the Reoute Record command.
1091  *  PARAMETERS
1092  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1093  *      packet_into *pinfo  - pointer to packet information fields
1094  *      proto_tree *tree    - pointer to the command subtree.
1095  *      zbee_nwk_packet *packet - pointer to the network packet struct.
1096  *      offset              - offset into the tvb to begin dissection.
1097  *  RETURNS
1098  *      guint               - offset after command dissection.
1099  *---------------------------------------------------------------
1100  */
1101 static guint
1102 dissect_zbee_nwk_route_rec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset)
1103 {
1104     guint8  relay_count;
1105     guint16 relay_addr;
1106     guint   i;
1107
1108     /* Get and display the relay count. */
1109     relay_count = tvb_get_guint8(tvb, offset);
1110     if (tree) {
1111         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_relay_count, tvb, offset, 1, relay_count);
1112     }
1113     offset += 1;
1114
1115     /* Get and display the relay addresses. */
1116     for (i=0; i<relay_count; i++) {
1117         relay_addr = tvb_get_letohs(tvb, offset);
1118         if (tree) {
1119             proto_tree_add_text(tree, tvb, offset, 2, "Relay Device %d: 0x%04x", i+1, relay_addr);
1120         }
1121         offset += 2;
1122     } /* for */
1123
1124     /* Update the info column. */
1125     col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: 0x%04x", packet->dst);
1126
1127
1128     /* Done */
1129     return offset;
1130 } /* dissect_zbee_nwk_route_rec */
1131
1132 /*FUNCTION:------------------------------------------------------
1133  *  NAME
1134  *      dissect_zbee_nwk_rejoin_req
1135  *  DESCRIPTION
1136  *      Helper dissector for the Rejoin Request command.
1137  *  PARAMETERS
1138  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1139  *      packet_into *pinfo  - pointer to packet information fields
1140  *      proto_tree *tree    - pointer to the command subtree.
1141  *      zbee_nwk_packet *packet - pointer to the network packet struct.
1142  *      offset              - offset into the tvb to begin dissection.
1143  *  RETURNS
1144  *      guint               - offset after command dissection.
1145  *---------------------------------------------------------------
1146  */
1147 static guint
1148 dissect_zbee_nwk_rejoin_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset)
1149 {
1150     proto_tree  *field_tree;
1151     proto_item  *ti;
1152
1153     guint8  capabilities;
1154
1155     /* Get and dispaly the capabilities information. */
1156     capabilities = tvb_get_guint8(tvb, offset);
1157     if (tree) {
1158         /* Create a subtree for the capability information. */
1159         ti = proto_tree_add_text(tree, tvb, offset, 1, "Capability Information");
1160         field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_cinfo);
1161
1162         /* Add the capability info flags. */
1163         proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_alt_coord, tvb, offset, 1,
1164                                 capabilities & ZBEE_CINFO_ALT_COORD);
1165         proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_type, tvb, offset, 1,
1166                                 capabilities & ZBEE_CINFO_FFD);
1167         proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_power, tvb, offset, 1,
1168                                 capabilities & ZBEE_CINFO_POWER);
1169         proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_idle_rx, tvb, offset, 1,
1170                                 capabilities & ZBEE_CINFO_IDLE_RX);
1171         proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_security, tvb, offset, 1,
1172                                 capabilities & ZBEE_CINFO_SECURITY);
1173         proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_alloc, tvb, offset, 1,
1174                                 capabilities & ZBEE_CINFO_ALLOC);
1175     }
1176     offset += 1;
1177
1178     /* Update the info column.*/
1179     col_append_fstr(pinfo->cinfo, COL_INFO, ", Device: 0x%04x", packet->src);
1180
1181     /* Done */
1182     return offset;
1183 } /* dissect_zbee_nwk_rejoin_req */
1184
1185 /*FUNCTION:------------------------------------------------------
1186  *  NAME
1187  *      dissect_zbee_nwk_rejoin_resp
1188  *  DESCRIPTION
1189  *      Helper dissector for the Rejoin Response command.
1190  *  PARAMETERS
1191  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1192  *      packet_into *pinfo  - pointer to packet information fields
1193  *      proto_tree *tree    - pointer to the command subtree.
1194  *      zbee_nwk_packet *packet - pointer to the network packet struct.
1195  *      offset              - offset into the tvb to begin dissection.
1196  *  RETURNS
1197  *      guint               - offset after command dissection.
1198  *---------------------------------------------------------------
1199  */
1200 static guint
1201 dissect_zbee_nwk_rejoin_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset)
1202 {
1203     guint16 addr;
1204     guint8  status;
1205
1206     /* Get and display the short address. */
1207     addr = tvb_get_letohs(tvb, offset);
1208     if (tree) {
1209         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_addr, tvb, offset, 2, addr);
1210     }
1211     offset += 2;
1212
1213     /* Get and display the rejoin status. */
1214     status = tvb_get_guint8(tvb, offset);
1215     if (tree) {
1216         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_rejoin_status, tvb, offset, 1, status);
1217     }
1218     offset += 1;
1219
1220     /* Update the info column. */
1221     if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
1222        col_append_fstr(pinfo->cinfo, COL_INFO, ", Address: 0x%04x", packet->src);
1223     }
1224     else {
1225         col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(status, zbee_nwk_rejoin_codes, "Unknown Rejoin Response"));
1226     }
1227
1228     /* Done */
1229     return offset;
1230 } /* dissect_zbee_nwk_rejoin_resp */
1231
1232 /*FUNCTION:------------------------------------------------------
1233  *  NAME
1234  *      dissect_zbee_nwk_link_status
1235  *  DESCRIPTION
1236  *      Helper dissector for the Link Status command.
1237  *  PARAMETERS
1238  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1239  *      proto_tree *tree    - pointer to the command subtree.
1240  *      offset              - offset into the tvb to begin dissection.
1241  *  RETURNS
1242  *      guint               - offset after command dissection.
1243  *---------------------------------------------------------------
1244  */
1245 static guint
1246 dissect_zbee_nwk_link_status(tvbuff_t *tvb, proto_tree *tree, guint offset)
1247 {
1248     guint8  options;
1249     guint16 addr;
1250     int     i, link_count;
1251
1252     /* Get and Display the link status options. */
1253     options = tvb_get_guint8(tvb, offset);
1254     link_count = options & ZBEE_NWK_CMD_LINK_OPTION_COUNT_MASK;
1255     if (tree) {
1256         proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_link_last, tvb, offset, 1,
1257                 options & ZBEE_NWK_CMD_LINK_OPTION_LAST_FRAME);
1258         proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_link_first, tvb, offset, 1,
1259                 options & ZBEE_NWK_CMD_LINK_OPTION_FIRST_FRAME);
1260         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_link_count, tvb, offset, 1, link_count);
1261     }
1262     offset += 1;
1263
1264     /* Get and Display the link status list. */
1265     for (i=0; i<link_count; i++) {
1266         /* Get the address and link status. */
1267         addr = tvb_get_letohs(tvb, offset);
1268         options = tvb_get_guint8(tvb, offset+2);
1269         if (tree) {
1270             proto_tree_add_text(tree, tvb, offset, 2+1,
1271                     "0x%04x, Incoming Cost: %d Outgoing Cost: %d", addr,
1272                     options & ZBEE_NWK_CMD_LINK_INCOMMING_COST_MASK,
1273                     (options & ZBEE_NWK_CMD_LINK_OUTGOING_COST_MASK)>>4);
1274         }
1275         offset += (2+1);
1276     } /* for */
1277
1278     /* TODO: Update the info column. */
1279     return offset;
1280 } /* dissect_zbee_nwk_link_status */
1281
1282 /*FUNCTION:------------------------------------------------------
1283  *  NAME
1284  *      dissect_zbee_nwk_report
1285  *  DESCRIPTION
1286  *      Helper dissector for the Network Report command.
1287  *  PARAMETERS
1288  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1289  *      packet_into *pinfo  - pointer to packet information fields
1290  *      proto_tree *tree    - pointer to the command subtree.
1291  *      offset              - offset into the tvb to begin dissection.
1292  *  RETURNS
1293  *      guint               - offset after command dissection.
1294  *---------------------------------------------------------------
1295  */
1296 static guint
1297 dissect_zbee_nwk_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
1298 {
1299     guint8  options;
1300     guint8  report_type;
1301     int     report_count;
1302     int     i;
1303
1304     /* Get and display the command options field. */
1305     options = tvb_get_guint8(tvb, offset);
1306     report_count = options & ZBEE_NWK_CMD_NWK_REPORT_COUNT_MASK;
1307     report_type = options & ZBEE_NWK_CMD_NWK_REPORT_ID_MASK;
1308     if (tree) {
1309         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_report_type, tvb, offset, 1, report_type);
1310         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_report_count, tvb, offset, 1, report_count);
1311     }
1312     offset += 1;
1313
1314     /* Get and display the epid. */
1315     if (tree) {
1316         proto_tree_add_item(tree, hf_zbee_nwk_cmd_epid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1317     }
1318     offset += 8;
1319
1320     if (report_type == ZBEE_NWK_CMD_NWK_REPORT_ID_PAN_CONFLICT) {
1321         guint16 panId;
1322
1323         /* Report information contains a list of PANS with range of the sender. */
1324         for (i=0; i<report_count; i++) {
1325             panId = tvb_get_letohs(tvb, offset);
1326             if (tree) {
1327                 proto_tree_add_text(tree, tvb, offset, 2, "PANID: 0x%04x", panId);
1328             }
1329             offset += 2;
1330         } /* for */
1331     }
1332
1333     /* Update the info column. */
1334     col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(report_type, zbee_nwk_report_types, "Unknown Report Type"));
1335
1336     /* Done */
1337     return offset;
1338 } /* dissect_zbee_nwk_report */
1339
1340 /*FUNCTION:------------------------------------------------------
1341  *  NAME
1342  *      dissect_zbee_nwk_update
1343  *  DESCRIPTION
1344  *      Helper dissector for the Network Update command.
1345  *  PARAMETERS
1346  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1347  *      packet_into *pinfo  - pointer to packet information fields
1348  *      proto_tree *tree    - pointer to the command subtree.
1349  *      offset              - offset into the tvb to begin dissection.
1350  *  RETURNS
1351  *      guint               - offset after command dissection.
1352  *---------------------------------------------------------------
1353  */
1354 static guint
1355 dissect_zbee_nwk_update(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
1356 {
1357     guint8  options;
1358     guint8  update_type;
1359     guint8  update_id;
1360     int     update_count;
1361     int     i;
1362
1363     /* Get and display the command options field. */
1364     options = tvb_get_guint8(tvb, offset);
1365     update_count = options & ZBEE_NWK_CMD_NWK_UPDATE_COUNT_MASK;
1366     update_type = options & ZBEE_NWK_CMD_NWK_UPDATE_ID_MASK;
1367     if (tree) {
1368         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_update_type, tvb, offset, 1, update_type);
1369         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_update_count, tvb, offset, 1, update_count);
1370     }
1371     offset += 1;
1372
1373     /* Get and display the epid. */
1374     if (tree) {
1375         proto_tree_add_item(tree, hf_zbee_nwk_cmd_epid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1376     }
1377     offset += 8;
1378
1379     /* Get and display the updateID. */
1380     update_id = tvb_get_guint8(tvb, offset);
1381     if (tree) {
1382         proto_tree_add_uint(tree, hf_zbee_nwk_cmd_update_id, tvb, offset, 1, update_id);
1383     }
1384     offset += 1;
1385
1386     if (update_type == ZBEE_NWK_CMD_NWK_UPDATE_ID_PAN_UPDATE) {
1387         guint16 panId;
1388
1389         /* Report information contains a list of PANS with range of the sender. */
1390         for (i=0; i<update_count; i++) {
1391             panId = tvb_get_letohs(tvb, offset);
1392             if (tree) {
1393                 proto_tree_add_text(tree, tvb, offset, 2, "PANID: 0x%04x", panId);
1394             }
1395             offset += 2;
1396         } /* for */
1397     }
1398
1399     /* Update the info column. */
1400     col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(update_type, zbee_nwk_update_types, "Unknown Update Type"));
1401
1402     /* Done */
1403     return offset;
1404 } /* dissect_zbee_nwk_update */
1405
1406 /*FUNCTION:------------------------------------------------------
1407  *  NAME
1408  *      dissect_zbee_beacon_heur
1409  *  DESCRIPTION
1410  *      Heuristic interpreter for the ZigBee PRO beacon dissectors.
1411  *  PARAMETERS
1412  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1413  *      packet_into *pinfo  - pointer to packet information fields
1414  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1415  *  RETURNS
1416  *      Boolean value, whether it handles the packet or not.
1417  *---------------------------------------------------------------
1418  */
1419 static gboolean
1420 dissect_zbee_beacon_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1421 {
1422     ieee802154_packet   *packet = (ieee802154_packet *)data;
1423
1424     /* All ZigBee frames must always have a 16-bit source address. */
1425     if (!packet) return FALSE;
1426     if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) return FALSE;
1427
1428     /* ZigBee beacons begin with a protocol identifier. */
1429     if (tvb_get_guint8(tvb, 0) != ZBEE_NWK_BEACON_PROTOCOL_ID) return FALSE;
1430     dissect_zbee_beacon(tvb, pinfo, tree, packet);
1431     return TRUE;
1432 } /* dissect_zbee_beacon_heur */
1433
1434 /*FUNCTION:------------------------------------------------------
1435  *  NAME
1436  *      dissect_zbee_beacon
1437  *  DESCRIPTION
1438  *      Dissector for ZigBee network beacons.
1439  *  PARAMETERS
1440  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1441  *      packet_into *pinfo  - pointer to packet information fields
1442  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1443  *  RETURNS
1444  *      void
1445  *---------------------------------------------------------------
1446  */
1447 static int dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1448 {
1449     ieee802154_packet   *packet;
1450
1451     proto_item  *beacon_root = NULL;
1452     proto_tree  *beacon_tree = NULL;
1453     guint       offset = 0;
1454
1455     guint8      version;
1456     guint64     epid;
1457
1458     /* Reject the packet if data is NULL */
1459     if (data == NULL)
1460         return 0;
1461     packet = (ieee802154_packet *)data;
1462
1463     /* Add ourself to the protocol column. */
1464     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee");
1465     /* Create the tree for this beacon. */
1466     if (tree) {
1467         beacon_root = proto_tree_add_protocol_format(tree, proto_zbee_nwk, tvb, 0, tvb_length(tvb), "ZigBee Beacon");
1468         beacon_tree = proto_item_add_subtree(beacon_root, ett_zbee_beacon);
1469     }
1470
1471     /* Update the info column. */
1472     col_add_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src16);
1473
1474     /* Get and display the protocol id, must be 0 on all ZigBee beacons. */
1475     proto_tree_add_item(beacon_tree, hf_zbee_beacon_protocol, tvb, offset, 1, ENC_NA);
1476     offset += 1;
1477
1478     /* Get and display the stack profile and protocol version. */
1479     version = zbee_get_bit_field(tvb_get_guint8(tvb, offset), ZBEE_NWK_BEACON_PROTOCOL_VERSION);
1480     if (tree) {
1481         proto_tree_add_item(beacon_tree, hf_zbee_beacon_stack_profile, tvb, offset, 1, ENC_NA);
1482         proto_tree_add_item(beacon_tree, hf_zbee_beacon_version, tvb, offset, 1, ENC_NA);
1483     }
1484     offset += 1;
1485
1486     /* Get and display the security level and flags. */
1487     if (tree) {
1488         proto_tree_add_item(beacon_tree, hf_zbee_beacon_router_capacity, tvb, offset, 1, ENC_NA);
1489         proto_tree_add_item(beacon_tree, hf_zbee_beacon_depth, tvb, offset, 1, ENC_NA);
1490         proto_tree_add_item(beacon_tree, hf_zbee_beacon_end_device_capacity, tvb, offset, 1, ENC_NA);
1491     }
1492     offset += 1;
1493
1494     if (version >= ZBEE_VERSION_2007) {
1495         /* In ZigBee 2006 and later, the beacon contains an extended PAN ID. */
1496         epid = tvb_get_letoh64(tvb, offset);
1497         proto_tree_add_item(beacon_tree, hf_zbee_beacon_epid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1498         offset += 8;
1499
1500         /* Update the Info Column with the EPID. */
1501         col_append_fstr(pinfo->cinfo, COL_INFO, ", EPID: %s", ep_eui64_to_display(epid));
1502
1503         /*
1504          * In ZigBee 2006 the Tx-Offset is optional, while in the 2007 and
1505          * later versions, the Tx-Offset is a required value. Since both 2006 and
1506          * and 2007 versions have the same protocol version (2), we should treat
1507          * the Tx-Offset as well as the update ID as optional elements
1508          */
1509         if (tvb_bytes_exist(tvb, offset, 3)) {
1510             proto_tree_add_item(beacon_tree, hf_zbee_beacon_tx_offset, tvb, offset, 3, ENC_LITTLE_ENDIAN);
1511             offset += 3;
1512
1513             /* Get and display the update ID. */
1514             if(tvb_length_remaining(tvb, offset)) {
1515                 proto_tree_add_item(beacon_tree, hf_zbee_beacon_update_id, tvb, offset, 1, ENC_NA);
1516                 offset += 1;
1517             }
1518         }
1519     }
1520     else if (tvb_bytes_exist(tvb, offset, 3)) {
1521         /* In ZigBee 2004, the Tx-Offset is an optional value. */
1522         proto_tree_add_item(beacon_tree, hf_zbee_beacon_tx_offset, tvb, offset, 3, ENC_LITTLE_ENDIAN);
1523         offset += 3;
1524
1525         /* Update the info column with the PAN ID. */
1526         col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->src_pan);
1527     }
1528
1529     /* Check for leftover bytes. */
1530     if (offset < tvb_length(tvb)) {
1531         /* Bytes leftover! */
1532         tvbuff_t    *leftover_tvb   = tvb_new_subset_remaining(tvb, offset);
1533         proto_tree  *root           = NULL;
1534
1535         /* Correct the length of the beacon tree. */
1536         if (tree) {
1537             root = proto_tree_get_root(tree);
1538             proto_item_set_len(beacon_root, offset);
1539         }
1540
1541         /* Dump the leftover to the data dissector. */
1542         call_dissector(data_handle, leftover_tvb, pinfo, root);
1543     }
1544
1545     return tvb_length(tvb);
1546 } /* dissect_zbee_beacon */
1547
1548 /*FUNCTION:------------------------------------------------------
1549  *  NAME
1550  *      dissect_zbip_beacon_heur
1551  *  DESCRIPTION
1552  *      Heuristic interpreter for the ZigBee IP beacon dissectors.
1553  *  PARAMETERS
1554  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1555  *      packet_into *pinfo  - pointer to packet information fields
1556  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1557  *  RETURNS
1558  *      Boolean value, whether it handles the packet or not.
1559  *---------------------------------------------------------------
1560  */
1561 static gboolean
1562 dissect_zbip_beacon_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1563 {
1564     ieee802154_packet   *packet = (ieee802154_packet *)data;
1565
1566     /* All ZigBee frames must always have a 16-bit source address. */
1567     if (!packet) return FALSE;
1568     if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) return FALSE;
1569
1570     /* ZigBee beacons begin with a protocol identifier. */
1571     if (tvb_get_guint8(tvb, 0) != ZBEE_IP_BEACON_PROTOCOL_ID) return FALSE;
1572     dissect_zbip_beacon(tvb, pinfo, tree, packet);
1573     return TRUE;
1574 } /* dissect_zbip_beacon_heur */
1575
1576 /*FUNCTION:------------------------------------------------------
1577  *  NAME
1578  *      dissect_zbip_beacon
1579  *  DESCRIPTION
1580  *      Dissector for ZigBee IP beacons.
1581  *  PARAMETERS
1582  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
1583  *      packet_into *pinfo  - pointer to packet information fields
1584  *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
1585  *  RETURNS
1586  *      void
1587  *---------------------------------------------------------------
1588  */
1589 static int dissect_zbip_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1590 {
1591     ieee802154_packet   *packet = (ieee802154_packet *)data;
1592
1593     proto_item  *beacon_root = NULL;
1594     proto_tree  *beacon_tree = NULL;
1595     guint       offset = 0;
1596     guint8      proto_id;
1597     char        *ssid;
1598
1599     /* Reject the packet if data is NULL */
1600     if (!packet) return 0;
1601
1602     /* Add ourself to the protocol column. */
1603     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee IP");
1604     /* Create the tree for this beacon. */
1605     if (tree) {
1606         beacon_root = proto_tree_add_protocol_format(tree, proto_zbee_nwk, tvb, 0, tvb_length(tvb), "ZigBee IP Beacon");
1607         beacon_tree = proto_item_add_subtree(beacon_root, ett_zbee_beacon);
1608     }
1609
1610     /* Update the info column. */
1611     col_clear(pinfo->cinfo, COL_INFO);
1612     col_append_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src16);
1613
1614     /* Get and display the protocol id, must be 0x02 on all ZigBee beacons. */
1615     proto_id = tvb_get_guint8(tvb, offset);
1616     if (tree) {
1617         proto_tree_add_uint(beacon_tree, hf_zbee_beacon_protocol, tvb, offset, 1, proto_id);
1618     }
1619     offset += 1;
1620
1621     /* Get and display the beacon flags */
1622     if (tree) {
1623         proto_tree_add_item(beacon_tree, hf_zbip_beacon_allow_join, tvb, offset, 1, ENC_BIG_ENDIAN);
1624         proto_tree_add_item(beacon_tree, hf_zbip_beacon_router_capacity, tvb, offset, 1, ENC_BIG_ENDIAN);
1625         proto_tree_add_item(beacon_tree, hf_zbip_beacon_host_capacity, tvb, offset, 1, ENC_BIG_ENDIAN);
1626         proto_tree_add_item(beacon_tree, hf_zbip_beacon_unsecure, tvb, offset, 1, ENC_BIG_ENDIAN);
1627     }
1628     offset += 1;
1629
1630     /* Get and display the network ID. */
1631     if (tree) {
1632         proto_tree_add_item(beacon_tree, hf_zbip_beacon_network_id, tvb, offset, 16, ENC_ASCII|ENC_NA);
1633     }
1634
1635     ssid = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 16, ENC_ASCII|ENC_NA);
1636     col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID: %s", ssid);
1637     offset += 16;
1638
1639     /* Check for leftover bytes. */
1640     if (offset < tvb_length(tvb)) {
1641         /* TODO: There are TLV's to parse. */
1642         /* Bytes leftover! */
1643         tvbuff_t    *leftover_tvb   = tvb_new_subset_remaining(tvb, offset);
1644         proto_tree  *root           = NULL;
1645
1646         /* Correct the length of the beacon tree. */
1647         if (tree) {
1648             root = proto_tree_get_root(tree);
1649             proto_item_set_len(beacon_root, offset);
1650         }
1651
1652         /* Dump the leftover to the data dissector. */
1653         call_dissector(data_handle, leftover_tvb, pinfo, root);
1654     }
1655     return tvb_length(tvb);
1656 } /* dissect_zbip_beacon */
1657
1658 /*FUNCTION:------------------------------------------------------
1659  *  NAME
1660  *      proto_register_zbee_nwk
1661  *  DESCRIPTION
1662  *      ZigBee protocol registration routine.
1663  *  PARAMETERS
1664  *      none
1665  *  RETURNS
1666  *      void
1667  *---------------------------------------------------------------
1668  */
1669 void proto_register_zbee_nwk(void)
1670 {
1671     static hf_register_info hf[] = {
1672
1673             { &hf_zbee_nwk_frame_type,
1674             { "Frame Type",             "zbee_nwk.frame_type", FT_UINT16, BASE_HEX, VALS(zbee_nwk_frame_types),
1675                 ZBEE_NWK_FCF_FRAME_TYPE, NULL, HFILL }},
1676
1677             { &hf_zbee_nwk_proto_version,
1678             { "Protocol Version",       "zbee_nwk.proto_version", FT_UINT16, BASE_DEC, NULL, ZBEE_NWK_FCF_VERSION,
1679                 NULL, HFILL }},
1680
1681             { &hf_zbee_nwk_discover_route,
1682             { "Discover Route",         "zbee_nwk.discovery", FT_UINT16, BASE_HEX, VALS(zbee_nwk_discovery_modes),
1683                 ZBEE_NWK_FCF_DISCOVER_ROUTE,
1684                 "Determines how route discovery may be handled, if at all.", HFILL }},
1685
1686             { &hf_zbee_nwk_multicast,
1687             { "Multicast",              "zbee_nwk.multicast", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_MULTICAST,
1688                 NULL, HFILL }},
1689
1690             { &hf_zbee_nwk_security,
1691             { "Security",               "zbee_nwk.security", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_SECURITY,
1692                 "Whether or not security operations are performed on the network payload.", HFILL }},
1693
1694             { &hf_zbee_nwk_source_route,
1695             { "Source Route",           "zbee_nwk.src_route", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_SOURCE_ROUTE,
1696                 NULL, HFILL }},
1697
1698             { &hf_zbee_nwk_ext_dst,
1699             { "Destination",            "zbee_nwk.ext_dst", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_EXT_DEST,
1700                 NULL, HFILL }},
1701
1702             { &hf_zbee_nwk_ext_src,
1703             { "Extended Source",        "zbee_nwk.ext_src", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_EXT_SOURCE,
1704                 NULL, HFILL }},
1705
1706             { &hf_zbee_nwk_dst,
1707             { "Destination",            "zbee_nwk.dst", FT_UINT16, BASE_HEX, NULL, 0x0,
1708                 NULL, HFILL }},
1709
1710             { &hf_zbee_nwk_src,
1711             { "Source",                 "zbee_nwk.src", FT_UINT16, BASE_HEX, NULL, 0x0,
1712                 NULL, HFILL }},
1713
1714             { &hf_zbee_nwk_radius,
1715             { "Radius",                 "zbee_nwk.radius", FT_UINT8, BASE_DEC, NULL, 0x0,
1716                 "Number of hops remaining for a range-limited broadcast packet.", HFILL }},
1717
1718             { &hf_zbee_nwk_seqno,
1719             { "Sequence Number",        "zbee_nwk.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
1720                 NULL, HFILL }},
1721
1722             { &hf_zbee_nwk_mcast_mode,
1723             { "Multicast Mode",         "zbee_nwk.multicast.mode", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_MCAST_MODE,
1724                 "Controls whether this packet is permitted to be routed through non-members of the multicast group.",
1725                 HFILL }},
1726
1727             { &hf_zbee_nwk_mcast_radius,
1728             { "Non-Member Radius",      "zbee_nwk.multicast.radius", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_MCAST_RADIUS,
1729                 "Limits the range of multicast packets when being routed through non-members.", HFILL }},
1730
1731             { &hf_zbee_nwk_mcast_max_radius,
1732             { "Max Non-Member Radius",  "zbee_nwk.multicast.max_radius", FT_UINT8, BASE_DEC, NULL,
1733                 ZBEE_NWK_MCAST_MAX_RADIUS, NULL, HFILL }},
1734
1735             { &hf_zbee_nwk_dst64,
1736             { "Destination",   "zbee_nwk.dst64", FT_EUI64, BASE_NONE, NULL, 0x0,
1737                 NULL, HFILL }},
1738
1739             { &hf_zbee_nwk_src64,
1740             { "Extended Source",        "zbee_nwk.src64", FT_EUI64, BASE_NONE, NULL, 0x0,
1741                 NULL, HFILL }},
1742
1743             { &hf_zbee_nwk_src64_origin,
1744             { "Origin",        "zbee_nwk.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1745                 NULL, HFILL }},
1746
1747             { &hf_zbee_nwk_relay_count,
1748             { "Relay Count",            "zbee_nwk.relay.count", FT_UINT8, BASE_DEC, NULL, 0x0,
1749                 "Number of entries in the relay list.", HFILL }},
1750
1751             { &hf_zbee_nwk_relay_index,
1752             { "Relay Index",            "zbee_nwk.relay.index", FT_UINT8, BASE_DEC, NULL, 0x0,
1753                 "Number of relays required to route to the source device.", HFILL }},
1754
1755             { &hf_zbee_nwk_cmd_id,
1756             { "Command Identifier",     "zbee_nwk.cmd.id", FT_UINT8, BASE_HEX, VALS(zbee_nwk_cmd_names), 0x0,
1757                 NULL, HFILL }},
1758
1759             { &hf_zbee_nwk_cmd_addr,
1760             { "Address",                "zbee_nwk.cmd.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
1761                 NULL, HFILL }},
1762
1763             { &hf_zbee_nwk_cmd_route_id,
1764             { "Route ID",               "zbee_nwk.cmd.route.id", FT_UINT8, BASE_DEC, NULL, 0x0,
1765                 "A sequence number for routing commands.", HFILL }},
1766
1767             { &hf_zbee_nwk_cmd_route_dest,
1768             { "Destination",            "zbee_nwk.cmd.route.dest", FT_UINT16, BASE_HEX, NULL, 0x0,
1769                 NULL, HFILL }},
1770
1771             { &hf_zbee_nwk_cmd_route_orig,
1772             { "Originator",             "zbee_nwk.cmd.route.orig", FT_UINT16, BASE_HEX, NULL, 0x0,
1773                 NULL, HFILL }},
1774
1775             { &hf_zbee_nwk_cmd_route_resp,
1776             { "Responder",              "zbee_nwk.cmd.route.resp", FT_UINT16, BASE_HEX, NULL, 0x0,
1777                 NULL, HFILL }},
1778
1779             { &hf_zbee_nwk_cmd_route_dest_ext,
1780             { "Extended Destination",   "zbee_nwk.cmd.route.dest_ext", FT_EUI64, BASE_NONE, NULL, 0x0,
1781                 NULL, HFILL }},
1782
1783             { &hf_zbee_nwk_cmd_route_orig_ext,
1784             { "Extended Originator",    "zbee_nwk.cmd.route.orig_ext", FT_EUI64, BASE_NONE, NULL, 0x0,
1785                 NULL, HFILL }},
1786
1787             { &hf_zbee_nwk_cmd_route_resp_ext,
1788             { "Extended Responder",     "zbee_nwk.cmd.route.resp_ext", FT_EUI64, BASE_NONE, NULL, 0x0,
1789                 NULL, HFILL }},
1790
1791             { &hf_zbee_nwk_cmd_route_cost,
1792             { "Path Cost",              "zbee_nwk.cmd.route.cost", FT_UINT8, BASE_DEC, NULL, 0x0,
1793                 "A value specifying the efficiency of this route.", HFILL }},
1794
1795             { &hf_zbee_nwk_cmd_route_opt_repair,
1796             { "Route Repair",           "zbee_nwk.cmd.route.opts.repair", FT_BOOLEAN, 8, NULL,
1797                 ZBEE_NWK_CMD_ROUTE_OPTION_REPAIR,
1798                 "Flag identifying whether the route request command was to repair a failed route.", HFILL }},
1799
1800             { &hf_zbee_nwk_cmd_route_opt_multicast,
1801             { "Multicast",              "zbee_nwk.cmd.route.opts.mcast", FT_BOOLEAN, 8, NULL,
1802                 ZBEE_NWK_CMD_ROUTE_OPTION_MCAST,
1803                 "Flag identifying this as a multicast route request.", HFILL }},
1804
1805             { &hf_zbee_nwk_cmd_route_opt_dest_ext,
1806             { "Extended Destination",   "zbee_nwk.cmd.route.opts.dest_ext", FT_BOOLEAN, 8, NULL,
1807                 ZBEE_NWK_CMD_ROUTE_OPTION_DEST_EXT, NULL, HFILL }},
1808
1809             { &hf_zbee_nwk_cmd_route_opt_resp_ext,
1810             { "Extended Responder",   "zbee_nwk.cmd.route.opts.resp_ext", FT_BOOLEAN, 8, NULL,
1811                 ZBEE_NWK_CMD_ROUTE_OPTION_RESP_EXT, NULL, HFILL }},
1812
1813             { &hf_zbee_nwk_cmd_route_opt_orig_ext,
1814             { "Extended Originator",    "zbee_nwk.cmd.route.opts.orig_ext", FT_BOOLEAN, 8, NULL,
1815                 ZBEE_NWK_CMD_ROUTE_OPTION_ORIG_EXT, NULL, HFILL }},
1816
1817             { &hf_zbee_nwk_cmd_route_opt_many_to_one,
1818             { "Many-to-One Discovery",  "zbee_nwk.cmd.route.opts.many2one", FT_UINT8, BASE_HEX,
1819                 VALS(zbee_nwk_cmd_route_many_modes), ZBEE_NWK_CMD_ROUTE_OPTION_MANY_MASK,
1820                 NULL, HFILL }},
1821
1822             { &hf_zbee_nwk_cmd_nwk_status,
1823             { "Status Code",            "zbee_nwk.cmd.status", FT_UINT8, BASE_HEX, VALS(zbee_nwk_status_codes), 0x0,
1824                 NULL, HFILL }},
1825
1826             { &hf_zbee_nwk_cmd_leave_rejoin,
1827             { "Rejoin",                 "zbee_nwk.cmd.leave.rejoin", FT_BOOLEAN, 8, NULL,
1828                 ZBEE_NWK_CMD_LEAVE_OPTION_REJOIN, "Flag instructing the device to rejoin the network.", HFILL }},
1829
1830             { &hf_zbee_nwk_cmd_leave_request,
1831             { "Request",                "zbee_nwk.cmd.leave.request", FT_BOOLEAN, 8, NULL,
1832                 ZBEE_NWK_CMD_LEAVE_OPTION_REQUEST,
1833                 "Flag identifying the direction of this command. 1=Request, 0=Indication", HFILL }},
1834
1835             { &hf_zbee_nwk_cmd_leave_children,
1836             { "Remove Children",        "zbee_nwk.cmd.leave.children", FT_BOOLEAN, 8, NULL,
1837                 ZBEE_NWK_CMD_LEAVE_OPTION_CHILDREN,
1838                 "Flag instructing the device to remove its children in addition to itself.", HFILL }},
1839
1840             { &hf_zbee_nwk_cmd_relay_count,
1841             { "Relay Count",            "zbee_nwk.cmd.relay_count", FT_UINT8, BASE_DEC, NULL, 0x0,
1842                 "Number of relays required to route to the destination.", HFILL }},
1843
1844             { &hf_zbee_nwk_cmd_cinfo_alt_coord,
1845             { "Alternate Coordinator",  "zbee_nwk.cmd.cinfo.alt_coord", FT_BOOLEAN, 8, NULL,
1846                 IEEE802154_CMD_CINFO_ALT_PAN_COORD,
1847                 "Indicates that the device is able to operate as a PAN coordinator.", HFILL }},
1848
1849             { &hf_zbee_nwk_cmd_cinfo_type,
1850             { "Full-Function Device",   "zbee_nwk.cmd.cinfo.ffd", FT_BOOLEAN, 8, NULL,
1851                 IEEE802154_CMD_CINFO_DEVICE_TYPE, NULL, HFILL }},
1852
1853             { &hf_zbee_nwk_cmd_cinfo_power,
1854             { "AC Power",               "zbee_nwk.cmd.cinfo.power", FT_BOOLEAN, 8, NULL,
1855                 IEEE802154_CMD_CINFO_POWER_SRC, "Indicates this device is using AC/Mains power.", HFILL }},
1856
1857             { &hf_zbee_nwk_cmd_cinfo_idle_rx,
1858             { "Rx On When Idle",        "zbee_nwk.cmd.cinfo.power", FT_BOOLEAN, 8, NULL,
1859                 IEEE802154_CMD_CINFO_IDLE_RX,
1860                 "Indicates the receiver is active when the device is idle.", HFILL }},
1861
1862             { &hf_zbee_nwk_cmd_cinfo_security,
1863             { "Security Capability",    "zbee_nwk.cmd.cinfo.security", FT_BOOLEAN, 8, NULL,
1864                 IEEE802154_CMD_CINFO_SEC_CAPABLE,
1865                 "Indicates this device is capable of performing encryption/decryption.", HFILL }},
1866
1867             { &hf_zbee_nwk_cmd_cinfo_alloc,
1868             { "Allocate Short Address", "zbee_nwk.cmd.cinfo.alloc", FT_BOOLEAN, 8, NULL,
1869                 IEEE802154_CMD_CINFO_ALLOC_ADDR,
1870                 "Flag requesting the parent to allocate a short address for this device.", HFILL }},
1871
1872             { &hf_zbee_nwk_cmd_rejoin_status,
1873             { "Status",                 "zbee_nwk.cmd.rejoin_status", FT_UINT8, BASE_HEX,
1874                 VALS(zbee_nwk_rejoin_codes), 0x0, NULL, HFILL }},
1875
1876             { &hf_zbee_nwk_cmd_link_last,
1877             { "Last Frame",             "zbee_nwk.cmd.link.last", FT_BOOLEAN, 8, NULL,
1878                 ZBEE_NWK_CMD_LINK_OPTION_LAST_FRAME,
1879                 "Flag indicating the last in a series of link status commands.", HFILL }},
1880
1881             { &hf_zbee_nwk_cmd_link_first,
1882             { "First Frame",            "zbee_nwk.cmd.link.first", FT_BOOLEAN, 8, NULL,
1883                 ZBEE_NWK_CMD_LINK_OPTION_FIRST_FRAME,
1884                 "Flag indicating the first in a series of link status commands.", HFILL }},
1885
1886             { &hf_zbee_nwk_cmd_link_count,
1887             { "Link Status Count",      "zbee_nwk.cmd.link.count", FT_UINT8, BASE_DEC, NULL,
1888                 ZBEE_NWK_CMD_LINK_OPTION_COUNT_MASK, NULL, HFILL }},
1889
1890             { &hf_zbee_nwk_cmd_report_type,
1891             { "Report Type",            "zbee_nwk.cmd.report.type", FT_UINT8, BASE_HEX,
1892                 VALS(zbee_nwk_report_types), ZBEE_NWK_CMD_NWK_REPORT_ID_MASK, NULL, HFILL }},
1893
1894             { &hf_zbee_nwk_cmd_report_count,
1895             { "Report Information Count",   "zbee_nwk.cmd.report.count", FT_UINT8, BASE_DEC, NULL,
1896                 ZBEE_NWK_CMD_NWK_REPORT_COUNT_MASK, NULL, HFILL }},
1897
1898             { &hf_zbee_nwk_cmd_update_type,
1899             { "Update Type",            "zbee_nwk.cmd.update.type", FT_UINT8, BASE_HEX,
1900                 VALS(zbee_nwk_update_types), ZBEE_NWK_CMD_NWK_UPDATE_ID_MASK, NULL, HFILL }},
1901
1902             { &hf_zbee_nwk_cmd_update_count,
1903             { "Update Information Count",   "zbee_nwk.cmd.update.count", FT_UINT8, BASE_DEC, NULL,
1904                 ZBEE_NWK_CMD_NWK_UPDATE_COUNT_MASK, NULL, HFILL }},
1905
1906             { &hf_zbee_nwk_cmd_update_id,
1907             { "Update ID",              "zbee_nwk.cmd.update.id", FT_UINT8, BASE_DEC, NULL, 0x0,
1908                 NULL, HFILL }},
1909
1910             { &hf_zbee_nwk_cmd_epid,
1911             { "Extended PAN ID",        "zbee_nwk.cmd.epid", FT_EUI64, BASE_NONE, NULL, 0x0,
1912                 NULL, HFILL }},
1913
1914             { &hf_zbee_beacon_protocol,
1915             { "Protocol ID",            "zbee_beacon.protocol", FT_UINT8, BASE_DEC, NULL, 0x0,
1916                 NULL, HFILL }},
1917
1918             { &hf_zbee_beacon_stack_profile,
1919             { "Stack Profile",          "zbee_beacon.profile", FT_UINT8, BASE_HEX,
1920                 VALS(zbee_nwk_stack_profiles), ZBEE_NWK_BEACON_STACK_PROFILE, NULL, HFILL }},
1921
1922             { &hf_zbee_beacon_version,
1923             { "Protocol Version",       "zbee_beacon.version", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_BEACON_PROTOCOL_VERSION,
1924                 NULL, HFILL }},
1925
1926             { &hf_zbee_beacon_router_capacity,
1927             { "Router Capacity", "zbee_beacon.router", FT_BOOLEAN, 8, NULL, ZBEE_NWK_BEACON_ROUTER_CAPACITY,
1928                 "Whether the device can accept join requests from routing capable devices.", HFILL }},
1929
1930             { &hf_zbee_beacon_depth,
1931             { "Device Depth",           "zbee_beacon.depth", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_BEACON_NETWORK_DEPTH,
1932                 "The tree depth of the device, 0 indicates the network coordinator.", HFILL }},
1933
1934             { &hf_zbee_beacon_end_device_capacity,
1935             { "End Device Capacity",        "zbee_beacon.end_dev", FT_BOOLEAN, 8, NULL, ZBEE_NWK_BEACON_END_DEVICE_CAPACITY,
1936                 "Whether the device can accept join requests from ZigBee end devices.", HFILL }},
1937
1938             { &hf_zbee_beacon_epid,
1939             { "Extended PAN ID",        "zbee_beacon.ext_panid", FT_EUI64, BASE_NONE, NULL, 0x0,
1940                 "Extended PAN identifier.", HFILL }},
1941
1942             { &hf_zbee_beacon_tx_offset,
1943             { "Tx Offset",              "zbee_beacon.tx_offset", FT_UINT24, BASE_DEC, NULL, 0x0,
1944                 "The time difference between a device and its parent's beacon.", HFILL }},
1945
1946             { &hf_zbee_beacon_update_id,
1947             { "Update ID",              "zbee_beacon.update_id", FT_UINT8, BASE_DEC, NULL, 0x0,
1948                 NULL, HFILL }},
1949
1950             { &hf_zbip_beacon_allow_join,
1951             { "Allow Join",             "zbip_beacon.allow_join", FT_BOOLEAN, 8, NULL, ZBEE_IP_BEACON_ALLOW_JOIN,
1952                 NULL, HFILL }},
1953
1954             { &hf_zbip_beacon_router_capacity,
1955             { "Router Capacity",        "zbip_beacon.router", FT_BOOLEAN, 8, NULL, ZBEE_IP_BEACON_ROUTER_CAPACITY,
1956                 "Whether this device can accept new routers on the network.", HFILL }},
1957
1958             { &hf_zbip_beacon_host_capacity,
1959             { "Host Capacity",        "zbip_beacon.host", FT_BOOLEAN, 8, NULL, ZBEE_IP_BEACON_HOST_CAPACITY,
1960                 "Whether this device can accept new host on the network.", HFILL }},
1961
1962             { &hf_zbip_beacon_unsecure,
1963             { "Unsecure Network",     "zbip_beacon.unsecure", FT_BOOLEAN, 8, NULL, ZBEE_IP_BEACON_UNSECURE,
1964                 "Indicates that this network is not using link layer security.", HFILL }},
1965
1966             { &hf_zbip_beacon_network_id,
1967             { "Network ID",           "zbip_beacon.network_id", FT_STRING, BASE_NONE, NULL, 0x0,
1968                 "A string that uniquely identifies this network.", HFILL }},
1969
1970     };
1971
1972     /*  NWK Layer subtrees */
1973     static gint *ett[] = {
1974         &ett_zbee_nwk,
1975         &ett_zbee_beacon,
1976         &ett_zbee_nwk_fcf,
1977         &ett_zbee_nwk_fcf_ext,
1978         &ett_zbee_nwk_mcast,
1979         &ett_zbee_nwk_route,
1980         &ett_zbee_nwk_cmd,
1981         &ett_zbee_nwk_cmd_options,
1982         &ett_zbee_nwk_cmd_cinfo
1983     };
1984
1985     static ei_register_info ei[] = {
1986         { &ei_zbee_nwk_missing_payload, { "zbee_nwk.missing_payload", PI_MALFORMED, PI_ERROR, "Missing Payload", EXPFILL }},
1987     };
1988
1989     expert_module_t* expert_zbee_nwk;
1990
1991     expert_zbee_nwk = expert_register_protocol(proto_zbee_nwk);
1992     expert_register_field_array(expert_zbee_nwk, ei, array_length(ei));
1993
1994     register_init_routine(proto_init_zbee_nwk);
1995
1996     /* Register the protocol with Wireshark. */
1997     proto_zbee_nwk = proto_register_protocol("ZigBee Network Layer", "ZigBee NWK", ZBEE_PROTOABBREV_NWK);
1998     proto_register_field_array(proto_zbee_nwk, hf, array_length(hf));
1999     proto_register_subtree_array(ett, array_length(ett));
2000
2001     /* Register the dissectors with Wireshark. */
2002     new_register_dissector(ZBEE_PROTOABBREV_NWK, dissect_zbee_nwk, proto_zbee_nwk);
2003     new_register_dissector("zbee_beacon", dissect_zbee_beacon, proto_zbee_nwk);
2004     new_register_dissector("zbip_beacon", dissect_zbip_beacon, proto_zbee_nwk);
2005
2006     /* Register the Security dissector. */
2007     zbee_security_register(NULL, proto_zbee_nwk);
2008 } /* proto_register_zbee_nwk */
2009
2010 /*FUNCTION:------------------------------------------------------
2011  *  NAME
2012  *      proto_reg_handoff_zbee_nwk
2013  *  DESCRIPTION
2014  *      Registers the zigbee dissector with Wireshark.
2015  *  PARAMETERS
2016  *      none
2017  *  RETURNS
2018  *      void
2019  *---------------------------------------------------------------
2020  */
2021 void proto_reg_handoff_zbee_nwk(void)
2022 {
2023     /* Find the other dissectors we need. */
2024     data_handle     = find_dissector("data");
2025     aps_handle      = find_dissector(ZBEE_PROTOABBREV_APS);
2026     zbee_gp_handle  = find_dissector(ZBEE_PROTOABBREV_NWK_GP);
2027
2028     /* Register our dissector with IEEE 802.15.4 */
2029     dissector_add_handle(IEEE802154_PROTOABBREV_WPAN_PANID, find_dissector(ZBEE_PROTOABBREV_NWK));
2030     heur_dissector_add(IEEE802154_PROTOABBREV_WPAN_BEACON, dissect_zbee_beacon_heur, proto_zbee_nwk);
2031     heur_dissector_add(IEEE802154_PROTOABBREV_WPAN_BEACON, dissect_zbip_beacon_heur, proto_zbee_nwk);
2032     heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_zbee_nwk_heur, proto_zbee_nwk);
2033
2034     /* Handoff the ZigBee security dissector code. */
2035     zbee_security_handoff();
2036 } /* proto_reg_handoff_zbee */
2037
2038 static void free_keyring_val(gpointer a)
2039 {
2040     GSList **slist = (GSList **)a;
2041     g_slist_free(*slist);
2042     return;
2043 }
2044
2045 /*FUNCTION:------------------------------------------------------
2046  *  NAME
2047  *      proto_init_zbee_nwk
2048  *  DESCRIPTION
2049  *      Init routine for the nwk dissector. Creates a
2050  *      hash table for mapping 16-bit to 64-bit addresses and
2051  *      populates it with static address pairs from a UAT
2052  *      preference table.
2053  *  PARAMETERS
2054  *      none
2055  *  RETURNS
2056  *      void
2057  *---------------------------------------------------------------
2058  */
2059 static void
2060 proto_init_zbee_nwk(void)
2061 {
2062     /* Destroy the hash tables, if they exist. */
2063     if (zbee_nwk_map.short_table) g_hash_table_destroy(zbee_nwk_map.short_table);
2064     if (zbee_nwk_map.long_table) g_hash_table_destroy(zbee_nwk_map.long_table);
2065     if (zbee_table_nwk_keyring) g_hash_table_destroy(zbee_table_nwk_keyring);
2066
2067     /* (Re)create the hash tables. */
2068     zbee_nwk_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
2069     zbee_nwk_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
2070     zbee_table_nwk_keyring  = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free_keyring_val);
2071 } /* proto_init_zbee_nwk */