source: lib/format_legacy.c @ c66068d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c66068d was c66068d, checked in by Perry Lorier <perry@…>, 13 years ago

Rewrite the libtrace io subsystem to use the new wandio abstraction layer.

  • Property mode set to 100644
File size: 16.9 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008 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#define _GNU_SOURCE
31
32#include "config.h"
33#include "common.h"
34#include "libtrace.h"
35#include "libtrace_int.h"
36#include "format_helper.h"
37#include "wandio.h"
38
39#include <sys/stat.h>
40#include <assert.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <stdio.h>
44#include <string.h>
45#include <stdlib.h>
46#include <regex.h>
47
48#ifdef WIN32
49#  include <io.h>
50#  include <share.h>
51#endif
52
53
54/* Catch undefined O_LARGEFILE on *BSD etc */
55#ifndef O_LARGEFILE
56#  define O_LARGEFILE 0
57#endif
58
59#ifndef UINT32_MAX
60#  define UINT32_MAX 0xffffffff
61#endif
62
63#define DATA(x) ((struct legacy_format_data_t *)x->format_data)
64#define INPUT DATA(libtrace)->input
65
66struct legacy_format_data_t {
67        union {
68                int fd;
69                io_t *file;
70        } input;
71        time_t starttime;       /* Used for legacy_nzix */
72        uint64_t ts_high;       /* Used for legacy_nzix */
73        uint32_t ts_old;        /* Used for legacy_nzix */
74};
75
76static void legacy_init_format_data(libtrace_t *libtrace) {
77        libtrace->format_data = malloc(sizeof(struct legacy_format_data_t));
78       
79        DATA(libtrace)->input.file = NULL;
80        DATA(libtrace)->ts_high = 0;
81        DATA(libtrace)->ts_old = 0;
82        DATA(libtrace)->starttime = 0;
83}
84
85static int legacyeth_get_framing_length(const libtrace_packet_t *packet UNUSED) 
86{
87        return sizeof(legacy_ether_t);
88}
89
90static int legacypos_get_framing_length(const libtrace_packet_t *packet UNUSED) 
91{
92        return sizeof(legacy_pos_t);
93}
94
95static int legacyatm_get_framing_length(const libtrace_packet_t *packet UNUSED) 
96{
97        return sizeof(legacy_cell_t);
98}
99
100static int legacynzix_get_framing_length(const libtrace_packet_t *packet UNUSED)
101{
102        return sizeof(legacy_nzix_t);
103}
104
105static int erf_init_input(libtrace_t *libtrace) 
106{
107        legacy_init_format_data(libtrace);
108
109        return 0;
110}
111
112static time_t trtime(char *s) {
113        /* XXX: this function may not be particularly portable to
114         * other platforms, e.g. *BSDs, Windows */
115        struct tm tm;
116        char *tz;
117        time_t ret;
118        static char envbuf[256];
119
120        if(sscanf(s, "%4u%2u%2u-%2u%2u%2u", &tm.tm_year, &tm.tm_mon,
121                                &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
122                                &tm.tm_sec) != 6) {
123                return (time_t)0;
124        }
125        tm.tm_year = tm.tm_year - 1900;
126        tm.tm_mon --;
127        tm.tm_wday = 0; /* ignored */
128        tm.tm_yday = 0; /* ignored */
129        tm.tm_isdst = -1; /* forces check for summer time */
130       
131        tz = getenv("TZ");
132        if (putenv("TZ=Pacific/Auckland")) {
133                perror("putenv");
134                return (time_t)0;
135        }
136        tzset();
137        ret = mktime(&tm);
138
139        return ret;
140}
141       
142
143static int legacynzix_init_input(libtrace_t *libtrace) {
144
145        int retval;
146        char *filename = libtrace->uridata;
147        regex_t reg;
148        regmatch_t match;
149
150
151        legacy_init_format_data(libtrace);     
152        if((retval = regcomp(&reg, "[0-9]{8}-[0-9]{6}", REG_EXTENDED)) != 0) {
153                trace_set_err(libtrace, errno, "Failed to compile regex");
154                return -1;
155        }
156        if ((retval = regexec(&reg, filename, 1, &match, 0)) !=0) {
157                trace_set_err(libtrace, errno, "Failed to exec regex");
158                return -1;
159        }
160        DATA(libtrace)->starttime = trtime(&filename[match.rm_so]);
161        return 0;
162}
163
164static int erf_start_input(libtrace_t *libtrace)
165{
166        if (DATA(libtrace)->input.file)
167                return 0;
168
169        DATA(libtrace)->input.file = trace_open_file(libtrace);
170
171        if (DATA(libtrace)->input.file)
172                return 0;
173
174        return -1;
175}
176
177static int erf_fin_input(libtrace_t *libtrace) {
178        wandio_destroy(INPUT.file);
179        free(libtrace->format_data);
180        return 0;
181}
182
183static int legacy_prepare_packet(libtrace_t *libtrace, 
184                libtrace_packet_t *packet, void *buffer, 
185                libtrace_rt_types_t rt_type, uint32_t flags) {
186
187        if (packet->buffer != buffer &&
188                        packet->buf_control == TRACE_CTRL_PACKET) {
189                free(packet->buffer);
190        }
191
192        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
193                packet->buf_control = TRACE_CTRL_PACKET;
194        } else
195                packet->buf_control = TRACE_CTRL_EXTERNAL;
196
197
198        packet->buffer = buffer;
199        packet->header = buffer;
200        packet->type = rt_type;
201        packet->payload = (void*)((char*)packet->buffer + 
202                libtrace->format->get_framing_length(packet));
203
204
205        if (libtrace->format_data == NULL) {
206                legacy_init_format_data(libtrace);
207        }
208        return 0;
209}
210
211static int legacy_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
212        int numbytes;
213        void *buffer;
214        uint32_t flags = 0;
215       
216        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
217                packet->buffer=malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
218        }
219        flags |= TRACE_PREP_OWN_BUFFER;
220        buffer = packet->buffer;
221
222        switch(libtrace->format->type) {
223                case TRACE_FORMAT_LEGACY_ATM:
224                        packet->type = TRACE_RT_DATA_LEGACY_ATM;
225                        break;
226                case TRACE_FORMAT_LEGACY_POS:
227                        packet->type = TRACE_RT_DATA_LEGACY_POS;
228                        break;
229                case TRACE_FORMAT_LEGACY_ETH:
230                        packet->type = TRACE_RT_DATA_LEGACY_ETH;
231                        break;
232                default:
233                        assert(0);
234        }
235
236        /* This is going to block until we either get an entire record
237         * or we reach the end of the file */
238        while (1) {
239       
240                if ((numbytes=wandio_read(INPUT.file,
241                                                buffer,
242                                                (size_t)64)) != 64) {
243                        if (numbytes < 0) {
244                                trace_set_err(libtrace,errno,"read(%s)",libtrace->uridata);
245                        } else if (numbytes > 0) {
246                               
247                                continue;
248                        }
249                        return numbytes;
250                }
251                break;
252        }
253       
254        if (legacy_prepare_packet(libtrace, packet, packet->buffer, 
255                                packet->type, flags)) {
256                return -1;
257        }
258       
259        return 64;
260       
261}
262
263static int legacynzix_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
264        /* Firstly, I apologize for all the constants being thrown around in
265         * this function, but it does befit the hackish origins of the
266         * NZIX format that I use them. Anyone who wants to clean them up is
267         * welcome to do so */
268        int numbytes;
269        void *buffer;
270        char *data_ptr;
271        uint32_t flags = 0;
272       
273        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
274                packet->buffer=malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
275        }
276        flags |= TRACE_PREP_OWN_BUFFER;
277       
278        buffer = packet->buffer;
279        packet->type = TRACE_RT_DATA_LEGACY_NZIX;
280       
281        while (1) {
282                if ((numbytes = wandio_read(INPUT.file, buffer,
283                                                (size_t)68)) != 68) {
284                        if (numbytes < 0) {
285                                trace_set_err(libtrace,errno,"read(%s)",libtrace->uridata);
286                        } else if (numbytes > 0)
287                                continue;
288                        return numbytes;
289                } 
290                /* Packets with a zero length are GPS timestamp packets
291                 * but they aren't inserted at the right time to be
292                 * useful - instead we'll ignore them unless we can think
293                 * of a compelling reason to do otherwise */
294                if (((legacy_nzix_t *)buffer)->len == 0)
295                        continue;
296               
297                break;
298        }
299
300        /* lets move the padding so that it's in the framing header */
301        data_ptr = ((char *)buffer) + 12;
302        memmove(data_ptr + 2, data_ptr, 26);
303
304        if (legacy_prepare_packet(libtrace, packet, packet->buffer, 
305                                packet->type, flags)) {
306                return -1;
307        }
308        return 68;
309}
310               
311
312static libtrace_linktype_t legacypos_get_link_type(
313                const libtrace_packet_t *packet) {
314        /* POS can be PPP over HDLC (DLT_PPP_SERIAL), or it can be
315         * just straight PPP.  Sigh.
316         *
317         * Ref: RFC 1549
318         *      - Perry Lorier (2008-11-04)
319         */
320        if (((char *)packet->payload)[0] == '\xFF'
321                && ((char*)packet->payload)[1] == '\x03')
322                return TRACE_TYPE_POS;
323        else 
324                return TRACE_TYPE_PPP;
325}
326
327static libtrace_linktype_t legacyatm_get_link_type(
328                const libtrace_packet_t *packet UNUSED) {
329        return TRACE_TYPE_ATM;
330}
331
332static libtrace_linktype_t legacyeth_get_link_type(const libtrace_packet_t *packet UNUSED) {
333        return TRACE_TYPE_ETH;
334}
335
336static libtrace_linktype_t legacynzix_get_link_type(const libtrace_packet_t *packet UNUSED) {
337        return TRACE_TYPE_ETH;
338}
339
340static int legacy_get_capture_length(const libtrace_packet_t *packet UNUSED) {
341        return 64;
342}
343
344static int legacynzix_get_capture_length(const libtrace_packet_t *packet UNUSED)
345{
346        return 54;
347}
348
349static int legacypos_get_wire_length(const libtrace_packet_t *packet) {
350        legacy_pos_t *lpos = (legacy_pos_t *)packet->header;
351        assert(ntohl(lpos->wlen)>0);
352        return ntohl(lpos->wlen);
353}
354
355static int legacyatm_get_wire_length(const libtrace_packet_t *packet UNUSED) {
356        return 53;
357}
358
359static int legacyeth_get_wire_length(const libtrace_packet_t *packet) {
360        legacy_ether_t *leth = (legacy_ether_t *)packet->header;
361        return leth->wlen;
362}
363
364static int legacynzix_get_wire_length(const libtrace_packet_t *packet) {
365        legacy_nzix_t *lnzix = (legacy_nzix_t *)packet->header;
366        return lnzix->len;
367}
368
369static uint64_t legacy_get_erf_timestamp(const libtrace_packet_t *packet)
370{
371        legacy_ether_t *legacy = (legacy_ether_t*)packet->header;
372        return legacy->ts;
373} 
374
375static uint32_t ts_cmp(uint32_t ts_a, uint32_t ts_b) {
376       
377        /* each ts is actually a 30 bit value */
378        ts_a <<= 2;
379        ts_b <<= 2;
380
381
382        if (ts_a > ts_b) 
383                return (ts_a - ts_b);
384        else
385                return (ts_b - ts_a);
386       
387}
388
389static struct timeval legacynzix_get_timeval(const libtrace_packet_t *packet) {
390        uint64_t new_ts = DATA(packet->trace)->ts_high;
391        uint32_t old_ts = DATA(packet->trace)->ts_old;
392        struct timeval tv;
393        uint32_t hdr_ts;
394
395        double dts;
396       
397        legacy_nzix_t *legacy = (legacy_nzix_t *)packet->header;
398               
399        hdr_ts = legacy->ts;
400
401        /* seems we only need 30 bits to represent our timestamp */
402        hdr_ts >>=2;
403        /* try a sequence number wrap-around comparison */
404        if (ts_cmp(hdr_ts, old_ts) > (UINT32_MAX / 2) )
405                new_ts += (1LL << 30); /* wraparound */
406        new_ts &= ~((1LL << 30) -1);    /* mask lower 30 bits */
407        new_ts += hdr_ts;               /* packet ts is the new 30 bits */
408        DATA(packet->trace)->ts_old = hdr_ts;
409
410        tv.tv_sec = DATA(packet->trace)->starttime + (new_ts / (1000 * 1000));
411        tv.tv_usec = new_ts % (1000 * 1000);
412        DATA(packet->trace)->ts_high = new_ts;
413
414
415        dts = tv.tv_sec + (double)tv.tv_usec / 1000 / 1000;
416        return tv;
417       
418}       
419
420static void legacypos_help(void) {
421        printf("legacypos format module: $Revision$\n");
422        printf("Supported input URIs:\n");
423        printf("\tlegacypos:/path/to/file\t(uncompressed)\n");
424        printf("\tlegacypos:/path/to/file.gz\t(gzip-compressed)\n");
425        printf("\tlegacypos:-\t(stdin, either compressed or not)\n");
426        printf("\n");
427        printf("\te.g.: legacypos:/tmp/trace.gz\n");
428        printf("\n");
429}
430
431static void legacyatm_help(void) {
432        printf("legacyatm format module: $Revision$\n");
433        printf("Supported input URIs:\n");
434        printf("\tlegacyatm:/path/to/file\t(uncompressed)\n");
435        printf("\tlegacyatm:/path/to/file.gz\t(gzip-compressed)\n");
436        printf("\tlegacyatm:-\t(stdin, either compressed or not)\n");
437        printf("\n");
438        printf("\te.g.: legacyatm:/tmp/trace.gz\n");
439        printf("\n");
440}
441
442static void legacyeth_help(void) {
443        printf("legacyeth format module: $Revision$\n");
444        printf("Supported input URIs:\n");
445        printf("\tlegacyeth:/path/to/file\t(uncompressed)\n");
446        printf("\tlegacyeth:/path/to/file.gz\t(gzip-compressed)\n");
447        printf("\tlegacyeth:-\t(stdin, either compressed or not)\n");
448        printf("\n");
449        printf("\te.g.: legacyeth:/tmp/trace.gz\n");
450        printf("\n");
451}
452
453static void legacynzix_help(void) {
454        printf("legacynzix format module: $Revision$\n");
455        printf("Supported input URIs:\n");
456        printf("\tlegacynzix:/path/to/file\t(uncompressed)\n");
457        printf("\tlegacynzix:/path/to/file.gz\t(gzip-compressed)\n");
458        printf("\tlegacynzix:-\t(stdin, either compressed or not)\n");
459        printf("\n");
460        printf("\te.g.: legacynzix:/tmp/trace.gz\n");
461        printf("\n");
462}
463
464static struct libtrace_format_t legacyatm = {
465        "legacyatm",
466        "$Id$",
467        TRACE_FORMAT_LEGACY_ATM,
468        erf_init_input,                 /* init_input */       
469        NULL,                           /* config_input */
470        erf_start_input,                /* start_input */
471        NULL,                           /* pause_input */
472        NULL,                           /* init_output */
473        NULL,                           /* config_output */
474        NULL,                           /* start_output */
475        erf_fin_input,                  /* fin_input */
476        NULL,                           /* fin_output */
477        legacy_read_packet,             /* read_packet */
478        legacy_prepare_packet,          /* prepare_packet */
479        NULL,                           /* fin_packet */
480        NULL,                           /* write_packet */
481        legacyatm_get_link_type,        /* get_link_type */
482        NULL,                           /* get_direction */
483        NULL,                           /* set_direction */
484        legacy_get_erf_timestamp,       /* get_erf_timestamp */
485        NULL,                           /* get_timeval */
486        NULL,                           /* get_seconds */
487        NULL,                           /* seek_erf */
488        NULL,                           /* seek_timeval */
489        NULL,                           /* seek_seconds */
490        legacy_get_capture_length,      /* get_capture_length */
491        legacyatm_get_wire_length,      /* get_wire_length */
492        legacyatm_get_framing_length,   /* get_framing_length */
493        NULL,                           /* set_capture_length */
494        NULL,                           /* get_received_packets */
495        NULL,                           /* get_filtered_packets */
496        NULL,                           /* get_dropped_packets */
497        NULL,                           /* get_captured_packets */
498        NULL,                           /* get_fd */
499        trace_event_trace,              /* trace_event */
500        legacyatm_help,                 /* help */
501        NULL                            /* next pointer */
502};
503
504static struct libtrace_format_t legacyeth = {
505        "legacyeth",
506        "$Id$",
507        TRACE_FORMAT_LEGACY_ETH,
508        erf_init_input,                 /* init_input */       
509        NULL,                           /* config_input */
510        erf_start_input,                /* start_input */
511        NULL,                           /* pause_input */
512        NULL,                           /* init_output */
513        NULL,                           /* config_output */
514        NULL,                           /* start_output */
515        erf_fin_input,                  /* fin_input */
516        NULL,                           /* fin_output */
517        legacy_read_packet,             /* read_packet */
518        legacy_prepare_packet,          /* prepare_packet */
519        NULL,                           /* fin_packet */
520        NULL,                           /* write_packet */
521        legacyeth_get_link_type,        /* get_link_type */
522        NULL,                           /* get_direction */
523        NULL,                           /* set_direction */
524        legacy_get_erf_timestamp,       /* get_erf_timestamp */
525        NULL,                           /* get_timeval */
526        NULL,                           /* get_seconds */
527        NULL,                           /* seek_erf */
528        NULL,                           /* seek_timeval */
529        NULL,                           /* seek_seconds */
530        legacy_get_capture_length,      /* get_capture_length */
531        legacyeth_get_wire_length,      /* get_wire_length */
532        legacyeth_get_framing_length,   /* get_framing_length */
533        NULL,                           /* set_capture_length */
534        NULL,                           /* get_received_packets */
535        NULL,                           /* get_filtered_packets */
536        NULL,                           /* get_dropped_packets */
537        NULL,                           /* get_captured_packets */
538        NULL,                           /* get_fd */
539        trace_event_trace,              /* trace_event */
540        legacyeth_help,                 /* help */
541        NULL                            /* next pointer */
542};
543
544static struct libtrace_format_t legacypos = {
545        "legacypos",
546        "$Id$",
547        TRACE_FORMAT_LEGACY_POS,
548        erf_init_input,                 /* init_input */       
549        NULL,                           /* config_input */
550        erf_start_input,                /* start_input */
551        NULL,                           /* pause_input */
552        NULL,                           /* init_output */
553        NULL,                           /* config_output */
554        NULL,                           /* start_output */
555        erf_fin_input,                  /* fin_input */
556        NULL,                           /* fin_output */
557        legacy_read_packet,             /* read_packet */
558        legacy_prepare_packet,          /* prepare_packet */
559        NULL,                           /* fin_packet */
560        NULL,                           /* write_packet */
561        legacypos_get_link_type,        /* get_link_type */
562        NULL,                           /* get_direction */
563        NULL,                           /* set_direction */
564        legacy_get_erf_timestamp,       /* get_erf_timestamp */
565        NULL,                           /* get_timeval */
566        NULL,                           /* get_seconds */
567        NULL,                           /* seek_erf */
568        NULL,                           /* seek_timeval */
569        NULL,                           /* seek_seconds */
570        legacy_get_capture_length,      /* get_capture_length */
571        legacypos_get_wire_length,      /* get_wire_length */
572        legacypos_get_framing_length,   /* get_framing_length */
573        NULL,                           /* set_capture_length */
574        NULL,                           /* get_received_packets */
575        NULL,                           /* get_filtered_packets */
576        NULL,                           /* get_dropped_packets */
577        NULL,                           /* get_captured_packets */
578        NULL,                           /* get_fd */
579        trace_event_trace,              /* trace_event */
580        legacypos_help,                 /* help */
581        NULL,                           /* next pointer */
582};
583
584static struct libtrace_format_t legacynzix = {
585        "legacynzix",
586        "$Id$",
587        TRACE_FORMAT_LEGACY_NZIX,
588        legacynzix_init_input,          /* init_input */       
589        NULL,                           /* config_input */
590        erf_start_input,                /* start_input */
591        NULL,                           /* pause_input */
592        NULL,                           /* init_output */
593        NULL,                           /* config_output */
594        NULL,                           /* start_output */
595        erf_fin_input,                  /* fin_input */
596        NULL,                           /* fin_output */
597        legacynzix_read_packet,         /* read_packet */
598        legacy_prepare_packet,          /* prepare_packet */
599        NULL,                           /* fin_packet */
600        NULL,                           /* write_packet */
601        legacynzix_get_link_type,       /* get_link_type */
602        NULL,                           /* get_direction */
603        NULL,                           /* set_direction */
604        NULL,                           /* get_erf_timestamp */
605        legacynzix_get_timeval,         /* get_timeval */
606        NULL,                           /* get_seconds */
607        NULL,                           /* seek_erf */
608        NULL,                           /* seek_timeval */
609        NULL,                           /* seek_seconds */
610        legacynzix_get_capture_length,  /* get_capture_length */
611        legacynzix_get_wire_length,     /* get_wire_length */
612        legacynzix_get_framing_length,  /* get_framing_length */
613        NULL,                           /* set_capture_length */
614        NULL,                           /* get_received_packets */
615        NULL,                           /* get_filtered_packets */
616        NULL,                           /* get_dropped_packets */
617        NULL,                           /* get_captured_packets */
618        NULL,                           /* get_fd */
619        trace_event_trace,              /* trace_event */
620        legacynzix_help,                /* help */
621        NULL,                           /* next pointer */
622};
623       
624void legacy_constructor(void) {
625        register_format(&legacypos);
626        register_format(&legacyeth);
627        register_format(&legacyatm);
628        register_format(&legacynzix);
629}
Note: See TracBrowser for help on using the repository browser.