1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Philippe Biondi <phil@secdev.org>
5# Copyright (C) Mike Ryan <mikeryan@lacklustre.net>
6# Copyright (C) Michael Farrell <micolous+git@gmail.com>
7# Copyright (C) Haram Park <freehr94@korea.ac.kr>
8
9"""
10Bluetooth layers, sockets and send/receive functions.
11"""
12
13import ctypes
14import functools
15import socket
16import struct
17import select
18from ctypes import sizeof
19
20from scapy.config import conf
21from scapy.data import (
22 DLT_BLUETOOTH_HCI_H4,
23 DLT_BLUETOOTH_HCI_H4_WITH_PHDR,
24 DLT_BLUETOOTH_LINUX_MONITOR,
25 BLUETOOTH_CORE_COMPANY_IDENTIFIERS
26)
27from scapy.packet import bind_layers, Packet
28from scapy.fields import (
29 BitField,
30 XBitField,
31 ByteEnumField,
32 ByteField,
33 FieldLenField,
34 FieldListField,
35 FlagsField,
36 IntField,
37 LEShortEnumField,
38 LEShortField,
39 LEIntField,
40 LenField,
41 MultipleTypeField,
42 NBytesField,
43 PacketListField,
44 PadField,
45 ShortField,
46 SignedByteField,
47 StrField,
48 StrFixedLenField,
49 StrLenField,
50 StrNullField,
51 UUIDField,
52 XByteField,
53 XLE3BytesField,
54 XLELongField,
55 XStrLenField,
56 XLEShortField,
57 XLEIntField,
58 LEMACField,
59 BitEnumField,
60 LEThreeBytesField,
61)
62from scapy.supersocket import SuperSocket
63from scapy.sendrecv import sndrcv
64from scapy.data import MTU
65from scapy.consts import WINDOWS
66from scapy.error import warning
67
68
69############
70# Consts #
71############
72
73# From hci.h
74HCI_CHANNEL_RAW = 0
75HCI_CHANNEL_USER = 1
76HCI_CHANNEL_MONITOR = 2
77HCI_CHANNEL_CONTROL = 3
78HCI_CHANNEL_LOGGING = 4
79
80HCI_DEV_NONE = 0xffff
81
82
83##########
84# Layers #
85##########
86
87# See bluez/lib/hci.h for details
88
89# Transport layers
90
91class HCI_PHDR_Hdr(Packet):
92 name = "HCI PHDR transport layer"
93 fields_desc = [IntField("direction", 0)]
94
95
96# Real layers
97
98_bluetooth_packet_types = {
99 0: "Acknowledgement",
100 1: "Command",
101 2: "ACL Data",
102 3: "Synchronous",
103 4: "Event",
104 5: "Reserve",
105 14: "Vendor",
106 15: "Link Control"
107}
108
109_bluetooth_error_codes = {
110 0x00: "Success",
111 0x01: "Unknown HCI Command",
112 0x02: "Unknown Connection Identifier",
113 0x03: "Hardware Failure",
114 0x04: "Page Timeout",
115 0x05: "Authentication Failure",
116 0x06: "PIN or Key Missing",
117 0x07: "Memory Capacity Exceeded",
118 0x08: "Connection Timeout",
119 0x09: "Connection Limit Exceeded",
120 0x0A: "Synchronous Connection Limit To A Device Exceeded",
121 0x0B: "Connection Already Exists",
122 0x0C: "Command Disallowed",
123 0x0D: "Connection Rejected due to Limited Resources",
124 0x0E: "Connection Rejected Due To Security Reasons",
125 0x0F: "Connection Rejected due to Unacceptable BD_ADDR",
126 0x10: "Connection Accept Timeout Exceeded",
127 0x11: "Unsupported Feature or Parameter Value",
128 0x12: "Invalid HCI Command Parameters",
129 0x13: "Remote User Terminated Connection",
130 0x14: "Remote Device Terminated Connection due to Low Resources",
131 0x15: "Remote Device Terminated Connection due to Power Off",
132 0x16: "Connection Terminated By Local Host",
133 0x17: "Repeated Attempts",
134 0x18: "Pairing Not Allowed",
135 0x19: "Unknown LMP PDU",
136 0x1A: "Unsupported Remote Feature / Unsupported LMP Feature",
137 0x1B: "SCO Offset Rejected",
138 0x1C: "SCO Interval Rejected",
139 0x1D: "SCO Air Mode Rejected",
140 0x1E: "Invalid LMP Parameters / Invalid LL Parameters",
141 0x1F: "Unspecified Error",
142 0x20: "Unsupported LMP Parameter Value / Unsupported LL Parameter Value",
143 0x21: "Role Change Not Allowed",
144 0x22: "LMP Response Timeout / LL Response Timeout",
145 0x23: "LMP Error Transaction Collision / LL Procedure Collision",
146 0x24: "LMP PDU Not Allowed",
147 0x25: "Encryption Mode Not Acceptable",
148 0x26: "Link Key cannot be Changed",
149 0x27: "Requested QoS Not Supported",
150 0x28: "Instant Passed",
151 0x29: "Pairing With Unit Key Not Supported",
152 0x2A: "Different Transaction Collision",
153 0x2B: "Reserved for future use",
154 0x2C: "QoS Unacceptable Parameter",
155 0x2D: "QoS Rejected",
156 0x2E: "Channel Classification Not Supported",
157 0x2F: "Insufficient Security",
158 0x30: "Parameter Out Of Mandatory Range",
159 0x31: "Reserved for future use",
160 0x32: "Role Switch Pending",
161 0x33: "Reserved for future use",
162 0x34: "Reserved Slot Violation",
163 0x35: "Role Switch Failed",
164 0x36: "Extended Inquiry Response Too Large",
165 0x37: "Secure Simple Pairing Not Supported By Host",
166 0x38: "Host Busy - Pairing",
167 0x39: "Connection Rejected due to No Suitable Channel Found",
168 0x3A: "Controller Busy",
169 0x3B: "Unacceptable Connection Parameters",
170 0x3C: "Advertising Timeout",
171 0x3D: "Connection Terminated due to MIC Failure",
172 0x3E: "Connection Failed to be Established / Synchronization Timeout",
173 0x3F: "MAC Connection Failed",
174 0x40: "Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock"
175 " Dragging",
176 0x41: "Type0 Submap Not Defined",
177 0x42: "Unknown Advertising Identifier",
178 0x43: "Limit Reached",
179 0x44: "Operation Cancelled by Host",
180 0x45: "Packet Too Long"
181}
182
183_att_error_codes = {
184 0x01: "invalid handle",
185 0x02: "read not permitted",
186 0x03: "write not permitted",
187 0x04: "invalid pdu",
188 0x05: "insufficient auth",
189 0x06: "unsupported req",
190 0x07: "invalid offset",
191 0x08: "insufficient author",
192 0x09: "prepare queue full",
193 0x0a: "attr not found",
194 0x0b: "attr not long",
195 0x0c: "insufficient key size",
196 0x0d: "invalid value size",
197 0x0e: "unlikely",
198 0x0f: "insufficiet encrypt",
199 0x10: "unsupported gpr type",
200 0x11: "insufficient resources",
201}
202
203_bluetooth_features = [
204 '3_slot_packets',
205 '5_slot_packets',
206 'encryption',
207 'slot_offset',
208 'timing_accuracy',
209 'role_switch',
210 'hold_mode',
211 'sniff_mode',
212 'park_mode',
213 'power_control_requests',
214 'channel_quality_driven_data_rate',
215 'sco_link',
216 'hv2_packets',
217 'hv3_packets',
218 'u_law_log_synchronous_data',
219 'a_law_log_synchronous_data',
220 'cvsd_synchronous_data',
221 'paging_parameter_negotiation',
222 'power_control',
223 'transparent_synchronous_data',
224 'flow_control_lag_4_bit0',
225 'flow_control_lag_4_bit1',
226 'flow_control_lag_4_bit2',
227 'broadband_encryption',
228 'cvsd_synchronous_data',
229 'edr_acl_2_mbps_mode',
230 'edr_acl_3_mbps_mode',
231 'enhanced_inquiry_scan',
232 'interlaced_inquiry_scan',
233 'interlaced_page_scan',
234 'rssi_with_inquiry_results',
235 'ev3_packets',
236 'ev4_packets',
237 'ev5_packets',
238 'reserved',
239 'afh_capable_slave',
240 'afh_classification_slave',
241 'br_edr_not_supported',
242 'le_supported_controller',
243 '3_slot_edr_acl_packets',
244 '5_slot_edr_acl_packets',
245 'sniff_subrating',
246 'pause_encryption',
247 'afh_capable_master',
248 'afh_classification_master',
249 'edr_esco_2_mbps_mode',
250 'edr_esco_3_mbps_mode',
251 '3_slot_edr_esco_packets',
252 'extended_inquiry_response',
253 'simultaneous_le_and_br_edr_to_same_device_capable_controller',
254 'reserved2',
255 'secure_simple_pairing',
256 'encapsulated_pdu',
257 'erroneous_data_reporting',
258 'non_flushable_packet_boundary_flag',
259 'reserved3',
260 'link_supervision_timeout_changed_event',
261 'inquiry_tx_power_level',
262 'enhanced_power_control',
263 'reserved4_bit0',
264 'reserved4_bit1',
265 'reserved4_bit2',
266 'reserved4_bit3',
267 'extended_features',
268]
269
270_bluetooth_core_specification_versions = {
271 0x00: '1.0b',
272 0x01: '1.1',
273 0x02: '1.2',
274 0x03: '2.0+EDR',
275 0x04: '2.1+EDR',
276 0x05: '3.0+HS',
277 0x06: '4.0',
278 0x07: '4.1',
279 0x08: '4.2',
280 0x09: '5.0',
281 0x0a: '5.1',
282 0x0b: '5.2',
283 0x0c: '5.3',
284 0x0d: '5.4',
285 0x0e: '6.0',
286}
287
288
289class HCI_Hdr(Packet):
290 name = "HCI header"
291 fields_desc = [ByteEnumField("type", 2, _bluetooth_packet_types)]
292
293 def mysummary(self):
294 return self.sprintf("HCI %type%")
295
296
297class HCI_ACL_Hdr(Packet):
298 name = "HCI ACL header"
299 fields_desc = [BitField("BC", 0, 2, tot_size=-2),
300 BitField("PB", 0, 2),
301 BitField("handle", 0, 12, end_tot_size=-2),
302 LEShortField("len", None), ]
303
304 def post_build(self, p, pay):
305 p += pay
306 if self.len is None:
307 p = p[:2] + struct.pack("<H", len(pay)) + p[4:]
308 return p
309
310
311class L2CAP_Hdr(Packet):
312 name = "L2CAP header"
313 fields_desc = [LEShortField("len", None),
314 LEShortEnumField("cid", 0, {1: "control", 4: "attribute"}), ] # noqa: E501
315
316 def post_build(self, p, pay):
317 p += pay
318 if self.len is None:
319 p = struct.pack("<H", len(pay)) + p[2:]
320 return p
321
322
323class L2CAP_CmdHdr(Packet):
324 name = "L2CAP command header"
325 fields_desc = [
326 ByteEnumField("code", 8, {1: "rej",
327 2: "conn_req",
328 3: "conn_resp",
329 4: "conf_req",
330 5: "conf_resp",
331 6: "disconn_req",
332 7: "disconn_resp",
333 8: "echo_req",
334 9: "echo_resp",
335 10: "info_req",
336 11: "info_resp",
337 12: "create_channel_req",
338 13: "create_channel_resp",
339 14: "move_channel_req",
340 15: "move_channel_resp",
341 16: "move_channel_confirm_req",
342 17: "move_channel_confirm_resp",
343 18: "conn_param_update_req",
344 19: "conn_param_update_resp",
345 20: "LE_credit_based_conn_req",
346 21: "LE_credit_based_conn_resp",
347 22: "flow_control_credit_ind",
348 23: "credit_based_conn_req",
349 24: "credit_based_conn_resp",
350 25: "credit_based_reconf_req",
351 26: "credit_based_reconf_resp"}),
352 ByteField("id", 1),
353 LEShortField("len", None)]
354
355 def post_build(self, p, pay):
356 p += pay
357 if self.len is None:
358 p = p[:2] + struct.pack("<H", len(pay)) + p[4:]
359 return p
360
361 def answers(self, other):
362 if other.id == self.id:
363 if self.code == 1:
364 return 1
365 if other.code in [2, 4, 6, 8, 10, 18] and self.code == other.code + 1: # noqa: E501
366 if other.code == 8:
367 return 1
368 return self.payload.answers(other.payload)
369 return 0
370
371
372class L2CAP_ConnReq(Packet):
373 name = "L2CAP Conn Req"
374 fields_desc = [LEShortEnumField("psm", 0, {1: "SDP",
375 3: "RFCOMM",
376 5: "TCS-BIN",
377 7: "TCS-BIN-CORDLESS",
378 15: "BNEP",
379 17: "HID-Control",
380 19: "HID-Interrupt",
381 21: "UPnP",
382 23: "AVCTP-Control",
383 25: "AVDTP",
384 27: "AVCTP-Browsing",
385 29: "UDI_C-Plane",
386 31: "ATT",
387 33: "3DSP",
388 35: "IPSP",
389 37: "OTS"}),
390 LEShortField("scid", 0),
391 ]
392
393
394class L2CAP_ConnResp(Packet):
395 name = "L2CAP Conn Resp"
396 fields_desc = [LEShortField("dcid", 0),
397 LEShortField("scid", 0),
398 LEShortEnumField("result", 0, ["success", "pend", "cr_bad_psm", "cr_sec_block", "cr_no_mem", "reserved", "cr_inval_scid", "cr_scid_in_use"]), # noqa: E501
399 LEShortEnumField("status", 0, ["no_info", "authen_pend", "author_pend", "reserved"]), # noqa: E501
400 ]
401
402 def answers(self, other):
403 # dcid Resp == scid Req. Therefore compare SCIDs
404 return isinstance(other, L2CAP_ConnReq) and self.scid == other.scid
405
406
407class L2CAP_CmdRej(Packet):
408 name = "L2CAP Command Rej"
409 fields_desc = [LEShortField("reason", 0),
410 ]
411
412
413class L2CAP_ConfReq(Packet):
414 name = "L2CAP Conf Req"
415 fields_desc = [LEShortField("dcid", 0),
416 LEShortField("flags", 0),
417 ]
418
419
420class L2CAP_ConfResp(Packet):
421 name = "L2CAP Conf Resp"
422 fields_desc = [LEShortField("scid", 0),
423 LEShortField("flags", 0),
424 LEShortEnumField("result", 0, ["success", "unaccept", "reject", "unknown"]), # noqa: E501
425 ]
426
427 def answers(self, other):
428 # Req and Resp contain either the SCID or the DCID.
429 return isinstance(other, L2CAP_ConfReq)
430
431
432class L2CAP_DisconnReq(Packet):
433 name = "L2CAP Disconn Req"
434 fields_desc = [LEShortField("dcid", 0),
435 LEShortField("scid", 0), ]
436
437
438class L2CAP_DisconnResp(Packet):
439 name = "L2CAP Disconn Resp"
440 fields_desc = [LEShortField("dcid", 0),
441 LEShortField("scid", 0), ]
442
443 def answers(self, other):
444 return self.scid == other.scid
445
446
447class L2CAP_EchoReq(Packet):
448 name = "L2CAP Echo Req"
449 fields_desc = [StrField("data", ""), ]
450
451
452class L2CAP_EchoResp(Packet):
453 name = "L2CAP Echo Resp"
454 fields_desc = [StrField("data", ""), ]
455
456
457class L2CAP_InfoReq(Packet):
458 name = "L2CAP Info Req"
459 fields_desc = [LEShortEnumField("type", 0, {1: "CL_MTU", 2: "FEAT_MASK"}),
460 StrField("data", "")
461 ]
462
463
464class L2CAP_InfoResp(Packet):
465 name = "L2CAP Info Resp"
466 fields_desc = [LEShortField("type", 0),
467 LEShortEnumField("result", 0, ["success", "not_supp"]),
468 StrField("data", ""), ]
469
470 def answers(self, other):
471 return self.type == other.type
472
473
474class L2CAP_Create_Channel_Request(Packet):
475 name = "L2CAP Create Channel Request"
476 fields_desc = [LEShortEnumField("psm", 0, {1: "SDP",
477 3: "RFCOMM",
478 5: "TCS-BIN",
479 7: "TCS-BIN-CORDLESS",
480 15: "BNEP",
481 17: "HID-Control",
482 19: "HID-Interrupt",
483 21: "UPnP",
484 23: "AVCTP-Control",
485 25: "AVDTP",
486 27: "AVCTP-Browsing",
487 29: "UDI_C-Plane",
488 31: "ATT",
489 33: "3DSP",
490 35: "IPSP",
491 37: "OTS"}),
492 LEShortField("scid", 0),
493 ByteField("controller_id", 0), ]
494
495
496class L2CAP_Create_Channel_Response(Packet):
497 name = "L2CAP Create Channel Response"
498 fields_desc = [LEShortField("dcid", 0),
499 LEShortField("scid", 0),
500 LEShortEnumField("result", 0, {
501 0: "Connection successful",
502 1: "Connection pending",
503 2: "Connection refused - PSM not supported",
504 3: "Connection refused - security block",
505 4: "Connection refused - no resources available",
506 5: "Connection refused - cont_ID not supported",
507 6: "Connection refused - invalid scid",
508 7: "Connection refused - scid already allocated"}),
509 LEShortEnumField("status", 0, {
510 0: "No further information available",
511 1: "Authentication pending",
512 2: "Authorization pending"}), ]
513
514
515class L2CAP_Move_Channel_Request(Packet):
516 name = "L2CAP Move Channel Request"
517 fields_desc = [LEShortField("icid", 0),
518 ByteField("dest_controller_id", 0), ]
519
520
521class L2CAP_Move_Channel_Response(Packet):
522 name = "L2CAP Move Channel Response"
523 fields_desc = [LEShortField("icid", 0),
524 LEShortEnumField("result", 0, {
525 0: "Move success",
526 1: "Move pending",
527 2: "Move refused - Cont_ID not supported",
528 3: "Move refused - Cont_ID is same as old one",
529 4: "Move refused - Configuration not supported",
530 5: "Move refused - Move channel collision",
531 6: "Move refused - Not allowed to be moved"}), ]
532
533
534class L2CAP_Move_Channel_Confirmation_Request(Packet):
535 name = "L2CAP Move Channel Confirmation Request"
536 fields_desc = [LEShortField("icid", 0),
537 LEShortEnumField("result", 0, {0: "Move success",
538 1: "Move failure"}), ]
539
540
541class L2CAP_Move_Channel_Confirmation_Response(Packet):
542 name = "L2CAP Move Channel Confirmation Response"
543 fields_desc = [LEShortField("icid", 0), ]
544
545
546class L2CAP_Connection_Parameter_Update_Request(Packet):
547 name = "L2CAP Connection Parameter Update Request"
548 fields_desc = [LEShortField("min_interval", 0),
549 LEShortField("max_interval", 0),
550 LEShortField("slave_latency", 0),
551 LEShortField("timeout_mult", 0), ]
552
553
554class L2CAP_Connection_Parameter_Update_Response(Packet):
555 name = "L2CAP Connection Parameter Update Response"
556 fields_desc = [LEShortField("move_result", 0), ]
557
558
559class L2CAP_LE_Credit_Based_Connection_Request(Packet):
560 name = "L2CAP LE Credit Based Connection Request"
561 fields_desc = [LEShortField("spsm", 0),
562 LEShortField("scid", 0),
563 LEShortField("mtu", 0),
564 LEShortField("mps", 0),
565 LEShortField("initial_credits", 0), ]
566
567
568class L2CAP_LE_Credit_Based_Connection_Response(Packet):
569 name = "L2CAP LE Credit Based Connection Response"
570 fields_desc = [LEShortField("dcid", 0),
571 LEShortField("mtu", 0),
572 LEShortField("mps", 0),
573 LEShortField("initial_credits", 0),
574 LEShortEnumField("result", 0, {
575 0: "Connection successful",
576 2: "Connection refused - SPSM not supported",
577 4: "Connection refused - no resources available",
578 5: "Connection refused - authentication error",
579 6: "Connection refused - authorization error",
580 7: "Connection refused - encrypt_key size error",
581 8: "Connection refused - insufficient encryption",
582 9: "Connection refused - invalid scid",
583 10: "Connection refused - scid already allocated",
584 11: "Connection refused - parameters error"}), ]
585
586
587class L2CAP_Flow_Control_Credit_Ind(Packet):
588 name = "L2CAP Flow Control Credit Ind"
589 fields_desc = [LEShortField("cid", 0),
590 LEShortField("credits", 0), ]
591
592
593class L2CAP_Credit_Based_Connection_Request(Packet):
594 name = "L2CAP Credit Based Connection Request"
595 fields_desc = [LEShortField("spsm", 0),
596 LEShortField("mtu", 0),
597 LEShortField("mps", 0),
598 LEShortField("initial_credits", 0),
599 LEShortField("scid", 0), ]
600
601
602class L2CAP_Credit_Based_Connection_Response(Packet):
603 name = "L2CAP Credit Based Connection Response"
604 fields_desc = [LEShortField("mtu", 0),
605 LEShortField("mps", 0),
606 LEShortField("initial_credits", 0),
607 LEShortEnumField("result", 0, {
608 0: "All connection successful",
609 2: "All connection refused - SPSM not supported",
610 4: "Some connections refused - resources error",
611 5: "All connection refused - authentication error",
612 6: "All connection refused - authorization error",
613 7: "All connection refused - encrypt_key size error",
614 8: "All connection refused - encryption error",
615 9: "Some connection refused - invalid scid",
616 10: "Some connection refused - scid already allocated",
617 11: "All Connection refused - unacceptable parameters",
618 12: "All connections refused - invalid parameters"}),
619 LEShortField("dcid", 0), ]
620
621
622class L2CAP_Credit_Based_Reconfigure_Request(Packet):
623 name = "L2CAP Credit Based Reconfigure Request"
624 fields_desc = [LEShortField("mtu", 0),
625 LEShortField("mps", 0),
626 LEShortField("dcid", 0), ]
627
628
629class L2CAP_Credit_Based_Reconfigure_Response(Packet):
630 name = "L2CAP Credit Based Reconfigure Response"
631 fields_desc = [LEShortEnumField("result", 0, {
632 0: "Reconfig successful",
633 1: "Reconfig failed - MTU size reduction not allowed",
634 2: "Reconfig failed - MPS size reduction not allowed",
635 3: "Reconfig failed - one or more dcids invalid",
636 4: "Reconfig failed - unacceptable parameters"}), ]
637
638
639class ATT_Hdr(Packet):
640 name = "ATT header"
641 fields_desc = [XByteField("opcode", None), ]
642
643
644class ATT_Handle(Packet):
645 name = "ATT Short Handle"
646 fields_desc = [XLEShortField("handle", 0),
647 XLEShortField("value", 0)]
648
649 def extract_padding(self, s):
650 return b'', s
651
652
653class ATT_Handle_UUID128(Packet):
654 name = "ATT Handle (UUID 128)"
655 fields_desc = [XLEShortField("handle", 0),
656 UUIDField("value", None, uuid_fmt=UUIDField.FORMAT_REV)]
657
658 def extract_padding(self, s):
659 return b'', s
660
661
662class ATT_Error_Response(Packet):
663 name = "Error Response"
664 fields_desc = [XByteField("request", 0),
665 LEShortField("handle", 0),
666 ByteEnumField("ecode", 0, _att_error_codes), ]
667
668
669class ATT_Exchange_MTU_Request(Packet):
670 name = "Exchange MTU Request"
671 fields_desc = [LEShortField("mtu", 0), ]
672
673
674class ATT_Exchange_MTU_Response(Packet):
675 name = "Exchange MTU Response"
676 fields_desc = [LEShortField("mtu", 0), ]
677
678
679class ATT_Find_Information_Request(Packet):
680 name = "Find Information Request"
681 fields_desc = [XLEShortField("start", 0x0000),
682 XLEShortField("end", 0xffff), ]
683
684
685class ATT_Find_Information_Response(Packet):
686 name = "Find Information Response"
687 fields_desc = [
688 XByteField("format", 1),
689 MultipleTypeField(
690 [
691 (PacketListField("handles", [], ATT_Handle),
692 lambda pkt: pkt.format == 1),
693 (PacketListField("handles", [], ATT_Handle_UUID128),
694 lambda pkt: pkt.format == 2),
695 ],
696 StrFixedLenField("handles", "", length=0)
697 )
698 ]
699
700
701class ATT_Find_By_Type_Value_Request(Packet):
702 name = "Find By Type Value Request"
703 fields_desc = [XLEShortField("start", 0x0001),
704 XLEShortField("end", 0xffff),
705 XLEShortField("uuid", None),
706 StrField("data", ""), ]
707
708
709class ATT_Find_By_Type_Value_Response(Packet):
710 name = "Find By Type Value Response"
711 fields_desc = [PacketListField("handles", [], ATT_Handle)]
712
713
714class ATT_Read_By_Type_Request_128bit(Packet):
715 name = "Read By Type Request"
716 fields_desc = [XLEShortField("start", 0x0001),
717 XLEShortField("end", 0xffff),
718 XLELongField("uuid1", None),
719 XLELongField("uuid2", None)]
720
721 @classmethod
722 def dispatch_hook(cls, _pkt=None, *args, **kargs):
723 if _pkt and len(_pkt) == 6:
724 return ATT_Read_By_Type_Request
725 return ATT_Read_By_Type_Request_128bit
726
727
728class ATT_Read_By_Type_Request(Packet):
729 name = "Read By Type Request"
730 fields_desc = [XLEShortField("start", 0x0001),
731 XLEShortField("end", 0xffff),
732 XLEShortField("uuid", None)]
733
734
735class ATT_Handle_Variable(Packet):
736 __slots__ = ["val_length"]
737 fields_desc = [XLEShortField("handle", 0),
738 XStrLenField(
739 "value", 0,
740 length_from=lambda pkt: pkt.val_length)]
741
742 def __init__(self, _pkt=b"", val_length=2, **kwargs):
743 self.val_length = val_length
744 Packet.__init__(self, _pkt, **kwargs)
745
746 def extract_padding(self, s):
747 return b"", s
748
749
750class ATT_Read_By_Type_Response(Packet):
751 name = "Read By Type Response"
752 fields_desc = [ByteField("len", 4),
753 PacketListField(
754 "handles", [],
755 next_cls_cb=lambda pkt, *args: (
756 pkt._next_cls_cb(pkt, *args)
757 ))]
758
759 @classmethod
760 def _next_cls_cb(cls, pkt, lst, p, remain):
761 if len(remain) >= pkt.len:
762 return functools.partial(
763 ATT_Handle_Variable,
764 val_length=pkt.len - 2
765 )
766 return None
767
768
769class ATT_Read_Request(Packet):
770 name = "Read Request"
771 fields_desc = [XLEShortField("gatt_handle", 0), ]
772
773
774class ATT_Read_Response(Packet):
775 name = "Read Response"
776 fields_desc = [StrField("value", "")]
777
778
779class ATT_Read_Multiple_Request(Packet):
780 name = "Read Multiple Request"
781 fields_desc = [FieldListField("handles", [], XLEShortField("", 0))]
782
783
784class ATT_Read_Multiple_Response(Packet):
785 name = "Read Multiple Response"
786 fields_desc = [StrField("values", "")]
787
788
789class ATT_Read_By_Group_Type_Request(Packet):
790 name = "Read By Group Type Request"
791 fields_desc = [XLEShortField("start", 0),
792 XLEShortField("end", 0xffff),
793 XLEShortField("uuid", 0), ]
794
795
796class ATT_Read_By_Group_Type_Response(Packet):
797 name = "Read By Group Type Response"
798 fields_desc = [XByteField("length", 0),
799 StrField("data", ""), ]
800
801
802class ATT_Write_Request(Packet):
803 name = "Write Request"
804 fields_desc = [XLEShortField("gatt_handle", 0),
805 StrField("data", ""), ]
806
807
808class ATT_Write_Command(Packet):
809 name = "Write Request"
810 fields_desc = [XLEShortField("gatt_handle", 0),
811 StrField("data", ""), ]
812
813
814class ATT_Write_Response(Packet):
815 name = "Write Response"
816
817
818class ATT_Prepare_Write_Request(Packet):
819 name = "Prepare Write Request"
820 fields_desc = [
821 XLEShortField("gatt_handle", 0),
822 LEShortField("offset", 0),
823 StrField("data", "")
824 ]
825
826
827class ATT_Prepare_Write_Response(ATT_Prepare_Write_Request):
828 name = "Prepare Write Response"
829
830
831class ATT_Handle_Value_Notification(Packet):
832 name = "Handle Value Notification"
833 fields_desc = [XLEShortField("gatt_handle", 0),
834 StrField("value", ""), ]
835
836
837class ATT_Execute_Write_Request(Packet):
838 name = "Execute Write Request"
839 fields_desc = [
840 ByteEnumField("flags", 1, {
841 0: "Cancel all prepared writes",
842 1: "Immediately write all pending prepared values",
843 }),
844 ]
845
846
847class ATT_Execute_Write_Response(Packet):
848 name = "Execute Write Response"
849
850
851class ATT_Read_Blob_Request(Packet):
852 name = "Read Blob Request"
853 fields_desc = [
854 XLEShortField("gatt_handle", 0),
855 LEShortField("offset", 0)
856 ]
857
858
859class ATT_Read_Blob_Response(Packet):
860 name = "Read Blob Response"
861 fields_desc = [
862 StrField("value", "")
863 ]
864
865
866class ATT_Handle_Value_Indication(Packet):
867 name = "Handle Value Indication"
868 fields_desc = [
869 XLEShortField("gatt_handle", 0),
870 StrField("value", ""),
871 ]
872
873
874class SM_Hdr(Packet):
875 name = "SM header"
876 fields_desc = [ByteField("sm_command", None)]
877
878
879class SM_Pairing_Request(Packet):
880 name = "Pairing Request"
881 fields_desc = [ByteEnumField("iocap", 3, {0: "DisplayOnly", 1: "DisplayYesNo", 2: "KeyboardOnly", 3: "NoInputNoOutput", 4: "KeyboardDisplay"}), # noqa: E501
882 ByteEnumField("oob", 0, {0: "Not Present", 1: "Present (from remote device)"}), # noqa: E501
883 BitField("authentication", 0, 8),
884 ByteField("max_key_size", 16),
885 ByteField("initiator_key_distribution", 0),
886 ByteField("responder_key_distribution", 0), ]
887
888
889class SM_Pairing_Response(Packet):
890 name = "Pairing Response"
891 fields_desc = [ByteEnumField("iocap", 3, {0: "DisplayOnly", 1: "DisplayYesNo", 2: "KeyboardOnly", 3: "NoInputNoOutput", 4: "KeyboardDisplay"}), # noqa: E501
892 ByteEnumField("oob", 0, {0: "Not Present", 1: "Present (from remote device)"}), # noqa: E501
893 BitField("authentication", 0, 8),
894 ByteField("max_key_size", 16),
895 ByteField("initiator_key_distribution", 0),
896 ByteField("responder_key_distribution", 0), ]
897
898
899class SM_Confirm(Packet):
900 name = "Pairing Confirm"
901 fields_desc = [StrFixedLenField("confirm", b'\x00' * 16, 16)]
902
903
904class SM_Random(Packet):
905 name = "Pairing Random"
906 fields_desc = [StrFixedLenField("random", b'\x00' * 16, 16)]
907
908
909class SM_Failed(Packet):
910 name = "Pairing Failed"
911 fields_desc = [XByteField("reason", 0)]
912
913
914class SM_Encryption_Information(Packet):
915 name = "Encryption Information"
916 fields_desc = [StrFixedLenField("ltk", b"\x00" * 16, 16), ]
917
918
919class SM_Master_Identification(Packet):
920 name = "Master Identification"
921 fields_desc = [XLEShortField("ediv", 0),
922 StrFixedLenField("rand", b'\x00' * 8, 8), ]
923
924
925class SM_Identity_Information(Packet):
926 name = "Identity Information"
927 fields_desc = [StrFixedLenField("irk", b'\x00' * 16, 16), ]
928
929
930class SM_Identity_Address_Information(Packet):
931 name = "Identity Address Information"
932 fields_desc = [ByteEnumField("atype", 0, {0: "public"}),
933 LEMACField("address", None), ]
934
935
936class SM_Signing_Information(Packet):
937 name = "Signing Information"
938 fields_desc = [StrFixedLenField("csrk", b'\x00' * 16, 16), ]
939
940
941class SM_Security_Request(Packet):
942 name = "Security Request"
943 fields_desc = [BitField("auth_req", 0, 8), ]
944
945
946class SM_Public_Key(Packet):
947 name = "Public Key"
948 fields_desc = [StrFixedLenField("key_x", b'\x00' * 32, 32),
949 StrFixedLenField("key_y", b'\x00' * 32, 32), ]
950
951
952class SM_DHKey_Check(Packet):
953 name = "DHKey Check"
954 fields_desc = [StrFixedLenField("dhkey_check", b'\x00' * 16, 16), ]
955
956
957class EIR_Hdr(Packet):
958 name = "EIR Header"
959 fields_desc = [
960 LenField("len", None, fmt="B", adjust=lambda x: x + 1), # Add bytes mark # noqa: E501
961 # https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
962 ByteEnumField("type", 0, {
963 0x01: "flags",
964 0x02: "incomplete_list_16_bit_svc_uuids",
965 0x03: "complete_list_16_bit_svc_uuids",
966 0x04: "incomplete_list_32_bit_svc_uuids",
967 0x05: "complete_list_32_bit_svc_uuids",
968 0x06: "incomplete_list_128_bit_svc_uuids",
969 0x07: "complete_list_128_bit_svc_uuids",
970 0x08: "shortened_local_name",
971 0x09: "complete_local_name",
972 0x0a: "tx_power_level",
973 0x0d: "class_of_device",
974 0x0e: "simple_pairing_hash",
975 0x0f: "simple_pairing_rand",
976
977 0x10: "sec_mgr_tk",
978 0x11: "sec_mgr_oob_flags",
979 0x12: "slave_conn_intvl_range",
980 0x14: "list_16_bit_svc_sollication_uuids",
981 0x15: "list_128_bit_svc_sollication_uuids",
982 0x16: "svc_data_16_bit_uuid",
983 0x17: "pub_target_addr",
984 0x18: "rand_target_addr",
985 0x19: "appearance",
986 0x1a: "adv_intvl",
987 0x1b: "le_addr",
988 0x1c: "le_role",
989 0x1d: "simple_pairing_hash_256",
990 0x1e: "simple_pairing_rand_256",
991 0x1f: "list_32_bit_svc_sollication_uuids",
992
993 0x20: "svc_data_32_bit_uuid",
994 0x21: "svc_data_128_bit_uuid",
995 0x22: "sec_conn_confirm",
996 0x23: "sec_conn_rand",
997 0x24: "uri",
998 0x25: "indoor_positioning",
999 0x26: "transport_discovery",
1000 0x27: "le_supported_features",
1001 0x28: "channel_map_update",
1002 0x29: "mesh_pb_adv",
1003 0x2a: "mesh_message",
1004 0x2b: "mesh_beacon",
1005
1006 0x3d: "3d_information",
1007
1008 0xff: "mfg_specific_data",
1009 }),
1010 ]
1011
1012 def mysummary(self):
1013 return self.sprintf("EIR %type%")
1014
1015 def guess_payload_class(self, payload):
1016 if self.len == 0:
1017 # For Extended_Inquiry_Response, stop when len=0
1018 return conf.padding_layer
1019 return super(EIR_Hdr, self).guess_payload_class(payload)
1020
1021
1022class EIR_Element(Packet):
1023 name = "EIR Element"
1024
1025 def extract_padding(self, s):
1026 # Needed to end each EIR_Element packet and make PacketListField work.
1027 return b'', s
1028
1029 @staticmethod
1030 def length_from(pkt):
1031 if not pkt.underlayer:
1032 warning("Missing an upper-layer")
1033 return 0
1034 # 'type' byte is included in the length, so subtract 1:
1035 return pkt.underlayer.len - 1
1036
1037
1038class EIR_Raw(EIR_Element):
1039 name = "EIR Raw"
1040 fields_desc = [
1041 StrLenField("data", "", length_from=EIR_Element.length_from)
1042 ]
1043
1044
1045class EIR_Flags(EIR_Element):
1046 name = "Flags"
1047 fields_desc = [
1048 FlagsField("flags", 0x2, 8,
1049 ["limited_disc_mode", "general_disc_mode",
1050 "br_edr_not_supported", "simul_le_br_edr_ctrl",
1051 "simul_le_br_edr_host"] + 3 * ["reserved"])
1052 ]
1053
1054
1055class EIR_CompleteList16BitServiceUUIDs(EIR_Element):
1056 name = "Complete list of 16-bit service UUIDs"
1057 fields_desc = [
1058 # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members
1059 FieldListField("svc_uuids", None, XLEShortField("uuid", 0),
1060 length_from=EIR_Element.length_from)
1061 ]
1062
1063
1064class EIR_IncompleteList16BitServiceUUIDs(EIR_CompleteList16BitServiceUUIDs):
1065 name = "Incomplete list of 16-bit service UUIDs"
1066
1067
1068class EIR_CompleteList32BitServiceUUIDs(EIR_Element):
1069 name = 'Complete list of 32-bit service UUIDs'
1070 fields_desc = [
1071 # https://www.bluetooth.com/specifications/assigned-numbers
1072 FieldListField('svc_uuids', None, XLEIntField('uuid', 0),
1073 length_from=EIR_Element.length_from)
1074 ]
1075
1076
1077class EIR_IncompleteList32BitServiceUUIDs(EIR_CompleteList32BitServiceUUIDs):
1078 name = 'Incomplete list of 32-bit service UUIDs'
1079
1080
1081class EIR_CompleteList128BitServiceUUIDs(EIR_Element):
1082 name = "Complete list of 128-bit service UUIDs"
1083 fields_desc = [
1084 FieldListField("svc_uuids", None,
1085 UUIDField("uuid", None, uuid_fmt=UUIDField.FORMAT_REV),
1086 length_from=EIR_Element.length_from)
1087 ]
1088
1089
1090class EIR_IncompleteList128BitServiceUUIDs(EIR_CompleteList128BitServiceUUIDs):
1091 name = "Incomplete list of 128-bit service UUIDs"
1092
1093
1094class EIR_CompleteLocalName(EIR_Element):
1095 name = "Complete Local Name"
1096 fields_desc = [
1097 StrLenField("local_name", "", length_from=EIR_Element.length_from)
1098 ]
1099
1100
1101class EIR_ShortenedLocalName(EIR_CompleteLocalName):
1102 name = "Shortened Local Name"
1103
1104
1105class EIR_TX_Power_Level(EIR_Element):
1106 name = "TX Power Level"
1107 fields_desc = [SignedByteField("level", 0)]
1108
1109
1110class EIR_ClassOfDevice(EIR_Element):
1111 name = 'Class of device'
1112 fields_desc = [
1113 FlagsField('major_service_classes', 0, 11, [
1114 'limited_discoverable_mode',
1115 'le_audio',
1116 'reserved',
1117 'positioning',
1118 'networking',
1119 'rendering',
1120 'capturing',
1121 'object_transfer',
1122 'audio',
1123 'telephony',
1124 'information'
1125 ], tot_size=-3),
1126 BitEnumField('major_device_class', 0, 5, {
1127 0x00: 'miscellaneous',
1128 0x01: 'computer',
1129 0x02: 'phone',
1130 0x03: 'lan',
1131 0x04: 'audio_video',
1132 0x05: 'peripheral',
1133 0x06: 'imaging',
1134 0x07: 'wearable',
1135 0x08: 'toy',
1136 0x09: 'health',
1137 0x1f: 'uncategorized'
1138 }),
1139 BitField('minor_device_class', 0, 6),
1140 BitField('fixed', 0, 2, end_tot_size=-3)
1141 ]
1142
1143
1144class EIR_SecureSimplePairingHashC192(EIR_Element):
1145 name = 'Secure Simple Pairing Hash C-192'
1146 fields_desc = [NBytesField('hash', 0, 16)]
1147
1148
1149class EIR_SecureSimplePairingRandomizerR192(EIR_Element):
1150 name = 'Secure Simple Pairing Randomizer R-192'
1151 fields_desc = [NBytesField('randomizer', 0, 16)]
1152
1153
1154class EIR_SecurityManagerOOBFlags(EIR_Element):
1155 name = 'Security Manager Out of Band Flags'
1156 fields_desc = [
1157 BitField('oob_flags_field', 0, 1),
1158 BitField('le_supported', 0, 1),
1159 BitField('previously_used', 0, 1),
1160 BitField('address_type', 0, 1),
1161 BitField('reserved', 0, 4)
1162 ]
1163
1164
1165class EIR_PeripheralConnectionIntervalRange(EIR_Element):
1166 name = 'Peripheral Connection Interval Range'
1167 fields_desc = [
1168 LEShortField('conn_interval_min', 0xFFFF),
1169 LEShortField('conn_interval_max', 0xFFFF)
1170 ]
1171
1172
1173class EIR_Manufacturer_Specific_Data(EIR_Element):
1174 name = "EIR Manufacturer Specific Data"
1175 deprecated_fields = {
1176 "company_id": ("company_identifier", "2.6.2"),
1177 }
1178 fields_desc = [
1179 # https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
1180 LEShortEnumField("company_identifier", None,
1181 BLUETOOTH_CORE_COMPANY_IDENTIFIERS),
1182 ]
1183
1184 registered_magic_payloads = {}
1185
1186 @classmethod
1187 def register_magic_payload(cls, payload_cls, magic_check=None):
1188 """
1189 Registers a payload type that uses magic data.
1190
1191 Traditional payloads require registration of a Bluetooth Company ID
1192 (requires company membership of the Bluetooth SIG), or a Bluetooth
1193 Short UUID (requires a once-off payment).
1194
1195 There are alternatives which don't require registration (such as
1196 128-bit UUIDs), but the biggest consumer of energy in a beacon is the
1197 radio -- so the energy consumption of a beacon is proportional to the
1198 number of bytes in a beacon frame.
1199
1200 Some beacon formats side-step this issue by using the Company ID of
1201 their beacon hardware manufacturer, and adding a "magic data sequence"
1202 at the start of the Manufacturer Specific Data field.
1203
1204 Examples of this are AltBeacon and GeoBeacon.
1205
1206 For an example of this method in use, see ``scapy.contrib.altbeacon``.
1207
1208 :param Type[scapy.packet.Packet] payload_cls:
1209 A reference to a Packet subclass to register as a payload.
1210 :param Callable[[bytes], bool] magic_check:
1211 (optional) callable to use to if a payload should be associated
1212 with this type. If not supplied, ``payload_cls.magic_check`` is
1213 used instead.
1214 :raises TypeError: If ``magic_check`` is not specified,
1215 and ``payload_cls.magic_check`` is not implemented.
1216 """
1217 if magic_check is None:
1218 if hasattr(payload_cls, "magic_check"):
1219 magic_check = payload_cls.magic_check
1220 else:
1221 raise TypeError("magic_check not specified, and {} has no "
1222 "attribute magic_check".format(payload_cls))
1223
1224 cls.registered_magic_payloads[payload_cls] = magic_check
1225
1226 def default_payload_class(self, payload):
1227 for cls, check in (
1228 EIR_Manufacturer_Specific_Data.registered_magic_payloads.items()
1229 ):
1230 if check(payload):
1231 return cls
1232
1233 return Packet.default_payload_class(self, payload)
1234
1235 def extract_padding(self, s):
1236 # Needed to end each EIR_Element packet and make PacketListField work.
1237 plen = EIR_Element.length_from(self) - 2
1238 return s[:plen], s[plen:]
1239
1240
1241class EIR_Device_ID(EIR_Element):
1242 name = "Device ID"
1243 fields_desc = [
1244 XLEShortField("vendor_id_source", 0),
1245 XLEShortField("vendor_id", 0),
1246 XLEShortField("product_id", 0),
1247 XLEShortField("version", 0),
1248 ]
1249
1250
1251class EIR_ServiceSolicitation16BitUUID(EIR_Element):
1252 name = "EIR Service Solicitation - 16-bit UUID"
1253 fields_desc = [
1254 XLEShortField("svc_uuid", None)
1255 ]
1256
1257 def extract_padding(self, s):
1258 # Needed to end each EIR_Element packet and make PacketListField work.
1259 plen = EIR_Element.length_from(self) - 2
1260 return s[:plen], s[plen:]
1261
1262
1263class EIR_ServiceSolicitation128BitUUID(EIR_Element):
1264 name = "EIR Service Solicitation - 128-bit UUID"
1265 fields_desc = [
1266 UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)
1267 ]
1268
1269 def extract_padding(self, s):
1270 # Needed to end each EIR_Element packet and make PacketListField work.
1271 plen = EIR_Element.length_from(self) - 2
1272 return s[:plen], s[plen:]
1273
1274
1275class EIR_ServiceData16BitUUID(EIR_Element):
1276 name = "EIR Service Data - 16-bit UUID"
1277 fields_desc = [
1278 # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members
1279 XLEShortField("svc_uuid", None),
1280 ]
1281
1282 def extract_padding(self, s):
1283 # Needed to end each EIR_Element packet and make PacketListField work.
1284 plen = EIR_Element.length_from(self) - 2
1285 return s[:plen], s[plen:]
1286
1287
1288class EIR_PublicTargetAddress(EIR_Element):
1289 name = "Public Target Address"
1290 fields_desc = [
1291 LEMACField('bd_addr', None)
1292 ]
1293
1294
1295class EIR_AdvertisingInterval(EIR_Element):
1296 name = "Advertising Interval"
1297 fields_desc = [
1298 MultipleTypeField(
1299 [
1300 (ByteField("advertising_interval", 0),
1301 lambda p: p.underlayer.len - 1 == 1),
1302 (LEShortField("advertising_interval", 0),
1303 lambda p: p.underlayer.len - 1 == 2),
1304 (LEThreeBytesField("advertising_interval", 0),
1305 lambda p: p.underlayer.len - 1 == 3),
1306 (LEIntField("advertising_interval", 0),
1307 lambda p: p.underlayer.len - 1 == 4),
1308 ],
1309 LEShortField("advertising_interval", 0)
1310 )
1311 ]
1312
1313
1314class EIR_LEBluetoothDeviceAddress(EIR_Element):
1315 name = "LE Bluetooth Device Address"
1316 fields_desc = [
1317 XBitField('reserved', 0, 7, tot_size=-1),
1318 BitEnumField('addr_type', 0, 1, end_tot_size=-1, enum={
1319 0x0: 'Public',
1320 0x1: 'Random'
1321 }),
1322 LEMACField('bd_addr', None)
1323 ]
1324
1325
1326class EIR_Appearance(EIR_Element):
1327 name = "EIR_Appearance"
1328 fields_desc = [
1329 BitEnumField('category', 0, 10, tot_size=-2, enum={
1330 0x000: 'Unknown',
1331 0x001: 'Phone',
1332 0x002: 'Computer',
1333 0x003: 'Watch',
1334 0x004: 'Clock',
1335 0x005: 'Display',
1336 0x006: 'Remote Control',
1337 0x007: 'Eyeglasses',
1338 0x008: 'Tag',
1339 0x009: 'Keyring',
1340 0x00A: 'Media Player',
1341 0x00B: 'Barcode Scanner',
1342 0x00C: 'Thermometer',
1343 0x00D: 'Heart Rate Sensor',
1344 0x00E: 'Blood Pressure',
1345 0x00F: 'Human Interface Device',
1346 0x010: 'Glucose Meter',
1347 0x011: 'Running Walking Sensor',
1348 0x012: 'Cycling',
1349 0x013: 'Control Device',
1350 0x014: 'Network Device',
1351 0x015: 'Sensor',
1352 0x016: 'Light Fixtures',
1353 0x017: 'Fan',
1354 0x018: 'HVAC',
1355 0x019: 'Air Conditioning',
1356 0x01A: 'Humidifier',
1357 0x01B: 'Heating',
1358 0x01C: 'Access Control',
1359 0x01D: 'Motorized Device',
1360 0x01E: 'Power Device',
1361 0x01F: 'Light Source',
1362 0x020: 'Window Covering',
1363 0x021: 'Audio Sink',
1364 0x022: 'Audio Source',
1365 0x023: 'Motorized Vehicle',
1366 0x024: 'Domestic Appliance',
1367 0x025: 'Wearable Audio Device',
1368 0x026: 'Aircraft',
1369 0x027: 'AV Equipment',
1370 0x028: 'Display Equipment',
1371 0x029: 'Hearing aid',
1372 0x02A: 'Gaming',
1373 0x02B: 'Signage',
1374 0x031: 'Pulse Oximeter',
1375 0x032: 'Weight Scale',
1376 0x033: 'Personal Mobility Device',
1377 0x034: 'Continuous Glucose Monitor',
1378 0x035: 'Insulin Pump',
1379 0x036: 'Medication Delivery',
1380 0x037: 'Spirometer',
1381 0x051: 'Outdoor Sports Activity'
1382 }),
1383 XBitField('subcategory', 0, 6, end_tot_size=-2)
1384 ]
1385
1386 @property
1387 def appearance(self):
1388 return (self.category << 6) + self.subcategory
1389
1390
1391class EIR_ServiceData32BitUUID(EIR_Element):
1392 name = 'EIR Service Data - 32-bit UUID'
1393 fields_desc = [
1394 XLEIntField('svc_uuid', 0),
1395 ]
1396
1397 def extract_padding(self, s):
1398 # Needed to end each EIR_Element packet and make PacketListField work.
1399 plen = EIR_Element.length_from(self) - 4
1400 return s[:plen], s[plen:]
1401
1402
1403class EIR_ServiceData128BitUUID(EIR_Element):
1404 name = 'EIR Service Data - 128-bit UUID'
1405 fields_desc = [
1406 UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)
1407 ]
1408
1409 def extract_padding(self, s):
1410 # Needed to end each EIR_Element packet and make PacketListField work.
1411 plen = EIR_Element.length_from(self) - 16
1412 return s[:plen], s[plen:]
1413
1414
1415class EIR_URI(EIR_Element):
1416 name = 'EIR URI'
1417 fields_desc = [
1418 ByteEnumField('scheme', 0, {
1419 0x01: '',
1420 0x02: 'aaa:',
1421 0x03: 'aaas:',
1422 0x04: 'about:',
1423 0x05: 'acap:',
1424 0x06: 'acct:',
1425 0x07: 'cap:',
1426 0x08: 'cid:',
1427 0x09: 'coap:',
1428 0x0A: 'coaps:',
1429 0x0B: 'crid:',
1430 0x0C: 'data:',
1431 0x0D: 'dav:',
1432 0x0E: 'dict:',
1433 0x0F: 'dns:',
1434 0x10: 'file:',
1435 0x11: 'ftp:',
1436 0x12: 'geo:',
1437 0x13: 'go:',
1438 0x14: 'gopher:',
1439 0x15: 'h323:',
1440 0x16: 'http:',
1441 0x17: 'https:',
1442 0x18: 'iax:',
1443 0x19: 'icap:',
1444 0x1A: 'im:',
1445 0x1B: 'imap:',
1446 0x1C: 'info:',
1447 0x1D: 'ipp:',
1448 0x1E: 'ipps:',
1449 0x1F: 'iris:',
1450 0x20: 'iris.beep:',
1451 0x21: 'iris.xpc:',
1452 0x22: 'iris.xpcs:',
1453 0x23: 'iris.lwz:',
1454 0x24: 'jabber:',
1455 0x25: 'ldap:',
1456 0x26: 'mailto:',
1457 0x27: 'mid:',
1458 0x28: 'msrp:',
1459 0x29: 'msrps:',
1460 0x2A: 'mtqp:',
1461 0x2B: 'mupdate:',
1462 0x2C: 'news:',
1463 0x2D: 'nfs:',
1464 0x2E: 'ni:',
1465 0x2F: 'nih:',
1466 0x30: 'nntp:',
1467 0x31: 'opaquelocktoken:',
1468 0x32: 'pop:',
1469 0x33: 'pres:',
1470 0x34: 'reload:',
1471 0x35: 'rtsp:',
1472 0x36: 'rtsps:',
1473 0x37: 'rtspu:',
1474 0x38: 'service:',
1475 0x39: 'session:',
1476 0x3A: 'shttp:',
1477 0x3B: 'sieve:',
1478 0x3C: 'sip:',
1479 0x3D: 'sips:',
1480 0x3E: 'sms:',
1481 0x3F: 'snmp:',
1482 0x40: 'soap.beep:',
1483 0x41: 'soap.beeps:',
1484 0x42: 'stun:',
1485 0x43: 'stuns:',
1486 0x44: 'tag:',
1487 0x45: 'tel:',
1488 0x46: 'telnet:',
1489 0x47: 'tftp:',
1490 0x48: 'thismessage:',
1491 0x49: 'tn3270:',
1492 0x4A: 'tip:',
1493 0x4B: 'turn:',
1494 0x4C: 'turns:',
1495 0x4D: 'tv:',
1496 0x4E: 'urn:',
1497 0x4F: 'vemmi:',
1498 0x50: 'ws:',
1499 0x51: 'wss:',
1500 0x52: 'xcon:',
1501 0x53: 'xconuserid:',
1502 0x54: 'xmlrpc.beep:',
1503 0x55: 'xmlrpc.beeps:',
1504 0x56: 'xmpp:',
1505 0x57: 'z39.50r:',
1506 0x58: 'z39.50s:',
1507 0x59: 'acr:',
1508 0x5A: 'adiumxtra:',
1509 0x5B: 'afp:',
1510 0x5C: 'afs:',
1511 0x5D: 'aim:',
1512 0x5E: 'apt:',
1513 0x5F: 'attachment:',
1514 0x60: 'aw:',
1515 0x61: 'barion:',
1516 0x62: 'beshare:',
1517 0x63: 'bitcoin:',
1518 0x64: 'bolo:',
1519 0x65: 'callto:',
1520 0x66: 'chrome:',
1521 0x67: 'chromeextension:',
1522 0x68: 'comeventbriteattendee:',
1523 0x69: 'content:',
1524 0x6A: 'cvs:',
1525 0x6B: 'dlnaplaysingle:',
1526 0x6C: 'dlnaplaycontainer:',
1527 0x6D: 'dtn:',
1528 0x6E: 'dvb:',
1529 0x6F: 'ed2k:',
1530 0x70: 'facetime:',
1531 0x71: 'feed:',
1532 0x72: 'feedready:',
1533 0x73: 'finger:',
1534 0x74: 'fish:',
1535 0x75: 'gg:',
1536 0x76: 'git:',
1537 0x77: 'gizmoproject:',
1538 0x78: 'gtalk:',
1539 0x79: 'ham:',
1540 0x7A: 'hcp:',
1541 0x7B: 'icon:',
1542 0x7C: 'ipn:',
1543 0x7D: 'irc:',
1544 0x7E: 'irc6:',
1545 0x7F: 'ircs:',
1546 0x80: 'itms:',
1547 0x81: 'jar:',
1548 0x82: 'jms:',
1549 0x83: 'keyparc:',
1550 0x84: 'lastfm:',
1551 0x85: 'ldaps:',
1552 0x86: 'magnet:',
1553 0x87: 'maps:',
1554 0x88: 'market:',
1555 0x89: 'message:',
1556 0x8A: 'mms:',
1557 0x8B: 'mshelp:',
1558 0x8C: 'mssettingspower:',
1559 0x8D: 'msnim:',
1560 0x8E: 'mumble:',
1561 0x8F: 'mvn:',
1562 0x90: 'notes:',
1563 0x91: 'oid:',
1564 0x92: 'palm:',
1565 0x93: 'paparazzi:',
1566 0x94: 'pkcs11:',
1567 0x95: 'platform:',
1568 0x96: 'proxy:',
1569 0x97: 'psyc:',
1570 0x98: 'query:',
1571 0x99: 'res:',
1572 0x9A: 'resource:',
1573 0x9B: 'rmi:',
1574 0x9C: 'rsync:',
1575 0x9D: 'rtmfp:',
1576 0x9E: 'rtmp:',
1577 0x9F: 'secondlife:',
1578 0xA0: 'sftp:',
1579 0xA1: 'sgn:',
1580 0xA2: 'skype:',
1581 0xA3: 'smb:',
1582 0xA4: 'smtp:',
1583 0xA5: 'soldat:',
1584 0xA6: 'spotify:',
1585 0xA7: 'ssh:',
1586 0xA8: 'steam:',
1587 0xA9: 'submit:',
1588 0xAA: 'svn:',
1589 0xAB: 'teamspeak:',
1590 0xAC: 'teliaeid:',
1591 0xAD: 'things:',
1592 0xAE: 'udp:',
1593 0xAF: 'unreal:',
1594 0xB0: 'ut2004:',
1595 0xB1: 'ventrilo:',
1596 0xB2: 'viewsource:',
1597 0xB3: 'webcal:',
1598 0xB4: 'wtai:',
1599 0xB5: 'wyciwyg:',
1600 0xB6: 'xfire:',
1601 0xB7: 'xri:',
1602 0xB8: 'ymsgr:',
1603 0xB9: 'example:',
1604 0xBA: 'mssettingscloudstorage:'
1605 }),
1606 StrLenField('uri_hier_part', None, length_from=EIR_Element.length_from)
1607 ]
1608
1609 @property
1610 def uri(self):
1611 return EIR_URI.scheme.i2s[self.scheme] + self.uri_hier_part.decode('utf-8')
1612
1613
1614class HCI_Command_Hdr(Packet):
1615 name = "HCI Command header"
1616 fields_desc = [XBitField("ogf", 0, 6, tot_size=-2),
1617 XBitField("ocf", 0, 10, end_tot_size=-2),
1618 LenField("len", None, fmt="B"), ]
1619
1620 def answers(self, other):
1621 return False
1622
1623 @property
1624 def opcode(self):
1625 return (self.ogf << 10) + self.ocf
1626
1627 def post_build(self, p, pay):
1628 p += pay
1629 if self.len is None:
1630 p = p[:2] + struct.pack("B", len(pay)) + p[3:]
1631 return p
1632
1633
1634# BUETOOTH CORE SPECIFICATION 5.4 | Vol 3, Part C
1635# 8 EXTENDED INQUIRY RESPONSE
1636
1637class HCI_Extended_Inquiry_Response(Packet):
1638 fields_desc = [
1639 PadField(
1640 PacketListField(
1641 "eir_data", [],
1642 next_cls_cb=lambda *args: (
1643 (not args[2] or args[2].len != 0) and EIR_Hdr or conf.raw_layer
1644 )
1645 ),
1646 align=31, padwith=b"\0",
1647 ),
1648 ]
1649
1650
1651# BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E
1652# 7 HCI COMMANDS AND EVENTS
1653# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01
1654
1655class HCI_Cmd_Inquiry(Packet):
1656 """
1657 7.1.1 Inquiry command
1658 """
1659 name = "HCI_Inquiry"
1660 fields_desc = [XLE3BytesField("lap", 0x9E8B33),
1661 ByteField("inquiry_length", 0),
1662 ByteField("num_responses", 0)]
1663
1664
1665class HCI_Cmd_Inquiry_Cancel(Packet):
1666 """
1667 7.1.2 Inquiry Cancel command
1668 """
1669 name = "HCI_Inquiry_Cancel"
1670
1671
1672class HCI_Cmd_Periodic_Inquiry_Mode(Packet):
1673 """
1674 7.1.3 Periodic Inquiry Mode command
1675 """
1676 name = "HCI_Periodic_Inquiry_Mode"
1677 fields_desc = [LEShortField("max_period_length", 0x0003),
1678 LEShortField("min_period_length", 0x0002),
1679 XLE3BytesField("lap", 0x9E8B33),
1680 ByteField("inquiry_length", 0),
1681 ByteField("num_responses", 0)]
1682
1683
1684class HCI_Cmd_Exit_Peiodic_Inquiry_Mode(Packet):
1685 """
1686 7.1.4 Exit Periodic Inquiry Mode command
1687 """
1688 name = "HCI_Exit_Periodic_Inquiry_Mode"
1689
1690
1691class HCI_Cmd_Create_Connection(Packet):
1692 """
1693 7.1.5 Create Connection command
1694 """
1695 name = "HCI_Create_Connection"
1696 fields_desc = [LEMACField("bd_addr", None),
1697 LEShortField("packet_type", 0xcc18),
1698 ByteField("page_scan_repetition_mode", 0x02),
1699 ByteField("reserved", 0x0),
1700 LEShortField("clock_offset", 0x0),
1701 ByteField("allow_role_switch", 0x1), ]
1702
1703
1704class HCI_Cmd_Disconnect(Packet):
1705 """
1706 7.1.6 Disconnect command
1707 """
1708 name = "HCI_Disconnect"
1709 fields_desc = [XLEShortField("handle", 0),
1710 ByteField("reason", 0x13), ]
1711
1712
1713class HCI_Cmd_Create_Connection_Cancel(Packet):
1714 """
1715 7.1.7 Create Connection Cancel command
1716 """
1717 name = "HCI_Create_Connection_Cancel"
1718 fields_desc = [LEMACField("bd_addr", None), ]
1719
1720
1721class HCI_Cmd_Accept_Connection_Request(Packet):
1722 """
1723 7.1.8 Accept Connection Request command
1724 """
1725 name = "HCI_Accept_Connection_Request"
1726 fields_desc = [LEMACField("bd_addr", None),
1727 ByteField("role", 0x1), ]
1728
1729
1730class HCI_Cmd_Reject_Connection_Response(Packet):
1731 """
1732 7.1.9 Reject Connection Request command
1733 """
1734 name = "HCI_Reject_Connection_Response"
1735 fields_desc = [LEMACField("bd_addr", None),
1736 ByteField("reason", 0x1), ]
1737
1738
1739class HCI_Cmd_Link_Key_Request_Reply(Packet):
1740 """
1741 7.1.10 Link Key Request Reply command
1742 """
1743 name = "HCI_Link_Key_Request_Reply"
1744 fields_desc = [LEMACField("bd_addr", None),
1745 NBytesField("link_key", None, 16), ]
1746
1747
1748class HCI_Cmd_Link_Key_Request_Negative_Reply(Packet):
1749 """
1750 7.1.11 Link Key Request Negative Reply command
1751 """
1752 name = "HCI_Link_Key_Request_Negative_Reply"
1753 fields_desc = [LEMACField("bd_addr", None), ]
1754
1755
1756class HCI_Cmd_PIN_Code_Request_Reply(Packet):
1757 """
1758 7.1.12 PIN Code Request Reply command
1759 """
1760 name = "HCI_PIN_Code_Request_Reply"
1761 fields_desc = [LEMACField("bd_addr", None),
1762 ByteField("pin_code_length", 7),
1763 NBytesField("pin_code", b"\x00" * 16, sz=16), ]
1764
1765
1766class HCI_Cmd_PIN_Code_Request_Negative_Reply(Packet):
1767 """
1768 7.1.13 PIN Code Request Negative Reply command
1769 """
1770 name = "HCI_PIN_Code_Request_Negative_Reply"
1771 fields_desc = [LEMACField("bd_addr", None), ]
1772
1773
1774class HCI_Cmd_Change_Connection_Packet_Type(Packet):
1775 """
1776 7.1.14 Change Connection Packet Type command
1777 """
1778 name = "HCI_Cmd_Change_Connection_Packet_Type"
1779 fields_desc = [XLEShortField("connection_handle", None),
1780 LEShortField("packet_type", 0), ]
1781
1782
1783class HCI_Cmd_Authentication_Requested(Packet):
1784 """
1785 7.1.15 Authentication Requested command
1786 """
1787 name = "HCI_Authentication_Requested"
1788 fields_desc = [LEShortField("handle", 0)]
1789
1790
1791class HCI_Cmd_Set_Connection_Encryption(Packet):
1792 """
1793 7.1.16 Set Connection Encryption command
1794 """
1795 name = "HCI_Set_Connection_Encryption"
1796 fields_desc = [LEShortField("handle", 0), ByteField("encryption_enable", 0)]
1797
1798
1799class HCI_Cmd_Change_Connection_Link_Key(Packet):
1800 """
1801 7.1.17 Change Connection Link Key command
1802 """
1803 name = "HCI_Change_Connection_Link_Key"
1804 fields_desc = [LEShortField("handle", 0), ]
1805
1806
1807class HCI_Cmd_Link_Key_Selection(Packet):
1808 """
1809 7.1.18 Change Connection Link Key command
1810 """
1811 name = "HCI_Cmd_Link_Key_Selection"
1812 fields_desc = [ByteEnumField("handle", 0, {0: "Use semi-permanent Link Keys",
1813 1: "Use Temporary Link Key", }), ]
1814
1815
1816class HCI_Cmd_Remote_Name_Request(Packet):
1817 """
1818 7.1.19 Remote Name Request command
1819 """
1820 name = "HCI_Remote_Name_Request"
1821 fields_desc = [LEMACField("bd_addr", None),
1822 ByteField("page_scan_repetition_mode", 0x02),
1823 ByteField("reserved", 0x0),
1824 LEShortField("clock_offset", 0x0), ]
1825
1826
1827class HCI_Cmd_Remote_Name_Request_Cancel(Packet):
1828 """
1829 7.1.20 Remote Name Request Cancel command
1830 """
1831 name = "HCI_Remote_Name_Request_Cancel"
1832 fields_desc = [LEMACField("bd_addr", None), ]
1833
1834
1835class HCI_Cmd_Read_Remote_Supported_Features(Packet):
1836 """
1837 7.1.21 Read Remote Supported Features command
1838 """
1839 name = "HCI_Read_Remote_Supported_Features"
1840 fields_desc = [LEShortField("connection_handle", None), ]
1841
1842
1843class HCI_Cmd_Read_Remote_Extended_Features(Packet):
1844 """
1845 7.1.22 Read Remote Extended Features command
1846 """
1847 name = "HCI_Read_Remote_Supported_Features"
1848 fields_desc = [LEShortField("connection_handle", None),
1849 ByteField("page_number", None), ]
1850
1851
1852class HCI_Cmd_IO_Capability_Request_Reply(Packet):
1853 """
1854 7.1.29 IO Capability Request Reply command
1855 """
1856 name = "HCI_Read_Remote_Supported_Features"
1857 fields_desc = [LEMACField("bd_addr", None),
1858 ByteEnumField("io_capability", None, {0x00: "DisplayOnly",
1859 0x01: "DisplayYesNo",
1860 0x02: "KeyboardOnly",
1861 0x03: "NoInputNoOutput", }),
1862 ByteEnumField("oob_data_present", None, {0x00: "Not Present",
1863 0x01: "P-192",
1864 0x02: "P-256",
1865 0x03: "P-192 + P-256", }),
1866 ByteEnumField("authentication_requirement", None,
1867 {0x00: "MITM Not Required",
1868 0x01: "MITM Required, No Bonding",
1869 0x02: "MITM Not Required + Dedicated Pairing",
1870 0x03: "MITM Required + Dedicated Pairing",
1871 0x04: "MITM Not Required, General Bonding",
1872 0x05: "MITM Required + General Bonding"}), ]
1873
1874
1875class HCI_Cmd_User_Confirmation_Request_Reply(Packet):
1876 """
1877 7.1.30 User Confirmation Request Reply command
1878 """
1879 name = "HCI_User_Confirmation_Request_Reply"
1880 fields_desc = [LEMACField("bd_addr", None), ]
1881
1882
1883class HCI_Cmd_User_Confirmation_Request_Negative_Reply(Packet):
1884 """
1885 7.1.31 User Confirmation Request Negative Reply command
1886 """
1887 name = "HCI_User_Confirmation_Request_Negative_Reply"
1888 fields_desc = [LEMACField("bd_addr", None), ]
1889
1890
1891class HCI_Cmd_User_Passkey_Request_Reply(Packet):
1892 """
1893 7.1.32 User Passkey Request Reply command
1894 """
1895 name = "HCI_User_Passkey_Request_Reply"
1896 fields_desc = [LEMACField("bd_addr", None),
1897 LEIntField("numeric_value", None), ]
1898
1899
1900class HCI_Cmd_User_Passkey_Request_Negative_Reply(Packet):
1901 """
1902 7.1.33 User Passkey Request Negative Reply command
1903 """
1904 name = "HCI_User_Passkey_Request_Negative_Reply"
1905 fields_desc = [LEMACField("bd_addr", None), ]
1906
1907
1908class HCI_Cmd_Remote_OOB_Data_Request_Reply(Packet):
1909 """
1910 7.1.34 Remote OOB Data Request Reply command
1911 """
1912 name = "HCI_Remote_OOB_Data_Request_Reply"
1913 fields_desc = [LEMACField("bd_addr", None),
1914 NBytesField("C", b"\x00" * 16, sz=16),
1915 NBytesField("R", b"\x00" * 16, sz=16), ]
1916
1917
1918class HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply(Packet):
1919 """
1920 7.1.35 Remote OOB Data Request Negative Reply command
1921 """
1922 name = "HCI_Remote_OOB_Data_Request_Negative_Reply"
1923 fields_desc = [LEMACField("bd_addr", None), ]
1924
1925
1926# 7.2 Link Policy commands, the OGF is defined as 0x02
1927
1928class HCI_Cmd_Hold_Mode(Packet):
1929 name = "HCI_Hold_Mode"
1930 fields_desc = [LEShortField("connection_handle", 0),
1931 LEShortField("hold_mode_max_interval", 0x0002),
1932 LEShortField("hold_mode_min_interval", 0x0002), ]
1933
1934
1935# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03
1936
1937class HCI_Cmd_Set_Event_Mask(Packet):
1938 """
1939 7.3.1 Set Event Mask command
1940 """
1941 name = "HCI_Set_Event_Mask"
1942 fields_desc = [StrFixedLenField("mask", b"\xff\xff\xfb\xff\x07\xf8\xbf\x3d", 8)] # noqa: E501
1943
1944
1945class HCI_Cmd_Reset(Packet):
1946 """
1947 7.3.2 Reset command
1948 """
1949 name = "HCI_Reset"
1950
1951
1952class HCI_Cmd_Set_Event_Filter(Packet):
1953 """
1954 7.3.3 Set Event Filter command
1955 """
1956 name = "HCI_Set_Event_Filter"
1957 fields_desc = [ByteEnumField("type", 0, {0: "clear"}), ]
1958
1959
1960class HCI_Cmd_Write_Local_Name(Packet):
1961 """
1962 7.3.11 Write Local Name command
1963 """
1964 name = "HCI_Write_Local_Name"
1965 fields_desc = [StrFixedLenField('name', '', length=248)]
1966
1967
1968class HCI_Cmd_Read_Local_Name(Packet):
1969 """
1970 7.3.12 Read Local Name command
1971 """
1972 name = "HCI_Read_Local_Name"
1973
1974
1975class HCI_Cmd_Write_Connect_Accept_Timeout(Packet):
1976 name = "HCI_Write_Connection_Accept_Timeout"
1977 fields_desc = [LEShortField("timeout", 32000)] # 32000 slots is 20000 msec
1978
1979
1980class HCI_Cmd_Write_Extended_Inquiry_Response(Packet):
1981 name = "HCI_Write_Extended_Inquiry_Response"
1982 fields_desc = [ByteField("fec_required", 0),
1983 HCI_Extended_Inquiry_Response]
1984
1985
1986class HCI_Cmd_Read_LE_Host_Support(Packet):
1987 name = "HCI_Read_LE_Host_Support"
1988
1989
1990class HCI_Cmd_Write_LE_Host_Support(Packet):
1991 name = "HCI_Write_LE_Host_Support"
1992 fields_desc = [ByteField("supported", 1),
1993 ByteField("unused", 1), ]
1994
1995
1996# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04
1997
1998class HCI_Cmd_Read_Local_Version_Information(Packet):
1999 """
2000 7.4.1 Read Local Version Information command
2001 """
2002 name = "HCI_Read_Local_Version_Information"
2003
2004
2005class HCI_Cmd_Read_Local_Extended_Features(Packet):
2006 """
2007 7.4.4 Read Local Extended Features command
2008 """
2009 name = "HCI_Read_Local_Extended_Features"
2010 fields_desc = [ByteField("page_number", 0)]
2011
2012
2013class HCI_Cmd_Read_BD_Addr(Packet):
2014 """
2015 7.4.6 Read BD_ADDR command
2016 """
2017 name = "HCI_Read_BD_ADDR"
2018
2019
2020# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05
2021
2022class HCI_Cmd_Read_Link_Quality(Packet):
2023 name = "HCI_Read_Link_Quality"
2024 fields_desc = [LEShortField("handle", 0)]
2025
2026
2027class HCI_Cmd_Read_RSSI(Packet):
2028 name = "HCI_Read_RSSI"
2029 fields_desc = [LEShortField("handle", 0)]
2030
2031
2032# 7.6 TESTING COMMANDS, the OGF is defined as 0x06
2033
2034class HCI_Cmd_Read_Loopback_Mode(Packet):
2035 name = "HCI_Read_Loopback_Mode"
2036
2037
2038class HCI_Cmd_Write_Loopback_Mode(Packet):
2039 name = "HCI_Write_Loopback_Mode"
2040 fields_desc = [ByteEnumField("loopback_mode", 0,
2041 {0: "no loopback",
2042 1: "enable local loopback",
2043 2: "enable remote loopback"})]
2044
2045
2046# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08
2047
2048class HCI_Cmd_LE_Read_Buffer_Size_V1(Packet):
2049 name = "HCI_LE_Read_Buffer_Size [v1]"
2050
2051
2052class HCI_Cmd_LE_Read_Buffer_Size_V2(Packet):
2053 name = "HCI_LE_Read_Buffer_Size [v2]"
2054
2055
2056class HCI_Cmd_LE_Read_Local_Supported_Features(Packet):
2057 name = "HCI_LE_Read_Local_Supported_Features"
2058
2059
2060class HCI_Cmd_LE_Set_Random_Address(Packet):
2061 name = "HCI_LE_Set_Random_Address"
2062 fields_desc = [LEMACField("address", None)]
2063
2064
2065class HCI_Cmd_LE_Set_Advertising_Parameters(Packet):
2066 name = "HCI_LE_Set_Advertising_Parameters"
2067 fields_desc = [LEShortField("interval_min", 0x0800),
2068 LEShortField("interval_max", 0x0800),
2069 ByteEnumField("adv_type", 0, {0: "ADV_IND", 1: "ADV_DIRECT_IND", 2: "ADV_SCAN_IND", 3: "ADV_NONCONN_IND", 4: "ADV_DIRECT_IND_LOW"}), # noqa: E501
2070 ByteEnumField("oatype", 0, {0: "public", 1: "random"}),
2071 ByteEnumField("datype", 0, {0: "public", 1: "random"}),
2072 LEMACField("daddr", None),
2073 ByteField("channel_map", 7),
2074 ByteEnumField("filter_policy", 0, {0: "all:all", 1: "connect:all scan:whitelist", 2: "connect:whitelist scan:all", 3: "all:whitelist"}), ] # noqa: E501
2075
2076
2077class HCI_Cmd_LE_Set_Advertising_Data(Packet):
2078 name = "HCI_LE_Set_Advertising_Data"
2079 fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"),
2080 PadField(
2081 PacketListField("data", [], EIR_Hdr,
2082 length_from=lambda pkt: pkt.len),
2083 align=31, padwith=b"\0"), ]
2084
2085
2086class HCI_Cmd_LE_Set_Scan_Response_Data(Packet):
2087 name = "HCI_LE_Set_Scan_Response_Data"
2088 fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"),
2089 StrLenField("data", "", length_from=lambda pkt: pkt.len), ]
2090
2091
2092class HCI_Cmd_LE_Set_Advertise_Enable(Packet):
2093 name = "HCI_LE_Set_Advertising_Enable"
2094 fields_desc = [ByteField("enable", 0)]
2095
2096
2097class HCI_Cmd_LE_Set_Scan_Parameters(Packet):
2098 name = "HCI_LE_Set_Scan_Parameters"
2099 fields_desc = [ByteEnumField("type", 0, {0: "passive", 1: "active"}),
2100 XLEShortField("interval", 16),
2101 XLEShortField("window", 16),
2102 ByteEnumField("atype", 0, {0: "public",
2103 1: "random",
2104 2: "rpa (pub)",
2105 3: "rpa (random)"}),
2106 ByteEnumField("policy", 0, {0: "all", 1: "whitelist"})]
2107
2108
2109class HCI_Cmd_LE_Set_Scan_Enable(Packet):
2110 name = "HCI_LE_Set_Scan_Enable"
2111 fields_desc = [ByteField("enable", 1),
2112 ByteField("filter_dups", 1), ]
2113
2114
2115class HCI_Cmd_LE_Create_Connection(Packet):
2116 name = "HCI_LE_Create_Connection"
2117 fields_desc = [LEShortField("interval", 96),
2118 LEShortField("window", 48),
2119 ByteEnumField("filter", 0, {0: "address"}),
2120 ByteEnumField("patype", 0, {0: "public", 1: "random"}),
2121 LEMACField("paddr", None),
2122 ByteEnumField("atype", 0, {0: "public", 1: "random"}),
2123 LEShortField("min_interval", 40),
2124 LEShortField("max_interval", 56),
2125 LEShortField("latency", 0),
2126 LEShortField("timeout", 42),
2127 LEShortField("min_ce", 0),
2128 LEShortField("max_ce", 0), ]
2129
2130
2131class HCI_Cmd_LE_Create_Connection_Cancel(Packet):
2132 name = "HCI_LE_Create_Connection_Cancel"
2133
2134
2135class HCI_Cmd_LE_Read_Filter_Accept_List_Size(Packet):
2136 name = "HCI_LE_Read_Filter_Accept_List_Size"
2137
2138
2139class HCI_Cmd_LE_Clear_Filter_Accept_List(Packet):
2140 name = "HCI_LE_Clear_Filter_Accept_List"
2141
2142
2143class HCI_Cmd_LE_Add_Device_To_Filter_Accept_List(Packet):
2144 name = "HCI_LE_Add_Device_To_Filter_Accept_List"
2145 fields_desc = [ByteEnumField("address_type", 0, {0: "public",
2146 1: "random",
2147 0xff: "anonymous"}),
2148 LEMACField("address", None)]
2149
2150
2151class HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List(HCI_Cmd_LE_Add_Device_To_Filter_Accept_List): # noqa: E501
2152 name = "HCI_LE_Remove_Device_From_Filter_Accept_List"
2153
2154
2155class HCI_Cmd_LE_Connection_Update(Packet):
2156 name = "HCI_LE_Connection_Update"
2157 fields_desc = [XLEShortField("handle", 0),
2158 XLEShortField("min_interval", 0),
2159 XLEShortField("max_interval", 0),
2160 XLEShortField("latency", 0),
2161 XLEShortField("timeout", 0),
2162 LEShortField("min_ce", 0),
2163 LEShortField("max_ce", 0xffff), ]
2164
2165
2166class HCI_Cmd_LE_Read_Remote_Features(Packet):
2167 name = "HCI_LE_Read_Remote_Features"
2168 fields_desc = [LEShortField("handle", 64)]
2169
2170
2171class HCI_Cmd_LE_Enable_Encryption(Packet):
2172 name = "HCI_LE_Enable_Encryption"
2173 fields_desc = [LEShortField("handle", 0),
2174 StrFixedLenField("rand", None, 8),
2175 XLEShortField("ediv", 0),
2176 StrFixedLenField("ltk", b'\x00' * 16, 16), ]
2177
2178
2179class HCI_Cmd_LE_Long_Term_Key_Request_Reply(Packet):
2180 name = "HCI_LE_Long_Term_Key_Request_Reply"
2181 fields_desc = [LEShortField("handle", 0),
2182 StrFixedLenField("ltk", b'\x00' * 16, 16), ]
2183
2184
2185class HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply(Packet):
2186 name = "HCI_LE_Long_Term_Key_Request _Negative_Reply"
2187 fields_desc = [LEShortField("handle", 0), ]
2188
2189
2190class HCI_Event_Hdr(Packet):
2191 name = "HCI Event header"
2192 fields_desc = [XByteField("code", 0),
2193 LenField("len", None, fmt="B"), ]
2194
2195 def answers(self, other):
2196 if HCI_Command_Hdr not in other:
2197 return False
2198
2199 # Delegate answers to event types
2200 return self.payload.answers(other)
2201
2202
2203class HCI_Event_Inquiry_Complete(Packet):
2204 """
2205 7.7.1 Inquiry Complete event
2206 """
2207 name = "HCI_Inquiry_Complete"
2208 fields_desc = [
2209 ByteEnumField('status', 0, _bluetooth_error_codes)
2210 ]
2211
2212
2213class HCI_Event_Inquiry_Result(Packet):
2214 """
2215 7.7.2 Inquiry Result event
2216 """
2217 name = "HCI_Inquiry_Result"
2218 fields_desc = [
2219 ByteField("num_response", 0x00),
2220 FieldListField("addr", None, LEMACField("addr", None),
2221 count_from=lambda p: p.num_response),
2222 FieldListField("page_scan_repetition_mode", None,
2223 ByteField("page_scan_repetition_mode", 0),
2224 count_from=lambda p: p.num_response),
2225 FieldListField("reserved", None, LEShortField("reserved", 0),
2226 count_from=lambda p: p.num_response),
2227 FieldListField("device_class", None, XLE3BytesField("device_class", 0),
2228 count_from=lambda p: p.num_response),
2229 FieldListField("clock_offset", None, LEShortField("clock_offset", 0),
2230 count_from=lambda p: p.num_response)
2231 ]
2232
2233
2234class HCI_Event_Connection_Complete(Packet):
2235 """
2236 7.7.3 Connection Complete event
2237 """
2238 name = "HCI_Connection_Complete"
2239 fields_desc = [ByteEnumField('status', 0, _bluetooth_error_codes),
2240 LEShortField("handle", 0x0100),
2241 LEMACField("bd_addr", None),
2242 ByteEnumField("link_type", 0, {0: "SCO connection",
2243 1: "ACL connection", }),
2244 ByteEnumField("encryption_enabled", 0,
2245 {0: "link level encryption disabled",
2246 1: "link level encryption enabled", }), ]
2247
2248
2249class HCI_Event_Disconnection_Complete(Packet):
2250 """
2251 7.7.5 Disconnection Complete event
2252 """
2253 name = "HCI_Disconnection_Complete"
2254 fields_desc = [ByteEnumField("status", 0, _bluetooth_error_codes),
2255 LEShortField("handle", 0),
2256 XByteField("reason", 0), ]
2257
2258
2259class HCI_Event_Remote_Name_Request_Complete(Packet):
2260 """
2261 7.7.7 Remote Name Request Complete event
2262 """
2263 name = "HCI_Remote_Name_Request_Complete"
2264 fields_desc = [ByteEnumField("status", 0, _bluetooth_error_codes),
2265 LEMACField("bd_addr", None),
2266 StrFixedLenField("remote_name", b"\x00", 248), ]
2267
2268
2269class HCI_Event_Encryption_Change(Packet):
2270 """
2271 7.7.8 Encryption Change event
2272 """
2273 name = "HCI_Encryption_Change"
2274 fields_desc = [ByteEnumField("status", 0, {0: "change has occurred"}),
2275 LEShortField("handle", 0),
2276 ByteEnumField("enabled", 0, {0: "OFF", 1: "ON (LE)", 2: "ON (BR/EDR)"}), ] # noqa: E501
2277
2278
2279class HCI_Event_Read_Remote_Supported_Features_Complete(Packet):
2280 """
2281 7.7.11 Read Remote Supported Features Complete event
2282 """
2283 name = "HCI_Read_Remote_Supported_Features_Complete"
2284 fields_desc = [
2285 ByteEnumField('status', 0, _bluetooth_error_codes),
2286 LEShortField('handle', 0),
2287 FlagsField('lmp_features', 0, -64, _bluetooth_features)
2288 ]
2289
2290
2291class HCI_Event_Read_Remote_Version_Information_Complete(Packet):
2292 """
2293 7.7.12 Read Remote Version Information Complete event
2294 """
2295 name = "HCI_Read_Remote_Version_Information"
2296 fields_desc = [
2297 ByteEnumField('status', 0, _bluetooth_error_codes),
2298 LEShortField('handle', 0),
2299 ByteField('version', 0x00),
2300 LEShortField('manufacturer_name', 0x0000),
2301 LEShortField('subversion', 0x0000)
2302 ]
2303
2304
2305class HCI_Event_Command_Complete(Packet):
2306 """
2307 7.7.14 Command Complete event
2308 """
2309 name = "HCI_Command_Complete"
2310 fields_desc = [ByteField("number", 0),
2311 XLEShortField("opcode", 0),
2312 ByteEnumField("status", 0, _bluetooth_error_codes)]
2313
2314 def answers(self, other):
2315 if HCI_Command_Hdr not in other:
2316 return False
2317
2318 return other[HCI_Command_Hdr].opcode == self.opcode
2319
2320
2321class HCI_Event_Command_Status(Packet):
2322 """
2323 7.7.15 Command Status event
2324 """
2325 name = "HCI_Command_Status"
2326 fields_desc = [ByteEnumField("status", 0, {0: "pending"}),
2327 ByteField("number", 0),
2328 XLEShortField("opcode", None), ]
2329
2330 def answers(self, other):
2331 if HCI_Command_Hdr not in other:
2332 return False
2333
2334 return other[HCI_Command_Hdr].opcode == self.opcode
2335
2336
2337class HCI_Event_Number_Of_Completed_Packets(Packet):
2338 """
2339 7.7.19 Number Of Completed Packets event
2340 """
2341 name = "HCI_Number_Of_Completed_Packets"
2342 fields_desc = [ByteField("num_handles", 0),
2343 FieldListField("connection_handle_list", None,
2344 LEShortField("connection_handle", 0),
2345 count_from=lambda p: p.num_handles),
2346 FieldListField("num_completed_packets_list", None,
2347 LEShortField("num_completed_packets", 0),
2348 count_from=lambda p: p.num_handles)]
2349
2350
2351class HCI_Event_Link_Key_Request(Packet):
2352 """
2353 7.7.23 Link Key Request event
2354 """
2355 name = 'HCI_Link_Key_Request'
2356 fields_desc = [
2357 LEMACField('bd_addr', None)
2358 ]
2359
2360
2361class HCI_Event_Inquiry_Result_With_Rssi(Packet):
2362 """
2363 7.7.33 Inquiry Result with RSSI event
2364 """
2365 name = "HCI_Inquiry_Result_with_RSSI"
2366 fields_desc = [
2367 ByteField("num_response", 0x00),
2368 FieldListField("bd_addr", None, LEMACField,
2369 count_from=lambda p: p.num_response),
2370 FieldListField("page_scan_repetition_mode", None, ByteField,
2371 count_from=lambda p: p.num_response),
2372 FieldListField("reserved", None, LEShortField,
2373 count_from=lambda p: p.num_response),
2374 FieldListField("device_class", None, XLE3BytesField,
2375 count_from=lambda p: p.num_response),
2376 FieldListField("clock_offset", None, LEShortField,
2377 count_from=lambda p: p.num_response),
2378 FieldListField("rssi", None, SignedByteField,
2379 count_from=lambda p: p.num_response)
2380 ]
2381
2382
2383class HCI_Event_Read_Remote_Extended_Features_Complete(Packet):
2384 """
2385 7.7.34 Read Remote Extended Features Complete event
2386 """
2387 name = "HCI_Read_Remote_Extended_Features_Complete"
2388 fields_desc = [
2389 ByteEnumField('status', 0, _bluetooth_error_codes),
2390 LEShortField('handle', 0),
2391 ByteField('page', 0x00),
2392 ByteField('max_page', 0x00),
2393 XLELongField('extended_features', 0)
2394 ]
2395
2396
2397class HCI_Event_Extended_Inquiry_Result(Packet):
2398 """
2399 7.7.38 Extended Inquiry Result event
2400 """
2401 name = "HCI_Extended_Inquiry_Result"
2402 fields_desc = [
2403 ByteField('num_response', 0x01),
2404 LEMACField('bd_addr', None),
2405 ByteField('page_scan_repetition_mode', 0x00),
2406 ByteField('reserved', 0x00),
2407 XLE3BytesField('device_class', 0x000000),
2408 LEShortField('clock_offset', 0x0000),
2409 SignedByteField('rssi', 0x00),
2410 HCI_Extended_Inquiry_Response,
2411 ]
2412
2413
2414class HCI_Event_IO_Capability_Response(Packet):
2415 """
2416 7.7.41 IO Capability Response event
2417 """
2418 name = "HCI_IO_Capability_Response"
2419 fields_desc = [
2420 LEMACField('bd_addr', None),
2421 ByteField('io_capability', 0x00),
2422 ByteField('oob_data_present', 0x00),
2423 ByteField('authentication_requirements', 0x00)
2424 ]
2425
2426
2427class HCI_Event_LE_Meta(Packet):
2428 """
2429 7.7.65 LE Meta event
2430 """
2431 name = "HCI_LE_Meta"
2432 fields_desc = [ByteEnumField("event", 0, {
2433 0x01: "connection_complete",
2434 0x02: "advertising_report",
2435 0x03: "connection_update_complete",
2436 0x04: "read_remote_features_page_0_complete",
2437 0x05: "long_term_key_request",
2438 0x06: "remote_connection_parameter_request",
2439 0x07: "data_length_change",
2440 0x08: "read_local_p256_public_key_complete",
2441 0x09: "generate_dhkey_complete",
2442 0x0a: "enhanced_connection_complete_v1",
2443 0x0b: "directed_advertising_report",
2444 0x0c: "phy_update_complete",
2445 0x0d: "extended_advertising_report",
2446 0x29: "enhanced_connection_complete_v2"
2447 }), ]
2448
2449 def answers(self, other):
2450 if not self.payload:
2451 return False
2452
2453 # Delegate answers to payload
2454 return self.payload.answers(other)
2455
2456
2457class HCI_Cmd_Complete_Read_Local_Name(Packet):
2458 """
2459 7.3.12 Read Local Name command complete
2460 """
2461 name = 'Read Local Name command complete'
2462 fields_desc = [StrFixedLenField('local_name', '', length=248)]
2463
2464
2465class HCI_Cmd_Complete_Read_Local_Version_Information(Packet):
2466 """
2467 7.4.1 Read Local Version Information command complete
2468 """
2469 name = 'Read Local Version Information'
2470 fields_desc = [
2471 ByteEnumField('hci_version', 0, _bluetooth_core_specification_versions),
2472 LEShortField('hci_subversion', 0),
2473 ByteEnumField('lmp_version', 0, _bluetooth_core_specification_versions),
2474 LEShortEnumField('company_identifier', 0, BLUETOOTH_CORE_COMPANY_IDENTIFIERS),
2475 LEShortField('lmp_subversion', 0)]
2476
2477
2478class HCI_Cmd_Complete_Read_Local_Extended_Features(Packet):
2479 """
2480 7.4.4 Read Local Extended Features command complete
2481 """
2482 name = 'Read Local Extended Features command complete'
2483 fields_desc = [
2484 ByteField('page', 0x00),
2485 ByteField('max_page', 0x00),
2486 XLELongField('extended_features', 0)
2487 ]
2488
2489
2490class HCI_Cmd_Complete_Read_BD_Addr(Packet):
2491 """
2492 7.4.6 Read BD_ADDR command complete
2493 """
2494 name = "Read BD Addr"
2495 fields_desc = [LEMACField("addr", None), ]
2496
2497
2498class HCI_Cmd_Complete_LE_Read_White_List_Size(Packet):
2499 name = "LE Read White List Size"
2500 fields_desc = [ByteField("status", 0),
2501 ByteField("size", 0), ]
2502
2503
2504class HCI_LE_Meta_Connection_Complete(Packet):
2505 name = "Connection Complete"
2506 fields_desc = [ByteEnumField("status", 0, {0: "success"}),
2507 LEShortField("handle", 0),
2508 ByteEnumField("role", 0, {0: "master"}),
2509 ByteEnumField("patype", 0, {0: "public", 1: "random"}),
2510 LEMACField("paddr", None),
2511 LEShortField("interval", 54),
2512 LEShortField("latency", 0),
2513 LEShortField("supervision", 42),
2514 XByteField("clock_latency", 5), ]
2515
2516 def answers(self, other):
2517 if HCI_Cmd_LE_Create_Connection not in other:
2518 return False
2519
2520 return (other[HCI_Cmd_LE_Create_Connection].patype == self.patype and
2521 other[HCI_Cmd_LE_Create_Connection].paddr == self.paddr)
2522
2523
2524class HCI_LE_Meta_Connection_Update_Complete(Packet):
2525 name = "Connection Update Complete"
2526 fields_desc = [ByteEnumField("status", 0, {0: "success"}),
2527 LEShortField("handle", 0),
2528 LEShortField("interval", 54),
2529 LEShortField("latency", 0),
2530 LEShortField("timeout", 42), ]
2531
2532
2533class HCI_LE_Meta_Advertising_Report(Packet):
2534 name = "Advertising Report"
2535 fields_desc = [ByteEnumField("type", 0, {0: "conn_und", 4: "scan_rsp"}),
2536 ByteEnumField("atype", 0, {0: "public", 1: "random"}),
2537 LEMACField("addr", None),
2538 FieldLenField("len", None, length_of="data", fmt="B"),
2539 PacketListField("data", [], EIR_Hdr,
2540 length_from=lambda pkt: pkt.len),
2541 SignedByteField("rssi", 0)]
2542
2543 def extract_padding(self, s):
2544 return '', s
2545
2546
2547class HCI_LE_Meta_Advertising_Reports(Packet):
2548 name = "Advertising Reports"
2549 fields_desc = [FieldLenField("len", None, count_of="reports", fmt="B"),
2550 PacketListField("reports", None,
2551 HCI_LE_Meta_Advertising_Report,
2552 count_from=lambda pkt: pkt.len)]
2553
2554
2555class HCI_LE_Meta_Long_Term_Key_Request(Packet):
2556 name = "Long Term Key Request"
2557 fields_desc = [LEShortField("handle", 0),
2558 StrFixedLenField("rand", None, 8),
2559 XLEShortField("ediv", 0), ]
2560
2561
2562class HCI_LE_Meta_Extended_Advertising_Report(Packet):
2563 name = "Extended Advertising Report"
2564 fields_desc = [
2565 BitField("reserved0", 0, 1),
2566 BitEnumField("data_status", 0, 2, {
2567 0b00: "complete",
2568 0b01: "incomplete",
2569 0b10: "incomplete_truncated",
2570 0b11: "reserved"
2571 }),
2572 BitField("legacy", 0, 1),
2573 BitField("scan_response", 0, 1),
2574 BitField("directed", 0, 1),
2575 BitField("scannable", 0, 1),
2576 BitField("connectable", 0, 1),
2577 ByteField("reserved", 0),
2578 ByteEnumField("address_type", 0, {
2579 0x00: "public_device_address",
2580 0x01: "random_device_address",
2581 0x02: "public_identity_address",
2582 0x03: "random_identity_address",
2583 0xff: "anonymous"
2584 }),
2585 LEMACField('address', None),
2586 ByteEnumField("primary_phy", 0, {
2587 0x01: "le_1m",
2588 0x03: "le_coded_s8",
2589 0x04: "le_coded_s2"
2590 }),
2591 ByteEnumField("secondary_phy", 0, {
2592 0x01: "le_1m",
2593 0x02: "le_2m",
2594 0x03: "le_coded_s8",
2595 0x04: "le_coded_s2"
2596 }),
2597 ByteField("advertising_sid", 0xff),
2598 ByteField("tx_power", 0x7f),
2599 SignedByteField("rssi", 0x00),
2600 LEShortField("periodic_advertising_interval", 0x0000),
2601 ByteEnumField("direct_address_type", 0, {
2602 0x00: "public_device_address",
2603 0x01: "non_resolvable_private_address",
2604 0x02: "resolvable_private_address_resolved_0",
2605 0x03: "resolvable_private_address_resolved_1",
2606 0xfe: "resolvable_private_address_unable_resolve"}),
2607 LEMACField("direct_address", None),
2608 FieldLenField("data_length", None, length_of="data", fmt="B"),
2609 PacketListField("data", [], EIR_Hdr,
2610 length_from=lambda pkt: pkt.data_length),
2611 ]
2612
2613 def extract_padding(self, s):
2614 return '', s
2615
2616
2617class HCI_LE_Meta_Extended_Advertising_Reports(Packet):
2618 name = "Extended Advertising Reports"
2619 fields_desc = [FieldLenField("num_reports", None, count_of="reports", fmt="B"),
2620 PacketListField("reports", None,
2621 HCI_LE_Meta_Extended_Advertising_Report,
2622 count_from=lambda pkt: pkt.num_reports)]
2623
2624
2625bind_layers(HCI_PHDR_Hdr, HCI_Hdr)
2626
2627bind_layers(HCI_Hdr, HCI_Command_Hdr, type=1)
2628bind_layers(HCI_Hdr, HCI_ACL_Hdr, type=2)
2629bind_layers(HCI_Hdr, HCI_Event_Hdr, type=4)
2630bind_layers(HCI_Hdr, conf.raw_layer,)
2631
2632conf.l2types.register(DLT_BLUETOOTH_HCI_H4, HCI_Hdr)
2633conf.l2types.register(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, HCI_PHDR_Hdr)
2634
2635
2636# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01
2637bind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry, ogf=0x01, ocf=0x0001)
2638bind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry_Cancel, ogf=0x01, ocf=0x0002)
2639bind_layers(HCI_Command_Hdr, HCI_Cmd_Periodic_Inquiry_Mode, ogf=0x01, ocf=0x0003)
2640bind_layers(HCI_Command_Hdr, HCI_Cmd_Exit_Peiodic_Inquiry_Mode, ogf=0x01, ocf=0x0004)
2641bind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection, ogf=0x01, ocf=0x0005)
2642bind_layers(HCI_Command_Hdr, HCI_Cmd_Disconnect, ogf=0x01, ocf=0x0006)
2643bind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection_Cancel, ogf=0x01, ocf=0x0008)
2644bind_layers(HCI_Command_Hdr, HCI_Cmd_Accept_Connection_Request, ogf=0x01, ocf=0x0009)
2645bind_layers(HCI_Command_Hdr, HCI_Cmd_Reject_Connection_Response, ogf=0x01, ocf=0x000a)
2646bind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Reply, ogf=0x01, ocf=0x000b)
2647bind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Negative_Reply,
2648 ogf=0x01, ocf=0x000c)
2649bind_layers(HCI_Command_Hdr, HCI_Cmd_PIN_Code_Request_Reply, ogf=0x01, ocf=0x000d)
2650bind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Packet_Type,
2651 ogf=0x01, ocf=0x000f)
2652bind_layers(HCI_Command_Hdr, HCI_Cmd_Authentication_Requested, ogf=0x01, ocf=0x0011)
2653bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Connection_Encryption, ogf=0x01, ocf=0x0013)
2654bind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Link_Key, ogf=0x01, ocf=0x0017)
2655bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request, ogf=0x01, ocf=0x0019)
2656bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request_Cancel, ogf=0x01, ocf=0x001a)
2657bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Supported_Features,
2658 ogf=0x01, ocf=0x001b)
2659bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Extended_Features,
2660 ogf=0x01, ocf=0x001c)
2661bind_layers(HCI_Command_Hdr, HCI_Cmd_IO_Capability_Request_Reply, ogf=0x01, ocf=0x002b)
2662bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Reply,
2663 ogf=0x01, ocf=0x002c)
2664bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Negative_Reply,
2665 ogf=0x01, ocf=0x002d)
2666bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Reply, ogf=0x01, ocf=0x002e)
2667bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Negative_Reply,
2668 ogf=0x01, ocf=0x002f)
2669bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Reply,
2670 ogf=0x01, ocf=0x0030)
2671bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply,
2672 ogf=0x01, ocf=0x0033)
2673
2674# 7.2 Link Policy commands, the OGF is defined as 0x02
2675bind_layers(HCI_Command_Hdr, HCI_Cmd_Hold_Mode, ogf=0x02, ocf=0x0001)
2676
2677# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03
2678bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Mask, ogf=0x03, ocf=0x0001)
2679bind_layers(HCI_Command_Hdr, HCI_Cmd_Reset, ogf=0x03, ocf=0x0003)
2680bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Filter, ogf=0x03, ocf=0x0005)
2681bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Local_Name, ogf=0x03, ocf=0x0013)
2682bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Name, ogf=0x03, ocf=0x0014)
2683bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Connect_Accept_Timeout, ogf=0x03, ocf=0x0016)
2684bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Extended_Inquiry_Response, ogf=0x03, ocf=0x0052) # noqa: E501
2685bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_LE_Host_Support, ogf=0x03, ocf=0x006c)
2686bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_LE_Host_Support, ogf=0x03, ocf=0x006d)
2687
2688# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04
2689bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Version_Information, ogf=0x04, ocf=0x0001) # noqa: E501
2690bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Extended_Features, ogf=0x04, ocf=0x0004)
2691bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_BD_Addr, ogf=0x04, ocf=0x0009)
2692
2693# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05
2694bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Link_Quality, ogf=0x05, ocf=0x0003)
2695bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_RSSI, ogf=0x05, ocf=0x0005)
2696
2697# 7.6 TESTING COMMANDS, the OGF is defined as 0x06
2698bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Loopback_Mode, ogf=0x06, ocf=0x0001)
2699bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Loopback_Mode, ogf=0x06, ocf=0x0002)
2700
2701# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08
2702bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V1, ogf=0x08, ocf=0x0002)
2703bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V2, ogf=0x08, ocf=0x0060)
2704bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Local_Supported_Features,
2705 ogf=0x08, ocf=0x0003)
2706bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Random_Address, ogf=0x08, ocf=0x0005)
2707bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Parameters, ogf=0x08, ocf=0x0006) # noqa: E501
2708bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Data, ogf=0x08, ocf=0x0008)
2709bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Response_Data, ogf=0x08, ocf=0x0009)
2710bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertise_Enable, ogf=0x08, ocf=0x000a)
2711bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Parameters, ogf=0x08, ocf=0x000b)
2712bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Enable, ogf=0x08, ocf=0x000c)
2713bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection, ogf=0x08, ocf=0x000d)
2714bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection_Cancel, ogf=0x08, ocf=0x000e) # noqa: E501
2715bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Filter_Accept_List_Size,
2716 ogf=0x08, ocf=0x000f)
2717bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Clear_Filter_Accept_List, ogf=0x08, ocf=0x0010)
2718bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Add_Device_To_Filter_Accept_List, ogf=0x08, ocf=0x0011) # noqa: E501
2719bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List, ogf=0x08, ocf=0x0012) # noqa: E501
2720bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Connection_Update, ogf=0x08, ocf=0x0013)
2721bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Remote_Features, ogf=0x08, ocf=0x0016) # noqa: E501
2722bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Enable_Encryption, ogf=0x08, ocf=0x0019) # noqa: E501
2723bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Reply, ogf=0x08, ocf=0x001a) # noqa: E501
2724bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply, ogf=0x08, ocf=0x001b) # noqa: E501
2725
2726# 7.7 EVENTS
2727bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Complete, code=0x01)
2728bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result, code=0x02)
2729bind_layers(HCI_Event_Hdr, HCI_Event_Connection_Complete, code=0x03)
2730bind_layers(HCI_Event_Hdr, HCI_Event_Disconnection_Complete, code=0x05)
2731bind_layers(HCI_Event_Hdr, HCI_Event_Remote_Name_Request_Complete, code=0x07)
2732bind_layers(HCI_Event_Hdr, HCI_Event_Encryption_Change, code=0x08)
2733bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Supported_Features_Complete, code=0x0b)
2734bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Version_Information_Complete, code=0x0c) # noqa: E501
2735bind_layers(HCI_Event_Hdr, HCI_Event_Command_Complete, code=0x0e)
2736bind_layers(HCI_Event_Hdr, HCI_Event_Command_Status, code=0x0f)
2737bind_layers(HCI_Event_Hdr, HCI_Event_Number_Of_Completed_Packets, code=0x13)
2738bind_layers(HCI_Event_Hdr, HCI_Event_Link_Key_Request, code=0x17)
2739bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result_With_Rssi, code=0x22)
2740bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Extended_Features_Complete, code=0x23)
2741bind_layers(HCI_Event_Hdr, HCI_Event_Extended_Inquiry_Result, code=0x2f)
2742bind_layers(HCI_Event_Hdr, HCI_Event_IO_Capability_Response, code=0x32)
2743bind_layers(HCI_Event_Hdr, HCI_Event_LE_Meta, code=0x3e)
2744
2745bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Name, opcode=0x0c14) # noqa: E501
2746bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Version_Information, opcode=0x1001) # noqa: E501
2747bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Extended_Features, opcode=0x1004) # noqa: E501
2748bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_BD_Addr, opcode=0x1009) # noqa: E501
2749bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_LE_Read_White_List_Size, opcode=0x200f) # noqa: E501
2750
2751bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Complete, event=0x01)
2752bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Advertising_Reports, event=0x02)
2753bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Update_Complete, event=0x03)
2754bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Long_Term_Key_Request, event=0x05)
2755bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Extended_Advertising_Reports, event=0x0d)
2756
2757bind_layers(EIR_Hdr, EIR_Flags, type=0x01)
2758bind_layers(EIR_Hdr, EIR_IncompleteList16BitServiceUUIDs, type=0x02)
2759bind_layers(EIR_Hdr, EIR_CompleteList16BitServiceUUIDs, type=0x03)
2760bind_layers(EIR_Hdr, EIR_IncompleteList32BitServiceUUIDs, type=0x04)
2761bind_layers(EIR_Hdr, EIR_CompleteList32BitServiceUUIDs, type=0x05)
2762bind_layers(EIR_Hdr, EIR_IncompleteList128BitServiceUUIDs, type=0x06)
2763bind_layers(EIR_Hdr, EIR_CompleteList128BitServiceUUIDs, type=0x07)
2764bind_layers(EIR_Hdr, EIR_ShortenedLocalName, type=0x08)
2765bind_layers(EIR_Hdr, EIR_CompleteLocalName, type=0x09)
2766bind_layers(EIR_Hdr, EIR_Device_ID, type=0x10)
2767bind_layers(EIR_Hdr, EIR_TX_Power_Level, type=0x0a)
2768bind_layers(EIR_Hdr, EIR_ClassOfDevice, type=0x0d)
2769bind_layers(EIR_Hdr, EIR_SecureSimplePairingHashC192, type=0x0e)
2770bind_layers(EIR_Hdr, EIR_SecureSimplePairingRandomizerR192, type=0x0f)
2771bind_layers(EIR_Hdr, EIR_SecurityManagerOOBFlags, type=0x11)
2772bind_layers(EIR_Hdr, EIR_PeripheralConnectionIntervalRange, type=0x12)
2773bind_layers(EIR_Hdr, EIR_ServiceSolicitation16BitUUID, type=0x14)
2774bind_layers(EIR_Hdr, EIR_ServiceSolicitation128BitUUID, type=0x15)
2775bind_layers(EIR_Hdr, EIR_ServiceData16BitUUID, type=0x16)
2776bind_layers(EIR_Hdr, EIR_PublicTargetAddress, type=0x17)
2777bind_layers(EIR_Hdr, EIR_Appearance, type=0x19)
2778bind_layers(EIR_Hdr, EIR_AdvertisingInterval, type=0x1a)
2779bind_layers(EIR_Hdr, EIR_LEBluetoothDeviceAddress, type=0x1b)
2780bind_layers(EIR_Hdr, EIR_ServiceData32BitUUID, type=0x20)
2781bind_layers(EIR_Hdr, EIR_ServiceData128BitUUID, type=0x21)
2782bind_layers(EIR_Hdr, EIR_URI, type=0x24)
2783bind_layers(EIR_Hdr, EIR_Manufacturer_Specific_Data, type=0xff)
2784bind_layers(EIR_Hdr, EIR_Raw)
2785
2786bind_layers(HCI_ACL_Hdr, L2CAP_Hdr,)
2787bind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=1)
2788bind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=5) # LE L2CAP Signaling Channel
2789bind_layers(L2CAP_CmdHdr, L2CAP_CmdRej, code=1)
2790bind_layers(L2CAP_CmdHdr, L2CAP_ConnReq, code=2)
2791bind_layers(L2CAP_CmdHdr, L2CAP_ConnResp, code=3)
2792bind_layers(L2CAP_CmdHdr, L2CAP_ConfReq, code=4)
2793bind_layers(L2CAP_CmdHdr, L2CAP_ConfResp, code=5)
2794bind_layers(L2CAP_CmdHdr, L2CAP_DisconnReq, code=6)
2795bind_layers(L2CAP_CmdHdr, L2CAP_DisconnResp, code=7)
2796bind_layers(L2CAP_CmdHdr, L2CAP_EchoReq, code=8)
2797bind_layers(L2CAP_CmdHdr, L2CAP_EchoResp, code=9)
2798bind_layers(L2CAP_CmdHdr, L2CAP_InfoReq, code=10)
2799bind_layers(L2CAP_CmdHdr, L2CAP_InfoResp, code=11)
2800bind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Request, code=12)
2801bind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Response, code=13)
2802bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Request, code=14)
2803bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Response, code=15)
2804bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Request, code=16)
2805bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Response, code=17)
2806bind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Request, code=18)
2807bind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Response, code=19)
2808bind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Request, code=20)
2809bind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Response, code=21)
2810bind_layers(L2CAP_CmdHdr, L2CAP_Flow_Control_Credit_Ind, code=22)
2811bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Request, code=23)
2812bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Response, code=24)
2813bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Request, code=25)
2814bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Response, code=26)
2815bind_layers(L2CAP_Hdr, ATT_Hdr, cid=4)
2816bind_layers(ATT_Hdr, ATT_Error_Response, opcode=0x1)
2817bind_layers(ATT_Hdr, ATT_Exchange_MTU_Request, opcode=0x2)
2818bind_layers(ATT_Hdr, ATT_Exchange_MTU_Response, opcode=0x3)
2819bind_layers(ATT_Hdr, ATT_Find_Information_Request, opcode=0x4)
2820bind_layers(ATT_Hdr, ATT_Find_Information_Response, opcode=0x5)
2821bind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Request, opcode=0x6)
2822bind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Response, opcode=0x7)
2823bind_layers(ATT_Hdr, ATT_Read_By_Type_Request_128bit, opcode=0x8)
2824bind_layers(ATT_Hdr, ATT_Read_By_Type_Request, opcode=0x8)
2825bind_layers(ATT_Hdr, ATT_Read_By_Type_Response, opcode=0x9)
2826bind_layers(ATT_Hdr, ATT_Read_Request, opcode=0xa)
2827bind_layers(ATT_Hdr, ATT_Read_Response, opcode=0xb)
2828bind_layers(ATT_Hdr, ATT_Read_Blob_Request, opcode=0xc)
2829bind_layers(ATT_Hdr, ATT_Read_Blob_Response, opcode=0xd)
2830bind_layers(ATT_Hdr, ATT_Read_Multiple_Request, opcode=0xe)
2831bind_layers(ATT_Hdr, ATT_Read_Multiple_Response, opcode=0xf)
2832bind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Request, opcode=0x10)
2833bind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Response, opcode=0x11)
2834bind_layers(ATT_Hdr, ATT_Write_Request, opcode=0x12)
2835bind_layers(ATT_Hdr, ATT_Write_Response, opcode=0x13)
2836bind_layers(ATT_Hdr, ATT_Prepare_Write_Request, opcode=0x16)
2837bind_layers(ATT_Hdr, ATT_Prepare_Write_Response, opcode=0x17)
2838bind_layers(ATT_Hdr, ATT_Execute_Write_Request, opcode=0x18)
2839bind_layers(ATT_Hdr, ATT_Execute_Write_Response, opcode=0x19)
2840bind_layers(ATT_Hdr, ATT_Write_Command, opcode=0x52)
2841bind_layers(ATT_Hdr, ATT_Handle_Value_Notification, opcode=0x1b)
2842bind_layers(ATT_Hdr, ATT_Handle_Value_Indication, opcode=0x1d)
2843bind_layers(L2CAP_Hdr, SM_Hdr, cid=6)
2844bind_layers(SM_Hdr, SM_Pairing_Request, sm_command=0x01)
2845bind_layers(SM_Hdr, SM_Pairing_Response, sm_command=0x02)
2846bind_layers(SM_Hdr, SM_Confirm, sm_command=0x03)
2847bind_layers(SM_Hdr, SM_Random, sm_command=0x04)
2848bind_layers(SM_Hdr, SM_Failed, sm_command=0x05)
2849bind_layers(SM_Hdr, SM_Encryption_Information, sm_command=0x06)
2850bind_layers(SM_Hdr, SM_Master_Identification, sm_command=0x07)
2851bind_layers(SM_Hdr, SM_Identity_Information, sm_command=0x08)
2852bind_layers(SM_Hdr, SM_Identity_Address_Information, sm_command=0x09)
2853bind_layers(SM_Hdr, SM_Signing_Information, sm_command=0x0a)
2854bind_layers(SM_Hdr, SM_Security_Request, sm_command=0x0b)
2855bind_layers(SM_Hdr, SM_Public_Key, sm_command=0x0c)
2856bind_layers(SM_Hdr, SM_DHKey_Check, sm_command=0x0d)
2857
2858
2859###############
2860# HCI Monitor #
2861###############
2862
2863
2864# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L27
2865class HCI_Mon_Hdr(Packet):
2866 name = 'Bluetooth Linux Monitor Transport Header'
2867 fields_desc = [
2868 LEShortEnumField('opcode', None, {
2869 0: "New index",
2870 1: "Delete index",
2871 2: "Command pkt",
2872 3: "Event pkt",
2873 4: "ACL TX pkt",
2874 5: "ACL RX pkt",
2875 6: "SCO TX pkt",
2876 7: "SCO RX pkt",
2877 8: "Open index",
2878 9: "Close index",
2879 10: "Index info",
2880 11: "Vendor diag",
2881 12: "System note",
2882 13: "User logging",
2883 14: "Ctrl open",
2884 15: "Ctrl close",
2885 16: "Ctrl command",
2886 17: "Ctrl event",
2887 18: "ISO TX pkt",
2888 19: "ISO RX pkt",
2889 }),
2890 LEShortField('adapter_id', None),
2891 LEShortField('len', None)
2892 ]
2893
2894
2895# https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LINUX_MONITOR.html
2896class HCI_Mon_Pcap_Hdr(HCI_Mon_Hdr):
2897 name = 'Bluetooth Linux Monitor Transport Pcap Header'
2898 fields_desc = [
2899 ShortField('adapter_id', None),
2900 ShortField('opcode', None)
2901 ]
2902
2903
2904class HCI_Mon_New_Index(Packet):
2905 name = 'Bluetooth Linux Monitor Transport New Index Packet'
2906 fields_desc = [
2907 ByteEnumField('bus', 0, {
2908 0x00: "BR/EDR",
2909 0x01: "AMP"
2910 }),
2911 ByteEnumField('type', 0, {
2912 0x00: "Virtual",
2913 0x01: "USB",
2914 0x02: "PC Card",
2915 0x03: "UART",
2916 0x04: "RS232",
2917 0x05: "PCI",
2918 0x06: "SDIO"
2919 }),
2920 LEMACField('addr', None),
2921 StrFixedLenField('devname', None, 8)
2922 ]
2923
2924
2925class HCI_Mon_Index_Info(Packet):
2926 name = 'Bluetooth Linux Monitor Transport Index Info Packet'
2927 fields_desc = [
2928 LEMACField('addr', None),
2929 XLEShortField('manufacturer', None)
2930 ]
2931
2932
2933class HCI_Mon_System_Note(Packet):
2934 name = 'Bluetooth Linux Monitor Transport System Note Packet'
2935 fields_desc = [
2936 StrNullField('note', None)
2937 ]
2938
2939
2940# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L34
2941bind_layers(HCI_Mon_Hdr, HCI_Mon_New_Index, opcode=0)
2942bind_layers(HCI_Mon_Hdr, HCI_Command_Hdr, opcode=2)
2943bind_layers(HCI_Mon_Hdr, HCI_Event_Hdr, opcode=3)
2944bind_layers(HCI_Mon_Hdr, HCI_ACL_Hdr, opcode=5)
2945bind_layers(HCI_Mon_Hdr, HCI_Mon_Index_Info, opcode=10)
2946bind_layers(HCI_Mon_Hdr, HCI_Mon_System_Note, opcode=12)
2947
2948conf.l2types.register(DLT_BLUETOOTH_LINUX_MONITOR, HCI_Mon_Pcap_Hdr)
2949
2950
2951###########
2952# Helpers #
2953###########
2954
2955class LowEnergyBeaconHelper:
2956 """
2957 Helpers for building packets for Bluetooth Low Energy Beacons.
2958
2959 Implementers provide a :meth:`build_eir` implementation.
2960
2961 This is designed to be used as a mix-in -- see
2962 ``scapy.contrib.eddystone`` and ``scapy.contrib.ibeacon`` for examples.
2963 """
2964
2965 # Basic flags that should be used by most beacons.
2966 base_eir = [EIR_Hdr() / EIR_Flags(flags=[
2967 "general_disc_mode", "br_edr_not_supported"]), ]
2968
2969 def build_eir(self):
2970 """
2971 Builds a list of EIR messages to wrap this frame.
2972
2973 Users of this helper must implement this method.
2974
2975 :return: List of HCI_Hdr with payloads that describe this beacon type
2976 :rtype: list[scapy.bluetooth.HCI_Hdr]
2977 """
2978 raise NotImplementedError("build_eir")
2979
2980 def build_advertising_report(self):
2981 """
2982 Builds a HCI_LE_Meta_Advertising_Report containing this frame.
2983
2984 :rtype: scapy.bluetooth.HCI_LE_Meta_Advertising_Report
2985 """
2986
2987 return HCI_LE_Meta_Advertising_Report(
2988 type=0, # Undirected
2989 atype=1, # Random address
2990 data=self.build_eir()
2991 )
2992
2993 def build_set_advertising_data(self):
2994 """Builds a HCI_Cmd_LE_Set_Advertising_Data containing this frame.
2995
2996 This includes the :class:`HCI_Hdr` and :class:`HCI_Command_Hdr` layers.
2997
2998 :rtype: scapy.bluetooth.HCI_Hdr
2999 """
3000
3001 return HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Set_Advertising_Data(
3002 data=self.build_eir()
3003 )
3004
3005
3006###########
3007# Sockets #
3008###########
3009
3010class BluetoothSocketError(BaseException):
3011 pass
3012
3013
3014class BluetoothCommandError(BaseException):
3015 pass
3016
3017
3018class BluetoothL2CAPSocket(SuperSocket):
3019 desc = "read/write packets on a connected L2CAP socket"
3020
3021 def __init__(self, bt_address):
3022 if WINDOWS:
3023 warning("Not available on Windows")
3024 return
3025 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
3026 socket.BTPROTO_L2CAP)
3027 s.connect((bt_address, 0))
3028 self.ins = self.outs = s
3029
3030 def recv(self, x=MTU):
3031 return L2CAP_CmdHdr(self.ins.recv(x))
3032
3033
3034class BluetoothRFCommSocket(BluetoothL2CAPSocket):
3035 """read/write packets on a connected RFCOMM socket"""
3036
3037 def __init__(self, bt_address, port=0):
3038 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
3039 socket.BTPROTO_RFCOMM)
3040 s.connect((bt_address, port))
3041 self.ins = self.outs = s
3042
3043
3044class BluetoothHCISocket(SuperSocket):
3045 desc = "read/write on a BlueTooth HCI socket"
3046
3047 def __init__(self, iface=0x10000, type=None):
3048 if WINDOWS:
3049 warning("Not available on Windows")
3050 return
3051 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) # noqa: E501
3052 s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR, 1)
3053 s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP, 1)
3054 s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffff, 0xffffffff, 0xffffffff, 0)) # type mask, event mask, event mask, opcode # noqa: E501
3055 s.bind((iface,))
3056 self.ins = self.outs = s
3057# s.connect((peer,0))
3058
3059 def recv(self, x=MTU):
3060 return HCI_Hdr(self.ins.recv(x))
3061
3062
3063class sockaddr_hci(ctypes.Structure):
3064 _fields_ = [
3065 ("sin_family", ctypes.c_ushort),
3066 ("hci_dev", ctypes.c_ushort),
3067 ("hci_channel", ctypes.c_ushort),
3068 ]
3069
3070
3071class _BluetoothLibcSocket(SuperSocket):
3072 def __init__(self, socket_domain, socket_type, socket_protocol, sock_address):
3073 # type: (int, int, int, sockaddr_hci) -> None
3074 if WINDOWS:
3075 warning("Not available on Windows")
3076 return
3077 # Python socket and bind implementations do not allow us to pass down
3078 # the correct parameters. We must call libc functions directly via
3079 # ctypes.
3080 sockaddr_hcip = ctypes.POINTER(sockaddr_hci)
3081 from ctypes.util import find_library
3082 libc = ctypes.cdll.LoadLibrary(find_library("c"))
3083
3084 socket_c = libc.socket
3085 socket_c.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_int)
3086 socket_c.restype = ctypes.c_int
3087
3088 bind = libc.bind
3089 bind.argtypes = (ctypes.c_int,
3090 ctypes.POINTER(sockaddr_hci),
3091 ctypes.c_int)
3092 bind.restype = ctypes.c_int
3093
3094 # Socket
3095 s = socket_c(socket_domain, socket_type, socket_protocol)
3096 if s < 0:
3097 raise BluetoothSocketError(
3098 f"Unable to open socket({socket_domain}, {socket_type}, "
3099 f"{socket_protocol})")
3100
3101 # Bind
3102 r = bind(s, sockaddr_hcip(sock_address), sizeof(sock_address))
3103 if r != 0:
3104 raise BluetoothSocketError("Unable to bind")
3105
3106 self.hci_fd = s
3107 self.ins = self.outs = socket.fromfd(
3108 s, socket_domain, socket_type, socket_protocol)
3109
3110 def readable(self, timeout=0):
3111 (ins, _, _) = select.select([self.ins], [], [], timeout)
3112 return len(ins) > 0
3113
3114 def flush(self):
3115 while self.readable():
3116 self.recv()
3117
3118 def close(self):
3119 if self.closed:
3120 return
3121
3122 # Properly close socket so we can free the device
3123 from ctypes.util import find_library
3124 libc = ctypes.cdll.LoadLibrary(find_library("c"))
3125
3126 close = libc.close
3127 close.restype = ctypes.c_int
3128 self.closed = True
3129 if hasattr(self, "outs"):
3130 if not hasattr(self, "ins") or self.ins != self.outs:
3131 if self.outs and (WINDOWS or self.outs.fileno() != -1):
3132 close(self.outs.fileno())
3133 if hasattr(self, "ins"):
3134 if self.ins and (WINDOWS or self.ins.fileno() != -1):
3135 close(self.ins.fileno())
3136 if hasattr(self, "hci_fd"):
3137 close(self.hci_fd)
3138
3139
3140class BluetoothUserSocket(_BluetoothLibcSocket):
3141 desc = "read/write H4 over a Bluetooth user channel"
3142
3143 def __init__(self, adapter_index=0):
3144 sa = sockaddr_hci()
3145 sa.sin_family = socket.AF_BLUETOOTH
3146 sa.hci_dev = adapter_index
3147 sa.hci_channel = HCI_CHANNEL_USER
3148 super().__init__(
3149 socket_domain=socket.AF_BLUETOOTH,
3150 socket_type=socket.SOCK_RAW,
3151 socket_protocol=socket.BTPROTO_HCI,
3152 sock_address=sa)
3153
3154 def send_command(self, cmd):
3155 opcode = cmd[HCI_Command_Hdr].opcode
3156 self.send(cmd)
3157 while True:
3158 r = self.recv()
3159 if r.type == 0x04 and r.code == 0xe and r.opcode == opcode:
3160 if r.status != 0:
3161 raise BluetoothCommandError("Command %x failed with %x" % (opcode, r.status)) # noqa: E501
3162 return r
3163
3164 def recv(self, x=MTU):
3165 return HCI_Hdr(self.ins.recv(x))
3166
3167
3168class BluetoothMonitorSocket(_BluetoothLibcSocket):
3169 desc = "Read/write over a Bluetooth monitor channel"
3170
3171 def __init__(self):
3172 sa = sockaddr_hci()
3173 sa.sin_family = socket.AF_BLUETOOTH
3174 sa.hci_dev = HCI_DEV_NONE
3175 sa.hci_channel = HCI_CHANNEL_MONITOR
3176 super().__init__(
3177 socket_domain=socket.AF_BLUETOOTH,
3178 socket_type=socket.SOCK_RAW,
3179 socket_protocol=socket.BTPROTO_HCI,
3180 sock_address=sa)
3181
3182 def recv(self, x=MTU):
3183 return HCI_Mon_Hdr(self.ins.recv(x))
3184
3185
3186conf.BTsocket = BluetoothRFCommSocket
3187
3188# Bluetooth
3189
3190
3191@conf.commands.register
3192def srbt(bt_address, pkts, inter=0.1, *args, **kargs):
3193 """send and receive using a bluetooth socket"""
3194 if "port" in kargs:
3195 s = conf.BTsocket(bt_address=bt_address, port=kargs.pop("port"))
3196 else:
3197 s = conf.BTsocket(bt_address=bt_address)
3198 a, b = sndrcv(s, pkts, inter=inter, *args, **kargs)
3199 s.close()
3200 return a, b
3201
3202
3203@conf.commands.register
3204def srbt1(bt_address, pkts, *args, **kargs):
3205 """send and receive 1 packet using a bluetooth socket"""
3206 a, b = srbt(bt_address, pkts, *args, **kargs)
3207 if len(a) > 0:
3208 return a[0][1]