source: lib/format_legacy.c @ 29c8666

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

Deal with PoS traces better

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