source: lib/format_wag.c @ 17ffb8a

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 17ffb8a was 17ffb8a, checked in by Perry Lorier <perry@…>, 16 years ago
  • Fixed packed vs packed issues
  • Fixed wrong prototype for format_wag
  • Property mode set to 100644
File size: 10.9 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 "libtrace.h"
33#include "libtrace_int.h"
34#include "format_helper.h"
35#include "wag.h"
36#include "config.h"
37
38#ifdef HAVE_INTTYPES_H
39#  include <inttypes.h>
40#else
41#  error "Can't find inttypes.h - this needs to be fixed"
42#endif
43
44#ifdef HAVE_STDDEF_H
45#  include <stddef.h>
46#else
47# error "Can't find stddef.h - do you define ptrdiff_t elsewhere?"
48#endif
49#include <sys/types.h>
50#include <sys/time.h>
51#include <time.h>
52#include <sys/socket.h>
53#include <sys/un.h>
54#include <sys/mman.h>
55#include <sys/stat.h>
56#include <fcntl.h>
57#include <unistd.h>
58#include <assert.h>
59#include <errno.h>
60#include <netdb.h>
61#include <stdio.h>
62#include <string.h>
63#include <stdlib.h>
64
65#if HAVE_ZLIB
66#  include <zlib.h>
67#  define LIBTRACE_READ gzread
68#  define LIBTRACE_FDOPEN gzdopen
69#  define LIBTRACE_CLOSE gzclose
70#  define LIBTRACE_WRITE gzwrite
71#else
72#  define LIBTRACE_READ read
73#  define LIBTRACE_FDOPEN open
74#  define LIBTRACE_CLOSE close
75#  define LIBTRACE_WRITE write
76#endif
77
78#ifdef HAVE_LIMITS_H
79#  include <limits.h>
80#endif
81
82#ifdef HAVE_SYS_LIMITS_H
83#  include <sys/limits.h>
84#endif
85
86#ifndef O_LARGEFILE
87#define O_LARGEFILE 0
88#endif
89
90static struct libtrace_format_t *wag_ptr = 0;
91
92#define CONNINFO libtrace->format_data->conn_info
93#define INPUT libtrace->format_data->input
94#define OUTPUT libtrace->format_data->output
95#define OPTIONS libtrace->format_data->options
96
97struct libtrace_format_data_t {
98        union {
99                /** Information about rtclients */
100                struct {
101                        char *hostname;
102                        short port;
103                } rt;
104                char *path;             /**< information for local sockets */
105        } conn_info;
106        /** Information about the current state of the input device */
107        union {
108                int fd;
109#if HAVE_ZLIB
110                gzFile *file;
111#else   
112                FILE *file;
113#endif
114        } input;       
115};
116
117struct libtrace_format_data_out_t {
118        union {
119                char *path;
120        } conn_info;
121        union {
122                struct {
123                        int level;
124                } zlib;
125        } options;
126        union {
127                int fd;
128#if HAVE_ZLIB
129                gzFile *file;
130#else
131                FILE *file;
132#endif
133        } output;
134};
135
136static int wag_init_input(struct libtrace_t *libtrace) {
137        struct stat buf;
138        struct sockaddr_un unix_sock;
139        libtrace->format_data = (struct libtrace_format_data_t *) 
140                calloc(1,sizeof(struct libtrace_format_data_t));
141        CONNINFO.path = libtrace->uridata;
142        if (!strncmp(CONNINFO.path,"-",1)) {
143                // STDIN
144                libtrace->sourcetype = STDIN;
145                INPUT.file = LIBTRACE_FDOPEN(STDIN,"r");
146
147        } else {
148                if (stat(CONNINFO.path,&buf) == -1 ) {
149                        perror("stat");
150                        return 0;
151                }
152                if (S_ISSOCK(buf.st_mode)) {
153                        libtrace->sourcetype = SOCKET;
154                        // SOCKET
155                        if ((INPUT.fd = socket(
156                                        AF_UNIX, SOCK_STREAM, 0)) == -1) {
157                                perror("socket");
158                                return 0;
159                        }
160                        unix_sock.sun_family = AF_UNIX;
161                        bzero(unix_sock.sun_path,108);
162                        snprintf(unix_sock.sun_path,
163                                        108,"%s"
164                                        ,CONNINFO.path);
165
166                        if (connect(INPUT.fd, 
167                                        (struct sockaddr *)&unix_sock,
168                                        sizeof(struct sockaddr)) == -1) {
169                                perror("connect (unix)");
170                                return 0;
171                        }
172                } else { 
173                        // TRACE
174                        libtrace->sourcetype = TRACE;
175                       
176                        // we use an FDOPEN call to reopen an FD
177                        // returned from open(), so that we can set
178                        // O_LARGEFILE. This gets around gzopen not
179                        // letting you do this...
180                        INPUT.file = LIBTRACE_FDOPEN(open(
181                                        CONNINFO.path,
182                                        O_LARGEFILE), "r");
183
184                }
185        }
186        return 1;
187}
188
189static int wag_init_output(struct libtrace_out_t *libtrace) {
190        char *filemode = 0;
191        libtrace->format_data = (struct libtrace_format_data_out_t *)
192                calloc(1,sizeof(struct libtrace_format_data_out_t));
193
194        OPTIONS.zlib.level = 0;
195        asprintf(&filemode,"wb%d",OPTIONS.zlib.level);
196        if (!strncmp(libtrace->uridata,"-",1)) {
197                // STDOUT                               
198                OUTPUT.file = LIBTRACE_FDOPEN(dup(1), filemode);
199        } else {
200                // TRACE
201                OUTPUT.file = LIBTRACE_FDOPEN(open(
202                                        libtrace->uridata,
203                                        O_CREAT | O_LARGEFILE | O_WRONLY,
204                                        S_IRUSR | S_IWUSR), filemode);
205        }
206
207        return 1;
208}
209
210static int wag_config_output(struct libtrace_out_t *libtrace, int argc, char *argv[]) {
211#if HAVE_ZLIB
212        int opt;
213        int level = OPTIONS.zlib.level;
214        optind = 1;
215        while ((opt = getopt(argc, argv, "z:")) != EOF) {
216                switch (opt) {
217                        case 'z':
218                                level = atoi(optarg);
219                                break;
220                        default:
221                                printf("Bad argument to wag: %s\n", optarg);
222                                return -1;
223                }
224        }
225        if (level != OPTIONS.zlib.level) {
226                if (level > 9 || level < 0) {
227                        // retarded level choice
228                        printf("Compression level must be between 0 and 9 inclusive - you selected %i \n", level);
229                } else {
230                        OPTIONS.zlib.level = level;
231                        return gzsetparams(OUTPUT.file, level, Z_DEFAULT_STRATEGY);
232                }
233        }
234#endif
235        return 0;
236}
237
238static int wag_fin_input(struct libtrace_t *libtrace) {
239        LIBTRACE_CLOSE(INPUT.file);
240        return 0;
241}
242
243static int wag_fin_output(struct libtrace_out_t *libtrace) {
244        LIBTRACE_CLOSE(OUTPUT.file);
245        return 0;
246}
247
248static int wag_read(struct libtrace_t *libtrace, void *buffer, size_t len) {
249        int numbytes;
250        assert(libtrace);
251
252        if (buffer == 0)
253                buffer = malloc(len);
254
255        while(1) {
256                switch(libtrace->sourcetype) {
257                        case DEVICE:
258                                if ((numbytes=read(INPUT.fd, 
259                                                                buffer, 
260                                                                len)) == -1) {
261                                        perror("read");
262                                        return -1;
263                                }
264                                break;
265                        default:
266                                if ((numbytes=LIBTRACE_READ(INPUT.file,
267                                                                buffer,
268                                                                len)) == -1) {
269                                        perror("libtrace_read");
270                                        return -1;
271                                }
272                }
273                break;
274        }
275        return numbytes;
276
277}
278
279
280static int wag_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
281        int numbytes;
282        int size;
283        char buf[RP_BUFSIZE];
284        int read_required = 0;
285
286        void *buffer = 0;
287
288        packet->trace = libtrace;
289        buffer = packet->buffer;
290       
291
292        do {
293                if (tracefifo_out_available(libtrace->fifo) == 0 || read_required) {
294                        if ((numbytes = wag_read(libtrace,buf,RP_BUFSIZE)) <= 0) {
295                                return numbytes;
296                        }
297                        assert(libtrace->fifo);
298                        tracefifo_write(libtrace->fifo,buf,numbytes);
299                        read_required = 0;
300                }
301                // read in wag_frame_hdr
302                if ((numbytes = tracefifo_out_read(libtrace->fifo, 
303                                                buffer,
304                                                sizeof(struct wag_frame_hdr)))
305                                == 0 ) {
306                        tracefifo_out_reset(libtrace->fifo);
307                        read_required = 1;
308                        continue;
309                }
310               
311                size = ntohs(((struct wag_frame_hdr *)buffer)->size);
312
313                // wag isn't in network byte order yet
314                //size = htons(size);
315                //printf("%d %d\n",size,htons(size));
316
317                // read in full packet
318                if((numbytes = tracefifo_out_read(libtrace->fifo,buffer,size)) == 0) {
319                        tracefifo_out_reset(libtrace->fifo);
320                        read_required = 1;
321                        continue;
322                }
323
324                // have the whole packet
325                tracefifo_out_update(libtrace->fifo,size);
326                tracefifo_ack_update(libtrace->fifo,size);
327
328                packet->status = 0;
329                packet->size = numbytes;
330                return numbytes;
331        } while(1);
332}
333
334static int wag_write_packet(struct libtrace_out_t *libtrace, const struct libtrace_packet_t *packet) {
335        int numbytes =0 ;
336        if (packet->trace->format != wag_ptr) {
337                fprintf(stderr,"Cannot convert from wag to %s format yet\n",
338                                packet->trace->format->name);
339                return -1;
340        }
341        if ((numbytes = LIBTRACE_WRITE(OUTPUT.file, packet->buffer, packet->size)) == 0) {
342                perror("libtrace_write");
343                return -1;
344        }
345        return numbytes;
346}
347
348static void *wag_get_link(const struct libtrace_packet_t *packet) {
349        struct wag_data_frame *wagptr = (struct wag_data_frame *)packet->buffer;
350        void *payload = wagptr->data;
351        return (void*)payload;
352}
353
354static libtrace_linktype_t wag_get_link_type(const struct libtrace_packet_t *packet __attribute__((unused))) {
355        return TRACE_TYPE_80211;
356}
357
358static int8_t wag_get_direction(const struct libtrace_packet_t *packet) {
359        struct wag_data_frame *wagptr = (struct wag_data_frame *)packet->buffer;
360        if (wagptr->hdr.type == 0) {
361                return wagptr->hdr.subtype;
362        }
363        return -1;
364}
365
366static uint64_t wag_get_erf_timestamp(const struct libtrace_packet_t *packet) {
367        struct wag_data_frame *wagptr = (struct wag_data_frame *)packet->buffer;
368        uint64_t timestamp = 0;
369        timestamp = wagptr->ts.subsecs;
370        //timestamp |= (uint64_t)wagptr->ts.secs<<32;
371        timestamp = ((timestamp%44000000)*(UINT_MAX/44000000)) 
372                | ((timestamp/44000000)<<32);
373        return timestamp;
374}
375
376static int wag_get_capture_length(const struct libtrace_packet_t *packet) {
377        struct wag_data_frame *wagptr = (struct wag_data_frame *)packet->buffer;
378        //return (wagptr->hdr.size);
379        return ntohs(wagptr->hdr.size);
380}
381
382static int wag_get_wire_length(const struct libtrace_packet_t *packet) {
383        struct wag_data_frame *wagptr = (struct wag_data_frame *)packet->buffer;
384        //return (wagptr->hdr.size);
385        return ntohs(wagptr->hdr.size);
386}
387
388static int wag_get_fd(const struct libtrace_packet_t *packet) {
389        return packet->trace->format_data->input.fd;
390}
391
392static struct libtrace_eventobj_t wag_event_trace(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
393        switch(trace->sourcetype) {
394                case DEVICE:
395                        return trace_event_device(trace,packet);
396                default:
397                        return trace_event_trace(trace,packet);
398        }
399}
400static void wag_help() {
401        printf("wag format module: $Revision$\n");
402        printf("Supported input URIs:\n");
403        printf("\twag:/dev/wagn\n");
404        printf("\twag:/path/to/trace.wag\n");
405        printf("\twag:/path/to/trace.wag.gz\n");
406        printf("\n");
407        printf("\te.g.: wag:/dev/wag0\n");
408        printf("\te.g.: wag:/tmp/trace.wag.gz\n");
409        printf("\n");
410        printf("Supported output URIs:\n");
411        printf("\tnone\n");
412        printf("\n");
413}
414
415static struct libtrace_format_t wag = {
416        "wag",
417        "$Id$",
418        "wag",
419        wag_init_input,                 /* init_input */       
420        wag_init_output,                /* init_output */
421        wag_config_output,              /* config_output */
422        wag_fin_input,                  /* fin_input */
423        wag_fin_output,                 /* fin_output */
424        wag_read_packet,                /* read_packet */
425        wag_write_packet,               /* write_packet */
426        wag_get_link,                   /* get_link */
427        wag_get_link_type,              /* get_link_type */
428        wag_get_direction,              /* get_direction */
429        NULL,                           /* set_direction */
430        wag_get_erf_timestamp,          /* get_erf_timestamp */
431        NULL,                           /* get_timeval */
432        NULL,                           /* get_seconds */
433        wag_get_capture_length,         /* get_capture_length */
434        wag_get_wire_length,            /* get_wire_length */
435        NULL,                           /* set_capture_length */
436        wag_get_fd,                     /* get_fd */
437        wag_event_trace,                /* trace_event */
438        wag_help                        /* help */
439};
440
441void __attribute__((constructor)) wag_constructor() {
442        wag_ptr = &wag;
443        register_format(wag_ptr);
444}
Note: See TracBrowser for help on using the repository browser.