source: lib/format_tsh.c @ 2c457ec

cachetimestampsdevelopdpdk-ndagetsiliverc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since 2c457ec was 2c457ec, checked in by Robert A Zeh <razeh@…>, 3 years ago

Add TRACE_ERR_WANDIO_FAILED for wandio error reporting.

Passing an errcode of 0 to trace_set_err triggers the assertion at
format_helper.c:290, making the error unrecoverable for the calling
code. This happens when the wandio layer encounters an error while
errno is still 0 (for example, an incomplete pcap packet).

To make the error recoverable, pass in TRACE_ERR_WANDIO_FAILED instead
of errno.

  • Property mode set to 100644
File size: 8.8 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        tsh_get_link_type,              /* get_link_type */
248        tsh_get_direction,              /* get_direction */
249        NULL,                           /* set_direction */
250        NULL,                           /* get_erf_timestamp */
251        tsh_get_timeval,                /* get_timeval */
252        NULL,                           /* get_timespec */
253        NULL,                           /* get_seconds */
254        NULL,                           /* seek_erf */
255        NULL,                           /* seek_timeval */
256        NULL,                           /* seek_seconds */
257        tsh_get_capture_length,         /* get_capture_length */
258        tsh_get_wire_length,            /* get_wire_length */
259        tsh_get_framing_length,         /* get_framing_length */
260        NULL,                           /* set_capture_length */
261        NULL,                           /* get_received_packets */
262        NULL,                           /* get_filtered_packets */
263        NULL,                           /* get_dropped_packets */
264        NULL,                           /* get_statistics */
265        NULL,                           /* get_fd */
266        trace_event_trace,              /* trace_event */
267        tsh_help,                       /* help */
268        NULL,                   /* next pointer */
269        NON_PARALLEL(false)
270};
271
272/* the tsh header format is the same as tsh, except that the bits that will
273 * always be "0" in the fr+ format are used for an "interface" identifier,
274 * thus on tr+ traces, this will always be 0.  So, we use the exact same
275 * decoder for both traces.
276 */
277static struct libtrace_format_t frplusformat = {
278        "fr+",
279        "$Id$",
280        TRACE_FORMAT_TSH,
281        NULL,                           /* probe filename */
282        NULL,                           /* probe magic */
283        tsh_init_input,                 /* init_input */       
284        NULL,                           /* config_input */
285        tsh_start_input,                /* start_input */
286        NULL,                           /* pause_input */
287        NULL,                           /* init_output */
288        NULL,                           /* config_output */
289        NULL,                           /* start_output */
290        tsh_fin_input,                  /* fin_input */
291        NULL,                           /* fin_output */
292        tsh_read_packet,                /* read_packet */
293        tsh_prepare_packet,             /* prepare_packet */
294        NULL,                           /* fin_packet */
295        NULL,                           /* write_packet */
296        tsh_get_link_type,              /* get_link_type */
297        tsh_get_direction,              /* get_direction */
298        NULL,                           /* set_direction */
299        NULL,                           /* get_erf_timestamp */
300        tsh_get_timeval,                /* get_timeval */
301        NULL,                           /* get_timespec */
302        NULL,                           /* get_seconds */
303        NULL,                           /* seek_erf */
304        NULL,                           /* seek_timeval */
305        NULL,                           /* seek_seconds */
306        tsh_get_capture_length,         /* get_capture_length */
307        tsh_get_wire_length,            /* get_wire_length */
308        tsh_get_framing_length,         /* get_framing_length */
309        NULL,                           /* set_capture_length */
310        NULL,                           /* get_received_packets */
311        NULL,                           /* get_filtered_packets */
312        NULL,                           /* get_dropped_packets */
313        NULL,                           /* get_statistics */
314        NULL,                           /* get_fd */
315        trace_event_trace,              /* trace_event */
316        tsh_help,                       /* help */
317        NULL,                   /* next pointer */
318        NON_PARALLEL(false)
319};
320
321void tsh_constructor(void) {
322        register_format(&tshformat);
323        register_format(&frplusformat);
324}
Note: See TracBrowser for help on using the repository browser.