source: lib/format_wag.c @ 5bb5dd2

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5bb5dd2 was 5bb5dd2, checked in by Shane Alcock <salcock@…>, 15 years ago

Fixed wag_get_capture_length to use the payload length field of the wag header, rather than using the total frame size and subtracting what we assumed to be the header size.
Fixed bug in dag_read_packet where rxerrors would cause the payload to be null but the packet's size would still include the (theoretical) payload size

  • Property mode set to 100644
File size: 16.2 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2004 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31#define _GNU_SOURCE
32#include "config.h"
33#include "common.h"
34#include "libtrace.h"
35#include "libtrace_int.h"
36#include "format_helper.h"
37#include "wag.h"
38
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <assert.h>
42#include <errno.h>
43#include <stdio.h>
44#include <string.h>
45#include <stdlib.h>
46
47#ifdef HAVE_LIMITS_H
48#  include <limits.h>
49#endif
50
51#ifdef HAVE_SYS_LIMITS_H
52#  include <sys/limits.h>
53#endif
54
55#ifdef WIN32
56#  include <io.h>
57#  include <share.h>
58#endif
59
60static struct libtrace_format_t wag;
61static struct libtrace_format_t wag_trace;
62
63#define DATA(x)         ((struct wag_format_data_t *)x->format_data)
64#define DATAOUT(x)      ((struct wag_format_data_out_t *)x->format_data)
65
66#define INPUT DATA(libtrace)->input
67#define OUTPUT DATAOUT(libtrace)->output
68#define OPTIONS DATAOUT(libtrace)->options
69
70struct wag_format_data_t {
71        /** Information about the current state of the input device */
72        union {
73                int fd;
74                libtrace_io_t *file;
75        } input;       
76};
77
78struct wag_format_data_out_t {
79        union {
80                struct {
81                        int level;
82                        int filemode;
83                } zlib;
84        } options;
85        union {
86                int fd;
87                libtrace_io_t *file;
88        } output;
89};
90
91static int wag_init_input(libtrace_t *libtrace) {
92        libtrace->format_data = calloc(1, sizeof(struct wag_format_data_t));
93
94        return 0;
95}
96
97static int wag_start_input(libtrace_t *libtrace)
98{
99        struct stat buf;
100        if (stat(libtrace->uridata,&buf) == -1 ) {
101                trace_set_err(libtrace,errno,"stat(%s)",libtrace->uridata);
102                return -1;
103        }
104#ifndef WIN32
105        if (S_ISCHR(buf.st_mode)) {
106                INPUT.fd = open(libtrace->uridata, O_RDONLY);
107                if (ioctl (INPUT.fd, CAPTURE_RADIOON, 0) == -1) {
108                        trace_set_err(libtrace, errno,
109                                "Could not turn WAG radio on");
110                        return -1;
111                }
112                return 0;
113        }
114#endif
115        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
116                        "%s is not a valid char device",
117                        libtrace->uridata);
118        return -1;
119}
120
121static int wtf_init_input(libtrace_t *libtrace) 
122{
123        libtrace->format_data = calloc(1,sizeof(struct wag_format_data_t));
124        return 0;
125}
126
127static int wtf_start_input(libtrace_t *libtrace)
128{
129        if (DATA(libtrace)->input.file)
130                return 0; /* success */
131        DATA(libtrace)->input.file = trace_open_file(libtrace);
132
133        if (!DATA(libtrace)->input.file)
134                return -1; 
135
136        return 0; /* success */
137}
138
139static int wtf_init_output(libtrace_out_t *libtrace) {
140        libtrace->format_data = malloc(sizeof(struct wag_format_data_out_t));
141
142        OUTPUT.file = 0;
143        OPTIONS.zlib.level = 0;
144        OPTIONS.zlib.filemode = O_CREAT | O_WRONLY;
145       
146        return 0;
147}
148
149static int wtf_start_output(libtrace_out_t *libtrace) {
150        OUTPUT.file = trace_open_file_out(libtrace,
151                        OPTIONS.zlib.level,
152                        OPTIONS.zlib.filemode);
153        if (!OUTPUT.file) {
154                return -1;
155        }
156        return 0;
157}
158
159static int wtf_config_output(libtrace_out_t *libtrace, 
160                trace_option_output_t option,
161                void *value) {
162        switch(option) {
163#ifdef HAVE_LIBZ
164                case TRACE_OPTION_OUTPUT_COMPRESS:
165                        OPTIONS.zlib.level = *(int*)value;
166                        assert(OPTIONS.zlib.level>=0 
167                                        && OPTIONS.zlib.level<=9);
168                        return 0;
169#else
170                case TRACE_OPTION_OUTPUT_COMPRESS:
171                        /* E feature unavailable */
172                        trace_set_err_out(libtrace,TRACE_ERR_OPTION_UNAVAIL,
173                                        "zlib not supported");
174                        return -1;
175#endif
176                default:
177                        /* E unknown feature */
178                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
179                                        "Unknown option");
180                        return -1;
181        }
182}
183
184static int wag_pause_input(libtrace_t *libtrace)
185{
186        if (ioctl (INPUT.fd, CAPTURE_RADIOON, 0) == -1) {
187                trace_set_err(libtrace, errno,
188                                "Could not turn WAG radio off");
189        }
190        close(INPUT.fd);
191        return 0;
192}
193
194static int wag_fin_input(libtrace_t *libtrace) {
195        ioctl (INPUT.fd, CAPTURE_RADIOON, 0);
196        free(libtrace->format_data);
197        return 0;
198}
199
200static int wtf_fin_input(libtrace_t *libtrace) {
201        libtrace_io_close(INPUT.file);
202        free(libtrace->format_data);
203        return 0;
204}
205
206static int wtf_fin_output(libtrace_out_t *libtrace) {
207        libtrace_io_close(OUTPUT.file);
208        free(libtrace->format_data);
209        return 0;
210}
211
212static int wag_read(libtrace_t *libtrace, void *buffer, size_t len, 
213                int block) {
214        size_t framesize;
215        char *buf_ptr = (char *)buffer;
216        int to_read = 0;
217        uint16_t magic = 0;
218        long fd_flags;
219       
220        assert(libtrace);
221
222        to_read = sizeof(struct frame_t);
223
224#ifndef WIN32
225        fd_flags = fcntl(INPUT.fd, F_GETFL);
226        if (fd_flags == -1) {
227                /* TODO: Replace with better libtrace-style
228                 * error handling later */
229                perror("Could not get fd flags");
230                return 0;
231        }
232       
233       
234       
235        if (!block) {
236                if (fcntl(INPUT.fd, F_SETFL, fd_flags | O_NONBLOCK) == -1) {
237                        perror("Could not set fd flags");
238                        return 0;
239                }
240        }
241        else {
242                if (fd_flags & O_NONBLOCK) {
243                        fd_flags &= ~O_NONBLOCK;
244                        if (fcntl(INPUT.fd, F_SETFL, fd_flags) == -1) {
245                                perror("Could not set fd flags");
246                                return 0;
247                        }
248                }
249        }
250#endif
251
252        /* I'm not sure if wag has a memory hole which we can use for
253         * zero-copy - something to add in later, I guess */
254       
255        while (to_read>0) {
256                int ret=read(INPUT.fd,buf_ptr,to_read);
257
258                if (ret == -1) {
259                        if (errno == EINTR)
260                                continue;
261                       
262                        if (errno == EAGAIN) {
263                                trace_set_err(libtrace, EAGAIN, "EAGAIN");
264                                return -1;
265                        }
266           
267                        trace_set_err(libtrace,errno,
268                                        "read(%s)",libtrace->uridata);
269                        return -1;
270                }
271
272                assert(ret>0);
273
274                to_read = to_read - ret;
275                buf_ptr = buf_ptr + ret;
276        }
277
278
279        framesize = ntohs(((struct frame_t *)buffer)->size);
280        magic = ntohs(((struct frame_t *)buffer)->magic);
281
282        if (magic != 0xdaa1) {
283          trace_set_err(libtrace,
284                          TRACE_ERR_BAD_PACKET,"magic number bad or missing");
285          return -1;
286        }
287
288        /* We should deal.  this is called "snapping", but we don't yet */
289        assert(framesize<=len);
290
291        buf_ptr = (void*)((char*)buffer + sizeof (struct frame_t));
292        to_read = framesize - sizeof(struct frame_t);
293       
294        while (to_read>0) {
295                int ret=read(INPUT.fd,buf_ptr,to_read);
296
297                if (ret == -1) {
298                        if (errno == EINTR) 
299                                continue;
300                        if (errno == EAGAIN) {
301                                /* What happens to the frame header?! */
302                                trace_set_err(libtrace, EAGAIN, "EAGAIN");
303                                return -1;
304                        }
305                        trace_set_err(libtrace,errno,"read(%s)",
306                                        libtrace->uridata);
307                        return -1;
308                }
309
310                to_read = to_read - ret;
311                buf_ptr = buf_ptr + ret;
312        }
313        return framesize;
314}
315
316
317static int wag_read_packet_versatile(libtrace_t *libtrace, libtrace_packet_t *packet, int block_flag) {
318        int numbytes;
319       
320        if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) {
321                packet->buf_control = TRACE_CTRL_PACKET;
322                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
323        }
324       
325       
326        packet->trace = libtrace;
327        packet->type = RT_DATA_WAG;
328       
329        if ((numbytes = wag_read(libtrace, (void *)packet->buffer, 
330                                        RP_BUFSIZE, block_flag)) <= 0) {
331           
332                return numbytes;
333        }
334
335       
336        packet->header = packet->buffer;
337        packet->payload=(char*)packet->buffer+trace_get_framing_length(packet);
338        packet->size = trace_get_framing_length(packet) + trace_get_capture_length(packet);
339        return numbytes;
340}
341
342static int wag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
343        return wag_read_packet_versatile(libtrace, packet, 1);
344}
345
346static int wtf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
347        int numbytes;
348        void *buffer;
349        void *buffer2;
350        int framesize;
351        int size;
352
353        if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) {
354                packet->buf_control = TRACE_CTRL_PACKET;
355                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
356        }
357        packet->type = RT_DATA_WAG;
358        buffer2 = buffer = packet->buffer;
359
360        numbytes = libtrace_io_read(INPUT.file, buffer, sizeof(struct frame_t));
361
362        if (numbytes == 0) {
363                return 0;
364        }
365
366        if (numbytes != sizeof(struct frame_t)) {
367                int err=errno;
368                trace_set_err(libtrace,err,
369                                "read(%s,frame_t)",packet->trace->uridata);
370                printf("failed to read header=%i\n",err);
371                return -1;
372        }
373
374        if (htons(((struct frame_t *)buffer)->magic) != 0xdaa1) {
375                trace_set_err(libtrace,
376                                TRACE_ERR_BAD_PACKET,"Insufficient magic (%04x)",htons(((struct frame_t *)buffer)->magic));
377                return -1;
378        }
379
380        framesize = ntohs(((struct frame_t *)buffer)->size);
381        buffer2 = (char*)buffer + sizeof(struct frame_t);
382        size = framesize - sizeof(struct frame_t);
383        assert(size < LIBTRACE_PACKET_BUFSIZE);
384        assert(size > 0);
385       
386        if ((numbytes=libtrace_io_read(INPUT.file, buffer2, size)) != size) {
387                trace_set_err(libtrace,
388                                errno,"read(%s,buffer)",packet->trace->uridata);
389                return -1;
390        }
391
392        packet->header = packet->buffer;
393        packet->payload=(char*)packet->buffer+trace_get_framing_length(packet);
394        return framesize;
395       
396}                               
397       
398static int wtf_write_packet(libtrace_out_t *libtrace, const libtrace_packet_t *packet) {
399        int numbytes =0 ;
400        if (packet->trace->format != &wag_trace) {
401                trace_set_err_out(libtrace,TRACE_ERR_NO_CONVERSION,
402                                "Cannot convert to wag trace format from %s format yet",
403                                packet->trace->format->name);
404                return -1;
405        }
406
407        /* We could just read from packet->buffer, but I feel it is more
408         * technically correct to read from the header and payload pointers
409         */
410        if ((numbytes = libtrace_io_write(OUTPUT.file, packet->header, 
411                                trace_get_framing_length(packet))) == -1) {
412                trace_set_err_out(libtrace,errno,
413                                "write(%s)",packet->trace->uridata);
414                return -1;
415        }
416        if ((numbytes = libtrace_io_write(OUTPUT.file, packet->payload, 
417                                trace_get_capture_length(packet)) == -1)) {
418                trace_set_err_out(libtrace,
419                                errno,"write(%s)",packet->trace->uridata);
420                return -1;
421        }
422        return numbytes;
423}
424
425static libtrace_linktype_t wag_get_link_type(const libtrace_packet_t *packet UNUSED) {
426        return TRACE_TYPE_80211;
427}
428
429static libtrace_direction_t wag_get_direction(const libtrace_packet_t *packet) {
430        struct frame_data_rx_t *wagptr = (struct frame_data_rx_t *)packet->buffer;
431        if (wagptr->hdr.type == 0) {
432                return wagptr->hdr.subtype; 
433        }
434        return -1;
435}
436
437static uint64_t wag_get_erf_timestamp(const libtrace_packet_t *packet) {
438        struct frame_data_rx_t *wagptr = (struct frame_data_rx_t *)packet->buffer;
439        uint64_t timestamp = 0;
440        timestamp = ((uint64_t)(ntohl(wagptr->ts.secs)) << 32) | (uint64_t)(ntohl(wagptr->ts.subsecs));
441        return timestamp;
442}
443
444static int wag_get_capture_length(const libtrace_packet_t *packet) {
445       
446        struct frame_t * wag_frame_data = (struct frame_t *)packet->header;
447
448       
449        if (wag_frame_data->subtype == FRAME_SUBTYPE_DATA_RX) {
450                struct frame_data_rx_t *wag_hdr = 
451                        (struct frame_data_rx_t *)packet->header;
452                return ntohs(wag_hdr->rxinfo.length);
453        }
454
455        if (wag_frame_data->subtype == FRAME_SUBTYPE_DATA_TX) {
456                struct frame_data_tx_t *wag_hdr =
457                       (struct frame_data_tx_t *)packet->header;
458                return ntohs(wag_hdr->txinfo.length);
459        }
460       
461        /* default option - not optimal as there tends to be an
462         * extra 2 bytes floating around somewhere */
463        return ntohs(((struct frame_t *)packet->header)->size)
464                -sizeof(struct frame_data_rx_t);
465}
466
467static int wag_get_wire_length(const libtrace_packet_t *packet) {
468        return ntohs(((struct frame_t *)packet->header)->size)
469                -sizeof(struct frame_data_rx_t);
470}
471
472static int wag_get_framing_length(UNUSED const libtrace_packet_t *packet) {
473        return sizeof(struct frame_data_rx_t);
474}
475
476static int wag_get_fd(const libtrace_t *trace) {
477        return DATA(trace)->input.fd;
478}
479
480struct libtrace_eventobj_t trace_event_wag(libtrace_t *trace, libtrace_packet_t *packet) {
481        struct libtrace_eventobj_t event = {0,0,0.0,0};
482        libtrace_err_t read_err;
483
484        assert(trace);
485        assert(packet);
486
487        /* We could probably just call get_fd here */
488        if (trace->format->get_fd) {
489                event.fd = trace->format->get_fd(trace);
490        } else {
491                event.fd = 0;
492        }
493       
494        event.size = wag_read_packet_versatile(trace, packet, 0);
495        if (event.size == -1) {
496                read_err = trace_get_err(trace);
497                if (read_err.err_num == EAGAIN) {
498                        event.type = TRACE_EVENT_IOWAIT;
499                }
500                else {
501                        printf("Packet error\n");
502                        event.type = TRACE_EVENT_PACKET;
503                }
504        } else if (event.size == 0) {
505                event.type = TRACE_EVENT_TERMINATE;
506        } else {
507                event.type = TRACE_EVENT_PACKET;
508        }
509
510        return event;
511}
512       
513static void wag_help() {
514        printf("wag format module: $Revision$\n");
515        printf("Supported input URIs:\n");
516        printf("\twag:/dev/wagn\n");
517        printf("\n");
518        printf("\te.g.: wag:/dev/wag0\n");
519        printf("\n");
520        printf("Supported output URIs:\n");
521        printf("\tNone\n");
522        printf("\n");
523}
524
525static void wtf_help() {
526        printf("wag trace format module: $Revision$\n");
527        printf("Supported input URIs:\n");
528        printf("\twtf:/path/to/trace.wag\n");
529        printf("\twtf:/path/to/trace.wag.gz\n");
530        printf("\n");
531        printf("\te.g.: wtf:/tmp/trace.wag.gz\n");
532        printf("\n");
533        printf("Supported output URIs:\n");
534        printf("\twtf:/path/to/trace.wag\n");
535        printf("\twtf:/path/to/trace.wag.gz\n");
536        printf("\n");
537        printf("\te.g.: wtf:/tmp/trace.wag.gz\n");
538        printf("\n");
539}
540
541static struct libtrace_format_t wag = {
542        "wag",
543        "$Id$",
544        TRACE_FORMAT_WAG,
545        wag_init_input,                 /* init_input */       
546        NULL,                           /* config_input */
547        wag_start_input,                /* start_input */
548        wag_pause_input,                /* pause_input */
549        NULL,                           /* init_output */
550        NULL,                           /* config_output */
551        NULL,                           /* start_output */
552        wag_fin_input,                  /* fin_input */
553        NULL,                           /* fin_output */
554        wag_read_packet,                /* read_packet */
555        NULL,                           /* fin_packet */
556        NULL,                           /* write_packet */
557        wag_get_link_type,              /* get_link_type */
558        wag_get_direction,              /* get_direction */
559        NULL,                           /* set_direction */
560        wag_get_erf_timestamp,          /* get_erf_timestamp */
561        NULL,                           /* get_timeval */
562        NULL,                           /* get_seconds */
563        NULL,                           /* seek_erf */
564        NULL,                           /* seek_timeval */
565        NULL,                           /* seek_seconds */
566        wag_get_capture_length,         /* get_capture_length */
567        wag_get_wire_length,            /* get_wire_length */
568        wag_get_framing_length,         /* get_framing_length */
569        NULL,                           /* set_capture_length */
570        wag_get_fd,                     /* get_fd */
571        trace_event_wag,                /* trace_event */
572        wag_help,                       /* help */
573        NULL                            /* next pointer */
574};
575
576/* wtf stands for Wag Trace Format */
577
578static struct libtrace_format_t wag_trace = {
579        "wtf",
580        "$Id$",
581        TRACE_FORMAT_WAG,
582        wtf_init_input,                 /* init_input */
583        NULL,                           /* config input */
584        wtf_start_input,                /* start input */
585        NULL,                           /* pause_input */
586        wtf_init_output,                /* init_output */
587        wtf_config_output,              /* config_output */
588        wtf_start_output,               /* start output */
589        wtf_fin_input,                  /* fin_input */
590        wtf_fin_output,                 /* fin_output */
591        wtf_read_packet,                /* read_packet */
592        NULL,                           /* fin_packet */
593        wtf_write_packet,               /* write_packet */
594        wag_get_link_type,              /* get_link_type */
595        wag_get_direction,              /* get_direction */
596        NULL,                           /* set_direction */
597        wag_get_erf_timestamp,          /* get_erf_timestamp */
598        NULL,                           /* get_timeval */
599        NULL,                           /* get_seconds */
600        NULL,                           /* seek_erf */
601        NULL,                           /* seek_timeval */
602        NULL,                           /* seek_seconds */
603        wag_get_capture_length,         /* get_capture_length */
604        wag_get_wire_length,            /* get_wire_length */
605        wag_get_framing_length,         /* get_framing_length */
606        NULL,                           /* set_capture_length */
607        NULL,                           /* get_fd */
608        trace_event_trace,              /* trace_event */
609        wtf_help,                       /* help */
610        NULL                            /* next pointer */
611};
612
613
614void CONSTRUCTOR wag_constructor() {
615        register_format(&wag);
616        register_format(&wag_trace);
617}
Note: See TracBrowser for help on using the repository browser.