diff --git a/tools/hcidump.1 b/tools/hcidump.1
index 33282ac..4f5911e 100644
--- a/tools/hcidump.1
+++ b/tools/hcidump.1
Data is not read from a Bluetooth device, but from host
.IR host .
.TP
+.BI -d " <host>" "\fR,\fP \-\^\-wait-dump=" "<host>"
+Data is read from a Bluetooth device, but then send to
+.IR host
+for processing. No data is read if no host is connected.
+.TP
.BR -t ", " "\-\^\-timestamp"
Prepend a time stamp to every packet.
.TP
diff --git a/tools/hcidump.c b/tools/hcidump.c
index 073c305..fef9357 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
WRITE,
RECEIVE,
SEND,
+ SERVER,
PPPDUMP,
AUDIO
};
/* Default options */
-static int device;
static int snap_len = SNAP_LEN;
-static int defpsm = 0;
-static int defcompid = DEFAULT_COMPID;
static int mode = PARSE;
static int permcheck = 1;
static int noappend = 0;
-static long flags;
-static long filter;
static char *dump_file = NULL;
static char *pppdump_file = NULL;
static char *audio_file = NULL;
static inline int read_n(int fd, char *buf, int len)
{
- register int t = 0, w;
+ int t = 0, w;
while (len > 0) {
if ((w = read(fd, buf, len)) < 0) {
static inline int write_n(int fd, char *buf, int len)
{
- register int t = 0, w;
+ int t = 0, w;
while (len > 0) {
if ((w = write(fd, buf, len)) < 0) {
else
printf("device: hci%d ", dev);
- printf("snap_len: %d filter: 0x%lx\n", snap_len, filter);
+ printf("snap_len: %d filter: 0x%lx\n", snap_len, parser.filter);
memset(&msg, 0, sizeof(msg));
len = recvmsg(sock, &msg, 0);
if (len < 0) {
perror("Receive failed");
- exit(1);
+ if (mode == SERVER)
+ return;
+ else
+ exit(1);
}
/* Process control message */
switch (mode) {
case WRITE:
case SEND:
+ case SERVER:
/* Save or send dump */
if (flags & DUMP_BTSNOOP) {
uint64_t ts;
if (write_n(fd, buf, frm.data_len + hdr_size) < 0) {
perror("Write error");
- exit(1);
+ if (mode == SERVER)
+ return;
+ else
+ exit(1);
}
break;
getnameinfo(res->ai_addr, res->ai_addrlen, hname, sizeof(hname),
hport, sizeof(hport), NI_NUMERICSERV);
- printf("device: %s:%s snap_len: %d filter: 0x%lx\n",
- hname, hport, snap_len, filter);
+ printf("device: %s:%s snap_len: %d filter: 0x%lx\n",
+ hname, port, snap_len, parser.filter);
if (listen(sk, 1) < 0) {
if (res->ai_next) {
close(sk);
hname, sizeof(hname), NULL, 0, 0);
printf("device: %s snap_len: %d filter: 0x%lx\n",
- hname, snap_len, filter);
+ hname, snap_len, parser.filter);
close(sk);
return nsk;
}
+static int run_server(int dev, char *addr, char *port, unsigned long flags)
+{
+ int dd, sk;
+
+ dd = open_socket(dev, flags);
+ if (dd < 0)
+ return dd;
+
+ close(dd);
+
+ flags &= ~DUMP_BTSNOOP;
+
+ while (1) {
+ sk = wait_connection(addr, port);
+ if (sk < 0)
+ continue;
+
+ dd = open_socket(dev, flags);
+ if (dd < 0) {
+ close(sk);
+ continue;
+ }
+
+ process_frames(dev, dd, sk, flags);
+
+ close(dd);
+ close(sk);
+ }
+
+ return 0;
+}
+
static struct {
char *name;
int flag;
{ 0 }
};
-static void parse_filter(int argc, char **argv)
+static unsigned long parse_filter(int argc, char **argv)
{
+ unsigned long filter = 0;
int i,n;
for (i = 0; i < argc; i++) {
}
}
}
+
+ return filter;
}
static void usage(void)
" -r, --read-dump=file Read dump from a file\n"
" -s, --send-dump=host Send dump to a host\n"
" -n, --recv-dump=host Receive dump on a host\n"
+ " -d, --wait-dump=host Wait on a host and send\n"
" -t, --ts Display time stamps\n"
" -a, --ascii Dump data in ascii\n"
" -x, --hex Dump data in hex\n"
{ "read-dump", 1, 0, 'r' },
{ "send-dump", 1, 0, 's' },
{ "recv-dump", 1, 0, 'n' },
+ { "wait-dump", 1, 0, 'd' },
{ "timestamp", 0, 0, 't' },
{ "ascii", 0, 0, 'a' },
{ "hex", 0, 0, 'x' },
int main(int argc, char *argv[])
{
+ unsigned long flags = 0;
+ unsigned long filter = 0;
+ int device = 0;
+ int defpsm = 0;
+ int defcompid = DEFAULT_COMPID;
int opt, pppdump_fd = -1, audio_fd = -1;
printf("HCI sniffer - Bluetooth packet analyzer ver %s\n", VERSION);
- while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:taxXRC:H:O:P:D:A:BVYZN46h", main_options, NULL)) != -1) {
+ while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:d:taxXRC:H:O:P:D:A:BVYZN46h", main_options, NULL)) != -1) {
switch(opt) {
case 'i':
if (strcasecmp(optarg, "none") && strcasecmp(optarg, "system"))
dump_addr = optarg;
break;
+ case 'd':
+ mode = SERVER;
+ dump_addr = optarg;
+ break;
+
case 't':
flags |= DUMP_TSTAMP;
break;
optind = 0;
if (argc > 0)
- parse_filter(argc, argv);
+ filter = parse_filter(argc, argv);
/* Default settings */
if (!filter)
process_frames(device, open_socket(device, flags),
open_connection(dump_addr, dump_port), flags);
break;
+
+ case SERVER:
+ init_parser(flags, filter, defpsm, defcompid, pppdump_fd, audio_fd);
+ run_server(device, dump_addr, dump_port, flags);
+ break;
}
return 0;