hcidump.c revision 2d5448570830f8f05b40cb090d1576630b69af73
1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2000-2002 Maxim Krasnyansky <maxk@qualcomm.com> 6 * Copyright (C) 2003-2006 Marcel Holtmann <marcel@holtmann.org> 7 * 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include <config.h> 27#endif 28 29#include <stdio.h> 30#include <errno.h> 31#include <fcntl.h> 32#include <unistd.h> 33#include <stdlib.h> 34#include <string.h> 35#include <getopt.h> 36#include <sys/stat.h> 37#include <sys/types.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 <arpa/inet.h> 46#include <netinet/in.h> 47#include <netdb.h> 48 49#include "parser/parser.h" 50#include "parser/sdp.h" 51 52#if __BYTE_ORDER == __LITTLE_ENDIAN 53static inline uint64_t ntoh64(uint64_t n) 54{ 55 uint64_t h; 56 uint64_t tmp = ntohl(n & 0x00000000ffffffff); 57 h = ntohl(n >> 32); 58 h |= tmp << 32; 59 return h; 60} 61#elif __BYTE_ORDER == __BIG_ENDIAN 62#define ntoh64(x) (x) 63#else 64#error "Unknown byte order" 65#endif 66#define hton64(x) ntoh64(x) 67 68#define SNAP_LEN HCI_MAX_FRAME_SIZE 69#define DEFAULT_PORT 10839; 70 71/* Modes */ 72enum { 73 PARSE, 74 READ, 75 WRITE, 76 RECEIVE, 77 SEND, 78 AUDIO 79}; 80 81/* Default options */ 82static int device; 83static int snap_len = SNAP_LEN; 84static int defpsm = 0; 85static int defcompid = DEFAULT_COMPID; 86static int mode = PARSE; 87static int permcheck = 1; 88static long flags; 89static long filter; 90static char *dump_file = NULL; 91static char *audio_file = NULL; 92static in_addr_t dump_addr = INADDR_LOOPBACK; 93static in_port_t dump_port = DEFAULT_PORT; 94 95struct hcidump_hdr { 96 uint16_t len; 97 uint8_t in; 98 uint8_t pad; 99 uint32_t ts_sec; 100 uint32_t ts_usec; 101} __attribute__ ((packed)); 102#define HCIDUMP_HDR_SIZE (sizeof(struct hcidump_hdr)) 103 104struct btsnoop_hdr { 105 uint8_t id[8]; /* Identification Pattern */ 106 uint32_t version; /* Version Number = 1 */ 107 uint32_t type; /* Datalink Type */ 108} __attribute__ ((packed)); 109#define BTSNOOP_HDR_SIZE (sizeof(struct btsnoop_hdr)) 110 111struct btsnoop_pkt { 112 uint32_t size; /* Original Length */ 113 uint32_t len; /* Included Length */ 114 uint32_t flags; /* Packet Flags */ 115 uint32_t drops; /* Cumulative Drops */ 116 uint64_t ts; /* Timestamp microseconds */ 117 uint8_t data[0]; /* Packet Data */ 118} __attribute__ ((packed)); 119#define BTSNOOP_PKT_SIZE (sizeof(struct btsnoop_pkt)) 120 121static uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e, 0x6f, 0x6f, 0x70, 0x00 }; 122 123static uint32_t btsnoop_version = 0; 124static uint32_t btsnoop_type = 0; 125 126static inline int read_n(int fd, char *buf, int len) 127{ 128 register int t = 0, w; 129 130 while (len > 0) { 131 if ((w = read(fd, buf, len)) < 0) { 132 if (errno == EINTR || errno == EAGAIN) 133 continue; 134 return -1; 135 } 136 if (!w) 137 return 0; 138 len -= w; buf += w; t += w; 139 } 140 return t; 141} 142 143static inline int write_n(int fd, char *buf, int len) 144{ 145 register int t = 0, w; 146 147 while (len > 0) { 148 if ((w = write(fd, buf, len)) < 0) { 149 if (errno == EINTR || errno == EAGAIN) 150 continue; 151 return -1; 152 } 153 if (!w) 154 return 0; 155 len -= w; buf += w; t += w; 156 } 157 return t; 158} 159 160static void process_frames(int dev, int sock, int fd, unsigned long flags) 161{ 162 struct cmsghdr *cmsg; 163 struct msghdr msg; 164 struct iovec iv; 165 struct hcidump_hdr *dh; 166 struct btsnoop_pkt *dp; 167 struct frame frm; 168 char *buf, *ctrl; 169 int len, hdr_size = HCIDUMP_HDR_SIZE; 170 171 if (snap_len < SNAP_LEN) 172 snap_len = SNAP_LEN; 173 174 if (flags & DUMP_BTSNOOP) 175 hdr_size = BTSNOOP_PKT_SIZE; 176 177 buf = malloc(snap_len + hdr_size); 178 if (!buf) { 179 perror("Can't allocate data buffer"); 180 exit(1); 181 } 182 183 dh = (void *) buf; 184 dp = (void *) buf; 185 frm.data = buf + hdr_size; 186 187 ctrl = malloc(100); 188 if (!ctrl) { 189 perror("Can't allocate control buffer"); 190 exit(1); 191 } 192 193 if (dev == HCI_DEV_NONE) 194 printf("system: "); 195 else 196 printf("device: hci%d ", dev); 197 198 printf("snap_len: %d filter: 0x%lx\n", snap_len, filter); 199 200 memset(&msg, 0, sizeof(msg)); 201 202 while (1) { 203 iv.iov_base = frm.data; 204 iv.iov_len = snap_len; 205 206 msg.msg_iov = &iv; 207 msg.msg_iovlen = 1; 208 msg.msg_control = ctrl; 209 msg.msg_controllen = 100; 210 211 len = recvmsg(sock, &msg, 0); 212 if (len < 0) { 213 perror("Receive failed"); 214 exit(1); 215 } 216 217 /* Process control message */ 218 frm.data_len = len; 219 frm.dev_id = dev; 220 frm.in = 0; 221 frm.audio_fd = parser.audio_fd; 222 223 cmsg = CMSG_FIRSTHDR(&msg); 224 while (cmsg) { 225 switch (cmsg->cmsg_type) { 226 case HCI_CMSG_DIR: 227 frm.in = *((int *) CMSG_DATA(cmsg)); 228 break; 229 case HCI_CMSG_TSTAMP: 230 frm.ts = *((struct timeval *) CMSG_DATA(cmsg)); 231 break; 232 } 233 cmsg = CMSG_NXTHDR(&msg, cmsg); 234 } 235 236 frm.ptr = frm.data; 237 frm.len = frm.data_len; 238 239 switch (mode) { 240 case WRITE: 241 case SEND: 242 /* Save or send dump */ 243 if (flags & DUMP_BTSNOOP) { 244 uint64_t ts; 245 uint8_t pkt_type = ((uint8_t *) frm.data)[0]; 246 dp->size = htonl(frm.data_len); 247 dp->len = dp->size; 248 dp->flags = ntohl(frm.in & 0x01); 249 dp->drops = 0; 250 ts = (frm.ts.tv_sec - 946684800ll) * 1000000ll + frm.ts.tv_usec; 251 dp->ts = hton64(ts + 0x00E03AB44A676000ll); 252 if (pkt_type == HCI_COMMAND_PKT || 253 pkt_type == HCI_EVENT_PKT) 254 dp->flags |= ntohl(0x02); 255 } else { 256 dh->len = htobs(frm.data_len); 257 dh->in = frm.in; 258 dh->ts_sec = htobl(frm.ts.tv_sec); 259 dh->ts_usec = htobl(frm.ts.tv_usec); 260 } 261 262 if (write_n(fd, buf, frm.data_len + hdr_size) < 0) { 263 perror("Write error"); 264 exit(1); 265 } 266 break; 267 268 default: 269 /* Parse and print */ 270 parse(&frm); 271 break; 272 } 273 } 274} 275 276static void read_dump(int fd) 277{ 278 struct hcidump_hdr dh; 279 struct btsnoop_pkt dp; 280 struct frame frm; 281 uint8_t pkt_type; 282 int err; 283 284 frm.data = malloc(HCI_MAX_FRAME_SIZE); 285 if (!frm.data) { 286 perror("Can't allocate data buffer"); 287 exit(1); 288 } 289 290 while (1) { 291 if (parser.flags & DUMP_BTSNOOP) 292 err = read_n(fd, (void *) &dp, BTSNOOP_PKT_SIZE); 293 else 294 err = read_n(fd, (void *) &dh, HCIDUMP_HDR_SIZE); 295 296 if (err < 0) 297 goto failed; 298 if (!err) 299 return; 300 301 if (parser.flags & DUMP_BTSNOOP) { 302 switch (btsnoop_type) { 303 case 1001: 304 if (ntohl(dp.flags) & 0x02) { 305 if (ntohl(dp.flags) & 0x01) 306 pkt_type = HCI_EVENT_PKT; 307 else 308 pkt_type = HCI_COMMAND_PKT; 309 } else 310 pkt_type = HCI_ACLDATA_PKT; 311 312 ((uint8_t *) frm.data)[0] = pkt_type; 313 314 frm.data_len = ntohl(dp.len) + 1; 315 err = read_n(fd, frm.data + 1, frm.data_len - 1); 316 break; 317 318 case 1002: 319 frm.data_len = ntohl(dp.len); 320 err = read_n(fd, frm.data, frm.data_len); 321 break; 322 } 323 } else { 324 frm.data_len = btohs(dh.len); 325 err = read_n(fd, frm.data, frm.data_len); 326 } 327 328 if (err < 0) 329 goto failed; 330 if (!err) 331 return; 332 333 frm.ptr = frm.data; 334 frm.len = frm.data_len; 335 336 if (parser.flags & DUMP_BTSNOOP) { 337 uint64_t ts; 338 frm.in = ntohl(dp.flags) & 0x01; 339 ts = ntoh64(dp.ts) - 0x00E03AB44A676000ll; 340 frm.ts.tv_sec = (ts / 1000000ll) + 946684800ll; 341 frm.ts.tv_usec = ts % 1000000ll; 342 } else { 343 frm.in = dh.in; 344 frm.ts.tv_sec = btohl(dh.ts_sec); 345 frm.ts.tv_usec = btohl(dh.ts_usec); 346 } 347 348 parse(&frm); 349 } 350 351failed: 352 perror("Read failed"); 353 exit(1); 354} 355 356static int open_file(char *file, int mode, unsigned long flags) 357{ 358 struct btsnoop_hdr hdr; 359 int fd, len, open_flags; 360 361 if (mode == WRITE || mode == AUDIO) { 362 if (flags & DUMP_BTSNOOP) 363 open_flags = O_WRONLY | O_CREAT; 364 else 365 open_flags = O_WRONLY | O_CREAT | O_APPEND; 366 } else 367 open_flags = O_RDONLY; 368 369 fd = open(file, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 370 if (fd < 0) { 371 perror("Can't open dump file"); 372 exit(1); 373 } 374 375 if (mode == READ) { 376 len = read(fd, &hdr, BTSNOOP_HDR_SIZE); 377 if (len != BTSNOOP_HDR_SIZE) { 378 lseek(fd, 0, SEEK_SET); 379 return fd; 380 } 381 382 if (!memcmp(hdr.id, btsnoop_id, sizeof(btsnoop_id))) { 383 parser.flags |= DUMP_BTSNOOP; 384 385 btsnoop_version = ntohl(hdr.version); 386 btsnoop_type = ntohl(hdr.type); 387 388 printf("btsnoop version: %d datalink type: %d\n", 389 btsnoop_version, btsnoop_type); 390 391 if (btsnoop_version != 1) { 392 fprintf(stderr, "Unsupported BTSnoop version\n"); 393 exit(1); 394 } 395 396 if (btsnoop_type != 1001 && btsnoop_type != 1002) { 397 fprintf(stderr, "Unsupported BTSnoop datalink type\n"); 398 exit(1); 399 } 400 } else { 401 parser.flags &= ~DUMP_BTSNOOP; 402 lseek(fd, 0, SEEK_SET); 403 return fd; 404 } 405 } else { 406 if (flags & DUMP_BTSNOOP) { 407 btsnoop_version = 1; 408 btsnoop_type = 1002; 409 410 memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id)); 411 hdr.version = htonl(btsnoop_version); 412 hdr.type = htonl(btsnoop_type); 413 414 printf("btsnoop version: %d datalink type: %d\n", 415 btsnoop_version, btsnoop_type); 416 417 len = write(fd, &hdr, BTSNOOP_HDR_SIZE); 418 if (len < 0) { 419 perror("Can't create dump header"); 420 exit(1); 421 } 422 423 if (len != BTSNOOP_HDR_SIZE) { 424 fprintf(stderr, "Header size mismatch\n"); 425 exit(1); 426 } 427 } 428 } 429 430 return fd; 431} 432 433static int open_socket(int dev, unsigned long flags) 434{ 435 struct sockaddr_hci addr; 436 struct hci_filter flt; 437 struct hci_dev_info di; 438 int sk, dd, opt; 439 440 if (permcheck && dev != HCI_DEV_NONE) { 441 dd = hci_open_dev(dev); 442 if (dd < 0) { 443 perror("Can't open device"); 444 exit(1); 445 } 446 447 if (hci_devinfo(dev, &di) < 0) { 448 perror("Can't get device info"); 449 exit(1); 450 } 451 452 opt = hci_test_bit(HCI_RAW, &di.flags); 453 if (ioctl(dd, HCISETRAW, opt) < 0) { 454 if (errno == EACCES) { 455 perror("Can't access device"); 456 exit(1); 457 } 458 } 459 460 hci_close_dev(dd); 461 } 462 463 /* Create HCI socket */ 464 sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 465 if (sk < 0) { 466 perror("Can't create raw socket"); 467 exit(1); 468 } 469 470 opt = 1; 471 if (setsockopt(sk, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) { 472 perror("Can't enable data direction info"); 473 exit(1); 474 } 475 476 opt = 1; 477 if (setsockopt(sk, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) { 478 perror("Can't enable time stamp"); 479 exit(1); 480 } 481 482 /* Setup filter */ 483 hci_filter_clear(&flt); 484 hci_filter_all_ptypes(&flt); 485 hci_filter_all_events(&flt); 486 if (setsockopt(sk, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 487 perror("Can't set filter"); 488 exit(1); 489 } 490 491 /* Bind socket to the HCI device */ 492 addr.hci_family = AF_BLUETOOTH; 493 addr.hci_dev = dev; 494 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 495 printf("Can't attach to device hci%d. %s(%d)\n", 496 dev, strerror(errno), errno); 497 exit(1); 498 } 499 500 return sk; 501} 502 503static int open_connection(in_addr_t addr, in_port_t port) 504{ 505 struct sockaddr_in sa; 506 int sk, opt; 507 508 sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 509 if (sk < 0) { 510 perror("Can't create inet socket"); 511 exit(1); 512 } 513 514 opt = 1; 515 setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 516 517 sa.sin_family = AF_INET; 518 sa.sin_addr.s_addr = htonl(INADDR_ANY); 519 sa.sin_port = htons(0); 520 if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 521 perror("Can't bind inet socket"); 522 close(sk); 523 exit(1); 524 } 525 526 sa.sin_family = AF_INET; 527 sa.sin_addr.s_addr = htonl(addr); 528 sa.sin_port = htons(port); 529 if (connect(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 530 perror("Can't connect inet socket"); 531 close(sk); 532 exit(1); 533 } 534 535 return sk; 536} 537 538static int wait_connection(in_addr_t addr, in_port_t port) 539{ 540 struct sockaddr_in sa; 541 struct hostent *host; 542 socklen_t len; 543 int sk, nsk, opt; 544 545 sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 546 if (sk < 0) { 547 perror("Can't create inet socket"); 548 exit(1); 549 } 550 551 opt = 1; 552 setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 553 554 sa.sin_family = AF_INET; 555 sa.sin_addr.s_addr = htonl(addr); 556 sa.sin_port = htons(port); 557 if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 558 perror("Can't bind inet socket"); 559 close(sk); 560 exit(1); 561 } 562 563 host = gethostbyaddr(&sa.sin_addr, sizeof(sa.sin_addr), AF_INET); 564 printf("device: %s:%d snap_len: %d filter: 0x%lx\n", 565 host ? host->h_name : inet_ntoa(sa.sin_addr), 566 ntohs(sa.sin_port), snap_len, filter); 567 568 if (listen(sk, 1)) { 569 perror("Can't listen on inet socket"); 570 close(sk); 571 exit(1); 572 } 573 574 len = sizeof(sa); 575 nsk = accept(sk, (struct sockaddr *) &sa, &len); 576 if (nsk < 0) { 577 perror("Can't accept new inet socket"); 578 close(sk); 579 exit(1); 580 } 581 582 host = gethostbyaddr(&sa.sin_addr, sizeof(sa.sin_addr), AF_INET); 583 printf("device: %s snap_len: %d filter: 0x%lx\n", 584 host ? host->h_name : inet_ntoa(sa.sin_addr), snap_len, filter); 585 586 close(sk); 587 588 return nsk; 589} 590 591static struct { 592 char *name; 593 int flag; 594} filters[] = { 595 { "lmp", FILT_LMP }, 596 { "hci", FILT_HCI }, 597 { "sco", FILT_SCO }, 598 { "l2cap", FILT_L2CAP }, 599 { "rfcomm", FILT_RFCOMM }, 600 { "sdp", FILT_SDP }, 601 { "bnep", FILT_BNEP }, 602 { "cmtp", FILT_CMTP }, 603 { "hidp", FILT_HIDP }, 604 { "hcrp", FILT_HCRP }, 605 { "avdtp", FILT_AVDTP }, 606 { "avctp", FILT_AVCTP }, 607 { "obex", FILT_OBEX }, 608 { "capi", FILT_CAPI }, 609 { "ppp", FILT_PPP }, 610 { "csr", FILT_CSR }, 611 { "dga", FILT_DGA }, 612 { 0 } 613}; 614 615static void parse_filter(int argc, char **argv) 616{ 617 int i,n; 618 619 for (i = 0; i < argc; i++) { 620 for (n = 0; filters[n].name; n++) { 621 if (!strcasecmp(filters[n].name, argv[i])) { 622 filter |= filters[n].flag; 623 break; 624 } 625 } 626 } 627} 628 629static void usage(void) 630{ 631 printf( 632 "Usage: hcidump [OPTION...] [filter]\n" 633 " -i, --device=hci_dev HCI device\n" 634 " -l, --snap-len=len Snap len (in bytes)\n" 635 " -p, --psm=psm Default PSM\n" 636 " -m, --manufacturer=compid Default manufacturer\n" 637 " -w, --save-dump=file Save dump to a file\n" 638 " -r, --read-dump=file Read dump from a file\n" 639 " -s, --send-dump=host Send dump to a host\n" 640 " -n, --recv-dump=host Receive dump on a host\n" 641 " -t, --ts Display time stamps\n" 642 " -a, --ascii Dump data in ascii\n" 643 " -x, --hex Dump data in hex\n" 644 " -X, --ext Dump data in hex and ascii\n" 645 " -R, --raw Dump raw data\n" 646 " -C, --cmtp=psm PSM for CMTP\n" 647 " -H, --hcrp=psm PSM for HCRP\n" 648 " -O, --obex=channel Channel for OBEX\n" 649 " -P, --ppp=channel Channel for PPP\n" 650 " -A, --audio=file Extract SCO audio data\n" 651 " -B, --btsnoop Use BTSnoop file format\n" 652 " -V, --verbose Verbose decoding\n" 653 " -Y, --novendor No vendor commands or events\n" 654 " -h, --help Give this help list\n" 655 " --usage Give a short usage message\n" 656 ); 657} 658 659static struct option main_options[] = { 660 { "device", 1, 0, 'i' }, 661 { "snap-len", 1, 0, 'l' }, 662 { "psm", 1, 0, 'p' }, 663 { "manufacturer", 1, 0, 'm' }, 664 { "save-dump", 1, 0, 'w' }, 665 { "read-dump", 1, 0, 'r' }, 666 { "send-dump", 1, 0, 's' }, 667 { "recv-dump", 1, 0, 'n' }, 668 { "timestamp", 0, 0, 't' }, 669 { "ascii", 0, 0, 'a' }, 670 { "hex", 0, 0, 'x' }, 671 { "ext", 0, 0, 'X' }, 672 { "raw", 0, 0, 'R' }, 673 { "cmtp", 1, 0, 'C' }, 674 { "hcrp", 1, 0, 'H' }, 675 { "obex", 1, 0, 'O' }, 676 { "ppp", 1, 0, 'P' }, 677 { "audio", 1, 0, 'A' }, 678 { "btsnoop", 0, 0, 'B' }, 679 { "verbose", 0, 0, 'V' }, 680 { "novendor", 0, 0, 'Y' }, 681 { "nopermcheck", 0, 0, 'Z' }, 682 { "help", 0, 0, 'h' }, 683 { 0 } 684}; 685 686int main(int argc, char *argv[]) 687{ 688 struct hostent *host; 689 struct in_addr addr; 690 int opt, fd = -1; 691 692 printf("HCI sniffer - Bluetooth packet analyzer ver %s\n", VERSION); 693 694 while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:taxXRC:H:O:P:A:BVYZh", main_options, NULL)) != -1) { 695 switch(opt) { 696 case 'i': 697 if (strcasecmp(optarg, "none") && strcasecmp(optarg, "system")) 698 device = atoi(optarg + 3); 699 else 700 device = HCI_DEV_NONE; 701 break; 702 703 case 'l': 704 snap_len = atoi(optarg); 705 break; 706 707 case 'p': 708 defpsm = atoi(optarg); 709 break; 710 711 case 'm': 712 defcompid = atoi(optarg); 713 break; 714 715 case 'w': 716 mode = WRITE; 717 dump_file = strdup(optarg); 718 break; 719 720 case 'r': 721 mode = READ; 722 dump_file = strdup(optarg); 723 break; 724 725 case 's': 726 mode = SEND; 727 host = gethostbyname(optarg); 728 if (host) { 729 bcopy(host->h_addr, &addr, sizeof(struct in_addr)); 730 dump_addr = ntohl(addr.s_addr); 731 dump_port = DEFAULT_PORT; 732 } else { 733 dump_addr = INADDR_LOOPBACK; 734 dump_port = DEFAULT_PORT; 735 } 736 break; 737 738 case 'n': 739 mode = RECEIVE; 740 host = gethostbyname(optarg); 741 if (host) { 742 bcopy(host->h_addr, &addr, sizeof(struct in_addr)); 743 dump_addr = ntohl(addr.s_addr); 744 dump_port = DEFAULT_PORT; 745 } else { 746 dump_addr = INADDR_LOOPBACK; 747 dump_port = DEFAULT_PORT; 748 } 749 break; 750 751 case 't': 752 flags |= DUMP_TSTAMP; 753 break; 754 755 case 'a': 756 flags |= DUMP_ASCII; 757 break; 758 759 case 'x': 760 flags |= DUMP_HEX; 761 break; 762 763 case 'X': 764 flags |= DUMP_EXT; 765 break; 766 767 case 'R': 768 flags |= DUMP_RAW; 769 break; 770 771 case 'C': 772 set_proto(0, atoi(optarg), 0, SDP_UUID_CMTP); 773 break; 774 775 case 'H': 776 set_proto(0, atoi(optarg), 0, SDP_UUID_HARDCOPY_CONTROL_CHANNEL); 777 break; 778 779 case 'O': 780 set_proto(0, 0, atoi(optarg), SDP_UUID_OBEX); 781 break; 782 783 case 'P': 784 set_proto(0, 0, atoi(optarg), SDP_UUID_LAN_ACCESS_PPP); 785 break; 786 787 case 'A': 788 audio_file = strdup(optarg); 789 break; 790 791 case 'B': 792 flags |= DUMP_BTSNOOP; 793 break; 794 795 case 'V': 796 flags |= DUMP_VERBOSE; 797 break; 798 799 case 'Y': 800 flags |= DUMP_NOVENDOR; 801 break; 802 803 case 'Z': 804 permcheck = 0; 805 break; 806 807 case 'h': 808 default: 809 usage(); 810 exit(0); 811 } 812 } 813 814 argc -= optind; 815 argv += optind; 816 optind = 0; 817 818 if (argc > 0) 819 parse_filter(argc, argv); 820 821 /* Default settings */ 822 if (!filter) 823 filter = ~0L; 824 825 if (audio_file) 826 fd = open_file(audio_file, AUDIO, flags); 827 828 switch (mode) { 829 case PARSE: 830 init_parser(flags, filter, defpsm, defcompid, fd); 831 process_frames(device, open_socket(device, flags), -1, flags); 832 break; 833 834 case READ: 835 init_parser(flags, filter, defpsm, defcompid, fd); 836 read_dump(open_file(dump_file, mode, flags)); 837 break; 838 839 case WRITE: 840 process_frames(device, open_socket(device, flags), 841 open_file(dump_file, mode, flags), flags); 842 break; 843 844 case RECEIVE: 845 init_parser(flags, filter, defpsm, defcompid, fd); 846 read_dump(wait_connection(dump_addr, dump_port)); 847 break; 848 849 case SEND: 850 process_frames(device, open_socket(device, flags), 851 open_connection(dump_addr, dump_port), flags); 852 break; 853 } 854 855 return 0; 856} 857