5#include <QtCore/qloggingcategory.h>
6#include <QtCore/qsocketnotifier.h>
7#include <QtCore/qtimer.h>
11#include "../qbluetoothsocketbase_p.h"
15#include <sys/syscall.h>
17#include <linux/capability.h>
27 quint16 controllerIndex;
29}
__attribute__((packed));
38}
__attribute__((packed));
42
43
44
45
46
47
48
49
50
52Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
69#define _LINUX_CAPABILITY_VERSION_3 0x20080522
73#define _LINUX_CAPABILITY_U32S_3 2
77#define CAP_NET_ADMIN 12
81#define CAP_TO_INDEX(x) ((x) >> 5
)
85#define CAP_TO_MASK(x) (1
<< ((x) & 31
))
92 return syscall(__NR_capget, header, data);
96
97
103 struct capHdr header = {};
106 header
.pid = getpid();
109 qCWarning(QT_BT_BLUEZ,
"BluetoothManangement: getCap failed with %s",
110 qPrintable(qt_error_string(errno)));
120 if (!hasPermission) {
121 qCInfo(QT_BT_BLUEZ,
"Missing CAP_NET_ADMIN permission. Cannot determine whether "
122 "a found address is of random or public type.");
128 fd = ::socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
BTPROTO_HCI);
130 qCWarning(QT_BT_BLUEZ,
"Cannot open Bluetooth Management socket: %s",
131 qPrintable(qt_error_string(errno)));
135 memset(&hciAddr, 0,
sizeof(hciAddr));
138 hciAddr.hci_family = AF_BLUETOOTH;
140 if (::bind(fd, (
struct sockaddr *)(&hciAddr),
sizeof(hciAddr)) < 0) {
141 qCWarning(QT_BT_BLUEZ,
"Cannot bind Bluetooth Management socket: %s",
142 qPrintable(qt_error_string(errno)));
148 notifier =
new QSocketNotifier(fd, QSocketNotifier::Read,
this);
149 connect(notifier, &QSocketNotifier::activated,
this, &BluetoothManagement::_q_readNotifier);
152 QTimer* timer =
new QTimer(
this);
154 timer->setTimerType(Qt::VeryCoarseTimer);
155 connect(timer, &QTimer::timeout,
this, &BluetoothManagement::cleanupOldAddressFlags);
163 return bluetoothKernelManager();
172 qCWarning(QT_BT_BLUEZ,
"Management Control read error %s", qPrintable(qt_error_string(errno)));
177 if (size_t(buffer.size()) <
sizeof(MgmtHdr))
180 QByteArray data = buffer.readAll();
183 if (size_t(data.size()) <
sizeof(MgmtHdr))
186 const MgmtHdr *hdr =
reinterpret_cast<
const MgmtHdr*>(data.constData());
187 const auto nextPackageSize = qsizetype(qFromLittleEndian(hdr->length) +
sizeof(MgmtHdr));
188 const qsizetype remainingPackageSize = data.size() - nextPackageSize;
190 if (data.size() < nextPackageSize)
193 switch (
static_cast<EventCode>(qFromLittleEndian(hdr->cmdCode))) {
194 case EventCode::DeviceFoundEvent:
197 (data.constData() +
sizeof(MgmtHdr));
200 const bdaddr_t address = event->bdaddr;
203 convertAddress(address.b, &bdaddr);
204 const QBluetoothAddress qtAddress(bdaddr);
205 qCDebug(QT_BT_BLUEZ) <<
"BluetoothManagement: found random device"
207 processRandomAddressFlagInformation(qtAddress);
213 qCDebug(QT_BT_BLUEZ) <<
"BluetoothManagement: Ignored event:"
214 << Qt::hex << (EventCode)qFromLittleEndian(hdr->cmdCode);
218 if (data.size() > nextPackageSize)
219 data = data.right(remainingPackageSize);
228 buffer.ungetBlock(data.constData(), data.size());
231void BluetoothManagement::processRandomAddressFlagInformation(
const QBluetoothAddress &address)
234 QMutexLocker locker(&accessLock);
235 privateFlagAddresses[address] = QDateTime::currentDateTimeUtc();
239
240
243 const auto cutOffTime = QDateTime::currentDateTimeUtc().addDays(-1);
245 QMutexLocker locker(&accessLock);
247 auto i = privateFlagAddresses.begin();
248 while (i != privateFlagAddresses.end()) {
249 if (i.value() < cutOffTime)
250 i = privateFlagAddresses.erase(i);
258 if (fd == -1 || address.isNull())
261 QMutexLocker locker(&accessLock);
262 return privateFlagAddresses.contains(address);
267 return (fd == -1) ?
false :
true;
273#include "moc_bluetoothmanagement_p.cpp"
#define _LINUX_CAPABILITY_U32S_3
#define _LINUX_CAPABILITY_VERSION_3
static int sysCallCapGet(capHdr *header, capData *data)
static bool hasBtMgmtPermission()
#define QPRIVATELINEARBUFFER_BUFFERSIZE
#define HCI_CHANNEL_CONTROL
bool isAddressRandom(const QBluetoothAddress &address) const
bool isMonitoringEnabled() const
static BluetoothManagement * instance()
unsigned short hci_channel