source: lib/format_wag.c @ 9c6aa95

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 9c6aa95 was 9c6aa95, checked in by Daniel Lawson <dlawson@…>, 16 years ago

cleaned up after compiling with -Wall -W

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