source: lib/format_legacy.c @ 15e9390

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

Support using timespec's for dealing with traces

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