1 /*******************************************************************
2 Copyright (C) 2009 FreakLabs
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. Neither the name of the the copyright holder nor the names of its contributors
15 may be used to endorse or promote products derived from this software
16 without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 Originally written by Christopher Wang aka Akiba.
31 Please post support questions to the FreakLabs forum.
33 *******************************************************************/
35 FreakLabs Freakduino/Wireshark Bridge
37 This program allows data from the Freakduino to be piped into wireshark.
38 When the sniffer firmware is loaded into the Freakduino, then the Freakduino
39 will be in promiscuous mode and will just dump any frames it sees. This
40 program takes the frame dump and sends it into Wireshark for analysis. The
41 global header is already set up to inform wireshark that the link layer for
42 all frames will be in IEEE 802.15.4 format. After that, it is up to the user
43 to choose any higher layer protocols to decode above 802.15.4 via the
44 wireshark "enable protocols" menu.
46 /**************************************************************************/
55 #include <sys/types.h>
60 #define PORTBUFSIZE 32
64 #define PIPENAME "/tmp/wireshark"
65 #define BAUDRATE B115200
73 static int FD_pipe
= -1;
74 static int FD_com
= -1;
75 static uint8_t port_buf
[PORTBUFSIZE
];
76 static uint8_t circ_buf
[BUFSIZE
];
77 static uint16_t rd_idx
= 0;
78 static uint16_t wr_idx
= 0;
80 static uint8_t state
= START_CAPTURE
;
81 static uint8_t file_write
= 0;
83 /**************************************************************************/
85 Open the serial port that we'll be communicating with the Freakduino (sniffer)
88 /**************************************************************************/
89 static int serial_open(char *portname
)
91 int FD_com
; // file descriptor for the serial port
94 FD_com
= open(portname
, O_RDONLY
| O_NOCTTY
| O_NDELAY
);
96 if(FD_com
== -1) // if open is unsucessful
98 printf("serial_open: Unable to open %s.\n", portname
);
103 cfsetspeed(&term
, BAUDRATE
);
105 // set to 8-bits, no parity, 1 stop bit
106 term
.c_cflag
&= ~PARENB
;
107 term
.c_cflag
&= ~CSTOPB
;
108 term
.c_cflag
&= ~CSIZE
;
111 term
.c_cflag
|= (CLOCAL
| CREAD
);
112 tcsetattr(FD_com
, TCSANOW
, &term
);
117 /**************************************************************************/
119 Create the named pipe that we will be communicating with wireshark through.
121 /**************************************************************************/
122 static void named_pipe_create(char *name
)
125 rv
= mkfifo(name
, 0666);
126 if ((rv
== -1) && (errno
!= EEXIST
))
128 perror("Error creating named pipe");
132 FD_pipe
= open(name
, O_WRONLY
);
136 perror("Error connecting to named pipe");
141 /**************************************************************************/
143 Write data to the pipe
145 /**************************************************************************/
146 size_t data_write(const void *ptr
, size_t size
)
151 bytes
= write(FD_pipe
, ptr
, size
);
155 /**************************************************************************/
157 Write the global header to wireshark. This is only done once at the
158 beginning of the capture.
160 /**************************************************************************/
161 static void write_global_hdr()
163 uint32_t magic_number
= 0xa1b2c3d4; /* magic number */
164 uint16_t version_major
= 2; /* major version number */
165 uint16_t version_minor
= 4; /* minor version number */
166 int32_t thiszone
= 0; /* GMT to local correction */
167 uint32_t sigfigs
= 0; /* accuracy of timestamps */
168 uint32_t snaplen
= 65535; /* max length of captured packets, in octets */
169 uint32_t network
= 195; /* data link type (DLT) - IEEE 802.15.4 */
171 data_write(&magic_number
, sizeof(magic_number
));
172 data_write(&version_major
, sizeof(version_major
));
173 data_write(&version_minor
, sizeof(version_minor
));
174 data_write(&thiszone
, sizeof(thiszone
));
175 data_write(&sigfigs
, sizeof(sigfigs
));
176 data_write(&snaplen
, sizeof(snaplen
));
177 data_write(&network
, sizeof(network
));
180 /**************************************************************************/
182 Write the frame header into wireshark. This is required for the libpcap
183 format and informs wireshark that a new frame is coming.
185 /**************************************************************************/
186 static void write_frame_hdr(uint8_t len
)
188 uint32_t ts_sec
; /* timestamp seconds */
189 uint32_t ts_usec
; /* timestamp microseconds */
190 uint32_t incl_len
; /* number of octets of packet saved in file */
191 uint32_t orig_len
; /* actual length of packet */
194 gettimeofday(&tv
, NULL
);
196 ts_usec
= tv
.tv_usec
;
198 orig_len
= len
+ PACKET_FCS
;
200 data_write(&ts_sec
, sizeof(ts_sec
));
201 data_write(&ts_usec
, sizeof(ts_usec
));
202 data_write(&incl_len
, sizeof(incl_len
));
203 data_write(&orig_len
, sizeof(orig_len
));
206 /**************************************************************************/
208 Write one frame into wireshark (via the pipe).
210 /**************************************************************************/
211 static void write_frame(uint8_t frame_len
)
215 // actual frame length for wireshark should not include FCS
216 frame_len
-= PACKET_FCS
;
218 // write header to inform WS that new frame has arrived
219 write_frame_hdr(frame_len
);
221 // bump rd_idx. we don't want to write the length byte
222 rd_idx
= (rd_idx
+ 1) % BUFSIZE
;
224 // write frame into wireshark
225 for (i
=0; i
<frame_len
; i
++)
227 data_write(&circ_buf
[rd_idx
], 1);
228 rd_idx
= (rd_idx
+ 1) % BUFSIZE
;
231 // bump rd_idx. we're not using the trailing FCS value
232 rd_idx
= (rd_idx
+ 1) % BUFSIZE
;
235 /**************************************************************************/
237 Calculate total number of bytes in buffer.
239 /**************************************************************************/
240 static uint16_t calc_bytes_in_buf()
244 // read index is greater than write. we must have wrapped around
245 return (BUFSIZE
- (rd_idx
- wr_idx
));
249 return (wr_idx
- rd_idx
);
253 /**************************************************************************/
255 Deal with any received signals. This includes ctrl-C to stop the program.
257 /**************************************************************************/
258 static void sig_int(int signo
)
263 printf("\nClosing pipe.\n");
269 printf("\nClosing serial port.\n");
273 printf("\nSignal captured and devices shut down.\n");
278 /**************************************************************************/
280 Init the signals we'll be checking for.
282 /**************************************************************************/
283 static void signal_init(void)
285 signal(SIGINT
, sig_int
);
286 signal(SIGHUP
, sig_int
);
287 signal(SIGTERM
, sig_int
);
290 /**************************************************************************/
292 Here's the meat of the code.
294 /**************************************************************************/
295 int main(int argc
, char *argv
[])
300 // capture any signals that will terminate program
303 // make sure the COM port is specified
307 if ((FD_com
= serial_open(argv
[1])) == -1)
309 printf("Serial port not opened.\n");
314 printf("Serial port connected. Waiting for wireshark connection.\n");
315 printf("Open wireshark and connect to local interface: %s\n", PIPENAME
);
320 printf("Usage: wsbridge <portname>.\n");
325 // create and open pipe for wireshark
326 named_pipe_create(PIPENAME
);
328 // wait for wireshark to connect to pipe. Once wireshark
329 // connects, then the global header will be written to it.
333 printf("Client connected to pipe.\n");
338 uint16_t bytes_in_buf
;
339 uint8_t frame_len
, byte_ctr
;
341 // wait for data to come in on the serial port
342 if ((nbytes
= read(FD_com
, port_buf
, PORTBUFSIZE
)) > 0)
344 // write data to circular buffer. loop through all received bytes
345 for (i
=0; i
<nbytes
; i
++)
350 // new frame starting
354 printf("Len = %02X.\n", len
);
356 circ_buf
[wr_idx
] = len
;
357 wr_idx
= (wr_idx
+ 1) % BUFSIZE
;
358 state
= PACKET_CAPTURE
;
363 // continue capturing bytes until end of frame
365 // write data to circular buffer and increment index
366 circ_buf
[wr_idx
] = port_buf
[i
];
368 printf("%02X ", circ_buf
[wr_idx
]);
370 wr_idx
= (wr_idx
+ 1) % BUFSIZE
;
372 // track number of received bytes. when received bytes
373 // equals frame length, then restart state machine and
374 // write bytes to wireshark
376 if (byte_ctr
== (len
- 1))
378 state
= START_CAPTURE
;
387 // at least one frame has been written. loop through circular buffer
388 // and write out all completed frames
391 // capture frame length and check buffer to see if one or more frames
393 frame_len
= circ_buf
[rd_idx
];
394 bytes_in_buf
= calc_bytes_in_buf();
396 if (bytes_in_buf
> frame_len
)
398 // if more than one frame is available, then write one frame to
399 // wireshark and then see if any more are available.
400 write_frame(frame_len
);
402 else if (bytes_in_buf
== frame_len
)
404 // only one frame is available. write to wireshark and then quit
406 write_frame(frame_len
);
411 // less than one frame is available. quit the loop and collect more
412 // bytes. we normally should not get here.
This page took 0.071173 seconds and 5 git commands to generate.