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 EIR_Hdr(Packet):
963 name = "EIR Header"
964 fields_desc = [
965 LenField("len", None, fmt="B", adjust=lambda x: x + 1), # Add bytes mark # noqa: E501
966 # https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
967 ByteEnumField("type", 0, {
968 0x01: "flags",
969 0x02: "incomplete_list_16_bit_svc_uuids",
970 0x03: "complete_list_16_bit_svc_uuids",
971 0x04: "incomplete_list_32_bit_svc_uuids",
972 0x05: "complete_list_32_bit_svc_uuids",
973 0x06: "incomplete_list_128_bit_svc_uuids",
974 0x07: "complete_list_128_bit_svc_uuids",
975 0x08: "shortened_local_name",
976 0x09: "complete_local_name",
977 0x0a: "tx_power_level",
978 0x0d: "class_of_device",
979 0x0e: "simple_pairing_hash",
980 0x0f: "simple_pairing_rand",
981
982 0x10: "sec_mgr_tk",
983 0x11: "sec_mgr_oob_flags",
984 0x12: "slave_conn_intvl_range",
985 0x14: "list_16_bit_svc_sollication_uuids",
986 0x15: "list_128_bit_svc_sollication_uuids",
987 0x16: "svc_data_16_bit_uuid",
988 0x17: "pub_target_addr",
989 0x18: "rand_target_addr",
990 0x19: "appearance",
991 0x1a: "adv_intvl",
992 0x1b: "le_addr",
993 0x1c: "le_role",
994 0x1d: "simple_pairing_hash_256",
995 0x1e: "simple_pairing_rand_256",
996 0x1f: "list_32_bit_svc_sollication_uuids",
997
998 0x20: "svc_data_32_bit_uuid",
999 0x21: "svc_data_128_bit_uuid",
1000 0x22: "sec_conn_confirm",
1001 0x23: "sec_conn_rand",
1002 0x24: "uri",
1003 0x25: "indoor_positioning",
1004 0x26: "transport_discovery",
1005 0x27: "le_supported_features",
1006 0x28: "channel_map_update",
1007 0x29: "mesh_pb_adv",
1008 0x2a: "mesh_message",
1009 0x2b: "mesh_beacon",
1010
1011 0x3d: "3d_information",
1012
1013 0xff: "mfg_specific_data",
1014 }),
1015 ]
1016
1017 def mysummary(self):
1018 return self.sprintf("EIR %type%")
1019
1020 def guess_payload_class(self, payload):
1021 if self.len == 0:
1022 # For Extended_Inquiry_Response, stop when len=0
1023 return conf.padding_layer
1024 return super(EIR_Hdr, self).guess_payload_class(payload)
1025
1026
1027class EIR_Element(Packet):
1028 name = "EIR Element"
1029
1030 def extract_padding(self, s):
1031 # Needed to end each EIR_Element packet and make PacketListField work.
1032 return b'', s
1033
1034 @staticmethod
1035 def length_from(pkt):
1036 if not pkt.underlayer:
1037 warning("Missing an upper-layer")
1038 return 0
1039 # 'type' byte is included in the length, so subtract 1:
1040 return pkt.underlayer.len - 1
1041
1042
1043class EIR_Raw(EIR_Element):
1044 name = "EIR Raw"
1045 fields_desc = [
1046 StrLenField("data", "", length_from=EIR_Element.length_from)
1047 ]
1048
1049
1050class EIR_Flags(EIR_Element):
1051 name = "Flags"
1052 fields_desc = [
1053 FlagsField("flags", 0x2, 8,
1054 ["limited_disc_mode", "general_disc_mode",
1055 "br_edr_not_supported", "simul_le_br_edr_ctrl",
1056 "simul_le_br_edr_host"] + 3 * ["reserved"])
1057 ]
1058
1059
1060class EIR_CompleteList16BitServiceUUIDs(EIR_Element):
1061 name = "Complete list of 16-bit service UUIDs"
1062 fields_desc = [
1063 # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members
1064 FieldListField("svc_uuids", None, XLEShortField("uuid", 0),
1065 length_from=EIR_Element.length_from)
1066 ]
1067
1068
1069class EIR_IncompleteList16BitServiceUUIDs(EIR_CompleteList16BitServiceUUIDs):
1070 name = "Incomplete list of 16-bit service UUIDs"
1071
1072
1073class EIR_CompleteList32BitServiceUUIDs(EIR_Element):
1074 name = 'Complete list of 32-bit service UUIDs'
1075 fields_desc = [
1076 # https://www.bluetooth.com/specifications/assigned-numbers
1077 FieldListField('svc_uuids', None, XLEIntField('uuid', 0),
1078 length_from=EIR_Element.length_from)
1079 ]
1080
1081
1082class EIR_IncompleteList32BitServiceUUIDs(EIR_CompleteList32BitServiceUUIDs):
1083 name = 'Incomplete list of 32-bit service UUIDs'
1084
1085
1086class EIR_CompleteList128BitServiceUUIDs(EIR_Element):
1087 name = "Complete list of 128-bit service UUIDs"
1088 fields_desc = [
1089 FieldListField("svc_uuids", None,
1090 UUIDField("uuid", None, uuid_fmt=UUIDField.FORMAT_REV),
1091 length_from=EIR_Element.length_from)
1092 ]
1093
1094
1095class EIR_IncompleteList128BitServiceUUIDs(EIR_CompleteList128BitServiceUUIDs):
1096 name = "Incomplete list of 128-bit service UUIDs"
1097
1098
1099class EIR_CompleteLocalName(EIR_Element):
1100 name = "Complete Local Name"
1101 fields_desc = [
1102 StrLenField("local_name", "", length_from=EIR_Element.length_from)
1103 ]
1104
1105
1106class EIR_ShortenedLocalName(EIR_CompleteLocalName):
1107 name = "Shortened Local Name"
1108
1109
1110class EIR_TX_Power_Level(EIR_Element):
1111 name = "TX Power Level"
1112 fields_desc = [SignedByteField("level", 0)]
1113
1114
1115class EIR_ClassOfDevice(EIR_Element):
1116 name = 'Class of device'
1117 fields_desc = [
1118 FlagsField('major_service_classes', 0, 11, [
1119 'limited_discoverable_mode',
1120 'le_audio',
1121 'reserved',
1122 'positioning',
1123 'networking',
1124 'rendering',
1125 'capturing',
1126 'object_transfer',
1127 'audio',
1128 'telephony',
1129 'information'
1130 ], tot_size=-3),
1131 BitEnumField('major_device_class', 0, 5, {
1132 0x00: 'miscellaneous',
1133 0x01: 'computer',
1134 0x02: 'phone',
1135 0x03: 'lan',
1136 0x04: 'audio_video',
1137 0x05: 'peripheral',
1138 0x06: 'imaging',
1139 0x07: 'wearable',
1140 0x08: 'toy',
1141 0x09: 'health',
1142 0x1f: 'uncategorized'
1143 }),
1144 BitField('minor_device_class', 0, 6),
1145 BitField('fixed', 0, 2, end_tot_size=-3)
1146 ]
1147
1148
1149class EIR_SecureSimplePairingHashC192(EIR_Element):
1150 name = 'Secure Simple Pairing Hash C-192'
1151 fields_desc = [NBytesField('hash', 0, 16)]
1152
1153
1154class EIR_SecureSimplePairingRandomizerR192(EIR_Element):
1155 name = 'Secure Simple Pairing Randomizer R-192'
1156 fields_desc = [NBytesField('randomizer', 0, 16)]
1157
1158
1159class EIR_SecurityManagerOOBFlags(EIR_Element):
1160 name = 'Security Manager Out of Band Flags'
1161 fields_desc = [
1162 BitField('oob_flags_field', 0, 1),
1163 BitField('le_supported', 0, 1),
1164 BitField('previously_used', 0, 1),
1165 BitField('address_type', 0, 1),
1166 BitField('reserved', 0, 4)
1167 ]
1168
1169
1170class EIR_PeripheralConnectionIntervalRange(EIR_Element):
1171 name = 'Peripheral Connection Interval Range'
1172 fields_desc = [
1173 LEShortField('conn_interval_min', 0xFFFF),
1174 LEShortField('conn_interval_max', 0xFFFF)
1175 ]
1176
1177
1178class EIR_Manufacturer_Specific_Data(EIR_Element):
1179 name = "EIR Manufacturer Specific Data"
1180 deprecated_fields = {
1181 "company_id": ("company_identifier", "2.6.2"),
1182 }
1183 fields_desc = [
1184 # https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
1185 LEShortEnumField("company_identifier", None,
1186 BLUETOOTH_CORE_COMPANY_IDENTIFIERS),
1187 ]
1188
1189 registered_magic_payloads = {}
1190
1191 @classmethod
1192 def register_magic_payload(cls, payload_cls, magic_check=None):
1193 """
1194 Registers a payload type that uses magic data.
1195
1196 Traditional payloads require registration of a Bluetooth Company ID
1197 (requires company membership of the Bluetooth SIG), or a Bluetooth
1198 Short UUID (requires a once-off payment).
1199
1200 There are alternatives which don't require registration (such as
1201 128-bit UUIDs), but the biggest consumer of energy in a beacon is the
1202 radio -- so the energy consumption of a beacon is proportional to the
1203 number of bytes in a beacon frame.
1204
1205 Some beacon formats side-step this issue by using the Company ID of
1206 their beacon hardware manufacturer, and adding a "magic data sequence"
1207 at the start of the Manufacturer Specific Data field.
1208
1209 Examples of this are AltBeacon and GeoBeacon.
1210
1211 For an example of this method in use, see ``scapy.contrib.altbeacon``.
1212
1213 :param Type[scapy.packet.Packet] payload_cls:
1214 A reference to a Packet subclass to register as a payload.
1215 :param Callable[[bytes], bool] magic_check:
1216 (optional) callable to use to if a payload should be associated
1217 with this type. If not supplied, ``payload_cls.magic_check`` is
1218 used instead.
1219 :raises TypeError: If ``magic_check`` is not specified,
1220 and ``payload_cls.magic_check`` is not implemented.
1221 """
1222 if magic_check is None:
1223 if hasattr(payload_cls, "magic_check"):
1224 magic_check = payload_cls.magic_check
1225 else:
1226 raise TypeError("magic_check not specified, and {} has no "
1227 "attribute magic_check".format(payload_cls))
1228
1229 cls.registered_magic_payloads[payload_cls] = magic_check
1230
1231 def default_payload_class(self, payload):
1232 for cls, check in (
1233 EIR_Manufacturer_Specific_Data.registered_magic_payloads.items()
1234 ):
1235 if check(payload):
1236 return cls
1237
1238 return Packet.default_payload_class(self, payload)
1239
1240 def extract_padding(self, s):
1241 # Needed to end each EIR_Element packet and make PacketListField work.
1242 plen = EIR_Element.length_from(self) - 2
1243 return s[:plen], s[plen:]
1244
1245
1246class EIR_Device_ID(EIR_Element):
1247 name = "Device ID"
1248 fields_desc = [
1249 XLEShortField("vendor_id_source", 0),
1250 XLEShortField("vendor_id", 0),
1251 XLEShortField("product_id", 0),
1252 XLEShortField("version", 0),
1253 ]
1254
1255
1256class EIR_ServiceSolicitation16BitUUID(EIR_Element):
1257 name = "EIR Service Solicitation - 16-bit UUID"
1258 fields_desc = [
1259 XLEShortField("svc_uuid", None)
1260 ]
1261
1262 def extract_padding(self, s):
1263 # Needed to end each EIR_Element packet and make PacketListField work.
1264 plen = EIR_Element.length_from(self) - 2
1265 return s[:plen], s[plen:]
1266
1267
1268class EIR_ServiceSolicitation128BitUUID(EIR_Element):
1269 name = "EIR Service Solicitation - 128-bit UUID"
1270 fields_desc = [
1271 UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)
1272 ]
1273
1274 def extract_padding(self, s):
1275 # Needed to end each EIR_Element packet and make PacketListField work.
1276 plen = EIR_Element.length_from(self) - 2
1277 return s[:plen], s[plen:]
1278
1279
1280class EIR_ServiceData16BitUUID(EIR_Element):
1281 name = "EIR Service Data - 16-bit UUID"
1282 fields_desc = [
1283 # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members
1284 XLEShortField("svc_uuid", None),
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_PublicTargetAddress(EIR_Element):
1294 name = "Public Target Address"
1295 fields_desc = [
1296 LEMACField('bd_addr', None)
1297 ]
1298
1299
1300class EIR_AdvertisingInterval(EIR_Element):
1301 name = "Advertising Interval"
1302 fields_desc = [
1303 MultipleTypeField(
1304 [
1305 (ByteField("advertising_interval", 0),
1306 lambda p: p.underlayer.len - 1 == 1),
1307 (LEShortField("advertising_interval", 0),
1308 lambda p: p.underlayer.len - 1 == 2),
1309 (LEThreeBytesField("advertising_interval", 0),
1310 lambda p: p.underlayer.len - 1 == 3),
1311 (LEIntField("advertising_interval", 0),
1312 lambda p: p.underlayer.len - 1 == 4),
1313 ],
1314 LEShortField("advertising_interval", 0)
1315 )
1316 ]
1317
1318
1319class EIR_LEBluetoothDeviceAddress(EIR_Element):
1320 name = "LE Bluetooth Device Address"
1321 fields_desc = [
1322 XBitField('reserved', 0, 7, tot_size=-1),
1323 BitEnumField('addr_type', 0, 1, end_tot_size=-1, enum={
1324 0x0: 'Public',
1325 0x1: 'Random'
1326 }),
1327 LEMACField('bd_addr', None)
1328 ]
1329
1330
1331class EIR_Appearance(EIR_Element):
1332 name = "EIR_Appearance"
1333 fields_desc = [
1334 BitEnumField('category', 0, 10, tot_size=-2, enum={
1335 0x000: 'Unknown',
1336 0x001: 'Phone',
1337 0x002: 'Computer',
1338 0x003: 'Watch',
1339 0x004: 'Clock',
1340 0x005: 'Display',
1341 0x006: 'Remote Control',
1342 0x007: 'Eyeglasses',
1343 0x008: 'Tag',
1344 0x009: 'Keyring',
1345 0x00A: 'Media Player',
1346 0x00B: 'Barcode Scanner',
1347 0x00C: 'Thermometer',
1348 0x00D: 'Heart Rate Sensor',
1349 0x00E: 'Blood Pressure',
1350 0x00F: 'Human Interface Device',
1351 0x010: 'Glucose Meter',
1352 0x011: 'Running Walking Sensor',
1353 0x012: 'Cycling',
1354 0x013: 'Control Device',
1355 0x014: 'Network Device',
1356 0x015: 'Sensor',
1357 0x016: 'Light Fixtures',
1358 0x017: 'Fan',
1359 0x018: 'HVAC',
1360 0x019: 'Air Conditioning',
1361 0x01A: 'Humidifier',
1362 0x01B: 'Heating',
1363 0x01C: 'Access Control',
1364 0x01D: 'Motorized Device',
1365 0x01E: 'Power Device',
1366 0x01F: 'Light Source',
1367 0x020: 'Window Covering',
1368 0x021: 'Audio Sink',
1369 0x022: 'Audio Source',
1370 0x023: 'Motorized Vehicle',
1371 0x024: 'Domestic Appliance',
1372 0x025: 'Wearable Audio Device',
1373 0x026: 'Aircraft',
1374 0x027: 'AV Equipment',
1375 0x028: 'Display Equipment',
1376 0x029: 'Hearing aid',
1377 0x02A: 'Gaming',
1378 0x02B: 'Signage',
1379 0x031: 'Pulse Oximeter',
1380 0x032: 'Weight Scale',
1381 0x033: 'Personal Mobility Device',
1382 0x034: 'Continuous Glucose Monitor',
1383 0x035: 'Insulin Pump',
1384 0x036: 'Medication Delivery',
1385 0x037: 'Spirometer',
1386 0x051: 'Outdoor Sports Activity'
1387 }),
1388 XBitField('subcategory', 0, 6, end_tot_size=-2)
1389 ]
1390
1391 @property
1392 def appearance(self):
1393 return (self.category << 6) + self.subcategory
1394
1395
1396class EIR_ServiceData32BitUUID(EIR_Element):
1397 name = 'EIR Service Data - 32-bit UUID'
1398 fields_desc = [
1399 XLEIntField('svc_uuid', 0),
1400 ]
1401
1402 def extract_padding(self, s):
1403 # Needed to end each EIR_Element packet and make PacketListField work.
1404 plen = EIR_Element.length_from(self) - 4
1405 return s[:plen], s[plen:]
1406
1407
1408class EIR_ServiceData128BitUUID(EIR_Element):
1409 name = 'EIR Service Data - 128-bit UUID'
1410 fields_desc = [
1411 UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)
1412 ]
1413
1414 def extract_padding(self, s):
1415 # Needed to end each EIR_Element packet and make PacketListField work.
1416 plen = EIR_Element.length_from(self) - 16
1417 return s[:plen], s[plen:]
1418
1419
1420class EIR_URI(EIR_Element):
1421 name = 'EIR URI'
1422 fields_desc = [
1423 ByteEnumField('scheme', 0, {
1424 0x01: '',
1425 0x02: 'aaa:',
1426 0x03: 'aaas:',
1427 0x04: 'about:',
1428 0x05: 'acap:',
1429 0x06: 'acct:',
1430 0x07: 'cap:',
1431 0x08: 'cid:',
1432 0x09: 'coap:',
1433 0x0A: 'coaps:',
1434 0x0B: 'crid:',
1435 0x0C: 'data:',
1436 0x0D: 'dav:',
1437 0x0E: 'dict:',
1438 0x0F: 'dns:',
1439 0x10: 'file:',
1440 0x11: 'ftp:',
1441 0x12: 'geo:',
1442 0x13: 'go:',
1443 0x14: 'gopher:',
1444 0x15: 'h323:',
1445 0x16: 'http:',
1446 0x17: 'https:',
1447 0x18: 'iax:',
1448 0x19: 'icap:',
1449 0x1A: 'im:',
1450 0x1B: 'imap:',
1451 0x1C: 'info:',
1452 0x1D: 'ipp:',
1453 0x1E: 'ipps:',
1454 0x1F: 'iris:',
1455 0x20: 'iris.beep:',
1456 0x21: 'iris.xpc:',
1457 0x22: 'iris.xpcs:',
1458 0x23: 'iris.lwz:',
1459 0x24: 'jabber:',
1460 0x25: 'ldap:',
1461 0x26: 'mailto:',
1462 0x27: 'mid:',
1463 0x28: 'msrp:',
1464 0x29: 'msrps:',
1465 0x2A: 'mtqp:',
1466 0x2B: 'mupdate:',
1467 0x2C: 'news:',
1468 0x2D: 'nfs:',
1469 0x2E: 'ni:',
1470 0x2F: 'nih:',
1471 0x30: 'nntp:',
1472 0x31: 'opaquelocktoken:',
1473 0x32: 'pop:',
1474 0x33: 'pres:',
1475 0x34: 'reload:',
1476 0x35: 'rtsp:',
1477 0x36: 'rtsps:',
1478 0x37: 'rtspu:',
1479 0x38: 'service:',
1480 0x39: 'session:',
1481 0x3A: 'shttp:',
1482 0x3B: 'sieve:',
1483 0x3C: 'sip:',
1484 0x3D: 'sips:',
1485 0x3E: 'sms:',
1486 0x3F: 'snmp:',
1487 0x40: 'soap.beep:',
1488 0x41: 'soap.beeps:',
1489 0x42: 'stun:',
1490 0x43: 'stuns:',
1491 0x44: 'tag:',
1492 0x45: 'tel:',
1493 0x46: 'telnet:',
1494 0x47: 'tftp:',
1495 0x48: 'thismessage:',
1496 0x49: 'tn3270:',
1497 0x4A: 'tip:',
1498 0x4B: 'turn:',
1499 0x4C: 'turns:',
1500 0x4D: 'tv:',
1501 0x4E: 'urn:',
1502 0x4F: 'vemmi:',
1503 0x50: 'ws:',
1504 0x51: 'wss:',
1505 0x52: 'xcon:',
1506 0x53: 'xconuserid:',
1507 0x54: 'xmlrpc.beep:',
1508 0x55: 'xmlrpc.beeps:',
1509 0x56: 'xmpp:',
1510 0x57: 'z39.50r:',
1511 0x58: 'z39.50s:',
1512 0x59: 'acr:',
1513 0x5A: 'adiumxtra:',
1514 0x5B: 'afp:',
1515 0x5C: 'afs:',
1516 0x5D: 'aim:',
1517 0x5E: 'apt:',
1518 0x5F: 'attachment:',
1519 0x60: 'aw:',
1520 0x61: 'barion:',
1521 0x62: 'beshare:',
1522 0x63: 'bitcoin:',
1523 0x64: 'bolo:',
1524 0x65: 'callto:',
1525 0x66: 'chrome:',
1526 0x67: 'chromeextension:',
1527 0x68: 'comeventbriteattendee:',
1528 0x69: 'content:',
1529 0x6A: 'cvs:',
1530 0x6B: 'dlnaplaysingle:',
1531 0x6C: 'dlnaplaycontainer:',
1532 0x6D: 'dtn:',
1533 0x6E: 'dvb:',
1534 0x6F: 'ed2k:',
1535 0x70: 'facetime:',
1536 0x71: 'feed:',
1537 0x72: 'feedready:',
1538 0x73: 'finger:',
1539 0x74: 'fish:',
1540 0x75: 'gg:',
1541 0x76: 'git:',
1542 0x77: 'gizmoproject:',
1543 0x78: 'gtalk:',
1544 0x79: 'ham:',
1545 0x7A: 'hcp:',
1546 0x7B: 'icon:',
1547 0x7C: 'ipn:',
1548 0x7D: 'irc:',
1549 0x7E: 'irc6:',
1550 0x7F: 'ircs:',
1551 0x80: 'itms:',
1552 0x81: 'jar:',
1553 0x82: 'jms:',
1554 0x83: 'keyparc:',
1555 0x84: 'lastfm:',
1556 0x85: 'ldaps:',
1557 0x86: 'magnet:',
1558 0x87: 'maps:',
1559 0x88: 'market:',
1560 0x89: 'message:',
1561 0x8A: 'mms:',
1562 0x8B: 'mshelp:',
1563 0x8C: 'mssettingspower:',
1564 0x8D: 'msnim:',
1565 0x8E: 'mumble:',
1566 0x8F: 'mvn:',
1567 0x90: 'notes:',
1568 0x91: 'oid:',
1569 0x92: 'palm:',
1570 0x93: 'paparazzi:',
1571 0x94: 'pkcs11:',
1572 0x95: 'platform:',
1573 0x96: 'proxy:',
1574 0x97: 'psyc:',
1575 0x98: 'query:',
1576 0x99: 'res:',
1577 0x9A: 'resource:',
1578 0x9B: 'rmi:',
1579 0x9C: 'rsync:',
1580 0x9D: 'rtmfp:',
1581 0x9E: 'rtmp:',
1582 0x9F: 'secondlife:',
1583 0xA0: 'sftp:',
1584 0xA1: 'sgn:',
1585 0xA2: 'skype:',
1586 0xA3: 'smb:',
1587 0xA4: 'smtp:',
1588 0xA5: 'soldat:',
1589 0xA6: 'spotify:',
1590 0xA7: 'ssh:',
1591 0xA8: 'steam:',
1592 0xA9: 'submit:',
1593 0xAA: 'svn:',
1594 0xAB: 'teamspeak:',
1595 0xAC: 'teliaeid:',
1596 0xAD: 'things:',
1597 0xAE: 'udp:',
1598 0xAF: 'unreal:',
1599 0xB0: 'ut2004:',
1600 0xB1: 'ventrilo:',
1601 0xB2: 'viewsource:',
1602 0xB3: 'webcal:',
1603 0xB4: 'wtai:',
1604 0xB5: 'wyciwyg:',
1605 0xB6: 'xfire:',
1606 0xB7: 'xri:',
1607 0xB8: 'ymsgr:',
1608 0xB9: 'example:',
1609 0xBA: 'mssettingscloudstorage:'
1610 }),
1611 StrLenField('uri_hier_part', None, length_from=EIR_Element.length_from)
1612 ]
1613
1614 @property
1615 def uri(self):
1616 return EIR_URI.scheme.i2s[self.scheme] + self.uri_hier_part.decode('utf-8')
1617
1618
1619class HCI_Command_Hdr(Packet):
1620 name = "HCI Command header"
1621 fields_desc = [XBitField("ogf", 0, 6, tot_size=-2),
1622 XBitField("ocf", 0, 10, end_tot_size=-2),
1623 LenField("len", None, fmt="B"), ]
1624
1625 def answers(self, other):
1626 return False
1627
1628 @property
1629 def opcode(self):
1630 return (self.ogf << 10) + self.ocf
1631
1632 def post_build(self, p, pay):
1633 p += pay
1634 if self.len is None:
1635 p = p[:2] + struct.pack("B", len(pay)) + p[3:]
1636 return p
1637
1638
1639# BUETOOTH CORE SPECIFICATION 5.4 | Vol 3, Part C
1640# 8 EXTENDED INQUIRY RESPONSE
1641
1642class HCI_Extended_Inquiry_Response(Packet):
1643 fields_desc = [
1644 PadField(
1645 PacketListField(
1646 "eir_data", [],
1647 next_cls_cb=lambda *args: (
1648 (not args[2] or args[2].len != 0) and EIR_Hdr or conf.raw_layer
1649 )
1650 ),
1651 align=31, padwith=b"\0",
1652 ),
1653 ]
1654
1655
1656# BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E
1657# 7 HCI COMMANDS AND EVENTS
1658# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01
1659
1660class HCI_Cmd_Inquiry(Packet):
1661 """
1662 7.1.1 Inquiry command
1663 """
1664 name = "HCI_Inquiry"
1665 fields_desc = [XLE3BytesField("lap", 0x9E8B33),
1666 ByteField("inquiry_length", 0),
1667 ByteField("num_responses", 0)]
1668
1669
1670class HCI_Cmd_Inquiry_Cancel(Packet):
1671 """
1672 7.1.2 Inquiry Cancel command
1673 """
1674 name = "HCI_Inquiry_Cancel"
1675
1676
1677class HCI_Cmd_Periodic_Inquiry_Mode(Packet):
1678 """
1679 7.1.3 Periodic Inquiry Mode command
1680 """
1681 name = "HCI_Periodic_Inquiry_Mode"
1682 fields_desc = [LEShortField("max_period_length", 0x0003),
1683 LEShortField("min_period_length", 0x0002),
1684 XLE3BytesField("lap", 0x9E8B33),
1685 ByteField("inquiry_length", 0),
1686 ByteField("num_responses", 0)]
1687
1688
1689class HCI_Cmd_Exit_Peiodic_Inquiry_Mode(Packet):
1690 """
1691 7.1.4 Exit Periodic Inquiry Mode command
1692 """
1693 name = "HCI_Exit_Periodic_Inquiry_Mode"
1694
1695
1696class HCI_Cmd_Create_Connection(Packet):
1697 """
1698 7.1.5 Create Connection command
1699 """
1700 name = "HCI_Create_Connection"
1701 fields_desc = [LEMACField("bd_addr", None),
1702 LEShortField("packet_type", 0xcc18),
1703 ByteField("page_scan_repetition_mode", 0x02),
1704 ByteField("reserved", 0x0),
1705 LEShortField("clock_offset", 0x0),
1706 ByteField("allow_role_switch", 0x1), ]
1707
1708
1709class HCI_Cmd_Disconnect(Packet):
1710 """
1711 7.1.6 Disconnect command
1712 """
1713 name = "HCI_Disconnect"
1714 fields_desc = [XLEShortField("handle", 0),
1715 ByteField("reason", 0x13), ]
1716
1717
1718class HCI_Cmd_Create_Connection_Cancel(Packet):
1719 """
1720 7.1.7 Create Connection Cancel command
1721 """
1722 name = "HCI_Create_Connection_Cancel"
1723 fields_desc = [LEMACField("bd_addr", None), ]
1724
1725
1726class HCI_Cmd_Accept_Connection_Request(Packet):
1727 """
1728 7.1.8 Accept Connection Request command
1729 """
1730 name = "HCI_Accept_Connection_Request"
1731 fields_desc = [LEMACField("bd_addr", None),
1732 ByteField("role", 0x1), ]
1733
1734
1735class HCI_Cmd_Reject_Connection_Response(Packet):
1736 """
1737 7.1.9 Reject Connection Request command
1738 """
1739 name = "HCI_Reject_Connection_Response"
1740 fields_desc = [LEMACField("bd_addr", None),
1741 ByteField("reason", 0x1), ]
1742
1743
1744class HCI_Cmd_Link_Key_Request_Reply(Packet):
1745 """
1746 7.1.10 Link Key Request Reply command
1747 """
1748 name = "HCI_Link_Key_Request_Reply"
1749 fields_desc = [LEMACField("bd_addr", None),
1750 NBytesField("link_key", None, 16), ]
1751
1752
1753class HCI_Cmd_Link_Key_Request_Negative_Reply(Packet):
1754 """
1755 7.1.11 Link Key Request Negative Reply command
1756 """
1757 name = "HCI_Link_Key_Request_Negative_Reply"
1758 fields_desc = [LEMACField("bd_addr", None), ]
1759
1760
1761class HCI_Cmd_PIN_Code_Request_Reply(Packet):
1762 """
1763 7.1.12 PIN Code Request Reply command
1764 """
1765 name = "HCI_PIN_Code_Request_Reply"
1766 fields_desc = [LEMACField("bd_addr", None),
1767 ByteField("pin_code_length", 7),
1768 NBytesField("pin_code", b"\x00" * 16, sz=16), ]
1769
1770
1771class HCI_Cmd_PIN_Code_Request_Negative_Reply(Packet):
1772 """
1773 7.1.13 PIN Code Request Negative Reply command
1774 """
1775 name = "HCI_PIN_Code_Request_Negative_Reply"
1776 fields_desc = [LEMACField("bd_addr", None), ]
1777
1778
1779class HCI_Cmd_Change_Connection_Packet_Type(Packet):
1780 """
1781 7.1.14 Change Connection Packet Type command
1782 """
1783 name = "HCI_Cmd_Change_Connection_Packet_Type"
1784 fields_desc = [XLEShortField("connection_handle", None),
1785 LEShortField("packet_type", 0), ]
1786
1787
1788class HCI_Cmd_Authentication_Requested(Packet):
1789 """
1790 7.1.15 Authentication Requested command
1791 """
1792 name = "HCI_Authentication_Requested"
1793 fields_desc = [LEShortField("handle", 0)]
1794
1795
1796class HCI_Cmd_Set_Connection_Encryption(Packet):
1797 """
1798 7.1.16 Set Connection Encryption command
1799 """
1800 name = "HCI_Set_Connection_Encryption"
1801 fields_desc = [LEShortField("handle", 0), ByteField("encryption_enable", 0)]
1802
1803
1804class HCI_Cmd_Change_Connection_Link_Key(Packet):
1805 """
1806 7.1.17 Change Connection Link Key command
1807 """
1808 name = "HCI_Change_Connection_Link_Key"
1809 fields_desc = [LEShortField("handle", 0), ]
1810
1811
1812class HCI_Cmd_Link_Key_Selection(Packet):
1813 """
1814 7.1.18 Change Connection Link Key command
1815 """
1816 name = "HCI_Cmd_Link_Key_Selection"
1817 fields_desc = [ByteEnumField("handle", 0, {0: "Use semi-permanent Link Keys",
1818 1: "Use Temporary Link Key", }), ]
1819
1820
1821class HCI_Cmd_Remote_Name_Request(Packet):
1822 """
1823 7.1.19 Remote Name Request command
1824 """
1825 name = "HCI_Remote_Name_Request"
1826 fields_desc = [LEMACField("bd_addr", None),
1827 ByteField("page_scan_repetition_mode", 0x02),
1828 ByteField("reserved", 0x0),
1829 LEShortField("clock_offset", 0x0), ]
1830
1831
1832class HCI_Cmd_Remote_Name_Request_Cancel(Packet):
1833 """
1834 7.1.20 Remote Name Request Cancel command
1835 """
1836 name = "HCI_Remote_Name_Request_Cancel"
1837 fields_desc = [LEMACField("bd_addr", None), ]
1838
1839
1840class HCI_Cmd_Read_Remote_Supported_Features(Packet):
1841 """
1842 7.1.21 Read Remote Supported Features command
1843 """
1844 name = "HCI_Read_Remote_Supported_Features"
1845 fields_desc = [LEShortField("connection_handle", None), ]
1846
1847
1848class HCI_Cmd_Read_Remote_Extended_Features(Packet):
1849 """
1850 7.1.22 Read Remote Extended Features command
1851 """
1852 name = "HCI_Read_Remote_Supported_Features"
1853 fields_desc = [LEShortField("connection_handle", None),
1854 ByteField("page_number", None), ]
1855
1856
1857class HCI_Cmd_IO_Capability_Request_Reply(Packet):
1858 """
1859 7.1.29 IO Capability Request Reply command
1860 """
1861 name = "HCI_Read_Remote_Supported_Features"
1862 fields_desc = [LEMACField("bd_addr", None),
1863 ByteEnumField("io_capability", None, {0x00: "DisplayOnly",
1864 0x01: "DisplayYesNo",
1865 0x02: "KeyboardOnly",
1866 0x03: "NoInputNoOutput", }),
1867 ByteEnumField("oob_data_present", None, {0x00: "Not Present",
1868 0x01: "P-192",
1869 0x02: "P-256",
1870 0x03: "P-192 + P-256", }),
1871 ByteEnumField("authentication_requirement", None,
1872 {0x00: "MITM Not Required",
1873 0x01: "MITM Required, No Bonding",
1874 0x02: "MITM Not Required + Dedicated Pairing",
1875 0x03: "MITM Required + Dedicated Pairing",
1876 0x04: "MITM Not Required, General Bonding",
1877 0x05: "MITM Required + General Bonding"}), ]
1878
1879
1880class HCI_Cmd_User_Confirmation_Request_Reply(Packet):
1881 """
1882 7.1.30 User Confirmation Request Reply command
1883 """
1884 name = "HCI_User_Confirmation_Request_Reply"
1885 fields_desc = [LEMACField("bd_addr", None), ]
1886
1887
1888class HCI_Cmd_User_Confirmation_Request_Negative_Reply(Packet):
1889 """
1890 7.1.31 User Confirmation Request Negative Reply command
1891 """
1892 name = "HCI_User_Confirmation_Request_Negative_Reply"
1893 fields_desc = [LEMACField("bd_addr", None), ]
1894
1895
1896class HCI_Cmd_User_Passkey_Request_Reply(Packet):
1897 """
1898 7.1.32 User Passkey Request Reply command
1899 """
1900 name = "HCI_User_Passkey_Request_Reply"
1901 fields_desc = [LEMACField("bd_addr", None),
1902 LEIntField("numeric_value", None), ]
1903
1904
1905class HCI_Cmd_User_Passkey_Request_Negative_Reply(Packet):
1906 """
1907 7.1.33 User Passkey Request Negative Reply command
1908 """
1909 name = "HCI_User_Passkey_Request_Negative_Reply"
1910 fields_desc = [LEMACField("bd_addr", None), ]
1911
1912
1913class HCI_Cmd_Remote_OOB_Data_Request_Reply(Packet):
1914 """
1915 7.1.34 Remote OOB Data Request Reply command
1916 """
1917 name = "HCI_Remote_OOB_Data_Request_Reply"
1918 fields_desc = [LEMACField("bd_addr", None),
1919 NBytesField("C", b"\x00" * 16, sz=16),
1920 NBytesField("R", b"\x00" * 16, sz=16), ]
1921
1922
1923class HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply(Packet):
1924 """
1925 7.1.35 Remote OOB Data Request Negative Reply command
1926 """
1927 name = "HCI_Remote_OOB_Data_Request_Negative_Reply"
1928 fields_desc = [LEMACField("bd_addr", None), ]
1929
1930
1931# 7.2 Link Policy commands, the OGF is defined as 0x02
1932
1933class HCI_Cmd_Hold_Mode(Packet):
1934 name = "HCI_Hold_Mode"
1935 fields_desc = [LEShortField("connection_handle", 0),
1936 LEShortField("hold_mode_max_interval", 0x0002),
1937 LEShortField("hold_mode_min_interval", 0x0002), ]
1938
1939
1940# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03
1941
1942class HCI_Cmd_Set_Event_Mask(Packet):
1943 """
1944 7.3.1 Set Event Mask command
1945 """
1946 name = "HCI_Set_Event_Mask"
1947 fields_desc = [StrFixedLenField("mask", b"\xff\xff\xfb\xff\x07\xf8\xbf\x3d", 8)] # noqa: E501
1948
1949
1950class HCI_Cmd_Reset(Packet):
1951 """
1952 7.3.2 Reset command
1953 """
1954 name = "HCI_Reset"
1955
1956
1957class HCI_Cmd_Set_Event_Filter(Packet):
1958 """
1959 7.3.3 Set Event Filter command
1960 """
1961 name = "HCI_Set_Event_Filter"
1962 fields_desc = [ByteEnumField("type", 0, {0: "clear"}), ]
1963
1964
1965class HCI_Cmd_Write_Local_Name(Packet):
1966 """
1967 7.3.11 Write Local Name command
1968 """
1969 name = "HCI_Write_Local_Name"
1970 fields_desc = [StrFixedLenField('name', '', length=248)]
1971
1972
1973class HCI_Cmd_Read_Local_Name(Packet):
1974 """
1975 7.3.12 Read Local Name command
1976 """
1977 name = "HCI_Read_Local_Name"
1978
1979
1980class HCI_Cmd_Write_Connect_Accept_Timeout(Packet):
1981 name = "HCI_Write_Connection_Accept_Timeout"
1982 fields_desc = [LEShortField("timeout", 32000)] # 32000 slots is 20000 msec
1983
1984
1985class HCI_Cmd_Write_Extended_Inquiry_Response(Packet):
1986 name = "HCI_Write_Extended_Inquiry_Response"
1987 fields_desc = [ByteField("fec_required", 0),
1988 HCI_Extended_Inquiry_Response]
1989
1990
1991class HCI_Cmd_Read_LE_Host_Support(Packet):
1992 name = "HCI_Read_LE_Host_Support"
1993
1994
1995class HCI_Cmd_Write_LE_Host_Support(Packet):
1996 name = "HCI_Write_LE_Host_Support"
1997 fields_desc = [ByteField("supported", 1),
1998 ByteField("unused", 1), ]
1999
2000
2001# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04
2002
2003class HCI_Cmd_Read_Local_Version_Information(Packet):
2004 """
2005 7.4.1 Read Local Version Information command
2006 """
2007 name = "HCI_Read_Local_Version_Information"
2008
2009
2010class HCI_Cmd_Read_Local_Extended_Features(Packet):
2011 """
2012 7.4.4 Read Local Extended Features command
2013 """
2014 name = "HCI_Read_Local_Extended_Features"
2015 fields_desc = [ByteField("page_number", 0)]
2016
2017
2018class HCI_Cmd_Read_BD_Addr(Packet):
2019 """
2020 7.4.6 Read BD_ADDR command
2021 """
2022 name = "HCI_Read_BD_ADDR"
2023
2024
2025# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05
2026
2027class HCI_Cmd_Read_Link_Quality(Packet):
2028 name = "HCI_Read_Link_Quality"
2029 fields_desc = [LEShortField("handle", 0)]
2030
2031
2032class HCI_Cmd_Read_RSSI(Packet):
2033 name = "HCI_Read_RSSI"
2034 fields_desc = [LEShortField("handle", 0)]
2035
2036
2037# 7.6 TESTING COMMANDS, the OGF is defined as 0x06
2038
2039class HCI_Cmd_Read_Loopback_Mode(Packet):
2040 name = "HCI_Read_Loopback_Mode"
2041
2042
2043class HCI_Cmd_Write_Loopback_Mode(Packet):
2044 name = "HCI_Write_Loopback_Mode"
2045 fields_desc = [ByteEnumField("loopback_mode", 0,
2046 {0: "no loopback",
2047 1: "enable local loopback",
2048 2: "enable remote loopback"})]
2049
2050
2051# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08
2052
2053class HCI_Cmd_LE_Set_Event_Mask(Packet):
2054 name = 'HCI_LE_Set_Event_Mask'
2055 fields_desc = [StrFixedLenField('mask', b'\xff\xff\xff\xff\xff\x1f\x00\x00', 8)]
2056
2057
2058class HCI_Cmd_LE_Read_Buffer_Size_V1(Packet):
2059 name = "HCI_LE_Read_Buffer_Size [v1]"
2060
2061
2062class HCI_Cmd_LE_Read_Buffer_Size_V2(Packet):
2063 name = "HCI_LE_Read_Buffer_Size [v2]"
2064
2065
2066class HCI_Cmd_LE_Read_Local_Supported_Features(Packet):
2067 name = "HCI_LE_Read_Local_Supported_Features"
2068
2069
2070class HCI_Cmd_LE_Set_Random_Address(Packet):
2071 name = "HCI_LE_Set_Random_Address"
2072 fields_desc = [LEMACField("addr", None)]
2073 deprecated_fields = {"address": ("addr", "2.7.0")}
2074
2075
2076class HCI_Cmd_LE_Set_Advertising_Parameters(Packet):
2077 name = "HCI_LE_Set_Advertising_Parameters"
2078 fields_desc = [LEShortField("interval_min", 0x0800),
2079 LEShortField("interval_max", 0x0800),
2080 ByteEnumField("adv_type", 0, {
2081 0: "ADV_IND",
2082 1: "ADV_DIRECT_IND",
2083 2: "ADV_SCAN_IND",
2084 3: "ADV_NONCONN_IND",
2085 4: "ADV_DIRECT_IND_LOW"}),
2086 ByteEnumField("own_addr_type", 0, {
2087 0: "public",
2088 1: "random"}),
2089 ByteEnumField("peer_addr_type", 0, {
2090 0: "public",
2091 1: "random"}),
2092 LEMACField("peer_addr", None),
2093 ByteField("channel_map", 7),
2094 ByteEnumField("filter_policy", 0, {
2095 0: "all:all",
2096 1: "connect:all scan:whitelist",
2097 2: "connect:whitelist scan:all",
2098 3: "all:whitelist"}), ]
2099 deprecated_fields = {
2100 "oatype": ("own_addr_type", "2.7.0"),
2101 "datype": ("peer_addr_type", "2.7.0"),
2102 "daddr": ("peer_addr", "2.7.0"),
2103 }
2104
2105
2106class HCI_Cmd_LE_Set_Extended_Advertising_Parameters(Packet):
2107 name = 'HCI_LE_Set_Extended_Advertising_Parameters'
2108 fields_desc = [ByteField('handle', 0),
2109 LEShortField('properties', 19),
2110 LEThreeBytesField('pri_interval_min', 160),
2111 LEThreeBytesField('pri_interval_max', 160),
2112 ByteField('pri_channel_map', 7),
2113 ByteEnumField('own_addr_type', 0, {
2114 0: 'public',
2115 1: 'random',
2116 2: 'rpa_pub',
2117 3: 'rpa_rand'}),
2118 ByteEnumField('peer_addr_type', 0, {
2119 0: 'public',
2120 1: 'random',
2121 2: 'rpa_pub',
2122 3: 'rpa_rand'}),
2123 LEMACField('peer_addr', None),
2124 ByteEnumField("filter_policy", 0, {
2125 0: "all:all",
2126 1: "connect:all scan:whitelist",
2127 2: "connect:whitelist scan:all",
2128 3: "all:whitelist"}),
2129 SignedByteField('tx_power', 127),
2130 ByteEnumField('pri_phy', 1, {1: '1M', 3: 'Coded'}),
2131 ByteField('sec_max_skip', 0),
2132 ByteEnumField('sec_phy', 1, {1: '1M', 2: '2M', 3: 'Coded'}),
2133 ByteField('sid', 0),
2134 ByteField('scan_req_notify_enable', 0)]
2135
2136
2137class HCI_Cmd_LE_Set_Advertising_Set_Random_Address(Packet):
2138 name = 'HCI_LE_Set_Advertising_Set_Random_Address'
2139 fields_desc = [ByteField('handle', 0), LEMACField('addr', None)]
2140
2141
2142class HCI_Cmd_LE_Set_Advertising_Data(Packet):
2143 name = "HCI_LE_Set_Advertising_Data"
2144 fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"),
2145 PadField(
2146 PacketListField("data", [], EIR_Hdr,
2147 length_from=lambda pkt: pkt.len),
2148 align=31, padwith=b"\0"), ]
2149
2150
2151class HCI_Cmd_LE_Set_Extended_Advertising_Data(Packet):
2152 name = 'HCI_LE_Set_Extended_Advertising_Data'
2153 fields_desc = [ByteField('handle', 0),
2154 ByteEnumField('operation', 3, {
2155 0: 'intermediate_frag',
2156 1: 'first_frag',
2157 2: 'last_frag',
2158 3: 'complete',
2159 4: 'unchanged_data'}),
2160 ByteEnumField('frag_pref', 1, {0: 'allow_frag', 1: 'no_frag'}),
2161 FieldLenField('len', None, length_of='data', fmt='B'),
2162 PacketListField('data', [], EIR_Hdr, length_from=lambda pkt: pkt.len)] # noqa: E501
2163
2164
2165class HCI_Cmd_LE_Set_Scan_Response_Data(Packet):
2166 name = "HCI_LE_Set_Scan_Response_Data"
2167 fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"),
2168 StrLenField("data", "", length_from=lambda pkt: pkt.len), ]
2169
2170
2171class HCI_Cmd_LE_Set_Advertise_Enable(Packet):
2172 name = "HCI_LE_Set_Advertising_Enable"
2173 fields_desc = [ByteField("enable", 0)]
2174
2175
2176class Extended_Advertise_Set(Packet):
2177 name = 'Extended Advertising Set'
2178 fields_desc = [ByteField('handle', 0),
2179 LEShortField('duration', 0),
2180 ByteField('max_events', 0)]
2181
2182
2183class HCI_Cmd_LE_Set_Extended_Advertise_Enable(Packet):
2184 name = 'HCI_LE_Set_Extended_Advertising_Enable'
2185 fields_desc = [ByteEnumField('enable', 1, {0: 'disable', 1: 'enable'}),
2186 FieldLenField('num_sets', None, count_of='sets', fmt='B'),
2187 PacketListField('sets', [], Extended_Advertise_Set, count_from=lambda pkt: pkt.num_sets)] # noqa: E501
2188
2189
2190class HCI_Cmd_LE_Set_Scan_Parameters(Packet):
2191 name = "HCI_LE_Set_Scan_Parameters"
2192 fields_desc = [ByteEnumField("type", 0, {0: "passive", 1: "active"}),
2193 XLEShortField("interval", 16),
2194 XLEShortField("window", 16),
2195 ByteEnumField("addr_type", 0, {
2196 0: "public",
2197 1: "random",
2198 2: "rpa (pub)",
2199 3: "rpa (random)"}),
2200 ByteEnumField("policy", 0, {0: "all", 1: "whitelist"})]
2201 deprecated_fields = {"atype": ("addr_type", "2.7.0")}
2202
2203
2204class HCI_Cmd_LE_Set_Extended_Scan_Parameters(Packet):
2205 name = 'HCI_LE_Set_Extended_Scan_Parameters'
2206 fields_desc = [
2207 ByteEnumField('own_address_type', 0, {
2208 0: 'public',
2209 1: 'random',
2210 2: 'rpa_pub',
2211 3: 'rpa_rand'}),
2212 ByteEnumField('scanning_filter_policy', 0, {
2213 0: 'basic',
2214 1: 'whitelist',
2215 2: 'basic_rpa',
2216 3: 'whitelist_rpa'}),
2217 ByteField('scanning_phys', 1),
2218 ConditionalField(ByteEnumField('scan_type_1m', 1, {
2219 0: 'passive',
2220 1: 'active'}), lambda pkt: pkt.scanning_phys & 1),
2221 ConditionalField(LEShortField('scan_interval_1m', 16),
2222 lambda pkt: pkt.scanning_phys & 1),
2223 ConditionalField(LEShortField('scan_window_1m', 16),
2224 lambda pkt: pkt.scanning_phys & 1),
2225 ConditionalField(ByteEnumField('scan_type_2m', 1, {
2226 0: 'passive',
2227 1: 'active'}), lambda pkt: pkt.scanning_phys & 2),
2228 ConditionalField(LEShortField('scan_interval_2m', 16),
2229 lambda pkt: pkt.scanning_phys & 2),
2230 ConditionalField(LEShortField('scan_window_2m', 16),
2231 lambda pkt: pkt.scanning_phys & 2),
2232 ConditionalField(ByteEnumField('scan_type_coded', 1, {
2233 0: 'passive',
2234 1: 'active'}), lambda pkt: pkt.scanning_phys & 4),
2235 ConditionalField(LEShortField('scan_interval_coded', 16),
2236 lambda pkt: pkt.scanning_phys & 4),
2237 ConditionalField(LEShortField('scan_window_coded', 16),
2238 lambda pkt: pkt.scanning_phys & 4)]
2239
2240
2241class HCI_Cmd_LE_Set_Scan_Enable(Packet):
2242 name = "HCI_LE_Set_Scan_Enable"
2243 fields_desc = [ByteField("enable", 1),
2244 ByteField("filter_dups", 1), ]
2245
2246
2247class HCI_Cmd_LE_Set_Extended_Scan_Enable(Packet):
2248 name = 'HCI_LE_Set_Extended_Scan_Enable'
2249 fields_desc = [ByteEnumField('enable', 1, {0: 'disabled', 1: 'enabled'}),
2250 ByteEnumField('filter_dups', 1, {
2251 0: 'disabled',
2252 1: 'enabled',
2253 2: 'reset_period'}),
2254 LEShortField('duration', 500),
2255 LEShortField('period', 0)]
2256
2257
2258class HCI_Cmd_LE_Create_Connection(Packet):
2259 name = "HCI_LE_Create_Connection"
2260 fields_desc = [LEShortField("interval", 96),
2261 LEShortField("window", 48),
2262 ByteEnumField("filter", 0, {0: "address"}),
2263 ByteEnumField("peer_addr_type", 0, {0: "public", 1: "random"}),
2264 LEMACField("peer_addr", None),
2265 ByteEnumField("own_addr_type", 0, {0: "public", 1: "random"}),
2266 LEShortField("min_interval", 40),
2267 LEShortField("max_interval", 56),
2268 LEShortField("latency", 0),
2269 LEShortField("timeout", 42),
2270 LEShortField("min_ce", 0),
2271 LEShortField("max_ce", 0), ]
2272 deprecated_fields = {
2273 "patype": ("peer_addr_type", "2.7.0"),
2274 "paddr": ("peer_addr", "2.7.0"),
2275 "atype": ("own_addr_type", "2.7.0"),
2276 }
2277
2278
2279class HCI_Cmd_LE_Extended_Create_Connection(Packet):
2280 name = 'HCI_LE_Extended_Create_Connection'
2281 fields_desc = [ByteEnumField('filter_policy', 0, {0: 'peer_addr', 1: 'accept_list'}), # noqa: E501
2282 ByteEnumField('address_type', 0, {
2283 0: 'public',
2284 1: 'random',
2285 2: 'rpa_pub',
2286 3: 'rpa_rand'}),
2287 ByteEnumField('peer_addr_type', 0, {
2288 0: 'public',
2289 1: 'random',
2290 2: 'rpa_pub',
2291 3: 'rpa_rand'}),
2292 LEMACField('peer_addr', None),
2293 ByteField('phys', 1),
2294 ConditionalField(LEShortField('interval_1m', 96),
2295 lambda pkt: pkt.phys & 1),
2296 ConditionalField(LEShortField('window_1m', 96),
2297 lambda pkt: pkt.phys & 1),
2298 ConditionalField(LEShortField('min_interval_1m', 40),
2299 lambda pkt: pkt.phys & 1),
2300 ConditionalField(LEShortField('max_interval_1m', 56),
2301 lambda pkt: pkt.phys & 1),
2302 ConditionalField(LEShortField('latency_1m', 0),
2303 lambda pkt: pkt.phys & 1),
2304 ConditionalField(LEShortField('timeout_1m', 42),
2305 lambda pkt: pkt.phys & 1),
2306 ConditionalField(LEShortField('min_ce_1m', 0),
2307 lambda pkt: pkt.phys & 1),
2308 ConditionalField(LEShortField('max_ce_1m', 0),
2309 lambda pkt: pkt.phys & 1),
2310 ConditionalField(LEShortField('interval_2m', 96),
2311 lambda pkt: pkt.phys & 2),
2312 ConditionalField(LEShortField('window_2m', 96),
2313 lambda pkt: pkt.phys & 2),
2314 ConditionalField(LEShortField('min_interval_2m', 40),
2315 lambda pkt: pkt.phys & 2),
2316 ConditionalField(LEShortField('max_interval_2m', 56),
2317 lambda pkt: pkt.phys & 2),
2318 ConditionalField(LEShortField('latency_2m', 0),
2319 lambda pkt: pkt.phys & 2),
2320 ConditionalField(LEShortField('timeout_2m', 42),
2321 lambda pkt: pkt.phys & 2),
2322 ConditionalField(LEShortField('min_ce_2m', 0),
2323 lambda pkt: pkt.phys & 2),
2324 ConditionalField(LEShortField('max_ce_2m', 0),
2325 lambda pkt: pkt.phys & 2),
2326 ConditionalField(LEShortField('interval_coded', 96),
2327 lambda pkt: pkt.phys & 4),
2328 ConditionalField(LEShortField('window_coded', 96),
2329 lambda pkt: pkt.phys & 4),
2330 ConditionalField(LEShortField('min_interval_coded', 40),
2331 lambda pkt: pkt.phys & 4),
2332 ConditionalField(LEShortField('max_interval_coded', 56),
2333 lambda pkt: pkt.phys & 4),
2334 ConditionalField(LEShortField('latency_coded', 0),
2335 lambda pkt: pkt.phys & 4),
2336 ConditionalField(LEShortField('timeout_coded', 42),
2337 lambda pkt: pkt.phys & 4),
2338 ConditionalField(LEShortField('min_ce_coded', 0),
2339 lambda pkt: pkt.phys & 4),
2340 ConditionalField(LEShortField('max_ce_coded', 0),
2341 lambda pkt: pkt.phys & 4)]
2342
2343
2344class HCI_Cmd_LE_Create_Connection_Cancel(Packet):
2345 name = "HCI_LE_Create_Connection_Cancel"
2346
2347
2348class HCI_Cmd_LE_Read_Filter_Accept_List_Size(Packet):
2349 name = "HCI_LE_Read_Filter_Accept_List_Size"
2350
2351
2352class HCI_Cmd_LE_Clear_Filter_Accept_List(Packet):
2353 name = "HCI_LE_Clear_Filter_Accept_List"
2354
2355
2356class HCI_Cmd_LE_Add_Device_To_Filter_Accept_List(Packet):
2357 name = "HCI_LE_Add_Device_To_Filter_Accept_List"
2358 fields_desc = [ByteEnumField("addr_type", 0, {0: "public",
2359 1: "random",
2360 0xff: "anonymous"}),
2361 LEMACField("addr", None)]
2362
2363
2364class HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List(HCI_Cmd_LE_Add_Device_To_Filter_Accept_List): # noqa: E501
2365 name = "HCI_LE_Remove_Device_From_Filter_Accept_List"
2366
2367
2368class HCI_Cmd_LE_Connection_Update(Packet):
2369 name = "HCI_LE_Connection_Update"
2370 fields_desc = [XLEShortField("handle", 0),
2371 XLEShortField("min_interval", 0),
2372 XLEShortField("max_interval", 0),
2373 XLEShortField("latency", 0),
2374 XLEShortField("timeout", 0),
2375 LEShortField("min_ce", 0),
2376 LEShortField("max_ce", 0xffff), ]
2377
2378
2379class HCI_Cmd_LE_Read_Remote_Features(Packet):
2380 name = "HCI_LE_Read_Remote_Features"
2381 fields_desc = [LEShortField("handle", 64)]
2382
2383
2384class HCI_Cmd_LE_Enable_Encryption(Packet):
2385 name = "HCI_LE_Enable_Encryption"
2386 fields_desc = [LEShortField("handle", 0),
2387 StrFixedLenField("rand", None, 8),
2388 XLEShortField("ediv", 0),
2389 StrFixedLenField("ltk", b'\x00' * 16, 16), ]
2390
2391
2392class HCI_Cmd_LE_Long_Term_Key_Request_Reply(Packet):
2393 name = "HCI_LE_Long_Term_Key_Request_Reply"
2394 fields_desc = [LEShortField("handle", 0),
2395 StrFixedLenField("ltk", b'\x00' * 16, 16), ]
2396
2397
2398class HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply(Packet):
2399 name = "HCI_LE_Long_Term_Key_Request _Negative_Reply"
2400 fields_desc = [LEShortField("handle", 0), ]
2401
2402
2403class HCI_Event_Hdr(Packet):
2404 name = "HCI Event header"
2405 fields_desc = [XByteField("code", 0),
2406 LenField("len", None, fmt="B"), ]
2407
2408 def answers(self, other):
2409 if HCI_Command_Hdr not in other:
2410 return False
2411
2412 # Delegate answers to event types
2413 return self.payload.answers(other)
2414
2415
2416class HCI_Event_Inquiry_Complete(Packet):
2417 """
2418 7.7.1 Inquiry Complete event
2419 """
2420 name = "HCI_Inquiry_Complete"
2421 fields_desc = [
2422 ByteEnumField('status', 0, _bluetooth_error_codes)
2423 ]
2424
2425
2426class HCI_Event_Inquiry_Result(Packet):
2427 """
2428 7.7.2 Inquiry Result event
2429 """
2430 name = "HCI_Inquiry_Result"
2431 fields_desc = [
2432 ByteField("num_response", 0x00),
2433 FieldListField("addr", None, LEMACField("addr", None),
2434 count_from=lambda p: p.num_response),
2435 FieldListField("page_scan_repetition_mode", None,
2436 ByteField("page_scan_repetition_mode", 0),
2437 count_from=lambda p: p.num_response),
2438 FieldListField("reserved", None, LEShortField("reserved", 0),
2439 count_from=lambda p: p.num_response),
2440 FieldListField("device_class", None, XLE3BytesField("device_class", 0),
2441 count_from=lambda p: p.num_response),
2442 FieldListField("clock_offset", None, LEShortField("clock_offset", 0),
2443 count_from=lambda p: p.num_response)
2444 ]
2445
2446
2447class HCI_Event_Connection_Complete(Packet):
2448 """
2449 7.7.3 Connection Complete event
2450 """
2451 name = "HCI_Connection_Complete"
2452 fields_desc = [ByteEnumField('status', 0, _bluetooth_error_codes),
2453 LEShortField("handle", 0x0100),
2454 LEMACField("bd_addr", None),
2455 ByteEnumField("link_type", 0, {0: "SCO connection",
2456 1: "ACL connection", }),
2457 ByteEnumField("encryption_enabled", 0,
2458 {0: "link level encryption disabled",
2459 1: "link level encryption enabled", }), ]
2460
2461
2462class HCI_Event_Disconnection_Complete(Packet):
2463 """
2464 7.7.5 Disconnection Complete event
2465 """
2466 name = "HCI_Disconnection_Complete"
2467 fields_desc = [ByteEnumField("status", 0, _bluetooth_error_codes),
2468 LEShortField("handle", 0),
2469 XByteField("reason", 0), ]
2470
2471
2472class HCI_Event_Remote_Name_Request_Complete(Packet):
2473 """
2474 7.7.7 Remote Name Request Complete event
2475 """
2476 name = "HCI_Remote_Name_Request_Complete"
2477 fields_desc = [ByteEnumField("status", 0, _bluetooth_error_codes),
2478 LEMACField("bd_addr", None),
2479 StrFixedLenField("remote_name", b"\x00", 248), ]
2480
2481
2482class HCI_Event_Encryption_Change(Packet):
2483 """
2484 7.7.8 Encryption Change event
2485 """
2486 name = "HCI_Encryption_Change"
2487 fields_desc = [ByteEnumField("status", 0, {0: "change has occurred"}),
2488 LEShortField("handle", 0),
2489 ByteEnumField("enabled", 0, {0: "OFF", 1: "ON (LE)", 2: "ON (BR/EDR)"}), ] # noqa: E501
2490
2491
2492class HCI_Event_Read_Remote_Supported_Features_Complete(Packet):
2493 """
2494 7.7.11 Read Remote Supported Features Complete event
2495 """
2496 name = "HCI_Read_Remote_Supported_Features_Complete"
2497 fields_desc = [
2498 ByteEnumField('status', 0, _bluetooth_error_codes),
2499 LEShortField('handle', 0),
2500 FlagsField('lmp_features', 0, -64, _bluetooth_features)
2501 ]
2502
2503
2504class HCI_Event_Read_Remote_Version_Information_Complete(Packet):
2505 """
2506 7.7.12 Read Remote Version Information Complete event
2507 """
2508 name = "HCI_Read_Remote_Version_Information"
2509 fields_desc = [
2510 ByteEnumField('status', 0, _bluetooth_error_codes),
2511 LEShortField('handle', 0),
2512 ByteField('version', 0x00),
2513 LEShortField('manufacturer_name', 0x0000),
2514 LEShortField('subversion', 0x0000)
2515 ]
2516
2517
2518class HCI_Event_Command_Complete(Packet):
2519 """
2520 7.7.14 Command Complete event
2521 """
2522 name = "HCI_Command_Complete"
2523 fields_desc = [ByteField("number", 0),
2524 XLEShortField("opcode", 0),
2525 ByteEnumField("status", 0, _bluetooth_error_codes)]
2526
2527 def answers(self, other):
2528 if HCI_Command_Hdr not in other:
2529 return False
2530
2531 return other[HCI_Command_Hdr].opcode == self.opcode
2532
2533
2534class HCI_Event_Command_Status(Packet):
2535 """
2536 7.7.15 Command Status event
2537 """
2538 name = "HCI_Command_Status"
2539 fields_desc = [ByteEnumField("status", 0, {0: "pending"}),
2540 ByteField("number", 0),
2541 XLEShortField("opcode", None), ]
2542
2543 def answers(self, other):
2544 if HCI_Command_Hdr not in other:
2545 return False
2546
2547 return other[HCI_Command_Hdr].opcode == self.opcode
2548
2549
2550class HCI_Event_Number_Of_Completed_Packets(Packet):
2551 """
2552 7.7.19 Number Of Completed Packets event
2553 """
2554 name = "HCI_Number_Of_Completed_Packets"
2555 fields_desc = [ByteField("num_handles", 0),
2556 FieldListField("connection_handle_list", None,
2557 LEShortField("connection_handle", 0),
2558 count_from=lambda p: p.num_handles),
2559 FieldListField("num_completed_packets_list", None,
2560 LEShortField("num_completed_packets", 0),
2561 count_from=lambda p: p.num_handles)]
2562
2563
2564class HCI_Event_Link_Key_Request(Packet):
2565 """
2566 7.7.23 Link Key Request event
2567 """
2568 name = 'HCI_Link_Key_Request'
2569 fields_desc = [
2570 LEMACField('bd_addr', None)
2571 ]
2572
2573
2574class HCI_Event_Inquiry_Result_With_Rssi(Packet):
2575 """
2576 7.7.33 Inquiry Result with RSSI event
2577 """
2578 name = "HCI_Inquiry_Result_with_RSSI"
2579 fields_desc = [
2580 ByteField("num_response", 0x00),
2581 FieldListField("bd_addr", None, LEMACField,
2582 count_from=lambda p: p.num_response),
2583 FieldListField("page_scan_repetition_mode", None, ByteField,
2584 count_from=lambda p: p.num_response),
2585 FieldListField("reserved", None, LEShortField,
2586 count_from=lambda p: p.num_response),
2587 FieldListField("device_class", None, XLE3BytesField,
2588 count_from=lambda p: p.num_response),
2589 FieldListField("clock_offset", None, LEShortField,
2590 count_from=lambda p: p.num_response),
2591 FieldListField("rssi", None, SignedByteField,
2592 count_from=lambda p: p.num_response)
2593 ]
2594
2595
2596class HCI_Event_Read_Remote_Extended_Features_Complete(Packet):
2597 """
2598 7.7.34 Read Remote Extended Features Complete event
2599 """
2600 name = "HCI_Read_Remote_Extended_Features_Complete"
2601 fields_desc = [
2602 ByteEnumField('status', 0, _bluetooth_error_codes),
2603 LEShortField('handle', 0),
2604 ByteField('page', 0x00),
2605 ByteField('max_page', 0x00),
2606 XLELongField('extended_features', 0)
2607 ]
2608
2609
2610class HCI_Event_Extended_Inquiry_Result(Packet):
2611 """
2612 7.7.38 Extended Inquiry Result event
2613 """
2614 name = "HCI_Extended_Inquiry_Result"
2615 fields_desc = [
2616 ByteField('num_response', 0x01),
2617 LEMACField('bd_addr', None),
2618 ByteField('page_scan_repetition_mode', 0x00),
2619 ByteField('reserved', 0x00),
2620 XLE3BytesField('device_class', 0x000000),
2621 LEShortField('clock_offset', 0x0000),
2622 SignedByteField('rssi', 0x00),
2623 HCI_Extended_Inquiry_Response,
2624 ]
2625
2626
2627class HCI_Event_IO_Capability_Response(Packet):
2628 """
2629 7.7.41 IO Capability Response event
2630 """
2631 name = "HCI_IO_Capability_Response"
2632 fields_desc = [
2633 LEMACField('bd_addr', None),
2634 ByteField('io_capability', 0x00),
2635 ByteField('oob_data_present', 0x00),
2636 ByteField('authentication_requirements', 0x00)
2637 ]
2638
2639
2640class HCI_Event_LE_Meta(Packet):
2641 """
2642 7.7.65 LE Meta event
2643 """
2644 name = "HCI_LE_Meta"
2645 fields_desc = [ByteEnumField("event", 0, {
2646 0x01: "connection_complete",
2647 0x02: "advertising_report",
2648 0x03: "connection_update_complete",
2649 0x04: "read_remote_features_page_0_complete",
2650 0x05: "long_term_key_request",
2651 0x06: "remote_connection_parameter_request",
2652 0x07: "data_length_change",
2653 0x08: "read_local_p256_public_key_complete",
2654 0x09: "generate_dhkey_complete",
2655 0x0a: "enhanced_connection_complete_v1",
2656 0x0b: "directed_advertising_report",
2657 0x0c: "phy_update_complete",
2658 0x0d: "extended_advertising_report",
2659 0x29: "enhanced_connection_complete_v2"
2660 }), ]
2661
2662 def answers(self, other):
2663 if not self.payload:
2664 return False
2665
2666 # Delegate answers to payload
2667 return self.payload.answers(other)
2668
2669
2670class HCI_Cmd_Complete_Read_Local_Name(Packet):
2671 """
2672 7.3.12 Read Local Name command complete
2673 """
2674 name = 'Read Local Name command complete'
2675 fields_desc = [StrFixedLenField('local_name', '', length=248)]
2676
2677
2678class HCI_Cmd_Complete_Read_Local_Version_Information(Packet):
2679 """
2680 7.4.1 Read Local Version Information command complete
2681 """
2682 name = 'Read Local Version Information'
2683 fields_desc = [
2684 ByteEnumField('hci_version', 0, _bluetooth_core_specification_versions),
2685 LEShortField('hci_subversion', 0),
2686 ByteEnumField('lmp_version', 0, _bluetooth_core_specification_versions),
2687 LEShortEnumField('company_identifier', 0, BLUETOOTH_CORE_COMPANY_IDENTIFIERS),
2688 LEShortField('lmp_subversion', 0)]
2689
2690
2691class HCI_Cmd_Complete_Read_Local_Extended_Features(Packet):
2692 """
2693 7.4.4 Read Local Extended Features command complete
2694 """
2695 name = 'Read Local Extended Features command complete'
2696 fields_desc = [
2697 ByteField('page', 0x00),
2698 ByteField('max_page', 0x00),
2699 XLELongField('extended_features', 0)
2700 ]
2701
2702
2703class HCI_Cmd_Complete_Read_BD_Addr(Packet):
2704 """
2705 7.4.6 Read BD_ADDR command complete
2706 """
2707 name = "Read BD Addr"
2708 fields_desc = [LEMACField("addr", None), ]
2709
2710
2711class HCI_Cmd_Complete_LE_Read_White_List_Size(Packet):
2712 name = "LE Read White List Size"
2713 fields_desc = [ByteField("status", 0),
2714 ByteField("size", 0), ]
2715
2716
2717class HCI_LE_Meta_Connection_Complete(Packet):
2718 name = "Connection Complete"
2719 fields_desc = [ByteEnumField("status", 0, {0: "success"}),
2720 LEShortField("handle", 0),
2721 ByteEnumField("role", 0, {0: "master"}),
2722 ByteEnumField("peer_addr_type", 0, {0: "public", 1: "random"}),
2723 LEMACField("peer_addr", None),
2724 LEShortField("interval", 54),
2725 LEShortField("latency", 0),
2726 LEShortField("supervision", 42),
2727 XByteField("master_clock_accuracy", 5)]
2728 deprecated_fields = {
2729 "patype": ("peer_addr_type", "2.7.0"),
2730 "paddr": ("peer_addr", "2.7.0"),
2731 "clock_latency": ("master_clock_accuracy", "2.7.0"),
2732 }
2733
2734 def answers(self, other):
2735 if HCI_Cmd_LE_Create_Connection in other:
2736 cmd = other[HCI_Cmd_LE_Create_Connection]
2737 elif HCI_Cmd_LE_Extended_Create_Connection in other:
2738 cmd = other[HCI_Cmd_LE_Extended_Create_Connection]
2739 else:
2740 return False
2741
2742 return (cmd.peer_addr_type == self.peer_addr_type and
2743 cmd.peer_addr == self.peer_addr)
2744
2745
2746class HCI_LE_Meta_Enhanced_Connection_Complete(Packet):
2747 name = 'LE Enhanced Connection Complete'
2748 fields_desc = [ByteEnumField('status', 0, {0: 'success'}),
2749 LEShortField('handle', 0),
2750 ByteEnumField('role', 0, {0: 'master', 1: 'slave'}),
2751 ByteEnumField('peer_addr_type', 0, {
2752 0: 'public',
2753 1: 'random',
2754 2: 'public_identity',
2755 3: 'random_identity'}),
2756 LEMACField('peer_addr', None),
2757 LEMACField('local_rpa', None),
2758 LEMACField('peer_rpa', None),
2759 LEShortField('interval', 54),
2760 LEShortField('latency', 0),
2761 LEShortField('supervision', 42),
2762 XByteField('master_clock_accuracy', 5)]
2763
2764 def answers(self, other):
2765 if HCI_Cmd_LE_Create_Connection in other:
2766 cmd = other[HCI_Cmd_LE_Create_Connection]
2767 elif HCI_Cmd_LE_Extended_Create_Connection in other:
2768 cmd = other[HCI_Cmd_LE_Extended_Create_Connection]
2769 else:
2770 return False
2771
2772 return cmd.peer_addr_type == self.peer_addr_type and cmd.peer_addr == self.peer_addr # noqa: E501
2773
2774
2775class HCI_LE_Meta_Connection_Update_Complete(Packet):
2776 name = "Connection Update Complete"
2777 fields_desc = [ByteEnumField("status", 0, {0: "success"}),
2778 LEShortField("handle", 0),
2779 LEShortField("interval", 54),
2780 LEShortField("latency", 0),
2781 LEShortField("timeout", 42), ]
2782
2783
2784class HCI_LE_Meta_Advertising_Report(Packet):
2785 name = "Advertising Report"
2786 fields_desc = [ByteEnumField("type", 0, {0: "conn_und", 4: "scan_rsp"}),
2787 ByteEnumField("addr_type", 0, {0: "public", 1: "random"}),
2788 LEMACField("addr", None),
2789 FieldLenField("len", None, length_of="data", fmt="B"),
2790 PacketListField("data", [], EIR_Hdr,
2791 length_from=lambda pkt: pkt.len),
2792 SignedByteField("rssi", 0)]
2793 deprecated_fields = {"atype": ("addr_type", "2.7.0")}
2794
2795 def extract_padding(self, s):
2796 return '', s
2797
2798
2799class HCI_LE_Meta_Advertising_Reports(Packet):
2800 name = "Advertising Reports"
2801 fields_desc = [FieldLenField("len", None, count_of="reports", fmt="B"),
2802 PacketListField("reports", None,
2803 HCI_LE_Meta_Advertising_Report,
2804 count_from=lambda pkt: pkt.len)]
2805
2806
2807class HCI_LE_Meta_Long_Term_Key_Request(Packet):
2808 name = "Long Term Key Request"
2809 fields_desc = [LEShortField("handle", 0),
2810 StrFixedLenField("rand", None, 8),
2811 XLEShortField("ediv", 0), ]
2812
2813
2814class HCI_LE_Meta_Extended_Advertising_Report(Packet):
2815 name = "Extended Advertising Report"
2816 fields_desc = [
2817 BitField("reserved0", 0, 1),
2818 BitEnumField("data_status", 0, 2, {
2819 0b00: "complete",
2820 0b01: "incomplete",
2821 0b10: "incomplete_truncated",
2822 0b11: "reserved"
2823 }),
2824 BitField("legacy", 0, 1),
2825 BitField("scan_response", 0, 1),
2826 BitField("directed", 0, 1),
2827 BitField("scannable", 0, 1),
2828 BitField("connectable", 0, 1),
2829 ByteField("reserved", 0),
2830 ByteEnumField("addr_type", 0, {
2831 0x00: "public_device_address",
2832 0x01: "random_device_address",
2833 0x02: "public_identity_address",
2834 0x03: "random_identity_address",
2835 0xff: "anonymous"
2836 }),
2837 LEMACField('addr', None),
2838 ByteEnumField("primary_phy", 0, {
2839 0x01: "le_1m",
2840 0x03: "le_coded_s8",
2841 0x04: "le_coded_s2"
2842 }),
2843 ByteEnumField("secondary_phy", 0, {
2844 0x01: "le_1m",
2845 0x02: "le_2m",
2846 0x03: "le_coded_s8",
2847 0x04: "le_coded_s2"
2848 }),
2849 ByteField("advertising_sid", 0xff),
2850 ByteField("tx_power", 0x7f),
2851 SignedByteField("rssi", 0x00),
2852 LEShortField("periodic_advertising_interval", 0x0000),
2853 ByteEnumField("direct_addr_type", 0, {
2854 0x00: "public_device_address",
2855 0x01: "non_resolvable_private_address",
2856 0x02: "resolvable_private_address_resolved_0",
2857 0x03: "resolvable_private_address_resolved_1",
2858 0xfe: "resolvable_private_address_unable_resolve"}),
2859 LEMACField("direct_addr", None),
2860 FieldLenField("data_length", None, length_of="data", fmt="B"),
2861 PacketListField("data", [], EIR_Hdr,
2862 length_from=lambda pkt: pkt.data_length),
2863 ]
2864 deprecated_fields = {
2865 "address_type": ("addr_type", "2.7.0"),
2866 "address": ("addr", "2.7.0"),
2867 "direct_address_type": ("direct_addr_type", "2.7.0"),
2868 "direct_address": ("direct_addr", "2.7.0"),
2869 }
2870
2871 def extract_padding(self, s):
2872 return '', s
2873
2874
2875class HCI_LE_Meta_Extended_Advertising_Reports(Packet):
2876 name = "Extended Advertising Reports"
2877 fields_desc = [FieldLenField("num_reports", None, count_of="reports", fmt="B"),
2878 PacketListField("reports", None,
2879 HCI_LE_Meta_Extended_Advertising_Report,
2880 count_from=lambda pkt: pkt.num_reports)]
2881
2882
2883bind_layers(HCI_PHDR_Hdr, HCI_Hdr)
2884
2885bind_layers(HCI_Hdr, HCI_Command_Hdr, type=1)
2886bind_layers(HCI_Hdr, HCI_ACL_Hdr, type=2)
2887bind_layers(HCI_Hdr, HCI_Event_Hdr, type=4)
2888bind_layers(HCI_Hdr, conf.raw_layer,)
2889
2890conf.l2types.register(DLT_BLUETOOTH_HCI_H4, HCI_Hdr)
2891conf.l2types.register(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, HCI_PHDR_Hdr)
2892
2893
2894# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01
2895bind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry, ogf=0x01, ocf=0x0001)
2896bind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry_Cancel, ogf=0x01, ocf=0x0002)
2897bind_layers(HCI_Command_Hdr, HCI_Cmd_Periodic_Inquiry_Mode, ogf=0x01, ocf=0x0003)
2898bind_layers(HCI_Command_Hdr, HCI_Cmd_Exit_Peiodic_Inquiry_Mode, ogf=0x01, ocf=0x0004)
2899bind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection, ogf=0x01, ocf=0x0005)
2900bind_layers(HCI_Command_Hdr, HCI_Cmd_Disconnect, ogf=0x01, ocf=0x0006)
2901bind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection_Cancel, ogf=0x01, ocf=0x0008)
2902bind_layers(HCI_Command_Hdr, HCI_Cmd_Accept_Connection_Request, ogf=0x01, ocf=0x0009)
2903bind_layers(HCI_Command_Hdr, HCI_Cmd_Reject_Connection_Response, ogf=0x01, ocf=0x000a)
2904bind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Reply, ogf=0x01, ocf=0x000b)
2905bind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Negative_Reply,
2906 ogf=0x01, ocf=0x000c)
2907bind_layers(HCI_Command_Hdr, HCI_Cmd_PIN_Code_Request_Reply, ogf=0x01, ocf=0x000d)
2908bind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Packet_Type,
2909 ogf=0x01, ocf=0x000f)
2910bind_layers(HCI_Command_Hdr, HCI_Cmd_Authentication_Requested, ogf=0x01, ocf=0x0011)
2911bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Connection_Encryption, ogf=0x01, ocf=0x0013)
2912bind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Link_Key, ogf=0x01, ocf=0x0017)
2913bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request, ogf=0x01, ocf=0x0019)
2914bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request_Cancel, ogf=0x01, ocf=0x001a)
2915bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Supported_Features,
2916 ogf=0x01, ocf=0x001b)
2917bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Extended_Features,
2918 ogf=0x01, ocf=0x001c)
2919bind_layers(HCI_Command_Hdr, HCI_Cmd_IO_Capability_Request_Reply, ogf=0x01, ocf=0x002b)
2920bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Reply,
2921 ogf=0x01, ocf=0x002c)
2922bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Negative_Reply,
2923 ogf=0x01, ocf=0x002d)
2924bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Reply, ogf=0x01, ocf=0x002e)
2925bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Negative_Reply,
2926 ogf=0x01, ocf=0x002f)
2927bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Reply,
2928 ogf=0x01, ocf=0x0030)
2929bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply,
2930 ogf=0x01, ocf=0x0033)
2931
2932# 7.2 Link Policy commands, the OGF is defined as 0x02
2933bind_layers(HCI_Command_Hdr, HCI_Cmd_Hold_Mode, ogf=0x02, ocf=0x0001)
2934
2935# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03
2936bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Mask, ogf=0x03, ocf=0x0001)
2937bind_layers(HCI_Command_Hdr, HCI_Cmd_Reset, ogf=0x03, ocf=0x0003)
2938bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Filter, ogf=0x03, ocf=0x0005)
2939bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Local_Name, ogf=0x03, ocf=0x0013)
2940bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Name, ogf=0x03, ocf=0x0014)
2941bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Connect_Accept_Timeout, ogf=0x03, ocf=0x0016)
2942bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Extended_Inquiry_Response, ogf=0x03, ocf=0x0052) # noqa: E501
2943bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_LE_Host_Support, ogf=0x03, ocf=0x006c)
2944bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_LE_Host_Support, ogf=0x03, ocf=0x006d)
2945
2946# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04
2947bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Version_Information, ogf=0x04, ocf=0x0001) # noqa: E501
2948bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Extended_Features, ogf=0x04, ocf=0x0004)
2949bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_BD_Addr, ogf=0x04, ocf=0x0009)
2950
2951# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05
2952bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Link_Quality, ogf=0x05, ocf=0x0003)
2953bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_RSSI, ogf=0x05, ocf=0x0005)
2954
2955# 7.6 TESTING COMMANDS, the OGF is defined as 0x06
2956bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Loopback_Mode, ogf=0x06, ocf=0x0001)
2957bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Loopback_Mode, ogf=0x06, ocf=0x0002)
2958
2959# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08
2960bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Event_Mask, ogf=0x08, ocf=0x0001)
2961bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V1, ogf=0x08, ocf=0x0002)
2962bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V2, ogf=0x08, ocf=0x0060)
2963bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Local_Supported_Features,
2964 ogf=0x08, ocf=0x0003)
2965bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Random_Address, ogf=0x08, ocf=0x0005)
2966bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Parameters, ogf=0x08, ocf=0x0006) # noqa: E501
2967bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Set_Random_Address, ogf=0x08, ocf=0x0035) # noqa: E501
2968bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Advertising_Parameters, ogf=0x08, ocf=0x0036) # noqa: E501
2969bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Data, ogf=0x08, ocf=0x0008)
2970bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Advertising_Data, ogf=0x08, ocf=0x0037) # noqa: E501
2971bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Response_Data, ogf=0x08, ocf=0x0009)
2972bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertise_Enable, ogf=0x08, ocf=0x000a)
2973bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Advertise_Enable, ogf=0x08, ocf=0x0039) # noqa: E501
2974bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Parameters, ogf=0x08, ocf=0x000b)
2975bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Scan_Parameters, ogf=0x08, ocf=0x0041) # noqa: E501
2976bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Enable, ogf=0x08, ocf=0x000c)
2977bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Scan_Enable, ogf=0x08, ocf=0x0042)
2978bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection, ogf=0x08, ocf=0x000d)
2979bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Extended_Create_Connection, ogf=0x08, ocf=0x0043) # noqa: E501
2980bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection_Cancel, ogf=0x08, ocf=0x000e) # noqa: E501
2981bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Filter_Accept_List_Size,
2982 ogf=0x08, ocf=0x000f)
2983bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Clear_Filter_Accept_List, ogf=0x08, ocf=0x0010)
2984bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Add_Device_To_Filter_Accept_List, ogf=0x08, ocf=0x0011) # noqa: E501
2985bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List, ogf=0x08, ocf=0x0012) # noqa: E501
2986bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Connection_Update, ogf=0x08, ocf=0x0013)
2987bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Remote_Features, ogf=0x08, ocf=0x0016) # noqa: E501
2988bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Enable_Encryption, ogf=0x08, ocf=0x0019) # noqa: E501
2989bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Reply, ogf=0x08, ocf=0x001a) # noqa: E501
2990bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply, ogf=0x08, ocf=0x001b) # noqa: E501
2991
2992# 7.7 EVENTS
2993bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Complete, code=0x01)
2994bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result, code=0x02)
2995bind_layers(HCI_Event_Hdr, HCI_Event_Connection_Complete, code=0x03)
2996bind_layers(HCI_Event_Hdr, HCI_Event_Disconnection_Complete, code=0x05)
2997bind_layers(HCI_Event_Hdr, HCI_Event_Remote_Name_Request_Complete, code=0x07)
2998bind_layers(HCI_Event_Hdr, HCI_Event_Encryption_Change, code=0x08)
2999bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Supported_Features_Complete, code=0x0b)
3000bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Version_Information_Complete, code=0x0c) # noqa: E501
3001bind_layers(HCI_Event_Hdr, HCI_Event_Command_Complete, code=0x0e)
3002bind_layers(HCI_Event_Hdr, HCI_Event_Command_Status, code=0x0f)
3003bind_layers(HCI_Event_Hdr, HCI_Event_Number_Of_Completed_Packets, code=0x13)
3004bind_layers(HCI_Event_Hdr, HCI_Event_Link_Key_Request, code=0x17)
3005bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result_With_Rssi, code=0x22)
3006bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Extended_Features_Complete, code=0x23)
3007bind_layers(HCI_Event_Hdr, HCI_Event_Extended_Inquiry_Result, code=0x2f)
3008bind_layers(HCI_Event_Hdr, HCI_Event_IO_Capability_Response, code=0x32)
3009bind_layers(HCI_Event_Hdr, HCI_Event_LE_Meta, code=0x3e)
3010
3011bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Name, opcode=0x0c14) # noqa: E501
3012bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Version_Information, opcode=0x1001) # noqa: E501
3013bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Extended_Features, opcode=0x1004) # noqa: E501
3014bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_BD_Addr, opcode=0x1009) # noqa: E501
3015bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_LE_Read_White_List_Size, opcode=0x200f) # noqa: E501
3016
3017bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Complete, event=0x01)
3018bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Enhanced_Connection_Complete, event=0x0a)
3019bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Advertising_Reports, event=0x02)
3020bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Update_Complete, event=0x03)
3021bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Long_Term_Key_Request, event=0x05)
3022bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Extended_Advertising_Reports, event=0x0d)
3023
3024bind_layers(EIR_Hdr, EIR_Flags, type=0x01)
3025bind_layers(EIR_Hdr, EIR_IncompleteList16BitServiceUUIDs, type=0x02)
3026bind_layers(EIR_Hdr, EIR_CompleteList16BitServiceUUIDs, type=0x03)
3027bind_layers(EIR_Hdr, EIR_IncompleteList32BitServiceUUIDs, type=0x04)
3028bind_layers(EIR_Hdr, EIR_CompleteList32BitServiceUUIDs, type=0x05)
3029bind_layers(EIR_Hdr, EIR_IncompleteList128BitServiceUUIDs, type=0x06)
3030bind_layers(EIR_Hdr, EIR_CompleteList128BitServiceUUIDs, type=0x07)
3031bind_layers(EIR_Hdr, EIR_ShortenedLocalName, type=0x08)
3032bind_layers(EIR_Hdr, EIR_CompleteLocalName, type=0x09)
3033bind_layers(EIR_Hdr, EIR_Device_ID, type=0x10)
3034bind_layers(EIR_Hdr, EIR_TX_Power_Level, type=0x0a)
3035bind_layers(EIR_Hdr, EIR_ClassOfDevice, type=0x0d)
3036bind_layers(EIR_Hdr, EIR_SecureSimplePairingHashC192, type=0x0e)
3037bind_layers(EIR_Hdr, EIR_SecureSimplePairingRandomizerR192, type=0x0f)
3038bind_layers(EIR_Hdr, EIR_SecurityManagerOOBFlags, type=0x11)
3039bind_layers(EIR_Hdr, EIR_PeripheralConnectionIntervalRange, type=0x12)
3040bind_layers(EIR_Hdr, EIR_ServiceSolicitation16BitUUID, type=0x14)
3041bind_layers(EIR_Hdr, EIR_ServiceSolicitation128BitUUID, type=0x15)
3042bind_layers(EIR_Hdr, EIR_ServiceData16BitUUID, type=0x16)
3043bind_layers(EIR_Hdr, EIR_PublicTargetAddress, type=0x17)
3044bind_layers(EIR_Hdr, EIR_Appearance, type=0x19)
3045bind_layers(EIR_Hdr, EIR_AdvertisingInterval, type=0x1a)
3046bind_layers(EIR_Hdr, EIR_LEBluetoothDeviceAddress, type=0x1b)
3047bind_layers(EIR_Hdr, EIR_ServiceData32BitUUID, type=0x20)
3048bind_layers(EIR_Hdr, EIR_ServiceData128BitUUID, type=0x21)
3049bind_layers(EIR_Hdr, EIR_URI, type=0x24)
3050bind_layers(EIR_Hdr, EIR_Manufacturer_Specific_Data, type=0xff)
3051bind_layers(EIR_Hdr, EIR_Raw)
3052
3053bind_layers(HCI_ACL_Hdr, L2CAP_Hdr,)
3054bind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=1)
3055bind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=5) # LE L2CAP Signaling Channel
3056bind_layers(L2CAP_CmdHdr, L2CAP_CmdRej, code=1)
3057bind_layers(L2CAP_CmdHdr, L2CAP_ConnReq, code=2)
3058bind_layers(L2CAP_CmdHdr, L2CAP_ConnResp, code=3)
3059bind_layers(L2CAP_CmdHdr, L2CAP_ConfReq, code=4)
3060bind_layers(L2CAP_CmdHdr, L2CAP_ConfResp, code=5)
3061bind_layers(L2CAP_CmdHdr, L2CAP_DisconnReq, code=6)
3062bind_layers(L2CAP_CmdHdr, L2CAP_DisconnResp, code=7)
3063bind_layers(L2CAP_CmdHdr, L2CAP_EchoReq, code=8)
3064bind_layers(L2CAP_CmdHdr, L2CAP_EchoResp, code=9)
3065bind_layers(L2CAP_CmdHdr, L2CAP_InfoReq, code=10)
3066bind_layers(L2CAP_CmdHdr, L2CAP_InfoResp, code=11)
3067bind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Request, code=12)
3068bind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Response, code=13)
3069bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Request, code=14)
3070bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Response, code=15)
3071bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Request, code=16)
3072bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Response, code=17)
3073bind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Request, code=18)
3074bind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Response, code=19)
3075bind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Request, code=20)
3076bind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Response, code=21)
3077bind_layers(L2CAP_CmdHdr, L2CAP_Flow_Control_Credit_Ind, code=22)
3078bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Request, code=23)
3079bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Response, code=24)
3080bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Request, code=25)
3081bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Response, code=26)
3082bind_layers(L2CAP_Hdr, ATT_Hdr, cid=4)
3083bind_layers(ATT_Hdr, ATT_Error_Response, opcode=0x1)
3084bind_layers(ATT_Hdr, ATT_Exchange_MTU_Request, opcode=0x2)
3085bind_layers(ATT_Hdr, ATT_Exchange_MTU_Response, opcode=0x3)
3086bind_layers(ATT_Hdr, ATT_Find_Information_Request, opcode=0x4)
3087bind_layers(ATT_Hdr, ATT_Find_Information_Response, opcode=0x5)
3088bind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Request, opcode=0x6)
3089bind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Response, opcode=0x7)
3090bind_layers(ATT_Hdr, ATT_Read_By_Type_Request_128bit, opcode=0x8)
3091bind_layers(ATT_Hdr, ATT_Read_By_Type_Request, opcode=0x8)
3092bind_layers(ATT_Hdr, ATT_Read_By_Type_Response, opcode=0x9)
3093bind_layers(ATT_Hdr, ATT_Read_Request, opcode=0xa)
3094bind_layers(ATT_Hdr, ATT_Read_Response, opcode=0xb)
3095bind_layers(ATT_Hdr, ATT_Read_Blob_Request, opcode=0xc)
3096bind_layers(ATT_Hdr, ATT_Read_Blob_Response, opcode=0xd)
3097bind_layers(ATT_Hdr, ATT_Read_Multiple_Request, opcode=0xe)
3098bind_layers(ATT_Hdr, ATT_Read_Multiple_Response, opcode=0xf)
3099bind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Request, opcode=0x10)
3100bind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Response, opcode=0x11)
3101bind_layers(ATT_Hdr, ATT_Write_Request, opcode=0x12)
3102bind_layers(ATT_Hdr, ATT_Write_Response, opcode=0x13)
3103bind_layers(ATT_Hdr, ATT_Prepare_Write_Request, opcode=0x16)
3104bind_layers(ATT_Hdr, ATT_Prepare_Write_Response, opcode=0x17)
3105bind_layers(ATT_Hdr, ATT_Execute_Write_Request, opcode=0x18)
3106bind_layers(ATT_Hdr, ATT_Execute_Write_Response, opcode=0x19)
3107bind_layers(ATT_Hdr, ATT_Write_Command, opcode=0x52)
3108bind_layers(ATT_Hdr, ATT_Handle_Value_Notification, opcode=0x1b)
3109bind_layers(ATT_Hdr, ATT_Handle_Value_Indication, opcode=0x1d)
3110bind_layers(L2CAP_Hdr, SM_Hdr, cid=6)
3111bind_layers(SM_Hdr, SM_Pairing_Request, sm_command=0x01)
3112bind_layers(SM_Hdr, SM_Pairing_Response, sm_command=0x02)
3113bind_layers(SM_Hdr, SM_Confirm, sm_command=0x03)
3114bind_layers(SM_Hdr, SM_Random, sm_command=0x04)
3115bind_layers(SM_Hdr, SM_Failed, sm_command=0x05)
3116bind_layers(SM_Hdr, SM_Encryption_Information, sm_command=0x06)
3117bind_layers(SM_Hdr, SM_Master_Identification, sm_command=0x07)
3118bind_layers(SM_Hdr, SM_Identity_Information, sm_command=0x08)
3119bind_layers(SM_Hdr, SM_Identity_Address_Information, sm_command=0x09)
3120bind_layers(SM_Hdr, SM_Signing_Information, sm_command=0x0a)
3121bind_layers(SM_Hdr, SM_Security_Request, sm_command=0x0b)
3122bind_layers(SM_Hdr, SM_Public_Key, sm_command=0x0c)
3123bind_layers(SM_Hdr, SM_DHKey_Check, sm_command=0x0d)
3124
3125
3126###############
3127# HCI Monitor #
3128###############
3129
3130
3131# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L27
3132class HCI_Mon_Hdr(Packet):
3133 name = 'Bluetooth Linux Monitor Transport Header'
3134 fields_desc = [
3135 LEShortEnumField('opcode', None, {
3136 0: "New index",
3137 1: "Delete index",
3138 2: "Command pkt",
3139 3: "Event pkt",
3140 4: "ACL TX pkt",
3141 5: "ACL RX pkt",
3142 6: "SCO TX pkt",
3143 7: "SCO RX pkt",
3144 8: "Open index",
3145 9: "Close index",
3146 10: "Index info",
3147 11: "Vendor diag",
3148 12: "System note",
3149 13: "User logging",
3150 14: "Ctrl open",
3151 15: "Ctrl close",
3152 16: "Ctrl command",
3153 17: "Ctrl event",
3154 18: "ISO TX pkt",
3155 19: "ISO RX pkt",
3156 }),
3157 LEShortField('adapter_id', None),
3158 LEShortField('len', None)
3159 ]
3160
3161
3162# https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LINUX_MONITOR.html
3163class HCI_Mon_Pcap_Hdr(HCI_Mon_Hdr):
3164 name = 'Bluetooth Linux Monitor Transport Pcap Header'
3165 fields_desc = [
3166 ShortField('adapter_id', None),
3167 ShortField('opcode', None)
3168 ]
3169
3170
3171class HCI_Mon_New_Index(Packet):
3172 name = 'Bluetooth Linux Monitor Transport New Index Packet'
3173 fields_desc = [
3174 ByteEnumField('bus', 0, {
3175 0x00: "BR/EDR",
3176 0x01: "AMP"
3177 }),
3178 ByteEnumField('type', 0, {
3179 0x00: "Virtual",
3180 0x01: "USB",
3181 0x02: "PC Card",
3182 0x03: "UART",
3183 0x04: "RS232",
3184 0x05: "PCI",
3185 0x06: "SDIO"
3186 }),
3187 LEMACField('addr', None),
3188 StrFixedLenField('devname', None, 8)
3189 ]
3190
3191
3192class HCI_Mon_Index_Info(Packet):
3193 name = 'Bluetooth Linux Monitor Transport Index Info Packet'
3194 fields_desc = [
3195 LEMACField('addr', None),
3196 XLEShortField('manufacturer', None)
3197 ]
3198
3199
3200class HCI_Mon_System_Note(Packet):
3201 name = 'Bluetooth Linux Monitor Transport System Note Packet'
3202 fields_desc = [
3203 StrNullField('note', None)
3204 ]
3205
3206
3207# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L34
3208bind_layers(HCI_Mon_Hdr, HCI_Mon_New_Index, opcode=0)
3209bind_layers(HCI_Mon_Hdr, HCI_Command_Hdr, opcode=2)
3210bind_layers(HCI_Mon_Hdr, HCI_Event_Hdr, opcode=3)
3211bind_layers(HCI_Mon_Hdr, HCI_ACL_Hdr, opcode=5)
3212bind_layers(HCI_Mon_Hdr, HCI_Mon_Index_Info, opcode=10)
3213bind_layers(HCI_Mon_Hdr, HCI_Mon_System_Note, opcode=12)
3214
3215conf.l2types.register(DLT_BLUETOOTH_LINUX_MONITOR, HCI_Mon_Pcap_Hdr)
3216
3217
3218###########
3219# Helpers #
3220###########
3221
3222class LowEnergyBeaconHelper:
3223 """
3224 Helpers for building packets for Bluetooth Low Energy Beacons.
3225
3226 Implementers provide a :meth:`build_eir` implementation.
3227
3228 This is designed to be used as a mix-in -- see
3229 ``scapy.contrib.eddystone`` and ``scapy.contrib.ibeacon`` for examples.
3230 """
3231
3232 # Basic flags that should be used by most beacons.
3233 base_eir = [EIR_Hdr() / EIR_Flags(flags=[
3234 "general_disc_mode", "br_edr_not_supported"]), ]
3235
3236 def build_eir(self):
3237 """
3238 Builds a list of EIR messages to wrap this frame.
3239
3240 Users of this helper must implement this method.
3241
3242 :return: List of HCI_Hdr with payloads that describe this beacon type
3243 :rtype: list[scapy.bluetooth.HCI_Hdr]
3244 """
3245 raise NotImplementedError("build_eir")
3246
3247 def build_advertising_report(self):
3248 """
3249 Builds a HCI_LE_Meta_Advertising_Report containing this frame.
3250
3251 :rtype: scapy.bluetooth.HCI_LE_Meta_Advertising_Report
3252 """
3253
3254 return HCI_LE_Meta_Advertising_Report(
3255 type=0, # Undirected
3256 addr_type=1, # Random address
3257 data=self.build_eir()
3258 )
3259
3260 def build_set_advertising_data(self):
3261 """Builds a HCI_Cmd_LE_Set_Advertising_Data containing this frame.
3262
3263 This includes the :class:`HCI_Hdr` and :class:`HCI_Command_Hdr` layers.
3264
3265 :rtype: scapy.bluetooth.HCI_Hdr
3266 """
3267
3268 return HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Set_Advertising_Data(
3269 data=self.build_eir()
3270 )
3271
3272
3273###########
3274# Sockets #
3275###########
3276
3277class BluetoothSocketError(BaseException):
3278 pass
3279
3280
3281class BluetoothCommandError(BaseException):
3282 pass
3283
3284
3285class BluetoothL2CAPSocket(SuperSocket):
3286 desc = "read/write packets on a connected L2CAP socket"
3287
3288 def __init__(self, bt_address):
3289 if WINDOWS:
3290 warning("Not available on Windows")
3291 return
3292 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
3293 socket.BTPROTO_L2CAP)
3294 s.connect((bt_address, 0))
3295 self.ins = self.outs = s
3296
3297 def recv(self, x=MTU):
3298 return L2CAP_CmdHdr(self.ins.recv(x))
3299
3300
3301class BluetoothRFCommSocket(BluetoothL2CAPSocket):
3302 """read/write packets on a connected RFCOMM socket"""
3303
3304 def __init__(self, bt_address, port=0):
3305 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
3306 socket.BTPROTO_RFCOMM)
3307 s.connect((bt_address, port))
3308 self.ins = self.outs = s
3309
3310
3311class BluetoothHCISocket(SuperSocket):
3312 desc = "read/write on a BlueTooth HCI socket"
3313
3314 def __init__(self, iface=0x10000, type=None):
3315 if WINDOWS:
3316 warning("Not available on Windows")
3317 return
3318 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) # noqa: E501
3319 s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR, 1)
3320 s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP, 1)
3321 s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffff, 0xffffffff, 0xffffffff, 0)) # type mask, event mask, event mask, opcode # noqa: E501
3322 s.bind((iface,))
3323 self.ins = self.outs = s
3324# s.connect((peer,0))
3325
3326 def recv(self, x=MTU):
3327 return HCI_Hdr(self.ins.recv(x))
3328
3329
3330class sockaddr_hci(ctypes.Structure):
3331 _fields_ = [
3332 ("sin_family", ctypes.c_ushort),
3333 ("hci_dev", ctypes.c_ushort),
3334 ("hci_channel", ctypes.c_ushort),
3335 ]
3336
3337
3338class _BluetoothLibcSocket(SuperSocket):
3339 def __init__(self, socket_domain, socket_type, socket_protocol, sock_address):
3340 # type: (int, int, int, sockaddr_hci) -> None
3341 if WINDOWS:
3342 warning("Not available on Windows")
3343 return
3344 # Python socket and bind implementations do not allow us to pass down
3345 # the correct parameters. We must call libc functions directly via
3346 # ctypes.
3347 sockaddr_hcip = ctypes.POINTER(sockaddr_hci)
3348 from ctypes.util import find_library
3349 libc = ctypes.cdll.LoadLibrary(find_library("c"))
3350
3351 socket_c = libc.socket
3352 socket_c.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_int)
3353 socket_c.restype = ctypes.c_int
3354
3355 bind = libc.bind
3356 bind.argtypes = (ctypes.c_int,
3357 ctypes.POINTER(sockaddr_hci),
3358 ctypes.c_int)
3359 bind.restype = ctypes.c_int
3360
3361 # Socket
3362 s = socket_c(socket_domain, socket_type, socket_protocol)
3363 if s < 0:
3364 raise BluetoothSocketError(
3365 f"Unable to open socket({socket_domain}, {socket_type}, "
3366 f"{socket_protocol})")
3367
3368 # Bind
3369 r = bind(s, sockaddr_hcip(sock_address), sizeof(sock_address))
3370 if r != 0:
3371 raise BluetoothSocketError("Unable to bind")
3372
3373 self.hci_fd = s
3374 self.ins = self.outs = socket.fromfd(
3375 s, socket_domain, socket_type, socket_protocol)
3376
3377 def readable(self, timeout=0):
3378 (ins, _, _) = select.select([self.ins], [], [], timeout)
3379 return len(ins) > 0
3380
3381 def flush(self):
3382 while self.readable():
3383 self.recv()
3384
3385 def close(self):
3386 if self.closed:
3387 return
3388
3389 # Properly close socket so we can free the device
3390 from ctypes.util import find_library
3391 libc = ctypes.cdll.LoadLibrary(find_library("c"))
3392
3393 close = libc.close
3394 close.restype = ctypes.c_int
3395 self.closed = True
3396 if hasattr(self, "outs"):
3397 if not hasattr(self, "ins") or self.ins != self.outs:
3398 if self.outs and (WINDOWS or self.outs.fileno() != -1):
3399 close(self.outs.fileno())
3400 if hasattr(self, "ins"):
3401 if self.ins and (WINDOWS or self.ins.fileno() != -1):
3402 close(self.ins.fileno())
3403 if hasattr(self, "hci_fd"):
3404 close(self.hci_fd)
3405
3406
3407class BluetoothUserSocket(_BluetoothLibcSocket):
3408 desc = "read/write H4 over a Bluetooth user channel"
3409
3410 def __init__(self, adapter_index=0):
3411 sa = sockaddr_hci()
3412 sa.sin_family = socket.AF_BLUETOOTH
3413 sa.hci_dev = adapter_index
3414 sa.hci_channel = HCI_CHANNEL_USER
3415 super().__init__(
3416 socket_domain=socket.AF_BLUETOOTH,
3417 socket_type=socket.SOCK_RAW,
3418 socket_protocol=socket.BTPROTO_HCI,
3419 sock_address=sa)
3420
3421 def send_command(self, cmd):
3422 opcode = cmd[HCI_Command_Hdr].opcode
3423 self.send(cmd)
3424 while True:
3425 r = self.recv()
3426 if r.type == 0x04 and r.code in (0xe, 0xf) and r.opcode == opcode:
3427 if hasattr(r, 'status') and r.status != 0:
3428 raise BluetoothCommandError("Command %x failed with %x" % (opcode, r.status)) # noqa: E501
3429 return r
3430
3431 def recv(self, x=MTU):
3432 return HCI_Hdr(self.ins.recv(x))
3433
3434
3435class BluetoothMonitorSocket(_BluetoothLibcSocket):
3436 desc = "Read/write over a Bluetooth monitor channel"
3437
3438 def __init__(self):
3439 sa = sockaddr_hci()
3440 sa.sin_family = socket.AF_BLUETOOTH
3441 sa.hci_dev = HCI_DEV_NONE
3442 sa.hci_channel = HCI_CHANNEL_MONITOR
3443 super().__init__(
3444 socket_domain=socket.AF_BLUETOOTH,
3445 socket_type=socket.SOCK_RAW,
3446 socket_protocol=socket.BTPROTO_HCI,
3447 sock_address=sa)
3448
3449 def recv(self, x=MTU):
3450 return HCI_Mon_Hdr(self.ins.recv(x))
3451
3452
3453conf.BTsocket = BluetoothRFCommSocket
3454
3455# Bluetooth
3456
3457
3458@conf.commands.register
3459def srbt(bt_address, pkts, inter=0.1, *args, **kargs):
3460 """send and receive using a bluetooth socket"""
3461 if "port" in kargs:
3462 s = conf.BTsocket(bt_address=bt_address, port=kargs.pop("port"))
3463 else:
3464 s = conf.BTsocket(bt_address=bt_address)
3465 a, b = sndrcv(s, pkts, inter=inter, *args, **kargs)
3466 s.close()
3467 return a, b
3468
3469
3470@conf.commands.register
3471def srbt1(bt_address, pkts, *args, **kargs):
3472 """send and receive 1 packet using a bluetooth socket"""
3473 a, b = srbt(bt_address, pkts, *args, **kargs)
3474 if len(a) > 0:
3475 return a[0][1]