Skip to Content
[CAIDA - Center for Applied Internet Data Analysis logo]
The Center for Applied Internet Data Analysis
corsaro_file.c
1 /*
2  * corsaro
3  *
4  * Alistair King, CAIDA, UC San Diego
5  * corsaro-info@caida.org
6  *
7  * Copyright (C) 2012 The Regents of the University of California.
8  *
9  * This file is part of corsaro.
10  *
11  * corsaro is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU 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  * corsaro 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 General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with corsaro. If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25 
26 #include "config.h"
27 #include "corsaro_int.h"
28 
29 #include <assert.h>
30 #include <stdarg.h>
31 #include <inttypes.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include <wandio.h>
37 
38 #include "wandio_utils.h"
39 
40 #include "corsaro_file.h"
41 #include "corsaro_log.h"
42 
43 /* fix for solaris (data-login.sdsc.edu) */
44 #if (defined (__SVR4) && defined (__sun))
45 extern int vasprintf(char **, const char *, __va_list);
46 #endif
47 
49 #define CORSARO_FILE_ASCII_CHECK "# CORSARO"
50 
52 #define CORSARO_FILE_TRACE_FORMAT "pcapfile:"
53 
55 {
56  return wandio_detect_compression_type(filename);
57 }
58 
60  const char *filename,
62  corsaro_file_compress_t compress_type,
63  int compress_level,
64  int flags)
65 {
66  corsaro_file_t *f = NULL;
67 
68  size_t flen, rlen, len;
69  char *ptr, *traceuri;
70 
71  if((f = malloc(sizeof(corsaro_file_t))) == NULL)
72  {
73  corsaro_log(__func__, corsaro, "could not malloc new corsaro_file_t");
74  return NULL;
75  }
76 
77  f->mode = mode;
78 
79  /* did they ask for a libtrace file? */
80  switch(mode)
81  {
83  flen = strlen(CORSARO_FILE_TRACE_FORMAT);
84  rlen = strlen(filename);
85  len = flen+rlen+1;
86  if((ptr = traceuri = malloc(len)) == NULL)
87  {
88  corsaro_log(__func__, corsaro, "could not malloc traceuri");
89  return NULL;
90  }
91  strncpy(traceuri, CORSARO_FILE_TRACE_FORMAT, flen);
92  ptr += flen;
93  strncpy(ptr, filename, rlen);
94  traceuri[len-1] = '\0';
95  f->trace_io = trace_create_output(traceuri);
96  free(traceuri);
97 
98  if (trace_is_err_output(f->trace_io))
99  {
100  corsaro_log(__func__, corsaro, "trace_create_output failed for %s",
101  filename);
102  return NULL;
103  }
104  if(trace_config_output(f->trace_io, TRACE_OPTION_OUTPUT_COMPRESS,
105  &compress_level) ||
106  trace_config_output(f->trace_io, TRACE_OPTION_OUTPUT_COMPRESSTYPE,
107  &compress_type) != 0)
108  {
109  corsaro_log(__func__, corsaro,
110  "could not set compression levels for trace");
111  return NULL;
112  }
113  if (trace_start_output(f->trace_io) == -1) {
114  corsaro_log(__func__, corsaro, "trace_start_output failed for %s",
115  filename);
116  return NULL;
117  }
118  /* trace is configured! */
119  break;
120 
123  if((f->wand_io = wandio_wcreate(filename, compress_type,
124  compress_level, flags)) == NULL)
125  {
126  corsaro_log(__func__, corsaro, "wandio could not create file %s",
127  filename);
128  free(f);
129  return NULL;
130  }
131  break;
132 
133  default:
134  corsaro_log(__func__, corsaro, "invalid file mode %d", mode);
135  free(f);
136  return NULL;
137  }
138 
139  return f;
140 }
141 
143  corsaro_file_t *file, const void *buffer, off_t len)
144 {
145  /* let's not try and write raw bytes to a libtrace file... */
146  assert(file->mode == CORSARO_FILE_MODE_ASCII ||
147  file->mode == CORSARO_FILE_MODE_BINARY ||
149  assert(file->wand_io != NULL);
150 
151  return wandio_wwrite(file->wand_io, buffer, len);
152 }
153 
155  corsaro_file_t *file, libtrace_packet_t *packet)
156 {
157  uint8_t *pkt_buf = NULL;
158  libtrace_linktype_t linktype;
159 
160  switch(file->mode)
161  {
163  assert(file->wand_io != NULL);
164 #ifdef HAVE_LIBPACKETDUMP
165  corsaro_log(__func__, corsaro,
166  "libpacketdump currently does not support dumping "
167  "to a file");
168  return 0;
169 #else
170  corsaro_log(__func__, corsaro,
171  "corsaro must be built with libpacketdump to dump "
172  "a packet to ASCII");
173  return 0;
174 #endif
175  break;
176 
178  assert(file->wand_io != NULL);
179  if((pkt_buf = trace_get_packet_buffer(packet,
180  &linktype, NULL)) == NULL)
181  {
182  corsaro_log(__func__, corsaro, "could not get packet buffer");
183  return -1;
184  }
185  return corsaro_file_write(corsaro, file, pkt_buf,
186  trace_get_capture_length(packet));
187 
189  assert(file->trace_io != NULL);
190  return trace_write_packet(file->trace_io, packet);
191 
192  default:
193  corsaro_log(__func__, corsaro, "invalid corsaro file mode %d", file->mode);
194  return -1;
195  }
196 
197  return -1;
198 }
199 
201  const char *format, va_list args)
202 {
203  /* let's not try and print text to a libtrace file... */
204  assert(file != NULL);
205  assert(file->mode == CORSARO_FILE_MODE_ASCII ||
206  file->mode == CORSARO_FILE_MODE_BINARY ||
208  assert(file->wand_io != NULL);
209 
210  return wandio_vprintf(file->wand_io, format, args);
211 
212 }
213 
215  corsaro_file_t *file, const char *format, ...)
216 {
217  va_list ap;
218 
219  va_start(ap, format);
220  return corsaro_file_vprintf(corsaro, file, format, ap);
221  va_end(ap);
222 }
223 
225 {
226  /* not supported by wandio? */
227  return;
228 }
229 
231 {
232  switch(file->mode)
233  {
236  /* close the wandio object */
237  assert(file->wand_io != NULL);
238  wandio_wdestroy(file->wand_io);
239  file->wand_io = NULL;
240  break;
241 
243  assert(file->trace_io != NULL);
244  trace_destroy_output(file->trace_io);
245  file->trace_io = NULL;
246  break;
247 
248  default:
249  assert(0);
250  }
251 
252  free(file);
253  return;
254 }
255 
256 corsaro_file_in_t *corsaro_file_ropen(const char *filename)
257 {
258  corsaro_file_in_t *f = NULL;
259  char buffer[1024];
260  int len;
261 
262  /* 2013-01-22 AK has removed all of the logging output on failures this is
263  because i dont want to need a corsaro_t object to open a file. but also
264  because i think it should be up to the caller to log the errors. logs from
265  this deep in corsaro just confuse people when somewhat common errors occur
266  (file not found etc). */
267 
268  if((f = malloc(sizeof(corsaro_file_in_t))) == NULL)
269  {
270  return NULL;
271  }
272 
273  /* we need to try and guess the mode... */
274  /* if there is a : in the uri, we guess it is a libtrace file */
275  /* this should be refined to do something more intelligent */
276  if(strchr(filename, ':') != NULL)
277  {
279 
280  /* open this as a trace file */
281  f->trace_io = trace_create(filename);
282 
283  if(trace_is_err(f->trace_io))
284  {
285  free(f);
286  return NULL;
287  }
288 
289  if (trace_start(f->trace_io) == -1) {
290  free(f);
291  return NULL;
292  }
293  /* trace is set to go! */
294  return f;
295  }
296  else
297  {
298  /* lets open the file and take a peek to see what we find */
299  if((f->wand_io = wandio_create(filename)) == NULL)
300  {
301  free(f);
302  return NULL;
303  }
304 
305  len = wandio_peek(f->wand_io, buffer, sizeof(buffer));
306 
307  /* an ASCII corsaro file will start with "# CORSARO_VERSION" */
308  if(len >= strlen(CORSARO_FILE_ASCII_CHECK) &&
309  memcmp(CORSARO_FILE_ASCII_CHECK, buffer,
310  strlen(CORSARO_FILE_ASCII_CHECK)) == 0)
311  {
313  }
314  /* a binary corsaro file will start with an corsaro header "EDGRHEAD" but,
315  it is possible that an old binary corsaro file can just start with an
316  interval header - "EDGRINTR", so we will only look for "EDGR" */
317  else if(len >= 4 && buffer[0] == 'E' && buffer[1] == 'D' &&
318  buffer[2] == 'G' && buffer[3] == 'R')
319  {
321  }
322  else
323  {
324  /* who knows, but maybe someone wants to read a non-corsaro file */
326  }
327  }
328 
329  return f;
330 }
331 
332 off_t corsaro_file_rread(corsaro_file_in_t *file, void *buffer, off_t len)
333 {
334  /* refuse to read from a libtrace file */
335  assert(file->mode == CORSARO_FILE_MODE_ASCII ||
336  file->mode == CORSARO_FILE_MODE_BINARY ||
338  assert(file->wand_io != NULL);
339 
340  return wandio_read(file->wand_io, buffer, len);
341 }
342 
343 off_t corsaro_file_rgets(corsaro_file_in_t *file, void *buffer, off_t len)
344 {
345  /* refuse to read from a libtrace file */
346  assert(file != NULL);
347  assert(file->mode == CORSARO_FILE_MODE_ASCII ||
348  file->mode == CORSARO_FILE_MODE_BINARY ||
350  assert(file->wand_io != NULL);
351 
352  /* just hand off to the helper func in wandio_utils (no chomp) */
353  return wandio_fgets(file->wand_io, buffer, len, 0);
354 }
355 
357  libtrace_packet_t *packet,
358  uint16_t len)
359 {
360  uint8_t *pktbuf;
361 
362  switch(file->mode)
363  {
365  if((pktbuf = malloc(len)) == NULL)
366  {
367  fprintf(stderr, "could not malloc the packet buffer\n");
368  return -1;
369  }
370  if(wandio_read(file->wand_io, pktbuf, len) != len)
371  {
372  fprintf(stderr, "could not read packet into buffer\n");
373  return -1;
374  }
375  trace_construct_packet(packet, TRACE_TYPE_ETH,
376  pktbuf, len);
377  return len;
378  break;
379 
381  return trace_read_packet(file->trace_io, packet);
382  break;
383 
386  /* refuse to read a packet from an ascii file */
387  /* this is a design flaw in the code if we get here */
388  assert(1);
389  return -1;
390  }
391 
392  return -1;
393 }
394 
395 off_t corsaro_file_rpeek(corsaro_file_in_t *file, void *buffer, off_t len)
396 {
397  /* refuse to read from a libtrace file */
398  assert(file->mode == CORSARO_FILE_MODE_ASCII ||
399  file->mode == CORSARO_FILE_MODE_BINARY ||
401  assert(file->wand_io != NULL);
402 
403  return wandio_peek(file->wand_io, buffer, len);
404 }
405 
406 off_t corsaro_file_rseek(corsaro_file_in_t *file, off_t offset, int whence)
407 {
408  /* refuse to read from a libtrace file */
409  assert(file->mode == CORSARO_FILE_MODE_ASCII ||
410  file->mode == CORSARO_FILE_MODE_BINARY ||
412  assert(file->wand_io != NULL);
413 
414  return wandio_seek(file->wand_io, offset, whence);
415 }
416 
418 {
419  /* refuse to read from a libtrace file */
420  assert(file->mode == CORSARO_FILE_MODE_ASCII ||
421  file->mode == CORSARO_FILE_MODE_BINARY ||
423  assert(file->wand_io != NULL);
424 
425  return wandio_tell(file->wand_io);
426 }
427 
429 {
430  switch(file->mode)
431  {
435  /* close the wandio object */
436  if(file->wand_io != NULL)
437  {
438  wandio_destroy(file->wand_io);
439  file->wand_io = NULL;
440  }
441  /* just for sanity */
442  file->trace_io = NULL;
443  break;
444 
446  if(file->trace_io != NULL)
447  {
448  trace_destroy(file->trace_io);
449  file->trace_io = NULL;
450  }
451  /* just for sanity */
452  file->wand_io = NULL;
453  break;
454 
455  default:
456  /* do nothing - it was already freed? */
457  /* leave the assert here for when people are debugging */
458  assert(0);
459  return;
460  }
461  /* this will prevent an idiot from using this object again */
462  file->mode = -1;
463 
464  free(file);
465 
466  return;
467 }
An opaque structure defining an corsaro input file.
Definition: corsaro_file.h:86
off_t corsaro_file_rgets(corsaro_file_in_t *file, void *buffer, off_t len)
Reads a string from an corsaro input file into the provided buffer.
Definition: corsaro_file.c:343
Header file dealing with the corsaro logging sub-system.
An opaque structure defining an corsaro output file.
Definition: corsaro_file.h:60
off_t corsaro_file_printf(struct corsaro *corsaro, corsaro_file_t *file, const char *format,...)
Print a string to an corsaro file.
Definition: corsaro_file.c:214
ASCII IO mode.
Definition: corsaro.h:153
Binary IO mode.
Definition: corsaro.h:155
off_t corsaro_file_rtell(corsaro_file_in_t *file)
Returns the current offset of the read pointer for an corsaro input file.
Definition: corsaro_file.c:417
off_t corsaro_file_write_packet(struct corsaro *corsaro, corsaro_file_t *file, libtrace_packet_t *packet)
Write a libtrace packet to an corsaro output file.
Definition: corsaro_file.c:154
off_t corsaro_file_rpeek(corsaro_file_in_t *file, void *buffer, off_t len)
Reads from an corsaro input file into the provided buffer, but does not update the read pointer...
Definition: corsaro_file.c:395
void corsaro_file_close(struct corsaro *corsaro, corsaro_file_t *file)
Closes an corsaro output file and frees the writer structure.
Definition: corsaro_file.c:230
static libtrace_packet_t * packet
A pointer to a libtrace packet.
Definition: corsaro_main.c:67
corsaro_file_mode_t mode
The requested output format for the file.
Definition: corsaro_file.h:63
void corsaro_file_flush(struct corsaro *corsaro, corsaro_file_t *file)
Force all buffered data for the file to be written out.
Definition: corsaro_file.c:224
void corsaro_file_rclose(corsaro_file_in_t *file)
Closes an corsaro input file and frees the reader structure.
Definition: corsaro_file.c:428
Header file dealing with the low-level file IO.
off_t corsaro_file_vprintf(struct corsaro *corsaro, corsaro_file_t *file, const char *format, va_list args)
Print a string to an corsaro file.
Definition: corsaro_file.c:200
Pseudo IO mode which allows trace files to be written.
Definition: corsaro.h:157
enum corsaro_file_compress corsaro_file_compress_t
Supported compression types (must be kept in sync with wandio)
off_t corsaro_file_rseek(corsaro_file_in_t *file, off_t offset, int whence)
Changes the read pointer offset to the specified value for an corsaro input file. ...
Definition: corsaro_file.c:406
off_t corsaro_file_rread(corsaro_file_in_t *file, void *buffer, off_t len)
Reads from an corsaro input file into the provided buffer.
Definition: corsaro_file.c:332
off_t corsaro_file_write(struct corsaro *corsaro, corsaro_file_t *file, const void *buffer, off_t len)
Writes the contents of a buffer using an corsaro output file.
Definition: corsaro_file.c:142
corsaro_file_mode_t mode
The requested/detected input format for the file.
Definition: corsaro_file.h:89
corsaro_file_t * corsaro_file_open(struct corsaro *corsaro, const char *filename, corsaro_file_mode_t mode, corsaro_file_compress_t compress_type, int compress_level, int flags)
Creates a new corsaro file write and opens the provided file for writing.
Definition: corsaro_file.c:59
Unknown IO mode.
Definition: corsaro.h:159
Corsaro output state.
Definition: corsaro_int.h:230
corsaro_file_compress_t corsaro_file_detect_compression(char *filename)
Attempts to detect the type of compression for a file based on the suffix.
Definition: corsaro_file.c:54
corsaro_file_in_t * corsaro_file_ropen(const char *filename)
Creates a new corsaro file reader and opens the provided file for reading.
Definition: corsaro_file.c:256
void corsaro_log(const char *func, corsaro_t *corsaro, const char *format,...)
Write a formatted string to the logfile associated with an corsaro object.
Definition: corsaro_log.c:113
enum corsaro_file_mode corsaro_file_mode_t
Enum of supported file modes.
Header file dealing with the internal corsaro functions.
off_t corsaro_file_rread_packet(corsaro_file_in_t *file, libtrace_packet_t *packet, uint16_t len)
Read a libtrace packet from an corsaro input file.
Definition: corsaro_file.c:356