source: lib/format_duck.c @ 2725318

develop
Last change on this file since 2725318 was 2725318, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Cleanup some of the assertions

  • Property mode set to 100644
File size: 10.5 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#include "config.h"
27#include "libtrace.h"
28#include "libtrace_int.h"
29#include "format_helper.h"
30#include "wandio.h"
31#include <stdlib.h>
32#include "rt_protocol.h"
33
34#include <errno.h>
35#include <assert.h>
36#include <stdio.h>
37#include <fcntl.h>
38
39/* This format module deals with reading and writing DUCK records.
40 *
41 * Both DUCK record types (the DAG 2.4 and 2.5 versions) are supported by this
42 * module.
43 *
44 * We differentiate between DUCK versions by writing the RT type to the start
45 * of the DUCK trace. This means that this code can only read DUCK files that
46 * were written using libtrace 3.
47 */
48
49#define DATA(x) ((struct duck_format_data_t *)x->format_data)
50#define DATAOUT(x) ((struct duck_format_data_out_t *)x->format_data)
51
52#define OUTPUT DATAOUT(libtrace)
53
54struct duck_format_data_t {
55        char *path;
56        int dag_version;
57};
58
59struct duck_format_data_out_t {
60        char *path;
61        int level;
62        int compress_type;
63        int fileflag;
64        iow_t *file;
65        int dag_version;
66};
67
68static int duck_init_input(libtrace_t *libtrace) {
69        libtrace->format_data = malloc(sizeof(struct duck_format_data_t));
70
71        if (!libtrace->format_data) {
72                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory duck_init_input()");
73                return 1;
74        }
75
76        DATA(libtrace)->dag_version = 0;
77        return 0;
78}
79
80static int duck_init_output(libtrace_out_t *libtrace) {
81        libtrace->format_data = malloc(sizeof(struct duck_format_data_out_t));
82
83        if (!libtrace->format_data) {
84                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory duck_init_output()");
85                return -1;
86        }
87
88        OUTPUT->level = 0;
89        OUTPUT->compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
90        OUTPUT->fileflag = O_CREAT | O_WRONLY;
91        OUTPUT->file = 0;
92        OUTPUT->dag_version = 0;
93        return 0;
94}
95
96static int duck_config_output(libtrace_out_t *libtrace, 
97                                trace_option_output_t option,
98                                void *data) {
99        switch (option) {
100                case TRACE_OPTION_OUTPUT_COMPRESS:
101                        OUTPUT->level = *(int *)data;
102                        return 0;
103                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
104                        OUTPUT->compress_type = *(int *)data;
105                        return 0;
106                case TRACE_OPTION_OUTPUT_FILEFLAGS:
107                        OUTPUT->fileflag = *(int *)data;
108                        return 0;
109                default:
110                        trace_set_err_out(libtrace, TRACE_ERR_UNKNOWN_OPTION,
111                                        "Unknown option");
112                        return -1;
113        }
114        assert(0);
115}
116
117static int duck_start_input(libtrace_t *libtrace) {
118       
119        if (libtrace->io)
120                /* File already open */
121                return 0;
122       
123        libtrace->io = trace_open_file(libtrace);
124        if (!libtrace->io)
125                return -1;
126
127        return 0;
128}
129
130static int duck_start_output(libtrace_out_t *libtrace) {
131        OUTPUT->file = trace_open_file_out(libtrace, 
132                                                OUTPUT->compress_type,
133                                                OUTPUT->level,
134                                                OUTPUT->fileflag);
135        if (!OUTPUT->file) {
136                return -1;
137        }
138        return 0;
139}
140
141static int duck_fin_input(libtrace_t *libtrace) {
142        wandio_destroy(libtrace->io);
143        free(libtrace->format_data);
144
145        return 0;
146}
147
148static int duck_fin_output(libtrace_out_t *libtrace) {
149        wandio_wdestroy(OUTPUT->file);
150        free(libtrace->format_data);
151        return 0;
152}
153
154static int duck_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
155                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
156
157        if (packet->buffer != buffer &&
158                        packet->buf_control == TRACE_CTRL_PACKET) {
159                free(packet->buffer);
160        }
161
162        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
163                packet->buf_control = TRACE_CTRL_PACKET;
164        } else
165                packet->buf_control = TRACE_CTRL_EXTERNAL;
166
167
168        packet->buffer = buffer;
169        packet->header = NULL;
170        packet->payload = buffer;
171        packet->type = rt_type;
172
173        if (libtrace->format_data == NULL) {
174                if (duck_init_input(libtrace))
175                        return -1;
176        }
177
178        return 0;
179}
180
181static int duck_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
182
183        int numbytes = 0;
184        uint32_t version = 0;
185        unsigned int duck_size;
186        uint32_t flags = 0;
187       
188        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
189                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
190                if (!packet->buffer) {
191                        trace_set_err(libtrace, errno,
192                                        "Cannot allocate memory");
193                        return -1;
194                }
195        }
196
197        flags |= TRACE_PREP_OWN_BUFFER;
198       
199        if (DATA(libtrace)->dag_version == 0) {
200                /* Read in the duck version from the start of the trace */
201                if ((numbytes = wandio_read(libtrace->io, &version, 
202                                        sizeof(version))) != sizeof(uint32_t)) {
203                        trace_set_err(libtrace, errno, 
204                                        "Reading DUCK version failed");
205                        return -1;
206                }
207                if (numbytes == 0) {
208                        return 0;
209                }
210                DATA(libtrace)->dag_version = bswap_le_to_host32(version);
211        }
212       
213
214        if (DATA(libtrace)->dag_version == TRACE_RT_DUCK_2_4) {
215                duck_size = sizeof(duck2_4_t);
216                packet->type = TRACE_RT_DUCK_2_4;
217        } else if (DATA(libtrace)->dag_version == TRACE_RT_DUCK_2_5) {
218                duck_size = sizeof(duck2_5_t);
219                packet->type = TRACE_RT_DUCK_2_5;
220        } else if (DATA(libtrace)->dag_version == TRACE_RT_DUCK_5_0) {
221                duck_size = sizeof(duck5_0_t);
222                packet->type = TRACE_RT_DUCK_5_0;
223        } else {
224                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
225                                "Unrecognised DUCK version %i", 
226                                DATA(libtrace)->dag_version);
227                return -1;
228        }
229
230        if ((numbytes = wandio_read(libtrace->io, packet->buffer,
231                                        (size_t)duck_size)) != (int)duck_size) {
232                if (numbytes == -1) {
233                        trace_set_err(libtrace, errno, "Reading DUCK failed");
234                        return -1;
235                }
236                else if (numbytes == 0) {
237                        return 0;
238                }
239                else {
240                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Truncated DUCK packet");
241                }
242        }
243
244        if (duck_prepare_packet(libtrace, packet, packet->buffer, packet->type,
245                                flags)) 
246                return -1;
247       
248        return numbytes;
249}
250
251static int duck_write_packet(libtrace_out_t *libtrace, 
252                libtrace_packet_t *packet) 
253{
254
255        int numbytes = 0;
256        uint32_t duck_version;
257
258        if (packet->type != TRACE_RT_DUCK_2_4
259                        && packet->type != TRACE_RT_DUCK_2_5 &&
260                        packet->type != TRACE_RT_DUCK_5_0) {
261                trace_set_err_out(libtrace, TRACE_ERR_BAD_PACKET,
262                                "Only DUCK packets may be written to a DUCK file");
263                return -1;
264        }
265       
266        assert(OUTPUT->file);
267
268        if (OUTPUT->dag_version == 0) {
269        /* Writing the DUCK version will help with reading it back in later! */
270                duck_version = bswap_host_to_le32(packet->type);
271                if ((numbytes = wandio_wwrite(OUTPUT->file, &duck_version,
272                                sizeof(duck_version))) != sizeof(uint32_t)){
273                        trace_set_err_out(libtrace, errno, 
274                                        "Writing DUCK version failed");
275                        return -1;
276                }
277                OUTPUT->dag_version = packet->type;
278        }
279       
280        if ((numbytes = wandio_wwrite(OUTPUT->file, packet->payload, 
281                                        trace_get_capture_length(packet))) !=
282                                (int)trace_get_capture_length(packet)) {
283                trace_set_err_out(libtrace, errno, "Writing DUCK failed");
284                return -1;
285        }
286        return numbytes;
287}
288
289static int duck_get_capture_length(const libtrace_packet_t *packet) {
290        switch(packet->type) {
291                case TRACE_RT_DUCK_2_4:
292                        return sizeof(duck2_4_t);
293                case TRACE_RT_DUCK_2_5:
294                        return sizeof(duck2_5_t);
295                case TRACE_RT_DUCK_5_0:
296                        return sizeof(duck5_0_t);
297                default:
298                        trace_set_err(packet->trace,TRACE_ERR_BAD_PACKET,
299                                        "Not a duck packet");
300                        return -1;
301        }
302        return 0;
303}
304
305static int duck_get_framing_length(const libtrace_packet_t *packet UNUSED) 
306{
307        return 0;
308}
309
310static int duck_get_wire_length(const libtrace_packet_t *packet UNUSED) 
311{
312        return 0;
313}
314
315static libtrace_linktype_t duck_get_link_type(
316                                const libtrace_packet_t *packet UNUSED) 
317{
318        return TRACE_TYPE_DUCK;
319}
320
321static void duck_help(void) {
322        printf("Endace DUCK format module\n");
323        printf("Supported input uris:\n");
324        printf("\tduck:/path/to/input/file\n");
325        printf("Supported output uris:\n");
326        printf("\tduck:/path/to/output/file\n");
327        printf("\n");
328        return;
329}
330static struct libtrace_format_t duck = {
331        "duck",
332        "$Id$",
333        TRACE_FORMAT_DUCK,
334        NULL,                           /* probe filename */
335        NULL,                           /* probe magic */
336        duck_init_input,                /* init_input */
337        NULL,                           /* config_input */
338        duck_start_input,               /* start_input */
339        NULL,                           /* pause_input */
340        duck_init_output,               /* init_output */
341        duck_config_output,             /* config_output */
342        duck_start_output,              /* start_output */
343        duck_fin_input,                 /* fin_input */
344        duck_fin_output,                /* fin_output */
345        duck_read_packet,               /* read_packet */
346        duck_prepare_packet,            /* prepare_packet */
347        NULL,                           /* fin_packet */
348        duck_write_packet,              /* write_packet */
349        NULL,                           /* flush_output */
350        duck_get_link_type,             /* get_link_type */
351        NULL,                           /* get_direction */
352        NULL,                           /* set_direction */
353        NULL,                           /* get_erf_timestamp */
354        NULL,                           /* get_timeval */
355        NULL,                           /* get_timespec */
356        NULL,                           /* get_seconds */
357        NULL,                           /* seek_erf */
358        NULL,                           /* seek_timeval */
359        NULL,                           /* seek_seconds */
360        duck_get_capture_length,        /* get_capture_length */
361        duck_get_wire_length,           /* get_wire_length */
362        duck_get_framing_length,        /* get_framing_length */
363        NULL,                           /* set_capture_length */
364        NULL,                           /* get_received_packets */
365        NULL,                           /* get_filtered_packets */
366        NULL,                           /* get_dropped_packets */
367        NULL,                           /* get_statistics */
368        NULL,                           /* get_fd */
369        NULL,                           /* trace_event */
370        duck_help,                      /* help */
371        NULL,                            /* next pointer */
372        NON_PARALLEL(false)
373};
374
375void duck_constructor(void) {
376        register_format(&duck);
377}       
Note: See TracBrowser for help on using the repository browser.