hcidump.c revision 8d58fe98fb6efd353c91dc2520e5bf46d72358ba
1/* 2 HCIDump - HCI packet analyzer 3 Copyright (C) 2000-2001 Maxim Krasnyansky <maxk@qualcomm.com> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License version 2 as 7 published by the Free Software Foundation; 8 9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, 13 OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER 14 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 16 USE OR PERFORMANCE OF THIS SOFTWARE. 17 18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, 19 TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. 20*/ 21 22/* 23 * $Id$ 24 */ 25 26#include <stdio.h> 27#include <stdlib.h> 28#include <unistd.h> 29#include <termios.h> 30#include <fcntl.h> 31#include <sys/ioctl.h> 32#include <sys/socket.h> 33#include <sys/types.h> 34#include <sys/uio.h> 35#include <errno.h> 36#include <string.h> 37 38#include <asm/types.h> 39 40#include <bluetooth/bluetooth.h> 41#include <bluetooth/hci.h> 42#include <bluetooth/l2cap.h> 43 44#include "parser.h" 45#include "hcidump.h" 46 47/* Default options */ 48int snap_len = SNAP_LEN; 49int mode = DUMP; 50 51void usage(void) 52{ 53 printf("HCIDump - HCI packet analyzer ver %s\n", VERSION); 54 printf("Usage:\n"); 55 printf("\thcidump <-i hciX> [-ah]\n"); 56} 57 58void process_frames(int dev, int sock, int file) 59{ 60 char *data, *ctrl, *frame; 61 struct cmsghdr *cmsg; 62 struct msghdr msg; 63 struct iovec iv; 64 struct dump_hdr *dh; 65 int len, in; 66 67 if (snap_len < SNAP_LEN) 68 snap_len = SNAP_LEN; 69 70 if (!(data = malloc(snap_len + DUMP_HDR_SIZE))) { 71 perror("Can't allocate data buffer"); 72 exit(1); 73 } 74 dh = (void *) data; 75 frame = data + DUMP_HDR_SIZE; 76 77 if (!(ctrl = malloc(100))) { 78 perror("Can't allocate control buffer"); 79 exit(1); 80 } 81 82 printf("device: hci%d snap_len: %d filter: none\n", dev, snap_len); 83 84 while (1) { 85 iv.iov_base = frame; 86 iv.iov_len = snap_len; 87 88 msg.msg_iov = &iv; 89 msg.msg_iovlen = 1; 90 msg.msg_control = ctrl; 91 msg.msg_controllen = 100; 92 93 if ((len = recvmsg(sock, &msg, 0)) < 0) { 94 perror("Receive failed"); 95 exit(1); 96 } 97 98 /* Process control message */ 99 in = 0; 100 cmsg = CMSG_FIRSTHDR(&msg); 101 while (cmsg) { 102 switch (cmsg->cmsg_type) { 103 case HCI_CMSG_DIR: 104 in = *((int *)CMSG_DATA(cmsg)); 105 break; 106 } 107 cmsg = CMSG_NXTHDR(&msg, cmsg); 108 } 109 110 if (file == -1) { 111 /* Parse and print */ 112 parse(in, frame, len); 113 } else { 114 /* Save dump */ 115 dh->len = __cpu_to_le16(len); 116 dh->in = in; 117 if (write_n(file, data, len + DUMP_HDR_SIZE) < 0) { 118 perror("Write error"); 119 exit(1); 120 } 121 } 122 } 123} 124 125void read_dump(int file) 126{ 127 struct dump_hdr dh; 128 char *data; 129 int err; 130 131 if (!(data = malloc(HCI_MAX_FRAME_SIZE))) { 132 perror("Can't allocate data buffer"); 133 exit(1); 134 } 135 136 while (1) { 137 int len; 138 139 if ((err = read_n(file, (void *) &dh, DUMP_HDR_SIZE)) < 0) 140 goto failed; 141 if (!err) return; 142 143 len = __le16_to_cpu(dh.len); 144 145 if ((err = read_n(file, data, len)) < 0) 146 goto failed; 147 if (!err) return; 148 149 parse(dh.in, data, len); 150 } 151 152failed: 153 perror("Read failed"); 154 exit(1); 155} 156 157int open_file(char *file, int mode) 158{ 159 int f, flags; 160 161 if (mode == WRITE) 162 flags = O_WRONLY | O_CREAT | O_APPEND; 163 else 164 flags = O_RDONLY; 165 166 if ((f = open(file, flags)) < 0) { 167 perror("Can't open output file"); 168 exit(1); 169 } 170 return f; 171} 172 173int open_socket(int dev) 174{ 175 struct sockaddr_hci addr; 176 struct hci_filter flt; 177 int s, opt; 178 179 /* Create HCI socket */ 180 if ((s=socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) { 181 perror("Can't create HCI socket"); 182 exit(1); 183 } 184 185 opt = 1; 186 if (setsockopt(s, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) { 187 perror("Can't enable data direction info"); 188 exit(1); 189 } 190 191 /* Setup filter */ 192 flt.type_mask = ~0; // All packet types 193 flt.event_mask[0] = ~0L; // All events 194 flt.event_mask[1] = ~0L; 195 if (setsockopt(s, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 196 perror("Can't set HCI filter"); 197 exit(1); 198 } 199 200 /* Bind socket to the HCI device */ 201 addr.hci_family = AF_BLUETOOTH; 202 addr.hci_dev = dev; 203 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 204 printf("Can't attach to device hci%d. %s(%d)\n", 205 dev, strerror(errno), errno); 206 exit(1); 207 } 208 return s; 209} 210 211int main(int argc, char *argv[]) 212{ 213 extern int optind, opterr, optopt; 214 extern char *optarg; 215 int dev, opt; 216 long flags; 217 char *file = NULL; 218 219 dev = 0; 220 flags = 0; 221 222 while ((opt=getopt(argc, argv,"i:s:haw:r:")) != EOF) { 223 switch(opt) { 224 case 'i': 225 dev = atoi(optarg+3); 226 break; 227 228 case 'h': 229 flags |= DUMP_HEX; 230 break; 231 232 case 'a': 233 flags |= DUMP_ASCII; 234 break; 235 236 case 's': 237 snap_len = atoi(optarg); 238 break; 239 240 case 'w': 241 mode = WRITE; 242 file = strdup(optarg); 243 break; 244 245 case 'r': 246 mode = READ; 247 file = strdup(optarg); 248 break; 249 250 default: 251 usage(); 252 exit(1); 253 } 254 } 255 256 printf("HCIDump - HCI packet analyzer ver %s.\n", VERSION); 257 258 switch (mode) { 259 case DUMP: 260 init_parser(flags); 261 process_frames(dev, open_socket(dev), -1); 262 break; 263 264 case WRITE: 265 process_frames(dev, open_socket(dev), open_file(file, mode)); 266 break; 267 268 case READ: 269 init_parser(flags); 270 read_dump(open_file(file, mode)); 271 break; 272 } 273 return 0; 274} 275