source: lib/format_legacy.c @ 87d7ab9

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 87d7ab9 was 87d7ab9, checked in by Shane Alcock <salcock@…>, 13 years ago
  • format_legacy should now compile on systems that don't define UINT32_MAX
  • 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        /* Is this a cisco hdlc frame? */
314        if ((((uint8_t*)packet->payload)[0] == 0x0F /* Unicast */
315                || ((uint8_t*)packet->payload)[0] == 0x8F /* Multicast */)
316                && ((uint8_t*)packet->payload)[1] == 0x00 /* control == 0x00 */
317           )
318                return TRACE_TYPE_HDLC_POS;
319        return TRACE_TYPE_PPP;
320}
321
322static libtrace_linktype_t legacyatm_get_link_type(
323                const libtrace_packet_t *packet UNUSED) {
324        return TRACE_TYPE_ATM;
325}
326
327static libtrace_linktype_t legacyeth_get_link_type(const libtrace_packet_t *packet UNUSED) {
328        return TRACE_TYPE_ETH;
329}
330
331static libtrace_linktype_t legacynzix_get_link_type(const libtrace_packet_t *packet UNUSED) {
332        return TRACE_TYPE_ETH;
333}
334
335static int legacy_get_capture_length(const libtrace_packet_t *packet UNUSED) {
336        return 64;
337}
338
339static int legacynzix_get_capture_length(const libtrace_packet_t *packet UNUSED)
340{
341        return 54;
342}
343
344static int legacypos_get_wire_length(const libtrace_packet_t *packet) {
345        legacy_pos_t *lpos = (legacy_pos_t *)packet->header;
346        assert(ntohl(lpos->wlen)>0);
347        return ntohl(lpos->wlen);
348}
349
350static int legacyatm_get_wire_length(const libtrace_packet_t *packet UNUSED) {
351        return 53;
352}
353
354static int legacyeth_get_wire_length(const libtrace_packet_t *packet) {
355        legacy_ether_t *leth = (legacy_ether_t *)packet->header;
356        return leth->wlen;
357}
358
359static int legacynzix_get_wire_length(const libtrace_packet_t *packet) {
360        legacy_nzix_t *lnzix = (legacy_nzix_t *)packet->header;
361        return lnzix->len;
362}
363
364static uint64_t legacy_get_erf_timestamp(const libtrace_packet_t *packet)
365{
366        legacy_ether_t *legacy = (legacy_ether_t*)packet->header;
367        return legacy->ts;
368} 
369
370static uint32_t ts_cmp(uint32_t ts_a, uint32_t ts_b) {
371       
372        /* each ts is actually a 30 bit value */
373        ts_a <<= 2;
374        ts_b <<= 2;
375
376
377        if (ts_a > ts_b) 
378                return (ts_a - ts_b);
379        else
380                return (ts_b - ts_a);
381       
382}
383
384static struct timeval legacynzix_get_timeval(const libtrace_packet_t *packet) {
385        uint64_t new_ts = DATA(packet->trace)->ts_high;
386        uint32_t old_ts = DATA(packet->trace)->ts_old;
387        struct timeval tv;
388        uint32_t hdr_ts;
389
390        double dts;
391       
392        legacy_nzix_t *legacy = (legacy_nzix_t *)packet->header;
393               
394        hdr_ts = legacy->ts;
395
396        /* seems we only need 30 bits to represent our timestamp */
397        hdr_ts >>=2;
398        /* try a sequence number wrap-around comparison */
399        if (ts_cmp(hdr_ts, old_ts) > (UINT32_MAX / 2) )
400                new_ts += (1LL << 30); /* wraparound */
401        new_ts &= ~((1LL << 30) -1);    /* mask lower 30 bits */
402        new_ts += hdr_ts;               /* packet ts is the new 30 bits */
403        DATA(packet->trace)->ts_old = hdr_ts;
404
405        tv.tv_sec = DATA(packet->trace)->starttime + (new_ts / (1000 * 1000));
406        tv.tv_usec = new_ts % (1000 * 1000);
407        DATA(packet->trace)->ts_high = new_ts;
408
409
410        dts = tv.tv_sec + (double)tv.tv_usec / 1000 / 1000;
411        return tv;
412       
413}       
414
415static void legacypos_help(void) {
416        printf("legacypos format module: $Revision$\n");
417        printf("Supported input URIs:\n");
418        printf("\tlegacypos:/path/to/file\t(uncompressed)\n");
419        printf("\tlegacypos:/path/to/file.gz\t(gzip-compressed)\n");
420        printf("\tlegacypos:-\t(stdin, either compressed or not)\n");
421        printf("\n");
422        printf("\te.g.: legacypos:/tmp/trace.gz\n");
423        printf("\n");
424}
425
426static void legacyatm_help(void) {
427        printf("legacyatm format module: $Revision$\n");
428        printf("Supported input URIs:\n");
429        printf("\tlegacyatm:/path/to/file\t(uncompressed)\n");
430        printf("\tlegacyatm:/path/to/file.gz\t(gzip-compressed)\n");
431        printf("\tlegacyatm:-\t(stdin, either compressed or not)\n");
432        printf("\n");
433        printf("\te.g.: legacyatm:/tmp/trace.gz\n");
434        printf("\n");
435}
436
437static void legacyeth_help(void) {
438        printf("legacyeth format module: $Revision$\n");
439        printf("Supported input URIs:\n");
440        printf("\tlegacyeth:/path/to/file\t(uncompressed)\n");
441        printf("\tlegacyeth:/path/to/file.gz\t(gzip-compressed)\n");
442        printf("\tlegacyeth:-\t(stdin, either compressed or not)\n");
443        printf("\n");
444        printf("\te.g.: legacyeth:/tmp/trace.gz\n");
445        printf("\n");
446}
447
448static void legacynzix_help(void) {
449        printf("legacynzix format module: $Revision$\n");
450        printf("Supported input URIs:\n");
451        printf("\tlegacynzix:/path/to/file\t(uncompressed)\n");
452        printf("\tlegacynzix:/path/to/file.gz\t(gzip-compressed)\n");
453        printf("\tlegacynzix:-\t(stdin, either compressed or not)\n");
454        printf("\n");
455        printf("\te.g.: legacynzix:/tmp/trace.gz\n");
456        printf("\n");
457}
458
459static struct libtrace_format_t legacyatm = {
460        "legacyatm",
461        "$Id$",
462        TRACE_FORMAT_LEGACY_ATM,
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_seconds */
482        NULL,                           /* seek_erf */
483        NULL,                           /* seek_timeval */
484        NULL,                           /* seek_seconds */
485        legacy_get_capture_length,      /* get_capture_length */
486        legacyatm_get_wire_length,      /* get_wire_length */
487        legacyatm_get_framing_length,   /* get_framing_length */
488        NULL,                           /* set_capture_length */
489        NULL,                           /* get_received_packets */
490        NULL,                           /* get_filtered_packets */
491        NULL,                           /* get_dropped_packets */
492        NULL,                           /* get_captured_packets */
493        NULL,                           /* get_fd */
494        trace_event_trace,              /* trace_event */
495        legacyatm_help,                 /* help */
496        NULL                            /* next pointer */
497};
498
499static struct libtrace_format_t legacyeth = {
500        "legacyeth",
501        "$Id$",
502        TRACE_FORMAT_LEGACY_ETH,
503        erf_init_input,                 /* init_input */       
504        NULL,                           /* config_input */
505        erf_start_input,                /* start_input */
506        NULL,                           /* pause_input */
507        NULL,                           /* init_output */
508        NULL,                           /* config_output */
509        NULL,                           /* start_output */
510        erf_fin_input,                  /* fin_input */
511        NULL,                           /* fin_output */
512        legacy_read_packet,             /* read_packet */
513        legacy_prepare_packet,          /* prepare_packet */
514        NULL,                           /* fin_packet */
515        NULL,                           /* write_packet */
516        legacyeth_get_link_type,        /* get_link_type */
517        NULL,                           /* get_direction */
518        NULL,                           /* set_direction */
519        legacy_get_erf_timestamp,       /* get_erf_timestamp */
520        NULL,                           /* get_timeval */
521        NULL,                           /* get_seconds */
522        NULL,                           /* seek_erf */
523        NULL,                           /* seek_timeval */
524        NULL,                           /* seek_seconds */
525        legacy_get_capture_length,      /* get_capture_length */
526        legacyeth_get_wire_length,      /* get_wire_length */
527        legacyeth_get_framing_length,   /* get_framing_length */
528        NULL,                           /* set_capture_length */
529        NULL,                           /* get_received_packets */
530        NULL,                           /* get_filtered_packets */
531        NULL,                           /* get_dropped_packets */
532        NULL,                           /* get_captured_packets */
533        NULL,                           /* get_fd */
534        trace_event_trace,              /* trace_event */
535        legacyeth_help,                 /* help */
536        NULL                            /* next pointer */
537};
538
539static struct libtrace_format_t legacypos = {
540        "legacypos",
541        "$Id$",
542        TRACE_FORMAT_LEGACY_POS,
543        erf_init_input,                 /* init_input */       
544        NULL,                           /* config_input */
545        erf_start_input,                /* start_input */
546        NULL,                           /* pause_input */
547        NULL,                           /* init_output */
548        NULL,                           /* config_output */
549        NULL,                           /* start_output */
550        erf_fin_input,                  /* fin_input */
551        NULL,                           /* fin_output */
552        legacy_read_packet,             /* read_packet */
553        legacy_prepare_packet,          /* prepare_packet */
554        NULL,                           /* fin_packet */
555        NULL,                           /* write_packet */
556        legacypos_get_link_type,        /* get_link_type */
557        NULL,                           /* get_direction */
558        NULL,                           /* set_direction */
559        legacy_get_erf_timestamp,       /* get_erf_timestamp */
560        NULL,                           /* get_timeval */
561        NULL,                           /* get_seconds */
562        NULL,                           /* seek_erf */
563        NULL,                           /* seek_timeval */
564        NULL,                           /* seek_seconds */
565        legacy_get_capture_length,      /* get_capture_length */
566        legacypos_get_wire_length,      /* get_wire_length */
567        legacypos_get_framing_length,   /* get_framing_length */
568        NULL,                           /* set_capture_length */
569        NULL,                           /* get_received_packets */
570        NULL,                           /* get_filtered_packets */
571        NULL,                           /* get_dropped_packets */
572        NULL,                           /* get_captured_packets */
573        NULL,                           /* get_fd */
574        trace_event_trace,              /* trace_event */
575        legacypos_help,                 /* help */
576        NULL,                           /* next pointer */
577};
578
579static struct libtrace_format_t legacynzix = {
580        "legacynzix",
581        "$Id$",
582        TRACE_FORMAT_LEGACY_NZIX,
583        legacynzix_init_input,          /* init_input */       
584        NULL,                           /* config_input */
585        erf_start_input,                /* start_input */
586        NULL,                           /* pause_input */
587        NULL,                           /* init_output */
588        NULL,                           /* config_output */
589        NULL,                           /* start_output */
590        erf_fin_input,                  /* fin_input */
591        NULL,                           /* fin_output */
592        legacynzix_read_packet,         /* read_packet */
593        legacy_prepare_packet,          /* prepare_packet */
594        NULL,                           /* fin_packet */
595        NULL,                           /* write_packet */
596        legacynzix_get_link_type,       /* get_link_type */
597        NULL,                           /* get_direction */
598        NULL,                           /* set_direction */
599        NULL,                           /* get_erf_timestamp */
600        legacynzix_get_timeval,         /* get_timeval */
601        NULL,                           /* get_seconds */
602        NULL,                           /* seek_erf */
603        NULL,                           /* seek_timeval */
604        NULL,                           /* seek_seconds */
605        legacynzix_get_capture_length,  /* get_capture_length */
606        legacynzix_get_wire_length,     /* get_wire_length */
607        legacynzix_get_framing_length,  /* get_framing_length */
608        NULL,                           /* set_capture_length */
609        NULL,                           /* get_received_packets */
610        NULL,                           /* get_filtered_packets */
611        NULL,                           /* get_dropped_packets */
612        NULL,                           /* get_captured_packets */
613        NULL,                           /* get_fd */
614        trace_event_trace,              /* trace_event */
615        legacynzix_help,                /* help */
616        NULL,                           /* next pointer */
617};
618       
619void legacy_constructor(void) {
620        register_format(&legacypos);
621        register_format(&legacyeth);
622        register_format(&legacyatm);
623        register_format(&legacynzix);
624}
Note: See TracBrowser for help on using the repository browser.