📄 bs_screen.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_screen.c: The code for the bluetooth screen 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 <curses.h>#include "btscanner.h"#define C_BLK_TMOUT 500#define SCR_BUF_SZ 1024sub_classes_t class_computer[] = { {0x00, "Uncategorised"}, {0x04, "Desktop"}, {0x08, "Server"}, {0x0c, "Laptop"}, {0x10, "Handheld PC-PDA"}, {0x14, "Palm sized PC-PDA"}, {0x18, "Wearable computer"}, {0x00, NULL}};sub_classes_t class_phone[] = { {0x00, "Uncategorised"}, {0x04, "Mobile"}, {0x08, "Cordless"}, {0x0c, "Smart phone"}, {0x10, "Wired modem or voice gateway"}, {0x14, "Common ISDN Access"}, {0x00, NULL}};sub_classes_t class_network[] = { {0x00, "0% utilised"}, {0x20, "1 - 17% utilised"}, {0x40, "17 - 33% utilised"}, {0x60, "33 - 50% utilised"}, {0x80, "50 - 67% utilised"}, {0xa0, "67 - 83% utilised"}, {0xc0, "83 - 99% utilised"}, {0xe0, "100% utilised"}, {0x00, NULL}};sub_classes_t class_av[] = { {0x00, "Uncategorised"}, {0x04, "Headset"}, {0x08, "Hands free"}, {0x0c, "Reserved"}, {0x10, "Microphone"}, {0x14, "Loudspeaker"}, {0x18, "Headphones"}, {0x1c, "Portable Audio"}, {0x20, "Car Audio"}, {0x24, "Set top box"}, {0x28, "HiFi Audio"}, {0x2c, "VCR"}, {0x30, "Video Camera"}, {0x34, "Camcorder"}, {0x38, "Video Monitor"}, {0x3c, "Video Display and Loudspeaker"}, {0x40, "Video Conferencing"}, {0x44, "Reserved"}, {0x48, "Gaming"}, {0x00, NULL},};sub_classes_t class_peripheral1[] = { {0x40, "Keyboard"}, {0x80, "Pointing device"}, {0xC0, "Combo"}, {0x00, NULL}};sub_classes_t class_peripheral2[] = { {0x00, "Uncategorised"}, {0x04, "Joystick"}, {0x08, "Gamepad"}, {0x0c, "Remote control"}, {0x10, "Sensing device"}, {0x14, "Digitiser tablet"}, {0x18, "Card Reader"}, {0x00, NULL}};sub_classes_t class_imaging[] = { {0x10, "Display"}, {0x20, "Camera"}, {0x40, "Scanner"}, {0x80, "Printer"}, {0x00, NULL}};#define MAJOR_CLASS_DEFAULT 0x1fclasses_t major_device_classes[] = { {0x00, 0x00, 0x00, CLASS_CHOOSE, NULL, NULL, "Miscellaneous"}, {0x01, 0xfc, 0x00, CLASS_CHOOSE, class_computer, NULL, "Computer"}, {0x02, 0xfc, 0x00, CLASS_CHOOSE, class_phone, NULL, "Phone"}, {0x03, 0xe0, 0x00, CLASS_CHOOSE, class_network, NULL, "Network"}, {0x04, 0xfc, 0x00, CLASS_CHOOSE, class_av, NULL, "Audio-Video"}, {0x05, 0xc0, 0x3c, CLASS_CHOOSE, class_peripheral1, class_peripheral2, "Peripheral"}, {0x06, 0xf0, 0x00, CLASS_BITMASK, class_imaging, NULL, "Imaging"}, {0x1f, 0x00, 0x00, CLASS_CHOOSE, NULL, NULL, "Uncategorised"}, {0x00, 0x00, 0x00, CLASS_CHOOSE, NULL, NULL, NULL}};sub_classes_t service_classes[] = { {0x001, "Limited Discoverable mode"}, {0x002, "Reserved"}, {0x004, "Reserved"}, {0x008, "Positioning"}, {0x010, "Networking"}, {0x020, "Rendering"}, {0x040, "Capturing"}, {0x080, "Object Transfer"}, {0x100, "Audio"}, {0x200, "Telephony"}, {0x400, "Information"}, {0, NULL}};/* curses startup */int bs_screen_on(void){ initscr(); /* initialise */ cbreak(); /* flush keys immediately */ noecho(); /* dont echo char */ nonl(); /* \n not translated */ intrflush(stdscr, FALSE); /* flush on interrupt */ keypad(stdscr, TRUE); /* enable keys */ wtimeout(stdscr, C_BLK_TMOUT); /* wait for 1 sec on input */ curs_set(0); /* invisible cursor */ return 0;}/* screen off */int bs_screen_off(void){ curs_set(1); endwin(); return 0;}/* clear, border and title */int bs_screen_cbt(WINDOW *w, const char *title, size_t len){ size_t maxx, maxy; if (NULL == w) return 1; /* clear */ werase(w); /* border */ wborder(w, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER); getmaxyx(w, maxy, maxx); /* header string */ if ((len+3) <= maxx) mvwaddnstr(w, 0, 2, title, len); mvwaddstr(w, 1, 1, " LS Address Clk Off Class Name"); /* static footer string */ if (20 <= maxx) mvwaddstr(w, (signed)maxy-1, (signed)2, "Devices found: "); return 0;}/* draw the footer */int bs_screen_footer(WINDOW *w, int ndev){ int maxx, maxy; getmaxyx(w, maxy, maxx); mvwprintw(w, maxy-1, 17, "%d ", ndev); return 0;}/* resize the screen */int bs_screen_resize(void){ return wresize(stdscr, LINES, COLS);}/* draw the list of found items */int bs_screen_drawlist(WINDOW *w, struct proc_info *pi, int itemsel){ int i, r; size_t c, j; char *buf; char tmp[32]; device_t *p; if (w == NULL) return -1; getmaxyx(w, r, c); r--; buf = (char*)malloc(sizeof(char)*(c+1)); if (NULL == buf) return -1; /* the list attached to pi->dhead will only ever grow, dont * need to clear the screen each time. we will imit the output width * to c-2 because the window has a border */ pthread_mutex_lock(&(pi->proc_info_mutex)); if (NULL != pi->scanner_error) { mvwaddstr(w, 0, 0, pi->scanner_error); p = NULL; } else { p = pi->dhead; } pthread_mutex_unlock(&(pi->proc_info_mutex)); pthread_mutex_lock(&(pi->dhead_mutex)); for (i = 0; p && i < r; i++) { ba2str(&(p->bdaddr), tmp); snprintf(buf, c, "%3d %s 0x%4.4x 0x%6.6x %s", p->last_scanned, tmp, p->clk_off, p->class, p->name); buf[c] = 0; /* pad with spaces */ for(j = strlen(buf); j<c; j++) buf[j] = ' '; buf[c] = 0; if (i == itemsel) wattron(w, A_REVERSE); mvwaddstr(w, i, 0, buf); if (i == itemsel) wattroff(w, A_REVERSE); p = p->next; } pthread_mutex_unlock(&(pi->dhead_mutex)); free(buf); return i;}/* check to the min screen size */int bs_screen_checksize(void){ int y,x; getmaxyx(stdscr, y, x); if(y>=10 && x>=80) return 0; return 1;}/* make a subwindow */WINDOW *bs_screen_subwin(WINDOW *parent){ WINDOW *n; int x,y; getmaxyx(parent, y, x); n = derwin(parent, y-3, x-2, 2, 1); wtimeout(n, C_BLK_TMOUT); /* wait for 1 sec on input */ keypad(n, TRUE); /* enable keys */ touchwin(parent); return n;}/* make a subwindow */int bs_screen_subwin_resize(WINDOW *p, WINDOW *me){ int x,y; getmaxyx(p, y, x); return wresize(me, y-3, x-2);}/* * process lines, this takes a string, cuts it into lines and makes a * linked list that holds all the display lines, therefore it is trivial * to do scrolling */int bs_processlines(struct proc_info *pi, char *s){ int start, end, len; scr_line_t *pp, *p, *n; if (!s) return 1; for (pp=NULL, p=pi->scr_head; p; pp=p, p=p->next); for(start = end = 0; s[end] != 0; end++) { if ('\n' == s[end]) { len = (end - start) + 1; n = (scr_line_t*)malloc(sizeof(scr_line_t)); if (!n) return 1; memset(n, 0, sizeof(scr_line_t)); n->line = (char*)malloc(sizeof(char) * (len + 1)); if (!n->line) {free(n); return 1;} strncpy(n->line, s+start, len); n->line[len] = 0; if (!pp) pi->scr_head = n; else pp->next = n; pp = n; pi->scr_lines++; start = end+1;/* start == end on next loop */ } } return 0;}int bs_freelines(struct proc_info *pi){ scr_line_t *p, *pn; if (pi) { for(p=pi->scr_head; p; p=pn) { pn = p->next; free(p->line); free(p); } } pi->scr_head = NULL; pi->scr_lines = 0; return 0;}int bs_displaylines(struct proc_info *pi, WINDOW *w){ scr_line_t *p; int i; werase(w); wmove(w, 0, 0); for(i=0, p=pi->scr_head; p && i < pi->scr_lines_end; i++, p=p->next) { if (pi->scr_lines_start <= i) { waddstr(w, p->line); } } return 0;}/* print the advanced details */int bs_screen_show_details(WINDOW *w, struct proc_info *pi, device_t *p){ char tmp[32], buf[SCR_BUF_SZ]; char *ouiname; uint32_t services, majorc, minorc; int i, found, majorc_id; sub_classes_t *scp; bs_freelines(pi); ba2str(&(p->bdaddr), tmp); ouiname = ouidb_query(pi, &(p->bdaddr)); /* find the class + services */ services = (p->class & 0x00ffe000) >> 13; majorc = (p->class & 0x00001f00) >> 8; minorc = (p->class & 0x000000fc); snprintf(buf, SCR_BUF_SZ, "Address: %s\n" "OUI owner: %s\n" "Name: %s\n" "Clk off: 0x%4.4x\n" "Class: 0x%6.6x\n" " ", tmp, (NULL==ouiname)?"":ouiname, p->name, p->clk_off, p->class); if (NULL != ouiname) free(ouiname); /* print the textual device class */ for (found=i=0; major_device_classes[i].class_name; i++) { if (major_device_classes[i].class_id == majorc) { found = 1; majorc_id = i; strncat(buf, major_device_classes[i].class_name, SCR_BUF_SZ); buf[SCR_BUF_SZ-1] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -