📄 bs_scan.c
字号:
/* * btscanner - Displays the output of Bluetooth scans * Copyright (C) 2003 Pentest Limited * * Written 2003 by Tim Hurman <timh at pentest.co.uk> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE * FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE * IS DISCLAIMED. *//* * bs_scan.c: The code for the bluetooth scanner thread. */#include <sys/types.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <stdio.h>#include <signal.h>#include <errno.h>#include <string.h>#include <sys/ioctl.h>#include "btscanner.h"void bs_set_scanner_error (struct proc_info *pi, const char *pfx){ size_t l; char *p; l = strlen(strerror(errno)) + strlen(pfx) + 3; p = (char *)malloc(l * sizeof(char)); if (NULL == p) return; snprintf(p, l, "%s: %s", pfx, strerror(errno)); p[l-1] = 0; pthread_mutex_lock(&(pi->proc_info_mutex)); if (pi->scanner_error != NULL) free(pi->scanner_error); pi->scanner_error = p; pthread_mutex_unlock(&(pi->proc_info_mutex)); return;}/* copy a device name */int bs_copy_name(device_t *td, char *name){ size_t i; if (td->name != NULL) free(td->name); i = strlen(name)+1; td->name = (char *)malloc(i * sizeof(char)); if (NULL == td->name) return 1; strncpy(td->name, name, i); return 0;}/* find an item in the linked list */device_t *bs_find_item(struct proc_info *pi, device_t *item){ device_t *p = pi->dhead; pthread_mutex_lock(&(pi->dhead_mutex)); while (p) { if (0 == bacmp(&(p->bdaddr), &(item->bdaddr))) break; p = p->next; } pthread_mutex_unlock(&(pi->dhead_mutex)); return p;}/* convert a bd address to an integer */uint64_t bd2int(bdaddr_t *bd){ uint64_t ret; ret = bd->b[0]; ret <<= 8; ret |= bd->b[1]; ret <<= 8; ret |= bd->b[2]; ret <<= 8; ret |= bd->b[3]; ret <<= 8; ret |= bd->b[4]; ret <<= 8; ret |= bd->b[5]; return ret;}/* intert an item into the list */int bs_insert_item(struct proc_info *pi, device_t *item){ device_t *p, *pp, *n; n = (device_t*)malloc(sizeof(device_t)); if (NULL == n) return 1; memset(n, 0, sizeof(device_t)); memcpy(n, item, sizeof(device_t)); pthread_mutex_lock(&(pi->dhead_mutex)); p = pi->dhead; pp = NULL; /* the list is ordered by mac/bdaddr */ /* pp = previous item, p = the current item */ while (p) { if (bd2int(&n->bdaddr) < bd2int(&p->bdaddr)) break; pp = p; p = p->next; } /* stick the new item on pp->next */ if (NULL == pp) { pi->dhead = n; n->next = p; } else { pp->next = n; n->next = p; } pthread_mutex_unlock(&(pi->dhead_mutex)); return 0;}/* update an item with new details */int bs_update_item(struct proc_info *pi, device_t *p, device_t *item){ pthread_mutex_lock(&(pi->dhead_mutex)); item->next = p->next; if(p->name) free(p->name); memcpy(p, item, sizeof(device_t)); pthread_mutex_unlock(&(pi->dhead_mutex)); return 0;}/* debug only */int bs_print_item(device_t *item){ fprintf(stderr, "Addr: %s\tName: %s\tClk off: %4.4x\tClass: %6.6x\n", batostr(&(item->bdaddr)), item->name, item->clk_off, item->class); return 1;}/* save the device detail to the linked list */int bs_save_details(struct proc_info *pi, device_t *item){ device_t *p; p = bs_find_item(pi, item); if (p == NULL) { bs_insert_item(pi, item); } else { bs_update_item(pi, p, item); } /*bs_print_item(item);*/ return 0;}int bs_sdp_free(search_context_t *ctxt){ if (ctxt->sub) bs_sdp_free(ctxt->sub); ctxt->sub=NULL; if (ctxt->next) bs_sdp_free(ctxt->next); ctxt->next=NULL; if(ctxt->rec) sdp_record_free(ctxt->rec); free(ctxt); return 0;}int bs_free_details(struct proc_info *pi){ device_t *p, *pp; pthread_mutex_lock(&(pi->dhead_mutex)); p = pi->dhead; pp = NULL; while(p) { pp = p; p = p->next; /* if the sdp tree exists, free that */ if (pp->sdp_info) { bs_sdp_free(pp->sdp_info); pp->sdp_info=NULL; } /* the main details */ if(pp->name) free(pp->name); free(pp); } pi->dhead = NULL; pthread_mutex_unlock(&(pi->dhead_mutex)); return 0;}int bs_inc_scan_count(struct proc_info *pi){ device_t *p, *pp; pthread_mutex_lock(&(pi->dhead_mutex)); p = pi->dhead; pp = NULL; while(p) { pp = p; p = p->next; pp->last_scanned<1000?pp->last_scanned++:pp->last_scanned; } pthread_mutex_unlock(&(pi->dhead_mutex)); return 0;}#define BUFN_SZ 512/* bs_do_inquiry: run a standard inquiry */int bs_do_inquiry (struct proc_info *pi, int *doloop){ int num_rsp, length, flags, dd, i; inquiry_info *info = NULL; device_t td, *tdp; char buf[BUFN_SZ]; /* reset the last found list */ bs_inc_scan_count(pi); length = 8; /* ~10 seconds */ flags = IREQ_CACHE_FLUSH; /* flush each time */ num_rsp = 10; /* max devices to scan for, FIXME */ /* scan */ num_rsp = hci_inquiry(pi->dev_id, length, num_rsp, NULL, &info, flags); if (num_rsp < 0) { if (EINTR == errno) return -1; bs_set_scanner_error(pi, "doscan::hci_inquiry():"); return -1; } /* open the bluetooth device to enquiries */ dd = hci_open_dev(pi->dev_id); if (dd < 0) { if (EINTR == errno) return -1; bs_set_scanner_error(pi, "doscan::hci_inquiry():"); return -1; } /* now we have a list of devices, get thier info and enum */ for (i = 0; i < num_rsp && *doloop; i++) { memset(&td, 0, sizeof(device_t)); /* the address */ bacpy(&(td.bdaddr), &(info+i)->bdaddr); /* look for the device, if found, skip it */ tdp = bs_find_item(pi, &td); if (NULL != tdp) { tdp->last_scanned = 0; continue; } /* the name */ if (hci_read_remote_name(dd, &(info+i)->bdaddr, BUFN_SZ*sizeof(char), buf, 100000) == 0) bs_copy_name(&td, buf); else bs_copy_name(&td, "n/a"); /* the clock offset + class */ td.clk_off = (info+i)->clock_offset; td.class = (info+i)->dev_class[2] << 16; td.class |= (info+i)->dev_class[1] << 8; td.class |= (info+i)->dev_class[0]; td.last_scanned = 0; /* save the details */ bs_save_details(pi, &td); } /* tidy up */ hci_close_dev(dd); free(info); info = NULL; return 0;}/* run the scanning loop */void *bs_runscan(void *arg){ struct proc_info *pi = (struct proc_info*)arg; sigset_t sset; int i; int *doloop = NULL; if (NULL == pi) goto bs_runscan_leave; doloop = (int*)malloc(sizeof(int)); if (NULL == doloop) goto bs_runscan_leave; *doloop = 1; if (0 != (i = pthread_setspecific(doloop_key, doloop))) goto bs_runscan_leave; /* block SIGWINCH, dont give a crap about it */ memset (&sset, 0, sizeof(sset)); sigfillset(&sset); sigdelset(&sset, SIGKILL); sigdelset(&sset, SIGSTOP); sigdelset(&sset, SIGTERM); sigdelset(&sset, SIGINT); sigdelset(&sset, SIGSEGV); sigdelset(&sset, SIGUSR1); if (0 != pthread_sigmask(SIG_SETMASK, &sset, NULL)) goto bs_runscan_leave; /* run loop */ while (*doloop) { /* clear the last error, if there was one */ pthread_mutex_lock(&(pi->proc_info_mutex)); if (pi->scanner_error) { free(pi->scanner_error); pi->scanner_error = NULL; } pthread_mutex_unlock(&(pi->proc_info_mutex)); /* run a scan */ pthread_mutex_lock(&(pi->dev_mutex)); i = bs_do_inquiry(pi, doloop); pthread_mutex_unlock(&(pi->dev_mutex)); if(i) sleep(1); } /* leave */ bs_runscan_leave: if(doloop) free(doloop); bs_free_details(pi); pthread_mutex_lock(&(pi->proc_info_mutex)); if (pi->scanner_error) free(pi->scanner_error); for (i=0; i<MAX_WORK_THREADS; i++) { if (pi->thr_ids[i] == pthread_self()) { pi->thr_died[i] = 1; break; } } pthread_mutex_unlock(&(pi->proc_info_mutex)); pthread_exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -