bpasniff.c revision 9594f14663b99363183735347aa5ab7bccf330b3
1/* 2 * 3 * Bluetooth packet analyzer - BPA sniffer 4 * 5 * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> 6 * 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * 23 * $Id$ 24 */ 25 26#ifdef HAVE_CONFIG_H 27#include <config.h> 28#endif 29 30#include <stdio.h> 31#include <errno.h> 32#include <ctype.h> 33#include <unistd.h> 34#include <stdlib.h> 35#include <malloc.h> 36#include <getopt.h> 37#include <signal.h> 38#include <sys/ioctl.h> 39#include <sys/socket.h> 40 41#include <bluetooth/bluetooth.h> 42#include <bluetooth/hci.h> 43#include <bluetooth/hci_lib.h> 44 45#include <netinet/in.h> 46 47static volatile sig_atomic_t __io_canceled = 0; 48 49static void sig_hup(int sig) 50{ 51} 52 53static void sig_term(int sig) 54{ 55 __io_canceled = 1; 56} 57 58static int read_revision(int dd, char *revision, int size) 59{ 60 struct hci_request rq; 61 unsigned char req[] = { 0x07 }; 62 unsigned char buf[46]; 63 64 memset(&rq, 0, sizeof(rq)); 65 rq.ogf = OGF_VENDOR_CMD; 66 rq.ocf = 0x000e; 67 rq.cparam = req; 68 rq.clen = sizeof(req); 69 rq.rparam = &buf; 70 rq.rlen = sizeof(buf); 71 72 if (hci_send_req(dd, &rq, 1000) < 0) 73 return -1; 74 75 if (buf[0] > 0) { 76 errno = EIO; 77 return -1; 78 } 79 80 if (revision) 81 strncpy(revision, buf + 1, size); 82 83 return 0; 84} 85 86static int enable_sniffer(int dd, uint8_t enable) 87{ 88 struct hci_request rq; 89 unsigned char req[] = { 0x00, enable }; 90 unsigned char buf[1]; 91 92 memset(&rq, 0, sizeof(rq)); 93 rq.ogf = OGF_VENDOR_CMD; 94 rq.ocf = 0x000e; 95 rq.cparam = req; 96 rq.clen = sizeof(req); 97 rq.rparam = &buf; 98 rq.rlen = sizeof(buf); 99 100 if (hci_send_req(dd, &rq, 1000) < 0) 101 return -1; 102 103 if (buf[0] > 0) { 104 errno = EIO; 105 return -1; 106 } 107 108 return 0; 109} 110 111static int enable_sync(int dd, uint8_t enable, bdaddr_t *bdaddr) 112{ 113 struct hci_request rq; 114 unsigned char req[] = { 0x01, enable, 115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 0x00, 0xfa, 0x00 }; 117 118 memcpy(req + 2, bdaddr, 6); 119 120 memset(&rq, 0, sizeof(rq)); 121 rq.ogf = OGF_VENDOR_CMD; 122 rq.ocf = 0x000e; 123 rq.cparam = req; 124 rq.clen = sizeof(req); 125 126 hci_send_req(dd, &rq, 1000); 127 128 return 0; 129} 130 131static void dump(unsigned char *buf, int count) 132{ 133 int i, n = 0, size; 134 135 while (count > 0) { 136 printf("%04x: ", n); 137 138 size = count > 16 ? 16 : count; 139 140 for (i = 0; i < size; i++) 141 printf("%02x%s", buf[i], (i + 1) % 8 ? " " : " "); 142 for (i = size; i < 16; i++) 143 printf(" %s", (i + 1) % 8 ? " " : " "); 144 145 for (i = 0; i < size; i++) 146 printf("%1c", isprint(buf[i]) ? buf[i] : '.'); 147 printf("\n"); 148 149 buf += size; 150 count -= size; 151 n += size; 152 } 153} 154 155static void process_frames(int dev) 156{ 157 struct sigaction sa; 158 struct hci_filter flt; 159 unsigned char *buf; 160 int dd, size = 2048; 161 162 buf = malloc(size); 163 if (!buf) { 164 fprintf(stderr, "Can't allocate buffer for hci%d: %s (%d)\n", 165 dev, strerror(errno), errno); 166 return; 167 } 168 169 dd = hci_open_dev(dev); 170 if (dd < 0) { 171 fprintf(stderr, "Can't open device hci%d: %s (%d)\n", 172 dev, strerror(errno), errno); 173 free(buf); 174 return; 175 } 176 177 hci_filter_clear(&flt); 178 hci_filter_set_ptype(HCI_VENDOR_PKT, &flt); 179 hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 180 hci_filter_set_event(EVT_VENDOR, &flt); 181 182 if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 183 fprintf(stderr, "Can't set filter for hci%d: %s (%d)\n", 184 dev, strerror(errno), errno); 185 hci_close_dev(dd); 186 free(buf); 187 return; 188 } 189 190 memset(&sa, 0, sizeof(sa)); 191 sa.sa_flags = SA_NOCLDSTOP; 192 sa.sa_handler = SIG_IGN; 193 sigaction(SIGCHLD, &sa, NULL); 194 sigaction(SIGPIPE, &sa, NULL); 195 196 sa.sa_handler = sig_term; 197 sigaction(SIGTERM, &sa, NULL); 198 sigaction(SIGINT, &sa, NULL); 199 200 sa.sa_handler = sig_hup; 201 sigaction(SIGHUP, &sa, NULL); 202 203 while (!__io_canceled) { 204 int len; 205 206 len = read(dd, buf, size); 207 if (len < 0) 208 break; 209 if (len < 2) 210 continue; 211 212 if (buf[0] == 0x04 && buf[1] == 0xff) { 213 if (buf[3] == 0x02) { 214 switch (buf[4]) { 215 case 0x00: 216 printf("Waiting for synchronization...\n"); 217 break; 218 case 0x08: 219 printf("Synchronization lost\n"); 220 __io_canceled = 1; 221 break; 222 default: 223 printf("Unknown event 0x%02x\n", buf[4]); 224 break; 225 } 226 } 227 } 228 229 if (buf[0] != 0xff) 230 continue; 231 232 dump(buf + 1, len - 1); 233 } 234 235 hci_close_dev(dd); 236 237 free(buf); 238} 239 240static void usage(void) 241{ 242 printf("bpasniff - Utility for the BPA 100/105 sniffers\n\n"); 243 printf("Usage:\n" 244 "\tcsrsniff [-i <dev>] <bdaddr>\n"); 245} 246 247static struct option main_options[] = { 248 { "help", 0, 0, 'h' }, 249 { "device", 1, 0, 'i' }, 250 { 0, 0, 0, 0} 251}; 252 253int main(int argc, char *argv[]) 254{ 255 struct hci_dev_info di; 256 struct hci_version ver; 257 char rev[46]; 258 bdaddr_t bdaddr; 259 int dd, opt, dev = 0; 260 261 bacpy(&bdaddr, BDADDR_ANY); 262 263 while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { 264 switch (opt) { 265 case 'i': 266 dev = hci_devid(optarg); 267 if (dev < 0) { 268 perror("Invalid device"); 269 exit(1); 270 } 271 break; 272 273 case 'h': 274 default: 275 usage(); 276 exit(0); 277 } 278 } 279 280 argc -= optind; 281 argv += optind; 282 optind = 0; 283 284 argc -= optind; 285 argv += optind; 286 optind = 0; 287 288 if (argc < 1) { 289 usage(); 290 exit(1); 291 } 292 293 str2ba(argv[0], &bdaddr); 294 295 dd = hci_open_dev(dev); 296 if (dd < 0) { 297 fprintf(stderr, "Can't open device hci%d: %s (%d)\n", 298 dev, strerror(errno), errno); 299 exit(1); 300 } 301 302 if (hci_devinfo(dev, &di) < 0) { 303 fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n", 304 dev, strerror(errno), errno); 305 hci_close_dev(dd); 306 exit(1); 307 } 308 309 if (hci_read_local_version(dd, &ver, 1000) < 0) { 310 fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n", 311 dev, strerror(errno), errno); 312 hci_close_dev(dd); 313 exit(1); 314 } 315 316 if (ver.manufacturer != 12) { 317 fprintf(stderr, "Can't find sniffer at hci%d: %s (%d)\n", 318 dev, strerror(ENOSYS), ENOSYS); 319 hci_close_dev(dd); 320 exit(1); 321 } 322 323 if (read_revision(dd, rev, sizeof(rev)) < 0) { 324 fprintf(stderr, "Can't read revision info for hci%d: %s (%d)\n", 325 dev, strerror(errno), errno); 326 hci_close_dev(dd); 327 exit(1); 328 } 329 330 printf("%s\n", rev); 331 332 if (enable_sniffer(dd, 0x01) < 0) { 333 fprintf(stderr, "Can't enable sniffer for hci%d: %s (%d)\n", 334 dev, strerror(errno), errno); 335 hci_close_dev(dd); 336 exit(1); 337 } 338 339 if (enable_sync(dd, 0x01, &bdaddr) < 0) { 340 fprintf(stderr, "Can't enable sync for hci%d: %s (%d)\n", 341 dev, strerror(errno), errno); 342 enable_sniffer(dd, 0x00); 343 hci_close_dev(dd); 344 exit(1); 345 } 346 347 process_frames(dev); 348 349 if (enable_sync(dd, 0x00, &bdaddr) < 0) { 350 fprintf(stderr, "Can't disable sync for hci%d: %s (%d)\n", 351 dev, strerror(errno), errno); 352 enable_sniffer(dd, 0x00); 353 hci_close_dev(dd); 354 exit(1); 355 } 356 357 if (enable_sniffer(dd, 0x00) < 0) { 358 fprintf(stderr, "Can't disable sniffer for hci%d: %s (%d)\n", 359 dev, strerror(errno), errno); 360 hci_close_dev(dd); 361 exit(1); 362 } 363 364 hci_close_dev(dd); 365 366 return 0; 367} 368