/src/wireshark/epan/dissectors/packet-lwm.c
Line | Count | Source |
1 | | /* packet-lwm.c |
2 | | * Dissector routines for the ATMEL Lightweight Mesh 1.1.1 |
3 | | * Copyright 2013 Martin Leixner <info@sewio.net> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | *------------------------------------------------------------ |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | |
15 | | #include <epan/packet.h> |
16 | | #include <epan/expert.h> |
17 | | |
18 | | #include <wsutil/filesystem.h> |
19 | | #include "packet-ieee802154.h" |
20 | | #include <epan/prefs.h> |
21 | | #include <epan/strutil.h> |
22 | | #include <wsutil/wsgcrypt.h> |
23 | | |
24 | | /*LwMesh lengths*/ |
25 | 177 | #define LWM_HEADER_BASE_LEN 7 |
26 | 29 | #define LWM_MIC_LEN 4 |
27 | 7 | #define LWM_MULTI_HEADER_LEN 2 |
28 | | |
29 | | /* Bit-masks for the FCF */ |
30 | 16 | #define LWM_FCF_ACK_REQUEST 0x01 |
31 | 69 | #define LWM_FCF_SEC_EN 0x02 |
32 | | |
33 | 16 | #define LWM_FCF_LINK_LOCAL 0x04 |
34 | 69 | #define LWM_FCF_MULTICAST 0x08 |
35 | | |
36 | 415 | #define LWM_FCF_RESERVED 0xF0 |
37 | | |
38 | 7 | #define LWM_MULTI_NON_MEM_RAD_MASK 0x000F |
39 | 7 | #define LWM_MULTI_NON_MEM_RAD_OFFSET 0 |
40 | | |
41 | 7 | #define LWM_MULTI_MAX_NON_MEM_RAD_MASK 0x00F0 |
42 | 7 | #define LWM_MULTI_MAX_NON_MEM_RAD_OFFSET 4 |
43 | | |
44 | 7 | #define LWM_MULTI_MEM_RAD_MASK 0x0F00 |
45 | 7 | #define LWM_MULTI_MEM_RAD_OFFSET 8 |
46 | | |
47 | 7 | #define LWM_MULTI_MAX_MEM_RAD_MASK 0xF000 |
48 | 7 | #define LWM_MULTI_MAX_MEM_RAD_OFFSET 12 |
49 | | |
50 | | /*Endpoints*/ |
51 | 168 | #define LWM_SRC_ENDP_MASK 0xF0 |
52 | 168 | #define LWM_SRC_ENDP_OFFSET 4 |
53 | 168 | #define LWM_DST_ENDP_MASK 0x0F |
54 | 168 | #define LWM_DST_ENDP_OFFSET 0 |
55 | | |
56 | | /*Defined addresses*/ |
57 | 106 | #define LWM_BCAST_ADDR 0xFFFF |
58 | | |
59 | | /*Command IDs*/ |
60 | 7 | #define LWM_CMD_ACK 0x00 |
61 | 4 | #define LWM_CMD_ROUTE_ERR 0x01 |
62 | 5 | #define LWM_CMD_ROUTE_REQ 0x02 |
63 | 5 | #define LWM_CMD_ROUTE_REPLY 0x03 |
64 | | |
65 | | /*Lengths of command frames*/ |
66 | 7 | #define LWM_CMD_FRAME_ACK_LEN 3 |
67 | 4 | #define LWM_CMD_FRAME_ROUTE_ERR_LEN 6 |
68 | 5 | #define LWM_CMD_FRAME_ROUTE_REQ_LEN 7 |
69 | 5 | #define LWM_CMD_FRAME_ROUTE_REPLY_LEN 8 |
70 | | |
71 | | /*Values for multicast field*/ |
72 | | #define LWM_CMD_MULTI_ADDR_FALSE 0 |
73 | 14 | #define LWM_CMD_MULTI_ADDR_TRUE 1 |
74 | | |
75 | | /*Defined strings*/ |
76 | 3 | #define LWM_CMD_LINKQ_STRING "(Sent by Originate node)" |
77 | 26 | #define LWM_CMD_UNKNOWN_VAL_STRING "Unknown command (0x%02x)" |
78 | | |
79 | 53 | #define LWM_MULTI_UNICAST_STRING "(Unicast)" |
80 | 11 | #define LWM_MULTI_GROUP_STRING "(Group ID)" |
81 | | |
82 | | /* Function declarations */ |
83 | | void proto_register_lwm(void); |
84 | | void proto_reg_handoff_lwm(void); |
85 | | |
86 | | /* User string with the decryption key. */ |
87 | | static const char *lwmes_key_str; |
88 | | static bool lwmes_key_valid; |
89 | | static uint8_t lwmes_key[16]; |
90 | | |
91 | | /* Dissection Routines. */ |
92 | | static int dissect_lwm (tvbuff_t *, packet_info *, proto_tree *, void *data); |
93 | | static int dissect_lwm_cmd_frame_ack (tvbuff_t *, packet_info *, proto_tree *); |
94 | | static int dissect_lwm_cmd_frame_route_err (tvbuff_t *, packet_info *, proto_tree *); |
95 | | static int dissect_lwm_cmd_frame_route_req (tvbuff_t *, packet_info *, proto_tree *); |
96 | | static int dissect_lwm_cmd_frame_route_reply (tvbuff_t *, packet_info *, proto_tree *); |
97 | | |
98 | | /* Initialize protocol and registered fields. */ |
99 | | static int proto_lwm; |
100 | | |
101 | | static int hf_lwm_fcf; |
102 | | static int hf_lwm_fcf_ack_req; |
103 | | static int hf_lwm_fcf_security; |
104 | | static int hf_lwm_fcf_linklocal; |
105 | | static int hf_lwm_fcf_multicast; |
106 | | static int hf_lwm_fcf_reserved; |
107 | | static int hf_lwm_seq; |
108 | | static int hf_lwm_src_addr; |
109 | | static int hf_lwm_dst_addr; |
110 | | static int hf_lwm_src_endp; |
111 | | static int hf_lwm_dst_endp; |
112 | | static int hf_lwm_multi_nmrad; |
113 | | static int hf_lwm_multi_mnmrad; |
114 | | static int hf_lwm_multi_mrad; |
115 | | static int hf_lwm_multi_mmrad; |
116 | | static int hf_lwm_mic; |
117 | | static int hf_lwm_cmd; |
118 | | static int hf_lwm_cmd_seq; |
119 | | static int hf_lwm_cmd_cm; |
120 | | static int hf_lwm_cmd_route_src; |
121 | | static int hf_lwm_cmd_route_dst; |
122 | | static int hf_lwm_cmd_route_multi; |
123 | | static int hf_lwm_cmd_linkquality; |
124 | | static int hf_lwm_cmd_forwlinkquality; |
125 | | static int hf_lwm_cmd_revlinkquality; |
126 | | |
127 | | /* Initialize protocol subtrees. */ |
128 | | static int ett_lwm; |
129 | | static int ett_lwm_fcf; |
130 | | static int ett_lwm_cmd_tree; |
131 | | static int ett_lwm_multi_tree; |
132 | | |
133 | | static expert_field ei_lwm_mal_error; |
134 | | static expert_field ei_lwm_n_src_broad; |
135 | | static expert_field ei_lwm_mismatch_endp; |
136 | | static expert_field ei_lwm_empty_payload; |
137 | | static expert_field ei_lwm_no_decryption_key; |
138 | | static expert_field ei_lwm_decryption_failed; |
139 | | |
140 | | static dissector_handle_t lwm_handle; |
141 | | |
142 | | static const value_string lwm_cmd_names[] = { |
143 | | { LWM_CMD_ACK, "LwMesh ACK" }, |
144 | | { LWM_CMD_ROUTE_ERR, "Route Error" }, |
145 | | { LWM_CMD_ROUTE_REQ, "Route Request" }, |
146 | | { LWM_CMD_ROUTE_REPLY, "Route Reply" }, |
147 | | { 0, NULL } |
148 | | }; |
149 | | |
150 | | static const value_string lwm_cmd_multi_names[] = { |
151 | | { LWM_CMD_MULTI_ADDR_FALSE, "FALSE" }, |
152 | | { LWM_CMD_MULTI_ADDR_TRUE, "TRUE" }, |
153 | | { 0, NULL } |
154 | | }; |
155 | | |
156 | | /*FUNCTION:------------------------------------------------------ |
157 | | * NAME |
158 | | * dissect_lwm_heur |
159 | | * DESCRIPTION |
160 | | * Heuristic interpreter for the Lightweight Mesh. |
161 | | * PARAMETERS |
162 | | * tvbuff_t *tvb - pointer to buffer containing raw packet. |
163 | | * packet_into *pinfo - pointer to packet information fields |
164 | | * proto_tree *tree - pointer to data tree Wireshark uses to display packet. |
165 | | * RETURNS |
166 | | * Boolean value, whether it handles the packet or not. |
167 | | *--------------------------------------------------------------- |
168 | | */ |
169 | | static bool |
170 | | dissect_lwm_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
171 | 399 | { |
172 | 399 | uint8_t endpt, srcep, dstep; |
173 | | |
174 | | /* 1) first byte must have bits 0000xxxx */ |
175 | 399 | if(tvb_get_uint8(tvb, 0) & LWM_FCF_RESERVED) |
176 | 275 | return false; |
177 | | |
178 | | /* The header should be at least long enough for the base header. */ |
179 | 124 | if (tvb_reported_length(tvb) < LWM_HEADER_BASE_LEN) |
180 | 9 | return false; |
181 | | |
182 | | /* The endpoints should either both be zero, or both non-zero. */ |
183 | 115 | endpt = tvb_get_uint8(tvb, 6); |
184 | 115 | srcep = (endpt & LWM_SRC_ENDP_MASK) >> LWM_SRC_ENDP_OFFSET; |
185 | 115 | dstep = (endpt & LWM_DST_ENDP_MASK) >> LWM_DST_ENDP_OFFSET; |
186 | 115 | if ((srcep == 0) && (dstep != 0)) |
187 | 42 | return false; |
188 | 73 | if ((srcep != 0) && (dstep == 0)) |
189 | 17 | return false; |
190 | | |
191 | 56 | dissect_lwm(tvb, pinfo, tree, data); |
192 | 56 | return true; |
193 | 73 | } /* dissect_lwm_heur */ |
194 | | |
195 | | /*FUNCTION:------------------------------------------------------ |
196 | | * NAME |
197 | | * dissect_lwm |
198 | | * DESCRIPTION |
199 | | * Lightweight Mesh packet dissection routine for Wireshark. |
200 | | * PARAMETERS |
201 | | * tvbuff_t *tvb - pointer to buffer containing raw packet. |
202 | | * packet_info *pinfo - pointer to packet information fields |
203 | | * proto_tree *tree - pointer to data tree Wireshark uses to display packet. |
204 | | * RETURNS |
205 | | * int - length of data processed, or 0 if not LWM. |
206 | | *--------------------------------------------------------------- |
207 | | */ |
208 | | static int dissect_lwm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
209 | 53 | { |
210 | 53 | unsigned lwm_header_len; |
211 | | |
212 | 53 | uint8_t lwm_fcf; |
213 | 53 | bool lwm_fcf_security; |
214 | 53 | bool lwm_fcf_multicast; |
215 | | |
216 | | |
217 | 53 | uint8_t lwm_seq; |
218 | 53 | uint16_t lwm_src_addr; |
219 | 53 | uint16_t lwm_dst_addr; |
220 | 53 | uint8_t lwm_endp_field; |
221 | 53 | uint8_t lwm_src_endp; |
222 | 53 | uint8_t lwm_dst_endp; |
223 | | |
224 | 53 | proto_tree *lwm_tree = NULL; |
225 | 53 | proto_item *ti_proto = NULL; |
226 | 53 | proto_item *ti; |
227 | 53 | tvbuff_t *new_tvb; |
228 | | |
229 | | /*---------------------------------------------------------*/ |
230 | | |
231 | | /*Enter name of protocol to info field*/ |
232 | 53 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "LwMesh"); |
233 | 53 | col_clear(pinfo->cinfo, COL_INFO); |
234 | | |
235 | | /*Set base length of LWM header*/ |
236 | 53 | lwm_header_len = LWM_HEADER_BASE_LEN; |
237 | | |
238 | | /*--------------------------------------------------*/ |
239 | | /* */ |
240 | | /* Create LwMesh dissector tree */ |
241 | | /* */ |
242 | | /*--------------------------------------------------*/ |
243 | 53 | if(tree){ |
244 | | /*Create subtree for the LwMesh*/ |
245 | 53 | ti_proto = proto_tree_add_protocol_format(tree, proto_lwm, tvb, 0, -1, "Lightweight Mesh"); |
246 | 53 | lwm_tree = proto_item_add_subtree(ti_proto, ett_lwm); |
247 | 53 | } |
248 | | |
249 | 53 | col_set_str(pinfo->cinfo, COL_INFO, "Lightweight Mesh"); |
250 | | |
251 | | /*--------------------------------------------------*/ |
252 | | /* */ |
253 | | /* Display LwMesh dissector tree */ |
254 | | /* */ |
255 | | /*--------------------------------------------------*/ |
256 | | |
257 | | /*Frame control fields*/ |
258 | 53 | lwm_fcf = tvb_get_uint8(tvb, 0); |
259 | | |
260 | 53 | lwm_fcf_security = (lwm_fcf & LWM_FCF_SEC_EN); |
261 | 53 | lwm_fcf_multicast = (lwm_fcf & LWM_FCF_MULTICAST); |
262 | | |
263 | 53 | if(tree){ |
264 | 53 | proto_tree *field_tree; |
265 | 53 | ti = proto_tree_add_uint(lwm_tree, hf_lwm_fcf, tvb, 0, 1, lwm_fcf); |
266 | | |
267 | 53 | field_tree = proto_item_add_subtree(ti, ett_lwm_fcf); |
268 | 53 | proto_tree_add_item(field_tree, hf_lwm_fcf_ack_req, tvb, 0, 1, ENC_NA); |
269 | | |
270 | 53 | proto_tree_add_item(field_tree, hf_lwm_fcf_security, tvb, 0, 1, ENC_NA); |
271 | 53 | proto_tree_add_item(field_tree, hf_lwm_fcf_linklocal, tvb, 0, 1, ENC_NA); |
272 | 53 | proto_tree_add_item(field_tree, hf_lwm_fcf_multicast, tvb, 0, 1, ENC_NA); |
273 | 53 | proto_tree_add_item(field_tree, hf_lwm_fcf_reserved, tvb, 0, 1, ENC_NA); |
274 | 53 | } |
275 | | |
276 | | /*Sequence number*/ |
277 | 53 | lwm_seq = tvb_get_uint8(tvb, 1); |
278 | 53 | proto_item_append_text(ti_proto, ", Sequence Number: %i", lwm_seq); |
279 | 53 | proto_tree_add_uint(lwm_tree, hf_lwm_seq, tvb, 1, 1, lwm_seq); |
280 | | |
281 | | /*Network addresses*/ |
282 | | |
283 | | /*Parse Source address*/ |
284 | 53 | lwm_src_addr = tvb_get_letohs(tvb, 2); |
285 | | |
286 | 53 | ti = proto_tree_add_uint(lwm_tree, hf_lwm_src_addr, tvb, 2, 2, lwm_src_addr); |
287 | | |
288 | 53 | if(lwm_src_addr < 0x8000){ |
289 | 38 | proto_item_append_text(ti, " (Routing node)"); |
290 | 38 | }else{ |
291 | 15 | proto_item_append_text(ti, " (Non-routing node)"); |
292 | 15 | } |
293 | | |
294 | | /*Check value of source address*/ |
295 | 53 | if(lwm_src_addr == LWM_BCAST_ADDR){ |
296 | 2 | expert_add_info(pinfo, lwm_tree, &ei_lwm_n_src_broad); |
297 | 2 | } |
298 | | |
299 | | /*Parse Destination address*/ |
300 | 53 | lwm_dst_addr = tvb_get_letohs(tvb, 4); |
301 | | |
302 | 53 | if(lwm_dst_addr == LWM_BCAST_ADDR){ |
303 | 3 | proto_tree_add_uint_format_value(lwm_tree, hf_lwm_dst_addr, tvb, 4, 2, lwm_dst_addr, |
304 | 3 | "Broadcast (0x%04x)", lwm_dst_addr); |
305 | 50 | }else{ |
306 | 50 | ti = proto_tree_add_uint(lwm_tree, hf_lwm_dst_addr, tvb, 4, 2, lwm_dst_addr); |
307 | | |
308 | 50 | if(lwm_fcf_multicast){ |
309 | 7 | proto_item_append_text(ti, " %s", LWM_MULTI_GROUP_STRING); |
310 | 43 | }else{ |
311 | 43 | proto_item_append_text(ti, " %s", LWM_MULTI_UNICAST_STRING); |
312 | | |
313 | 43 | if(lwm_dst_addr < 0x8000){ |
314 | 35 | proto_item_append_text(ti, " (Routing node)"); |
315 | 35 | }else{ |
316 | 8 | proto_item_append_text(ti, " (Non-routing node)"); |
317 | 8 | } |
318 | 43 | } |
319 | 50 | } |
320 | | |
321 | | /*Enter description to info field*/ |
322 | 53 | col_append_fstr(pinfo->cinfo, COL_INFO, ", Nwk_Dst: 0x%04x, Nwk_Src: 0x%04x", lwm_dst_addr, lwm_src_addr); |
323 | | |
324 | | /*Endpoints*/ |
325 | 53 | lwm_endp_field = tvb_get_uint8(tvb, 6); |
326 | 53 | lwm_src_endp = (lwm_endp_field & LWM_SRC_ENDP_MASK) >> LWM_SRC_ENDP_OFFSET; |
327 | 53 | lwm_dst_endp = (lwm_endp_field & LWM_DST_ENDP_MASK) >> LWM_DST_ENDP_OFFSET; |
328 | | |
329 | 53 | ti = proto_tree_add_uint(lwm_tree, hf_lwm_src_endp, tvb, 6, 1, lwm_src_endp); |
330 | 53 | if(lwm_src_endp == 0){ |
331 | 31 | proto_item_append_text(ti, " (Stack command endpoint)"); |
332 | 31 | } |
333 | | |
334 | 53 | ti = proto_tree_add_uint(lwm_tree, hf_lwm_dst_endp, tvb, 6, 1, lwm_dst_endp); |
335 | 53 | if(lwm_dst_endp == 0){ |
336 | 31 | proto_item_append_text(ti, " (Stack command endpoint)"); |
337 | 31 | } |
338 | | |
339 | 53 | if( (lwm_src_endp == 0) && (lwm_dst_endp == 0)){ |
340 | | /*stack command endpoints*/ |
341 | | |
342 | 31 | } |
343 | 22 | else if( (lwm_src_endp == 0) || (lwm_dst_endp == 0)){ |
344 | | /*If only one endpoint is 0, alert about that*/ |
345 | |
|
346 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "[Stack command Endpoints mismatch]"); |
347 | |
|
348 | 0 | expert_add_info(pinfo, lwm_tree, &ei_lwm_mismatch_endp); |
349 | 0 | } |
350 | | |
351 | | /*Multicast header*/ |
352 | 53 | if( (lwm_fcf_multicast) ){ |
353 | | |
354 | 7 | lwm_header_len += LWM_MULTI_HEADER_LEN; |
355 | | |
356 | 7 | if(tree){ |
357 | 7 | proto_tree *multi_tree; |
358 | 7 | uint16_t lwm_multi_header; |
359 | | |
360 | 7 | lwm_multi_header = tvb_get_letohs(tvb, 7); |
361 | 7 | multi_tree = proto_tree_add_subtree(lwm_tree, tvb, 7, 2, ett_lwm_multi_tree, NULL, "Multicast Header"); |
362 | | |
363 | 7 | proto_tree_add_uint(multi_tree, hf_lwm_multi_nmrad, tvb, 7, 2, |
364 | 7 | (lwm_multi_header & LWM_MULTI_NON_MEM_RAD_MASK) >> LWM_MULTI_NON_MEM_RAD_OFFSET); |
365 | 7 | proto_tree_add_uint(multi_tree, hf_lwm_multi_mnmrad, tvb, 7, 2, |
366 | 7 | (lwm_multi_header & LWM_MULTI_MAX_NON_MEM_RAD_MASK) >> LWM_MULTI_MAX_NON_MEM_RAD_OFFSET); |
367 | 7 | proto_tree_add_uint(multi_tree, hf_lwm_multi_mrad, tvb, 7, 2, |
368 | 7 | (lwm_multi_header & LWM_MULTI_MEM_RAD_MASK) >> LWM_MULTI_MEM_RAD_OFFSET); |
369 | 7 | proto_tree_add_uint(multi_tree, hf_lwm_multi_mmrad, tvb, 7, 2, |
370 | 7 | (lwm_multi_header & LWM_MULTI_MAX_MEM_RAD_MASK) >> LWM_MULTI_MAX_MEM_RAD_OFFSET); |
371 | 7 | } |
372 | 7 | } |
373 | | |
374 | | |
375 | | /*------------------------------*/ |
376 | | /* */ |
377 | | /* Dissect payload */ |
378 | | /* */ |
379 | | /*------------------------------*/ |
380 | | |
381 | | /*Note: exception will already have occurred if "short header"*/ |
382 | | |
383 | 53 | if (tvb_reported_length(tvb) <= lwm_header_len) { |
384 | | /*Empty payload*/ |
385 | 5 | expert_add_info(pinfo, lwm_tree, &ei_lwm_empty_payload); |
386 | 5 | col_append_str(pinfo->cinfo, COL_INFO, "[Empty LwMesh Payload]"); |
387 | | |
388 | 5 | return tvb_captured_length(tvb); |
389 | 5 | } |
390 | | |
391 | 48 | new_tvb = tvb_new_subset_remaining(tvb, lwm_header_len); |
392 | | |
393 | | /*Encrypted data*/ |
394 | 48 | if(lwm_fcf_security){ |
395 | 6 | unsigned rlen; |
396 | 6 | int start; |
397 | 6 | uint32_t lwm_mic; |
398 | | |
399 | | /*MIC field*/ |
400 | 6 | rlen = tvb_reported_length(new_tvb); |
401 | 6 | start = (rlen >= LWM_MIC_LEN) ? (rlen-LWM_MIC_LEN) : 0; |
402 | | /*An exception will occur if there are not enough bytes for the MIC */ |
403 | 6 | proto_tree_add_item_ret_uint(lwm_tree, hf_lwm_mic, new_tvb, start, LWM_MIC_LEN, ENC_LITTLE_ENDIAN, &lwm_mic); |
404 | | |
405 | 6 | if(lwmes_key_valid) |
406 | 0 | { |
407 | 0 | ieee802154_packet *ieee_packet = NULL; |
408 | 0 | int payload_length = 0; |
409 | 0 | int length = 0; |
410 | 0 | int payload_offset = 0; |
411 | 0 | uint8_t block; |
412 | 0 | tvbuff_t *decrypted_tvb; |
413 | 0 | gcry_cipher_hd_t cypher_hd; |
414 | 0 | uint8_t* vector = NULL; |
415 | 0 | uint8_t* text =NULL; |
416 | 0 | uint8_t* text_dec =NULL; |
417 | 0 | uint8_t i; |
418 | 0 | uint32_t vmic; |
419 | 0 | uint32_t nwkSecurityVector[4]; |
420 | 0 | int gcrypt_err; |
421 | |
|
422 | 0 | ieee_packet = (ieee802154_packet *)data; |
423 | |
|
424 | 0 | memset(&nwkSecurityVector, 0, sizeof(nwkSecurityVector)); |
425 | 0 | nwkSecurityVector[0] = lwm_seq; |
426 | 0 | nwkSecurityVector[1] = ((uint32_t)lwm_dst_addr<< 16) | lwm_dst_endp; |
427 | 0 | nwkSecurityVector[2]= ((uint32_t) lwm_src_addr<< 16) | lwm_src_endp; |
428 | 0 | nwkSecurityVector[3] = ((uint32_t)ieee_packet->dst_pan << 16) | (uint8_t)lwm_fcf; |
429 | |
|
430 | 0 | payload_length=tvb_reported_length(new_tvb) - LWM_MIC_LEN; |
431 | | |
432 | | /* ECB - Nwk security vector*/ |
433 | 0 | text = (uint8_t *)tvb_memdup(pinfo->pool, new_tvb, 0, payload_length); |
434 | 0 | payload_offset=0; |
435 | |
|
436 | 0 | gcrypt_err = gcry_cipher_open(&cypher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0); |
437 | | /*Decrypt the actual data */ |
438 | 0 | while(payload_length>0) |
439 | 0 | { |
440 | 0 | if(gcrypt_err == 0) { |
441 | 0 | gcrypt_err = gcry_cipher_setkey(cypher_hd,(uint8_t *)lwmes_key, 16); |
442 | 0 | } |
443 | 0 | if(gcrypt_err == 0) { |
444 | 0 | gcrypt_err = gcry_cipher_encrypt(cypher_hd,(uint8_t *)nwkSecurityVector,16,(uint8_t *)nwkSecurityVector,16); |
445 | 0 | } |
446 | |
|
447 | 0 | if(gcrypt_err) |
448 | 0 | { |
449 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, |
450 | 0 | "Encrypted data (%i byte(s)) DECRYPT FAILED", |
451 | 0 | tvb_reported_length(new_tvb) - LWM_MIC_LEN); |
452 | 0 | expert_add_info(pinfo, lwm_tree, &ei_lwm_decryption_failed); |
453 | 0 | tvb_set_reported_length(new_tvb, tvb_reported_length(new_tvb) - LWM_MIC_LEN); |
454 | 0 | call_data_dissector(new_tvb, pinfo, lwm_tree); |
455 | 0 | } |
456 | |
|
457 | 0 | text_dec = &text[payload_offset]; |
458 | 0 | vector = (uint8_t *)nwkSecurityVector; |
459 | 0 | block = (payload_length < 16) ? payload_length : 16; |
460 | |
|
461 | 0 | for (i = 0; i < block; i++) |
462 | 0 | { |
463 | 0 | text_dec[i] ^= vector[i]; |
464 | | /* |
465 | | * GCC 12.2.0 gives a false positive Wstringop-overflow warning. |
466 | | * https://gitlab.com/wireshark/wireshark/-/issues/18383 |
467 | | */ |
468 | 0 | DIAG_OFF_STRINGOP_OVERFLOW() |
469 | 0 | vector[i] ^= text_dec[i]; |
470 | 0 | DIAG_ON_STRINGOP_OVERFLOW() |
471 | 0 | } |
472 | |
|
473 | 0 | payload_offset += block; |
474 | 0 | payload_length -= block; |
475 | 0 | gcry_cipher_reset(cypher_hd); |
476 | 0 | } |
477 | 0 | gcry_cipher_close(cypher_hd); |
478 | |
|
479 | 0 | vmic = nwkSecurityVector[0] ^ nwkSecurityVector[1] ^ nwkSecurityVector[2] ^ nwkSecurityVector[3]; |
480 | 0 | length = tvb_reported_length(new_tvb) - LWM_MIC_LEN; |
481 | |
|
482 | 0 | if(vmic == lwm_mic) |
483 | 0 | { |
484 | 0 | decrypted_tvb = tvb_new_real_data(text,length, length); |
485 | 0 | call_data_dissector(decrypted_tvb, pinfo, lwm_tree); |
486 | | /* XXX - needed? |
487 | | add_new_data_source(pinfo, decrypted_tvb, "Decrypted LWmesh Payload"); */ |
488 | 0 | col_append_str(pinfo->cinfo, COL_INFO, ", MIC SUCCESS"); |
489 | |
|
490 | 0 | } |
491 | 0 | else |
492 | 0 | { |
493 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, |
494 | 0 | "Encrypted data (%i byte(s)) MIC FAILURE", |
495 | 0 | tvb_reported_length(new_tvb) - LWM_MIC_LEN); |
496 | 0 | tvb_set_reported_length(new_tvb, tvb_reported_length(new_tvb) - LWM_MIC_LEN); |
497 | 0 | call_data_dissector(new_tvb, pinfo, lwm_tree); |
498 | 0 | } |
499 | 0 | } |
500 | 6 | else |
501 | 6 | { |
502 | 6 | col_add_fstr(pinfo->cinfo, COL_INFO, |
503 | 6 | "Encrypted data (%i byte(s)) NO DECRYPT KEY", |
504 | 6 | tvb_reported_length(new_tvb) - LWM_MIC_LEN); |
505 | | |
506 | 6 | expert_add_info(pinfo, lwm_tree, &ei_lwm_no_decryption_key); |
507 | 6 | tvb_set_reported_length(new_tvb, tvb_reported_length(new_tvb) - LWM_MIC_LEN); |
508 | 6 | call_data_dissector(new_tvb, pinfo, lwm_tree); |
509 | 6 | } |
510 | 6 | } |
511 | | /*stack command endpoint 0 and not secured*/ |
512 | 42 | else if( (lwm_src_endp == 0) && (lwm_dst_endp == 0) ){ |
513 | 26 | proto_tree *lwm_cmd_tree; |
514 | 26 | uint8_t lwm_cmd; |
515 | 26 | unsigned len; |
516 | 26 | char *str_cmd; |
517 | | |
518 | | /*----------------------------------------------------------------------*/ |
519 | | /* */ |
520 | | /* Call command dissector (depends on value of first byte of payload) */ |
521 | | /* */ |
522 | | /*----------------------------------------------------------------------*/ |
523 | 26 | lwm_cmd = tvb_get_uint8(new_tvb, 0); |
524 | 26 | str_cmd = val_to_str(pinfo->pool, lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING); |
525 | | |
526 | 26 | col_clear(pinfo->cinfo, COL_INFO); /*XXX: why ?*/ |
527 | 26 | col_add_str(pinfo->cinfo, COL_INFO, str_cmd); |
528 | | |
529 | 26 | lwm_cmd_tree = proto_tree_add_subtree(lwm_tree, new_tvb, 0, -1, ett_lwm_cmd_tree, &ti, str_cmd); |
530 | | |
531 | 26 | proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd, new_tvb, 0, 1, lwm_cmd); |
532 | | |
533 | 26 | switch (lwm_cmd) { |
534 | | |
535 | 7 | case LWM_CMD_ACK: |
536 | 7 | len = dissect_lwm_cmd_frame_ack(new_tvb, pinfo, lwm_cmd_tree); |
537 | 7 | break; |
538 | | |
539 | 4 | case LWM_CMD_ROUTE_ERR: |
540 | 4 | len = dissect_lwm_cmd_frame_route_err(new_tvb, pinfo, lwm_cmd_tree); |
541 | 4 | break; |
542 | | |
543 | 5 | case LWM_CMD_ROUTE_REQ: |
544 | 5 | len = dissect_lwm_cmd_frame_route_req(new_tvb, pinfo, lwm_cmd_tree); |
545 | 5 | break; |
546 | | |
547 | 5 | case LWM_CMD_ROUTE_REPLY: |
548 | 5 | len = dissect_lwm_cmd_frame_route_reply(new_tvb, pinfo, lwm_cmd_tree); |
549 | 5 | break; |
550 | | |
551 | 5 | default: |
552 | | /*Unknown command*/ |
553 | 5 | expert_add_info_format(pinfo, lwm_cmd_tree, &ei_lwm_mal_error, "Unknown command"); |
554 | 5 | call_data_dissector(new_tvb, pinfo, lwm_cmd_tree); |
555 | 5 | return tvb_captured_length(tvb); |
556 | 26 | } |
557 | | |
558 | 20 | proto_item_set_len(ti, len); |
559 | | |
560 | | /*Here only if additional data after valid 'cmd' data*/ |
561 | | /*Note: exception will have already occurred if tvb was missing required bytes for 'cmd'*/ |
562 | | /* Report error if additional undissected data*/ |
563 | 20 | if (len < tvb_reported_length(new_tvb)) { |
564 | | /*unknown additional data*/ |
565 | 18 | expert_add_info_format(pinfo, lwm_cmd_tree, &ei_lwm_mal_error, |
566 | 18 | "Size is %i byte(s), instead of %i bytes", tvb_reported_length(new_tvb), len); |
567 | | |
568 | 18 | new_tvb = tvb_new_subset_remaining(new_tvb, len); |
569 | 18 | call_data_dissector(new_tvb, pinfo, lwm_tree); |
570 | 18 | } |
571 | 20 | } |
572 | 16 | else{ |
573 | | /*unknown data*/ |
574 | 16 | call_data_dissector(new_tvb, pinfo, lwm_tree); |
575 | 16 | } |
576 | 42 | return tvb_captured_length(tvb); |
577 | 48 | } /* dissect_lwm */ |
578 | | |
579 | | /*FUNCTION:------------------------------------------------------ |
580 | | * NAME |
581 | | * dissect_lwm_cmd_frame_ack |
582 | | * DESCRIPTION |
583 | | * LwMesh command frame - Ack. |
584 | | * |
585 | | * PARAMETERS |
586 | | * tvbuff_t *tvb - pointer to buffer containing raw packet. |
587 | | * packet_info *pinfo - pointer to packet information fields |
588 | | * proto_tree *tree - pointer to data tree wireshark uses to display packet. |
589 | | * RETURNS |
590 | | * int length - amount of data processed |
591 | | *--------------------------------------------------------------- |
592 | | */ |
593 | | static int dissect_lwm_cmd_frame_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lwm_cmd_tree) |
594 | 7 | { |
595 | 7 | uint8_t lwm_seq; |
596 | | |
597 | | /*Get fields*/ |
598 | 7 | lwm_seq = tvb_get_uint8(tvb, 1); |
599 | | |
600 | 7 | col_append_fstr(pinfo->cinfo, COL_INFO, ", Sequence number: %d", lwm_seq); |
601 | | |
602 | 7 | if(lwm_cmd_tree){ |
603 | 7 | proto_item_append_text(proto_tree_get_parent(lwm_cmd_tree), ", Sequence number: %d", lwm_seq); |
604 | 7 | proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_seq, tvb, 1, 1, lwm_seq); |
605 | 7 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_cm, tvb, 2, 1, ENC_NA); |
606 | 7 | } |
607 | | |
608 | 7 | return LWM_CMD_FRAME_ACK_LEN; |
609 | | |
610 | 7 | } /* dissect_lwm_cmd_frame_ack*/ |
611 | | |
612 | | /*FUNCTION:------------------------------------------------------ |
613 | | * NAME |
614 | | * dissect_lwm_cmd_frame_route_err |
615 | | * DESCRIPTION |
616 | | * LwMesh command frame - Route error. |
617 | | * |
618 | | * PARAMETERS |
619 | | * tvbuff_t *tvb - pointer to buffer containing raw packet. |
620 | | * packet_info *pinfo - pointer to packet information fields |
621 | | * proto_tree *tree - pointer to data tree wireshark uses to display packet. |
622 | | * RETURNS |
623 | | * int length - amount of data processed |
624 | | *--------------------------------------------------------------- |
625 | | */ |
626 | | static int dissect_lwm_cmd_frame_route_err(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *lwm_cmd_tree) |
627 | 4 | { |
628 | 4 | if(lwm_cmd_tree){ |
629 | 4 | proto_item *ti; |
630 | | |
631 | 4 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_src, tvb, 1, 2, ENC_LITTLE_ENDIAN); |
632 | 4 | ti = proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_dst, tvb, 3, 2, ENC_LITTLE_ENDIAN); |
633 | | |
634 | 4 | if(tvb_get_uint8(tvb, 5) == LWM_CMD_MULTI_ADDR_TRUE){ |
635 | 2 | proto_item_append_text(ti, " %s", LWM_MULTI_GROUP_STRING); |
636 | 2 | }else{ |
637 | 2 | proto_item_append_text(ti, " %s", LWM_MULTI_UNICAST_STRING); |
638 | 2 | } |
639 | | |
640 | 4 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_multi, tvb, 5, 1, ENC_NA); |
641 | 4 | } |
642 | | |
643 | 4 | return LWM_CMD_FRAME_ROUTE_ERR_LEN; |
644 | | |
645 | 4 | } /* dissect_lwm_cmd_frame_route_err*/ |
646 | | |
647 | | /*FUNCTION:------------------------------------------------------ |
648 | | * NAME |
649 | | * dissect_lwm_cmd_frame_route_req |
650 | | * DESCRIPTION |
651 | | * LwMesh command frame - Route Request. |
652 | | * |
653 | | * PARAMETERS |
654 | | * tvbuff_t *tvb - pointer to buffer containing raw packet. |
655 | | * packet_info *pinfo - pointer to packet information fields |
656 | | * proto_tree *tree - pointer to data tree wireshark uses to display packet. |
657 | | * RETURNS |
658 | | * int length - amount of data processed |
659 | | *--------------------------------------------------------------- |
660 | | */ |
661 | | static int dissect_lwm_cmd_frame_route_req(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *lwm_cmd_tree) |
662 | 5 | { |
663 | 5 | if(lwm_cmd_tree){ |
664 | 5 | proto_item *ti; |
665 | 5 | uint8_t lwm_linkqual; |
666 | | |
667 | 5 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_src, tvb, 1, 2, ENC_LITTLE_ENDIAN); |
668 | 5 | ti = proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_dst, tvb, 3, 2, ENC_LITTLE_ENDIAN); |
669 | | |
670 | 5 | if(tvb_get_uint8(tvb, 5) == LWM_CMD_MULTI_ADDR_TRUE){ |
671 | 1 | proto_item_append_text(ti, " %s", LWM_MULTI_GROUP_STRING); |
672 | 4 | }else{ |
673 | 4 | proto_item_append_text(ti, " %s", LWM_MULTI_UNICAST_STRING); |
674 | 4 | } |
675 | | |
676 | 5 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_multi, tvb, 5, 1, ENC_NA); |
677 | | |
678 | 5 | lwm_linkqual = tvb_get_uint8(tvb, 6); |
679 | 5 | ti = proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_linkquality, tvb, 6, 1, lwm_linkqual); |
680 | 5 | if(lwm_linkqual == 255){ |
681 | 1 | proto_item_append_text(ti, " %s", LWM_CMD_LINKQ_STRING); |
682 | 1 | } |
683 | 5 | } |
684 | | |
685 | 5 | return LWM_CMD_FRAME_ROUTE_REQ_LEN; |
686 | | |
687 | 5 | } /* dissect_lwm_cmd_frame_route_req*/ |
688 | | |
689 | | /*FUNCTION:------------------------------------------------------ |
690 | | * NAME |
691 | | * dissect_lwm_cmd_frame_route_reply |
692 | | * DESCRIPTION |
693 | | * LwMesh command frame - Route Reply. |
694 | | * |
695 | | * PARAMETERS |
696 | | * tvbuff_t *tvb - pointer to buffer containing raw packet. |
697 | | * packet_info *pinfo - pointer to packet information fields |
698 | | * proto_tree *tree - pointer to data tree wireshark uses to display packet. |
699 | | * RETURNS |
700 | | * int length - amount of data processed |
701 | | *--------------------------------------------------------------- |
702 | | */ |
703 | | static int dissect_lwm_cmd_frame_route_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *lwm_cmd_tree) |
704 | 5 | { |
705 | 5 | if(lwm_cmd_tree){ |
706 | 5 | proto_item *ti; |
707 | 5 | uint8_t lwm_revlinkqual; |
708 | | |
709 | 5 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_src, tvb, 1, 2, ENC_LITTLE_ENDIAN); |
710 | 5 | ti = proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_dst, tvb, 3, 2, ENC_LITTLE_ENDIAN); |
711 | | |
712 | 5 | if(tvb_get_uint8(tvb, 5) == LWM_CMD_MULTI_ADDR_TRUE){ |
713 | 1 | proto_item_append_text(ti, " %s", LWM_MULTI_GROUP_STRING); |
714 | 4 | }else{ |
715 | 4 | proto_item_append_text(ti, " %s", LWM_MULTI_UNICAST_STRING); |
716 | 4 | } |
717 | | |
718 | 5 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_multi, tvb, 5, 1, ENC_NA); |
719 | 5 | proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_forwlinkquality, tvb, 6, 1, ENC_NA); |
720 | | |
721 | 5 | lwm_revlinkqual = tvb_get_uint8(tvb, 7); |
722 | 5 | ti = proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_revlinkquality, tvb, 7, 1, lwm_revlinkqual); |
723 | 5 | if(lwm_revlinkqual == 255){ |
724 | 2 | proto_item_append_text(ti, " %s", LWM_CMD_LINKQ_STRING); |
725 | 2 | } |
726 | 5 | } |
727 | | |
728 | 5 | return LWM_CMD_FRAME_ROUTE_REPLY_LEN; |
729 | | |
730 | 5 | } /* dissect_lwm_cmd_frame_route_reply*/ |
731 | | |
732 | | /*FUNCTION:------------------------------------------------------ |
733 | | * NAME |
734 | | * proto_register_lwm |
735 | | * DESCRIPTION |
736 | | * IEEE 802.15.4 protocol registration routine. |
737 | | * PARAMETERS |
738 | | * none |
739 | | * RETURNS |
740 | | * void |
741 | | *--------------------------------------------------------------- |
742 | | */ |
743 | | void proto_register_lwm(void) |
744 | 16 | { |
745 | | |
746 | 16 | static hf_register_info hf[] = { |
747 | | |
748 | | /*Frame control field*/ |
749 | 16 | { &hf_lwm_fcf, |
750 | 16 | { "Frame control field", "lwm.fcf", FT_UINT8, BASE_HEX, NULL, 0x0, |
751 | 16 | "Control information for the frame.", HFILL }}, |
752 | | |
753 | 16 | { &hf_lwm_fcf_ack_req, |
754 | 16 | { "Acknowledgment Request", "lwm.ack_req", FT_BOOLEAN, 8, NULL, LWM_FCF_ACK_REQUEST, |
755 | 16 | "Specifies whether an acknowledgment is required from the destination node.", HFILL }}, |
756 | | |
757 | 16 | { &hf_lwm_fcf_security, |
758 | 16 | { "Security Enabled", "lwm.security", FT_BOOLEAN, 8, NULL, LWM_FCF_SEC_EN, |
759 | 16 | "Specifies whether the frame payload is encrypted.", HFILL }}, |
760 | | |
761 | 16 | { &hf_lwm_fcf_linklocal, |
762 | 16 | { "Link Local", "lwm.linklocal", FT_BOOLEAN, 8, NULL, LWM_FCF_LINK_LOCAL, |
763 | 16 | "It may be set to one to prevent neighboring nodes from rebroadcasting a frame.", HFILL }}, |
764 | | |
765 | 16 | { &hf_lwm_fcf_multicast, |
766 | 16 | { "Multicast", "lwm.multicast", FT_BOOLEAN, 8, NULL, LWM_FCF_MULTICAST, |
767 | 16 | "If the Multicast subfield is set to one, Multicast Header should be present and the Destination Address is a group address.", HFILL }}, |
768 | | |
769 | 16 | { &hf_lwm_fcf_reserved, |
770 | 16 | { "Reserved bits", "lwm.fcf.reserved", FT_UINT8, BASE_HEX, NULL, LWM_FCF_RESERVED, |
771 | 16 | "The 4 bits are reserved.", HFILL }}, |
772 | | |
773 | | /*Other fields*/ |
774 | 16 | { &hf_lwm_seq, |
775 | 16 | { "Sequence Number", "lwm.seq", FT_UINT8, BASE_DEC, NULL, 0x0, |
776 | 16 | "Specifies the sequence identifier for the frame.", HFILL }}, |
777 | | |
778 | 16 | { &hf_lwm_src_addr, |
779 | 16 | { "Network Source Address", "lwm.src_addr", FT_UINT16, BASE_HEX, NULL, 0x0, |
780 | 16 | "Specifies the network address of the node originating the frame.", HFILL }}, |
781 | | |
782 | 16 | { &hf_lwm_dst_addr, |
783 | 16 | { "Network Destination Address", "lwm.dst_addr", FT_UINT16, BASE_HEX, NULL, 0x0, |
784 | 16 | "Specifies the network address of the destination node or group address for multicast messages.", HFILL }}, |
785 | | |
786 | 16 | { &hf_lwm_src_endp, |
787 | 16 | { "Source Endpoint", "lwm.src_endp", FT_UINT8, BASE_DEC, NULL, 0x0, |
788 | 16 | "Specifies the source endpoint identifier.", HFILL }}, |
789 | | |
790 | 16 | { &hf_lwm_dst_endp, |
791 | 16 | { "Destination Endpoint", "lwm.dst_endp", FT_UINT8, BASE_DEC, NULL, 0x0, |
792 | 16 | "Specifies the destination endpoint identifier.", HFILL }}, |
793 | | |
794 | | |
795 | | /*Multicast header*/ |
796 | 16 | { &hf_lwm_multi_nmrad, |
797 | 16 | { "Non-member Radius", "lwm.multi_nmrad", FT_UINT16, BASE_DEC, NULL, 0x0, |
798 | 16 | "Specifies remaining radius (number of hops) for Non-members of multicast group.", HFILL }}, |
799 | | |
800 | 16 | { &hf_lwm_multi_mnmrad, |
801 | 16 | { "Maximum Non-member Radius", "lwm.multi_mnmrad", FT_UINT16, BASE_DEC, NULL, 0x0, |
802 | 16 | "Specifies maximum radius (number of hops) for Non-members of multicast group.", HFILL }}, |
803 | | |
804 | 16 | { &hf_lwm_multi_mrad, |
805 | 16 | { "Member Radius", "lwm.multi_mrad", FT_UINT16, BASE_DEC, NULL, 0x0, |
806 | 16 | "Specifies remaining radius (number of hops) for Members of multicast group.", HFILL }}, |
807 | | |
808 | 16 | { &hf_lwm_multi_mmrad, |
809 | 16 | { "Maximum Member Radius", "lwm.multi_mmrad", FT_UINT16, BASE_DEC, NULL, 0x0, |
810 | 16 | "Specifies maximum radius (number of hops) for Members of multicast group.", HFILL }}, |
811 | | |
812 | | |
813 | | /*MIC, security*/ |
814 | 16 | { &hf_lwm_mic, |
815 | 16 | { "Message Integrity Code", "lwm.mic", FT_UINT32, BASE_HEX, NULL, 0x0, |
816 | 16 | "Specifies Message Integrity Code (MIC).", HFILL }}, |
817 | | |
818 | | |
819 | | /*----------------------------------*/ |
820 | | /* */ |
821 | | /* Command Frames Specific Fields */ |
822 | | /* */ |
823 | | /*----------------------------------*/ |
824 | | |
825 | 16 | { &hf_lwm_cmd, |
826 | 16 | { "Command ID", "lwm.cmd", FT_UINT8, BASE_HEX, VALS(lwm_cmd_names), 0x0, |
827 | 16 | "It contains Command ID value.", HFILL }}, |
828 | | |
829 | | /* Command Frame - Ack */ |
830 | 16 | { &hf_lwm_cmd_seq, |
831 | 16 | { "Sequence number", "lwm.cmd.seq", FT_UINT8, BASE_DEC, NULL, 0x0, |
832 | 16 | "It contains a network sequence number of a frame that is being acknowledged.", HFILL }}, |
833 | | |
834 | 16 | { &hf_lwm_cmd_cm, |
835 | 16 | { "Control Message", "lwm.cmd.cm", FT_UINT8, BASE_HEX, NULL, 0x0, |
836 | 16 | "It contains an arbitrary value that can be set on the sending side.", HFILL }}, |
837 | | |
838 | | /* Part of Command Frames - Route Request, Route Reply*/ |
839 | 16 | { &hf_lwm_cmd_route_src, |
840 | 16 | { "Source address", "lwm.cmd.route_src", FT_UINT16, BASE_HEX, NULL, 0x0, |
841 | 16 | "It contains a source network address from the frame that cannot be routed", HFILL }}, |
842 | | |
843 | 16 | { &hf_lwm_cmd_route_dst, |
844 | 16 | { "Destination Address", "lwm.cmd.route_dst", FT_UINT16, BASE_HEX, NULL, 0x0, |
845 | 16 | "It contains a destination network address from the frame that cannot be routed", HFILL }}, |
846 | | |
847 | 16 | { &hf_lwm_cmd_route_multi, |
848 | 16 | { "Multicast", "lwm.cmd.multi", FT_UINT8, BASE_HEX, VALS(lwm_cmd_multi_names), 0x0, |
849 | 16 | "If it set to 0, Destination Address field contains a network address. If it set to 1, Destination Address field contains a group ID.", HFILL }}, |
850 | | |
851 | | /* Part of Command Frame - Route Request */ |
852 | 16 | { &hf_lwm_cmd_linkquality, |
853 | 16 | { "Link Quality", "lwm.cmd.linkq", FT_UINT8, BASE_DEC, NULL, 0x0, |
854 | 16 | "It contains a link quality value of the potential route accumulated over all hops towards the destination.", HFILL }}, |
855 | | |
856 | | /* Part of Command Frame - Route Reply */ |
857 | 16 | { &hf_lwm_cmd_forwlinkquality, |
858 | 16 | { "Forward Link Quality", "lwm.cmd.flinkq", FT_UINT8, BASE_DEC, NULL, 0x0, |
859 | 16 | "It contains a value of the Link Quality field from the corresponding Route Request Command Frame.", HFILL }}, |
860 | | |
861 | 16 | { &hf_lwm_cmd_revlinkquality, |
862 | 16 | { "Reverse Link Quality", "lwm.cmd.rlinkq", FT_UINT8, BASE_DEC, NULL, 0x0, |
863 | 16 | "It contains a link quality value of the discovered route accumulated over all hops towards the originator.", HFILL }}, |
864 | | |
865 | | |
866 | 16 | }; |
867 | | |
868 | | /* Subtrees */ |
869 | 16 | static int *ett[] = { |
870 | 16 | &ett_lwm, |
871 | 16 | &ett_lwm_fcf, |
872 | 16 | &ett_lwm_multi_tree, |
873 | 16 | &ett_lwm_cmd_tree |
874 | 16 | }; |
875 | | |
876 | 16 | static ei_register_info ei[] = { |
877 | 16 | { &ei_lwm_mal_error, { "lwm.malformed_error", PI_MALFORMED, PI_ERROR, "Malformed Packet", EXPFILL }}, |
878 | 16 | { &ei_lwm_n_src_broad, { "lwm.not_src_broadcast", PI_COMMENTS_GROUP, PI_NOTE, "Source address can not be broadcast address !", EXPFILL }}, |
879 | 16 | { &ei_lwm_mismatch_endp, { "lwm.mismatch_endp", PI_COMMENTS_GROUP, PI_WARN, "Stack command Endpoints mismatch (should be 0, both)!", EXPFILL }}, |
880 | 16 | { &ei_lwm_empty_payload, { "lwm.empty_payload", PI_COMMENTS_GROUP, PI_WARN, "Empty LwMesh Payload!", EXPFILL }}, |
881 | 16 | { &ei_lwm_no_decryption_key, { "lwm.no_decryption_key", PI_PROTOCOL, PI_NOTE, "No encryption key set - can't decrypt", EXPFILL }}, |
882 | 16 | { &ei_lwm_decryption_failed, { "lwm.decryption_failed", PI_PROTOCOL, PI_WARN, "Decryption Failed", EXPFILL }}, |
883 | 16 | }; |
884 | | |
885 | 16 | module_t *lw_module; |
886 | 16 | expert_module_t* expert_lwm; |
887 | | |
888 | | /* Register protocol name and description. */ |
889 | 16 | proto_lwm = proto_register_protocol("Lightweight Mesh (v1.1.1)", "LwMesh", "lwm"); |
890 | | |
891 | | /* Register header fields and subtrees. */ |
892 | 16 | proto_register_field_array(proto_lwm, hf, array_length(hf)); |
893 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
894 | 16 | expert_lwm = expert_register_protocol(proto_lwm); |
895 | 16 | expert_register_field_array(expert_lwm, ei, array_length(ei)); |
896 | | |
897 | 16 | lw_module = prefs_register_protocol(proto_lwm,proto_reg_handoff_lwm); |
898 | | |
899 | | /* Register preferences for a decryption key */ |
900 | | /* TODO: Implement a UAT for multiple keys, and with more advanced key management. */ |
901 | 16 | prefs_register_string_preference(lw_module, "lwmes_key", "Lw Decryption key", |
902 | 16 | "128-bit decryption key in hexadecimal format", (const char **)&lwmes_key_str); |
903 | | |
904 | | /* Register dissector with Wireshark. */ |
905 | 16 | lwm_handle = register_dissector("lwm", dissect_lwm, proto_lwm); |
906 | | |
907 | 16 | } /* proto_register_lwm */ |
908 | | |
909 | | /*FUNCTION:------------------------------------------------------ |
910 | | * NAME |
911 | | * proto_reg_handoff_lwm |
912 | | * DESCRIPTION |
913 | | * Registers the lwm dissector with Wireshark. |
914 | | * Will be called during Wireshark startup, and whenever |
915 | | * preferences are changed. |
916 | | * PARAMETERS |
917 | | * none |
918 | | * RETURNS |
919 | | * void |
920 | | *--------------------------------------------------------------- |
921 | | */ |
922 | | void proto_reg_handoff_lwm(void) |
923 | 16 | { |
924 | 16 | static bool initialized = false; |
925 | 16 | GByteArray *bytes; |
926 | 16 | bool res; |
927 | | |
928 | 16 | if (!initialized) { |
929 | | /* Register our dissector with IEEE 802.15.4 */ |
930 | 16 | dissector_add_for_decode_as(IEEE802154_PROTOABBREV_WPAN_PANID, lwm_handle); |
931 | 16 | heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_lwm_heur, "Lightweight Mesh over IEEE 802.15.4", "lwm_wlan", proto_lwm, HEURISTIC_ENABLE); |
932 | | |
933 | 16 | initialized = true; |
934 | 16 | } |
935 | | /* Convert key to raw bytes */ |
936 | 16 | bytes = g_byte_array_new(); |
937 | 16 | res = hex_str_to_bytes(lwmes_key_str, bytes, false); |
938 | 16 | lwmes_key_valid = (res && bytes->len >= IEEE802154_CIPHER_SIZE); |
939 | 16 | if (lwmes_key_valid) { |
940 | 0 | memcpy(lwmes_key, bytes->data, IEEE802154_CIPHER_SIZE); |
941 | 0 | } |
942 | 16 | g_byte_array_free(bytes, true); |
943 | | |
944 | 16 | } /* proto_reg_handoff_lwm */ |
945 | | |
946 | | /* |
947 | | * Editor modelines |
948 | | * |
949 | | * Local Variables: |
950 | | * c-basic-offset: 4 |
951 | | * tab-width: 8 |
952 | | * indent-tabs-mode: nil |
953 | | * End: |
954 | | * |
955 | | * ex: set shiftwidth=4 tabstop=8 expandtab: |
956 | | * :indentSize=4:tabSize=8:noTabs=true: |
957 | | */ |