📄 bs_info.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_info.c: query the device */#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_info_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->info_error != NULL) free(pi->info_error); pi->info_error = p; pthread_mutex_unlock(&(pi->proc_info_mutex)); return;}/* * most of this is a blatant rip-off of hcitool.c, but hey, because it is * GPL, then we can to that. */static int find_conn(int s, int dev_id, long arg){ struct hci_conn_list_req *cl; struct hci_conn_info *ci; int i, ret=0; if (!(cl = malloc(10 * sizeof(*ci) + sizeof(*cl)))) return 0; cl->dev_id = dev_id; cl->conn_num = 10; ci = cl->conn_info; if (ioctl(s, HCIGETCONNLIST, (void*)cl)) { free(cl); return 0; } for (i=0; i < cl->conn_num; i++, ci++) { if (!bacmp((bdaddr_t *)arg, &ci->bdaddr)) { ret = 1; break; } } free(cl); return ret;}/* sdp search - extract the public sdp info */int sdp_search(struct proc_info *pi, bdaddr_t *bdaddr, search_context_t *context){ sdp_list_t *attrid, *search, *seq, *next; uint32_t range = 0x0000ffff; sdp_session_t *sess; search_context_t *sub_ctxt_prev, *sub_ctxt; /* conenct */ sess = sdp_connect(&pi->dev_bd, bdaddr, SDP_RETRY_IF_BUSY); if (!sess) return 1; /* search */ attrid = sdp_list_append(0, &range); search = sdp_list_append(0, &context->group); if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) { sdp_close(sess); return 1; } sdp_list_free(attrid, 0); sdp_list_free(search, 0); /* recursive extract */ sub_ctxt_prev = NULL; for (; seq; seq = next) { sub_ctxt = (search_context_t*)malloc(sizeof(search_context_t)); if (NULL == sub_ctxt) break; memset(sub_ctxt, 0, sizeof(search_context_t)); sub_ctxt->rec = (sdp_record_t *) seq->data; /* append then expand the sub context */ if (sub_ctxt_prev == NULL) { context->sub = sub_ctxt; } else { sub_ctxt_prev->next = sub_ctxt; } if (sdp_get_group_id(sub_ctxt->rec, &sub_ctxt->group) != -1) { /* Set the subcontext for browsing the sub tree */ memcpy(sub_ctxt, context, sizeof(search_context_t)); sub_ctxt->sub = sub_ctxt->next = NULL; /* Browse the next level down if not done */ if (sub_ctxt->group.value.uuid16 != context->group.value.uuid16) sdp_search(pi, bdaddr, sub_ctxt); } /* step on */ sub_ctxt_prev = sub_ctxt; next = seq->next; free(seq); } sdp_close(sess); return 0;}/* bs_get_info: get more info from a device */int bs_get_info (struct proc_info *pi, int *doloop, bdaddr_t *ba){ device_t *p; uint16_t handle; int dev_id, i, dd, cc = 0; struct hci_conn_info_req *cr; struct hci_request rq; read_rssi_rp rp_rssi; get_link_quality_rp rp_lq; int err = 0; int leave = 0;; /* we have something to do, yay!! */ pthread_mutex_lock(&(pi->dhead_mutex)); for (p=pi->dhead; 0 != bacmp(ba, &(p->bdaddr)); p=p->next); if (p) p->scan_count = 0; pthread_mutex_unlock(&(pi->dhead_mutex)); /* found anything */ if (NULL == p) { bs_set_info_error(pi, "Unable to find device info"); return -1; } /* begin */ dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) ba); if (dev_id < 0) { dev_id = hci_get_route(ba); cc = 1; } if (dev_id < 0) { bs_set_info_error(pi, "Device is not available or not connected"); return -1; } /* we have a local device with a route to the remote device */ dd = hci_open_dev(dev_id); if (dd < 0) { bs_set_info_error(pi, "HCI device open failed"); return -1; } /* create a new connection or get the old one */ if (cc) { if (hci_create_connection(dd, ba, 0x0008 | 0x0010, 0, 0, &handle, 25000) < 0) { bs_set_info_error(pi, "Can't create connection"); close(dd); return -1; } } else { cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); if (!cr) return -1; bacpy(&cr->bdaddr, ba); cr->type = ACL_LINK; if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { free(cr); bs_set_info_error(pi, "Get connection info failed"); return -1; } handle = cr->conn_info->handle; } /* read the remote details */ /* lock the list so that we can edit it */ pthread_mutex_lock(&(pi->dhead_mutex)); err = 0; /* hci version details */ if (!p->got_version) { if (hci_read_remote_version(dd, handle, &(p->version), 20000) == 0) p->got_version=1; else { err = 1; } } /* hci features */ if(!p->got_features && !err) if (hci_read_remote_features(dd, handle, p->features, 20000) == 0) p->got_features=1; /* sdp info */ if (!p->sdp_info && !err) { /* allocate the head and search */ p->sdp_info = (search_context_t*)malloc(sizeof(search_context_t)); if (NULL != p->sdp_info) { memset(p->sdp_info, 0, sizeof(search_context_t)); sdp_uuid16_create(&(p->sdp_info->group), PUBLIC_BROWSE_GROUP); sdp_search(pi, &p->bdaddr, p->sdp_info); leave = 1; /*sdp kills the conenction */ } } /* let the ther threads have a look */ pthread_mutex_unlock(&(pi->dhead_mutex)); if (leave) goto bs_get_info_tidyup; err = 0; /* keep a monitor on the rssi and lq */ while(*doloop) { /* lock the list so that we can edit it */ pthread_mutex_lock(&(pi->dhead_mutex)); if (err) { sleep(1); continue; } /* get the "interesting" values */ /* rssi */ memset(&rq, 0, sizeof(rq)); memset(&rp_rssi, 0, sizeof(rp_rssi)); rq.ogf = OGF_STATUS_PARAM; rq.ocf = OCF_READ_RSSI; rq.cparam = &handle; rq.clen = 2; rq.rparam = &rp_rssi; rq.rlen = READ_RSSI_RP_SIZE; if (hci_send_req(dd, &rq, 100) < 0) { p->rssi_status = (uint8_t)-1; p->rssi = 0; err = 1; } p->rssi_status = rp_rssi.status; if (rp_rssi.status) p->rssi = 0; else p->rssi = rp_rssi.rssi; /* the link quality (essentially BER on CSR devices) */ memset(&rq, 0, sizeof(rq)); memset(&rp_lq, 0, sizeof(rp_lq)); rq.ogf = OGF_STATUS_PARAM; rq.ocf = OCF_GET_LINK_QUALITY; rq.cparam = &handle; rq.clen = 2; rq.rparam = &rp_lq; rq.rlen = GET_LINK_QUALITY_RP_SIZE; if (hci_send_req(dd, &rq, 100) < 0) { p->lq_status = (uint8_t)-1; p->lq = 0; err = 1; } p->lq_status = rp_lq.status; if (rp_lq.status) p->lq = 0; else p->lq = rp_lq.link_quality; p->scan_count++; /* unlock the list so someone else can play */ pthread_mutex_unlock(&(pi->dhead_mutex)); /* should we do another loop? */ pthread_mutex_lock(&(pi->proc_info_mutex)); i = bacmp(ba, &(pi->query_bd)); pthread_mutex_unlock(&(pi->proc_info_mutex)); /* and relax ... */ if (i) break; usleep(500000); } /* tidy up */ bs_get_info_tidyup: if (cc) hci_disconnect(dd, handle, 0x13, 10000); else free(cr); hci_close_dev(dd); return 0;}/* run the info loop */void *bs_runinfo(void *arg){ struct proc_info *pi = (struct proc_info*)arg; sigset_t sset; int i; bdaddr_t bd_local; int *doloop = NULL; if (NULL == pi) goto bs_runinfo_leave; doloop = (int*)malloc(sizeof(int)); if (NULL == doloop) goto bs_runinfo_leave; *doloop = 1; if (0 != (i = pthread_setspecific(doloop_key, doloop))) goto bs_runinfo_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_runinfo_leave; /* run loop */ while (*doloop) { memset(&bd_local, 0, sizeof(bdaddr_t)); /* clear the last error, if there was one */ pthread_mutex_lock(&(pi->proc_info_mutex)); i = bacmp(&bd_local, &(pi->query_bd)); if(i) bacpy(&bd_local, &(pi->query_bd)); pthread_mutex_unlock(&(pi->proc_info_mutex)); /* get more info */ if (i) { pthread_mutex_lock(&(pi->dev_mutex)); bs_get_info(pi, doloop, &bd_local); pthread_mutex_unlock(&(pi->dev_mutex)); } else sleep(1); } /* leave */ bs_runinfo_leave: if (doloop) free(doloop); pthread_mutex_lock(&(pi->proc_info_mutex)); if (pi->info_error) free(pi->info_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 + -