summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2018-08-10 09:45:25 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2018-08-10 09:45:25 +0200
commit8d1250c286f3b33bffbb89ae6756c7703f9b8d16 (patch)
tree3e75768105738e3efe7ff751b0b161808abe66c0
parent7b9ad0d7d67e208cd65b7f0e647b41b2b09cc43e (diff)
New upstream version 2018.08.R1
-rw-r--r--README.md4
-rw-r--r--changelog7
-rw-r--r--firmware/bluetooth_rxtx/bluetooth_le.h3
-rw-r--r--firmware/bluetooth_rxtx/bluetooth_rxtx.c44
-rw-r--r--firmware/bluetooth_rxtx/le_phy.c108
-rw-r--r--firmware/bluetooth_rxtx/ubertooth_usb.c2
-rw-r--r--host/CMakeLists.txt2
-rw-r--r--host/cmake/set_release.cmake2
-rw-r--r--host/doc/man/ubertooth-btle.147
-rw-r--r--host/doc/ubertooth-btle.md34
-rw-r--r--host/libubertooth/src/ubertooth_control.c27
-rw-r--r--host/libubertooth/src/ubertooth_control.h4
-rw-r--r--host/libubertooth/src/ubertooth_interface.h2
-rw-r--r--host/ubertooth-tools/src/ubertooth-btle.c91
-rw-r--r--tools/RELEASENOTES29
15 files changed, 333 insertions, 73 deletions
diff --git a/README.md b/README.md
index 829e877..2c10dbd 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,10 @@ suitable for Bluetooth experimentation. Ubertooth ships with a capable
BLE (Bluetooth Smart) sniffer and can sniff some data from Basic Rate
(BR) Bluetooth Classic connections.
-The latest release is [2018-06-R1](https://github.com/greatscottgadgets/ubertooth/releases/tag/2018-06-R1).
+The latest release is [2018-08-R1](https://github.com/greatscottgadgets/ubertooth/releases/tag/2018-08-R1).
The latest firmware build can be found on the release page.
-This release is paired with [libbtbb 2018-06-R1](https://github.com/greatscottgadgets/libbtbb/releases/tag/2018-06-R1).
+This release is paired with [libbtbb 2018-08-R1](https://github.com/greatscottgadgets/libbtbb/releases/tag/2018-08-R1).
Instructions for flashing the firmware can be found [on the corresponding Wiki page](https://github.com/greatscottgadgets/ubertooth/wiki/Firmware).
Instructions for building libbrbb can be found [on the corresponding Wiki page](https://github.com/greatscottgadgets/ubertooth/wiki/Build-Guide).
diff --git a/changelog b/changelog
index 447b6a6..1e02d2e 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,10 @@
+ubertooth (2018-08-R1) unstable; urgency=low
+ * Support for partial channel map updates
+ * LE no-follow mode (advertising packets only)
+ * USB API version bumped to 1.04
+
+ -- Mike Ryan <mikeryan@lacklustre.net> 07 Aug 2018 15:20:00 -0700
+
ubertooth (2018-06-R1) unstable; urgency=low
* Brand new LE sniffing engine
* Support for partial channel maps and channel map updates during connection
diff --git a/firmware/bluetooth_rxtx/bluetooth_le.h b/firmware/bluetooth_rxtx/bluetooth_le.h
index 1830416..ac1ec4d 100644
--- a/firmware/bluetooth_rxtx/bluetooth_le.h
+++ b/firmware/bluetooth_rxtx/bluetooth_le.h
@@ -59,7 +59,10 @@ typedef struct _le_state_t {
u8 win_size_update; // the new window size
u16 win_offset_update; // the new window offset
+ int do_follow; // 1 if follow connections, 0 to only log advertising packets
+
u8 target[6]; // target MAC for connection following (byte order reversed)
+ u8 target_mask[6]; // mask for MAC connection following (byte order reversed)
int target_set; // whether a target has been set (default: false)
u32 last_packet; // when was the last packet received
} le_state_t;
diff --git a/firmware/bluetooth_rxtx/bluetooth_rxtx.c b/firmware/bluetooth_rxtx/bluetooth_rxtx.c
index 6982c01..3bfbec3 100644
--- a/firmware/bluetooth_rxtx/bluetooth_rxtx.c
+++ b/firmware/bluetooth_rxtx/bluetooth_rxtx.c
@@ -88,6 +88,7 @@ le_state_t le = {
.link_state = LINK_INACTIVE,
.conn_epoch = 0,
+ .do_follow = 1,
.target_set = 0,
.last_packet = 0,
};
@@ -538,6 +539,7 @@ static int vendor_request_handler(uint8_t request, uint16_t* request_params, uin
break;
case UBERTOOTH_BTLE_SNIFFING:
+ le.do_follow = request_params[0];
*data_len = 0;
do_hop = 0;
@@ -647,13 +649,41 @@ static int vendor_request_handler(uint8_t request, uint16_t* request_params, uin
case UBERTOOTH_BTLE_SET_TARGET:
// Addresses appear in packets in reverse-octet order.
// Store the target address in reverse order so that we can do a simple memcmp later
- le.target[0] = data[5];
- le.target[1] = data[4];
- le.target[2] = data[3];
- le.target[3] = data[2];
- le.target[4] = data[1];
- le.target[5] = data[0];
- le.target_set = 1;
+ if (data[6] > 48) {
+ return 1; // invalid mask
+ }
+ else if (data[6] == 0) {
+ le.target_set = 0;
+ memset(le.target, 0, 6);
+ memset(le.target_mask, 0, 6);
+ } else {
+ unsigned last;
+
+ for (i = 0; i < 6; ++i)
+ le.target[i] = data[5-i];
+
+ // compute mask
+ memset(le.target_mask, 0, 6);
+ for (i = 5; data[6] > 8; --i, data[6] -= 8) {
+ le.target_mask[i] = 0xff;
+ }
+ last = i;
+
+ if (data[6] > 0) {
+ uint8_t final_byte = 0;
+ for (i = 0; i < data[6]; ++i) {
+ final_byte >>= 1;
+ final_byte |= 0b10000000;
+ }
+ le.target_mask[last] = final_byte;
+ }
+
+ // in case the user specifies a bad mask
+ for (i = 0; i < 5; ++i)
+ le.target[i] &= le.target_mask[i];
+
+ le.target_set = 1;
+ }
break;
case UBERTOOTH_CANCEL_FOLLOW:
diff --git a/firmware/bluetooth_rxtx/le_phy.c b/firmware/bluetooth_rxtx/le_phy.c
index 2f4782d..caafbde 100644
--- a/firmware/bluetooth_rxtx/le_phy.c
+++ b/firmware/bluetooth_rxtx/le_phy.c
@@ -112,6 +112,11 @@ typedef struct _le_conn_t {
uint16_t conn_event_counter;
+ int conn_update_pending;
+ uint32_t conn_update_pending_interval;
+ uint32_t conn_update_pending_supervision_timeout;
+ uint16_t conn_update_instant;
+
int channel_map_update_pending;
uint16_t channel_map_update_instant;
le_channel_remapping_t pending_remapping;
@@ -202,8 +207,9 @@ static void reset_conn_event(void) {
// finish a connection event
//
// 1) update the anchor point (see details below)
-// 2) check if supervision timeout is exceeded
-// 2) setup radio for next packet (data or adv if timeout exceeded)
+// 2) increment connection event counter
+// 3) check if supervision timeout is exceeded
+// 4) setup radio for next packet (data or adv if timeout exceeded)
//
// anchor update logic can be summarized thusly:
// 1) if we received two packets, set the connection anchor to the
@@ -558,11 +564,45 @@ static void timer1_cancel_fs_lock(void) {
}
void TIMER1_IRQHandler(void) {
+ // MR0: connection events
if (T1IR & TIR_MR0_Interrupt) {
// ack the interrupt
T1IR = TIR_MR0_Interrupt;
- // channel map update, can be interleaved with connection update
+ // connection update procedure
+ if (conn.conn_update_pending &&
+ conn.conn_event_counter == conn.conn_update_instant) {
+
+ // on the first past through, handle the transmit window
+ // offset. if there's no offset, skip down to else block
+ if (!conn_event.opened && conn.win_offset > 0) {
+ timer1_set_match(conn.last_anchor + conn.conn_interval +
+ conn.win_offset - RX_WARMUP_TIME);
+ conn_event.opened = 1;
+ }
+
+ // after the transmit window offset, or if there is no
+ // transmit window, set a packet timeout and change the
+ // channel
+ else { // conn_event.opened || conn.win_offset == 0
+ conn_event.opened = 1;
+
+ // this is like a new connection, so set all values
+ // accordingly
+ conn.anchor_set = 0;
+ conn.conn_interval = conn.conn_update_pending_interval;
+ conn.supervision_timeout = conn.conn_update_pending_supervision_timeout;
+ conn.conn_update_pending = 0;
+
+ // timeout after conn window + max packet length
+ timer1_set_match(conn.last_anchor + conn.conn_interval +
+ conn.win_offset + conn.win_size + USEC(2120));
+ change_channel();
+ }
+ return;
+ }
+
+ // channel map update
if (conn.channel_map_update_pending &&
conn.conn_event_counter == conn.channel_map_update_instant) {
conn.remapping = conn.pending_remapping;
@@ -577,9 +617,25 @@ void TIMER1_IRQHandler(void) {
change_channel();
}
- // timeout: close connection event and set timer for next hop
+ // regular connection event, plus timeout from connection updates
+ // FIXME connection update timeouts and initial connection
+ // timeouts need to be handled differently: they should have a
+ // full window until the packets from the new connection are
+ // captured and a new anchor is set.
else {
- finish_conn_event();
+ // new connection event: set timeout and change channel
+ if (!conn_event.opened) {
+ conn_event.opened = 1;
+
+ // timeout is max packet length + warmup time (slack)
+ timer1_set_match(NOW + USEC(2120) + RX_WARMUP_TIME);
+ change_channel();
+ }
+
+ // timeout: close connection event and set timer for next hop
+ else {
+ finish_conn_event();
+ }
}
}
@@ -687,6 +743,9 @@ static void le_connect_handler(le_rx_t *buf) {
uint32_t aa, crc_init;
uint32_t win_size, max_win_size;
+ if (!le.do_follow)
+ return;
+
if (buf->size != 2 + 6 + 6 + 22 + 3)
return;
@@ -747,6 +806,24 @@ err_out:
reset_conn();
}
+static void connection_update_handler(le_rx_t *buf) {
+ conn.win_size = extract_field(buf, 3, 1);
+ conn.win_offset = extract_field(buf, 4, 2);
+ conn.conn_update_pending_interval = extract_field(buf, 6, 2);
+ conn.conn_update_pending_supervision_timeout = extract_field(buf, 10, 2);
+ conn.conn_update_instant = extract_field(buf, 12, 2);
+
+ // TODO check for invalid values. XXX what do we even do in that
+ // case? we will probably drop the connection, but at least it's on
+ // our own terms and not some impossibly long supervision timeout.
+ conn.win_size *= USEC(1250);
+ conn.win_offset *= USEC(1250);
+ conn.conn_update_pending_interval *= USEC(1250);
+ conn.conn_update_pending_supervision_timeout *= MSEC(10);
+
+ conn.conn_update_pending = 1;
+}
+
static void channel_map_update_handler(le_rx_t *buf) {
conn.channel_map_update_pending = 1;
conn.channel_map_update_instant = extract_field(buf, 8, 2);
@@ -759,6 +836,7 @@ static void packet_handler(le_rx_t *buf) {
switch (buf->data[0] & 0xf) {
// CONNECT_REQ
case 0x05:
+ // TODO validate length
le_connect_handler(buf);
break;
}
@@ -769,6 +847,12 @@ static void packet_handler(le_rx_t *buf) {
// LL control PDU
if ((buf->data[0] & 0b11) == 0b11 && buf->data[1] > 0) {
switch (buf->data[2]) {
+ // LE_CONNECTION_UPDATE_REQ -- update connection parameters
+ case 0x0:
+ if (buf->data[1] == 12)
+ connection_update_handler(buf);
+ break;
+
// LE_CHANNEL_MAP_REQ -- update channel map
case 0x1:
if (buf->data[1] == 8)
@@ -777,7 +861,15 @@ static void packet_handler(le_rx_t *buf) {
}
}
}
+}
+// compare a BD addr against target with mask
+static int bd_addr_cmp(uint8_t *bd_addr) {
+ unsigned i;
+ for (i = 0; i < 6; ++i)
+ if ((bd_addr[i] & le.target_mask[i]) != le.target[i])
+ return 0;
+ return 1;
}
static int filter_match(le_rx_t *buf) {
@@ -797,7 +889,7 @@ static int filter_match(le_rx_t *buf) {
// header + one address
if (buf->size < 2 + 6)
return 0;
- return memcmp(&buf->data[2], le.target, 6) == 0;
+ return bd_addr_cmp(&buf->data[2]);
break;
// ADV_DIRECT_IND, SCAN_REQ, CONNECT_REQ
@@ -807,8 +899,8 @@ static int filter_match(le_rx_t *buf) {
// header + two addresses
if (buf->size < 2 + 6 + 6)
return 0;
- return memcmp(&buf->data[2], le.target, 6) == 0 ||
- memcmp(&buf->data[8], le.target, 6) == 0;
+ return bd_addr_cmp(&buf->data[2]) ||
+ bd_addr_cmp(&buf->data[8]);
break;
default:
diff --git a/firmware/bluetooth_rxtx/ubertooth_usb.c b/firmware/bluetooth_rxtx/ubertooth_usb.c
index 939aaa0..cc27a18 100644
--- a/firmware/bluetooth_rxtx/ubertooth_usb.c
+++ b/firmware/bluetooth_rxtx/ubertooth_usb.c
@@ -91,7 +91,7 @@ static u8 abDescriptors[] = {
MAX_PACKET_SIZE0, // bMaxPacketSize
LE_WORD(ID_VENDOR), // idVendor
LE_WORD(ID_PRODUCT), // idProduct
- LE_WORD(0x0103), // bcdDevice
+ LE_WORD(0x0105), // bcdDevice
0x01, // iManufacturer
0x02, // iProduct
0x03, // iSerialNumber
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index 7ecca53..ea0dfa6 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -26,7 +26,7 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules
CACHE STRING "CMake module path")
set(MAJOR_VERSION 1 CACHE INT "libUbertooth major version number")
-set(MINOR_VERSION 0 CACHE INT "libUbertooth minor version number")
+set(MINOR_VERSION 1 CACHE INT "libUbertooth minor version number")
set( VERSION ${MAJOR_VERSION}.${MINOR_VERSION} )
add_definitions( -DVERSION="${VERSION}" )
diff --git a/host/cmake/set_release.cmake b/host/cmake/set_release.cmake
index 39851e8..74628b2 100644
--- a/host/cmake/set_release.cmake
+++ b/host/cmake/set_release.cmake
@@ -6,7 +6,7 @@
# tagged
if(NOT DEFINED RELEASE_STRING)
- set(LATEST_RELEASE "2018-06-R1")
+ set(LATEST_RELEASE "2018-08-R1")
execute_process(
COMMAND git log -n 1 --format=%h
diff --git a/host/doc/man/ubertooth-btle.1 b/host/doc/man/ubertooth-btle.1
index b97deb5..110bd00 100644
--- a/host/doc/man/ubertooth-btle.1
+++ b/host/doc/man/ubertooth-btle.1
@@ -1,4 +1,4 @@
-.TH UBERTOOTH\-BTLE 1 "March 2017" "Project Ubertooth" "User Commands"
+.TH UBERTOOTH\-BTLE 1 "July 2018" "Project Ubertooth" "User Commands"
.SH NAME
.PP
ubertooth\-btle \-\- Bluetooth Low Energy (BLE) sniffing and more
@@ -36,6 +36,9 @@ sent between the central and peripheral. After the connection
terminates, Ubertooth will return to the advertising channel and wait
for another connection.
.PP
+No\-follow mode is similar to follow mode, but it only logs advertising
+packets and will not follow connections as they are established.
+.PP
Promiscuous mode is an experimental mode for sniffing connections after
they have already been established. This mode can be used to sniff
long\-lived connections.
@@ -56,7 +59,34 @@ ubertooth\-btle \-f \-t22:44:66:88:AA:CC
.fi
.RE
.PP
-In both sniffing modes, Ubertooth can log data to PCAP or PcapNG with a
+\fB\fC\-t\fR can also take a mask length in CIDR\-like notation. Masks can be
+between 1 and 48 bits long, with a 48 bit mask matching the entire
+address. Using a /24 mask will filter on just the OUI. For example, to
+limit sniffing to just TI devices with the OUI 00:1A:7D, use the
+following:
+.PP
+.RS
+.nf
+ubertooth\-btle \-t 00:1A:7D:00:00:00/24
+.fi
+.RE
+.PP
+Filters persist until they are explicitly cleared or the system restarts
+(either via \fB\fCubertooth\-util \-r\fR or unplug/replug). To clear a filter,
+use the special filter \fB\fCnone\fR\&. Example:
+.PP
+.RS
+.nf
+ubertooth\-btle \-t none
+.fi
+.RE
+.PP
+When filtering, previous versions of the firmware would still log all
+advertising packets but only follow connections based on the filter
+parameters. As of 2018\-06\-R1, advertising packets that do not match the
+filter are dropped.
+.PP
+In all sniffing modes, Ubertooth can log data to PCAP or PcapNG with a
variety of pseudoheaders. The recommended logging format is PcapNG
(\fB\fC\-r\fR) or PCAP with LE Pseudoheader (\fB\fC\-q\fR). For compatibility with
crackle (see [USING WITH CRACKLE][]), use PCAP with PPI (\fB\fC\-c\fR).
@@ -83,6 +113,14 @@ ubertooth\-btle \-f \-A 38 \-r log.pcapng
.fi
.RE
.PP
+Log advertising packets without following connections:
+.PP
+.RS
+.nf
+ubertooth\-btle \-n
+.fi
+.RE
+.PP
Interfere with connections recovered with promiscuous mode:
.PP
.RS
@@ -111,6 +149,9 @@ Major modes:
\fB\fC\-f\fR :
Follow mode: sniff connections as they are established
.IP \(bu 2
+\fB\fC\-n\fR :
+No\-follow mode: log advertising packets but don't follow connections
+.IP \(bu 2
\fB\fC\-p\fR :
Promiscuous mode: sniff already\-established connections
.IP \(bu 2
@@ -193,5 +234,5 @@ Refer to \fB\fCcrackle\fR documentation for further details.
\[la]https://github.com/mikeryan/crackle\[ra]
.SH COPYRIGHT
.PP
-\fB\fCubertooth\-btle\fR is Copyright (C) 2012\-2017 Mike Ryan. This tool is
+\fB\fCubertooth\-btle\fR is Copyright (C) 2012\-2018 Mike Ryan. This tool is
released under the GPLv2. Refer to COPYING for futher details.
diff --git a/host/doc/ubertooth-btle.md b/host/doc/ubertooth-btle.md
index 087f36e..fee2f53 100644
--- a/host/doc/ubertooth-btle.md
+++ b/host/doc/ubertooth-btle.md
@@ -1,4 +1,4 @@
-# UBERTOOTH-BTLE 1 "March 2017" "Project Ubertooth" "User Commands"
+# UBERTOOTH-BTLE 1 "July 2018" "Project Ubertooth" "User Commands"
## NAME
@@ -29,6 +29,9 @@ sent between the central and peripheral. After the connection
terminates, Ubertooth will return to the advertising channel and wait
for another connection.
+No-follow mode is similar to follow mode, but it only logs advertising
+packets and will not follow connections as they are established.
+
Promiscuous mode is an experimental mode for sniffing connections after
they have already been established. This mode can be used to sniff
long-lived connections.
@@ -45,7 +48,26 @@ sniff connections where the central or peripheral's BD ADDR is
ubertooth-btle -f -t22:44:66:88:AA:CC
-In both sniffing modes, Ubertooth can log data to PCAP or PcapNG with a
+`-t` can also take a mask length in CIDR-like notation. Masks can be
+between 1 and 48 bits long, with a 48 bit mask matching the entire
+address. Using a /24 mask will filter on just the OUI. For example, to
+limit sniffing to just TI devices with the OUI 00:1A:7D, use the
+following:
+
+ ubertooth-btle -t 00:1A:7D:00:00:00/24
+
+Filters persist until they are explicitly cleared or the system restarts
+(either via `ubertooth-util -r` or unplug/replug). To clear a filter,
+use the special filter `none`. Example:
+
+ ubertooth-btle -t none
+
+When filtering, previous versions of the firmware would still log all
+advertising packets but only follow connections based on the filter
+parameters. As of 2018-06-R1, advertising packets that do not match the
+filter are dropped.
+
+In all sniffing modes, Ubertooth can log data to PCAP or PcapNG with a
variety of pseudoheaders. The recommended logging format is PcapNG
(`-r`) or PCAP with LE Pseudoheader (`-q`). For compatibility with
crackle (see [USING WITH CRACKLE][]), use PCAP with PPI (`-c`).
@@ -69,6 +91,10 @@ PcapNG:
ubertooth-btle -f -A 38 -r log.pcapng
+Log advertising packets without following connections:
+
+ ubertooth-btle -n
+
Interfere with connections recovered with promiscuous mode:
ubertooth-btle -p -I
@@ -86,6 +112,8 @@ Major modes:
- `-f` :
Follow mode: sniff connections as they are established
+ - `-n` :
+ No-follow mode: log advertising packets but don't follow connections
- `-p` :
Promiscuous mode: sniff already-established connections
- `-s<BD ADDR>` :
@@ -147,5 +175,5 @@ crackle(1): https://github.com/mikeryan/crackle
## COPYRIGHT
-`ubertooth-btle` is Copyright (C) 2012-2017 Mike Ryan. This tool is
+`ubertooth-btle` is Copyright (C) 2012-2018 Mike Ryan. This tool is
released under the GPLv2. Refer to COPYING for futher details.
diff --git a/host/libubertooth/src/ubertooth_control.c b/host/libubertooth/src/ubertooth_control.c
index 6b90fc2..a542caf 100644
--- a/host/libubertooth/src/ubertooth_control.c
+++ b/host/libubertooth/src/ubertooth_control.c
@@ -724,11 +724,11 @@ uint32_t cmd_get_clock(struct libusb_device_handle* devh)
return clock;
}
-int cmd_btle_sniffing(struct libusb_device_handle* devh, u16 num)
+int cmd_btle_sniffing(struct libusb_device_handle* devh, uint8_t do_follow)
{
int r;
- r = libusb_control_transfer(devh, CTRL_OUT, UBERTOOTH_BTLE_SNIFFING, num, 0,
+ r = libusb_control_transfer(devh, CTRL_OUT, UBERTOOTH_BTLE_SNIFFING, do_follow, 0,
NULL, 0, 1000);
if (r < 0) {
if (r == LIBUSB_ERROR_PIPE) {
@@ -866,11 +866,16 @@ int cmd_set_crc_verify(struct libusb_device_handle* devh, int verify)
int cmd_poll(struct libusb_device_handle* devh, usb_pkt_rx *p)
{
int r;
-
- r = libusb_control_transfer(devh, CTRL_IN, UBERTOOTH_POLL, 0, 0,
- (u8 *)p, sizeof(usb_pkt_rx), 1000);
- if (r < 0) {
- show_libusb_error(r);
+ unsigned i;
+
+ // retry up to three times due to stalls
+ for (i = 0; i < 3; ++i) {
+ r = libusb_control_transfer(devh, CTRL_IN, UBERTOOTH_POLL, 0, 0,
+ (u8 *)p, sizeof(usb_pkt_rx), 1000);
+ if (r == LIBUSB_ERROR_PIPE) // retry
+ continue;
+ if (r < 0)
+ show_libusb_error(r);
return r;
}
return r;
@@ -930,12 +935,16 @@ int cmd_btle_slave(struct libusb_device_handle* devh, u8 *mac_address)
return 0;
}
-int cmd_btle_set_target(struct libusb_device_handle* devh, u8 *mac_address)
+int cmd_btle_set_target(struct libusb_device_handle* devh, uint8_t *mac_address, uint8_t mac_mask)
{
int r;
+ uint8_t cmd_buf[7];
+
+ memcpy(cmd_buf, mac_address, 6);
+ cmd_buf[6] = mac_mask;
r = libusb_control_transfer(devh, CTRL_OUT, UBERTOOTH_BTLE_SET_TARGET, 0, 0,
- mac_address, 6, 1000);
+ cmd_buf, 7, 1000);
if (r < 0) {
if (r == LIBUSB_ERROR_PIPE) {
fprintf(stderr, "control message unsupported\n");
diff --git a/host/libubertooth/src/ubertooth_control.h b/host/libubertooth/src/ubertooth_control.h
index e53f70f..675b899 100644
--- a/host/libubertooth/src/ubertooth_control.h
+++ b/host/libubertooth/src/ubertooth_control.h
@@ -124,7 +124,7 @@ int cmd_set_clock(struct libusb_device_handle* devh, u32 clkn);
uint32_t cmd_get_clock(struct libusb_device_handle* devh);
int cmd_set_afh_map(struct libusb_device_handle* devh, u8* afh_map);
int cmd_clear_afh_map(struct libusb_device_handle* devh);
-int cmd_btle_sniffing(struct libusb_device_handle* devh, u16 num);
+int cmd_btle_sniffing(struct libusb_device_handle* devh, uint8_t do_follow);
u32 cmd_get_access_address(struct libusb_device_handle* devh);
int cmd_set_access_address(struct libusb_device_handle* devh, u32 access_address);
int cmd_do_something(struct libusb_device_handle *devh, unsigned char *data, int len);
@@ -135,7 +135,7 @@ int cmd_poll(struct libusb_device_handle* devh, usb_pkt_rx *p);
int cmd_btle_promisc(struct libusb_device_handle* devh);
int cmd_read_register(struct libusb_device_handle* devh, u8 reg);
int cmd_btle_slave(struct libusb_device_handle* devh, u8 *mac_address);
-int cmd_btle_set_target(struct libusb_device_handle* devh, u8 *mac_address);
+int cmd_btle_set_target(struct libusb_device_handle* devh, uint8_t *mac_address, uint8_t mac_mask);
int cmd_set_jam_mode(struct libusb_device_handle* devh, int mode);
int cmd_ego(struct libusb_device_handle* devh, int mode);
int cmd_afh(struct libusb_device_handle* devh);
diff --git a/host/libubertooth/src/ubertooth_interface.h b/host/libubertooth/src/ubertooth_interface.h
index 01e8796..b170332 100644
--- a/host/libubertooth/src/ubertooth_interface.h
+++ b/host/libubertooth/src/ubertooth_interface.h
@@ -25,7 +25,7 @@
#include <stdint.h>
// increment on every API change
-#define UBERTOOTH_API_VERSION 0x0103
+#define UBERTOOTH_API_VERSION 0x0105
#define DMA_SIZE 50
diff --git a/host/ubertooth-tools/src/ubertooth-btle.c b/host/ubertooth-tools/src/ubertooth-btle.c
index 0583fad..2959a2c 100644
--- a/host/ubertooth-tools/src/ubertooth-btle.c
+++ b/host/ubertooth-tools/src/ubertooth-btle.c
@@ -42,8 +42,38 @@ static void quit(int sig __attribute__((unused))) {
running = 0;
}
-int convert_mac_address(char *s, uint8_t *o) {
+void print_mac(uint8_t *mac_address, int mask) {
+ unsigned i;
+ for (i = 0; i < 5; ++i)
+ printf("%02x:", mac_address[i]);
+ printf("%02x", mac_address[5]);
+ if (mask >= 0)
+ printf("/%u", mask);
+}
+
+int convert_mac_address(char *s, uint8_t *o, uint8_t *mask_out) {
int i;
+ char *mask_p;
+ unsigned mask = 48; // default mask is entire BD ADDR
+
+ if (strcmp(s, "none") == 0) {
+ memset(o, 0, 6);
+ mask_out = 0;
+ return 1;
+ }
+
+ // if there is a mask included, parse it
+ mask_p = strchr(s, '/');
+ if (mask_p != NULL) {
+ *mask_p = '\0';
+ ++mask_p;
+ mask = strtoul(mask_p, NULL, 10);
+ if (mask > 48) {
+ printf("Error: MAC mask must be between 0 and 48\n");
+ return 0;
+ }
+ }
+ *mask_out = mask; // see above, default 48, otherwise user-supplied
// validate length
if (strlen(s) != 6 * 2 + 5) {
@@ -82,10 +112,13 @@ static void usage(void)
printf("\n");
printf(" Major modes:\n");
printf("\t-f follow connections\n");
+ printf("\t-n don't follow, only print advertisements\n");
printf("\t-p promiscuous: sniff active connections\n");
+ printf("\n");
printf("\t-a[address] get/set access address (example: -a8e89bed6)\n");
printf("\t-s<address> faux slave mode, using MAC addr (example: -s22:44:66:88:aa:cc)\n");
- printf("\t-t<address> set connection following target (example: -t22:44:66:88:aa:cc)\n");
+ printf("\t-t<address> set connection following target (example: -t22:44:66:88:aa:cc/48)\n");
+ printf("\t-tnone unset connection following target\n");
printf("\n");
printf(" Interference (use with -f or -p):\n");
printf("\t-i interfere with one connection and return to idle\n");
@@ -109,7 +142,7 @@ static void usage(void)
int main(int argc, char *argv[])
{
int opt;
- int do_follow, do_promisc;
+ int do_follow, do_no_follow, do_promisc;
int do_get_aa, do_set_aa;
int do_crc;
int do_adv_index;
@@ -124,14 +157,15 @@ int main(int argc, char *argv[])
int r;
u32 access_address;
uint8_t mac_address[6] = { 0, };
+ uint8_t mac_mask = 0;
- do_follow = do_promisc = 0;
+ do_follow = do_no_follow = do_promisc = 0;
do_get_aa = do_set_aa = 0;
do_crc = -1; // 0 and 1 mean set, 2 means get
do_adv_index = 37;
do_slave_mode = do_target = 0;
- while ((opt=getopt(argc,argv,"a::r:hfpU:v::A:s:t:x:c:q:jJiI")) != EOF) {
+ while ((opt=getopt(argc,argv,"a::r:hfnpU:v::A:s:t:x:c:q:jJiI")) != EOF) {
switch(opt) {
case 'a':
if (optarg == NULL) {
@@ -144,6 +178,9 @@ int main(int argc, char *argv[])
case 'f':
do_follow = 1;
break;
+ case 'n':
+ do_no_follow = 1;
+ break;
case 'p':
do_promisc = 1;
break;
@@ -196,7 +233,7 @@ int main(int argc, char *argv[])
break;
case 's':
do_slave_mode = 1;
- r = convert_mac_address(optarg, mac_address);
+ r = convert_mac_address(optarg, mac_address, &mac_mask);
if (!r) {
usage();
return 1;
@@ -204,7 +241,7 @@ int main(int argc, char *argv[])
break;
case 't':
do_target = 1;
- r = convert_mac_address(optarg, mac_address);
+ r = convert_mac_address(optarg, mac_address, &mac_mask);
if (!r) {
usage();
return 1;
@@ -252,12 +289,29 @@ int main(int argc, char *argv[])
// cancel following on USR1
signal(SIGUSR1, cancel_follow_handler);
- if (do_follow && do_promisc) {
- printf("Error: must choose either -f or -p, one or the other pal\n");
+ if (do_follow + do_no_follow + do_promisc > 1) {
+ printf("Error: must choose one -f, -n, or -p, pick one pal\n");
return 1;
}
- if (do_follow || do_promisc) {
+ // allow user to set target before following
+ if (do_target) {
+ r = cmd_btle_set_target(ut->devh, mac_address, mac_mask);
+ if (r == 0) {
+ if (mac_mask == 0) {
+ printf("target cleared\n");
+ } else {
+ printf("target set to: ");
+ print_mac(mac_address, mac_mask);
+ printf("\n");
+ }
+ } else {
+ printf("Unable to set target\n");
+ return 1;
+ }
+ }
+
+ if (do_follow || do_no_follow || do_promisc) {
usb_pkt_rx rx;
r = cmd_set_jam_mode(ut->devh, jam_mode);
@@ -267,7 +321,7 @@ int main(int argc, char *argv[])
}
cmd_set_modulation(ut->devh, MOD_BT_LOW_ENERGY);
- if (do_follow) {
+ if (do_follow || do_no_follow) {
u16 channel;
if (do_adv_index == 37)
channel = 2402;
@@ -276,7 +330,7 @@ int main(int argc, char *argv[])
else
channel = 2480;
cmd_set_channel(ut->devh, channel);
- cmd_btle_sniffing(ut->devh, 2);
+ cmd_btle_sniffing(ut->devh, do_follow);
} else {
cmd_btle_promisc(ut->devh);
}
@@ -336,18 +390,7 @@ int main(int argc, char *argv[])
cmd_btle_slave(ut->devh, mac_address);
}
- if (do_target) {
- r = cmd_btle_set_target(ut->devh, mac_address);
- if (r == 0) {
- int i;
- printf("target set to: ");
- for (i = 0; i < 5; ++i)
- printf("%02x:", mac_address[i]);
- printf("%02x\n", mac_address[5]);
- }
- }
-
- if (!(do_follow || do_promisc || do_get_aa || do_set_aa ||
+ if (!(do_follow || do_no_follow || do_promisc || do_get_aa || do_set_aa ||
do_crc >= 0 || do_slave_mode || do_target))
usage();
diff --git a/tools/RELEASENOTES b/tools/RELEASENOTES
index 2b4adaa..ed64d7f 100644
--- a/tools/RELEASENOTES
+++ b/tools/RELEASENOTES
@@ -1,7 +1,7 @@
-Ubertooth 2018-06-R1 Release Notes
+Ubertooth 2018-08-R1 Release Notes
==============================
-The Ubertooth host utilities in this release require libbtbb-2018-06-R1
-(https://github.com/greatscottgadgets/libbtbb/releases/tag/2018-06-R1) or
+The Ubertooth host utilities in this release require libbtbb-2018-08-R1
+(https://github.com/greatscottgadgets/libbtbb/releases/tag/2018-08-R1) or
greater.
Changes
@@ -21,22 +21,29 @@ connection is established as well as support for the Channel Map Update
Link Layer Procedure. This allows capturing connections from virtually
all modern BLE devices.
-**Feature degradation** - Support for Connection Update Link Layer
-Procedure has been lost as of this update. This is a relatively rare
-occurrence, and it will be added in an upcoming release once it has been
-fully debugged. If you encounter a device that uses this feature, please
-file a bug on the project as it will help with our implementation
-testing.
+**Connection update support** - Support for Connection Update Link Layer
+Procedure has been reimplemented as of this update. This was a feature
+degradation in 2018-06-R1 but has been fixed.
+
+**Improved filtering** - LE filtering now applies to all advertising
+packets, not just connections. Packets that do not match the filter are
+silently dropped. Filters can include a CIDR-style netmask, allowing as
+few as 1 or as many as 48 bits to be included in the BD ADDR filter.
+
+**No-follow mode** - In LE, it is now a first-class operation to only
+log advertising packets (inhibit connection following). The previous
+mechanism of using a filter of 00:00:00:00:00:00 is no longer
+functional, and this new feature should be used instead.
**USB API version** - As with the previous release, we are using USB API
versioning to improve the experience of failures due to mismatched
firmware and host code. As of this release, the USB API has been bumped
-to 1.03. If the Ubertooth tools complain that your firmware is out of
+to 1.04. If the Ubertooth tools complain that your firmware is out of
date, please update your firmware. Updating firmware is simple and
reliable, please follow the instructions on the wiki
https://github.com/greatscottgadgets/ubertooth/wiki/Firmware
A release archive with precompiled firmware is available from
-https://github.com/greatscottgadgets/ubertooth/releases/download/2018-06-R1/ubertooth-2018-06-R1.tar.xz
+https://github.com/greatscottgadgets/ubertooth/releases/download/2018-08-R1/ubertooth-2018-08-R1.tar.xz
Support
-------