/src/wireshark/epan/dissectors/packet-btmesh-pbadv.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-btmesh-pbadv.c |
2 | | * Routines for Bluetooth mesh PB-ADV dissection |
3 | | * |
4 | | * Copyright 2019, Piotr Winiarczyk <wino45@gmail.com> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | * |
12 | | * Ref: Mesh Profile v1.0 |
13 | | * https://www.bluetooth.com/specifications/mesh-specifications |
14 | | */ |
15 | | |
16 | | #include "config.h" |
17 | | |
18 | | #include <epan/packet.h> |
19 | | #include <epan/prefs.h> |
20 | | #include <epan/reassemble.h> |
21 | | #include <epan/expert.h> |
22 | | |
23 | | #include "packet-btmesh.h" |
24 | | |
25 | 32 | #define BTMESH_PB_ADV_NOT_USED 0 |
26 | | |
27 | 5 | #define TRANSACTION_START 0x00 |
28 | 12 | #define TRANSACTION_ACKNOWLEDGMENT 0x01 |
29 | 19 | #define TRANSACTION_CONTINUATION 0x02 |
30 | 3 | #define PROVISIONING_BEARER_CONTROL 0x03 |
31 | | |
32 | 1 | #define LINK_OPEN 0x00 |
33 | 0 | #define LINK_ACK 0x01 |
34 | 1 | #define LINK_CLOSE 0x02 |
35 | | |
36 | | void proto_register_btmesh_pbadv(void); |
37 | | void proto_reg_handoff_btmesh_pbadv(void); |
38 | | |
39 | | static int proto_btmesh_pbadv; |
40 | | |
41 | | static dissector_handle_t btmesh_provisioning_handle; |
42 | | |
43 | | static int hf_btmesh_pbadv_linkid; |
44 | | static int hf_btmesh_pbadv_trnumber; |
45 | | |
46 | | static int hf_btmesh_generic_provisioning_control_format; |
47 | | static int hf_btmesh_gpcf_segn; |
48 | | static int hf_btmesh_gpcf_total_length; |
49 | | //TODO - check FCS |
50 | | static int hf_btmesh_gpcf_fcs; |
51 | | static int hf_btmesh_gpcf_padding; |
52 | | static int hf_btmesh_gpcf_segment_index; |
53 | | static int hf_btmesh_gpcf_bearer_opcode; |
54 | | static int hf_btmesh_gpcf_bearer_opcode_device_UUID; |
55 | | static int hf_btmesh_gpcf_bearer_opcode_reason; |
56 | | static int hf_btmesh_gpcf_bearer_unknown_data; |
57 | | |
58 | | static int hf_btmesh_gpp_payload; |
59 | | static int hf_btmesh_gpp_payload_fragment; |
60 | | static int hf_btmesh_gpp_fragments; |
61 | | static int hf_btmesh_gpp_fragment; |
62 | | static int hf_btmesh_gpp_fragment_overlap; |
63 | | static int hf_btmesh_gpp_fragment_overlap_conflict; |
64 | | static int hf_btmesh_gpp_fragment_multiple_tails; |
65 | | static int hf_btmesh_gpp_fragment_too_long_fragment; |
66 | | static int hf_btmesh_gpp_fragment_error; |
67 | | static int hf_btmesh_gpp_fragment_count; |
68 | | static int hf_btmesh_gpp_reassembled_length; |
69 | | |
70 | | static int ett_btmesh_pbadv; |
71 | | static int ett_btmesh_generic_provisioning; |
72 | | static int ett_btmesh_gpp_fragments; |
73 | | static int ett_btmesh_gpp_fragment; |
74 | | |
75 | | static expert_field ei_btmesh_gpcf_unknown_opcode; |
76 | | static expert_field ei_btmesh_gpcf_unknown_payload; |
77 | | |
78 | | static const fragment_items btmesh_gpp_frag_items = { |
79 | | &ett_btmesh_gpp_fragments, |
80 | | &ett_btmesh_gpp_fragment, |
81 | | |
82 | | &hf_btmesh_gpp_fragments, |
83 | | &hf_btmesh_gpp_fragment, |
84 | | &hf_btmesh_gpp_fragment_overlap, |
85 | | &hf_btmesh_gpp_fragment_overlap_conflict, |
86 | | &hf_btmesh_gpp_fragment_multiple_tails, |
87 | | &hf_btmesh_gpp_fragment_too_long_fragment, |
88 | | &hf_btmesh_gpp_fragment_error, |
89 | | &hf_btmesh_gpp_fragment_count, |
90 | | NULL, |
91 | | &hf_btmesh_gpp_reassembled_length, |
92 | | /* Reassembled data field */ |
93 | | NULL, |
94 | | "fragments" |
95 | | }; |
96 | | |
97 | | static const value_string btmesh_generic_provisioning_control_format[] = { |
98 | | { 0, "Transaction Start" }, |
99 | | { 1, "Transaction Acknowledgment" }, |
100 | | { 2, "Transaction Continuation" }, |
101 | | { 3, "Provisioning Bearer Control" }, |
102 | | { 0, NULL } |
103 | | }; |
104 | | |
105 | | static const value_string btmesh_gpcf_bearer_opcode_format[] = { |
106 | | { 0, "Link Open" }, |
107 | | { 1, "Link ACK" }, |
108 | | { 2, "Link Close" }, |
109 | | { 0, NULL } |
110 | | }; |
111 | | |
112 | | static const value_string btmesh_gpcf_bearer_opcode_reason_format[] = { |
113 | | { 0, "Success" }, |
114 | | { 1, "Timeout" }, |
115 | | { 2, "Fail" }, |
116 | | { 0, NULL } |
117 | | }; |
118 | | |
119 | | /* needed for packet reassembly */ |
120 | | static reassembly_table pbadv_reassembly_table; |
121 | | |
122 | | typedef struct _pbadv_fragment_key { |
123 | | uint32_t link_id; |
124 | | uint8_t transaction_number; |
125 | | } pbadv_fragment_key; |
126 | | |
127 | | static unsigned |
128 | | pbadv_fragment_hash(const void *k) |
129 | 36 | { |
130 | 36 | const pbadv_fragment_key* key = (const pbadv_fragment_key*) k; |
131 | 36 | unsigned hash_val; |
132 | | |
133 | 36 | hash_val = 0; |
134 | | |
135 | 36 | hash_val += key->link_id; |
136 | 36 | hash_val += key->transaction_number; |
137 | 36 | return hash_val; |
138 | 36 | } |
139 | | |
140 | | static int |
141 | | pbadv_fragment_equal(const void *k1, const void *k2) |
142 | 25 | { |
143 | 25 | const pbadv_fragment_key* key1 = (const pbadv_fragment_key*) k1; |
144 | 25 | const pbadv_fragment_key* key2 = (const pbadv_fragment_key*) k2; |
145 | | |
146 | 25 | return ((key1->link_id == key2->link_id) && (key1->transaction_number == key2->transaction_number) |
147 | 25 | ? true : false); |
148 | 25 | } |
149 | | |
150 | | static void * |
151 | | pbadv_fragment_temporary_key(const packet_info *pinfo _U_, const uint32_t id _U_, |
152 | | const void *data) |
153 | 31 | { |
154 | 31 | pbadv_fragment_key *key = g_slice_new(pbadv_fragment_key); |
155 | 31 | const pbadv_fragment_key *pbadv = (const pbadv_fragment_key *)data; |
156 | | |
157 | 31 | key->link_id = pbadv->link_id; |
158 | 31 | key->transaction_number = pbadv->transaction_number; |
159 | | |
160 | 31 | return key; |
161 | 31 | } |
162 | | |
163 | | static void |
164 | | pbadv_fragment_free_temporary_key(void *ptr) |
165 | 31 | { |
166 | 31 | pbadv_fragment_key *key = (pbadv_fragment_key *)ptr; |
167 | | |
168 | 31 | g_slice_free(pbadv_fragment_key, key); |
169 | 31 | } |
170 | | |
171 | | static void * |
172 | | pbadv_fragment_persistent_key(const packet_info *pinfo _U_, const uint32_t id _U_, |
173 | | const void *data) |
174 | 5 | { |
175 | 5 | pbadv_fragment_key *key = g_slice_new(pbadv_fragment_key); |
176 | 5 | const pbadv_fragment_key *pbadv = (const pbadv_fragment_key *)data; |
177 | | |
178 | 5 | key->link_id = pbadv->link_id; |
179 | 5 | key->transaction_number = pbadv->transaction_number; |
180 | | |
181 | 5 | return key; |
182 | 5 | } |
183 | | |
184 | | static void |
185 | | pbadv_fragment_free_persistent_key(void *ptr) |
186 | 0 | { |
187 | 0 | pbadv_fragment_key *key = (pbadv_fragment_key *)ptr; |
188 | 0 | if (key) { |
189 | 0 | g_slice_free(pbadv_fragment_key, key); |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | | static const reassembly_table_functions pbadv_reassembly_table_functions = { |
194 | | pbadv_fragment_hash, |
195 | | pbadv_fragment_equal, |
196 | | pbadv_fragment_temporary_key, |
197 | | pbadv_fragment_persistent_key, |
198 | | pbadv_fragment_free_temporary_key, |
199 | | pbadv_fragment_free_persistent_key |
200 | | }; |
201 | | |
202 | | static int |
203 | | dissect_btmesh_pbadv_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
204 | 39 | { |
205 | | |
206 | 39 | proto_item *item; |
207 | 39 | proto_tree *sub_tree, *sub_tree_generic_provisioning; |
208 | 39 | proto_item *ti; |
209 | 39 | bool defragment = false; |
210 | 39 | int offset = 0; |
211 | 39 | btle_mesh_transport_ctx_t tr_ctx; |
212 | 39 | uint8_t segn, length; |
213 | 39 | uint32_t total_length; |
214 | 39 | uint8_t gpcf_bearer_opcode; |
215 | | |
216 | 39 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "BT Mesh PB-ADV"); |
217 | | |
218 | 39 | item = proto_tree_add_item(tree, proto_btmesh_pbadv, tvb, offset, -1, ENC_NA); |
219 | 39 | sub_tree = proto_item_add_subtree(item, ett_btmesh_pbadv); |
220 | | |
221 | 39 | uint32_t pbadv_link_id = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN); |
222 | 39 | proto_tree_add_item(sub_tree, hf_btmesh_pbadv_linkid, tvb, offset, 4, ENC_BIG_ENDIAN); |
223 | 39 | offset += 4; |
224 | | |
225 | 39 | uint8_t pbadv_trnumber = tvb_get_uint8(tvb, offset); |
226 | 39 | proto_tree_add_item(sub_tree, hf_btmesh_pbadv_trnumber, tvb, offset, 1, ENC_NA); |
227 | 39 | offset += 1; |
228 | | |
229 | 39 | pbadv_fragment_key frg_key; |
230 | 39 | frg_key.link_id = pbadv_link_id; |
231 | 39 | frg_key.transaction_number = pbadv_trnumber; |
232 | | |
233 | 39 | sub_tree_generic_provisioning = proto_tree_add_subtree(sub_tree, tvb, offset, -1, ett_btmesh_generic_provisioning, &ti, "Generic Provisioning PDU"); |
234 | | |
235 | 39 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_generic_provisioning_control_format, tvb, offset, 1, ENC_NA); |
236 | 39 | uint8_t gpcf = tvb_get_uint8(tvb, offset) & 0x03; |
237 | | |
238 | 39 | col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(gpcf, btmesh_generic_provisioning_control_format, "Unknown PDU")); |
239 | | |
240 | 39 | fragment_head *fd_head = NULL; |
241 | 39 | int segment_index = -1; |
242 | | |
243 | 39 | switch (gpcf) { |
244 | | //Transaction Start |
245 | 5 | case TRANSACTION_START: |
246 | 5 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_segn, tvb, offset, 1, ENC_NA); |
247 | 5 | segn = (tvb_get_uint8(tvb, offset) & 0xFC) >> 2; |
248 | 5 | offset += 1; |
249 | 5 | total_length = (uint32_t)tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN); |
250 | 5 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_total_length, tvb, offset, 2, ENC_BIG_ENDIAN); |
251 | 5 | offset += 2; |
252 | 5 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_fcs, tvb, offset, 1, ENC_NA); |
253 | 5 | offset += 1; |
254 | 5 | segment_index = 0; |
255 | 5 | defragment = true; |
256 | 5 | if (segn == 0) { |
257 | 1 | if (btmesh_provisioning_handle) { |
258 | 1 | length = tvb_reported_length(tvb); |
259 | 1 | tr_ctx.transport = E_BTMESH_TR_ADV; |
260 | 1 | tr_ctx.fragmented = false; |
261 | 1 | tr_ctx.segment_index = 0; |
262 | 1 | call_dissector_with_data(btmesh_provisioning_handle, tvb_new_subset_length(tvb, offset, length), |
263 | 1 | pinfo, proto_tree_get_root(sub_tree_generic_provisioning), &tr_ctx); |
264 | 1 | } else { |
265 | 0 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpp_payload, tvb, offset, -1, ENC_NA); |
266 | 0 | } |
267 | 4 | } else { |
268 | | //Segmentation |
269 | 4 | if (!pinfo->fd->visited) { |
270 | | //First fragment can be delivered out of order, and can be the last one. |
271 | 4 | fd_head = fragment_get(&pbadv_reassembly_table, pinfo, BTMESH_PB_ADV_NOT_USED, &frg_key); |
272 | 4 | if (fd_head) { |
273 | 3 | fragment_set_tot_len(&pbadv_reassembly_table, pinfo, BTMESH_PB_ADV_NOT_USED, &frg_key, total_length); |
274 | 3 | } |
275 | 4 | fd_head = fragment_add(&pbadv_reassembly_table, |
276 | 4 | tvb, offset, pinfo, |
277 | 4 | BTMESH_PB_ADV_NOT_USED, &frg_key, |
278 | 4 | 0, |
279 | 4 | tvb_captured_length_remaining(tvb, offset), |
280 | 4 | true); |
281 | 4 | if (!fd_head) { |
282 | | //Set the length only when not reassembled |
283 | 2 | fragment_set_tot_len(&pbadv_reassembly_table, pinfo, BTMESH_PB_ADV_NOT_USED, &frg_key, total_length); |
284 | 2 | } |
285 | 4 | } else { |
286 | 0 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpp_payload_fragment, tvb, offset, -1, ENC_NA); |
287 | 0 | } |
288 | 4 | } |
289 | | |
290 | 5 | break; |
291 | | //Transaction Acknowledgment |
292 | 12 | case TRANSACTION_ACKNOWLEDGMENT: |
293 | 12 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_padding, tvb, offset, 1, ENC_NA); |
294 | | |
295 | 12 | break; |
296 | | //Transaction Continuation |
297 | 19 | case TRANSACTION_CONTINUATION: |
298 | 19 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_segment_index, tvb, offset, 1, ENC_NA); |
299 | 19 | segment_index = (tvb_get_uint8(tvb, offset) & 0xFC) >> 2; |
300 | 19 | defragment = true; |
301 | 19 | offset += 1; |
302 | | //Segmentation |
303 | 19 | if (!pinfo->fd->visited) { |
304 | 19 | fragment_add(&pbadv_reassembly_table, |
305 | 19 | tvb, offset, pinfo, |
306 | 19 | BTMESH_PB_ADV_NOT_USED, &frg_key, |
307 | 19 | 20 + (segment_index - 1) * 23, |
308 | 19 | tvb_captured_length_remaining(tvb, offset), |
309 | 19 | true); |
310 | 19 | } else { |
311 | 0 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpp_payload_fragment, tvb, offset, -1, ENC_NA); |
312 | 0 | } |
313 | | |
314 | 19 | break; |
315 | | //Provisioning Bearer Control |
316 | 3 | case PROVISIONING_BEARER_CONTROL: |
317 | 3 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_bearer_opcode, tvb, offset, 1, ENC_NA); |
318 | 3 | gpcf_bearer_opcode = (tvb_get_uint8(tvb, offset) & 0xFC) >> 2; |
319 | 3 | offset += 1; |
320 | 3 | switch(gpcf_bearer_opcode) { |
321 | 1 | case LINK_OPEN: |
322 | 1 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_bearer_opcode_device_UUID, tvb, offset, 16, ENC_BIG_ENDIAN); |
323 | 1 | offset += 16; |
324 | | |
325 | 1 | break; |
326 | 0 | case LINK_ACK: |
327 | | //No data in this PDU |
328 | |
|
329 | 0 | break; |
330 | 1 | case LINK_CLOSE: |
331 | 1 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_bearer_opcode_reason, tvb, offset, 1, ENC_NA); |
332 | 1 | offset += 1; |
333 | | |
334 | 1 | break; |
335 | 1 | default: |
336 | | //Unknown data |
337 | 1 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpcf_bearer_unknown_data, tvb, offset, -1, ENC_NA); |
338 | 1 | offset += tvb_captured_length_remaining(tvb, offset); |
339 | 1 | proto_tree_add_expert(sub_tree, pinfo, &ei_btmesh_gpcf_unknown_opcode, tvb, offset, -1); |
340 | 1 | break; |
341 | 3 | } |
342 | | //There is still some data but all data should be already disssected |
343 | 2 | if (tvb_captured_length_remaining(tvb, offset) != 0) { |
344 | 2 | proto_tree_add_expert(sub_tree, pinfo, &ei_btmesh_gpcf_unknown_payload, tvb, offset, -1); |
345 | 2 | } |
346 | | |
347 | 2 | break; |
348 | 39 | } |
349 | | //Second pass |
350 | 36 | if (pinfo->fd->visited && defragment ) { |
351 | 0 | fd_head = fragment_get(&pbadv_reassembly_table, pinfo, BTMESH_PB_ADV_NOT_USED, &frg_key); |
352 | 0 | if (fd_head && (fd_head->flags&FD_DEFRAGMENTED)) { |
353 | 0 | tvbuff_t *next_tvb; |
354 | 0 | next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled Provisioning PDU", fd_head, &btmesh_gpp_frag_items, NULL, sub_tree_generic_provisioning); |
355 | 0 | if (next_tvb) { |
356 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)"); |
357 | 0 | if (btmesh_provisioning_handle) { |
358 | 0 | tr_ctx.transport = E_BTMESH_TR_ADV; |
359 | 0 | tr_ctx.fragmented = true; |
360 | 0 | tr_ctx.segment_index = segment_index; |
361 | 0 | call_dissector_with_data(btmesh_provisioning_handle, next_tvb, pinfo, |
362 | 0 | proto_tree_get_root(sub_tree_generic_provisioning), &tr_ctx); |
363 | 0 | } else { |
364 | 0 | proto_tree_add_item(sub_tree_generic_provisioning, hf_btmesh_gpp_payload, next_tvb, 0, -1, ENC_NA); |
365 | 0 | } |
366 | 0 | } else { |
367 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO," (Message fragment %u)", segment_index); |
368 | 0 | } |
369 | 0 | } |
370 | 0 | } |
371 | | |
372 | 36 | return tvb_reported_length(tvb); |
373 | 39 | } |
374 | | |
375 | | void |
376 | | proto_register_btmesh_pbadv(void) |
377 | 14 | { |
378 | 14 | static hf_register_info hf[] = { |
379 | | //PB-ADV |
380 | 14 | { &hf_btmesh_pbadv_linkid, |
381 | 14 | { "Link ID", "pbadv.linkid", |
382 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
383 | 14 | NULL, HFILL } |
384 | 14 | }, |
385 | 14 | { &hf_btmesh_pbadv_trnumber, |
386 | 14 | { "Transaction Number", "pbadv.trnumber", |
387 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
388 | 14 | NULL, HFILL } |
389 | 14 | }, |
390 | | //Generic Provisioning Control |
391 | 14 | { &hf_btmesh_generic_provisioning_control_format, |
392 | 14 | { "Generic Provisioning Control Format", "pbadv.gen_prov.gpcf", |
393 | 14 | FT_UINT8, BASE_DEC, VALS(btmesh_generic_provisioning_control_format), 0x03, |
394 | 14 | NULL, HFILL } |
395 | 14 | }, |
396 | 14 | { &hf_btmesh_gpcf_segn, |
397 | 14 | { "The last segment number", "pbadv.gen_prov.gpcf.segn", |
398 | 14 | FT_UINT8, BASE_DEC, NULL, 0xFC, |
399 | 14 | NULL, HFILL } |
400 | 14 | }, |
401 | 14 | { &hf_btmesh_gpcf_total_length, |
402 | 14 | { "Total Length", "pbadv.gen_prov.gpcf.total_length", |
403 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
404 | 14 | NULL, HFILL } |
405 | 14 | }, |
406 | 14 | { &hf_btmesh_gpcf_fcs, |
407 | 14 | { "Frame Check Sequence", "pbadv.gen_prov.gpcf.fcs", |
408 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
409 | 14 | NULL, HFILL } |
410 | 14 | }, |
411 | 14 | { &hf_btmesh_gpcf_padding, |
412 | 14 | { "Padding", "pbadv.gen_prov.gpcf.padding", |
413 | 14 | FT_UINT8, BASE_DEC, NULL, 0xFC, |
414 | 14 | NULL, HFILL } |
415 | 14 | }, |
416 | 14 | { &hf_btmesh_gpcf_segment_index, |
417 | 14 | { "Segment number of the transaction", "pbadv.gen_prov.gpcf.segment_index", |
418 | 14 | FT_UINT8, BASE_DEC, NULL, 0xFC, |
419 | 14 | NULL, HFILL } |
420 | 14 | }, |
421 | 14 | { &hf_btmesh_gpcf_bearer_opcode, |
422 | 14 | { "Bearer Opcode", "pbadv.gen_prov.gpcf.bearer_opcode", |
423 | 14 | FT_UINT8, BASE_DEC, VALS(btmesh_gpcf_bearer_opcode_format), 0xFC, |
424 | 14 | NULL, HFILL } |
425 | 14 | }, |
426 | 14 | { &hf_btmesh_gpcf_bearer_opcode_device_UUID, |
427 | 14 | { "Device UUID", "pbadv.gen_prov.gpcf.bearer_opcode.device_uuid", |
428 | 14 | FT_GUID, BASE_NONE, NULL, 0x00, |
429 | 14 | NULL, HFILL } |
430 | 14 | }, |
431 | 14 | { &hf_btmesh_gpcf_bearer_opcode_reason, |
432 | 14 | { "Reason", "pbadv.gen_prov.gpcf.bearer_opcode.reason", |
433 | 14 | FT_UINT8, BASE_DEC, VALS(btmesh_gpcf_bearer_opcode_reason_format), 0x00, |
434 | 14 | NULL, HFILL } |
435 | 14 | }, |
436 | 14 | { &hf_btmesh_gpcf_bearer_unknown_data, |
437 | 14 | { "Unknown Data", "pbadv.gen_prov.gpcf.unknown_data", |
438 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
439 | 14 | NULL, HFILL } |
440 | 14 | }, |
441 | | //Generic Provisioning Payload |
442 | 14 | { &hf_btmesh_gpp_payload, |
443 | 14 | { "Generic Provisioning Payload", "pbadv.gen_prov.gpp.payload", |
444 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
445 | 14 | NULL, HFILL } |
446 | 14 | }, |
447 | 14 | { &hf_btmesh_gpp_payload_fragment, |
448 | 14 | { "Generic Provisioning Payload Fragment", "pbadv.gen_prov.gpp.payload.fragment", |
449 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
450 | 14 | NULL, HFILL } |
451 | 14 | }, |
452 | | //Generic Provisioning Payload Reassembly |
453 | 14 | { &hf_btmesh_gpp_fragments, |
454 | 14 | { "Reassembled Generic Provisioning Payload Fragments", "pbadv.gen_prov.gpp.fragments", |
455 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, |
456 | 14 | NULL, HFILL } |
457 | 14 | }, |
458 | 14 | { &hf_btmesh_gpp_fragment, |
459 | 14 | { "Generic Provisioning Payload Fragment", "pbadv.gen_prov.gpp.fragment", |
460 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
461 | 14 | NULL, HFILL } |
462 | 14 | }, |
463 | 14 | { &hf_btmesh_gpp_fragment_overlap, |
464 | 14 | { "Fragment overlap", "pbadv.gen_prov.gpp.fragment.overlap", |
465 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
466 | 14 | "Fragment overlaps with other fragments", HFILL } |
467 | 14 | }, |
468 | 14 | { &hf_btmesh_gpp_fragment_overlap_conflict, |
469 | 14 | { "Conflicting data in fragment overlap", "pbadv.gen_prov.gpp.fragment.overlap.conflict", |
470 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
471 | 14 | "Overlapping fragments contained conflicting data", HFILL } |
472 | 14 | }, |
473 | 14 | { &hf_btmesh_gpp_fragment_multiple_tails, |
474 | 14 | { "Multiple tail fragments found", "pbadv.gen_prov.gpp.fragment.multipletails", |
475 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
476 | 14 | "Several tails were found when defragmenting the packet", HFILL } |
477 | 14 | }, |
478 | 14 | { &hf_btmesh_gpp_fragment_too_long_fragment, |
479 | 14 | { "Fragment too long", "pbadv.gen_prov.gpp.fragment.toolongfragment", |
480 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
481 | 14 | "Fragment contained data past end of packet", HFILL } |
482 | 14 | }, |
483 | 14 | { &hf_btmesh_gpp_fragment_error, |
484 | 14 | { "Defragmentation error", "pbadv.gen_prov.gpp.fragment.error", |
485 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
486 | 14 | "Defragmentation error due to illegal fragments", HFILL } |
487 | 14 | }, |
488 | 14 | { &hf_btmesh_gpp_fragment_count, |
489 | 14 | { "Fragment count", "pbadv.gen_prov.gpp.fragment.count", |
490 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
491 | 14 | NULL, HFILL } |
492 | 14 | }, |
493 | 14 | { &hf_btmesh_gpp_reassembled_length, |
494 | 14 | { "Reassembled Generic Provisioning Payload length", "pbadv.gen_prov.gpp.reassembled.length", |
495 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
496 | 14 | "The total length of the reassembled payload", HFILL } |
497 | 14 | }, |
498 | 14 | }; |
499 | | |
500 | 14 | static int *ett[] = { |
501 | 14 | &ett_btmesh_pbadv, |
502 | 14 | &ett_btmesh_generic_provisioning, |
503 | 14 | &ett_btmesh_gpp_fragments, |
504 | 14 | &ett_btmesh_gpp_fragment, |
505 | 14 | }; |
506 | | |
507 | 14 | static ei_register_info ei[] = { |
508 | 14 | { &ei_btmesh_gpcf_unknown_opcode,{ "pbadv.gpcf.unknown_opcode", PI_PROTOCOL, PI_WARN, "Unknown Opcode", EXPFILL } }, |
509 | 14 | { &ei_btmesh_gpcf_unknown_payload,{ "pbadv.gpcf.unknown_payload", PI_PROTOCOL, PI_ERROR, "Unknown Payload", EXPFILL } }, |
510 | 14 | }; |
511 | | |
512 | 14 | expert_module_t* expert_btmesh_pbadv; |
513 | | |
514 | 14 | proto_btmesh_pbadv = proto_register_protocol("Bluetooth Mesh PB-ADV", "BT Mesh PB-ADV", "pbadv"); |
515 | | |
516 | 14 | proto_register_field_array(proto_btmesh_pbadv, hf, array_length(hf)); |
517 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
518 | | |
519 | 14 | expert_btmesh_pbadv = expert_register_protocol(proto_btmesh_pbadv); |
520 | 14 | expert_register_field_array(expert_btmesh_pbadv, ei, array_length(ei)); |
521 | | |
522 | 14 | prefs_register_protocol_subtree("Bluetooth", proto_btmesh_pbadv, NULL); |
523 | 14 | register_dissector("btmesh.pbadv", dissect_btmesh_pbadv_msg, proto_btmesh_pbadv); |
524 | | |
525 | 14 | reassembly_table_register(&pbadv_reassembly_table, &pbadv_reassembly_table_functions); |
526 | 14 | } |
527 | | |
528 | | void |
529 | | proto_reg_handoff_btmesh_pbadv(void) |
530 | 14 | { |
531 | 14 | btmesh_provisioning_handle = find_dissector("btmesh.provisioning"); |
532 | 14 | } |
533 | | |
534 | | /* |
535 | | * Editor modelines |
536 | | * |
537 | | * Local Variables: |
538 | | * c-basic-offset: 4 |
539 | | * tab-width: 8 |
540 | | * indent-tabs-mode: nil |
541 | | * End: |
542 | | * |
543 | | * ex: set shiftwidth=4 tabstop=8 expandtab: |
544 | | * :indentSize=4:tabSize=8:noTabs=true: |
545 | | */ |