source: lib/format_tsh.c @ c69aecb

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c69aecb was c69aecb, checked in by Shane Alcock <salcock@…>, 7 years ago

Handle incomplete file reads in libtrace formats

Some file read function calls assumed that the full amount that was
asked for will be read from the file, which is not necessarily true
especially if the file was truncated.

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