static void cb_dump_bitstream(void* args, usb_pkt_rx *rx, int bank) { /* unused parameter */ args = args; unpack_symbols(rx->data, symbols[bank]); fprintf(stderr, "rx block timestamp %u * 100 nanoseconds\n", rx->clk100ns); if (dumpfile == NULL) { if (fwrite(symbols[bank], sizeof(u8), BANK_LEN, stdout) != 1) {;} } else { if (fwrite(symbols[bank], sizeof(u8), BANK_LEN, dumpfile) != 1) {;} } }
static void cb_dump_bitstream(void* args, usb_pkt_rx *rx, int bank) { int i; char nl = '\n'; UNUSED(args); unpack_symbols(rx->data, br_symbols[bank]); // convert to ascii for (i = 0; i < BANK_LEN; ++i) br_symbols[bank][i] += 0x30; fprintf(stderr, "rx block timestamp %u * 100 nanoseconds\n", rx->clk100ns); if (dumpfile == NULL) { if (fwrite(br_symbols[bank], sizeof(u8), BANK_LEN, stdout) != 1) {;} fwrite(&nl, sizeof(u8), 1, stdout); } else { if (fwrite(br_symbols[bank], sizeof(u8), BANK_LEN, dumpfile) != 1) {;} fwrite(&nl, sizeof(u8), 1, dumpfile); } }
/* * Sniff Bluetooth Low Energy packets. So far this is just a proof of concept * that only captures advertising packets. */ static void cb_btle(void* args, usb_pkt_rx *rx, int bank) { char syms[BANK_LEN * NUM_BANKS]; int i, j, k; uint32_t access_address = 0; uint32_t clk100ns; /* in 100 nanosecond units */ char *channel_rssi_history; int8_t signal_level; int8_t noise_level; int8_t snr; time_t systime; uint8_t byte; /* unused parameter */ args = args; /* Sanity check */ if (rx->channel > (NUM_CHANNELS-1)) return; clk100ns = letoh32(rx->clk100ns); /* wire format is le32 */ unpack_symbols(rx->data, symbols[bank]); /* Shift rssi max history and append current max */ channel_rssi_history = rssi_history[rx->channel]; for(i = 1; i < RSSI_HISTORY_LEN; i++) { int8_t v = channel_rssi_history[i]; channel_rssi_history[i - 1] = v; } channel_rssi_history[RSSI_HISTORY_LEN-1] = rx->rssi_max; /* Signal starts in oldest bank, but may cross into second oldest bank. * Take the max or the 2 maxs. */ signal_level = MAX(channel_rssi_history[0], channel_rssi_history[1]) + RSSI_BASE; /* Noise is an IIR of averages */ noise_level = rx->rssi_avg + RSSI_BASE; snr = signal_level - noise_level; /* Copy 2 banks for analysis */ for (i = 0; i < 2; i++) memcpy(syms + i * BANK_LEN, symbols[(i + 1 + bank) % NUM_BANKS], BANK_LEN); for (i = 32; i < (BANK_LEN + 32); i++) { access_address >>= 1; access_address |= (syms[i] << 31); if (access_address == 0x8e89bed6) { /* advertising access address */ systime = time(NULL); printf("systime=%u freq=%d addr=%08x clk100ns=%u s=%d n=%d snr=%d\n", (int)systime, rx->channel + 2402, access_address, clk100ns, signal_level, noise_level, snr); /* hard coded to maximum packet length (46) */ for (j = 0; j < 46; j++) { byte = 0; for (k = 0; k < 8; k++) { byte |= syms[k + (j * 8) + i - 31] << k; } printf("%02x", byte); } printf("\n\n"); } } }
static void cb_hop(void* args, usb_pkt_rx *rx, int bank) { char syms[BANK_LEN * NUM_BANKS]; int i, j, k; access_code r; uint8_t channel; uint32_t time; /* in 100 nanosecond units */ uint8_t clkn_high; packet pkt; piconet* pn = (piconet *)args; uint8_t uap = pn->UAP; channel = rx->channel; time = letoh32(rx->clk100ns); /* wire format is le32 */ clkn_high = rx->clkn_high; unpack_symbols(rx->data, symbols[bank]); /* fprintf(stderr, "rx block timestamp %u * 100 nanoseconds\n", time); */ /* awfully repetitious */ k = 0; for (i = 0; i < 2; i++) for (j = 0; j < BANK_LEN; j++) syms[k++] = symbols[(i + 1 + bank) % NUM_BANKS][j]; r = find_ac(syms, BANK_LEN, pn->LAP); if (r.offset > -1) { for (i = 2; i < NUM_BANKS; i++) for (j = 0; j < BANK_LEN; j++) syms[k++] = symbols[(i + 1 + bank) % NUM_BANKS][j]; init_packet(&pkt, &syms[r.offset], BANK_LEN * NUM_BANKS - r.offset); pkt.LAP = r.LAP; pkt.clkn = (clkn_high << 19) | ((time + r.offset * 10) / 6250); pkt.channel = channel; if ((pkt.LAP == pn->LAP) && header_present(&pkt)) { printf("\nGOT PACKET on channel %d, LAP = %06x at time stamp %u, clkn %u\n", channel, pkt.LAP, time + r.offset * 10, pkt.clkn); if (pn->have_clk6) { UAP_from_header(&pkt, pn); if (!pn->have_clk6) { printf("CLK1-27 discovery failed\n"); exit(1); /* FIXME */ winnow(pn); } if (pn->have_clk27) { printf("got CLK1-27\n"); exit(0); } } else { if (UAP_from_header(&pkt, pn)) { if (uap == pn->UAP) { printf("got CLK1-6\n"); init_hop_reversal(0, pn); winnow(pn); } else { printf("failed to confirm UAP\n"); exit(1); } } } } } }
/* Sniff for LAPs. If a piconet is provided, use the given LAP to * search for UAP. */ static void cb_lap(void* args, usb_pkt_rx *rx, int bank) { piconet* pn = (piconet *)args; char syms[BANK_LEN * NUM_BANKS]; int i; access_code r; uint32_t clk100ns; /* in 100 nanosecond units */ packet pkt; char *channel_rssi_history; int8_t signal_level; int8_t noise_level; int8_t snr; uint32_t clk0; uint32_t clk1; /* Sanity check */ if (rx->channel > (NUM_CHANNELS-1)) return; /* Copy packet (for dump) */ memcpy(&packets[bank], rx, sizeof(usb_pkt_rx)); clk100ns = letoh32(rx->clk100ns); /* wire format is le32 */ /* printf("%10u %02x %02d %3.02d %3d %3d %3d\n", rx->clk100ns, rx->status, rx->channel, rx->rssi_min-54, rx->rssi_max-54, rx->rssi_avg-54, rx->rssi_count); */ unpack_symbols(rx->data, symbols[bank]); /* Do analysis based on oldest packet */ rx = &packets[ (bank+1) % NUM_BANKS ]; /* Shift rssi max history and append current max */ channel_rssi_history = rssi_history[rx->channel]; memmove(channel_rssi_history, channel_rssi_history+1, RSSI_HISTORY_LEN-1); channel_rssi_history[RSSI_HISTORY_LEN-1] = rx->rssi_max; /* Signal starts in oldest bank, but may cross into second * oldest bank. Take the max or the 2 maxs. */ signal_level = MAX(channel_rssi_history[0], channel_rssi_history[1]) + RSSI_BASE; /* Noise is an IIR of averages */ noise_level = rx->rssi_avg + RSSI_BASE; snr = signal_level - noise_level; /* Copy 2 banks for analysis */ for (i = 0; i < 2; i++) memcpy(syms + i * BANK_LEN, symbols[(i + 1 + bank) % NUM_BANKS], BANK_LEN); /* No piconet given, sniff for any LAP */ if (pn == NULL) { r = sniff_ac(syms, BANK_LEN); } /* Find packets for specified LAP. */ else { r = find_ac(syms, BANK_LEN, pn->LAP); } if ((r.offset > -1) && (r.error_count <= max_ac_errors)) { /* Native (Ubertooth) clock with period 312.5 uS. */ clk0 = (rx->clkn_high << 20) + (rx->clk100ns + r.offset * 10) / 3125; /* Bottom clkn bit not needed, clk1 period is 625 uS. */ clk1 = clk0 / 2; /* When reading from file, caller will read * systime before calling this routine, so do * not overwrite. Otherwise, get current time. */ if ( infile == NULL ) systime = time(NULL); printf("systime=%u ch=%2d LAP=%06x err=%u clk100ns=%u clk1=%u s=%d n=%d snr=%d\n", (int)systime, rx->channel, r.LAP, r.error_count, clk100ns, clk1, signal_level, noise_level, snr); /* Found a packet with the requested LAP */ if (pn != NULL && r.LAP == pn->LAP) { /* Determining UAP requires more symbols. Copy * remaining banks. */ for (i = 2; i < NUM_BANKS; i++) memcpy(syms + i * BANK_LEN, symbols[(i + 1 + bank) % NUM_BANKS], BANK_LEN); init_packet(&pkt, &syms[r.offset], BANK_LEN * NUM_BANKS - r.offset); pkt.LAP = r.LAP; pkt.clkn = clk1; pkt.channel = rx->channel; if (header_present(&pkt)) { if (UAP_from_header(&pkt, pn)) exit(0); } } /* If dumpfile is specified, write out all banks to * the file. There could be duplicate data in the dump * if more than one LAP is found within the span of * NUM_BANKS. If experiment mode is selected, extra * info is written out. For now, it just prepends * capture time. */ if (dumpfile) { for(i = 0; i < NUM_BANKS; i++) { uint32_t systime_be = htobe32(systime); if (fwrite(&systime_be, sizeof(systime_be), 1, dumpfile) != 1) {;} if (fwrite(&packets[(i + 1 + bank) % NUM_BANKS], sizeof(usb_pkt_rx), 1, dumpfile) != 1) {;} } } } }
/* Sniff for LAPs. If a piconet is provided, use the given LAP to * search for UAP. */ static void cb_br_rx(void* args, usb_pkt_rx *rx, int bank) { btbb_packet *pkt = NULL; btbb_piconet *pn = (btbb_piconet *)args; char syms[BANK_LEN * NUM_BANKS]; int i; int8_t signal_level; int8_t noise_level; int8_t snr; int offset; uint32_t clkn; uint32_t lap = LAP_ANY; uint8_t uap = UAP_ANY; /* Sanity check */ if (rx->channel > (NUM_BREDR_CHANNELS-1)) goto out; /* Copy packet (for dump) */ memcpy(&usb_packets[bank], rx, sizeof(usb_pkt_rx)); unpack_symbols(rx->data, br_symbols[bank]); /* Do analysis based on oldest packet */ rx = &usb_packets[ (bank+1) % NUM_BANKS ]; uint64_t nowns = now_ns_from_clk100ns( rx ); determine_signal_and_noise( rx, &signal_level, &noise_level ); snr = signal_level - noise_level; /* WC4: use vm circbuf if target allows. This gets rid of this * wrapped copy step. */ /* Copy 2 oldest banks of symbols for analysis. Packet may * cross a bank boundary. */ for (i = 0; i < 2; i++) memcpy(syms + i * BANK_LEN, br_symbols[(i + 1 + bank) % NUM_BANKS], BANK_LEN); /* Look for packets with specified LAP, if given. Otherwise * search for any packet. Also determine if UAP is known. */ if (pn) { lap = btbb_piconet_get_flag(pn, BTBB_LAP_VALID) ? btbb_piconet_get_lap(pn) : LAP_ANY; uap = btbb_piconet_get_flag(pn, BTBB_UAP_VALID) ? btbb_piconet_get_uap(pn) : UAP_ANY; } /* Pass packet-pointer-pointer so that * packet can be created in libbtbb. */ offset = btbb_find_ac(syms, BANK_LEN, lap, max_ac_errors, &pkt); if (offset < 0) goto out; /* Copy out remaining banks of symbols for full analysis. */ for (i = 1; i < NUM_BANKS; i++) memcpy(syms + i * BANK_LEN, br_symbols[(i + 1 + bank) % NUM_BANKS], BANK_LEN); /* Once offset is known for a valid packet, copy in symbols * and other rx data. CLKN here is the 312.5us CLK27-0. The * btbb library can shift it be CLK1 if needed. */ clkn = (rx->clkn_high << 20) + (le32toh(rx->clk100ns) + offset + 1562) / 3125; btbb_packet_set_data(pkt, syms + offset, NUM_BANKS * BANK_LEN - offset, rx->channel, clkn); /* Dump to PCAP/PCAPNG if specified */ #if defined(USE_PCAP) if (h_pcap_bredr) { btbb_pcap_append_packet(h_pcap_bredr, nowns, signal_level, noise_level, lap, uap, pkt); } #endif if (h_pcapng_bredr) { btbb_pcapng_append_packet(h_pcapng_bredr, nowns, signal_level, noise_level, lap, uap, pkt); } /* When reading from file, caller will read * systime before calling this routine, so do * not overwrite. Otherwise, get current time. */ if (infile == NULL) systime = time(NULL); /* If dumpfile is specified, write out all banks to the * file. There could be duplicate data in the dump if more * than one LAP is found within the span of NUM_BANKS. */ if (dumpfile) { for(i = 0; i < NUM_BANKS; i++) { uint32_t systime_be = htobe32(systime); if (fwrite(&systime_be, sizeof(systime_be), 1, dumpfile) != 1) {;} if (fwrite(&usb_packets[(i + 1 + bank) % NUM_BANKS], sizeof(usb_pkt_rx), 1, dumpfile) != 1) {;} } } printf("systime=%u ch=%2d LAP=%06x err=%u clk100ns=%u clk1=%u s=%d n=%d snr=%d\n", (int)systime, btbb_packet_get_channel(pkt), btbb_packet_get_lap(pkt), btbb_packet_get_ac_errors(pkt), rx->clk100ns, btbb_packet_get_clkn(pkt), signal_level, noise_level, snr); i = btbb_process_packet(pkt, pn); if(i < 0) { follow_pn = pn; stop_ubertooth = 1; } out: if (pkt) btbb_packet_unref(pkt); }