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