source: lib/format_tsh.c @ 95ca714

cachetimestampsdeveloprc-4.0.4ringdecrementfixringperformance
Last change on this file since 95ca714 was 32ee9b2, checked in by Shane Alcock <salcock@…>, 3 years ago

Add new trace_flush_output() to public API

Can be used to force a libtrace output to dump any buffered output
to disk immediately.

Note that if the file is compressed or the output trace format
requires a trailer, the flushed file will still not be properly
readable afterwards as this will not result in any trailers
being written. You'll still have to close the file for that.

Mainly this is useful for ensuring that output file sizes grow
over time in situations where the amount of output is relatively
small, rather than staying stuck at 0 bytes until we either reach
1MB of output or the file is closed. For instance, you could have
a timer that calls trace_flush_output() every 30 seconds so that
the output file size will grow if any packets were written in the
last 30 seconds.

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26
27#include "config.h"
28#include "common.h"
29#include "libtrace.h"
30#include "libtrace_int.h"
31#include "format_helper.h"
32
33#include <assert.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
40/* This format module deals with reading traces that are in the TSH format.
41 *
42 * We do not support writing TSH traces, because it's a pretty rubbish format.
43 */
44
45static struct libtrace_format_t tshformat;
46
47typedef struct tsh_pkt_header_t {
48        uint32_t seconds;
49        uint32_t usecs;
50} tsh_pkt_header_t;
51
52static int tsh_get_framing_length(const libtrace_packet_t *packet UNUSED)
53{
54        return sizeof(tsh_pkt_header_t);
55}
56
57
58static int tsh_init_input(libtrace_t *libtrace) 
59{
60        libtrace->format_data = NULL; /* No format data */
61       
62        return 0; /* success */
63}
64
65static int tsh_start_input(libtrace_t *libtrace)
66{
67        if (libtrace->io)
68                return 0; /* success */
69
70        libtrace->io = trace_open_file(libtrace);
71
72        if (!libtrace->io)
73                return -1;
74
75        return 0; /* success */
76}
77
78static int tsh_fin_input(libtrace_t *libtrace) {
79        if (libtrace->io)
80                wandio_destroy(libtrace->io);
81        return 0;
82}
83
84static int tsh_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
85                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
86        if (packet->buffer != buffer &&
87                        packet->buf_control == TRACE_CTRL_PACKET) {
88                free(packet->buffer);
89        }
90
91        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
92                packet->buf_control = TRACE_CTRL_PACKET;
93        } else
94                packet->buf_control = TRACE_CTRL_EXTERNAL;
95
96
97        packet->buffer = buffer;
98        packet->header = buffer;
99        packet->type = rt_type;
100        packet->payload = (char *)packet->buffer + sizeof(tsh_pkt_header_t);
101
102        if (libtrace->format_data == NULL) {
103                if (tsh_init_input(libtrace))
104                        return -1;
105        }
106
107        return 0;
108}
109
110static int tsh_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
111        int numbytes;
112        void *buffer2 = packet->buffer;
113        uint32_t flags = 0;
114
115        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
116                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
117                if (!packet->buffer) {
118                        trace_set_err(libtrace, errno, 
119                                        "Cannot allocate memory");
120                        return -1;
121                }
122        }
123
124        flags |= TRACE_PREP_OWN_BUFFER;
125        packet->type = TRACE_RT_DATA_TSH;
126
127        buffer2 = packet->buffer;
128
129        /* Read the TSH header */
130        if ((numbytes=wandio_read(libtrace->io,
131                                        buffer2,
132                                        (size_t)sizeof(tsh_pkt_header_t))) == -1) {
133                trace_set_err(libtrace,TRACE_ERR_WANDIO_FAILED,"read(%s)",
134                                libtrace->uridata);
135                return -1;
136        }
137        /* EOF */
138        if (numbytes == 0) {
139                return 0;
140        }
141
142        if (numbytes < (int)sizeof(tsh_pkt_header_t)) {
143                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "Incomplete TSH header");
144                return -1;
145        }
146
147        buffer2 = (char*)buffer2 + numbytes;
148
149        /* Read the IP header */
150        if ((numbytes=wandio_read(libtrace->io,
151                                buffer2,
152                                (size_t)sizeof(libtrace_ip_t)+16))  /* 16 bytes of transport header */
153                        != sizeof(libtrace_ip_t)+16) {
154                trace_set_err(libtrace,TRACE_ERR_WANDIO_FAILED,"read(%s)",
155                                libtrace->uridata);
156                return -1;
157        }
158
159#if 0
160        /* IP Options aren't captured in the trace, so leave room
161         * for them, and put the transport header where it "should" be
162         */
163        buffer2 = (char*)buffer2 + ((libtrace_ip_t*)buffer2)->ip_hl*4;
164
165        /* Read the transport header */
166        if ((numbytes=wandio_read(libtrace->io,
167                                buffer2,
168                                16)) != 16) {
169                trace_set_err(libtrace,TRACE_ERR_WANDIO_FAILED,"read(%s)",
170                                libtrace->uridata);
171                return -1;
172        }
173#endif
174       
175        if (tsh_prepare_packet(libtrace, packet, packet->buffer, packet->type, 
176                                flags)) {
177                return -1;
178        }
179
180
181        return 80;
182}
183
184static libtrace_linktype_t tsh_get_link_type(const libtrace_packet_t *packet UNUSED) {
185        return TRACE_TYPE_NONE;
186}
187
188static libtrace_direction_t tsh_get_direction(const libtrace_packet_t *packet) {
189        return ntohl(((tsh_pkt_header_t*)(packet->header))->usecs & htonl(0xFF000000)) >> 24;
190}
191
192static struct timeval tsh_get_timeval(const libtrace_packet_t *packet)
193{
194        struct timeval tv;
195        tv.tv_sec=ntohl(((tsh_pkt_header_t*)(packet->header))->seconds);
196        tv.tv_usec=ntohl(((tsh_pkt_header_t*)(packet->header))->usecs & htonl(0x00FFFFFF));
197
198        return tv;
199}
200
201static int tsh_get_capture_length(const libtrace_packet_t *packet UNUSED) {
202        /* 16 bytes transport + 24 bytes IP, and we're missing the
203         * IP options, but we'll pretend we have them
204         */
205#if 0
206        return 16+((libtrace_ip_t*)packet->payload)->ip_hl*4;
207#else
208        return 16+sizeof(libtrace_ip_t);
209#endif
210}
211
212static int tsh_get_wire_length(const libtrace_packet_t *packet) {
213        return ntohs(((libtrace_ip_t*)packet->payload)->ip_len);
214}
215
216static void tsh_help(void) {
217        printf("tsh format module: $Revision: 1611 $\n");
218        printf("Supported input URIs:\n");
219        printf("\ttsh:/path/to/file\t(uncompressed)\n");
220        printf("\ttsh:/path/to/file.gz\t(gzip-compressed)\n");
221        printf("\ttsh:-\t(stdin, either compressed or not)\n");
222        printf("\ttsh:/path/to/socket\n");
223        printf("\n");
224        printf("\te.g.: erf:/tmp/trace\n");
225        printf("\n");
226}
227
228static struct libtrace_format_t tshformat = {
229        "tsh",
230        "$Id$",
231        TRACE_FORMAT_TSH,
232        NULL,                           /* probe filename */
233        NULL,                           /* probe magic */
234        tsh_init_input,                 /* init_input */       
235        NULL,                           /* config_input */
236        tsh_start_input,                /* start_input */
237        NULL,                           /* pause_input */
238        NULL,                           /* init_output */
239        NULL,                           /* config_output */
240        NULL,                           /* start_output */
241        tsh_fin_input,                  /* fin_input */
242        NULL,                           /* fin_output */
243        tsh_read_packet,                /* read_packet */
244        tsh_prepare_packet,             /* prepare_packet */
245        NULL,                           /* fin_packet */
246        NULL,                           /* write_packet */
247        NULL,                           /* flush_output */
248        tsh_get_link_type,              /* get_link_type */
249        tsh_get_direction,              /* get_direction */
250        NULL,                           /* set_direction */
251        NULL,                           /* get_erf_timestamp */
252        tsh_get_timeval,                /* get_timeval */
253        NULL,                           /* get_timespec */
254        NULL,                           /* get_seconds */
255        NULL,                           /* seek_erf */
256        NULL,                           /* seek_timeval */
257        NULL,                           /* seek_seconds */
258        tsh_get_capture_length,         /* get_capture_length */
259        tsh_get_wire_length,            /* get_wire_length */
260        tsh_get_framing_length,         /* get_framing_length */
261        NULL,                           /* set_capture_length */
262        NULL,                           /* get_received_packets */
263        NULL,                           /* get_filtered_packets */
264        NULL,                           /* get_dropped_packets */
265        NULL,                           /* get_statistics */
266        NULL,                           /* get_fd */
267        trace_event_trace,              /* trace_event */
268        tsh_help,                       /* help */
269        NULL,                   /* next pointer */
270        NON_PARALLEL(false)
271};
272
273/* the tsh header format is the same as tsh, except that the bits that will
274 * always be "0" in the fr+ format are used for an "interface" identifier,
275 * thus on tr+ traces, this will always be 0.  So, we use the exact same
276 * decoder for both traces.
277 */
278static struct libtrace_format_t frplusformat = {
279        "fr+",
280        "$Id$",
281        TRACE_FORMAT_TSH,
282        NULL,                           /* probe filename */
283        NULL,                           /* probe magic */
284        tsh_init_input,                 /* init_input */       
285        NULL,                           /* config_input */
286        tsh_start_input,                /* start_input */
287        NULL,                           /* pause_input */
288        NULL,                           /* init_output */
289        NULL,                           /* config_output */
290        NULL,                           /* start_output */
291        tsh_fin_input,                  /* fin_input */
292        NULL,                           /* fin_output */
293        tsh_read_packet,                /* read_packet */
294        tsh_prepare_packet,             /* prepare_packet */
295        NULL,                           /* fin_packet */
296        NULL,                           /* write_packet */
297        NULL,                           /* flush_output */
298        tsh_get_link_type,              /* get_link_type */
299        tsh_get_direction,              /* get_direction */
300        NULL,                           /* set_direction */
301        NULL,                           /* get_erf_timestamp */
302        tsh_get_timeval,                /* get_timeval */
303        NULL,                           /* get_timespec */
304        NULL,                           /* get_seconds */
305        NULL,                           /* seek_erf */
306        NULL,                           /* seek_timeval */
307        NULL,                           /* seek_seconds */
308        tsh_get_capture_length,         /* get_capture_length */
309        tsh_get_wire_length,            /* get_wire_length */
310        tsh_get_framing_length,         /* get_framing_length */
311        NULL,                           /* set_capture_length */
312        NULL,                           /* get_received_packets */
313        NULL,                           /* get_filtered_packets */
314        NULL,                           /* get_dropped_packets */
315        NULL,                           /* get_statistics */
316        NULL,                           /* get_fd */
317        trace_event_trace,              /* trace_event */
318        tsh_help,                       /* help */
319        NULL,                   /* next pointer */
320        NON_PARALLEL(false)
321};
322
323void tsh_constructor(void) {
324        register_format(&tshformat);
325        register_format(&frplusformat);
326}
Note: See TracBrowser for help on using the repository browser.