xref: /libbtbb/wireshark/plugins-legacy/btle/packet-btle.c (revision e018180df8c9bd1ca869d5329a027253be1a76ec)
1 /* packet-btle.c
2  * Routines for Bluetooth Low Energy dissection
3  * Copyright 2013, Mike Ryan, mikeryan /at/ isecpartners /dot/ com
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <[email protected]>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 
28 #include <wireshark/config.h> /* needed for epan/gcc-4.x */
29 #include <epan/packet.h>
30 #include <epan/prefs.h>
31 
32 /* function prototypes */
33 void proto_reg_handoff_btle(void);
34 
35 /* initialize the protocol and registered fields */
36 static int proto_btle = -1;
37 static int hf_btle_pkthdr = -1;
38 static int hf_btle_aa = -1;
39 static int hf_btle_type = -1;
40 static int hf_btle_randomized_tx = -1;
41 static int hf_btle_randomized_rx = -1;
42 static int hf_btle_length = -1;
43 static int hf_btle_adv_addr = -1;
44 static int hf_btle_adv_data = -1;
45 static int hf_btle_init_addr = -1;
46 static int hf_btle_scan_addr = -1;
47 static int hf_btle_scan_rsp_data = -1;
48 static int hf_btle_connect = -1;
49 static int hf_btle_connect_aa = -1;
50 static int hf_btle_crc_init = -1;
51 static int hf_btle_win_size = -1;
52 static int hf_btle_win_offset = -1;
53 static int hf_btle_interval = -1;
54 static int hf_btle_latency = -1;
55 static int hf_btle_timeout = -1;
56 static int hf_btle_data = -1;
57 static int hf_btle_data_llid = -1;
58 static int hf_btle_data_nesn = -1;
59 static int hf_btle_data_sn = -1;
60 static int hf_btle_data_md = -1;
61 static int hf_btle_data_rfu = -1;
62 static int hf_btle_ll_control_opcode = -1;
63 static int hf_btle_ll_control_data = -1;
64 static int hf_btle_ll_control_ll_enc_req = -1;
65 static int hf_btle_ll_control_ll_enc_req_rand = -1;
66 static int hf_btle_ll_control_ll_enc_req_ediv = -1;
67 static int hf_btle_ll_control_ll_enc_req_skdm = -1;
68 static int hf_btle_ll_control_ll_enc_req_ivm = -1;
69 static int hf_btle_ll_control_ll_enc_rsp = -1;
70 static int hf_btle_ll_control_ll_enc_rsp_skds = -1;
71 static int hf_btle_ll_control_ll_enc_rsp_ivs = -1;
72 static int hf_btle_crc = -1;
73 
74 static const value_string packet_types[] = {
75 	{ 0x0, "ADV_IND" },
76 	{ 0x1, "ADV_DIRECT_IND" },
77 	{ 0x2, "ADV_NONCONN_IND" },
78 	{ 0x3, "SCAN_REQ" },
79 	{ 0x4, "SCAN_RSP" },
80 	{ 0x5, "CONNECT_REQ" },
81 	{ 0x6, "ADV_SCAN_IND" },
82 	{ 0, NULL }
83 };
84 
85 static const value_string llid_codes[] = {
86 	{ 0x0, "undefined" },
87 	{ 0x1, "Continuation fragment of an L2CAP message" },
88 	{ 0x2, "Start of an L2CAP message or no fragmentation" },
89 	{ 0x3, "LL Control PDU" },
90 	{ 0, NULL }
91 };
92 
93 static const value_string ll_control_opcodes[] = {
94 	{ 0x00, "LL_CONNECTION_UPDATE_REQ" },
95 	{ 0x01, "LL_CHANNEL_MAP_REQ" },
96 	{ 0x02, "LL_TERMINATE_IND" },
97 	{ 0x03, "LL_ENC_REQ" },
98 	{ 0x04, "LL_ENC_RSP" },
99 	{ 0x05, "LL_START_ENC_REQ" },
100 	{ 0x06, "LL_START_ENC_RSP" },
101 	{ 0x07, "LL_UNKNOWN_RSP" },
102 	{ 0x08, "LL_FEATURE_REQ" },
103 	{ 0x09, "LL_FEATURE_RSP" },
104 	{ 0x0A, "LL_PAUSE_ENC_REQ" },
105 	{ 0x0B, "LL_PAUSE_ENC_RSP" },
106 	{ 0x0C, "LL_VERSION_IND" },
107 	{ 0x0D, "LL_REJECT_IND" },
108 	{ 0, NULL }
109 };
110 
111 static const guint32 ADV_AA = 0x8e89bed6;
112 
113 /* initialize the subtree pointers */
114 static gint ett_btle = -1;
115 static gint ett_btle_pkthdr = -1;
116 static gint ett_btle_connect = -1;
117 static gint ett_btle_data = -1;
118 static gint ett_ll_enc_req = -1;
119 static gint ett_ll_enc_rsp = -1;
120 
121 /* subdissectors */
122 static dissector_handle_t btl2cap_handle = NULL;
123 
124 void
dissect_adv_ind_or_nonconn_or_scan(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset,int datalen)125 dissect_adv_ind_or_nonconn_or_scan(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int datalen)
126 {
127 	const guint8 *adv_addr;
128 
129 	DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1);
130 
131 	adv_addr = tvb_get_ptr(tvb, offset, 6);
132 	SET_ADDRESS(&pinfo->src, AT_ETHER, 6, adv_addr);
133 
134 	proto_tree_add_ether(tree, hf_btle_adv_addr, tvb, offset, 6, adv_addr);
135 	proto_tree_add_item(tree, hf_btle_adv_data, tvb, offset + 6, datalen, TRUE);
136 }
137 
138 void
dissect_adv_direct_ind(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset)139 dissect_adv_direct_ind(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset)
140 {
141 	const guint8 *adv_addr, *init_addr;
142 
143 	DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1);
144 
145 	adv_addr = tvb_get_ptr(tvb, offset, 6);
146 	SET_ADDRESS(&pinfo->src, AT_ETHER, 6, adv_addr);
147 	init_addr = tvb_get_ptr(tvb, offset+6, 6);
148 	SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, init_addr);
149 
150 	proto_tree_add_ether(tree, hf_btle_adv_addr, tvb, offset, 6, adv_addr);
151 	proto_tree_add_ether(tree, hf_btle_init_addr, tvb, offset + 6, 6, init_addr);
152 }
153 
154 void
dissect_scan_req(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset)155 dissect_scan_req(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset)
156 {
157 	const guint8 *scan_addr, *adv_addr;
158 
159 	DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1);
160 
161 	scan_addr = tvb_get_ptr(tvb, offset, 6);
162 	SET_ADDRESS(&pinfo->src, AT_ETHER, 6, scan_addr);
163 	adv_addr = tvb_get_ptr(tvb, offset+6, 6);
164 	SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, adv_addr);
165 
166 	proto_tree_add_ether(tree, hf_btle_scan_addr, tvb, offset, 6, scan_addr);
167 	proto_tree_add_ether(tree, hf_btle_adv_addr, tvb, offset+6, 6, adv_addr);
168 }
169 
170 void
dissect_scan_rsp(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset,int datalen)171 dissect_scan_rsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int datalen)
172 {
173 	const guint8 *adv_addr;
174 
175 	DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1);
176 
177 	adv_addr = tvb_get_ptr(tvb, offset, 6);
178 	SET_ADDRESS(&pinfo->src, AT_ETHER, 6, adv_addr);
179 
180 	proto_tree_add_ether(tree, hf_btle_adv_addr, tvb, offset, 6, adv_addr);
181 	proto_tree_add_item(tree, hf_btle_scan_rsp_data, tvb, offset + 6, datalen, TRUE);
182 }
183 
184 void
dissect_connect_req(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset)185 dissect_connect_req(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset)
186 {
187 	proto_item *connect_item;
188 	proto_tree *connect_tree;
189 	const guint8 *adv_addr, *init_addr;
190 
191 
192 	DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1);
193 
194 	init_addr = tvb_get_ptr(tvb, offset, 6);
195 	SET_ADDRESS(&pinfo->src, AT_ETHER, 6, init_addr);
196 	adv_addr = tvb_get_ptr(tvb, offset+6, 6);
197 	SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, adv_addr);
198 
199 	proto_tree_add_ether(tree, hf_btle_init_addr, tvb, offset, 6, init_addr);
200 	proto_tree_add_ether(tree, hf_btle_adv_addr, tvb, offset + 6, 6, adv_addr);
201 	offset += 12;
202 
203 	connect_item = proto_tree_add_item(tree, hf_btle_connect, tvb, offset, 22, TRUE);
204 	connect_tree = proto_item_add_subtree(connect_item, ett_btle_connect);
205 
206 	proto_tree_add_item(connect_tree, hf_btle_connect_aa,	tvb, offset+ 0, 4, ENC_LITTLE_ENDIAN);
207 	proto_tree_add_item(connect_tree, hf_btle_crc_init,		tvb, offset+ 4, 3, ENC_LITTLE_ENDIAN);
208 	proto_tree_add_item(connect_tree, hf_btle_win_size,		tvb, offset+ 7, 1, ENC_LITTLE_ENDIAN);
209 	proto_tree_add_item(connect_tree, hf_btle_win_offset,	tvb, offset+ 8, 2, ENC_LITTLE_ENDIAN);
210 	proto_tree_add_item(connect_tree, hf_btle_interval,		tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
211 	proto_tree_add_item(connect_tree, hf_btle_latency,		tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
212 	proto_tree_add_item(connect_tree, hf_btle_timeout,		tvb, offset+14, 2, ENC_LITTLE_ENDIAN);
213 }
214 
215 void
dissect_ll_enc_req(proto_tree * tree,tvbuff_t * tvb,int offset)216 dissect_ll_enc_req(proto_tree *tree, tvbuff_t *tvb, int offset)
217 {
218 	proto_item *ll_enc_req_item;
219 	proto_tree *ll_enc_req_tree;
220 
221 	ll_enc_req_item = proto_tree_add_item(tree, hf_btle_ll_control_ll_enc_req, tvb, offset + 1, 22, TRUE);
222 	ll_enc_req_tree = proto_item_add_subtree(ll_enc_req_item, ett_ll_enc_req);
223 
224 	proto_tree_add_item(ll_enc_req_tree, hf_btle_ll_control_ll_enc_req_rand, tvb, offset + 1,  8, TRUE);
225 	proto_tree_add_item(ll_enc_req_tree, hf_btle_ll_control_ll_enc_req_ediv, tvb, offset + 9,  2, TRUE);
226 	proto_tree_add_item(ll_enc_req_tree, hf_btle_ll_control_ll_enc_req_skdm, tvb, offset + 11, 8, TRUE);
227 	proto_tree_add_item(ll_enc_req_tree, hf_btle_ll_control_ll_enc_req_ivm,  tvb, offset + 19, 4, TRUE);
228 }
229 
230 void
dissect_ll_enc_rsp(proto_tree * tree,tvbuff_t * tvb,int offset)231 dissect_ll_enc_rsp(proto_tree *tree, tvbuff_t *tvb, int offset)
232 {
233 	proto_item *ll_enc_rsp_item;
234 	proto_tree *ll_enc_rsp_tree;
235 
236 	ll_enc_rsp_item = proto_tree_add_item(tree, hf_btle_ll_control_ll_enc_rsp, tvb, offset + 1, 12, TRUE);
237 	ll_enc_rsp_tree = proto_item_add_subtree(ll_enc_rsp_item, ett_ll_enc_rsp);
238 
239 	proto_tree_add_item(ll_enc_rsp_tree, hf_btle_ll_control_ll_enc_rsp_skds, tvb, offset + 1, 8, TRUE);
240 	proto_tree_add_item(ll_enc_rsp_tree, hf_btle_ll_control_ll_enc_rsp_ivs,  tvb, offset + 9, 4, TRUE);
241 }
242 
243 void
dissect_ll_control(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset,guint8 length)244 dissect_ll_control(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, guint8 length)
245 {
246 	guint8 ll_control_opcode;
247 
248 	proto_tree_add_item(tree, hf_btle_ll_control_opcode, tvb, offset, 1, ENC_NA);
249 
250 	ll_control_opcode = tvb_get_guint8(tvb, offset);
251 	if (ll_control_opcode <= 0x0d) {
252 		col_add_fstr(pinfo->cinfo, COL_INFO, "LL Control PDU: %s",
253 				ll_control_opcodes[ll_control_opcode].strptr);
254 
255 		switch (ll_control_opcode) {
256 			case 0x03: // LL_ENC_REQ
257 				dissect_ll_enc_req(tree, tvb, offset);
258 				break;
259 			case 0x04: // LL_ENC_RSP
260 				dissect_ll_enc_rsp(tree, tvb, offset);
261 				break;
262 			default:
263 				if (length > 1)
264 					proto_tree_add_item(tree, hf_btle_ll_control_data, tvb, offset + 1, length-1, TRUE);
265 				break;
266 		}
267 	} else {
268 		col_set_str(pinfo->cinfo, COL_INFO, "LL Control PDU: unknown");
269 		if (length > 1)
270 			proto_tree_add_item(tree, hf_btle_ll_control_data, tvb, offset + 1, length-1, TRUE);
271 	}
272 }
273 
274 /* dissect a packet */
275 static void
dissect_btle(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)276 dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
277 {
278 	proto_item *btle_item, *pkthdr_item, *data_item;
279 	proto_tree *btle_tree, *pkthdr_tree, *data_tree;
280 	int offset;
281 	guint32 aa;
282 	guint8 type, length;
283 	guint8 llid;
284 	tvbuff_t *pld_tvb;
285 
286 	/*
287 	 * FIXME
288 	 * I have no idea what this does, but the L2CAP dissector segfaults
289 	 * without it.
290 	 */
291 	guint16 fake_acl_data;
292 
293 #if 0
294 	/* sanity check: length */
295 	if (tvb_length(tvb) > 0 && tvb_length(tvb) < 9)
296 		/* bad length: look for a different dissector */
297 		return 0;
298 #endif
299 
300 	/* make entries in protocol column and info column on summary display */
301 	if (check_col(pinfo->cinfo, COL_PROTOCOL))
302 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "Bluetooth LE");
303 
304 	aa = tvb_get_letohl(tvb, 0);
305 
306 	// advertising packet
307 	if (aa == ADV_AA) {
308 		type = tvb_get_guint8(tvb, 4) & 0xf;
309 		length = tvb_get_guint8(tvb, 5) & 0x3f;
310 
311 		/* see if we are being asked for details */
312 		if (tree) {
313 
314 			/* create display subtree for the protocol */
315 			offset = 0;
316 			btle_item = proto_tree_add_item(tree, proto_btle, tvb, offset, -1, TRUE);
317 			btle_tree = proto_item_add_subtree(btle_item, ett_btle);
318 
319 			proto_tree_add_item(btle_tree, hf_btle_aa, tvb, offset, 4, TRUE);
320 			offset += 4;
321 
322 			/* packet header */
323 			pkthdr_item = proto_tree_add_item(btle_tree, hf_btle_pkthdr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
324 			pkthdr_tree = proto_item_add_subtree(pkthdr_item, ett_btle_pkthdr);
325 
326 			proto_tree_add_bits_item(pkthdr_tree, hf_btle_randomized_rx, tvb, offset * 8, 1, TRUE);
327 			proto_tree_add_bits_item(pkthdr_tree, hf_btle_randomized_tx, tvb, offset * 8 + 1, 1, TRUE);
328 			proto_tree_add_bits_item(pkthdr_tree, hf_btle_type, tvb, offset * 8 + 4, 4, TRUE);
329 			offset += 1;
330 
331 			proto_tree_add_item(pkthdr_tree, hf_btle_length, tvb, offset, 1, TRUE);
332 			offset += 1;
333 
334 			if (check_col(pinfo->cinfo, COL_INFO)) {
335 				if (type <= 0x6) {
336 					col_set_str(pinfo->cinfo, COL_INFO, packet_types[type].strptr);
337 				} else {
338 					col_set_str(pinfo->cinfo, COL_INFO, "Unknown");
339 				}
340 			}
341 
342 			/* payload */
343 			switch (type) {
344 			case 0x0: // ADV_IND
345 			case 0x2: // ADV_NONCONN_IND
346 			case 0x6: // ADV_SCAN_IND
347 				dissect_adv_ind_or_nonconn_or_scan(btle_tree, tvb, pinfo, offset, length - 6);
348 				break;
349 			case 0x1: // ADV_DIRECT_IND
350 				dissect_adv_direct_ind(btle_tree, tvb, pinfo, offset);
351 				break;
352 			case 0x3:
353 				dissect_scan_req(btle_tree, tvb, pinfo, offset);
354 				break;
355 			case 0x4: // SCAN_RSP
356 				dissect_scan_rsp(btle_tree, tvb, pinfo, offset, length - 6);
357 				break;
358 			case 0x5: // CONNECT_REQ
359 				dissect_connect_req(btle_tree, tvb, pinfo, offset);
360 				break;
361 			default:
362 				break;
363 			}
364 
365 			offset += length;
366 			proto_tree_add_item(btle_tree, hf_btle_crc, tvb, offset, 3, TRUE);
367 		}
368 	}
369 
370 	// data PDU
371 	else {
372 		if (tree) {
373 			col_set_str(pinfo->cinfo, COL_INFO, "Data");
374 
375 			length = tvb_get_guint8(tvb, 5) & 0x1f;
376 
377 			/* create display subtree for the protocol */
378 			offset = 0;
379 			btle_item = proto_tree_add_item(tree, proto_btle, tvb, offset, -1, TRUE);
380 			btle_tree = proto_item_add_subtree(btle_item, ett_btle);
381 
382 			proto_tree_add_item(btle_tree, hf_btle_aa, tvb, offset, 4, TRUE);
383 			offset += 4;
384 
385 			// data PDU header
386 			data_item = proto_tree_add_item(btle_tree, hf_btle_data, tvb, offset, 2, TRUE);
387 			data_tree = proto_item_add_subtree(data_item, ett_btle_data);
388 
389 			proto_tree_add_item(data_tree, hf_btle_data_rfu, tvb, offset, 1, ENC_NA);
390 			proto_tree_add_item(data_tree, hf_btle_data_md, tvb, offset, 1, ENC_NA);
391 			proto_tree_add_item(data_tree, hf_btle_data_sn, tvb, offset, 1, ENC_NA);
392 			proto_tree_add_item(data_tree, hf_btle_data_nesn, tvb, offset, 1, ENC_NA);
393 			proto_tree_add_item(data_tree, hf_btle_data_llid, tvb, offset, 1, ENC_NA);
394 			llid = tvb_get_guint8(tvb, offset) & 0x3;
395 			offset += 1;
396 
397 			proto_tree_add_item(data_tree, hf_btle_length, tvb, offset, 1, TRUE);
398 			offset += 1;
399 
400 			// LL control PDU
401 			if (llid == 0x3) {
402 				dissect_ll_control(btle_tree, tvb, pinfo, offset, length);
403 			}
404 
405 			// L2CAP
406 			else if (llid == 0x1 || llid == 0x2) {
407 				if (length > 0 && btl2cap_handle) {
408 					pinfo->private_data = &fake_acl_data;
409 					pld_tvb = tvb_new_subset(tvb, offset, length, length);
410 					call_dissector(btl2cap_handle, pld_tvb, pinfo, btle_tree);
411 				}
412 				else if (length == 0) {
413 					col_set_str(pinfo->cinfo, COL_INFO, "Empty Data PDU");
414 				}
415 			}
416 
417 			offset += length;
418 
419 			proto_tree_add_item(btle_tree, hf_btle_crc, tvb, offset, 3, TRUE);
420 		}
421 	}
422 
423 	return;
424 }
425 
426 /* register the protocol with Wireshark */
427 void
proto_register_btle(void)428 proto_register_btle(void)
429 {
430 
431 	/* list of fields */
432 	static hf_register_info hf[] = {
433 		{ &hf_btle_aa,
434 			{ "Access Address", "btle.aa",
435 			FT_UINT32, BASE_HEX, NULL, 0x0,
436 			NULL, HFILL }
437 		},
438 
439 		{ &hf_btle_pkthdr,
440 			{ "Packet Header", "btle.pkthdr",
441 			FT_NONE, BASE_NONE, NULL, 0x0,
442 			NULL, HFILL }
443 		},
444 
445 		{ &hf_btle_type,
446 			{ "TYPE", "btle.type",
447 			FT_UINT8, BASE_HEX, VALS(packet_types), 0x0,
448 			"Packet Type", HFILL }
449 		},
450 		{ &hf_btle_randomized_tx,
451 			{ "Randomized TX Address", "btle.randomized_tx",
452 			FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
453 			NULL, HFILL }
454 		},
455 		{ &hf_btle_randomized_rx,
456 			{ "Randomized RX Address", "btle.randomized_rx",
457 			FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
458 			NULL, HFILL }
459 		},
460 		{ &hf_btle_length,
461 			{ "Length", "btle.length",
462 			FT_UINT8, BASE_DEC, NULL, 0x0,
463 			NULL, HFILL }
464 		},
465 		{ &hf_btle_adv_addr,
466 			{ "Advertising Address", "btle.adv_addr",
467 			FT_ETHER, BASE_NONE, NULL, 0x0,
468 			NULL, HFILL }
469 		},
470 		{ &hf_btle_init_addr,
471 			{ "Init Address", "btle.init_addr",
472 			FT_ETHER, BASE_NONE, NULL, 0x0,
473 			NULL, HFILL }
474 		},
475 		{ &hf_btle_scan_addr,
476 			{ "Scan Address", "btle.scan_addr",
477 			FT_ETHER, BASE_NONE, NULL, 0x0,
478 			NULL, HFILL }
479 		},
480 		{ &hf_btle_adv_data,
481 			{ "Advertising Data", "btle.adv_data",
482 			FT_BYTES, BASE_NONE, NULL, 0x0,
483 			NULL, HFILL }
484 		},
485 		{ &hf_btle_scan_rsp_data,
486 			{ "Scan Response Data", "btle.scan_rsp_data",
487 			FT_BYTES, BASE_NONE, NULL, 0x0,
488 			NULL, HFILL }
489 		},
490 
491 		// connection packet fields
492 		{ &hf_btle_connect,
493 			{ "Connection Request", "btle.connect",
494 			FT_NONE, BASE_NONE, NULL, 0x0,
495 			NULL, HFILL }
496 		},
497 		{ &hf_btle_connect_aa,
498 			{ "Connection AA", "btle.connect.aa",
499 			FT_UINT32, BASE_HEX, NULL, 0x0,
500 			NULL, HFILL }
501 		},
502 		{ &hf_btle_crc_init,
503 			{ "CRC Init", "btle.connect.crc_init",
504 			FT_UINT24, BASE_HEX, NULL, 0x0,
505 			NULL, HFILL }
506 		},
507 		{ &hf_btle_win_size,
508 			{ "Window Size", "btle.connect.win_size",
509 			FT_UINT8, BASE_HEX, NULL, 0x0,
510 			NULL, HFILL }
511 		},
512 		{ &hf_btle_win_offset,
513 			{ "Window Offset", "btle.connect.win_offset",
514 			FT_UINT16, BASE_HEX, NULL, 0x0,
515 			NULL, HFILL }
516 		},
517 		{ &hf_btle_interval,
518 			{ "Interval", "btle.connect.interval",
519 			FT_UINT16, BASE_HEX, NULL, 0x0,
520 			NULL, HFILL }
521 		},
522 		{ &hf_btle_latency,
523 			{ "Latency", "btle.connect.latency",
524 			FT_UINT16, BASE_HEX, NULL, 0x0,
525 			NULL, HFILL }
526 		},
527 		{ &hf_btle_timeout,
528 			{ "Timeout", "btle.connect.timeout",
529 			FT_UINT16, BASE_HEX, NULL, 0x0,
530 			NULL, HFILL }
531 		},
532 
533 		// data header
534 		{ &hf_btle_data,
535 			{ "Data PDU Header", "btle.data",
536 			FT_UINT16, BASE_HEX, NULL, 0x0,
537 			NULL, HFILL }
538 		},
539 		{ &hf_btle_data_llid,
540 			{ "LLID", "btle.data.llid",
541 			FT_UINT8, BASE_DEC, VALS(llid_codes), 0x3,
542 			NULL, HFILL }
543 		},
544 		{ &hf_btle_data_nesn,
545 			{ "NESN", "btle.data.nesn",
546 			FT_UINT8, BASE_DEC, NULL, 0x4,
547 			"Next Expected Sequence Number", HFILL }
548 		},
549 		{ &hf_btle_data_sn,
550 			{ "SN", "btle.data.sn",
551 			FT_UINT8, BASE_DEC, NULL, 0x8,
552 			"Sequence Number", HFILL }
553 		},
554 		{ &hf_btle_data_md,
555 			{ "MD", "btle.data.md",
556 			FT_UINT8, BASE_DEC, NULL, 0x10,
557 			"More Data", HFILL }
558 		},
559 		{ &hf_btle_data_rfu,
560 			{ "RFU", "btle.data.rfu",
561 			FT_UINT8, BASE_DEC, NULL, 0xe0,
562 			"Reserved for Future Use (must be zero)", HFILL }
563 		},
564 
565 		{ &hf_btle_ll_control_opcode,
566 			{ "LL Control Opcode", "btle.ll_control_opcode",
567 			FT_UINT8, BASE_HEX, VALS(ll_control_opcodes), 0x0,
568 			NULL, HFILL }
569 		},
570 		{ &hf_btle_ll_control_data,
571 			{ "LL Control Data", "btle.ll_control_data",
572 			FT_BYTES, BASE_NONE, NULL, 0x0,
573 			NULL, HFILL }
574 		},
575 
576 		{ &hf_btle_ll_control_ll_enc_req,
577 			{ "Encryption Request", "btle.ll_enc_req",
578 			FT_NONE, BASE_NONE, NULL, 0x0,
579 			NULL, HFILL }
580 		},
581 		{ &hf_btle_ll_control_ll_enc_req_rand,
582 			{ "Rand", "btle.ll_enc_req.rand",
583 			FT_BYTES, BASE_NONE, NULL, 0x0,
584 			NULL, HFILL }
585 		},
586 		{ &hf_btle_ll_control_ll_enc_req_ediv,
587 			{ "EDIV", "btle.ll_enc_req.ediv",
588 			FT_BYTES, BASE_NONE, NULL, 0x0,
589 			"Encrypted Diversifier", HFILL }
590 		},
591 		{ &hf_btle_ll_control_ll_enc_req_skdm,
592 			{ "SDKm", "btle.ll_enc_req.skdm",
593 			FT_BYTES, BASE_NONE, NULL, 0x0,
594 			"Master's Session Key Identifier", HFILL }
595 		},
596 		{ &hf_btle_ll_control_ll_enc_req_ivm,
597 			{ "IVm", "btle.ll_enc_req.ivm",
598 			FT_BYTES, BASE_NONE, NULL, 0x0,
599 			"Master's Initialization Vector", HFILL }
600 		},
601 
602 		{ &hf_btle_ll_control_ll_enc_rsp,
603 			{ "Encryption Response", "btle.ll_enc_rsp",
604 			FT_NONE, BASE_NONE, NULL, 0x0,
605 			NULL, HFILL }
606 		},
607 		{ &hf_btle_ll_control_ll_enc_rsp_skds,
608 			{ "SDKs", "btle.ll_enc_rsp.skds",
609 			FT_BYTES, BASE_NONE, NULL, 0x0,
610 			"Slave's Session Key Identifier", HFILL }
611 		},
612 		{ &hf_btle_ll_control_ll_enc_rsp_ivs,
613 			{ "IVs", "btle.ll_enc_rsp.ivs",
614 			FT_BYTES, BASE_NONE, NULL, 0x0,
615 			"Slave's Initialization Vector", HFILL }
616 		},
617 
618 
619 		{ &hf_btle_crc,
620 			{ "CRC", "btle.crc",
621 			FT_UINT24, BASE_HEX, NULL, 0x0,
622 			"Ticklish Redundancy Check", HFILL }
623 		},
624 	};
625 
626 	/* protocol subtree arrays */
627 	static gint *ett[] = {
628 		&ett_btle,
629 		&ett_btle_pkthdr,
630 		&ett_btle_connect,
631 		&ett_btle_data,
632 		&ett_ll_enc_req,
633 		&ett_ll_enc_rsp,
634 	};
635 
636 	/* register the protocol name and description */
637 	proto_btle = proto_register_protocol(
638 		"Bluetooth Low Energy",	/* full name */
639 		"BTLE",			/* short name */
640 		"btle"			/* abbreviation (e.g. for filters) */
641 		);
642 
643 	register_dissector("btle", dissect_btle, proto_btle);
644 
645 	/* register the header fields and subtrees used */
646 	proto_register_field_array(proto_btle, hf, array_length(hf));
647 	proto_register_subtree_array(ett, array_length(ett));
648 }
649 
650 void
proto_reg_handoff_btle(void)651 proto_reg_handoff_btle(void)
652 {
653 	static gboolean inited = FALSE;
654 
655 	if (!inited) {
656 		dissector_handle_t btle_handle;
657 
658 		// btle_handle = new_create_dissector_handle(dissect_btle, proto_btle);
659 		// dissector_add("ppi.dlt", 147, btle_handle);
660 
661 		btl2cap_handle = find_dissector("btl2cap");
662 
663 		inited = TRUE;
664 	}
665 }
666