source: lib/format_duck.c @ ef5ba20

develop
Last change on this file since ef5ba20 was ef5ba20, checked in by Jacob Van Walraven <jcv9@…>, 22 months ago

add abilty to get custom option from meta packets, add abilty to get entire section from meta packet, meta api now returns libtrace_meta_t structure

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