source: lib/format_legacy.c @ f0fb38f

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