Skip to content

Commit eae1567

Browse files
Bluetooth: refactor Bluetooth Monitor packets (#4091)
* Add many Bluetooth Monitor packets * Restore HCI_MON in bluetooth.py --------- Co-authored-by: gpotter2 <10530980+gpotter2@users.noreply.github.com>
1 parent d2d76fc commit eae1567

File tree

2 files changed

+129
-26
lines changed

2 files changed

+129
-26
lines changed

scapy/layers/bluetooth.py

Lines changed: 94 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
StrField,
4747
StrFixedLenField,
4848
StrLenField,
49+
StrNullField,
4950
UUIDField,
5051
XByteField,
5152
XLE3BytesField,
@@ -196,24 +197,6 @@ class HCI_PHDR_Hdr(Packet):
196197
}
197198

198199

199-
class BT_Mon_Hdr(Packet):
200-
name = 'Bluetooth Linux Monitor Transport Header'
201-
fields_desc = [
202-
LEShortField('opcode', None),
203-
LEShortField('adapter_id', None),
204-
LEShortField('len', None)
205-
]
206-
207-
208-
# https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LINUX_MONITOR.html
209-
class BT_Mon_Pcap_Hdr(BT_Mon_Hdr):
210-
name = 'Bluetooth Linux Monitor Transport Pcap Header'
211-
fields_desc = [
212-
ShortField('adapter_id', None),
213-
ShortField('opcode', None)
214-
]
215-
216-
217200
class HCI_Hdr(Packet):
218201
name = "HCI header"
219202
fields_desc = [ByteEnumField("type", 2, _bluetooth_packet_types)]
@@ -1889,7 +1872,6 @@ class HCI_LE_Meta_Long_Term_Key_Request(Packet):
18891872

18901873
conf.l2types.register(DLT_BLUETOOTH_HCI_H4, HCI_Hdr)
18911874
conf.l2types.register(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, HCI_PHDR_Hdr)
1892-
conf.l2types.register(DLT_BLUETOOTH_LINUX_MONITOR, BT_Mon_Pcap_Hdr)
18931875

18941876

18951877
# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01
@@ -2084,6 +2066,97 @@ class HCI_LE_Meta_Long_Term_Key_Request(Packet):
20842066
bind_layers(SM_Hdr, SM_DHKey_Check, sm_command=0x0d)
20852067

20862068

2069+
###############
2070+
# HCI Monitor #
2071+
###############
2072+
2073+
2074+
# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L27
2075+
class HCI_Mon_Hdr(Packet):
2076+
name = 'Bluetooth Linux Monitor Transport Header'
2077+
fields_desc = [
2078+
LEShortEnumField('opcode', None, {
2079+
0: "New index",
2080+
1: "Delete index",
2081+
2: "Command pkt",
2082+
3: "Event pkt",
2083+
4: "ACL TX pkt",
2084+
5: "ACL RX pkt",
2085+
6: "SCO TX pkt",
2086+
7: "SCO RX pkt",
2087+
8: "Open index",
2088+
9: "Close index",
2089+
10: "Index info",
2090+
11: "Vendor diag",
2091+
12: "System note",
2092+
13: "User logging",
2093+
14: "Ctrl open",
2094+
15: "Ctrl close",
2095+
16: "Ctrl command",
2096+
17: "Ctrl event",
2097+
18: "ISO TX pkt",
2098+
19: "ISO RX pkt",
2099+
}),
2100+
LEShortField('adapter_id', None),
2101+
LEShortField('len', None)
2102+
]
2103+
2104+
2105+
# https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LINUX_MONITOR.html
2106+
class HCI_Mon_Pcap_Hdr(HCI_Mon_Hdr):
2107+
name = 'Bluetooth Linux Monitor Transport Pcap Header'
2108+
fields_desc = [
2109+
ShortField('adapter_id', None),
2110+
ShortField('opcode', None)
2111+
]
2112+
2113+
2114+
class HCI_Mon_New_Index(Packet):
2115+
name = 'Bluetooth Linux Monitor Transport New Index Packet'
2116+
fields_desc = [
2117+
ByteEnumField('bus', 0, {
2118+
0x00: "BR/EDR",
2119+
0x01: "AMP"
2120+
}),
2121+
ByteEnumField('type', 0, {
2122+
0x00: "Virtual",
2123+
0x01: "USB",
2124+
0x02: "PC Card",
2125+
0x03: "UART",
2126+
0x04: "RS232",
2127+
0x05: "PCI",
2128+
0x06: "SDIO"
2129+
}),
2130+
LEMACField('addr', None),
2131+
StrFixedLenField('devname', None, 8)
2132+
]
2133+
2134+
2135+
class HCI_Mon_Index_Info(Packet):
2136+
name = 'Bluetooth Linux Monitor Transport Index Info Packet'
2137+
fields_desc = [
2138+
LEMACField('addr', None),
2139+
XLEShortField('manufacturer', None)
2140+
]
2141+
2142+
2143+
class HCI_Mon_System_Note(Packet):
2144+
name = 'Bluetooth Linux Monitor Transport System Note Packet'
2145+
fields_desc = [
2146+
StrNullField('note', None)
2147+
]
2148+
2149+
2150+
# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L34
2151+
bind_layers(HCI_Mon_Hdr, HCI_Mon_New_Index, opcode=0)
2152+
bind_layers(HCI_Mon_Hdr, HCI_Command_Hdr, opcode=2)
2153+
bind_layers(HCI_Mon_Hdr, HCI_Event_Hdr, opcode=3)
2154+
bind_layers(HCI_Mon_Hdr, HCI_Mon_Index_Info, opcode=10)
2155+
bind_layers(HCI_Mon_Hdr, HCI_Mon_System_Note, opcode=12)
2156+
2157+
conf.l2types.register(DLT_BLUETOOTH_LINUX_MONITOR, HCI_Mon_Pcap_Hdr)
2158+
2159+
20872160
###########
20882161
# Helpers #
20892162
###########
@@ -2302,7 +2375,7 @@ def recv(self, x=MTU):
23022375

23032376

23042377
class BluetoothMonitorSocket(_BluetoothLibcSocket):
2305-
desc = "read/write over a Bluetooth monitor channel"
2378+
desc = "Read/write over a Bluetooth monitor channel"
23062379

23072380
def __init__(self):
23082381
sa = sockaddr_hci()
@@ -2316,7 +2389,7 @@ def __init__(self):
23162389
sock_address=sa)
23172390

23182391
def recv(self, x=MTU):
2319-
return BT_Mon_Hdr(self.ins.recv(x))
2392+
return HCI_Mon_Hdr(self.ins.recv(x))
23202393

23212394

23222395
conf.BTsocket = BluetoothRFCommSocket

test/scapy/layers/bluetooth.uts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,39 @@ p = SM_Hdr(r)
529529
assert SM_DHKey_Check in p and p.dhkey_check[:5] == b"scapy"
530530

531531

532-
= Bluetooth Monitor Pcap Header
532+
+ HCIMon tests
533533

534-
p = BT_Mon_Pcap_Hdr(hex_bytes("00000008"))
535-
assert BT_Mon_Pcap_Hdr in p
536-
assert p[BT_Mon_Pcap_Hdr].adapter_id == 0
537-
assert p[BT_Mon_Pcap_Hdr].opcode == 8
534+
= HCI_Mon - Bluetooth Monitor Pcap Header
535+
536+
p = HCI_Mon_Pcap_Hdr(hex_bytes("00000008"))
537+
assert HCI_Mon_Pcap_Hdr in p
538+
assert p[HCI_Mon_Pcap_Hdr].adapter_id == 0
539+
assert p[HCI_Mon_Pcap_Hdr].opcode == 8
540+
541+
= HCI_Mon - Bluetooth Monitor HCI_Mon_New_Index
542+
543+
p = HCI_Mon_Pcap_Hdr(hex_bytes("0000000000030000109a81206863693000000000"))
544+
assert HCI_Mon_New_Index in p
545+
assert p[HCI_Mon_New_Index].bus == 0
546+
assert p[HCI_Mon_New_Index].type == 3
547+
assert p[HCI_Mon_New_Index].addr == '20:81:9a:10:00:00'
548+
assert p[HCI_Mon_New_Index].devname.decode('utf-8').rstrip('\x00') == 'hci0'
549+
550+
= HCI_Mon - Bluetooth Monitor HCI_Mon_Delete_Index
551+
552+
p = HCI_Mon_Pcap_Hdr(hex_bytes("00000001"))
553+
assert HCI_Mon_Pcap_Hdr in p
554+
assert p[HCI_Mon_Pcap_Hdr].opcode == 1
555+
556+
= HCI_Mon - Bluetooth Monitor HCI_Mon_Index_Info
557+
558+
p = HCI_Mon_Pcap_Hdr(hex_bytes("0000000a0000109a81203101"))
559+
assert HCI_Mon_Index_Info in p
560+
assert p[HCI_Mon_Index_Info].addr == '20:81:9a:10:00:00'
561+
assert p[HCI_Mon_Index_Info].manufacturer == 0x131
562+
563+
= HCI_Mon - Bluetooth Monitor HCI_Mon_System_Note
564+
565+
p = HCI_Mon_Pcap_Hdr(hex_bytes("ffff000c426c7565746f6f74682073756273797374656d2076657273696f6e20322e323200"))
566+
assert HCI_Mon_System_Note in p
567+
assert p[HCI_Mon_System_Note].note == b'Bluetooth subsystem version 2.22'

0 commit comments

Comments
 (0)